removed some obsolete files (appBasicSample), FCollada lib, external-libs folder
start physics by default (not pressing 'i')
This commit is contained in:
BIN
BulletDocs.chi
BIN
BulletDocs.chi
Binary file not shown.
BIN
BulletDocs.chm
BIN
BulletDocs.chm
Binary file not shown.
@@ -1,793 +0,0 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "CcdPhysicsEnvironment.h"
|
||||
#include "CcdPhysicsController.h"
|
||||
#include "MyMotionState.h"
|
||||
#include "CollisionShapes/BoxShape.h"
|
||||
#include "CollisionShapes/SphereShape.h"
|
||||
#include "CollisionShapes/ConeShape.h"
|
||||
#include "CollisionShapes/Simplex1to4Shape.h"
|
||||
#include "CollisionShapes/EmptyShape.h"
|
||||
|
||||
#include "Dynamics/RigidBody.h"
|
||||
#include "CollisionDispatch/CollisionDispatcher.h"
|
||||
#include "BroadphaseCollision/SimpleBroadphase.h"
|
||||
#include "BroadphaseCollision/AxisSweep3.h"
|
||||
#include "ConstraintSolver/Point2PointConstraint.h"
|
||||
#include "ConstraintSolver/HingeConstraint.h"
|
||||
|
||||
#include "quickprof.h"
|
||||
#include "PrintfDebugDrawer.h"
|
||||
|
||||
|
||||
#include "PHY_Pro.h"
|
||||
#include <stdio.h> //printf debugging
|
||||
|
||||
|
||||
int getDebugMode()
|
||||
{
|
||||
return IDebugDraw::DBG_ProfileTimings;
|
||||
}
|
||||
|
||||
//make up for lack of glut and camera
|
||||
float eye[3]={10.f,0.f,0.f};
|
||||
int glutScreenWidth=640;
|
||||
int glutScreenHeight=480;
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
const int numObjects = 22;
|
||||
#else
|
||||
const int numObjects = 120;
|
||||
#endif
|
||||
|
||||
const int maxNumObjects = 450;
|
||||
|
||||
MyMotionState ms[maxNumObjects];
|
||||
CcdPhysicsController* physObjects[maxNumObjects] = {0,0,0,0};
|
||||
int shapeIndex[maxNumObjects];
|
||||
CcdPhysicsEnvironment* physicsEnvironmentPtr = 0;
|
||||
|
||||
|
||||
#define CUBE_HALF_EXTENTS 1
|
||||
|
||||
#define EXTRA_HEIGHT -20.f
|
||||
static const int numShapes = 4;
|
||||
|
||||
CollisionShape* shapePtr[numShapes] =
|
||||
{
|
||||
new BoxShape (SimdVector3(50,10,50)),
|
||||
new BoxShape (SimdVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS)),
|
||||
new SphereShape (CUBE_HALF_EXTENTS- 0.05f),
|
||||
|
||||
//new ConeShape(CUBE_HALF_EXTENTS,2.f*CUBE_HALF_EXTENTS),
|
||||
//new BU_Simplex1to4(SimdPoint3(-1,-1,-1),SimdPoint3(1,-1,-1),SimdPoint3(-1,1,-1),SimdPoint3(0,0,1)),
|
||||
|
||||
//new EmptyShape(),
|
||||
|
||||
new BoxShape (SimdVector3(0.4f,1.f,0.8f))
|
||||
|
||||
};
|
||||
|
||||
void clientResetScene();
|
||||
void simulateMe();
|
||||
void clientDisplay()
|
||||
{
|
||||
}
|
||||
void clientMoveAndDisplay()
|
||||
{
|
||||
}
|
||||
PrintfDebugDrawer debugDrawer;
|
||||
|
||||
int main(int argc,char** argv)
|
||||
{
|
||||
|
||||
|
||||
|
||||
CollisionDispatcher* dispatcher = new CollisionDispatcher();
|
||||
|
||||
|
||||
SimdVector3 worldAabbMin(-10000,-10000,-10000);
|
||||
SimdVector3 worldAabbMax(10000,10000,10000);
|
||||
|
||||
BroadphaseInterface* broadphase = new AxisSweep3(worldAabbMin,worldAabbMax);
|
||||
//BroadphaseInterface* broadphase = new SimpleBroadphase();
|
||||
|
||||
physicsEnvironmentPtr = new CcdPhysicsEnvironment(dispatcher,broadphase);
|
||||
physicsEnvironmentPtr->setDeactivationTime(2.f);
|
||||
|
||||
|
||||
physicsEnvironmentPtr->setGravity(0,-10,0);
|
||||
PHY_ShapeProps shapeProps;
|
||||
|
||||
shapeProps.m_do_anisotropic = false;
|
||||
shapeProps.m_do_fh = false;
|
||||
shapeProps.m_do_rot_fh = false;
|
||||
shapeProps.m_friction_scaling[0] = 1.;
|
||||
shapeProps.m_friction_scaling[1] = 1.;
|
||||
shapeProps.m_friction_scaling[2] = 1.;
|
||||
|
||||
shapeProps.m_inertia = 1.f;
|
||||
shapeProps.m_lin_drag = 0.2f;
|
||||
shapeProps.m_ang_drag = 0.1f;
|
||||
shapeProps.m_mass = 10.0f;
|
||||
|
||||
PHY_MaterialProps materialProps;
|
||||
materialProps.m_friction = 10.5f;
|
||||
materialProps.m_restitution = 0.0f;
|
||||
|
||||
CcdConstructionInfo ccdObjectCi;
|
||||
ccdObjectCi.m_friction = 0.5f;
|
||||
|
||||
ccdObjectCi.m_linearDamping = shapeProps.m_lin_drag;
|
||||
ccdObjectCi.m_angularDamping = shapeProps.m_ang_drag;
|
||||
|
||||
SimdTransform tr;
|
||||
tr.setIdentity();
|
||||
|
||||
int i;
|
||||
for (i=0;i<numObjects;i++)
|
||||
{
|
||||
if (i>0)
|
||||
{
|
||||
shapeIndex[i] = 1;//sphere
|
||||
}
|
||||
else
|
||||
shapeIndex[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
for (i=0;i<numObjects;i++)
|
||||
{
|
||||
shapeProps.m_shape = shapePtr[shapeIndex[i]];
|
||||
shapeProps.m_shape->SetMargin(0.05f);
|
||||
|
||||
|
||||
|
||||
bool isDyna = i>0;
|
||||
//if (i==1)
|
||||
// isDyna=false;
|
||||
|
||||
if (0)//i==1)
|
||||
{
|
||||
SimdQuaternion orn(0,0,0.1*SIMD_HALF_PI);
|
||||
ms[i].setWorldOrientation(orn.x(),orn.y(),orn.z(),orn[3]);
|
||||
}
|
||||
|
||||
|
||||
if (i>0)
|
||||
{
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
ms[i].setWorldPosition(0,10,0);
|
||||
//for testing, rotate the ground cube so the stack has to recover a bit
|
||||
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
ms[i].setWorldPosition(0,8,2);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ms[i].setWorldPosition(0,i*CUBE_HALF_EXTENTS*2 - CUBE_HALF_EXTENTS,0);
|
||||
}
|
||||
|
||||
|
||||
SimdQuaternion quat;
|
||||
SimdVector3 axis(0.f,0.f,1.f);
|
||||
SimdScalar angle=0.5f;
|
||||
|
||||
quat.setRotation(axis,angle);
|
||||
|
||||
ms[i].setWorldOrientation(quat.getX(),quat.getY(),quat.getZ(),quat[3]);
|
||||
|
||||
|
||||
|
||||
} else
|
||||
{
|
||||
ms[i].setWorldPosition(0,-100+EXTRA_HEIGHT,0);
|
||||
|
||||
}
|
||||
|
||||
ccdObjectCi.m_MotionState = &ms[i];
|
||||
ccdObjectCi.m_gravity = SimdVector3(0,0,0);
|
||||
ccdObjectCi.m_localInertiaTensor =SimdVector3(0,0,0);
|
||||
if (!isDyna)
|
||||
{
|
||||
shapeProps.m_mass = 0.f;
|
||||
ccdObjectCi.m_mass = shapeProps.m_mass;
|
||||
}
|
||||
else
|
||||
{
|
||||
shapeProps.m_mass = 1.f;
|
||||
ccdObjectCi.m_mass = shapeProps.m_mass;
|
||||
}
|
||||
|
||||
|
||||
SimdVector3 localInertia;
|
||||
if (shapePtr[shapeIndex[i]]->GetShapeType() == EMPTY_SHAPE_PROXYTYPE)
|
||||
{
|
||||
//take inertia from first shape
|
||||
shapePtr[1]->CalculateLocalInertia(shapeProps.m_mass,localInertia);
|
||||
} else
|
||||
{
|
||||
shapePtr[shapeIndex[i]]->CalculateLocalInertia(shapeProps.m_mass,localInertia);
|
||||
}
|
||||
ccdObjectCi.m_localInertiaTensor = localInertia;
|
||||
|
||||
ccdObjectCi.m_collisionShape = shapePtr[shapeIndex[i]];
|
||||
|
||||
|
||||
physObjects[i]= new CcdPhysicsController( ccdObjectCi);
|
||||
physicsEnvironmentPtr->addCcdPhysicsController( physObjects[i]);
|
||||
|
||||
if (i==1)
|
||||
{
|
||||
//physObjects[i]->SetAngularVelocity(0,0,-2,true);
|
||||
}
|
||||
|
||||
physicsEnvironmentPtr->setDebugDrawer(&debugDrawer);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//create a constraint
|
||||
{
|
||||
//physObjects[i]->SetAngularVelocity(0,0,-2,true);
|
||||
int constraintId;
|
||||
|
||||
//0.0f, -1.0f, 1.0f
|
||||
|
||||
float pivotX=CUBE_HALF_EXTENTS,
|
||||
pivotY=-CUBE_HALF_EXTENTS,
|
||||
pivotZ=CUBE_HALF_EXTENTS;
|
||||
|
||||
float axisX=1,axisY=0,axisZ=0;
|
||||
|
||||
/*constraintId =physicsEnvironmentPtr->createConstraint(
|
||||
physObjects[1],
|
||||
//0,
|
||||
physObjects[2],
|
||||
//PHY_POINT2POINT_CONSTRAINT,
|
||||
PHY_LINEHINGE_CONSTRAINT,
|
||||
pivotX,pivotY,pivotZ,
|
||||
axisX,axisY,axisZ
|
||||
);
|
||||
|
||||
*/
|
||||
|
||||
HingeConstraint* hinge = 0;
|
||||
|
||||
SimdVector3 pivotInA(CUBE_HALF_EXTENTS,-CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS);
|
||||
SimdVector3 pivotInB(-CUBE_HALF_EXTENTS,-CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS);
|
||||
SimdVector3 axisInA(0,1,0);
|
||||
SimdVector3 axisInB(0,-1,0);
|
||||
|
||||
RigidBody* rb0 = physObjects[1]->GetRigidBody();
|
||||
RigidBody* rb1 = physObjects[2]->GetRigidBody();
|
||||
|
||||
hinge = new HingeConstraint(
|
||||
*rb0,
|
||||
*rb1,pivotInA,pivotInB,axisInA,axisInB);
|
||||
|
||||
physicsEnvironmentPtr->m_constraints.push_back(hinge);
|
||||
|
||||
hinge->SetUserConstraintId(100);
|
||||
hinge->SetUserConstraintType(PHY_LINEHINGE_CONSTRAINT);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
clientResetScene();
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
simulateMe();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//to be implemented by the demo
|
||||
|
||||
|
||||
void simulateMe()
|
||||
{
|
||||
float deltaTime = 1.f/60.f;
|
||||
physicsEnvironmentPtr->proceedDeltaTime(0.f,deltaTime);
|
||||
|
||||
|
||||
debugDrawer.SetDebugMode(getDebugMode());
|
||||
|
||||
//render the hinge axis
|
||||
{
|
||||
SimdVector3 color(1,0,0);
|
||||
SimdVector3 dirLocal(0,1,0);
|
||||
SimdVector3 pivotInA(CUBE_HALF_EXTENTS,-CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS);
|
||||
SimdVector3 pivotInB(-CUBE_HALF_EXTENTS,-CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS);
|
||||
SimdVector3 from = physObjects[1]->GetRigidBody()->getCenterOfMassTransform()(pivotInA);
|
||||
SimdVector3 fromB = physObjects[2]->GetRigidBody()->getCenterOfMassTransform()(pivotInB);
|
||||
SimdVector3 dirWorldA = physObjects[1]->GetRigidBody()->getCenterOfMassTransform().getBasis() * dirLocal ;
|
||||
SimdVector3 dirWorldB = physObjects[2]->GetRigidBody()->getCenterOfMassTransform().getBasis() * dirLocal ;
|
||||
debugDrawer.DrawLine(from,from+dirWorldA,color);
|
||||
debugDrawer.DrawLine(fromB,fromB+dirWorldB,color);
|
||||
}
|
||||
|
||||
float m[16];
|
||||
int i;
|
||||
|
||||
|
||||
if (getDebugMode() & IDebugDraw::DBG_DisableBulletLCP)
|
||||
{
|
||||
//don't use Bullet, use quickstep
|
||||
physicsEnvironmentPtr->setSolverType(0);
|
||||
} else
|
||||
{
|
||||
//Bullet LCP solver
|
||||
physicsEnvironmentPtr->setSolverType(1);
|
||||
}
|
||||
|
||||
|
||||
bool isSatEnabled = (getDebugMode() & IDebugDraw::DBG_EnableSatComparison);
|
||||
|
||||
physicsEnvironmentPtr->EnableSatCollisionDetection(isSatEnabled);
|
||||
|
||||
|
||||
|
||||
|
||||
for (i=0;i<numObjects;i++)
|
||||
{
|
||||
SimdTransform transA;
|
||||
transA.setIdentity();
|
||||
|
||||
float pos[3];
|
||||
float rot[4];
|
||||
|
||||
ms[i].getWorldPosition(pos[0],pos[1],pos[2]);
|
||||
ms[i].getWorldOrientation(rot[0],rot[1],rot[2],rot[3]);
|
||||
|
||||
SimdQuaternion q(rot[0],rot[1],rot[2],rot[3]);
|
||||
transA.setRotation(q);
|
||||
|
||||
SimdPoint3 dpos;
|
||||
dpos.setValue(pos[0],pos[1],pos[2]);
|
||||
|
||||
transA.setOrigin( dpos );
|
||||
transA.getOpenGLMatrix( m );
|
||||
|
||||
|
||||
SimdVector3 wireColor(1.f,1.0f,0.5f); //wants deactivation
|
||||
if (i & 1)
|
||||
{
|
||||
wireColor = SimdVector3(0.f,0.0f,1.f);
|
||||
}
|
||||
///color differently for active, sleeping, wantsdeactivation states
|
||||
if (physObjects[i]->GetRigidBody()->GetActivationState() == 1) //active
|
||||
{
|
||||
if (i & 1)
|
||||
{
|
||||
wireColor += SimdVector3 (1.f,0.f,0.f);
|
||||
} else
|
||||
{
|
||||
wireColor += SimdVector3 (.5f,0.f,0.f);
|
||||
}
|
||||
}
|
||||
if (physObjects[i]->GetRigidBody()->GetActivationState() == 2) //ISLAND_SLEEPING
|
||||
{
|
||||
if (i & 1)
|
||||
{
|
||||
wireColor += SimdVector3 (0.f,1.f, 0.f);
|
||||
} else
|
||||
{
|
||||
wireColor += SimdVector3 (0.f,0.5f,0.f);
|
||||
}
|
||||
}
|
||||
|
||||
char extraDebug[125];
|
||||
sprintf(extraDebug,"islId, Body=%i , %i",physObjects[i]->GetRigidBody()->m_islandTag1,physObjects[i]->GetRigidBody()->m_debugBodyId);
|
||||
physObjects[i]->GetRigidBody()->GetCollisionShape()->SetExtraDebugInfo(extraDebug);
|
||||
|
||||
//GL_ShapeDrawer::DrawOpenGL(m,physObjects[i]->GetRigidBody()->GetCollisionShape(),wireColor,getDebugMode());
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (!(getDebugMode() & IDebugDraw::DBG_NoHelpText))
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
float xOffset = 10.f;
|
||||
float yStart = 20.f;
|
||||
|
||||
float yIncr = -2.f;
|
||||
|
||||
char buf[124];
|
||||
|
||||
//glColor3f(0, 0, 0);
|
||||
|
||||
#ifdef USE_QUICKPROF
|
||||
if ( getDebugMode() & IDebugDraw::DBG_ProfileTimings)
|
||||
{
|
||||
static int counter = 0;
|
||||
counter++;
|
||||
std::map<std::string, hidden::ProfileBlock*>::iterator iter;
|
||||
for (iter = Profiler::mProfileBlocks.begin(); iter != Profiler::mProfileBlocks.end(); ++iter)
|
||||
{
|
||||
char blockTime[128];
|
||||
sprintf(blockTime, "%s: %lf",&((*iter).first[0]),Profiler::getBlockTime((*iter).first, Profiler::BLOCK_CYCLE_SECONDS));//BLOCK_TOTAL_PERCENT));
|
||||
printf(blockTime);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //USE_QUICKPROF
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
glRasterPos3f(xOffset,yStart,0);
|
||||
sprintf(buf,"mouse to interact");
|
||||
BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf);
|
||||
yStart += yIncr;
|
||||
|
||||
glRasterPos3f(xOffset,yStart,0);
|
||||
sprintf(buf,"space to reset");
|
||||
BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf);
|
||||
yStart += yIncr;
|
||||
|
||||
glRasterPos3f(xOffset,yStart,0);
|
||||
sprintf(buf,"c to show contact points");
|
||||
BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf);
|
||||
yStart += yIncr;
|
||||
|
||||
glRasterPos3f(xOffset,yStart,0);
|
||||
sprintf(buf,"cursor keys and z,x to navigate");
|
||||
BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf);
|
||||
yStart += yIncr;
|
||||
|
||||
glRasterPos3f(xOffset,yStart,0);
|
||||
sprintf(buf,"i to toggle simulation, s single step");
|
||||
BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf);
|
||||
yStart += yIncr;
|
||||
|
||||
glRasterPos3f(xOffset,yStart,0);
|
||||
sprintf(buf,"q to quit");
|
||||
BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf);
|
||||
yStart += yIncr;
|
||||
|
||||
glRasterPos3f(xOffset,yStart,0);
|
||||
sprintf(buf,"d to toggle deactivation");
|
||||
BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf);
|
||||
yStart += yIncr;
|
||||
|
||||
glRasterPos3f(xOffset,yStart,0);
|
||||
sprintf(buf,". to shoot primitive");
|
||||
BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf);
|
||||
yStart += yIncr;
|
||||
|
||||
glRasterPos3f(xOffset,yStart,0);
|
||||
sprintf(buf,"h to toggle help text");
|
||||
BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf);
|
||||
yStart += yIncr;
|
||||
|
||||
bool useBulletLCP = !(getDebugMode() & IDebugDraw::DBG_DisableBulletLCP);
|
||||
|
||||
glRasterPos3f(xOffset,yStart,0);
|
||||
sprintf(buf,"m Bullet GJK = %i",!isSatEnabled);
|
||||
BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf);
|
||||
yStart += yIncr;
|
||||
|
||||
glRasterPos3f(xOffset,yStart,0);
|
||||
sprintf(buf,"n Bullet LCP = %i",useBulletLCP);
|
||||
BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf);
|
||||
yStart += yIncr;
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
///make this positive to show stack falling from a distance
|
||||
///this shows the penalty tresholds in action, springy/spungy look
|
||||
|
||||
|
||||
|
||||
void clientResetScene()
|
||||
{
|
||||
|
||||
int i;
|
||||
for (i=0;i<numObjects;i++)
|
||||
{
|
||||
if (i>0)
|
||||
{
|
||||
|
||||
if ((getDebugMode() & IDebugDraw::DBG_NoHelpText))
|
||||
{
|
||||
if (physObjects[i]->GetRigidBody()->GetCollisionShape()->GetShapeType() == BOX_SHAPE_PROXYTYPE)
|
||||
{
|
||||
physObjects[i]->GetRigidBody()->SetCollisionShape(shapePtr[2]);
|
||||
} else
|
||||
{
|
||||
physObjects[i]->GetRigidBody()->SetCollisionShape(shapePtr[1]);
|
||||
}
|
||||
|
||||
BroadphaseProxy* bpproxy = physObjects[i]->GetRigidBody()->m_broadphaseHandle;
|
||||
physicsEnvironmentPtr->GetBroadphase()->CleanProxyFromPairs(bpproxy);
|
||||
}
|
||||
|
||||
//stack them
|
||||
int colsize = 10;
|
||||
int row = (i*CUBE_HALF_EXTENTS*2)/(colsize*2*CUBE_HALF_EXTENTS);
|
||||
int row2 = row;
|
||||
int col = (i)%(colsize)-colsize/2;
|
||||
|
||||
|
||||
if (col>3)
|
||||
{
|
||||
col=11;
|
||||
row2 |=1;
|
||||
}
|
||||
physObjects[i]->setPosition(col*2*CUBE_HALF_EXTENTS + (row2%2)*CUBE_HALF_EXTENTS,
|
||||
row*2*CUBE_HALF_EXTENTS+CUBE_HALF_EXTENTS+EXTRA_HEIGHT,0);
|
||||
physObjects[i]->setOrientation(0,0,0,1);
|
||||
physObjects[i]->SetLinearVelocity(0,0,0,false);
|
||||
physObjects[i]->SetAngularVelocity(0,0,0,false);
|
||||
} else
|
||||
{
|
||||
ms[i].setWorldPosition(0,-10-EXTRA_HEIGHT,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void shootBox(const SimdVector3& destination)
|
||||
{
|
||||
int i = numObjects-1;
|
||||
|
||||
float speed = 40.f;
|
||||
SimdVector3 linVel(destination[0]-eye[0],destination[1]-eye[1],destination[2]-eye[2]);
|
||||
linVel.normalize();
|
||||
linVel*=speed;
|
||||
|
||||
physObjects[i]->setPosition(eye[0],eye[1],eye[2]);
|
||||
physObjects[i]->setOrientation(0,0,0,1);
|
||||
physObjects[i]->SetLinearVelocity(linVel[0],linVel[1],linVel[2],false);
|
||||
physObjects[i]->SetAngularVelocity(0,0,0,false);
|
||||
}
|
||||
|
||||
void clientKeyboard(unsigned char key, int x, int y)
|
||||
{
|
||||
|
||||
if (key == '.')
|
||||
{
|
||||
shootBox(SimdVector3(0,0,0));
|
||||
}
|
||||
//defaultKeyboard(key, x, y);
|
||||
}
|
||||
|
||||
int gPickingConstraintId = 0;
|
||||
SimdVector3 gOldPickingPos;
|
||||
float gOldPickingDist = 0.f;
|
||||
RigidBody* pickedBody = 0;//for deactivation state
|
||||
|
||||
|
||||
SimdVector3 GetRayTo(int x,int y)
|
||||
{
|
||||
float top = 1.f;
|
||||
float bottom = -1.f;
|
||||
float nearPlane = 1.f;
|
||||
float tanFov = (top-bottom)*0.5f / nearPlane;
|
||||
float fov = 2.0 * atanf (tanFov);
|
||||
|
||||
SimdVector3 rayFrom(eye[0],eye[1],eye[2]);
|
||||
SimdVector3 rayForward = -rayFrom;
|
||||
rayForward.normalize();
|
||||
float farPlane = 600.f;
|
||||
rayForward*= farPlane;
|
||||
|
||||
SimdVector3 rightOffset;
|
||||
SimdVector3 vertical(0.f,1.f,0.f);
|
||||
SimdVector3 hor;
|
||||
hor = rayForward.cross(vertical);
|
||||
hor.normalize();
|
||||
vertical = hor.cross(rayForward);
|
||||
vertical.normalize();
|
||||
|
||||
float tanfov = tanf(0.5f*fov);
|
||||
hor *= 2.f * farPlane * tanfov;
|
||||
vertical *= 2.f * farPlane * tanfov;
|
||||
SimdVector3 rayToCenter = rayFrom + rayForward;
|
||||
SimdVector3 dHor = hor * 1.f/float(glutScreenWidth);
|
||||
SimdVector3 dVert = vertical * 1.f/float(glutScreenHeight);
|
||||
SimdVector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical;
|
||||
rayTo += x * dHor;
|
||||
rayTo -= y * dVert;
|
||||
return rayTo;
|
||||
}
|
||||
void clientMouseFunc(int button, int state, int x, int y)
|
||||
{
|
||||
//printf("button %i, state %i, x=%i,y=%i\n",button,state,x,y);
|
||||
//button 0, state 0 means left mouse down
|
||||
|
||||
SimdVector3 rayTo = GetRayTo(x,y);
|
||||
|
||||
switch (button)
|
||||
{
|
||||
case 2:
|
||||
{
|
||||
if (state==0)
|
||||
{
|
||||
shootBox(rayTo);
|
||||
}
|
||||
break;
|
||||
};
|
||||
case 1:
|
||||
{
|
||||
if (state==0)
|
||||
{
|
||||
//apply an impulse
|
||||
if (physicsEnvironmentPtr)
|
||||
{
|
||||
float hit[3];
|
||||
float normal[3];
|
||||
PHY_IPhysicsController* hitObj = physicsEnvironmentPtr->rayTest(0,eye[0],eye[1],eye[2],rayTo.getX(),rayTo.getY(),rayTo.getZ(),hit[0],hit[1],hit[2],normal[0],normal[1],normal[2]);
|
||||
if (hitObj)
|
||||
{
|
||||
CcdPhysicsController* physCtrl = static_cast<CcdPhysicsController*>(hitObj);
|
||||
RigidBody* body = physCtrl->GetRigidBody();
|
||||
if (body)
|
||||
{
|
||||
body->SetActivationState(ACTIVE_TAG);
|
||||
SimdVector3 impulse = rayTo;
|
||||
impulse.normalize();
|
||||
float impulseStrength = 10.f;
|
||||
impulse *= impulseStrength;
|
||||
SimdVector3 relPos(
|
||||
hit[0] - body->getCenterOfMassPosition().getX(),
|
||||
hit[1] - body->getCenterOfMassPosition().getY(),
|
||||
hit[2] - body->getCenterOfMassPosition().getZ());
|
||||
|
||||
body->applyImpulse(impulse,relPos);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else
|
||||
{
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0:
|
||||
{
|
||||
if (state==0)
|
||||
{
|
||||
//add a point to point constraint for picking
|
||||
if (physicsEnvironmentPtr)
|
||||
{
|
||||
float hit[3];
|
||||
float normal[3];
|
||||
PHY_IPhysicsController* hitObj = physicsEnvironmentPtr->rayTest(0,eye[0],eye[1],eye[2],rayTo.getX(),rayTo.getY(),rayTo.getZ(),hit[0],hit[1],hit[2],normal[0],normal[1],normal[2]);
|
||||
if (hitObj)
|
||||
{
|
||||
|
||||
CcdPhysicsController* physCtrl = static_cast<CcdPhysicsController*>(hitObj);
|
||||
RigidBody* body = physCtrl->GetRigidBody();
|
||||
|
||||
if (body)
|
||||
{
|
||||
pickedBody = body;
|
||||
pickedBody->SetActivationState(DISABLE_DEACTIVATION);
|
||||
|
||||
SimdVector3 pickPos(hit[0],hit[1],hit[2]);
|
||||
|
||||
SimdVector3 localPivot = body->getCenterOfMassTransform().inverse() * pickPos;
|
||||
|
||||
gPickingConstraintId = physicsEnvironmentPtr->createConstraint(physCtrl,0,PHY_POINT2POINT_CONSTRAINT,
|
||||
localPivot.getX(),
|
||||
localPivot.getY(),
|
||||
localPivot.getZ(),
|
||||
0,0,0);
|
||||
//printf("created constraint %i",gPickingConstraintId);
|
||||
|
||||
//save mouse position for dragging
|
||||
gOldPickingPos = rayTo;
|
||||
|
||||
|
||||
SimdVector3 eyePos(eye[0],eye[1],eye[2]);
|
||||
|
||||
gOldPickingDist = (pickPos-eyePos).length();
|
||||
|
||||
Point2PointConstraint* p2p = static_cast<Point2PointConstraint*>(physicsEnvironmentPtr->getConstraintById(gPickingConstraintId));
|
||||
if (p2p)
|
||||
{
|
||||
//very weak constraint for picking
|
||||
p2p->m_setting.m_tau = 0.1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (gPickingConstraintId && physicsEnvironmentPtr)
|
||||
{
|
||||
physicsEnvironmentPtr->removeConstraint(gPickingConstraintId);
|
||||
//printf("removed constraint %i",gPickingConstraintId);
|
||||
gPickingConstraintId = 0;
|
||||
pickedBody->ForceActivationState(ACTIVE_TAG);
|
||||
pickedBody->m_deactivationTime = 0.f;
|
||||
pickedBody = 0;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
default:
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void clientMotionFunc(int x,int y)
|
||||
{
|
||||
|
||||
if (gPickingConstraintId && physicsEnvironmentPtr)
|
||||
{
|
||||
|
||||
//move the constraint pivot
|
||||
|
||||
Point2PointConstraint* p2p = static_cast<Point2PointConstraint*>(physicsEnvironmentPtr->getConstraintById(gPickingConstraintId));
|
||||
if (p2p)
|
||||
{
|
||||
//keep it at the same picking distance
|
||||
|
||||
SimdVector3 newRayTo = GetRayTo(x,y);
|
||||
SimdVector3 eyePos(eye[0],eye[1],eye[2]);
|
||||
SimdVector3 dir = newRayTo-eyePos;
|
||||
dir.normalize();
|
||||
dir *= gOldPickingDist;
|
||||
|
||||
SimdVector3 newPos = eyePos + dir;
|
||||
p2p->SetPivotB(newPos);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
SubDir TOP Demos BasicSample ;
|
||||
|
||||
BulletBasicDemo BasicSample : [ Wildcard *.h *.cpp ] ;
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "MyMotionState.h"
|
||||
#include "SimdPoint3.h"
|
||||
|
||||
MyMotionState::MyMotionState()
|
||||
{
|
||||
m_worldTransform.setIdentity();
|
||||
}
|
||||
|
||||
|
||||
MyMotionState::~MyMotionState()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MyMotionState::getWorldPosition(float& posX,float& posY,float& posZ)
|
||||
{
|
||||
posX = m_worldTransform.getOrigin().x();
|
||||
posY = m_worldTransform.getOrigin().y();
|
||||
posZ = m_worldTransform.getOrigin().z();
|
||||
}
|
||||
|
||||
void MyMotionState::getWorldScaling(float& scaleX,float& scaleY,float& scaleZ)
|
||||
{
|
||||
scaleX = 1.;
|
||||
scaleY = 1.;
|
||||
scaleZ = 1.;
|
||||
}
|
||||
|
||||
void MyMotionState::getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal)
|
||||
{
|
||||
quatIma0 = m_worldTransform.getRotation().x();
|
||||
quatIma1 = m_worldTransform.getRotation().y();
|
||||
quatIma2 = m_worldTransform.getRotation().z();
|
||||
quatReal = m_worldTransform.getRotation()[3];
|
||||
}
|
||||
|
||||
void MyMotionState::setWorldPosition(float posX,float posY,float posZ)
|
||||
{
|
||||
SimdPoint3 pos(posX,posY,posZ);
|
||||
m_worldTransform.setOrigin( pos );
|
||||
}
|
||||
|
||||
void MyMotionState::setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal)
|
||||
{
|
||||
SimdQuaternion orn(quatIma0,quatIma1,quatIma2,quatReal);
|
||||
m_worldTransform.setRotation( orn );
|
||||
}
|
||||
|
||||
void MyMotionState::calculateWorldTransformations()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef MY_MOTIONSTATE_H
|
||||
#define MY_MOTIONSTATE_H
|
||||
|
||||
#include "PHY_IMotionState.h"
|
||||
#include <SimdTransform.h>
|
||||
|
||||
|
||||
class MyMotionState : public PHY_IMotionState
|
||||
|
||||
{
|
||||
public:
|
||||
MyMotionState();
|
||||
|
||||
virtual ~MyMotionState();
|
||||
|
||||
virtual void getWorldPosition(float& posX,float& posY,float& posZ);
|
||||
virtual void getWorldScaling(float& scaleX,float& scaleY,float& scaleZ);
|
||||
virtual void getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal);
|
||||
|
||||
virtual void setWorldPosition(float posX,float posY,float posZ);
|
||||
virtual void setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal);
|
||||
|
||||
virtual void calculateWorldTransformations();
|
||||
|
||||
SimdTransform m_worldTransform;
|
||||
|
||||
};
|
||||
|
||||
#endif //MY_MOTIONSTATE_H
|
||||
@@ -1,31 +0,0 @@
|
||||
#include "PrintfDebugDrawer.h"
|
||||
|
||||
#include <stdio.h> //printf debugging
|
||||
|
||||
PrintfDebugDrawer::PrintfDebugDrawer()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void PrintfDebugDrawer::DrawLine(const SimdVector3& from,const SimdVector3& to,const SimdVector3& color)
|
||||
{
|
||||
if (m_debugMode > 0)
|
||||
{
|
||||
printf("DrawLine: from(%f , %f . %f) , to(%f , %f . %f)\n",from.getX(),from.getY(),from.getZ(),to.getX(),to.getY(),to.getZ());
|
||||
}
|
||||
}
|
||||
|
||||
void PrintfDebugDrawer::DrawContactPoint(const SimdVector3& pointOnB,const SimdVector3& normalOnB,float distance,int lifeTime,const SimdVector3& color)
|
||||
{
|
||||
if (m_debugMode & IDebugDraw::DBG_DrawContactPoints)
|
||||
{
|
||||
SimdVector3 to=pointOnB+normalOnB*distance;
|
||||
const SimdVector3&from = pointOnB;
|
||||
printf("DrawContactPoint (%d) from(%f , %f . %f) , to(%f , %f . %f)\n",lifeTime, from.getX(),from.getY(),from.getZ(),to.getX(),to.getY(),to.getZ());
|
||||
}
|
||||
}
|
||||
|
||||
void PrintfDebugDrawer::SetDebugMode(int debugMode)
|
||||
{
|
||||
m_debugMode = debugMode;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#ifndef PRINTF_DEBUG_DRAWER_H
|
||||
#define PRINTF_DEBUG_DRAWER_H
|
||||
|
||||
#include "IDebugDraw.h"
|
||||
|
||||
|
||||
|
||||
|
||||
class PrintfDebugDrawer : public IDebugDraw
|
||||
{
|
||||
int m_debugMode;
|
||||
|
||||
public:
|
||||
|
||||
PrintfDebugDrawer();
|
||||
|
||||
virtual void DrawLine(const SimdVector3& from,const SimdVector3& to,const SimdVector3& color);
|
||||
|
||||
virtual void DrawContactPoint(const SimdVector3& PointOnB,const SimdVector3& normalOnB,float distance,int lifeTime,const SimdVector3& color);
|
||||
|
||||
virtual void SetDebugMode(int debugMode);
|
||||
|
||||
virtual int GetDebugMode() const { return m_debugMode;}
|
||||
|
||||
};
|
||||
|
||||
#endif//PRINTF_DEBUG_DRAWER_H
|
||||
@@ -75,7 +75,6 @@ else
|
||||
SubInclude TOP Demos CcdPhysicsDemo ;
|
||||
SubInclude TOP Demos ConvexDecompositionDemo ;
|
||||
SubInclude TOP Demos ColladaDemo ;
|
||||
SubInclude TOP Demos BasicSample ;
|
||||
SubInclude TOP Demos CollisionDemo ;
|
||||
SubInclude TOP Demos CollisionInterfaceDemo ;
|
||||
SubInclude TOP Demos ConcaveDemo ;
|
||||
|
||||
@@ -90,7 +90,7 @@ bool stepping= true;
|
||||
bool singleStep = false;
|
||||
|
||||
|
||||
static bool idle = true;
|
||||
static bool idle = false;
|
||||
|
||||
void toggleIdle() {
|
||||
|
||||
@@ -365,7 +365,7 @@ int glutmain(int argc, char **argv,int width,int height,const char* title) {
|
||||
glutSpecialFunc(mySpecial);
|
||||
glutReshapeFunc(myReshape);
|
||||
//createMenu();
|
||||
glutIdleFunc(0);//clientMoveAndDisplay);
|
||||
glutIdleFunc(clientMoveAndDisplay);
|
||||
glutMouseFunc(clientMouseFunc);
|
||||
glutMotionFunc(clientMotionFunc);
|
||||
glutDisplayFunc( clientDisplay );
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
|
||||
#include "BVHTrimeshShape.h"
|
||||
|
||||
#define TRIMESH_INTERNAL //requires OPCODE for the AABB tree
|
||||
#include <../ode/src/collision_trimesh_internal.h>
|
||||
|
||||
//Thanks AndrewONeil for the TrimeshBridge fix
|
||||
|
||||
BVHTrimeshShape::BVHTrimeshShape(dxTriMesh* trimesh)
|
||||
: TriangleMeshShape(new TrimeshBridge(trimesh))
|
||||
, m_triangleBridge( static_cast<TrimeshBridge*>(m_meshInterface))
|
||||
{
|
||||
}
|
||||
|
||||
BVHTrimeshShape::~BVHTrimeshShape ()
|
||||
{
|
||||
delete m_triangleBridge;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TrimeshBridge::TrimeshBridge(dxTriMesh* trimesh)
|
||||
:m_trimesh(trimesh)
|
||||
{
|
||||
}
|
||||
|
||||
void TrimeshBridge::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const
|
||||
{
|
||||
numverts = m_trimesh->Data->Mesh.GetNbVertices();
|
||||
(*vertexbase) = (unsigned char *)m_trimesh->Data->Mesh.GetVerts();
|
||||
type = PHY_FLOAT;
|
||||
stride = m_trimesh->Data->Mesh.GetVertexStride();
|
||||
|
||||
numfaces = m_trimesh->Data->Mesh.GetNbTriangles();
|
||||
(*indexbase) = (unsigned char *)m_trimesh->Data->Mesh.GetTris();
|
||||
indexstride = m_trimesh->Data->Mesh.GetTriStride();
|
||||
indicestype = PHY_INTEGER;
|
||||
}
|
||||
|
||||
void TrimeshBridge::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart)
|
||||
{
|
||||
|
||||
numverts = m_trimesh->Data->Mesh.GetNbVertices();
|
||||
(*vertexbase) = (unsigned char *)m_trimesh->Data->Mesh.GetVerts();
|
||||
type = PHY_FLOAT;
|
||||
stride = m_trimesh->Data->Mesh.GetVertexStride();
|
||||
|
||||
numfaces = m_trimesh->Data->Mesh.GetNbTriangles();
|
||||
(*indexbase) = (unsigned char *)m_trimesh->Data->Mesh.GetTris();
|
||||
indexstride = m_trimesh->Data->Mesh.GetTriStride();
|
||||
indicestype = PHY_INTEGER;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_AABB_TREE
|
||||
|
||||
//ProcessAllTriangles first gets the overlapping triangles using BVH culling
|
||||
//and passes them on to the TriangleCallback
|
||||
void BVHTrimeshShape::ProcessAllTriangles(TriangleCallback* callback,const SimdVector3& aabbMin,const SimdVector3& aabbMax) const
|
||||
{
|
||||
dxTriMesh* TriMesh = m_triangleBridge->m_trimesh;
|
||||
|
||||
// Init
|
||||
const dVector3& TLPosition = *(const dVector3*)dGeomGetPosition(TriMesh);
|
||||
const dMatrix3& TLRotation = *(const dMatrix3*)dGeomGetRotation(TriMesh);
|
||||
|
||||
SphereCollider& Collider = TriMesh->_SphereCollider;
|
||||
|
||||
|
||||
SimdVector3 he = (aabbMax-aabbMin)*0.5f;
|
||||
SimdVector3 cen = (aabbMax+aabbMin)*0.5f;
|
||||
|
||||
|
||||
dVector3 aabbHalfExtents;
|
||||
aabbHalfExtents[0] = he.x();
|
||||
aabbHalfExtents[1] = he.y();
|
||||
aabbHalfExtents[2] = he.z();
|
||||
|
||||
dVector3 Position;
|
||||
Position[0]=cen.x();
|
||||
Position[1]=cen.y();
|
||||
Position[2]=cen.z();
|
||||
|
||||
dReal Radius = he.length();
|
||||
|
||||
// Bounding Sphere (from aabb)
|
||||
Sphere Sphere;
|
||||
Sphere.mCenter.x = Position[0];
|
||||
Sphere.mCenter.y = Position[1];
|
||||
Sphere.mCenter.z = Position[2];
|
||||
Sphere.mRadius = Radius;
|
||||
|
||||
Matrix4x4 trimeshTransform;
|
||||
MakeMatrix(TLPosition, TLRotation, trimeshTransform);
|
||||
|
||||
// bvhTraversal.getOverlappingPrimitiveIndices(
|
||||
// indicesCache,
|
||||
// Sphere,
|
||||
// TriMesh->Data->BVTree,
|
||||
// &trimeshTransform);
|
||||
|
||||
Collider.SetTemporalCoherence(false);
|
||||
Collider.SetPrimitiveTests(false);
|
||||
Collider.Collide(dxTriMesh::defaultSphereCache, Sphere, TriMesh->Data->BVTree, null,
|
||||
&trimeshTransform);
|
||||
|
||||
// get results
|
||||
int TriCount = Collider.GetNbTouchedPrimitives();
|
||||
const int* Triangles = (const int*)Collider.GetTouchedPrimitives();
|
||||
|
||||
if (TriCount != 0){
|
||||
|
||||
int OutTriCount = 0;
|
||||
for (int i = 0; i < TriCount; i++){
|
||||
//what was this
|
||||
//if (OutTriCount == (Flags & 0xffff)){
|
||||
// break;
|
||||
//}
|
||||
|
||||
const int& TriIndex = Triangles[i];
|
||||
|
||||
dVector3 dv[3];
|
||||
FetchTriangle(TriMesh, TriIndex, TLPosition, TLRotation, dv);
|
||||
|
||||
SimdVector3 vts[3] =
|
||||
{ SimdVector3(dv[0][0],dv[0][1],dv[0][2]),
|
||||
SimdVector3 (dv[1][0],dv[1][1],dv[1][2]),
|
||||
SimdVector3 (dv[2][0],dv[2][1],dv[2][2])
|
||||
};
|
||||
|
||||
callback->ProcessTriangle(&vts[0]);
|
||||
|
||||
OutTriCount++;
|
||||
}
|
||||
if (OutTriCount)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#endif //USE_AABB_TREE
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
|
||||
#ifndef BVH_TRIMESH_SHAPE_H
|
||||
#define BVH_TRIMESH_SHAPE_H
|
||||
|
||||
#include <ode/collision.h>
|
||||
#include <ode/matrix.h>
|
||||
#include <ode/rotation.h>
|
||||
#include <ode/odemath.h>
|
||||
#include <../ode/src/collision_util.h>
|
||||
#include <../ode/src/collision_kernel.h>
|
||||
#include <../ode/src/collision_kernel.h>
|
||||
#include "CollisionShapes/TriangleMeshShape.h"
|
||||
struct dxTriMesh;
|
||||
|
||||
///if this USE_AABB_TREE is not defined, it will brute force go through all triangles
|
||||
#define USE_AABB_TREE
|
||||
|
||||
|
||||
class TrimeshBridge : public StridingMeshInterface
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
dxTriMesh* m_trimesh;
|
||||
|
||||
TrimeshBridge(dxTriMesh* trimesh);
|
||||
|
||||
virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0);
|
||||
|
||||
virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const;
|
||||
|
||||
/// unLockVertexBase finishes the access to a subpart of the triangle mesh
|
||||
/// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
|
||||
virtual void unLockVertexBase(int subpart) {}
|
||||
|
||||
virtual void unLockReadOnlyVertexBase(int subpart) const {}
|
||||
|
||||
/// getNumSubParts returns the number of seperate subparts
|
||||
/// each subpart has a continuous array of vertices and indices
|
||||
virtual int getNumSubParts() const { return 1;}
|
||||
|
||||
virtual void preallocateVertices(int numverts){}
|
||||
virtual void preallocateIndices(int numindices){}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/// BVHTrimeshShape bridges the Opcode to provide backwards compatibility with dxTriMesh.
|
||||
/// You can also avoid using Opcode and use Bullet trimesh support See: BvhTriangleMeshShape
|
||||
class BVHTrimeshShape : public TriangleMeshShape
|
||||
{
|
||||
TrimeshBridge * m_triangleBridge;
|
||||
|
||||
public:
|
||||
BVHTrimeshShape(dxTriMesh* trimesh);
|
||||
virtual ~BVHTrimeshShape ();
|
||||
|
||||
|
||||
#ifdef USE_AABB_TREE
|
||||
//ProcessAllTriangles first gets the overlapping triangles using BVH culling
|
||||
//and passes them on to the TriangleCallback
|
||||
void ProcessAllTriangles(TriangleCallback* callback,const SimdVector3& aabbMin,const SimdVector3& aabbMax) const;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //BVH_TRIMESH_SHAPE_H
|
||||
@@ -1,139 +0,0 @@
|
||||
|
||||
#include "BulletOdeCollide.h"
|
||||
|
||||
//quick hack, we need internals, not just the public ode api
|
||||
#include <../ode/src/collision_kernel.h>
|
||||
|
||||
#include "NarrowPhaseCollision/PersistentManifold.h"
|
||||
#include "NarrowPhaseCollision/ManifoldPoint.h"
|
||||
|
||||
#include "BroadphaseCollision/CollisionAlgorithm.h"
|
||||
#include "BulletOdeCollisionPair.h"
|
||||
#include "../ode/src/collision_convex_internal.h"
|
||||
|
||||
#define CONTACT(p,skip) ((dContactGeom*) (((char*)p) + (skip)))
|
||||
|
||||
|
||||
//Persistent collision pairs. Best is to store this in the broadphase/collision-pairs if the collision detection framework provides this
|
||||
#define MAX_COLLISION_PAIRS 10000
|
||||
static BulletOdeCollisionPair* sCollisionPair[MAX_COLLISION_PAIRS];
|
||||
static int numActiveCollisionPairs = 0;
|
||||
|
||||
void InitBulletOdeCollide()
|
||||
{
|
||||
numActiveCollisionPairs = 0;
|
||||
}
|
||||
|
||||
void ExitBulletOdeCollide()
|
||||
{
|
||||
//todo: cleanup memory
|
||||
numActiveCollisionPairs = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CollisionShape* GetCollisionShapeFromConvex(dGeomID geom)
|
||||
{
|
||||
dUASSERT (geom && geom->type == dConvexClass,"argument not a convex");
|
||||
dxConvex* cnvx = (dxConvex*) geom;
|
||||
return cnvx->m_bulletCollisionShape;
|
||||
}
|
||||
|
||||
|
||||
BulletOdeCollisionPair* FindCollisionPair(dGeomID o1,dGeomID o2)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<numActiveCollisionPairs;i++)
|
||||
{
|
||||
if ( (sCollisionPair[i]->m_o1 == o1) &&
|
||||
(sCollisionPair[i]->m_o2 == o2))
|
||||
{
|
||||
return sCollisionPair[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void RemoveOdeGeomFromCollisionCache(dGeomID geom)
|
||||
{
|
||||
int i;
|
||||
for (i=numActiveCollisionPairs-1;i>=0;i--)
|
||||
{
|
||||
if ( (sCollisionPair[i]->m_o1 == geom) ||
|
||||
(sCollisionPair[i]->m_o2 == geom))
|
||||
{
|
||||
delete sCollisionPair[i];
|
||||
sCollisionPair[i] = sCollisionPair[numActiveCollisionPairs-1];
|
||||
numActiveCollisionPairs--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int BulletOdeCollide(dGeomID o1,dGeomID o2,dContactGeom *contact,int maxContact,int skip)
|
||||
{
|
||||
|
||||
//In order to have more then 1 point we use persistent manifold per overlapping pair
|
||||
BulletOdeCollisionPair* collisionPair = FindCollisionPair(o1,o2);
|
||||
if (!collisionPair)
|
||||
{
|
||||
if (numActiveCollisionPairs < MAX_COLLISION_PAIRS)
|
||||
{
|
||||
collisionPair = new BulletOdeCollisionPair(o1,o2);
|
||||
sCollisionPair[numActiveCollisionPairs++] = collisionPair ;
|
||||
} else
|
||||
{
|
||||
printf("overflow in collisionpair cache\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//perform collision detection and recalculate the contact manifold
|
||||
collisionPair->CalculateContacts();
|
||||
|
||||
//transfer contacts from PersistentManifold to gContactGeom
|
||||
int validContacts = 0;
|
||||
float maxDepth = -1e30f;
|
||||
|
||||
for (int i=0; i<collisionPair->m_manifold->GetNumContacts(); i++)
|
||||
{
|
||||
const ManifoldPoint& pt = collisionPair->m_manifold->GetContactPoint(i);
|
||||
|
||||
if (pt.GetDistance() < 0.f)
|
||||
{
|
||||
float depth = -pt.GetDistance();
|
||||
|
||||
//add contacts, and make sure to add the deepest contact in any case
|
||||
if ((validContacts < maxContact) || (depth > maxDepth))
|
||||
{
|
||||
maxDepth = depth;
|
||||
int contactIndex = validContacts;
|
||||
|
||||
if (contactIndex >= maxContact)
|
||||
contactIndex = 0;
|
||||
|
||||
if (contactIndex < maxContact)
|
||||
{
|
||||
SimdVector3 pos = (pt.m_positionWorldOnB + pt.m_positionWorldOnA)*0.5f;
|
||||
|
||||
CONTACT(contact,contactIndex*skip)->depth = depth;
|
||||
CONTACT(contact,contactIndex*skip)->pos[0] = pos.getX();
|
||||
CONTACT(contact,contactIndex*skip)->pos[1] = pos.getY();
|
||||
CONTACT(contact,contactIndex*skip)->pos[2] = pos.getZ();
|
||||
CONTACT(contact,contactIndex*skip)->normal[0] = pt.m_normalWorldOnB.getX();
|
||||
CONTACT(contact,contactIndex*skip)->normal[1] = pt.m_normalWorldOnB.getY();
|
||||
CONTACT(contact,contactIndex*skip)->normal[2] = pt.m_normalWorldOnB.getZ();
|
||||
CONTACT(contact,contactIndex*skip)->g1 = o1;
|
||||
CONTACT(contact,contactIndex*skip)->g2 = o2;
|
||||
}
|
||||
if (validContacts < maxContact)
|
||||
validContacts++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//printf("numcontacts: %d",validContacts);
|
||||
|
||||
return validContacts;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#ifndef _BULLET_ODE_COLLIDE_H
|
||||
#define _BULLET_ODE_COLLIDE_H
|
||||
|
||||
#include <ode/common.h>
|
||||
#include <ode/contact.h>
|
||||
|
||||
int BulletOdeCollide(dGeomID o1,dGeomID o2,dContactGeom *contact,int maxContacts,int skip);
|
||||
void RemoveOdeGeomFromCollisionCache(dGeomID geom);
|
||||
class CollisionShape* GetCollisionShapeFromConvex(dGeomID convex);
|
||||
dGeomID dCreateConvex (dSpaceID space, class CollisionShape* shape);
|
||||
void dGeomConvexGetLengths(dGeomID convex, dVector3 result);
|
||||
|
||||
#endif //_BULLET_ODE_COLLIDE_H
|
||||
@@ -1,161 +0,0 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="BulletOdeCollide"
|
||||
ProjectGUID="{44672927-0084-4B70-8CDA-8697BF848C7F}"
|
||||
RootNamespace="BulletOdeCollide"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../ode/include;../../Bullet;../../LinearMath;."
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB,BULLET_CONVEX_SUPPORT"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories="../ode/include;../../Bullet;../../LinearMath;."
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB,BULLET_CONVEX_SUPPORT"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath=".\BulletOdeCollide.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\BulletOdeCollisionPair.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\BulletOdeManifoldResult.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\BulletOdeTransformConvert.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ode\ode\src\collision_convex.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GeomToShape.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
||||
<File
|
||||
RelativePath=".\BulletOdeCollide.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\BulletOdeCollisionPair.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\BulletOdeManifoldResult.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\BulletOdeTransformConvert.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\BVHTraversal.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\BVHTrimeshShape.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GeomToShape.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\VTune\BulletOdeCollide.vpj">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ReadMe.txt">
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -1,184 +0,0 @@
|
||||
#include "BulletOdeCollisionPair.h"
|
||||
|
||||
#include "NarrowPhaseCollision/PersistentManifold.h"
|
||||
//quick hack, we need internals, not just the public ode api
|
||||
#include <../ode/src/collision_kernel.h>
|
||||
#include "CollisionShapes/BoxShape.h"
|
||||
#include "BulletOdeCollide.h"
|
||||
|
||||
#include "CollisionShapes/SphereShape.h"
|
||||
#include "CollisionShapes/CylinderShape.h"
|
||||
#include "CollisionShapes/MultiSphereShape.h"//capped cylinder is convex hull of two spheres
|
||||
#include "CollisionShapes/ConvexTriangleCallback.h"
|
||||
|
||||
#include "BVHTrimeshShape.h"
|
||||
|
||||
#include "NarrowPhaseCollision/GjkPairDetector.h"
|
||||
#include "NarrowPhaseCollision/VoronoiSimplexSolver.h"
|
||||
#include "NarrowPhaseCollision/MinkowskiPenetrationDepthSolver.h"
|
||||
///for comparison/unit testing
|
||||
#ifdef UNIT_TEST_COMPARE_PENETRATION_DEPTH
|
||||
#include "../ExtraSolid35/Solid3EpaPenetrationDepth.h"
|
||||
#endif //UNIT_TEST_COMPARE_PENETRATION_DEPTH
|
||||
|
||||
#include "BulletOdeManifoldResult.h"
|
||||
#include "BulletOdeTransformConvert.h"
|
||||
|
||||
BulletOdeCollisionPair::BulletOdeCollisionPair(dGeomID o1,dGeomID o2)
|
||||
{
|
||||
m_manifold = new PersistentManifold();
|
||||
|
||||
m_o1 = o1;
|
||||
m_o2 = o2;
|
||||
|
||||
m_shape1 = CreateShapeFromGeom(o1);
|
||||
|
||||
m_shape2 = CreateShapeFromGeom(o2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
BulletOdeCollisionPair::~BulletOdeCollisionPair()
|
||||
{
|
||||
}
|
||||
|
||||
void BulletOdeCollisionPair::CalculateContacts()
|
||||
{
|
||||
//perform gjk, passing the points to the persistent manifold and convert to ode contacts
|
||||
|
||||
if ((!m_shape1) || (!m_shape2))
|
||||
return;
|
||||
|
||||
if (m_shape1->IsConcave() && m_shape2->IsConvex())
|
||||
{
|
||||
TriangleMeshShape* triangleMesh = (TriangleMeshShape*)m_shape1;
|
||||
ConvexShape* convexShape2 = (ConvexShape*)m_shape2;
|
||||
|
||||
float collisionMarginTriangle = 0.02f;//triangleMesh->GetMargin();
|
||||
SimdTransform triangleMeshTrans = GetTransformFromGeom(m_o1);
|
||||
SimdTransform convexTrans = GetTransformFromGeom(m_o2);
|
||||
|
||||
ConvexTriangleCallback convexTriangleCallback(m_manifold,convexShape2,convexTrans,triangleMeshTrans);
|
||||
convexTriangleCallback.Update(collisionMarginTriangle);
|
||||
|
||||
triangleMesh->ProcessAllTriangles( &convexTriangleCallback,convexTriangleCallback.GetAabbMin(),convexTriangleCallback.GetAabbMax());
|
||||
|
||||
m_manifold->RefreshContactPoints(triangleMeshTrans,convexTrans);
|
||||
|
||||
}
|
||||
|
||||
if (m_shape1->IsConvex() && m_shape2->IsConvex())
|
||||
{
|
||||
ConvexShape* convexShape1 = (ConvexShape*)m_shape1;
|
||||
ConvexShape* convexShape2 = (ConvexShape*)m_shape2;
|
||||
|
||||
|
||||
|
||||
BulletOdeManifoldResult output(m_o1,m_o2,m_manifold);
|
||||
|
||||
GjkPairDetector::ClosestPointInput input;
|
||||
|
||||
VoronoiSimplexSolver simplexSolver;
|
||||
|
||||
#ifdef UNIT_TEST_COMPARE_PENETRATION_DEPTH
|
||||
Solid3EpaPenetrationDepth penetrationDepthSolver;
|
||||
#else
|
||||
MinkowskiPenetrationDepthSolver penetrationDepthSolver;
|
||||
#endif// UNIT_TEST_COMPARE_PENETRATION_DEPTH
|
||||
|
||||
GjkPairDetector gjkDetector(convexShape1,convexShape2,&simplexSolver,&penetrationDepthSolver);
|
||||
|
||||
|
||||
gjkDetector.SetMinkowskiA(convexShape1);
|
||||
gjkDetector.SetMinkowskiB(convexShape2);
|
||||
input.m_maximumDistanceSquared = m_shape1->GetMargin()+ m_shape2->GetMargin() + m_manifold->GetManifoldMargin();
|
||||
input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
|
||||
|
||||
input.m_maximumDistanceSquared = 1e30;//?
|
||||
|
||||
input.m_transformA = GetTransformFromGeom(m_o1);
|
||||
input.m_transformB = GetTransformFromGeom(m_o2);
|
||||
|
||||
gjkDetector.GetClosestPoints(input,output,0);
|
||||
|
||||
m_manifold->RefreshContactPoints(input.m_transformA,input.m_transformB);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void BulletOdeCollisionPair::ProcessCollision (BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,const struct DispatcherInfo& dispatchInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
float BulletOdeCollisionPair::CalculateTimeOfImpact(BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,const struct DispatcherInfo& dispatchInfo)
|
||||
{
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
|
||||
CollisionShape* BulletOdeCollisionPair::CreateShapeFromGeom(dGeomID geom)
|
||||
{
|
||||
CollisionShape* shape = 0;
|
||||
|
||||
if (geom->type == dConvexClass)
|
||||
{
|
||||
shape = GetCollisionShapeFromConvex(geom);
|
||||
} else
|
||||
{
|
||||
//bullet shape versus ode geom, create a compatible shape from the ode types
|
||||
switch (geom->type)
|
||||
{
|
||||
case dPlaneClass:
|
||||
break;
|
||||
case dBoxClass:
|
||||
{
|
||||
dVector3 size;
|
||||
dGeomBoxGetLengths (geom,size);
|
||||
SimdVector3 halfExtents(0.5f*size[0],0.5f*size[1],0.5f*size[2]);
|
||||
shape = new BoxShape(halfExtents);
|
||||
break;
|
||||
}
|
||||
case dSphereClass:
|
||||
{
|
||||
dVector3 size;
|
||||
shape = new SphereShape(dGeomSphereGetRadius(geom));
|
||||
break;
|
||||
}
|
||||
case dCylinderClass:
|
||||
{
|
||||
dVector3 size;
|
||||
dGeomBoxGetLengths (geom,size);
|
||||
SimdVector3 boxHalfExtents(size[0],size[0],size[1]);
|
||||
shape = new CylinderShapeZ(boxHalfExtents);
|
||||
break;
|
||||
}
|
||||
case dCCylinderClass:
|
||||
{
|
||||
dReal radius,length;
|
||||
dGeomCCylinderGetParams (geom, &radius, &length);
|
||||
SimdVector3 boxHalfExtents(radius,radius,0.5f*length);
|
||||
int numspheres = 2;
|
||||
SimdVector3 centers[2]={ SimdVector3(0,0,0.5f*length),SimdVector3(0,0,-0.5f*length)};
|
||||
SimdScalar radi[2]={radius,radius};
|
||||
shape = new MultiSphereShape(boxHalfExtents,centers,radi,numspheres);
|
||||
break;
|
||||
}
|
||||
case dTriMeshClass:
|
||||
{
|
||||
dxTriMesh* trimesh = (dxTriMesh*) geom;
|
||||
shape = 0;//new BVHTrimeshShape(trimesh);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
return shape;
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
#ifndef BULLET_ODE_COLLISION_PAIR_H
|
||||
#define BULLET_ODE_COLLISION_PAIR_H
|
||||
|
||||
#include <BroadphaseCollision/CollisionAlgorithm.h>
|
||||
#include <ode/common.h>
|
||||
class PersistentManifold;
|
||||
|
||||
/// BulletOdeCollisionPair provides Bullet convex collision detection for Open Dynamics Engine
|
||||
class BulletOdeCollisionPair : public CollisionAlgorithm
|
||||
{
|
||||
public:
|
||||
BulletOdeCollisionPair(dGeomID o1,dGeomID o2);
|
||||
virtual ~BulletOdeCollisionPair();
|
||||
|
||||
PersistentManifold* m_manifold;
|
||||
dGeomID m_o1;
|
||||
dGeomID m_o2;
|
||||
|
||||
class CollisionShape* m_shape1;
|
||||
|
||||
class CollisionShape* m_shape2;
|
||||
|
||||
|
||||
void CalculateContacts();
|
||||
|
||||
CollisionShape* CreateShapeFromGeom(dGeomID);
|
||||
|
||||
///future support for Bullet broadphase + framework?
|
||||
virtual void ProcessCollision (BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,const struct DispatcherInfo& dispatchInfo);
|
||||
|
||||
///future support for Bullet broadphase + framework?
|
||||
virtual float CalculateTimeOfImpact(BroadphaseProxy* proxy0,BroadphaseProxy* proxy1,const struct DispatcherInfo& dispatchInfo);
|
||||
};
|
||||
|
||||
#endif //BULLET_ODE_COLLISION_PAIR_H
|
||||
@@ -1,33 +0,0 @@
|
||||
#include "BulletOdeManifoldResult.h"
|
||||
#include "NarrowPhaseCollision/PersistentManifold.h"
|
||||
#include "BulletOdeTransformConvert.h"
|
||||
|
||||
BulletOdeManifoldResult::BulletOdeManifoldResult(dGeomID geom1,dGeomID geom2,PersistentManifold* manifoldPtr)
|
||||
:m_manifoldPtr(manifoldPtr),
|
||||
m_geom1(geom1),
|
||||
m_geom2(geom2)
|
||||
{
|
||||
}
|
||||
|
||||
void BulletOdeManifoldResult::AddContactPoint(const SimdVector3& normalOnBInWorld,const SimdVector3& pointInWorld,float depth)
|
||||
{
|
||||
if (depth > m_manifoldPtr->GetManifoldMargin())
|
||||
return;
|
||||
|
||||
SimdTransform transAInv = GetTransformFromGeom(m_geom1).inverse();
|
||||
SimdTransform transBInv = GetTransformFromGeom(m_geom2).inverse();
|
||||
|
||||
SimdVector3 pointA = pointInWorld + normalOnBInWorld * depth;
|
||||
SimdVector3 localA = transAInv(pointA );
|
||||
SimdVector3 localB = transBInv(pointInWorld);
|
||||
ManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
|
||||
|
||||
int insertIndex = m_manifoldPtr->GetCacheEntry(newPt);
|
||||
if (insertIndex >= 0)
|
||||
{
|
||||
m_manifoldPtr->ReplaceContactPoint(newPt,insertIndex);
|
||||
} else
|
||||
{
|
||||
m_manifoldPtr->AddManifoldPoint(newPt);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BULLET_ODE_MANIFOLD_RESULT_H
|
||||
#define BULLET_ODE_MANIFOLD_RESULT_H
|
||||
|
||||
#include "NarrowPhaseCollision/DiscreteCollisionDetectorInterface.h"
|
||||
class PersistentManifold;
|
||||
#include <ode/common.h>
|
||||
|
||||
class BulletOdeManifoldResult : public DiscreteCollisionDetectorInterface::Result
|
||||
{
|
||||
PersistentManifold* m_manifoldPtr;
|
||||
dGeomID m_geom1;
|
||||
dGeomID m_geom2;
|
||||
|
||||
public:
|
||||
|
||||
BulletOdeManifoldResult(dGeomID geom1,dGeomID geom2,PersistentManifold* manifoldPtr);
|
||||
|
||||
virtual void AddContactPoint(const SimdVector3& normalOnBInWorld,const SimdVector3& pointInWorld,float depth);
|
||||
|
||||
};
|
||||
|
||||
#endif //BULLET_ODE_MANIFOLD_RESULT_H
|
||||
@@ -1,39 +0,0 @@
|
||||
#include "BulletOdeTransformConvert.h"
|
||||
#include "../ode/src/collision_kernel.h"
|
||||
|
||||
SimdTransform GetTransformFromGeom(dGeomID geom)
|
||||
{
|
||||
SimdTransform trans;
|
||||
trans.setIdentity();
|
||||
|
||||
|
||||
const dReal* pos = dGeomGetPosition (geom);// pointer to object's position vector
|
||||
const dReal* rot = dGeomGetRotation (geom);; // pointer to object's rotation matrix, 4*3 format!
|
||||
|
||||
SimdMatrix3x3 orn(rot[0],rot[1],rot[2],
|
||||
rot[4],rot[5],rot[6],
|
||||
rot[8],rot[9],rot[10]);
|
||||
|
||||
trans.setOrigin(SimdVector3(pos[0],pos[1],pos[2]));
|
||||
trans.setBasis(orn);
|
||||
|
||||
return trans;
|
||||
}
|
||||
|
||||
SimdTransform GetTransformFromBody(dBodyID body)
|
||||
{
|
||||
SimdTransform trans;
|
||||
|
||||
const dReal* pos = body->pos;
|
||||
const dReal* rot = body->R;
|
||||
|
||||
SimdMatrix3x3 orn(rot[0],rot[1],rot[2],
|
||||
rot[4],rot[5],rot[6],
|
||||
rot[8],rot[9],rot[10]);
|
||||
|
||||
trans.setOrigin(SimdVector3(pos[0],pos[1],pos[2]));
|
||||
trans.setBasis(orn);
|
||||
|
||||
return trans;
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
#ifndef BULLET_ODE_TRANSFORM_CONVERT_H
|
||||
#define BULLET_ODE_TRANSFORM_CONVERT_H
|
||||
|
||||
#include "SimdTransform.h"
|
||||
#include <ode/common.h>
|
||||
|
||||
SimdTransform GetTransformFromGeom(dGeomID geom);
|
||||
SimdTransform GetTransformFromBody(dBodyID body);
|
||||
|
||||
#endif //BULLET_ODE_TRANSFORM_CONVERT_H
|
||||
@@ -1,70 +0,0 @@
|
||||
|
||||
#include "CollisionShapes/SphereShape.h"
|
||||
#include "CollisionShapes/CylinderShape.h"
|
||||
#include "CollisionShapes/MultiSphereShape.h"//capped cylinder is convex hull of two spheres
|
||||
#include "CollisionShapes/ConvexTriangleCallback.h"
|
||||
#include "CollisionShapes/BoxShape.h"
|
||||
|
||||
//need access to internals to convert...
|
||||
#include <../ode/src/collision_kernel.h>
|
||||
|
||||
|
||||
CollisionShape* CreateShapeFromGeom(dGeomID geom)
|
||||
{
|
||||
CollisionShape* shape = 0;
|
||||
|
||||
switch (geom->type)
|
||||
{
|
||||
case dPlaneClass:
|
||||
break;
|
||||
case dBoxClass:
|
||||
{
|
||||
dVector3 size;
|
||||
dGeomBoxGetLengths (geom,size);
|
||||
SimdVector3 halfExtents(0.5f*size[0],0.5f*size[1],0.5f*size[2]);
|
||||
shape = new BoxShape(halfExtents);
|
||||
break;
|
||||
}
|
||||
case dSphereClass:
|
||||
{
|
||||
dVector3 size;
|
||||
shape = new SphereShape(dGeomSphereGetRadius(geom));
|
||||
break;
|
||||
}
|
||||
case dCylinderClass:
|
||||
{
|
||||
dVector3 size;
|
||||
dGeomBoxGetLengths (geom,size);
|
||||
SimdVector3 boxHalfExtents(size[0],size[0],size[1]);
|
||||
shape = new CylinderShapeZ(boxHalfExtents);
|
||||
break;
|
||||
}
|
||||
case dCCylinderClass:
|
||||
{
|
||||
dReal radius,length;
|
||||
dGeomCCylinderGetParams (geom, &radius, &length);
|
||||
SimdVector3 boxHalfExtents(radius,radius,0.5f*length);
|
||||
int numspheres = 2;
|
||||
SimdVector3 centers[2]={ SimdVector3(0,0,0.5f*length),SimdVector3(0,0,-0.5f*length)};
|
||||
SimdScalar radi[2]={radius,radius};
|
||||
shape = new MultiSphereShape(boxHalfExtents,centers,radi,numspheres);
|
||||
break;
|
||||
}
|
||||
/*case dTriMeshClass:
|
||||
{
|
||||
dxTriMesh* trimesh = (dxTriMesh*) geom;
|
||||
shape = 0;//new BVHTrimeshShape(trimesh);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
default:
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return shape;
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#ifndef GEOM_TO_SHAPE_H
|
||||
#define GEOM_TO_SHAPE_H
|
||||
|
||||
class CollisionShape;
|
||||
|
||||
//need internals to handle dGeomID
|
||||
#include <../ode/src/collision_kernel.h>
|
||||
|
||||
CollisionShape* CreateShapeFromGeom(dGeomID geom);
|
||||
|
||||
#endif //
|
||||
@@ -1,119 +0,0 @@
|
||||
? OPCODE/Debug
|
||||
? OPCODE/Opcode.vcproj
|
||||
? OPCODE/Release
|
||||
? VC6/Debug
|
||||
? VC6/Release
|
||||
? VC6/msvcdefs.def
|
||||
? VC6/ode.ncb
|
||||
? VC6/ode.vcproj
|
||||
? VC6/Samples/BuildLog.htm
|
||||
? VC6/Samples/DrawStuff.vcproj
|
||||
? VC6/Samples/DrawStuff_Debug
|
||||
? VC6/Samples/DrawStuff_Release
|
||||
? VC6/Samples/MakeAllTests.ncb
|
||||
? VC6/Samples/MakeAllTests.sln
|
||||
? VC6/Samples/MakeAllTests.suo
|
||||
? VC6/Samples/MakeAllTests.vcproj
|
||||
? VC6/Samples/Test_BoxStack.vcproj
|
||||
? VC6/Samples/Test_BoxStack_Debug
|
||||
? VC6/Samples/Test_BoxStack_Release
|
||||
? VC6/Samples/Test_Buggy.vcproj
|
||||
? VC6/Samples/Test_Chain1.vcproj
|
||||
? VC6/Samples/Test_Chain2.vcproj
|
||||
? VC6/Samples/Test_Collision.vcproj
|
||||
? VC6/Samples/Test_Friction.vcproj
|
||||
? VC6/Samples/Test_Hinge.vcproj
|
||||
? VC6/Samples/Test_I.vcproj
|
||||
? VC6/Samples/Test_Joints.vcproj
|
||||
? VC6/Samples/Test_MovingTrimesh.vcproj
|
||||
? VC6/Samples/Test_Ode.vcproj
|
||||
? VC6/Samples/Test_Slider.vcproj
|
||||
? VC6/Samples/Test_Space.vcproj
|
||||
? VC6/Samples/Test_Step.vcproj
|
||||
? VC6/Samples/Test_Trimesh.vcproj
|
||||
? VC6/Samples/Test_Trimesh_Debug
|
||||
? VC6/Samples/Test_Trimesh_Release
|
||||
? VC6/Samples/state.dif
|
||||
? include/ode/config.h
|
||||
? ode/test/test_trimesh_convex.cpp
|
||||
? ode/test/text_convex.cpp
|
||||
Index: include/ode/collision.h
|
||||
===================================================================
|
||||
RCS file: /cvsroot/opende/ode/include/ode/collision.h,v
|
||||
retrieving revision 1.9
|
||||
diff -u -r1.9 collision.h
|
||||
--- include/ode/collision.h 19 Jun 2004 15:44:22 -0000 1.9
|
||||
+++ include/ode/collision.h 6 Nov 2005 23:06:52 -0000
|
||||
@@ -84,6 +84,7 @@
|
||||
dRayClass,
|
||||
dGeomTransformClass,
|
||||
dTriMeshClass,
|
||||
+ dConvexClass,
|
||||
|
||||
dFirstSpaceClass,
|
||||
dSimpleSpaceClass = dFirstSpaceClass,
|
||||
Index: ode/src/collision_kernel.cpp
|
||||
===================================================================
|
||||
RCS file: /cvsroot/opende/ode/ode/src/collision_kernel.cpp,v
|
||||
retrieving revision 1.18
|
||||
diff -u -r1.18 collision_kernel.cpp
|
||||
--- ode/src/collision_kernel.cpp 19 Apr 2004 18:27:56 -0000 1.18
|
||||
+++ ode/src/collision_kernel.cpp 6 Nov 2005 23:10:02 -0000
|
||||
@@ -146,6 +146,17 @@
|
||||
setCollider (dTriMeshClass,dTriMeshClass,&dCollideTTL);
|
||||
setCollider (dTriMeshClass,dCCylinderClass,&dCollideCCTL);
|
||||
#endif
|
||||
+
|
||||
+#ifdef BULLET_CONVEX_SUPPORT
|
||||
+ ///see collision_convex.cpp
|
||||
+ setCollider (dConvexClass,dConvexClass,&dCollideConvexConvex);
|
||||
+ setCollider (dConvexClass,dPlaneClass,&dCollideConvexConvex);
|
||||
+ setCollider (dConvexClass,dBoxClass,&dCollideConvexConvex);
|
||||
+ setCollider (dConvexClass,dSphereClass,&dCollideConvexConvex);
|
||||
+ setCollider (dConvexClass,dCCylinderClass,&dCollideConvexConvex);
|
||||
+ setCollider( dTriMeshClass,dConvexClass, dCollideConvexConvex);
|
||||
+#endif //BULLET_CONVEX_SUPPORT
|
||||
+
|
||||
setAllColliders (dGeomTransformClass,&dCollideTransform);
|
||||
}
|
||||
|
||||
Index: ode/src/collision_std.h
|
||||
===================================================================
|
||||
RCS file: /cvsroot/opende/ode/ode/src/collision_std.h,v
|
||||
retrieving revision 1.2
|
||||
diff -u -r1.2 collision_std.h
|
||||
--- ode/src/collision_std.h 1 Dec 2002 06:13:42 -0000 1.2
|
||||
+++ ode/src/collision_std.h 6 Nov 2005 23:03:52 -0000
|
||||
@@ -37,6 +37,7 @@
|
||||
// the same interface as dCollide(). the first and second geom arguments must
|
||||
// have the specified types.
|
||||
|
||||
+
|
||||
int dCollideSphereSphere (dxGeom *o1, dxGeom *o2, int flags,
|
||||
dContactGeom *contact, int skip);
|
||||
int dCollideSphereBox (dxGeom *o1, dxGeom *o2, int flags,
|
||||
@@ -63,6 +64,9 @@
|
||||
int flags, dContactGeom *contact, int skip);
|
||||
int dCollideRayPlane (dxGeom *o1, dxGeom *o2, int flags,
|
||||
dContactGeom *contact, int skip);
|
||||
+///dCollideConvexConvex: see collision_convex.cpp for details
|
||||
+int dCollideConvexConvex(dxGeom *o1, dxGeom *o2, int flags,
|
||||
+ dContactGeom *contact, int skip);
|
||||
|
||||
|
||||
#endif
|
||||
Index: ode/src/collision_trimesh_internal.h
|
||||
===================================================================
|
||||
RCS file: /cvsroot/opende/ode/ode/src/collision_trimesh_internal.h,v
|
||||
retrieving revision 1.10
|
||||
diff -u -r1.10 collision_trimesh_internal.h
|
||||
--- ode/src/collision_trimesh_internal.h 21 Sep 2004 20:54:21 -0000 1.10
|
||||
+++ ode/src/collision_trimesh_internal.h 6 Nov 2005 23:04:52 -0000
|
||||
@@ -25,6 +25,7 @@
|
||||
#ifndef _ODE_COLLISION_TRIMESH_INTERNAL_H_
|
||||
#define _ODE_COLLISION_TRIMESH_INTERNAL_H_
|
||||
|
||||
+int dCollideTrimeshConvex(dxGeom* g1, dxGeom* cnvx, int Flags, dContactGeom* Contacts, int Stride);
|
||||
int dCollideSTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
|
||||
int dCollideBTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
|
||||
int dCollideRTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
|
||||
Binary file not shown.
@@ -1,145 +0,0 @@
|
||||
Release 1.08
|
||||
[ zhang 04-04-06] FXC exports images within <effect>, but ColladaMaya looks for images in <library_images>. Disable the error return in image loading in FCDEffectParameterSurface, and add the dump of images in the FCDEffect.
|
||||
[glaforte 03-04-06] Export and Documentation: Documenting the FCDSceneNode class. Added the FCDTFactory class to easily create and import new transforms. Fixed the parenting of transforms inside scene nodes. Changed the visual scene node<64>s target flag into a target counter, in case there are multiple cameras/lights that target the same visual scene node. Documented the FCDTransform class and all its up-classes.
|
||||
[ aazar 03-04-06] Fixed with Guillaume a curve cloning issue and removed the ownsCurve boolean from FCDAnimated.
|
||||
[ aazar 02-04-06] Fixed a code typo that prevented the loading of some physics scenes.
|
||||
[glaforte 02-04-06] Export and Documentation: Documented the FCDAnimation class and added necessary functions to insert/release/retrieve child elements. Documented/refactored the FCDAnimated base class and its many up-classes. Wrote an automated test procedure for the animation tree export/re-import. Added to this test the creation of an animation curve and placing that animation curve to affect one component of a light color. Added and implemented generic creating functions for the typed animated up-classes: these will be used to add animation curves. To add new animations, I need access to the animatable parameters directly, so I added to cameras, lights, materials and effect parameters accessor that return the float references not as constant. Documented the FCDAnimationChannel class and added the necessary mutators/curve insertion/release functionality. Documented the FCDAnimationCurve class and the FCDAnimationMultiCurve class.
|
||||
[glaforte 02-04-06] Export and Documentation: Documented the FUDaeWriter namespace. Documented the FUCrc32 namespace, the FUDebug and the FUAssert functions, the FUObject and the FUObjectContainer classes.
|
||||
[ aazar 28-04-06] Implemented Guillaume's suggestion for FCDEffectParameterSurfaceInit and created a factory along with clone methods. It might be a good idea to move these guys to a new file though, as FCDEffectParameterSurface.h/cpp are getting crowded.
|
||||
[glaforte 28-04-06] Export and Documentation: Documented the FCDExtra tree class and its technique/node sub-classes, also added the necessary information modifying/pulling and pushing functionality. Wrote an automated test for the export/re-import of a custom <extra> information tree. Documented the FUUniqueStringMapT template and started documenting the FUDaeWriter.h namespace.
|
||||
[ zhang 28-04-06] Added "channels" and "format_hint" COLLADA tokens.
|
||||
[glaforte 28-04-06] Export and Documentation: Documented the FUStringConversion, the FCDEntity, the FCDTargetedEntity classes.
|
||||
[glaforte 25-04-06] Export and Documentation: Added an automated import/re-export test for a simple skin controller with two joints and on top of a mesh. Added one automated import/re-import test for a simple morpher on top of spline. Fixed the export of the skin controller: wrong count on the accessor of the bind-pose source and the wrong source id was used for the influence weight input in the <vertex_weights> element. Added an automated test for the export/re-import of the orthographic camera.
|
||||
[glaforte 25-04-06] Export and Documentation: Documented the FCDEffectParameterSurface class, its initialization method sub-classes, the FCDController class, the FCDSkinController class and the FCDMorphController class. Added the FCDMorphTarget class, as the weight must now be attached to the controller at all times: before, I had a separate STL vector with the weights and on a resize, all the animations would have been lost. Added modifiers/pullers and pushers to these classes. Fixed ColladaMaya, ColladaMax and the viewer for the interface change in the morph controller class.
|
||||
[ aazar 25-04-06] Fixed bug that would cause crash in FCDMaterialInstance if a controller had another controller as a base target. Fixed a bug where the wrong nodes would be sent to the animation linking, preventing correct shading animation. Fixed driven animation by fixing some bugs in FCollada for the driver.
|
||||
[glaforte 25-04-06] Documentation and Export: Documented the FCDEffectParameterSurface class and its initialization method sub-classes. Added modifiers/pullers and pushers to these classes.
|
||||
[glaforte 25-04-06] Fixed the import of the orthographic camera: it always failed as the camera strangely became both orthographic and perspective at the same time.
|
||||
[glaforte 24-04-06] Export and Documentation: Documented the FCDImage class and added new modifiers/pullers/pushers. Modified the automated export/re-import test for the profile COMMON material to include a few textures and added the export/re-import of a few images for these textures. Fixed the export of COLLADA images: the id was missing and the filename was not a valid URL. Documented the FCDEffectParameterFactory class, the FCDEffectParameterList class, the FCDEffectParameter class and most of its derivates: the FCDEffectParameterSurface class is not yet documented. Added modifiers/pullers and pushers to all these classes, as well. Improved the document parsing error reporting by adding the line number on all the warnings/errors reported.
|
||||
[glaforte 22-04-06] Export and Documentation: Documented the FCDTexture class. The FCDEffectStandard class now always owns all its textures, as I added the texture push/pull for this class. It will be easier that way for COLLADA 1.3 backward compatibility: the texture entities are cloned. Documented the FCDEffectPassShader and fixes a few typos and grammar mistakes in the documentation.
|
||||
[glaforte 21-04-06] Export and Documentation: Documented the FCDEffectTechnique class and the FCDEffectPass class. Documented the FCDEffectCode class. Fixed the STL-related doxygen warnings.
|
||||
[ aazar 20-04-06] Added a check for zero-length in FMVector3::NormalizeIt().
|
||||
[glaforte 20-04-06] Export and Documentation: The output file for the export/re-import automated test is starting to contain important information: ran it through a XML validator and fixed the validation issues: quite a few missing <20>sid<69> and <20>url<72> attributes, as well as quite a few required nodes: <20><node> in an empty visual scene<6E>, <20><pass> in an empty effect technique<75>...
|
||||
[glaforte 20-04-06] Export and Documentation: Documented the FCDEffectStandard class and the FCDEffectProfileFX class. Wrote two automated tests for the export and re-import of the CG and COMMON profile materials. Simplified the documentation, removing all the "defines a" and "defines the", to be simply "A" and "The".
|
||||
[glaforte 20-04-06] Export and Documentation: Documented the FCDEffect class. I realized that the FCDEffect class can still hold only one effect profile. Renamed the FCDEffectProfile class into the FCDEffectProfileFX class. Created a new FCDEffectProfile class which is the base class for the FCDEffectProfileFX and the FCDEffectStandard classes. Refactored the FCDEffect class to contain a list of FCDEffectProfile objects. Documented/implemented the FCDEffectProfile class. Updated ColladaMaya, ColladaMax and the Feeling Viewer to use the new effect/profile architecture.
|
||||
[ aazar 19-04-06] Fixed material instancing issue with geometry controllers.
|
||||
[glaforte 17-04-06] Export and Documentation: Started writing the export-import test for the materials/effects classes. Documented the FCDMaterialLibrary and FCDMaterial classes. Removed the ClearDaeIdWithoutTouchingTheUniqueMap function from the FCDObjectWithId class and refactored the import of materials to handle empty materials correctly. This will need to be re-tested with COLLADA 1.3 materials.
|
||||
[glaforte 17-04-06] Export and Documentation: Added Doxygen group for all the math classes. Re-organized the automated export/import test into multiple files and a namespace. Wrote an automated test for the export/import of lights. Fixed the case of the exported light type. Added un-implemented RemoveEntity function to the library. This function will require a lot of extra structure.
|
||||
[glaforte 17-04-06] Documentation: Finished (finally), the documentation of the FCDCamera class. Corrected some doxygen warnings in the polygon set class and the document class.
|
||||
|
||||
Release 1.07
|
||||
[glaforte 13-04-06] FCollada: Corrected a small application-compatibility issue found in ColladaMax.
|
||||
[glaforte 13-04-06] FCollada: Added basic exception handling in non-debug builds and fixed XSI import of animation curve tangents [theirs are 2D points, we use the strange bezier derivate].
|
||||
[ aazar 13-04-06] Fixed overwrite/clone bug in the FCDEffectParameterSurface. Everything works back correctly with shaders. Fixed reading of multiple <init_from> elements. Fixed reading of gravity and timestep in the Collada file. Added angular velocity to physics
|
||||
[ zhang 13-04-06] Traverse the group node and looking for <bind_material> to import light link.
|
||||
[ aazar 12-04-06] Fixed bug in file path reading for FCDEffectCode. This fixed the rendering for a few Cg datasets. Rewrote the FCDEffectParameterSurface class to support the 40,000 new initialization possibilities of a surface.
|
||||
[ zhang 12-04-06] Modified FindNamedAnimated() with string operations.
|
||||
[glaforte 11-04-06] Integration: Integrated the errors found within FCollada by Autodesk's recent changes to ColladaMax.
|
||||
[glaforte 10-04-06] Export and Documentation: Continued writing a simple test scenario for a mesh export/import: added a list of static indices for the vertex positions and colors to export and verify on re-import. Added functions to the mesh polygon set interface to add and remove faces. Since holes and faces are listed together within the face-vertex degree list for a polygon set, added function to access the hole/face information using an iterative index for faces.
|
||||
[glaforte 07-04-06] Export and Documentation: Wrote the export/re-import test for the geometry sources. Fixed a memory hog within the DAE import code. Added a new constructor and an equivalency function for the FloatList class, which is now a class rather than a typedef. Added push/pull function for polygon set inputs as well as some renaming.
|
||||
[glaforte 07-04-06] Export and Documentation: Documented the FCDGeometryPolygons and FCDGeometryPolygonsInput classes. Removed the <20>sourceId?member from the polygon set input class, as it now contains a pointer to the data source. Improved the interface of the geometry polygon set class. Added FMFloat and FMInteger, in order to better classify the information previously contained within FUtils.h. FMath.h now includes all the mathematical classes below it, rather than have FUtils includes them.
|
||||
[glaforte 06-04-06] Export and documentation: Started an export/re-import test for a geometry mesh. Documented the FCDGeometryMesh class at the same time as I added the information pushing functions and improved on the interface of the class. Documented the FCDGeometrySource class. Created a new sub-class: FCDObjectWithId, so that non-entity objects which require a unique id have access to that functionality. Documented the FCDObject and FCDObjectWithId classes. Fixed the export of the geometry source.
|
||||
[glaforte 06-04-06] Export and Documentation: Enabled and fixed the MSVC 64-bit warnings: many integer types went from uint32 to size_t, which is unsigned, or intptr_t, which is signed. LibXML required a lot of work, as there are many 8-bit string substractions to calculate sizes. Removed from LibXML the "trio" classes, which were unused.
|
||||
[ aazar 06-04-06] Fixed bug in FCDEffectParameter concerning 1D, 3D and Cube samplers.
|
||||
|
||||
Release 1.06
|
||||
[glaforte 05-04-06] Zapped a few Doxygen warnings.
|
||||
[glaforte 05-04-06] Documented FUDateTime.h. Documented FUXmlWriter.h.
|
||||
[glaforte 05-04-06] Removed the FPoint and FMatrix typedefs. Everyone should use FMVector3 and FMMatrix44 instead. Documented the FUStatus class and some of the FUtils.h macros. Added FUString.h which includes string-related macros/functions previously found in FUtils.h.
|
||||
[glaforte 05-04-06] Work from two weeks ago: continued the documentation of the FCDCamera class.
|
||||
[glaforte 04-04-06] Bug #38: Debug crash when importing. Reported by Alfred, this issue occurs only when importing a COLLADA document that has some visibility animation. This bug was due to leaking animation curves, when the animation curves for visibility were cloned in FCollada.
|
||||
[ zhang 31-03-06] FCDEffectParameterBool returns boolean value
|
||||
[ aazar 28-03-06] Implemented hack to allow Collada 1.3 materials and effects to load properly with the unique IDs. Simplified the FCDMaterialLibrary::LoadFromXML.
|
||||
[glaforte 27-03-06] Updated the documentation for FCDLibrary and up-ed the version of the FCollada library.
|
||||
|
||||
Internal Release 1.05
|
||||
[glaforte 27-03-06] Export and Documentation: Wrote the documentation for the FCDGeometry class. Added the CreateMesh and CreateSpline functions to the FCDGeometry class, in order to create a new mesh/spline for a new geometry object. Fixed the export of the camera, which was missing the <optics> element. Fixed the re-import of the entity notes: Refactored the extra structure containment. The FCDEntity base class now contains the extra structure. Documented and wrote an import/export test for the FCDGeometrySpline class. Implemented the export of splines. Improved the interface of the FCDGeometrySpline class so that retrieving information for splines is slightly less convoluted.
|
||||
[ aazar 27-03-06] Fixed loading of physics scene since unique names have been implemented. We now load the rigid constraints and bodies correctly from sid instead of id, but looking them up in their physics model.
|
||||
[glaforte 24-03-06] Added a test sequence for the export/import/push of camera information. Started documenting the FCDCamera class.
|
||||
[glaforte 24-03-06] Completed the first draft Doxygeon documentation for the FCDocument class.
|
||||
[ aazar 24-03-06] Completed some WriteToXML functions in physics classes. Fixed some bugs in the analytical geometries.
|
||||
[glaforte 24-03-06] Started the documentation of the FCDocument class and header.
|
||||
[glaforte 23-03-06] More information pushing: of transforms. Some re-organization of the scene node class header with some accessor additions. Initialization of the matrix can now take in a constant list of floats. Added testing of the pushing/export/import of transforms.
|
||||
[ aazar 23-03-06] Adapted FCDImage to read in height, width and depth.
|
||||
[glaforte 23-03-06] Started a full, simple, import-export scene test for visual scenes within FColladaTest. Wrote the push for libraries entities and the scene node transforms/children. Added the unique name map for the entities. Write out default names for all the entities, targeted or otherwise. Fixed a few export issues: empty names and the push of visual scene when there are no roots.
|
||||
[glaforte 23-03-06] Implemented the export of the animation clips. Added accessors for the parent of an animation channel.
|
||||
[ aazar 22-03-06] Fixed rigid constraint angular limit bug.
|
||||
[ aazar 17-03-06] In FCDPhysicsRigidConstraint, added reading in of translation/rotation nodes inside rigid constraint attachment, and fixed a bug in reading interpenetrate node.
|
||||
[glaforte 17-03-06] Added a flushing function to FULogFile.
|
||||
[claforte 16-03-06] Fixed crash when exporting the default sphere in ColladaMaya: due to the string builder not being initialized properly.
|
||||
[ aazar 16-03-06] Initialization and bug fix in FCDPhysicsRigidConstraint.
|
||||
[glaforte 16-03-06] Animation clips don't have Ids when exported from ColladaMaya, right now so work-around them when importing in FCollada.
|
||||
[claforte 15-03-06] Fixed import problems with files loaded from FX Composer 2, that have surfaces with no <init_from> image.
|
||||
[ aazar 15-03-06] Fixed Analytical shape reading from Collada file, and set only one radius per cylinder/capsule. Fixed bug in reading rigid constraints in FCDPhysicsModelInstance. Fixed bugs in reading rigid contraints parameters in FCDPhysicsRigidConstraint. Fixed bug reading in gravity in FCDPhysicsSceneNode.
|
||||
[ aleung 15-03-06] Fixed Maya parameters nodes that were missing in FCDEffectStandard.
|
||||
[glaforte 14-03-06] PS3: Fixed up the strlen within the string builder. Modified the absolute path creation with the FUFileManager.
|
||||
[ aazar 13-03-06] Updated the LoadFromXML functions of the analytical geometries to take into account they have no Id. Added some Get functions to the FCDPhysicsRigidConstraint.
|
||||
[claforte 13-03-06] Port to PS3: Fixed many warnings, e.g. missing newline at the end of include, enums were not using latest C++ spec, etc. Added #ifdefs related to PPU (PowerPC Unit), for stuff OpenGL ES-specific limitations, missing time() function, etc. Fixed bug in FindHierarchyChildBySid. Introduced some abstractions, e.g. fglActiveTexture and fglClientActiveTexture, to simplify support for OpenGL ES. Replaced Configure-generated makefile in PS3 DevIL by a hand-written one. Note that the ported version compiles and runs on the PS3, but nothing shows up due to #ifdef-ed code that needs to be written.
|
||||
[glaforte 13-03-06] Added to FDCSkinController::ReduceInfluences a minimum weight threshold.
|
||||
[ aazar 10-03-06] Mostly all physics-related: Completed the FCollada part for importing.
|
||||
[ aazar 10-03-06] Added cloning support for FCDAnimated, FCDAnimationClip and FCDAnimationCurve objects.
|
||||
[ aazar 10-03-06] Added SetClassName in FUObject so that classes can better identify themselves.
|
||||
[ aazar 10-03-06] Corrected a suspected bug in material and effect flattening.
|
||||
[ aazar 10-03-06] Fixed bug in creation of FCDPhysicsRigidConstraintInstance where it would try to compare the parent's type to the wrong one.
|
||||
[glaforte 08-03-06] Added a unique name map that somewhat generates unique names. Added whether the FMath classes are used within FCollada to the doxygen documentation. Some improvements on the FCollada test project.
|
||||
|
||||
Release 1.04
|
||||
[ aleung 06-03-06] Fixed up the Doxygen script for an improved main page template, files, global functions and completed the documentation of the FMath classes.
|
||||
[ aleung 03-03-06] Wrote an initial doxygen script. Started documenting the FMath classes for Doxygen.
|
||||
[glaforte 02-03-06] Planned the refactoring of the animation classes in order to support import/export/push/pull correctly. Added to the FCDAnimationCurve all the information necessary for it to do its own import/export. Similarly for FCDAnimationMultiCurve. When registering the animated values for export, just write out the targets to the curves. Implemented the recursive export of the animation trees.
|
||||
[glaforte 02-03-06] Fixed memory overwrite within the FUStringBuilder template class.
|
||||
[ zhang 28-02-06] Correct the float parameter min/max parsing.
|
||||
[glaforte 27-02-06] Removed the Maya-Max type references from FCollada. Fixed the compilation errors in FUtils.
|
||||
[glaforte 25-02-06] Added FUAssert and included Blinn shading on a few levels.
|
||||
[glaforte 23-02-06] Fixed-up the STL #includes, in an attempt to fix the FCollada DLL.
|
||||
[glaforte 23-02-06] 06-003-07: Fixed the loading of this skin test case, coming from COLLADA 1.3: the geometry cloning was not working when overriding the position-source.
|
||||
[glaforte 23-02-06] ColladaMaya Fixes: Fixed the morph target input types. Fixed the array export types to be IDREF_arrays as well as their accessor parameter types to be IDREF. Fixed the import of the animation drivers: the input driver target processing was not correctly.
|
||||
[ aleung 22-02-06] Performance: performance boost by reserving all the memory at once for the tessellations.
|
||||
[ aazar 21-02-06] Physics: Completed FCDPhysicsShape and FCDAnalyticalGeometry, added FCDPhysicsScene class separate from FCDScene. Fixed many parsing bugs (mostly related to the order of parsing and instantiation) and some crashes related to incomplete destructors. It is now possible to load physics scenes and the FCD classes will read in correctly all the physics information.
|
||||
[ aazar 21-02-06] Physics: Created the FCDPhysicsRigidConstraintInstance class. Completed the LoadXML for the FCDPhysicsRigidConstraint class.
|
||||
[glaforte 21-02-06] Importer: Fixed the scene node animation import sampling.
|
||||
[ aazar 20-02-06] Physics: Added lots of stuff for 1.4 Physics support. Some nodes are not complete yet, so don't try importing physics datasets as it will probably crash. The main nodes that need more work are the FCDPhysicsShape and the FCDPhysicsAnalyticalGeometry (need to derive classes for sphere, box, capsule, etc).
|
||||
[ aazar 20-02-06] Physics: The other change worth mentioning is a slight modification in the ToFloat functions of the FUStringConversion, to check for infinity. That's a sensitive function and if something goes wrong, the whole rendering gets screwed up.
|
||||
[glaforte 19-02-06] Light/Camera Export: Added and implemented the WriteToXML for the FCDlight and FCDCamera classes, writing out all the different supported light/camera types and the extra parameters for both Max and Maya, with their animations.
|
||||
|
||||
Release 1.03
|
||||
[glaforte 15-02-06] Fixed the matrix flattening of scene nodes.
|
||||
[glaforte 15-02-06] Fixed the import of scene node's notes/user-properties.
|
||||
[glaforte 14-02-06] Standard Material Export: Wrote the export of the standard material texture and its animated placement/projection parameters.
|
||||
[glaforte 13-02-06] Standard Material Export: Implemented the export of the standard material<61>s parameters and texture lists. Split the export function into four functions that export either the textures belong to the correct texture channel(s) as a standard material parameter, or the <color>/<float> element with its animation, if there is one.
|
||||
[glaforte 11-02-06] Controller Export: Added and implemented the WriteToXML to the FCDController, FCDMorphController and FCDSkinController classes. Added morph method string conversion. Implemented the export of IDRef arrays and sources. Corrected the missing id/name for the <geometry> element export. Corrected the extra ??in the morph target source. Corrected the <20>float?parameter type used too often in accessors.
|
||||
[glaforte 10-02-06] Fixed the ordering of the cloning, so that the FCDEffectCode objects are always cloned before the passes.
|
||||
[glaforte 09-02-06] Material Export: Split the FCDEffectPass class into itself and the FCDEffectPassShader class, which will hold all custom shader information, instead of assuming there are exactly one vertex and one fragment shader. Implemented the XML export of the FCDEffectPass and the FCDEffectPassShader classes. Created the FCDEffectCode class to hold both <include> and <code> ColladaFX element values. Corrected the <shader><name> element to read in the contents as the name and to use the <20>source?attribute for name-matching with the <include>/<code> elements.
|
||||
[glaforte 08-02-06] Instantiation Export: Added the basic WriteToXML functionality to the effects/materials and the instances.
|
||||
[glaforte 08-02-06] Fixed memory-related crash within the effect parameter release.
|
||||
[ aleung 08-02-06] Fixed compilation error in FCDMorphController.
|
||||
[glaforte 08-02-06] Instantiation Refactoring: Added the parsing of the <20>platform?attribute for ColladaFX profiles. Refactored the material instance class to hold the simple bind information as well. Added material <20>flattening?to the material instance class, so that viewers can assume only ColladaFX techniques hold parameters. The parameter values are trickled down by matching references. All the <newparam> parameters are trickled down, while the <setparam> parameters overwrite the <newparam> parameters below. Implemented the WriteToXML functions for the effect, the effect profile and the effect technique classes. Added the parsing of the <technique_hint> elements at the material level.
|
||||
[glaforte 08-02-06] Instantiation Refactoring: Added FCDEffectParameterList class, based on the std:vector of parameters, adding a parameter lookup-by-name function. Refactored the FCDEffectParameter to not be tied to a <20>pass?object, as a parent. The parameters now use their own reference string for error-reporting. Added a parameter list at the material, effect, profile and technique levels. Refactored the <20>pass?to hold simple bind information, rather than all the parameters.
|
||||
[glaforte 08-02-06] Instantiation Refactoring: In order to support correctly the export of geometry/controller instances, some refactoring is necessary, with respect to material parameters and their binding. The plan is to move from flattening materials on import to flattening materials on-demand, keeping the parameter override information around so that it can be modified and exported correctly.
|
||||
[glaforte 07-02-06] Animation Export: Remove empty animation libraries.
|
||||
[ aazar 07-02-06] Fixed a crash when releasing FCDocument, due to non-virtual destructors and missing memory deallocations.
|
||||
[glaforte 07-02-06] Animation Export: Implemented XML export functions for the basic animation curve: splitting the export of the sources, samplers and channels, in order to keep the <animation> element enforced ordering. Wrote the XML export functions for the merged animation curve, with a custom stride and multiple accessor parameters. Implemented the export of animated translations and rotations. Tested with a simple, animated DAE file. Found/Investigated memory corruption crash: was due to wrong include being added to the tools?project. Corrected id-generation for the animation sources, the export of float arrays.
|
||||
[glaforte 07-02-06] Animation Export: New feature: when generating a <20>sid? look for uniqueness, within the scope. Use an incremental counter appended to the wanted <20>sid?value, in order to generate unique sids. Fixed duplicated VERTEX geometry input, found within my current test case. Added the animation export to the other transformation elements.
|
||||
[glaforte 06-02-06] Animation Export: Plan out the export of animation curves, animated values and animation clips, for FCollada. Implemented the cleaning-up of name and id string values, in order to strip them of the invalid characters, on export. Save the node for the animation library in the FCDocument object. Added a function to export the animated value, if it has curves attached to it. Added and Implemented WriteToXML function for the animated value: check for curve merging, and then export either the merged curve or the individual curves.
|
||||
[glaforte 05-02-06] DLL Project: Some refactoring related to the usage of int8. Added functions to FUFileManager for relative/absolute/url filenames.
|
||||
[glaforte 05-02-06] Material Export: The material library now exports effects for ColladaFX profiles and the standard profile, as well as materials with instantiated effects. The image library now exports file images correctly.
|
||||
[claforte 03-02-06] Modified definitions used in ColladaMaya physics export: <limits> instead of <limit>, <ref_attachment>.
|
||||
[glaforte 03-02-06] Geometry Export/Refactoring: Added WriteToXML functions at the relevant levels. Split the FCDGeometry class into the spline and mesh components. This modifies the API for the FCollada: merge in the changes within the viewer.
|
||||
[glaforte 03-02-06] Import/Export of Asset tag: Added FCDAsset and FCDAssetContributor elements. Added FUDateTime class and its string parsing mechanism: mostly for the UTC times in the asset tags.
|
||||
|
||||
Release 1.02
|
||||
[glaforte 02-02-06] Some corrections of warnings/errors for MacOSX and GCC.
|
||||
[glaforte 01-02-06] Refactored the FUStringConversion header to have more inlined functions and reverted the changes on the ToFloat, ToUInt and ToInt functions to use our own parsing functions, as they were much faster than fstrtoX.
|
||||
[glaforte 31-01-06] FCollada Extra Tree: Added and Implemented FCDExtra, FCDETechnique and FCDENode classes. Added an FCDExtra object to the scene node.
|
||||
[glaforte 31-01-06] FCollada Extra Tree and Animations: Added FCDAnimatedCustom class that contains animation curves of any sizes and their float* targets directly. Refactored the animation system to link animations right away, resulting in a much smaller FCDAnimated object count. FCDENode contains an FCDAnimatedCustom object. Modified the scene node object to parse and extra the Max and Maya-specific parameters and their animations directly from the extra tree.
|
||||
[ aazar 31-01-06] Created FCDEffectTechnique class to support multiple techniques in ColladaFX. FCDEffectProfile now has a list of FCDEffectTechnique, which has a list of FCDEffectPass, which has a list of FCDEffectParameters.
|
||||
[glaforte 30-01-06] Added to FCDocument the export functions: WriteToFile and WriteDocumentToXML(). I'll be propagating these over the other FCDx classes.
|
||||
[glaforte 30-01-06] Added writing utility namespaces: FUXmlWriter and FUDaeWriter. Ported ColladaMaya's XML writing functions over to the FUXmlWriter, but FUDaeWriter is still empty.
|
||||
[glaforte 30-01-06] Added to FCDLibrary, FCDEntity and FCDSceneNode some basic writing functionality.
|
||||
[glaforte 30-01-06] Made all the write to XML functions const.
|
||||
[glaforte 30-01-06] Added ToString functions for FPoint and FMatrix, with length conversion.
|
||||
[glaforte 30-01-06] Added to FCDTransform and its derivates, XML writing functions.
|
||||
|
||||
Release 1.01
|
||||
[glaforte 30-01-06] First official version: includes all the modifications to the FS import classes made for the different projects,
|
||||
[glaforte 30-01-06] up to now. Added DLL support and unicode support to the project(s).
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
You can get more information and the latest versions of the FCollada library
|
||||
on our website.
|
||||
|
||||
Feel free to drop us an email if you want more information on using the library.
|
||||
|
||||
Guillaume Laforte
|
||||
glaforte@feelingsoftware.com
|
||||
|
||||
Feeling Software Inc.
|
||||
http://www.feelingsoftware.com
|
||||
|
||||
|
||||
Copyright and License information:
|
||||
------------------------------------
|
||||
|
||||
|
||||
FCollada:
|
||||
----------
|
||||
Copyright 2006 Feeling Software.
|
||||
Under MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
|
||||
FS import classes:
|
||||
-----------------------
|
||||
Copyright 2005-2006 Feeling Software and
|
||||
Copyright 2005-2006 Autodesk Media Entertainment.
|
||||
Under MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
|
||||
LibXML2:
|
||||
---------
|
||||
Except where otherwise noted in the source code (e.g. the files
|
||||
hash.c,
|
||||
list.c and the trio files, which are covered by a similar
|
||||
licence but
|
||||
with different Copyright notices) all the files are:
|
||||
|
||||
|
||||
|
||||
Copyright (C) 1998-2003 Daniel Veillard. All Rights Reserved.
|
||||
|
||||
|
||||
Permission is hereby granted, free of charge,
|
||||
to any person obtaining a copy
|
||||
of this software and associated documentation
|
||||
files (the "Software"), to deal
|
||||
in the Software without restriction, including
|
||||
without limitation the rights
|
||||
to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell
|
||||
copies of the Software, and to
|
||||
permit persons to whom the Software is fur-
|
||||
nished to do so, subject
|
||||
to the following conditions:
|
||||
|
||||
The above copyright notice and this
|
||||
permission notice shall be included in
|
||||
all copies or substantial
|
||||
portions of the Software.
|
||||
|
||||
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FIT-
|
||||
NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE
|
||||
DANIEL VEILLARD BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
|
||||
NECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
|
||||
Except as contained in this notice, the name of Daniel
|
||||
Veillard shall not
|
||||
be used in advertising or otherwise to
|
||||
promote the sale, use or other deal-
|
||||
ings in this Software
|
||||
without prior written authorization from him.
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
HINSTANCE hInstance = NULL;
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE _hInstance, ULONG UNUSED(fdwReason), LPVOID UNUSED(lpvReserved))
|
||||
{
|
||||
hInstance = _hInstance;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
namespace FCollada
|
||||
{
|
||||
FCOLLADA_EXPORT unsigned long GetVersion() { return FCOLLADA_VERSION; }
|
||||
};
|
||||
|
||||
#include "FMath/FMColor.h"
|
||||
#include "FUtils/FUDebug.h"
|
||||
#include "FUtils/FULogFile.h"
|
||||
|
||||
// Trick the linker so that it adds the functionalities of the classes that are not used internally.
|
||||
FCOLLADA_EXPORT void TrickLinker()
|
||||
{
|
||||
// FMColor
|
||||
FMColor* color = NULL;
|
||||
float* f = NULL;
|
||||
color->ToFloats(f, 4);
|
||||
|
||||
// FULogFile
|
||||
FULogFile* logFile = NULL;
|
||||
logFile->WriteLine("Test");
|
||||
|
||||
// FUDebug
|
||||
DebugOut("Tricking Linker...");
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,544 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDAnimationChannel.h"
|
||||
#include "FCDocument/FCDAnimationCurve.h"
|
||||
#include "FCDocument/FCDAnimationMultiCurve.h"
|
||||
#include "FCDocument/FCDAnimated.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDAnimated::FCDAnimated(FCDocument* document, size_t valueCount) : FCDObject(document, "FCDAnimated")
|
||||
{
|
||||
arrayElement = -1;
|
||||
|
||||
// Allocate the values/qualifiers/curves arrays
|
||||
values.resize(valueCount, NULL);
|
||||
qualifiers.resize(valueCount, "");
|
||||
curves.resize(valueCount, NULL);
|
||||
}
|
||||
|
||||
FCDAnimated::~FCDAnimated()
|
||||
{
|
||||
values.clear();
|
||||
qualifiers.clear();
|
||||
curves.clear();
|
||||
}
|
||||
|
||||
// Assigns a curve to a value of the animated element.
|
||||
bool FCDAnimated::SetCurve(size_t index, FCDAnimationCurve* curve)
|
||||
{
|
||||
FUAssert(index < GetValueCount(), return false);
|
||||
curves.at(index) = curve;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Removes the curve affecting a value of the animated element.
|
||||
bool FCDAnimated::RemoveCurve(size_t index)
|
||||
{
|
||||
FUAssert(index < GetValueCount(), return false);
|
||||
bool hasCurve = curves[index] != NULL;
|
||||
curves[index] = NULL;
|
||||
return hasCurve;
|
||||
}
|
||||
|
||||
bool FCDAnimated::Link(xmlNode* node)
|
||||
{
|
||||
bool linked = false;
|
||||
|
||||
if (node != NULL)
|
||||
{
|
||||
// Write down the expected target string for the given node
|
||||
FUDaeParser::CalculateNodeTargetPointer(node, pointer);
|
||||
|
||||
// Check if this animated value is used as a driver
|
||||
linked |= GetDocument()->LinkDriver(this);
|
||||
|
||||
// Retrieve the list of the channels pointing to this node
|
||||
FCDAnimationChannelList channels;
|
||||
GetDocument()->FindAnimationChannels(pointer, channels);
|
||||
linked |= ProcessChannels(channels);
|
||||
}
|
||||
else linked = true;
|
||||
|
||||
if (linked)
|
||||
{
|
||||
// Register this animated value with the document
|
||||
GetDocument()->RegisterAnimatedValue(this);
|
||||
}
|
||||
|
||||
return linked;
|
||||
}
|
||||
|
||||
bool FCDAnimated::ProcessChannels(FCDAnimationChannelList& channels)
|
||||
{
|
||||
bool linked = false;
|
||||
for (FCDAnimationChannelList::iterator it = channels.begin(); it != channels.end(); ++it)
|
||||
{
|
||||
FCDAnimationChannel* channel = *it;
|
||||
const FCDAnimationCurveList& channelCurves = channel->GetCurves();
|
||||
if (channelCurves.empty()) continue;
|
||||
|
||||
// Retrieve the channel's qualifier and check for a requested matrix element
|
||||
string qualifier = channel->GetTargetQualifier();
|
||||
if (arrayElement != -1)
|
||||
{
|
||||
int32 element = ReadTargetMatrixElement(qualifier);
|
||||
if (arrayElement != element) continue;
|
||||
}
|
||||
|
||||
if (qualifier.empty())
|
||||
{
|
||||
// An empty qualifier implies that the channel should provide ALL the curves
|
||||
for (size_t i = 0; i < channelCurves.size() && i < curves.size(); ++i)
|
||||
{
|
||||
curves[i] = channelCurves[i];
|
||||
linked = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Attempt to match the qualifier with this animated qualifiers
|
||||
size_t index;
|
||||
for (index = 0; index < qualifiers.size(); ++index)
|
||||
{
|
||||
if (qualifiers[index] == qualifier) break;
|
||||
}
|
||||
|
||||
// Check for a matrix element instead
|
||||
if (index == qualifiers.size()) index = ReadTargetMatrixElement(qualifier);
|
||||
if (index < qualifiers.size())
|
||||
{
|
||||
curves[index] = channelCurves.front();
|
||||
linked = true;
|
||||
}
|
||||
/* else return status.Fail(FS("Invalid qualifier for animation channel target: ") + TO_FSTRING(pointer)); */
|
||||
}
|
||||
}
|
||||
|
||||
if (linked)
|
||||
{
|
||||
// Now that the curves are imported: set their target information
|
||||
for (size_t i = 0; i < curves.size(); ++i)
|
||||
{
|
||||
if (curves[i] != NULL)
|
||||
{
|
||||
curves[i]->SetTargetElement(arrayElement);
|
||||
curves[i]->SetTargetQualifier(qualifiers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return linked;
|
||||
}
|
||||
|
||||
const string& FCDAnimated::GetQualifier(size_t index) const
|
||||
{
|
||||
FUAssert(index < GetValueCount(), return emptyString);
|
||||
return qualifiers.at(index);
|
||||
}
|
||||
|
||||
// Retrieves an animated value, given a valid qualifier
|
||||
float* FCDAnimated::FindValue(const string& qualifier)
|
||||
{
|
||||
for (size_t i = 0; i < qualifiers.size(); ++i)
|
||||
{
|
||||
if (qualifiers[i] == qualifier) return values[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
const float* FCDAnimated::FindValue(const string& qualifier) const
|
||||
{
|
||||
for (size_t i = 0; i < qualifiers.size(); ++i)
|
||||
{
|
||||
if (qualifiers[i] == qualifier) return values[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Retrieve the index of a given qualifier
|
||||
size_t FCDAnimated::FindQualifier(const char* qualifier) const
|
||||
{
|
||||
for (size_t i = 0; i < qualifiers.size(); ++i)
|
||||
{
|
||||
if (qualifiers[i] == qualifier) return i;
|
||||
}
|
||||
|
||||
// Otherwise, check for a matrix element
|
||||
string q = qualifier;
|
||||
int32 matrixElement = FUDaeParser::ReadTargetMatrixElement(q);
|
||||
if (matrixElement >= 0 && matrixElement < (int32) qualifiers.size()) return matrixElement;
|
||||
return size_t(-1);
|
||||
}
|
||||
|
||||
// Retrieve the index of a given value pointer
|
||||
size_t FCDAnimated::FindValue(const float* value) const
|
||||
{
|
||||
for (size_t i = 0; i < values.size(); ++i)
|
||||
{
|
||||
if (values[i] == value) return i;
|
||||
}
|
||||
return size_t(-1);
|
||||
}
|
||||
|
||||
// Returns whether any of the contained curves are non-NULL
|
||||
bool FCDAnimated::HasCurve() const
|
||||
{
|
||||
FCDAnimationCurveList::const_iterator cit;
|
||||
for (cit = curves.begin(); cit != curves.end() && (*cit) == NULL; ++cit) {}
|
||||
return cit != curves.end();
|
||||
}
|
||||
|
||||
// Create one multi-curve out of this animated value's single curves
|
||||
FCDAnimationMultiCurve* FCDAnimated::CreateMultiCurve() const
|
||||
{
|
||||
FloatList defaultValues;
|
||||
size_t count = values.size();
|
||||
defaultValues.resize(count);
|
||||
for (size_t i = 0; i < count; ++i) defaultValues[i] = (*values[i]);
|
||||
|
||||
vector<const FCDAnimationCurve*> toMerge;
|
||||
toMerge.resize(count);
|
||||
for (size_t i = 0; i < count; ++i) toMerge[i] = curves[i];
|
||||
return FCDAnimationMultiCurve::MergeCurves(toMerge, defaultValues);
|
||||
}
|
||||
|
||||
// Create one multi-curve out of the single curves from many FCDAnimated objects
|
||||
FCDAnimationMultiCurve* FCDAnimated::CreateMultiCurve(const FCDAnimatedList& toMerge)
|
||||
{
|
||||
// Calculate the total dimension of the curve to create
|
||||
size_t count = 0;
|
||||
for (FCDAnimatedList::const_iterator cit = toMerge.begin(); cit != toMerge.end(); ++cit)
|
||||
{
|
||||
count += (*cit)->GetValueCount();
|
||||
}
|
||||
|
||||
// Generate the list of default values and the list of curves
|
||||
FloatList defaultValues(count, 0.0f);
|
||||
vector<const FCDAnimationCurve*> curves(count, NULL);
|
||||
size_t offset = 0;
|
||||
for (FCDAnimatedList::const_iterator cit = toMerge.begin(); cit != toMerge.end(); ++cit)
|
||||
{
|
||||
size_t localCount = (*cit)->GetValueCount();
|
||||
for (size_t i = 0; i < localCount; ++i)
|
||||
{
|
||||
defaultValues[offset + i] = *(*cit)->GetValue(i);
|
||||
curves[offset + i] = (*cit)->GetCurve(i);
|
||||
}
|
||||
offset += localCount;
|
||||
}
|
||||
|
||||
return FCDAnimationMultiCurve::MergeCurves(curves, defaultValues);
|
||||
}
|
||||
|
||||
// Sample the animated values for a given time
|
||||
void FCDAnimated::Evaluate(float time)
|
||||
{
|
||||
size_t valueCount = values.size();
|
||||
size_t curveCount = curves.size();
|
||||
size_t count = min(curveCount, valueCount);
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
// Retrieve the curve and the corresponding value
|
||||
FCDAnimationCurve* curve = curves[i];
|
||||
if (curve == NULL) continue;
|
||||
float* value = values[i];
|
||||
if (value == NULL) continue;
|
||||
|
||||
// Evaluate the curve at this time
|
||||
(*value) = curve->Evaluate(time);
|
||||
}
|
||||
}
|
||||
|
||||
FCDAnimated* FCDAnimated::Clone(FCDocument* document)
|
||||
{
|
||||
FCDAnimated* clone = new FCDAnimated(document, GetValueCount());
|
||||
clone->arrayElement = arrayElement;
|
||||
for(size_t i = 0; i < curves.size(); ++i)
|
||||
{
|
||||
clone->curves[i] = curves[i]->Clone();
|
||||
}
|
||||
clone->pointer = pointer;
|
||||
clone->qualifiers = qualifiers;
|
||||
clone->values = values;
|
||||
document->RegisterAnimatedValue(clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
// Clones the whole animated associated with a given value.
|
||||
FCDAnimated* FCDAnimated::Clone(FCDocument* document, const float* animatedValue, FloatPtrList& newAnimatedValues)
|
||||
{
|
||||
const FCDAnimated* toClone = document->FindAnimatedValue(animatedValue);
|
||||
if (toClone == NULL) return NULL;
|
||||
|
||||
FCDAnimated* clone = new FCDAnimated(document, toClone->GetValueCount());
|
||||
clone->arrayElement = toClone->arrayElement;
|
||||
for(size_t i = 0; i < toClone->curves.size(); ++i)
|
||||
{
|
||||
clone->curves[i] = toClone->curves[i];
|
||||
}
|
||||
|
||||
clone->pointer = toClone->pointer;
|
||||
clone->qualifiers = toClone->qualifiers;
|
||||
clone->values = newAnimatedValues;
|
||||
document->RegisterAnimatedValue(clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
FCDAnimatedFloat::FCDAnimatedFloat(FCDocument* document, float* value, int32 _arrayElement) : FCDAnimated(document, 1)
|
||||
{
|
||||
values[0] = value;
|
||||
qualifiers[0] = "";
|
||||
arrayElement = _arrayElement;
|
||||
}
|
||||
|
||||
FCDAnimatedFloat* FCDAnimatedFloat::Create(FCDocument* document, float* value, int32 arrayElement)
|
||||
{
|
||||
FCDAnimatedFloat* animated = new FCDAnimatedFloat(document, value, arrayElement);
|
||||
if (!animated->Link(NULL)) SAFE_DELETE(animated);
|
||||
return animated;
|
||||
}
|
||||
FCDAnimatedFloat* FCDAnimatedFloat::Create(FCDocument* document, xmlNode* node, float* value, int32 arrayElement)
|
||||
{
|
||||
FCDAnimatedFloat* animated = new FCDAnimatedFloat(document, value, arrayElement);
|
||||
if (!animated->Link(node)) SAFE_DELETE(animated);
|
||||
return animated;
|
||||
}
|
||||
|
||||
FCDAnimated* FCDAnimatedFloat::Clone(FCDocument* document, const float* oldValue, float* newValue)
|
||||
{
|
||||
FloatPtrList newValues;
|
||||
newValues.push_back(newValue);
|
||||
return FCDAnimated::Clone(document, oldValue, newValues);
|
||||
}
|
||||
|
||||
FCDAnimatedPoint3::FCDAnimatedPoint3(FCDocument* document, FMVector3* value, int32 _arrayElement) : FCDAnimated(document, 3)
|
||||
{
|
||||
values[0] = &value->x; values[1] = &value->y; values[2] = &value->z;
|
||||
qualifiers[0] = ".X"; qualifiers[1] = ".Y"; qualifiers[2] = ".Z";
|
||||
arrayElement = _arrayElement;
|
||||
}
|
||||
|
||||
FCDAnimatedPoint3* FCDAnimatedPoint3::Create(FCDocument* document, FMVector3* value, int32 arrayElement)
|
||||
{
|
||||
FCDAnimatedPoint3* animated = new FCDAnimatedPoint3(document, value, arrayElement);
|
||||
if (!animated->Link(NULL)) SAFE_DELETE(animated);
|
||||
return animated;
|
||||
}
|
||||
FCDAnimatedPoint3* FCDAnimatedPoint3::Create(FCDocument* document, xmlNode* node, FMVector3* value, int32 arrayElement)
|
||||
{
|
||||
FCDAnimatedPoint3* animated = new FCDAnimatedPoint3(document, value, arrayElement);
|
||||
if (!animated->Link(node)) SAFE_DELETE(animated);
|
||||
return animated;
|
||||
}
|
||||
|
||||
FCDAnimated* FCDAnimatedPoint3::Clone(FCDocument* document, const FMVector3* oldValue, FMVector3* newValue)
|
||||
{
|
||||
FloatPtrList newValues;
|
||||
newValues.push_back(&newValue->x); newValues.push_back(&newValue->y); newValues.push_back(&newValue->z);
|
||||
return FCDAnimated::Clone(document, &oldValue->x, newValues);
|
||||
}
|
||||
|
||||
FCDAnimatedColor::FCDAnimatedColor(FCDocument* document, FMVector3* value, int32 _arrayElement) : FCDAnimated(document, 3)
|
||||
{
|
||||
values[0] = &value->x; values[1] = &value->y; values[2] = &value->z;
|
||||
qualifiers[0] = ".R"; qualifiers[1] = ".G"; qualifiers[2] = ".B";
|
||||
arrayElement = _arrayElement;
|
||||
}
|
||||
|
||||
FCDAnimatedColor* FCDAnimatedColor::Create(FCDocument* document, FMVector3* value, int32 arrayElement)
|
||||
{
|
||||
FCDAnimatedColor* animated = new FCDAnimatedColor(document, value, arrayElement);
|
||||
if (!animated->Link(NULL)) SAFE_DELETE(animated);
|
||||
return animated;
|
||||
}
|
||||
FCDAnimatedColor* FCDAnimatedColor::Create(FCDocument* document, xmlNode* node, FMVector3* value, int32 arrayElement)
|
||||
{
|
||||
FCDAnimatedColor* animated = new FCDAnimatedColor(document, value, arrayElement);
|
||||
if (!animated->Link(node)) SAFE_DELETE(animated);
|
||||
return animated;
|
||||
}
|
||||
|
||||
FCDAnimated* FCDAnimatedColor::Clone(FCDocument* document, const FMVector3* oldValue, FMVector3* newValue)
|
||||
{
|
||||
FloatPtrList newValues; newValues.push_back(&newValue->x); newValues.push_back(&newValue->y); newValues.push_back(&newValue->z);
|
||||
return FCDAnimated::Clone(document, &oldValue->x, newValues);
|
||||
}
|
||||
|
||||
FCDAnimatedAngle::FCDAnimatedAngle(FCDocument* document, float* value, int32 _arrayElement) : FCDAnimated(document, 1)
|
||||
{
|
||||
values[0] = value;
|
||||
qualifiers[0] = ".ANGLE";
|
||||
arrayElement = _arrayElement;
|
||||
}
|
||||
|
||||
FCDAnimatedAngle* FCDAnimatedAngle::Create(FCDocument* document, float* value, int32 arrayElement)
|
||||
{
|
||||
FCDAnimatedAngle* animated = new FCDAnimatedAngle(document, value, arrayElement);
|
||||
if (!animated->Link(NULL)) SAFE_DELETE(animated);
|
||||
return animated;
|
||||
}
|
||||
FCDAnimatedAngle* FCDAnimatedAngle::Create(FCDocument* document, xmlNode* node, float* value, int32 arrayElement)
|
||||
{
|
||||
FCDAnimatedAngle* animated = new FCDAnimatedAngle(document, value, arrayElement);
|
||||
if (!animated->Link(node)) SAFE_DELETE(animated);
|
||||
return animated;
|
||||
}
|
||||
|
||||
FCDAnimated* FCDAnimatedAngle::Clone(FCDocument* document, const float* oldValue, float* newValue)
|
||||
{
|
||||
FloatPtrList newValues;
|
||||
newValues.push_back(newValue);
|
||||
return FCDAnimated::Clone(document, oldValue, newValues);
|
||||
}
|
||||
|
||||
FCDAnimatedAngleAxis::FCDAnimatedAngleAxis(FCDocument* document, FMVector3* axis, float* angle, int32 _arrayElement) : FCDAnimated(document, 4)
|
||||
{
|
||||
values[0] = &axis->x; values[1] = &axis->y; values[2] = &axis->z; values[3] = angle;
|
||||
qualifiers[0] = ".X"; qualifiers[1] = ".Y"; qualifiers[2] = ".Z"; qualifiers[3] = ".ANGLE";
|
||||
arrayElement = _arrayElement;
|
||||
}
|
||||
|
||||
FCDAnimatedAngleAxis* FCDAnimatedAngleAxis::Create(FCDocument* document, FMVector3* axis, float* angle, int32 arrayElement)
|
||||
{
|
||||
FCDAnimatedAngleAxis* animated = new FCDAnimatedAngleAxis(document, axis, angle, arrayElement);
|
||||
if (!animated->Link(NULL)) SAFE_DELETE(animated);
|
||||
return animated;
|
||||
}
|
||||
FCDAnimatedAngleAxis* FCDAnimatedAngleAxis::Create(FCDocument* document, xmlNode* node, FMVector3* axis, float* angle, int32 arrayElement)
|
||||
{
|
||||
FCDAnimatedAngleAxis* animated = new FCDAnimatedAngleAxis(document, axis, angle, arrayElement);
|
||||
if (!animated->Link(node)) SAFE_DELETE(animated);
|
||||
return animated;
|
||||
}
|
||||
|
||||
FCDAnimated* FCDAnimatedAngleAxis::Clone(FCDocument* document, const float* oldAngle, FMVector3* newAxis, float* newAngle)
|
||||
{
|
||||
FloatPtrList newValues;
|
||||
newValues.push_back(&newAxis->x); newValues.push_back(&newAxis->y); newValues.push_back(&newAxis->z);
|
||||
newValues.push_back(newAngle);
|
||||
return FCDAnimated::Clone(document, oldAngle, newValues);
|
||||
}
|
||||
|
||||
FCDAnimatedMatrix::FCDAnimatedMatrix(FCDocument* document, FMMatrix44* value, int32 _arrayElement) : FCDAnimated(document, 16)
|
||||
{
|
||||
arrayElement = _arrayElement;
|
||||
|
||||
#define MX_V(a,b) values[b*4+a] = (&(*value)[a][b])
|
||||
MX_V(0,0); MX_V(1,0); MX_V(2,0); MX_V(3,0);
|
||||
MX_V(0,1); MX_V(1,1); MX_V(2,1); MX_V(3,1);
|
||||
MX_V(0,2); MX_V(1,2); MX_V(2,2); MX_V(3,2);
|
||||
MX_V(0,3); MX_V(1,3); MX_V(2,3); MX_V(3,3);
|
||||
#undef MX_V
|
||||
|
||||
#define MX_V(a,b) qualifiers[b*4+a] = ("(" #a ")(" #b ")");
|
||||
MX_V(0,0); MX_V(0,1); MX_V(0,2); MX_V(0,3);
|
||||
MX_V(1,0); MX_V(1,1); MX_V(1,2); MX_V(1,3);
|
||||
MX_V(2,0); MX_V(2,1); MX_V(2,2); MX_V(2,3);
|
||||
MX_V(3,0); MX_V(3,1); MX_V(3,2); MX_V(3,3);
|
||||
#undef MX_V
|
||||
}
|
||||
|
||||
FCDAnimatedMatrix* FCDAnimatedMatrix::Create(FCDocument* document, FMMatrix44* value, int32 arrayElement)
|
||||
{
|
||||
FCDAnimatedMatrix* animated = new FCDAnimatedMatrix(document, value, arrayElement);
|
||||
if (!animated->Link(NULL)) SAFE_DELETE(animated);
|
||||
return animated;
|
||||
}
|
||||
FCDAnimatedMatrix* FCDAnimatedMatrix::Create(FCDocument* document, xmlNode* node, FMMatrix44* value, int32 arrayElement)
|
||||
{
|
||||
FCDAnimatedMatrix* animated = new FCDAnimatedMatrix(document, value, arrayElement);
|
||||
if (!animated->Link(node)) SAFE_DELETE(animated);
|
||||
return animated;
|
||||
}
|
||||
|
||||
FCDAnimated* FCDAnimatedMatrix::Clone(FCDocument* document, const FMMatrix44* oldMx, FMMatrix44* newMx)
|
||||
{
|
||||
FloatPtrList newValues;
|
||||
|
||||
#define MX_V(a,b) newValues.push_back(&(*newMx)[a][b]);
|
||||
MX_V(0,0); MX_V(0,1); MX_V(0,2); MX_V(0,3);
|
||||
MX_V(1,0); MX_V(1,1); MX_V(1,2); MX_V(1,3);
|
||||
MX_V(2,0); MX_V(2,1); MX_V(2,2); MX_V(2,3);
|
||||
MX_V(3,0); MX_V(3,1); MX_V(3,2); MX_V(3,3);
|
||||
#undef MX_V
|
||||
|
||||
return FCDAnimated::Clone(document, &(*oldMx)[0][0], newValues);
|
||||
}
|
||||
|
||||
FCDAnimatedCustom::FCDAnimatedCustom(FCDocument* document) : FCDAnimated(document, 1)
|
||||
{
|
||||
dummy = 0.0f;
|
||||
}
|
||||
|
||||
bool FCDAnimatedCustom::Link(xmlNode* node)
|
||||
{
|
||||
bool linked = false;
|
||||
|
||||
// Retrieve the list of the channels pointing to this node
|
||||
FUDaeParser::CalculateNodeTargetPointer(node, pointer);
|
||||
FCDAnimationChannelList channels;
|
||||
GetDocument()->FindAnimationChannels(pointer, channels);
|
||||
|
||||
// Extract all the qualifiers needed to hold these channels
|
||||
for (FCDAnimationChannelList::iterator itC = channels.begin(); itC != channels.end(); ++itC)
|
||||
{
|
||||
FCDAnimationChannel* channel = *itC;
|
||||
const FCDAnimationCurveList& channelCurves = channel->GetCurves();
|
||||
if (channelCurves.empty()) continue;
|
||||
|
||||
// Retrieve the channel's qualifier
|
||||
string qualifier = channel->GetTargetQualifier();
|
||||
if (qualifier.empty())
|
||||
{
|
||||
// Implies one channel holding multiple curves
|
||||
qualifiers.clear();
|
||||
qualifiers.resize(channels.size());
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
qualifiers.push_back(qualifier);
|
||||
}
|
||||
}
|
||||
|
||||
// Link the curves and check if this animated value is used as a driver
|
||||
values.resize(qualifiers.size());
|
||||
curves.resize(values.size());
|
||||
for (size_t i = 0; i < qualifiers.size(); ++i) { values[i] = &dummy; curves[i] = NULL; }
|
||||
linked |= ProcessChannels(channels);
|
||||
linked |= GetDocument()->LinkDriver(this);
|
||||
|
||||
if (linked)
|
||||
{
|
||||
// Register this animated value with the document
|
||||
GetDocument()->RegisterAnimatedValue(this);
|
||||
}
|
||||
return linked;
|
||||
}
|
||||
|
||||
FCDAnimatedCustom* FCDAnimatedCustom::Create(FCDocument* document)
|
||||
{
|
||||
FCDAnimatedCustom* animated = new FCDAnimatedCustom(document);
|
||||
if (!animated->Link(NULL)) SAFE_DELETE(animated);
|
||||
return animated;
|
||||
}
|
||||
FCDAnimatedCustom* FCDAnimatedCustom::Create(FCDocument* document, xmlNode* node)
|
||||
{
|
||||
FCDAnimatedCustom* animated = new FCDAnimatedCustom(document);
|
||||
if (!animated->Link(node)) SAFE_DELETE(animated);
|
||||
return animated;
|
||||
}
|
||||
@@ -1,488 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDAnimated.h
|
||||
This file contains the FCDAnimated class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_ANIMATED_H_
|
||||
#define _FCD_ANIMATED_H_
|
||||
|
||||
#include "FCDocument/FCDObject.h"
|
||||
|
||||
class FCDocument;
|
||||
class FCDAnimated;
|
||||
class FCDAnimationCurve;
|
||||
class FCDAnimationChannel;
|
||||
class FCDAnimationMultiCurve;
|
||||
|
||||
typedef vector<float*> FloatPtrList; /**< A dynamically-sized array of floating-point value pointers. */
|
||||
typedef vector<FCDAnimationCurve*> FCDAnimationCurveList; /**< A dynamically-sized array of animation curves. */
|
||||
typedef vector<FCDAnimationChannel*> FCDAnimationChannelList; /**< A dynamically-sized array of animation channels. */
|
||||
typedef vector<FCDAnimated*> FCDAnimatedList; /**< A dynamically-sized array of animated values. */
|
||||
|
||||
/**
|
||||
An animated element.
|
||||
An animated element encapsulates a set of floating-point values that are
|
||||
marked as animated.
|
||||
|
||||
For this purpose, an animated element holds a list of floating-point values,
|
||||
their animation curves and their COLLADA qualifiers for the generation of
|
||||
COLLADA targets. For animated list elements, an animated element holds an array index.
|
||||
|
||||
There are many classes built on top of this class. They represent
|
||||
the different element types that may be animated, such as 3D points,
|
||||
colors and matrices.
|
||||
|
||||
@ingroup FCDocument
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDAnimated : public FCDObject
|
||||
{
|
||||
protected:
|
||||
/** The list of value pointers. */
|
||||
FloatPtrList values;
|
||||
|
||||
/** The list of target qualifiers.
|
||||
There is always one qualifier for one value pointer. */
|
||||
StringList qualifiers;
|
||||
|
||||
/** The list of animation curves.
|
||||
There is always one curve for one value pointer, although
|
||||
that curve may be the NULL pointer to indicate a non-animated value. */
|
||||
FCDAnimationCurveList curves;
|
||||
|
||||
/** The array index for animated element that belong
|
||||
to a list of animated elements. This value may be -1
|
||||
to indicate that the element does not belong to a list.
|
||||
Otherwise, the index should always be unsigned. */
|
||||
int32 arrayElement;
|
||||
|
||||
/** [INTERNAL] The target pointer prefix. */
|
||||
string pointer;
|
||||
|
||||
public:
|
||||
/** Constructor.
|
||||
In most cases, it is preferable to create objects of the up-classes.
|
||||
@param document The COLLADA document that owns this animated element.
|
||||
@param valueCount The number of values inside the animated element. */
|
||||
FCDAnimated(FCDocument* document, size_t valueCount);
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~FCDAnimated();
|
||||
|
||||
/** Retrieves the number of values contained within this animated element.
|
||||
@return The number of values. */
|
||||
inline size_t GetValueCount() const { return values.size(); }
|
||||
|
||||
/** Retrieves the animation curve affecting the value of an animated element.
|
||||
@param index The value index.
|
||||
@return The curve affecting the value at the given index. This pointer will
|
||||
be NULL if the index is out-of-bounds or if the value is not animated. */
|
||||
inline FCDAnimationCurve* GetCurve(size_t index) { FUAssert(index < GetValueCount(), return NULL); return curves.at(index); }
|
||||
inline const FCDAnimationCurve* GetCurve(size_t index) const { FUAssert(index < GetValueCount(), return NULL); return curves.at(index); } /**< See above. */
|
||||
|
||||
/** Retrieves the list of the curves affecting the values of an animated element.
|
||||
This list may contain the NULL pointer, where a value is not animated.
|
||||
@return The list of animation curves. */
|
||||
inline FCDAnimationCurveList& GetCurves() { return curves; }
|
||||
inline const FCDAnimationCurveList& GetCurves() const { return curves; } /**< See above. */
|
||||
|
||||
/** Assigns a curve to a value of the animated element.
|
||||
The previously assigned curve will be deleted.
|
||||
@param index The value index.
|
||||
@param curve The new curve that will affect the value at the given index.
|
||||
@return Whether the curve was successfully assigned. Will return false if
|
||||
the index is out-of-bounds. */
|
||||
bool SetCurve(size_t index, FCDAnimationCurve* curve);
|
||||
|
||||
/** Removes the curve affecting a value of the animated element.
|
||||
@param index The value index.
|
||||
@return Whether a curve was successfully removed. Will return false
|
||||
if there was no curve to release or the index is out-of-bounds. */
|
||||
bool RemoveCurve(size_t index);
|
||||
|
||||
/** Retrieves the value of an animated element.
|
||||
@param index The value index.
|
||||
@return The value at the given index. This pointer will
|
||||
be NULL if the index is out-of-boudns. */
|
||||
inline float* GetValue(size_t index) { FUAssert(index < GetValueCount(), return NULL); return values.at(index); }
|
||||
inline const float* GetValue(size_t index) const { FUAssert(index < GetValueCount(), return NULL); return values.at(index); } /**< See above. */
|
||||
|
||||
/** Retrieves the qualifier of the value of an animated element.
|
||||
@param index The value index.
|
||||
@return The qualifier for the value. The value returned will be an
|
||||
empty string when the index is out-of-bounds. */
|
||||
inline const string& GetQualifier(size_t index) const;
|
||||
|
||||
/** Retrieves an animated value given a valid qualifier.
|
||||
@param qualifier A valid qualifier.
|
||||
@return The animated value for this qualifier. This pointer will be
|
||||
NULL if the given qualifier is not used within this animated element. */
|
||||
float* FindValue(const string& qualifier);
|
||||
const float* FindValue(const string& qualifier) const; /**< See above. */
|
||||
|
||||
/** Retrieves an animation curve given a valid qualifier.
|
||||
@param qualifier A valid qualifier.
|
||||
@return The animation curve for this qualifier. This pointer will be
|
||||
NULL if the given qualifier is not used within this animated element
|
||||
or if the value for the given qualifier is not animated. */
|
||||
inline FCDAnimationCurve* FindCurve(const char* qualifier) { return GetCurve(FindQualifier(qualifier)); }
|
||||
inline FCDAnimationCurve* FindCurve(const string& qualifier) { return FindCurve(qualifier.c_str()); } /**< See above. */
|
||||
inline const FCDAnimationCurve* FindCurve(const char* qualifier) const { return GetCurve(FindQualifier(qualifier)); } /**< See above. */
|
||||
inline const FCDAnimationCurve* FindCurve(const string& qualifier) const { return FindCurve(qualifier.c_str()); } /**< See above. */
|
||||
|
||||
/** Retrieves an animation curve given a value pointer.
|
||||
@param value A value pointer contained within the animated element.
|
||||
@return The animation curve for this qualifier. This pointer will be
|
||||
NULL if the value pointer is not contained by this animated element
|
||||
or if the value is not animated. */
|
||||
inline FCDAnimationCurve* FindCurve(const float* value) { return GetCurve(FindValue(value)); }
|
||||
inline const FCDAnimationCurve* FindCurve(const float* value) const { return GetCurve(FindValue(value)); } /**< See above. */
|
||||
|
||||
/** Retrieves the value index for a given qualifier.
|
||||
@param qualifier A valid qualifier.
|
||||
@return The value index. This value will be -1 to indicate that the
|
||||
qualifier does not belong to this animated element. */
|
||||
size_t FindQualifier(const char* qualifier) const;
|
||||
inline size_t FindQualifier(const string& qualifier) const { return FindQualifier(qualifier.c_str()); } /**< See above. */
|
||||
|
||||
/** Retrieves the value index for a given value pointer.
|
||||
@param value A value pointer contained within the animated element.
|
||||
@return The value index. This value will be -1 to indicate that the
|
||||
value pointer is not contained by this animated element. */
|
||||
size_t FindValue(const float* value) const;
|
||||
|
||||
/** Retrieves the array index for an animated element.
|
||||
This value is used only for animated elements that belong
|
||||
to a list of animated elements within the COLLADA document.
|
||||
@return The array index. This value will be -1 to indicate that
|
||||
the animated element does not belong to a list. */
|
||||
inline int32 GetArrayElement() const { return arrayElement; }
|
||||
|
||||
/** Sets the array index for an animated element.
|
||||
This value is used only for animated elements that belong
|
||||
to a list of animated elements within the COLLADA document.
|
||||
@param index The array index. This value should be -1 to indicate that
|
||||
the animated element does not belong to a list. */
|
||||
inline void SetArrayElement(int32 index) { arrayElement = index; }
|
||||
|
||||
/** Retrieves whether this animated element has any animation curves
|
||||
affecting its values.
|
||||
@return Whether any curves affect this animated element. */
|
||||
bool HasCurve() const;
|
||||
|
||||
/** Creates one multi-dimensional animation curve from this animated element.
|
||||
This function is useful is your application does not handle animations
|
||||
per-values, but instead needs one animation per-element.
|
||||
@return The multi-dimensional animation curve. */
|
||||
FCDAnimationMultiCurve* CreateMultiCurve() const;
|
||||
|
||||
/** Creates one multi-dimensional animation curve from a list of animated element.
|
||||
This function is useful is your application does not handle animations
|
||||
per-values. For example, we use this function is ColladaMax for animated scale values,
|
||||
where one scale value is two rotations for the scale rotation pivot and one
|
||||
3D point for the scale factors.
|
||||
@param toMerge The list of animated elements to merge
|
||||
@return The multi-dimensional animation curve. */
|
||||
static FCDAnimationMultiCurve* CreateMultiCurve(const FCDAnimatedList& toMerge);
|
||||
|
||||
/** Evaluates the animated element at a given time.
|
||||
This function directly and <b>permanently</b> modifies the values
|
||||
of the animated element according to the curves affecting them.
|
||||
@param time The evaluation time. */
|
||||
void Evaluate(float time);
|
||||
|
||||
/** [INTERNAL] Clones an animated element.
|
||||
@param document The COLLADA document that owns the cloned animated element.
|
||||
@param animatedValue One animated value contained within the original animated element.
|
||||
@param newAnimatedValues The list of value pointers to be contained by the cloned animated element.
|
||||
@return The cloned animated element. */
|
||||
static FCDAnimated* Clone(FCDocument* document, const float* animatedValue, FloatPtrList& newAnimatedValues);
|
||||
|
||||
/** [INTERNAL] Clones an animated element.
|
||||
@param document The COLLADA document that owns the cloned animated element.
|
||||
@return The cloned animated element. */
|
||||
FCDAnimated* Clone(FCDocument* document);
|
||||
|
||||
/** [INTERNAL] Retrieves the target pointer that prefixes the
|
||||
fully-qualified target for the element.
|
||||
@return The target pointer prefix. */
|
||||
const string& GetTargetPointer() const { return pointer; }
|
||||
|
||||
/** [INTERNAL] Links this animated element with a given XML tree node.
|
||||
This function is solely used within the import of a COLLADA document.
|
||||
The floating-point values held within the XML tree node will be linked
|
||||
with the list of floating-point value pointers held by the animated entity.
|
||||
@param node The XML tree node.
|
||||
@return Whether there was any linkage done. */
|
||||
bool Link(xmlNode* node);
|
||||
|
||||
/** [INTERNAL] Links the animated element with the imported animation curves.
|
||||
This compares the animation channel targets with the animated element target
|
||||
and qualifiers to assign curves unto the value pointers.
|
||||
@param channels A list of animation channels with the correct target pointer.
|
||||
@return Whether any animation curves were assigned to the animation element. */
|
||||
bool ProcessChannels(FCDAnimationChannelList& channels);
|
||||
};
|
||||
|
||||
/** A COLLADA animated single floating-point value element.
|
||||
Use this animated element class for all generic-purpose single floating-point values.
|
||||
For angles, use the FCDAnimatedAngle class.
|
||||
@ingroup FCDocument */
|
||||
class FCOLLADA_EXPORT FCDAnimatedFloat : public FCDAnimated
|
||||
{
|
||||
private:
|
||||
// Don't build directly, use the Create function instead
|
||||
FCDAnimatedFloat(FCDocument* document, float* value, int32 arrayElement);
|
||||
|
||||
public:
|
||||
/** Creates a new animated element.
|
||||
@param document The COLLADA document that owns the animated element.
|
||||
@param value The value pointer for the single floating-point value.
|
||||
@param arrayElement The optional array index for animated element
|
||||
that belong to an animated element list.
|
||||
@return The new animated element. */
|
||||
static FCDAnimatedFloat* Create(FCDocument* document, float* value, int32 arrayElement=-1);
|
||||
|
||||
/** [INTERNAL] Creates a new animated element.
|
||||
This function is used during the import of a COLLADA document.
|
||||
@param document The COLLADA document that owns the animated element.
|
||||
@param node The XML tree node that contains the animated values.
|
||||
@param value The value pointer for the single floating-point value.
|
||||
@param arrayElement The optional array index for animated element
|
||||
that belong to an animated element list.
|
||||
@return The new animated element. */
|
||||
static FCDAnimatedFloat* Create(FCDocument* document, xmlNode* node, float* value, int32 arrayElement=-1);
|
||||
|
||||
/** [INTERNAL] Clones an animated element.
|
||||
@param document The COLLADA document that owns the cloned animated element.
|
||||
@param oldValue The single floating-point value pointer contained within the original animated element.
|
||||
@param newValue The single floating-point value pointer for the cloned animated element.
|
||||
@return The cloned animated value. */
|
||||
static FCDAnimated* Clone(FCDocument* document, const float* oldValue, float* newValue);
|
||||
};
|
||||
|
||||
/** A COLLADA animated 3D vector element.
|
||||
@ingroup FCDocument */
|
||||
class FCOLLADA_EXPORT FCDAnimatedPoint3 : public FCDAnimated
|
||||
{
|
||||
private:
|
||||
// Don't build directly, use the Create function instead
|
||||
FCDAnimatedPoint3(FCDocument* document, FMVector3* value, int32 arrayElement);
|
||||
|
||||
public:
|
||||
/** Creates a new animated element.
|
||||
@param document The COLLADA document that owns the animated element.
|
||||
@param value The value pointer for the 3D vector.
|
||||
@param arrayElement The optional array index for animated element
|
||||
that belong to an animated element list.
|
||||
@return The new animated element. */
|
||||
static FCDAnimatedPoint3* Create(FCDocument* document, FMVector3* value, int32 arrayElement=-1);
|
||||
|
||||
/** [INTERNAL] Creates a new animated element.
|
||||
This function is used during the import of a COLLADA document.
|
||||
@param document The COLLADA document that owns the animated element.
|
||||
@param node The XML tree node that contains the animated values.
|
||||
@param value The value pointer for the 3D vector.
|
||||
@param arrayElement The optional array index for animated element
|
||||
that belong to an animated element list.
|
||||
@return The new animated element. */
|
||||
static FCDAnimatedPoint3* Create(FCDocument* document, xmlNode* node, FMVector3* value, int32 arrayElement=-1);
|
||||
|
||||
/** [INTERNAL] Clones an animated element.
|
||||
@param document The COLLADA document that owns the cloned animated element.
|
||||
@param oldValue The 3D vector contained within the original animated element.
|
||||
@param newValue The 3D vector for the cloned animated element.
|
||||
@return The cloned animated value. */
|
||||
static FCDAnimated* Clone(FCDocument* document, const FMVector3* oldValue, FMVector3* newValue);
|
||||
};
|
||||
|
||||
/** A COLLADA animated RGB color element.
|
||||
@ingroup FCDocument */
|
||||
class FCOLLADA_EXPORT FCDAnimatedColor : public FCDAnimated
|
||||
{
|
||||
private:
|
||||
// Don't build directly, use the Create function instead
|
||||
FCDAnimatedColor(FCDocument* document, FMVector3* value, int32 arrayElement);
|
||||
|
||||
public:
|
||||
/** Creates a new animated element.
|
||||
@param document The COLLADA document that owns the animated element.
|
||||
@param value The value pointer for the RGB color.
|
||||
@param arrayElement The optional array index for animated element
|
||||
that belong to an animated element list.
|
||||
@return The new animated element. */
|
||||
static FCDAnimatedColor* Create(FCDocument* document, FMVector3* value, int32 arrayElement=-1);
|
||||
|
||||
/** [INTERNAL] Creates a new animated element.
|
||||
This function is used during the import of a COLLADA document.
|
||||
@param document The COLLADA document that owns the animated element.
|
||||
@param node The XML tree node that contains the animated values.
|
||||
@param value The value pointer for the RGB color.
|
||||
@param arrayElement The optional array index for animated element
|
||||
that belong to an animated element list.
|
||||
@return The new animated element. */
|
||||
static FCDAnimatedColor* Create(FCDocument* document, xmlNode* node, FMVector3* value, int32 arrayElement=-1);
|
||||
|
||||
/** [INTERNAL] Clones an animated element.
|
||||
@param document The COLLADA document that owns the cloned animated element.
|
||||
@param oldValue The RGB color contained within the original animated element.
|
||||
@param newValue The RGB color for the cloned animated element.
|
||||
@return The cloned animated value. */
|
||||
static FCDAnimated* Clone(FCDocument* document, const FMVector3* oldValue, FMVector3* newValue);
|
||||
};
|
||||
|
||||
/** A COLLADA floating-point value that represents an angle.
|
||||
@ingroup FCDocument */
|
||||
class FCOLLADA_EXPORT FCDAnimatedAngle : public FCDAnimated
|
||||
{
|
||||
private:
|
||||
// Don't build directly, use the Create function instead
|
||||
FCDAnimatedAngle(FCDocument* document, float* value, int32 arrayElement);
|
||||
|
||||
public:
|
||||
/** Creates a new animated element.
|
||||
@param document The COLLADA document that owns the animated element.
|
||||
@param value The value pointer for the angle.
|
||||
@param arrayElement The optional array index for animated element
|
||||
that belong to an animated element list.
|
||||
@return The new animated element. */
|
||||
static FCDAnimatedAngle* Create(FCDocument* document, float* value, int32 arrayElement=-1);
|
||||
|
||||
/** [INTERNAL] Creates a new animated element.
|
||||
This function is used during the import of a COLLADA document.
|
||||
@param document The COLLADA document that owns the animated element.
|
||||
@param node The XML tree node that contains the animated values.
|
||||
@param value The value pointer for the angle.
|
||||
@param arrayElement The optional array index for animated element
|
||||
that belong to an animated element list.
|
||||
@return The new animated element. */
|
||||
static FCDAnimatedAngle* Create(FCDocument* document, xmlNode* node, float* value, int32 arrayElement=-1);
|
||||
|
||||
/** [INTERNAL] Clones an animated element.
|
||||
@param document The COLLADA document that owns the cloned animated element.
|
||||
@param oldValue The angle value pointer contained within the original animated element.
|
||||
@param newValue The angle value pointer for the cloned animated element.
|
||||
@return The cloned animated value. */
|
||||
static FCDAnimated* Clone(FCDocument* document, const float* oldValue, float* newValue);
|
||||
};
|
||||
|
||||
/** A COLLADA animated angle-axis.
|
||||
Used for rotations, takes in a 3D vector for the axis and
|
||||
a single floating-point value for the angle.
|
||||
@ingroup FCDocument */
|
||||
class FCOLLADA_EXPORT FCDAnimatedAngleAxis : public FCDAnimated
|
||||
{
|
||||
private:
|
||||
// Don't build directly, use the Create function instead
|
||||
FCDAnimatedAngleAxis(FCDocument* document, FMVector3* axis, float* angle, int32 arrayElement);
|
||||
|
||||
public:
|
||||
/** Creates a new animated element.
|
||||
@param document The COLLADA document that owns the animated element.
|
||||
@param value The value pointer for the axis.
|
||||
@param angle The value pointer for the angle.
|
||||
@param arrayElement The optional array index for animated element
|
||||
that belong to an animated element list.
|
||||
@return The new animated element. */
|
||||
static FCDAnimatedAngleAxis* Create(FCDocument* document, FMVector3* value, float* angle, int32 arrayElement=-1);
|
||||
|
||||
/** [INTERNAL] Creates a new animated element.
|
||||
This function is used during the import of a COLLADA document.
|
||||
@param document The COLLADA document that owns the animated element.
|
||||
@param node The XML tree node that contains the animated values.
|
||||
@param axis The value pointer for the axis.
|
||||
@param angle The value pointer for the angle.
|
||||
@param arrayElement The optional array index for animated element
|
||||
that belong to an animated element list.
|
||||
@return The new animated element. */
|
||||
static FCDAnimatedAngleAxis* Create(FCDocument* document, xmlNode* node, FMVector3* axis, float* angle, int32 arrayElement=-1);
|
||||
|
||||
/** [INTERNAL] Clones an animated element.
|
||||
@param document The COLLADA document that owns the cloned animated element.
|
||||
@param oldAngle The angle value pointer contained within the original animated element.
|
||||
@param newAxis The axis value pointer for the cloned animated element.
|
||||
@param newAngle The angle value pointer for the cloned animated element.
|
||||
@return The cloned animated value. */
|
||||
static FCDAnimated* Clone(FCDocument* document, const float* oldAngle, FMVector3* newAxis, float* newAngle);
|
||||
};
|
||||
|
||||
/** A COLLADA animated matrix.
|
||||
Used for animated transforms, takes in a 16 floating-point values.
|
||||
@ingroup FCDocument */
|
||||
class FCOLLADA_EXPORT FCDAnimatedMatrix : public FCDAnimated
|
||||
{
|
||||
private:
|
||||
// Don't build directly, use the Create function instead
|
||||
FCDAnimatedMatrix(FCDocument* document, FMMatrix44* value, int32 arrayElement);
|
||||
|
||||
public:
|
||||
/** Creates a new animated element.
|
||||
@param document The COLLADA document that owns the animated element.
|
||||
@param value The value pointer for the matrix.
|
||||
@param arrayElement The optional array index for animated element
|
||||
that belong to an animated element list.
|
||||
@return The new animated element. */
|
||||
static FCDAnimatedMatrix* Create(FCDocument* document, FMMatrix44* value, int32 arrayElement=-1);
|
||||
|
||||
/** [INTERNAL] Creates a new animated element.
|
||||
This function is used during the import of a COLLADA document.
|
||||
@param document The COLLADA document that owns the animated element.
|
||||
@param node The XML tree node that contains the animated values.
|
||||
@param value The value pointer for the matrix.
|
||||
@param arrayElement The optional array index for animated element
|
||||
that belong to an animated element list.
|
||||
@return The new animated element. */
|
||||
static FCDAnimatedMatrix* Create(FCDocument* document, xmlNode* node, FMMatrix44* value, int32 arrayElement=-1);
|
||||
|
||||
/** [INTERNAL] Clones an animated element.
|
||||
@param document The COLLADA document that owns the cloned animated element.
|
||||
@param oldMx The matrix value pointer contained within the original animated element.
|
||||
@param newMx The matrix value pointer for the cloned animated element.
|
||||
@return The cloned animated value. */
|
||||
static FCDAnimated* Clone(FCDocument* document, const FMMatrix44* oldMx, FMMatrix44* newMx);
|
||||
};
|
||||
|
||||
/** A COLLADA custom animated value.
|
||||
Used for animated extra elements. A single value is used multiple times to hold
|
||||
as many value pointers are necessary to hold the animation curves.
|
||||
@ingroup FCDocument */
|
||||
class FCOLLADA_EXPORT FCDAnimatedCustom : public FCDAnimated
|
||||
{
|
||||
private:
|
||||
float dummy;
|
||||
|
||||
// Don't build directly, use the Create function instead
|
||||
FCDAnimatedCustom(FCDocument* document);
|
||||
|
||||
bool Link(xmlNode* node);
|
||||
|
||||
public:
|
||||
/** Creates a new animated element.
|
||||
@param document The COLLADA document that owns the animated element.
|
||||
@return The new animated element. */
|
||||
static FCDAnimatedCustom* Create(FCDocument* document);
|
||||
|
||||
/** [INTERNAL] Creates a new animated element.
|
||||
This function is used during the import of a COLLADA document.
|
||||
@param document The COLLADA document that owns the animated element.
|
||||
@param node The XML tree node that contains the animated values.
|
||||
@return The new animated element. */
|
||||
static FCDAnimatedCustom* Create(FCDocument* document, xmlNode* node);
|
||||
|
||||
/** Retrieves the floating-point value used for all the value pointers.
|
||||
@return The dummy floating-point value. */
|
||||
const float& GetDummy() const { return dummy; }
|
||||
};
|
||||
|
||||
#endif // _FCD_ANIMATED_H_
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDAnimation.h"
|
||||
#include "FCDocument/FCDAnimationChannel.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
using namespace FUDaeParser;
|
||||
|
||||
FCDAnimation::FCDAnimation(FCDocument* document) : FCDEntity(document, "Animation")
|
||||
{
|
||||
}
|
||||
|
||||
FCDAnimation::~FCDAnimation()
|
||||
{
|
||||
CLEAR_POINTER_VECTOR(channels);
|
||||
CLEAR_POINTER_VECTOR(children);
|
||||
childNodes.clear();
|
||||
}
|
||||
|
||||
// Creates a new animation entity sub-tree contained within this animation entity tree.
|
||||
FCDAnimation* FCDAnimation::AddChild()
|
||||
{
|
||||
FCDAnimation* animation = new FCDAnimation(GetDocument());
|
||||
children.push_back(animation);
|
||||
return animation;
|
||||
}
|
||||
|
||||
// Releases an animation entity sub-tree contained by this animation entity tree.
|
||||
void FCDAnimation::ReleaseChild(FCDAnimation* animation)
|
||||
{
|
||||
FCDAnimationList::iterator itA = std::find(children.begin(), children.end(), animation);
|
||||
if (itA != children.end())
|
||||
{
|
||||
delete *itA;
|
||||
children.erase(itA);
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a new animation channel to this animation entity.
|
||||
FCDAnimationChannel* FCDAnimation::AddChannel()
|
||||
{
|
||||
FCDAnimationChannel* channel = new FCDAnimationChannel(GetDocument(), this);
|
||||
channels.push_back(channel);
|
||||
return channel;
|
||||
}
|
||||
|
||||
// Releases an animation channel contained within this animation entity.
|
||||
void FCDAnimation::ReleaseChannel(FCDAnimationChannel* channel)
|
||||
{
|
||||
FCDAnimationChannelList::iterator itC = std::find(channels.begin(), channels.end(), channel);
|
||||
if (itC != channels.end())
|
||||
{
|
||||
delete *itC;
|
||||
channels.erase(itC);
|
||||
}
|
||||
}
|
||||
|
||||
// Optimization: Look for the xml child node with the given id
|
||||
xmlNode* FCDAnimation::FindChildById(const string& _id)
|
||||
{
|
||||
FUCrc32::crc32 id = FUCrc32::CRC32(_id.c_str() + ((_id[0] == '#') ? 1 : 0));
|
||||
for (FUXmlNodeIdPairList::iterator it = childNodes.begin(); it != childNodes.end(); ++it)
|
||||
{
|
||||
if ((*it).id == id) return (*it).node;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Look for an animation children with the given COLLADA Id.
|
||||
FCDEntity* FCDAnimation::FindDaeId(const string& daeId)
|
||||
{
|
||||
if (GetDaeId() == daeId) return this;
|
||||
|
||||
for (FCDAnimationList::iterator it = children.begin(); it != children.end(); ++it)
|
||||
{
|
||||
FCDEntity* found = (*it)->FindDaeId(daeId);
|
||||
if (found != NULL) return found;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Retrieve all the curves created under this animation element, in the animation tree
|
||||
void FCDAnimation::GetCurves(FCDAnimationCurveList& curves)
|
||||
{
|
||||
// Retrieve the curves for this animation tree element
|
||||
for (FCDAnimationChannelList::iterator it = channels.begin(); it != channels.end(); ++it)
|
||||
{
|
||||
const FCDAnimationCurveList& channelCurves = (*it)->GetCurves();
|
||||
for (FCDAnimationCurveList::const_iterator itC = channelCurves.begin(); itC != channelCurves.end(); ++itC)
|
||||
{
|
||||
curves.push_back(*itC);
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve the curves for the animation nodes under this one in the animation tree
|
||||
for (FCDAnimationList::iterator it = children.begin(); it != children.end(); ++it)
|
||||
{
|
||||
(*it)->GetCurves(curves);
|
||||
}
|
||||
}
|
||||
|
||||
FUStatus FCDAnimation::Link()
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// Link the child nodes and check the curves for their drivers
|
||||
for (FCDAnimationChannelList::iterator it = channels.begin(); it != channels.end(); ++it)
|
||||
{
|
||||
status.AppendStatus((*it)->CheckDriver());
|
||||
}
|
||||
for (FCDAnimationList::iterator it = children.begin(); it != children.end(); ++it)
|
||||
{
|
||||
status.AppendStatus((*it)->Link());
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Check for animation curves that need this animated as a driver
|
||||
bool FCDAnimation::LinkDriver(FCDAnimated* animated)
|
||||
{
|
||||
bool driver = false;
|
||||
|
||||
// Link the child curves and child nodes
|
||||
for (FCDAnimationChannelList::iterator it = channels.begin(); it != channels.end(); ++it)
|
||||
{
|
||||
driver |= (*it)->LinkDriver(animated);
|
||||
}
|
||||
for (FCDAnimationList::iterator it = children.begin(); it != children.end(); ++it)
|
||||
{
|
||||
driver |= (*it)->LinkDriver(animated);
|
||||
}
|
||||
|
||||
return driver;
|
||||
}
|
||||
|
||||
// Load a Collada animation node from the XML document
|
||||
FUStatus FCDAnimation::LoadFromXML(xmlNode* node)
|
||||
{
|
||||
FUStatus status = FCDEntity::LoadFromXML(node);
|
||||
if (!status) return status;
|
||||
if (!IsEquivalent(node->name, DAE_ANIMATION_ELEMENT))
|
||||
{
|
||||
return status.Warning(FS("Animation library contains unknown element."), node->line);
|
||||
}
|
||||
|
||||
// Optimization: Grab all the IDs of the child nodes, in CRC format.
|
||||
ReadChildrenIds(node, childNodes);
|
||||
|
||||
// Parse all the inner <channel> elements
|
||||
xmlNodeList channelNodes;
|
||||
FindChildrenByType(node, DAE_CHANNEL_ELEMENT, channelNodes);
|
||||
channels.reserve(channelNodes.size());
|
||||
for (xmlNodeList::iterator itC = channelNodes.begin(); itC != channelNodes.end(); ++itC)
|
||||
{
|
||||
// Parse each <channel> element individually
|
||||
// They each handle reading the <sampler> and <source> elements
|
||||
FCDAnimationChannel* channel = AddChannel();
|
||||
status.AppendStatus(channel->LoadFromXML(*itC));
|
||||
if (!status)
|
||||
{
|
||||
ReleaseChannel(channel);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse all the hierarchical <animation> elements
|
||||
xmlNodeList animationNodes;
|
||||
FindChildrenByType(node, DAE_ANIMATION_ELEMENT, animationNodes);
|
||||
for (xmlNodeList::iterator itA = animationNodes.begin(); itA != animationNodes.end(); ++itA)
|
||||
{
|
||||
FCDAnimation* animation = AddChild();
|
||||
animation->LoadFromXML(*itA);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// Search for an animation channel for the given XML pointer in this animation node
|
||||
void FCDAnimation::FindAnimationChannels(const string& pointer, vector<FCDAnimationChannel*>& targetChannels)
|
||||
{
|
||||
// Look for channels locally
|
||||
for (FCDAnimationChannelList::iterator itChannel = channels.begin(); itChannel != channels.end(); ++itChannel)
|
||||
{
|
||||
if ((*itChannel)->GetTargetPointer() == pointer)
|
||||
{
|
||||
targetChannels.push_back(*itChannel);
|
||||
}
|
||||
}
|
||||
|
||||
// Look for channel(s) within the child animations
|
||||
for (FCDAnimationList::iterator it = children.begin(); it != children.end(); ++it)
|
||||
{
|
||||
(*it)->FindAnimationChannels(pointer, targetChannels);
|
||||
}
|
||||
}
|
||||
|
||||
// Write out the COLLADA animations to the document
|
||||
xmlNode* FCDAnimation::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* animationNode = WriteToEntityXML(parentNode, DAE_ANIMATION_ELEMENT);
|
||||
|
||||
// Write out the local channels
|
||||
for (FCDAnimationChannelList::const_iterator itChannel = channels.begin(); itChannel != channels.end(); ++itChannel)
|
||||
{
|
||||
(*itChannel)->WriteToXML(animationNode);
|
||||
}
|
||||
|
||||
// Write out the child animations
|
||||
for (FCDAnimationList::const_iterator it = children.begin(); it != children.end(); ++it)
|
||||
{
|
||||
(*it)->WriteToXML(animationNode);
|
||||
}
|
||||
|
||||
FCDEntity::WriteToExtraXML(animationNode);
|
||||
return animationNode;
|
||||
}
|
||||
@@ -1,163 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDAnimation.h
|
||||
This file contains the FCDAnimation class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_ANIMATION_H_
|
||||
#define _FCD_ANIMATION_H_
|
||||
|
||||
#include "FUtils/FUXmlNodeIdPair.h"
|
||||
#include "FCDocument/FCDEntity.h"
|
||||
|
||||
class FCDocument;
|
||||
class FCDAnimated;
|
||||
class FCDAnimation;
|
||||
class FCDAnimationChannel;
|
||||
class FCDAnimationCurve;
|
||||
|
||||
typedef vector<FCDAnimation*> FCDAnimationList; /**< A dynamically-sized array of animation entities. */
|
||||
typedef vector<FCDAnimationChannel*> FCDAnimationChannelList; /**< A dynamically-sized array of animation channels. */
|
||||
typedef vector<FCDAnimationCurve*> FCDAnimationCurveList; /**< A dynamically-sized array of animation curves. */
|
||||
|
||||
/**
|
||||
A COLLADA animation entity.
|
||||
An animation entity contains a list of child animation entities,
|
||||
in order to form a tree of animation entities.
|
||||
It also hold a list of animation channels, which hold the information
|
||||
to generate animation curves.
|
||||
|
||||
In other words, the animation entity is a structural class
|
||||
used to group animation channels hierarchically.
|
||||
|
||||
@ingroup FCDocument
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDAnimation : public FCDEntity
|
||||
{
|
||||
private:
|
||||
FCDAnimationChannelList channels;
|
||||
FUXmlNodeIdPairList childNodes;
|
||||
FCDAnimationList children;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDLibrary::AddEntity function
|
||||
or the AddChild function, depending on the
|
||||
hierarchical level of the animation entity.
|
||||
@param document The COLLADA document that owns the animation entity. */
|
||||
FCDAnimation(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDLibrary::ReleaseEntity function
|
||||
or the ReleaseChild function, depending on the
|
||||
hierarchical level of the animation entity.*/
|
||||
virtual ~FCDAnimation();
|
||||
|
||||
/** Retrieves the entity class type.
|
||||
This function is a part of the FCDEntity interface.
|
||||
@return The entity class type: ANIMATION. */
|
||||
virtual Type GetType() const { return ANIMATION; }
|
||||
|
||||
/** Retrieves the entity with the given COLLADA id.
|
||||
This function will look through the local sub-tree of animations
|
||||
for the given COLLADA id.
|
||||
@param daeId A COLLADA id.
|
||||
@return The animation entity that matches the COLLADA id. This pointer
|
||||
will be NULL if there are no animation entities that matches the COLLADA id. */
|
||||
virtual FCDEntity* FindDaeId(const string& daeId);
|
||||
|
||||
/** Retrieves the number of animation entity sub-trees contained
|
||||
by this animation entity tree.
|
||||
@return The number of animation entity sub-trees. */
|
||||
inline size_t GetChildCount() const { return children.size(); }
|
||||
|
||||
/** Retrieves an animation entity sub-tree contained by this
|
||||
animation entity tree.
|
||||
@param index The index of the sub-tree.
|
||||
@return The animation entity sub-tree at the given index. This pointer will
|
||||
be NULL if the index is out-of-bounds. */
|
||||
inline FCDAnimation* GetChild(size_t index) { FUAssert(index < GetChildCount(), return NULL); return children.at(index); }
|
||||
inline const FCDAnimation* GetChild(size_t index) const { FUAssert(index < GetChildCount(), return NULL); return children.at(index); } /**< See above. */
|
||||
|
||||
/** Creates a new animation entity sub-tree contained within this animation entity tree.
|
||||
@return The new animation sub-tree. */
|
||||
inline FCDAnimation* AddChild();
|
||||
|
||||
/** Releases an animation entity sub-tree contained by this animation entity tree.
|
||||
@param animation The animation entity the release. */
|
||||
inline void ReleaseChild(FCDAnimation* animation);
|
||||
|
||||
/** Retrieves the animation channels that target the given COLLADA target pointer.
|
||||
@param pointer A COLLADA target pointer.
|
||||
@param targetChannels A list of animation channels to fill in.
|
||||
This list is not cleared. */
|
||||
void FindAnimationChannels(const string& pointer, FCDAnimationChannelList& targetChannels);
|
||||
|
||||
/** Retrieves the number of animation channels at this level within the animation tree.
|
||||
@return The number of animation channels. */
|
||||
size_t GetChannelCount() const { return channels.size(); }
|
||||
|
||||
/** Retrieves an animation channel contained by this animation entity.
|
||||
@param index The index of the channel.
|
||||
@return The channel at the given index. This pointer will be NULL
|
||||
if the index is out-of-bounds. */
|
||||
FCDAnimationChannel* GetChannel(size_t index) { FUAssert(index < GetChannelCount(), return NULL); return channels.at(index); }
|
||||
const FCDAnimationChannel* GetChannel(size_t index) const { FUAssert(index < GetChannelCount(), return NULL); return channels.at(index); } /**< See above. */
|
||||
|
||||
/** Adds a new animation channel to this animation entity.
|
||||
@return The new animation channel. */
|
||||
FCDAnimationChannel* AddChannel();
|
||||
|
||||
/** Releases an animation channel contained within this animation entity.
|
||||
@param channel The animation channel to release. */
|
||||
void ReleaseChannel(FCDAnimationChannel* channel);
|
||||
|
||||
/** Retrieves all the curves created in the subtree of this animation element.
|
||||
@param curves A list of animation curves to fill in.
|
||||
This list is not cleared. */
|
||||
void GetCurves(FCDAnimationCurveList& curves);
|
||||
|
||||
/** [INTERNAL] Links the animation sub-tree with the other entities within the document.
|
||||
This function is used at the end of the import of a document to verify that all the
|
||||
necessary drivers were found.
|
||||
@return The status of the linkage. */
|
||||
FUStatus Link();
|
||||
|
||||
/** [INTERNAL] Reads in the animation entity from a given COLLADA XML tree node.
|
||||
@param animationNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the animation. */
|
||||
virtual FUStatus LoadFromXML(xmlNode* animationNode);
|
||||
|
||||
/** [INTERNAL] Writes out the \<animation\> element to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the animation tree.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
|
||||
/** [INTERNAL] Retrieves the child source or sampler.
|
||||
This function should only be used by the FCDAnimationChannel class
|
||||
during the import of a COLLADA document.
|
||||
@param id The COLLADA id of a sampler or a source.
|
||||
@return The XML node tree for the sampler or the source. This pointer
|
||||
will be NULL if there are no child nodes for the given id. */
|
||||
xmlNode* FindChildById(const string& id);
|
||||
|
||||
/** [INTERNAL] Links a possible driver with the animation curves contained
|
||||
within the subtree of this animation element.
|
||||
This function is used during the import of a COLLADA document.
|
||||
@param animated The driver animated value.
|
||||
@return Whether any linkage was done. */
|
||||
bool LinkDriver(FCDAnimated* animated);
|
||||
};
|
||||
|
||||
#endif // _FCD_ANIMATION_H_
|
||||
@@ -1,292 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDAnimated.h"
|
||||
#include "FCDocument/FCDAnimation.h"
|
||||
#include "FCDocument/FCDAnimationChannel.h"
|
||||
#include "FCDocument/FCDAnimationCurve.h"
|
||||
#include "FCDocument/FCDAnimationMultiCurve.h"
|
||||
#include "FUtils/FUDaeEnum.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
#include "FUtils/FUStringConversion.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDAnimationChannel::FCDAnimationChannel(FCDocument* document, FCDAnimation* _parent) : FCDObject(document, "FCDAnimationChannel")
|
||||
{
|
||||
parent = _parent;
|
||||
}
|
||||
|
||||
FCDAnimationChannel::~FCDAnimationChannel()
|
||||
{
|
||||
CLEAR_POINTER_VECTOR(curves);
|
||||
parent = NULL;
|
||||
}
|
||||
|
||||
FCDAnimationCurve* FCDAnimationChannel::AddCurve()
|
||||
{
|
||||
FCDAnimationCurve* curve = new FCDAnimationCurve(GetDocument(), this);
|
||||
curves.push_back(curve);
|
||||
return curve;
|
||||
}
|
||||
|
||||
void FCDAnimationChannel::ReleaseCurve(FCDAnimationCurve* curve)
|
||||
{
|
||||
FCDAnimationCurveList::iterator itC = std::find(curves.begin(), curves.end(), curve);
|
||||
if (itC != curves.end())
|
||||
{
|
||||
// TODO: IMPLEMENT THIS. NEED RTTI and memory management. In other words, I need time!!! :(.
|
||||
// delete *itC;
|
||||
curves.erase(itC);
|
||||
}
|
||||
}
|
||||
|
||||
// Consider this animated as the curve's driver
|
||||
bool FCDAnimationChannel::LinkDriver(FCDAnimated* animated)
|
||||
{
|
||||
bool driver = !driverPointer.empty();
|
||||
driver = driver && animated->GetTargetPointer() == driverPointer;
|
||||
if (driver && driverQualifier >= 0 && (uint32) driverQualifier < animated->GetValueCount())
|
||||
{
|
||||
// Retrieve the value pointer for the driver
|
||||
for (FCDAnimationCurveList::iterator itC = curves.begin(); itC != curves.end(); ++itC)
|
||||
{
|
||||
(*itC)->SetDriver(animated->GetValue((uint32) driverQualifier));
|
||||
}
|
||||
}
|
||||
return driver;
|
||||
}
|
||||
FUStatus FCDAnimationChannel::CheckDriver()
|
||||
{
|
||||
FUStatus status;
|
||||
if (!driverPointer.empty() && !curves.empty() && curves.front()->GetDriver() == NULL)
|
||||
{
|
||||
status.Fail(FS("Unable to find animation curve driver: ") + TO_FSTRING(driverPointer) + FS(" for animation: ") + TO_FSTRING(parent->GetDaeId()));
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// Load a Collada animation channel from the XML document
|
||||
FUStatus FCDAnimationChannel::LoadFromXML(xmlNode* channelNode)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// Read the channel-specific ID
|
||||
string daeId = ReadNodeId(channelNode);
|
||||
string samplerId = ReadNodeSource(channelNode);
|
||||
ReadNodeTargetProperty(channelNode, targetPointer, targetQualifier);
|
||||
|
||||
xmlNode* samplerNode = parent->FindChildById(samplerId);
|
||||
if (samplerNode == NULL || !IsEquivalent(samplerNode->name, DAE_SAMPLER_ELEMENT))
|
||||
{
|
||||
return status.Fail(FS("Unable to find sampler node for channel node: ") + TO_FSTRING(daeId), channelNode->line);
|
||||
}
|
||||
|
||||
// Find and process the sources
|
||||
xmlNode* inputSource = NULL,* outputSource = NULL,* inTangentSource = NULL,* outTangentSource = NULL;
|
||||
xmlNode* outTangentWeightSource = NULL,* inTangentWeightSource = NULL,* interpolationSource = NULL;
|
||||
xmlNodeList samplerInputNodes;
|
||||
FindChildrenByType(samplerNode, DAE_INPUT_ELEMENT, samplerInputNodes);
|
||||
for (size_t i = 0; i < samplerInputNodes.size(); ++i) // Don't use iterator here because we are possibly appending source nodes in the loop
|
||||
{
|
||||
xmlNode* inputNode = samplerInputNodes[i];
|
||||
string sourceId = ReadNodeSource(inputNode);
|
||||
xmlNode* sourceNode = parent->FindChildById(sourceId);
|
||||
string sourceSemantic = ReadNodeSemantic(inputNode);
|
||||
|
||||
if (sourceSemantic == DAE_INPUT_ANIMATION_INPUT) inputSource = sourceNode;
|
||||
else if (sourceSemantic == DAE_OUTPUT_ANIMATION_INPUT) outputSource = sourceNode;
|
||||
else if (sourceSemantic == DAE_INTANGENT_ANIMATION_INPUT) inTangentSource = sourceNode;
|
||||
else if (sourceSemantic == DAE_OUTTANGENT_ANIMATION_INPUT) outTangentSource = sourceNode;
|
||||
else if (sourceSemantic == DAEMAYA_INTANGENTWEIGHT_ANIMATION_INPUT) inTangentWeightSource = sourceNode;
|
||||
else if (sourceSemantic == DAEMAYA_OUTTANGENTWEIGHT_ANIMATION_INPUT) outTangentWeightSource = sourceNode;
|
||||
else if (sourceSemantic == DAE_INTERPOLATION_ANIMATION_INPUT) interpolationSource = sourceNode;
|
||||
}
|
||||
if (inputSource == NULL || outputSource == NULL)
|
||||
{
|
||||
return status.Fail(FS("Missing INPUT or OUTPUT sources in animation channel: ") + TO_FSTRING(parent->GetDaeId()), samplerNode->line);
|
||||
}
|
||||
|
||||
// Calculate the number of curves that in contained by this channel
|
||||
xmlNode* outputAccessor = FindTechniqueAccessor(outputSource);
|
||||
string accessorStrideString = ReadNodeProperty(outputAccessor, DAE_STRIDE_ATTRIBUTE);
|
||||
uint32 curveCount = FUStringConversion::ToUInt32(accessorStrideString);
|
||||
if (curveCount == 0) curveCount = 1;
|
||||
|
||||
// Create the animation curves
|
||||
curves.reserve(curveCount);
|
||||
for (uint32 i = 0; i < curveCount; ++i) AddCurve();
|
||||
|
||||
// Read in the animation curves
|
||||
// The input keys are shared by all the curves
|
||||
ReadSource(inputSource, curves.front()->GetKeys());
|
||||
for (uint32 i = 1; i < curveCount; ++i) curves[i]->GetKeys() = curves.front()->GetKeys();
|
||||
|
||||
// Read in the interleaved outputs and tangents as floats
|
||||
#define READ_SOURCE_INTERLEAVED(sourceNode, curveArrayPtr) \
|
||||
if (sourceNode != NULL) { \
|
||||
vector<FloatList*> arrays(curveCount); \
|
||||
for (uint32 i = 0; i < curveCount; ++i) { \
|
||||
arrays[i] = &(curves[i]->curveArrayPtr()); } \
|
||||
ReadSourceInterleaved(sourceNode, arrays); \
|
||||
}
|
||||
|
||||
READ_SOURCE_INTERLEAVED(outputSource, GetKeyValues)
|
||||
READ_SOURCE_INTERLEAVED(inTangentSource, GetInTangents)
|
||||
READ_SOURCE_INTERLEAVED(outTangentSource, GetOutTangents)
|
||||
READ_SOURCE_INTERLEAVED(inTangentWeightSource, GetInTangentWeights)
|
||||
READ_SOURCE_INTERLEAVED(outTangentWeightSource, GetOutTangentWeights)
|
||||
#undef READ_SOURCE_INTERLEAVED
|
||||
|
||||
// Read in the interleaved interpolation values, parsing the tokens directly
|
||||
if (interpolationSource != NULL)
|
||||
{
|
||||
vector<UInt32List*> arrays(curveCount);
|
||||
for (uint32 i = 0; i < curveCount; ++i) arrays[i] = &(curves[i]->GetInterpolations());
|
||||
ReadSourceInterpolationInterleaved(interpolationSource, arrays);
|
||||
}
|
||||
|
||||
// Read in the pre/post-infinity type
|
||||
xmlNodeList mayaParameterNodes; StringList mayaParameterNames;
|
||||
xmlNode* mayaTechnique = FindTechnique(inputSource, DAEMAYA_MAYA_PROFILE);
|
||||
FindParameters(mayaTechnique, mayaParameterNames, mayaParameterNodes);
|
||||
size_t parameterCount = mayaParameterNodes.size();
|
||||
for (size_t i = 0; i < parameterCount; ++i)
|
||||
{
|
||||
xmlNode* parameterNode = mayaParameterNodes[i];
|
||||
const string& paramName = mayaParameterNames[i];
|
||||
const char* content = ReadNodeContentDirect(parameterNode);
|
||||
|
||||
if (paramName == DAEMAYA_PREINFINITY_PARAMETER || paramName == DAEMAYA_PREINFINITY_PARAMETER1_3)
|
||||
{
|
||||
for (FCDAnimationCurveList::iterator itC = curves.begin(); itC != curves.end(); ++itC)
|
||||
{
|
||||
(*itC)->SetPreInfinity(FUDaeInfinity::FromString(content));
|
||||
}
|
||||
}
|
||||
else if (paramName == DAEMAYA_POSTINFINITY_PARAMETER || paramName == DAEMAYA_POSTINFINITY_PARAMETER1_3)
|
||||
{
|
||||
for (FCDAnimationCurveList::iterator itC = curves.begin(); itC != curves.end(); ++itC)
|
||||
{
|
||||
(*itC)->SetPostInfinity(FUDaeInfinity::FromString(content));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Look for driven-key input target
|
||||
if (paramName == DAE_INPUT_ELEMENT)
|
||||
{
|
||||
string semantic = ReadNodeSemantic(parameterNode);
|
||||
if (semantic == DAEMAYA_DRIVER_INPUT)
|
||||
{
|
||||
string fullDriverTarget = ReadNodeSource(parameterNode);
|
||||
const char* driverTarget = FUDaeParser::SkipPound(fullDriverTarget);
|
||||
if (driverTarget != NULL)
|
||||
{
|
||||
string driverQualifierValue;
|
||||
FUDaeParser::SplitTarget(driverTarget, driverPointer, driverQualifierValue);
|
||||
driverQualifier = FUDaeParser::ReadTargetMatrixElement(driverQualifierValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ready the curves for usage/evaluation.
|
||||
for (uint32 i = 0; i < curveCount; ++i) curves[i]->Ready();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out the animation curves for an animation channel to a COLLADA document
|
||||
void FCDAnimationChannel::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
string baseId = CleanId(targetPointer);
|
||||
|
||||
// Check for curve merging
|
||||
uint32 realCurveCount = 0;
|
||||
FCDAnimationCurve* masterCurve = NULL;
|
||||
bool mergeCurves = true;
|
||||
for (FCDAnimationCurveList::const_iterator itC = curves.begin(); itC != curves.end(); ++itC)
|
||||
{
|
||||
FCDAnimationCurve* curve = (*itC);
|
||||
if ((*itC) != NULL)
|
||||
{
|
||||
++realCurveCount;
|
||||
if (masterCurve == NULL)
|
||||
{
|
||||
masterCurve = curve;
|
||||
if (masterCurve->GetDriver() != NULL) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check preliminary information, before verifying the individual keys: key count, infinity types and such..
|
||||
const FloatList& masterKeys = masterCurve->GetKeys();
|
||||
const FloatList& curveKeys = curve->GetKeys();
|
||||
size_t keyCount = masterKeys.size();
|
||||
mergeCurves &= curveKeys.size() == keyCount && curve->GetPostInfinity() == masterCurve->GetPostInfinity() && curve->GetPreInfinity() == masterCurve->GetPreInfinity();
|
||||
for (size_t k = 0; k < keyCount && mergeCurves; ++k)
|
||||
{
|
||||
mergeCurves = curveKeys[k] == masterKeys[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mergeCurves && realCurveCount > 1)
|
||||
{
|
||||
// HACK: Will need to merge the channel and animated classes.
|
||||
FloatList defaultValues(curves.size(), 0.0f);
|
||||
|
||||
// Merge and export the curves
|
||||
FCDAnimationMultiCurve* multiCurve = FCDAnimationMultiCurve::MergeCurves(curves, defaultValues);
|
||||
multiCurve->WriteSourceToXML(parentNode, baseId);
|
||||
multiCurve->WriteSamplerToXML(parentNode, baseId);
|
||||
multiCurve->WriteChannelToXML(parentNode, baseId, targetPointer);
|
||||
SAFE_DELETE(multiCurve);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Interlace the curve's sources, samplers and channels
|
||||
// Generate new ids for each of the curve's data sources, to avoid collision in special cases
|
||||
size_t curveCount = curves.size();
|
||||
StringList ids; ids.resize(curves.size());
|
||||
FUSStringBuilder curveId;
|
||||
for (size_t c = 0; c < curveCount; ++c)
|
||||
{
|
||||
if (curves[c] != NULL)
|
||||
{
|
||||
// Generate a valid id for this curve
|
||||
curveId.set(baseId);
|
||||
if (curves[c]->GetTargetElement() >= 0)
|
||||
{
|
||||
curveId.append('_'); curveId.append(curves[c]->GetTargetElement()); curveId.append('_');
|
||||
}
|
||||
curveId.append(curves[c]->GetTargetQualifier());
|
||||
ids[c] = CleanId(curveId.ToCharPtr());
|
||||
|
||||
// Write out the curve's sources
|
||||
curves[c]->WriteSourceToXML(parentNode, ids[c]);
|
||||
}
|
||||
}
|
||||
for (size_t c = 0; c < curveCount; ++c)
|
||||
{
|
||||
if (curves[c] != NULL) curves[c]->WriteSamplerToXML(parentNode, ids[c]);
|
||||
}
|
||||
for (size_t c = 0; c < curveCount; ++c)
|
||||
{
|
||||
if (curves[c] != NULL) curves[c]->WriteChannelToXML(parentNode, ids[c], targetPointer.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDAnimationChannel.h
|
||||
This file contains the FCDAnimationChannel class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_ANIMATION_CHANNEL_H_
|
||||
#define _FCD_ANIMATION_CHANNEL_H_
|
||||
|
||||
#include "FCDocument/FCDObject.h"
|
||||
|
||||
class FCDocument;
|
||||
class FCDAnimated;
|
||||
class FCDAnimation;
|
||||
class FCDAnimationCurve;
|
||||
|
||||
/** A dynamically-sized array of animation curves. */
|
||||
typedef vector<FCDAnimationCurve*> FCDAnimationCurveList;
|
||||
|
||||
/**
|
||||
A COLLADA animation channel.
|
||||
Each animation channel holds the animation curves for one animatable element,
|
||||
such as a single floating-point value, a 3D vector or a matrix.
|
||||
|
||||
@see FCDAnimated
|
||||
@ingroup FCDocument
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDAnimationChannel : public FCDObject
|
||||
{
|
||||
private:
|
||||
FCDAnimation* parent;
|
||||
|
||||
// Channel target
|
||||
string targetPointer;
|
||||
string targetQualifier;
|
||||
|
||||
// Maya-specific: the driver for this/these curves
|
||||
string driverPointer;
|
||||
int32 driverQualifier;
|
||||
|
||||
FCDAnimationCurveList curves;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, call the FCDAnimation::AddChannel function.
|
||||
@param document The COLLADA document that owns the animation channel.
|
||||
@param parent The animation sub-tree that contains the animation channel. */
|
||||
FCDAnimationChannel(FCDocument* document, FCDAnimation* parent);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, call the FCDAnimation::ReleaseChannel function. */
|
||||
virtual ~FCDAnimationChannel();
|
||||
|
||||
/** Retrieves the animation sub-tree that contains the animation channel.
|
||||
@return The parent animation sub-tree. */
|
||||
FCDAnimation* GetParent() { return parent; }
|
||||
const FCDAnimation* GetParent() const { return parent; } /**< See above. */
|
||||
|
||||
/** Retrieves the list of animation curves contained within the channel.
|
||||
@return The list of animation curves. */
|
||||
const FCDAnimationCurveList& GetCurves() const { return curves; }
|
||||
|
||||
/** Retrieves the number of animation curves contained within the channel.
|
||||
@return The number of animation curves. */
|
||||
size_t GetCurveCount() const { return curves.size(); }
|
||||
|
||||
/** Retrieves an animation curve contained within the channel.
|
||||
@param index The index of the animation curve.
|
||||
@return The animation curve at the given index. This pointer will be NULL
|
||||
if the index is out-of-bounds. */
|
||||
FCDAnimationCurve* GetCurve(size_t index) { FUAssert(index < GetCurveCount(), return NULL); return curves.at(index); }
|
||||
const FCDAnimationCurve* GetCurve(size_t index) const { FUAssert(index < GetCurveCount(), return NULL); return curves.at(index); } /**< See above. */
|
||||
|
||||
/** Adds a new animation curve to this animation channel.
|
||||
@return The new animation curve. */
|
||||
FCDAnimationCurve* AddCurve();
|
||||
|
||||
/** Releases an animation curve contained within this channel.
|
||||
@todo This function is not yet implemented, as it requires
|
||||
a lot more memory management than FCollada currently does.
|
||||
@param curve The animation curve to release. */
|
||||
void ReleaseCurve(FCDAnimationCurve* curve);
|
||||
|
||||
/** [INTERNAL] Retrieves the target pointer prefix for this animation channel.
|
||||
This function is used during the import of a COLLADA document to match the
|
||||
target pointer prefixes with the animated elements.
|
||||
@return The target pointer prefix. */
|
||||
const string& GetTargetPointer() const { return targetPointer; }
|
||||
|
||||
/** [INTERNAL] Retrieves the target qualifier for this animation channel.
|
||||
This function is used during the import of a COLLADA document.
|
||||
Where there is a target qualifier, there should be only one curve contained by the channel.
|
||||
@return The target qualifier. This value may be the empty string if the channel
|
||||
targets all the values targeted by the target pointer prefix. */
|
||||
const string& GetTargetQualifier() const { return targetQualifier; }
|
||||
|
||||
/** [INTERNAL] Enforces the tarrget pointer prefix for the animation channel.
|
||||
This function is used during the export of a COLLADA document.
|
||||
@param p The new target pointer prefix. */
|
||||
void SetTargetPointer(const string& p) { targetPointer = p; }
|
||||
|
||||
/** [INTERNAL] Considers the given animated element as the driver for this animation channel.
|
||||
@param animated An animated element.
|
||||
@return Whether the animated element is in fact the driver for the animation channel. */
|
||||
bool LinkDriver(FCDAnimated* animated);
|
||||
|
||||
/** [INTERNAL] Verifies that if a driver is used by this channel, then it was found during
|
||||
the import of the animated elements.
|
||||
@return The status of the verification. */
|
||||
FUStatus CheckDriver();
|
||||
|
||||
/** [INTERNAL] Reads in the animation channel from a given COLLADA XML tree node.
|
||||
@param channelNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the animation channel. */
|
||||
FUStatus LoadFromXML(xmlNode* channelNode);
|
||||
|
||||
/** [INTERNAL] Writes out the animation channel to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the animation channel.
|
||||
@return The created element XML tree node. */
|
||||
void WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif // _FCD_ANIMATION_CHANNEL_H_
|
||||
@@ -1,139 +0,0 @@
|
||||
/*
|
||||
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/FCDAnimation.h"
|
||||
#include "FCDocument/FCDAnimationChannel.h"
|
||||
#include "FCDocument/FCDAnimationClip.h"
|
||||
#include "FCDocument/FCDAnimationCurve.h"
|
||||
#include "FCDocument/FCDAnimated.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDAnimationClip::FCDAnimationClip(FCDocument* document) : FCDEntity(document, "AnimationClip")
|
||||
{
|
||||
start = end = 0.0f;
|
||||
}
|
||||
|
||||
FCDAnimationClip::~FCDAnimationClip()
|
||||
{
|
||||
curves.clear();
|
||||
}
|
||||
|
||||
FCDAnimationClip* FCDAnimationClip::Clone()
|
||||
{
|
||||
FCDAnimationClip* clone = new FCDAnimationClip(GetDocument());
|
||||
FCDEntity::Clone(clone);
|
||||
|
||||
for(FCDAnimationCurveList::iterator it = curves.begin(); it != curves.end(); ++it)
|
||||
{
|
||||
curves.push_back((*it)->Clone());
|
||||
}
|
||||
|
||||
clone->start = start;
|
||||
clone->end = end;
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
FUStatus FCDAnimationClip::LoadFromXML(xmlNode* clipNode)
|
||||
{
|
||||
FUStatus status = FCDEntity::LoadFromXML(clipNode);
|
||||
if (!status) return status;
|
||||
if (!IsEquivalent(clipNode->name, DAE_ANIMCLIP_ELEMENT))
|
||||
{
|
||||
return status.Warning(FS("Unknown element in animation clip library."), clipNode->line);
|
||||
}
|
||||
|
||||
// Read in and verify the clip's time/input bounds
|
||||
start = FUStringConversion::ToFloat(ReadNodeProperty(clipNode, DAE_START_ATTRIBUTE));
|
||||
end = FUStringConversion::ToFloat(ReadNodeProperty(clipNode, DAE_END_ATTRIBUTE));
|
||||
if (end - start < FLT_TOLERANCE)
|
||||
{
|
||||
status.Warning(FS("Invalid start/end pair for animation clip: ") + TO_FSTRING(GetDaeId()), clipNode->line);
|
||||
}
|
||||
|
||||
// Read in the <input> elements and segment the corresponding animation curves
|
||||
xmlNodeList inputNodes;
|
||||
FindChildrenByType(clipNode, DAE_INSTANCE_ANIMATION_ELEMENT, inputNodes);
|
||||
for (xmlNodeList::iterator itI = inputNodes.begin(); itI != inputNodes.end(); ++itI)
|
||||
{
|
||||
xmlNode* inputNode = (*itI);
|
||||
|
||||
// Retrieve the animation for this input
|
||||
FUUri animationId = ReadNodeUrl(inputNode);
|
||||
if (animationId.suffix.empty() || !animationId.prefix.empty())
|
||||
{
|
||||
return status.Fail(FS("Invalid animation instantiation for animation clip: ") + TO_FSTRING(GetDaeId()), inputNode->line);
|
||||
}
|
||||
FCDAnimation* animation = GetDocument()->FindAnimation(animationId.suffix);
|
||||
if (animation == NULL) continue;
|
||||
|
||||
// Retrieve all the curves created under this animation node
|
||||
FCDAnimationCurveList animationCurves;
|
||||
animation->GetCurves(animationCurves);
|
||||
if (animationCurves.empty())
|
||||
{
|
||||
status.Warning(FS("No curves instantiated by animation '") + TO_FSTRING(animationId.suffix) + FS("' for animation clip: ") + TO_FSTRING(GetDaeId()), inputNode->line);
|
||||
}
|
||||
|
||||
for (FCDAnimationCurveList::iterator itC = animationCurves.begin(); itC != animationCurves.end(); ++itC)
|
||||
{
|
||||
// Keep only newly listed curves
|
||||
FCDAnimationCurve* curve = *itC;
|
||||
FCDAnimationCurveList::iterator itF = std::find(curves.begin(), curves.end(), curve);
|
||||
if (itF == curves.end()) continue;
|
||||
|
||||
curve->RegisterAnimationClip(this);
|
||||
curves.push_back(curve);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for an empty clip
|
||||
if (curves.empty())
|
||||
{
|
||||
status.Warning(FS("Empty animation clip :") + TO_FSTRING(GetDaeId()), clipNode->line);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out the COLLADA animations to the document
|
||||
xmlNode* FCDAnimationClip::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
// Create the <clip> element and write out its start/end information.
|
||||
xmlNode* clipNode = FCDEntity::WriteToEntityXML(parentNode, DAE_ANIMCLIP_ELEMENT);
|
||||
AddAttribute(clipNode, DAE_START_ATTRIBUTE, start);
|
||||
AddAttribute(clipNode, DAE_END_ATTRIBUTE, end);
|
||||
|
||||
// Build a list of the animations to instantiate
|
||||
// from the list of curves for this clip
|
||||
typedef vector<const FCDAnimation*> FCDAnimationConstList;
|
||||
FCDAnimationConstList animations;
|
||||
for (FCDAnimationCurveList::const_iterator itC = curves.begin(); itC != curves.end(); ++itC)
|
||||
{
|
||||
const FCDAnimationChannel* channel = (*itC)->GetParent();
|
||||
if (channel == NULL) continue;
|
||||
const FCDAnimation* animation = channel->GetParent();
|
||||
if (std::find(animations.begin(), animations.end(), animation) == animations.end())
|
||||
{
|
||||
animations.push_back(animation);
|
||||
}
|
||||
}
|
||||
|
||||
// Instantiate all the animations
|
||||
for (FCDAnimationConstList::iterator itA = animations.begin(); itA != animations.end(); ++itA)
|
||||
{
|
||||
xmlNode* instanceNode = AddChild(clipNode, DAE_INSTANCE_ANIMATION_ELEMENT);
|
||||
AddAttribute(instanceNode, DAE_URL_ATTRIBUTE, string("#") + (*itA)->GetDaeId());
|
||||
}
|
||||
|
||||
FCDEntity::WriteToExtraXML(clipNode);
|
||||
return clipNode;
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#ifndef _FCD_ANIMATION_CLIP_H_
|
||||
#define _FCD_ANIMATION_CLIP_H_
|
||||
|
||||
class FCDocument;
|
||||
class FCDAnimationCurve;
|
||||
|
||||
typedef vector<FCDAnimationCurve*> FCDAnimationCurveList;
|
||||
|
||||
#include "FCDocument/FCDEntity.h"
|
||||
#include "FCDocument/FCDObject.h"
|
||||
|
||||
class FCOLLADA_EXPORT FCDAnimationClip : public FCDEntity
|
||||
{
|
||||
private:
|
||||
FCDAnimationCurveList curves;
|
||||
float start, end;
|
||||
|
||||
public:
|
||||
FCDAnimationClip(FCDocument* document);
|
||||
virtual ~FCDAnimationClip();
|
||||
|
||||
FCDAnimationClip* Clone();
|
||||
|
||||
// FCDEntity overrides
|
||||
virtual Type GetType() const { return ANIMATION_CLIP; }
|
||||
|
||||
// Accessors
|
||||
FCDAnimationCurveList& GetClipCurves() { return curves; }
|
||||
const FCDAnimationCurveList& GetClipCurves() const { return curves; }
|
||||
float GetStart() const { return start; }
|
||||
float GetEnd() const { return end; }
|
||||
|
||||
// Load a Collada animation node from the XML document
|
||||
virtual FUStatus LoadFromXML(xmlNode* clipNode);
|
||||
|
||||
// Write out the COLLADA animations to the document
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif // _FCD_ANIMATION_CLIP_H_
|
||||
|
||||
@@ -1,295 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDAnimationCurve.h"
|
||||
#include "FCDocument/FCDAnimationClip.h"
|
||||
#include "FUtils/FUDaeEnum.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDAnimationCurve::FCDAnimationCurve(FCDocument* document, FCDAnimationChannel* _parent)
|
||||
: FCDObject(document, "FCDAnimationCurve"),
|
||||
parent(_parent),
|
||||
targetElement(-1),
|
||||
preInfinity(FUDaeInfinity::CONSTANT),
|
||||
postInfinity(FUDaeInfinity::CONSTANT),
|
||||
inputDriver(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
FCDAnimationCurve::~FCDAnimationCurve()
|
||||
{
|
||||
inputDriver = NULL;
|
||||
parent = NULL;
|
||||
clips.clear();
|
||||
}
|
||||
|
||||
FCDAnimationCurve* FCDAnimationCurve::Clone()
|
||||
{
|
||||
FCDAnimationCurve* clone = new FCDAnimationCurve(GetDocument(), parent);
|
||||
|
||||
clone->SetTargetElement(targetElement);
|
||||
string q;
|
||||
q.assign(targetQualifier);
|
||||
clone->SetTargetQualifier(q);
|
||||
|
||||
clone->keys = keys;
|
||||
clone->keyValues = keyValues;
|
||||
clone->inTangents = inTangents;
|
||||
clone->outTangents = outTangents;
|
||||
clone->inTangentWeights = inTangentWeights;
|
||||
clone->outTangentWeights = outTangentWeights;
|
||||
clone->isWeightedCurve = isWeightedCurve;
|
||||
clone->preInfinity = preInfinity;
|
||||
clone->postInfinity = postInfinity;
|
||||
|
||||
clone->inputDriver = inputDriver;
|
||||
|
||||
clone->SetDriverPointer(driverPointer);
|
||||
|
||||
clone->interpolations = interpolations;
|
||||
|
||||
// Animation clips that depend on this curve
|
||||
for(FCDAnimationClipList::iterator it = clips.begin(); it != clips.end(); ++it)
|
||||
{
|
||||
clone->clips.push_back((*it)->Clone());
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Prepare a curve for evaluation
|
||||
void FCDAnimationCurve::Ready()
|
||||
{
|
||||
if (keys.empty()) return;
|
||||
|
||||
if (inTangents.empty() || outTangents.empty())
|
||||
{
|
||||
// Calculate the bezier tangents
|
||||
inTangents.resize(keys.size(), 0.0f);
|
||||
outTangents.resize(keys.size(), 0.0f);
|
||||
|
||||
if (keys.size() > 1)
|
||||
{
|
||||
for (size_t i = 0; i < keys.size(); ++i)
|
||||
{
|
||||
float previousKeySpan = (i > 0) ? keys[i] - keys[i - 1] : keys[i + 1] - keys[i];
|
||||
float nextKeySpan = (i < keys.size() - 1) ? keys[i + 1] - keys[i] : previousKeySpan;
|
||||
float currentKeyValue = keyValues[i];
|
||||
float previousKeyValue = (i > 0) ? keyValues[i - 1] : currentKeyValue;
|
||||
float nextKeyValue = (i < keys.size() - 1) ? keyValues[i + 1] : currentKeyValue;
|
||||
float slope = (nextKeyValue - previousKeyValue) / (nextKeySpan + previousKeySpan);
|
||||
inTangents[i] = previousKeySpan / 3.0f * slope;
|
||||
outTangents[i] = nextKeySpan / 3.0f * slope;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (interpolations.empty())
|
||||
{
|
||||
// Fill in the array with the default interpolation type
|
||||
interpolations.resize(keys.size(), FUDaeInterpolation::DEFAULT);
|
||||
}
|
||||
|
||||
isWeightedCurve = !inTangentWeights.empty() && !outTangentWeights.empty();
|
||||
}
|
||||
|
||||
// Main workhorse for the animation system:
|
||||
// Evaluates the curve for a given input
|
||||
float FCDAnimationCurve::Evaluate(float input) const
|
||||
{
|
||||
if (keys.size() == 1) return keyValues.front();
|
||||
|
||||
float outputStart = keyValues.front();
|
||||
float outputEnd = keyValues.back();
|
||||
float inputStart = keys.front();
|
||||
float inputEnd = keys.back();
|
||||
float inputSpan = inputEnd - inputStart;
|
||||
|
||||
// Account for pre-infinity mode
|
||||
float outputOffset = 0.0f;
|
||||
if (input <= inputStart)
|
||||
{
|
||||
switch (preInfinity)
|
||||
{
|
||||
case FUDaeInfinity::CONSTANT: return outputStart;
|
||||
case FUDaeInfinity::LINEAR: return outputStart + (input - inputStart) * (keyValues[1] - outputStart) / (keys[1] - inputStart);
|
||||
case FUDaeInfinity::CYCLE: { float cycleCount = ceilf((inputStart - input) / inputSpan); input += cycleCount * inputSpan; break; }
|
||||
case FUDaeInfinity::CYCLE_RELATIVE: { float cycleCount = ceilf((inputStart - input) / inputSpan); input += cycleCount * inputSpan; outputOffset -= cycleCount * (outputEnd - outputStart); break; }
|
||||
case FUDaeInfinity::OSCILLATE: { float cycleCount = ceilf((inputStart - input) / (2.0f * inputSpan)); input += cycleCount * 2.0f * inputSpan; input = inputEnd - fabsf(input - inputEnd); break; }
|
||||
case FUDaeInfinity::UNKNOWN: default: return outputStart;
|
||||
}
|
||||
}
|
||||
|
||||
// Account for post-infinity mode
|
||||
else if (input >= inputEnd)
|
||||
{
|
||||
switch (postInfinity)
|
||||
{
|
||||
case FUDaeInfinity::CONSTANT: return outputEnd;
|
||||
case FUDaeInfinity::LINEAR: return outputEnd + (input - inputEnd) * (keyValues[keys.size() - 2] - outputEnd) / (keys[keys.size() - 2] - inputEnd);
|
||||
case FUDaeInfinity::CYCLE: { float cycleCount = ceilf((input - inputEnd) / inputSpan); input -= cycleCount * inputSpan; break; }
|
||||
case FUDaeInfinity::CYCLE_RELATIVE: { float cycleCount = ceilf((input - inputEnd) / inputSpan); input -= cycleCount * inputSpan; outputOffset += cycleCount * (outputEnd - outputStart); break; }
|
||||
case FUDaeInfinity::OSCILLATE: { float cycleCount = ceilf((input - inputEnd) / (2.0f * inputSpan)); input -= cycleCount * 2.0f * inputSpan; input = inputStart + fabsf(input - inputStart); break; }
|
||||
case FUDaeInfinity::UNKNOWN: default: return outputEnd;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the current interval
|
||||
uint32 index = 0;
|
||||
FloatList::const_iterator it;
|
||||
for (it = keys.begin(); it != keys.end(); ++it, ++index)
|
||||
{
|
||||
if ((*it) > input) break;
|
||||
}
|
||||
|
||||
// Get the keys and values for this interval
|
||||
float endKey = *it;
|
||||
float startKey = *(it - 1);
|
||||
float endValue = keyValues[index];
|
||||
float startValue = keyValues[index - 1];
|
||||
float output;
|
||||
|
||||
// Interpolate the output.
|
||||
// Similar code is found in FCDAnimationMultiCurve.cpp. If you update this, update the other one too.
|
||||
uint32 interpolation = interpolations.empty() ? ((uint32) FUDaeInterpolation::DEFAULT) : interpolations[index];
|
||||
switch (FUDaeInterpolation::Interpolation(interpolation))
|
||||
{
|
||||
case FUDaeInterpolation::LINEAR:
|
||||
output = (input - startKey) / (endKey - startKey) * (endValue - startValue) + startValue;
|
||||
break;
|
||||
|
||||
case FUDaeInterpolation::BEZIER: {
|
||||
float t = (input - startKey) / (endKey - startKey);
|
||||
float bValue = startValue + outTangents[index - 1];
|
||||
float cValue = endValue - inTangents[index];
|
||||
float ti = 1.0f - t;
|
||||
output = startValue * ti * ti * ti + 3.0f * bValue * ti * ti * t + 3.0f * cValue * ti * t * t + endValue * t * t * t;
|
||||
break; }
|
||||
|
||||
case FUDaeInterpolation::STEP:
|
||||
case FUDaeInterpolation::UNKNOWN:
|
||||
default:
|
||||
output = startValue;
|
||||
break;
|
||||
}
|
||||
|
||||
return outputOffset + output;
|
||||
}
|
||||
|
||||
// Apply a conversion function on the key values and tangents
|
||||
void FCDAnimationCurve::ConvertValues(FCDConversionFunction valueConversion, FCDConversionFunction tangentConversion)
|
||||
{
|
||||
size_t keyCount = keys.size();
|
||||
if (valueConversion != NULL)
|
||||
{
|
||||
for (size_t k = 0; k < keyCount; k++)
|
||||
{
|
||||
keyValues[k] = (*valueConversion)(keyValues[k]);
|
||||
}
|
||||
}
|
||||
if (tangentConversion != NULL)
|
||||
{
|
||||
for (size_t k = 0; k < keyCount; k++)
|
||||
{
|
||||
inTangents[k] = (*tangentConversion)(inTangents[k]);
|
||||
outTangents[k] = (*tangentConversion)(outTangents[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply a conversion function on the key times and tangent weights
|
||||
void FCDAnimationCurve::ConvertInputs(FCDConversionFunction timeConversion, FCDConversionFunction tangentWeightConversion)
|
||||
{
|
||||
size_t keyCount = keys.size();
|
||||
if (timeConversion != NULL)
|
||||
{
|
||||
for (size_t k = 0; k < keyCount; k++)
|
||||
{
|
||||
keys[k] = (*timeConversion)(keys[k]);
|
||||
}
|
||||
}
|
||||
if (tangentWeightConversion != NULL)
|
||||
{
|
||||
for (size_t k = 0; k < keyCount; k++)
|
||||
{
|
||||
inTangentWeights[k] = (*tangentWeightConversion)(inTangentWeights[k]);
|
||||
outTangentWeights[k] = (*tangentWeightConversion)(outTangentWeights[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write out the specific animation elements to the COLLADA xml tree node
|
||||
void FCDAnimationCurve::WriteSourceToXML(xmlNode* parentNode, const string& baseId) const
|
||||
{
|
||||
const char* parameter = targetQualifier.c_str();
|
||||
if (*parameter == '.') ++parameter;
|
||||
|
||||
xmlNode* sourceNode = AddSourceFloat(parentNode, baseId + "-input", keys, "TIME");
|
||||
AddSourceFloat(parentNode, baseId + "-output", keyValues, parameter);
|
||||
AddSourceFloat(parentNode, baseId + "-intangents", inTangents, parameter);
|
||||
AddSourceFloat(parentNode, baseId + "-outtangents", outTangents, parameter);
|
||||
if (isWeightedCurve && !inTangentWeights.empty())
|
||||
{
|
||||
AddSourceFloat(parentNode, baseId + "-intangents_weights", inTangents, parameter);
|
||||
AddSourceFloat(parentNode, baseId + "-outtangents_weights", outTangents, parameter);
|
||||
}
|
||||
AddSourceInterpolation(parentNode, baseId + "-interpolations", *(FUDaeInterpolationList*)&interpolations);
|
||||
|
||||
// Export the infinity parameters
|
||||
xmlNode* mayaTechnique = AddTechniqueChild(sourceNode, DAEMAYA_MAYA_PROFILE);
|
||||
string infinityType = FUDaeInfinity::ToString(preInfinity);
|
||||
AddChild(mayaTechnique, DAEMAYA_PREINFINITY_PARAMETER, infinityType);
|
||||
infinityType = FUDaeInfinity::ToString(postInfinity);
|
||||
AddChild(mayaTechnique, DAEMAYA_POSTINFINITY_PARAMETER, infinityType);
|
||||
}
|
||||
|
||||
xmlNode* FCDAnimationCurve::WriteSamplerToXML(xmlNode* parentNode, const string& baseId) const
|
||||
{
|
||||
xmlNode* samplerNode = AddChild(parentNode, DAE_SAMPLER_ELEMENT);
|
||||
AddAttribute(samplerNode, DAE_ID_ATTRIBUTE, baseId + "-sampler");
|
||||
|
||||
// Add the sampler inputs
|
||||
AddInput(samplerNode, baseId + "-input", DAE_INPUT_ANIMATION_INPUT);
|
||||
AddInput(samplerNode, baseId + "-output", DAE_OUTPUT_ANIMATION_INPUT);
|
||||
AddInput(samplerNode, baseId + "-intangents", DAE_INTANGENT_ANIMATION_INPUT);
|
||||
AddInput(samplerNode, baseId + "-outtangents", DAE_OUTTANGENT_ANIMATION_INPUT);
|
||||
if (isWeightedCurve && !inTangentWeights.empty())
|
||||
{
|
||||
AddInput(samplerNode, baseId + "-intangents_weights", DAEMAYA_INTANGENTWEIGHT_ANIMATION_INPUT);
|
||||
AddInput(samplerNode, baseId + "-outtangents_weights", DAEMAYA_OUTTANGENTWEIGHT_ANIMATION_INPUT);
|
||||
}
|
||||
AddInput(samplerNode, baseId + "-interpolations", DAE_INTERPOLATION_ANIMATION_INPUT);
|
||||
|
||||
// Add the driver input
|
||||
if (inputDriver != NULL)
|
||||
{
|
||||
AddInput(samplerNode, driverPointer, DAEMAYA_DRIVER_INPUT);
|
||||
}
|
||||
|
||||
return samplerNode;
|
||||
}
|
||||
|
||||
xmlNode* FCDAnimationCurve::WriteChannelToXML(xmlNode* parentNode, const string& baseId, const char* targetPointer) const
|
||||
{
|
||||
xmlNode* channelNode = AddChild(parentNode, DAE_CHANNEL_ELEMENT);
|
||||
AddAttribute(channelNode, DAE_SOURCE_ATTRIBUTE, baseId + "-sampler");
|
||||
|
||||
// Generate and export the channel target
|
||||
globalSBuilder.set(targetPointer);
|
||||
if (targetElement >= 0)
|
||||
{
|
||||
globalSBuilder.append('('); globalSBuilder.append(targetElement); globalSBuilder.append(')');
|
||||
}
|
||||
globalSBuilder.append(targetQualifier);
|
||||
AddAttribute(channelNode, DAE_TARGET_ATTRIBUTE, globalSBuilder);
|
||||
return channelNode;
|
||||
}
|
||||
@@ -1,262 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDAnimationCurve.h
|
||||
This file contains the FCDAnimationCurve class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_ANIMATION_CURVE_H_
|
||||
#define _FCD_ANIMATION_CURVE_H_
|
||||
|
||||
#include "FUtils/FUDaeEnum.h"
|
||||
#include "FCDocument/FCDObject.h"
|
||||
|
||||
class FCDAnimationClip;
|
||||
class FCDAnimationChannel;
|
||||
|
||||
typedef vector<FCDAnimationClip*> FCDAnimationClipList; /**< A dynamically-sized array of animation clips. */
|
||||
typedef float (*FCDConversionFunction)(float v); /**< A simple conversion function. */
|
||||
|
||||
/**
|
||||
A COLLADA single-dimensional animation curve.
|
||||
An animation curve holds the keyframes necessary
|
||||
to animate an animatable floating-point value.
|
||||
|
||||
There are multiple interpolation mechanisms supported by COLLADA.
|
||||
FCollada supports the CONSTANT, LINEAR and BEZIER interpolations.
|
||||
|
||||
@see FUDaeInterpolation FUDaeInfinity
|
||||
@ingroup FCDocument
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDAnimationCurve : public FCDObject
|
||||
{
|
||||
private:
|
||||
FCDAnimationChannel* parent;
|
||||
|
||||
// Targeting information
|
||||
int32 targetElement;
|
||||
string targetQualifier;
|
||||
|
||||
// Input information
|
||||
FloatList keys, keyValues;
|
||||
FloatList inTangents, outTangents;
|
||||
FloatList inTangentWeights, outTangentWeights;
|
||||
bool isWeightedCurve;
|
||||
FUDaeInfinity::Infinity preInfinity;
|
||||
FUDaeInfinity::Infinity postInfinity;
|
||||
|
||||
// Driver information
|
||||
const float* inputDriver;
|
||||
string driverPointer;
|
||||
|
||||
// The interpolation values follow the FUDaeInterpolation enum (FUDaeEnum.h)
|
||||
UInt32List interpolations;
|
||||
|
||||
// Animation clips that depend on this curve
|
||||
FCDAnimationClipList clips;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDAnimationChannel::AddCurve function.
|
||||
You should also attach the new curve to an animated
|
||||
element using the FCDAnimated::SetCurve function.
|
||||
@param document The COLLADA document that owns the animation curve.
|
||||
@param parent The animation channel that contains the curve. */
|
||||
FCDAnimationCurve(FCDocument* document, FCDAnimationChannel* parent);
|
||||
|
||||
/** Destructor: do not release directly.
|
||||
Instead, use the FCDAnimationChannel::ReleaseCurve function. */
|
||||
virtual ~FCDAnimationCurve();
|
||||
|
||||
/** Retrieves the animation channel that contains this animation curve.
|
||||
@return The parent animation channel. */
|
||||
inline FCDAnimationChannel* GetParent() { return parent; }
|
||||
inline const FCDAnimationChannel* GetParent() const { return parent; } /**< See above. */
|
||||
|
||||
/** Retrieves the list of key inputs for the animation curve.
|
||||
@return The list of key inputs. */
|
||||
inline FloatList& GetKeys() { return keys; }
|
||||
inline const FloatList& GetKeys() const { return keys; } /**< See above. */
|
||||
|
||||
/** Retrieves the list of key outputs for the animation curve.
|
||||
@return The list of key outputs. */
|
||||
inline FloatList& GetKeyValues() { return keyValues; }
|
||||
inline const FloatList& GetKeyValues() const { return keyValues; } /**< See above. */
|
||||
|
||||
/** Retrieves the list of interpolation type for the segments of the animation curve.
|
||||
There is always one interpolation type for each key in the curve. The interpolation type
|
||||
of a segment of the curve is set at the key at which begins the segment.
|
||||
@see FUDaeInterpolation
|
||||
@return The list of interpolation types. */
|
||||
inline UInt32List& GetInterpolations() { return interpolations; }
|
||||
inline const UInt32List& GetInterpolations() const { return interpolations; } /**< See above. */
|
||||
|
||||
/** Retrieves the list of key in-tangent values for the animation curve.
|
||||
This list has data only for curves that include segments with the bezier interpolation.
|
||||
@return The list of in-tangent values. */
|
||||
inline FloatList& GetInTangents() { return inTangents; }
|
||||
inline const FloatList& GetInTangents() const { return inTangents; } /**< See above. */
|
||||
|
||||
/** Retrieves the list of key out-tangent values for the animation curve.
|
||||
This list has data only for curves that include segments with the bezier interpolation.
|
||||
@return The list of out-tangent values. */
|
||||
inline FloatList& GetOutTangents() { return outTangents; }
|
||||
inline const FloatList& GetOutTangents() const { return outTangents; } /**< See above. */
|
||||
|
||||
/** Retrieves the list of key in-tangent weights for the animation curve.
|
||||
This list has data only for curves that are weighted
|
||||
and include segments with the bezier interpolation.
|
||||
@see IsWeightedCurve
|
||||
@return The list of in-tangent weights. */
|
||||
inline FloatList& GetInTangentWeights() { return inTangentWeights; }
|
||||
inline const FloatList& GetInTangentWeights() const { return inTangentWeights; } /**< See above. */
|
||||
|
||||
/** Retrieves the list of key out-tangent weights for the animation curve.
|
||||
This list has data only for curves that are weighted
|
||||
and include segments with the bezier interpolation.
|
||||
@see IsWeightedCurve
|
||||
@return The list of out-tangent weights. */
|
||||
inline FloatList& GetOutTangentWeights() { return outTangentWeights; }
|
||||
inline const FloatList& GetOutTangentWeights() const { return outTangentWeights; } /**< See above. */
|
||||
|
||||
/** Retrieves whether this curve has weighted tangents. Tangent weights
|
||||
give you access to 2D tangents by providing the length of the tangent.
|
||||
@return Whether this curve has weighted tangents. */
|
||||
inline bool IsWeightedCurve() const { return isWeightedCurve; }
|
||||
|
||||
/** Sets whether this curve has weighted tangents. Tangent weights
|
||||
give you access to 2D tangents by providing the length of the tangent.
|
||||
@param _isWeightedCurve Whether this curve has weighted tangents. */
|
||||
inline void SetWeightedCurveFlag(bool _isWeightedCurve) { isWeightedCurve = _isWeightedCurve; }
|
||||
|
||||
/** Retrieves the type of behavior for the curve if the input value is
|
||||
outside the input interval defined by the curve keys and less than any key input value.
|
||||
@see FUDaeInfinity
|
||||
@return The pre-infinity behavior of the curve. */
|
||||
inline FUDaeInfinity::Infinity GetPreInfinity() const { return preInfinity; }
|
||||
|
||||
/** Sets the behavior of the curve if the input value is
|
||||
outside the input interval defined by the curve keys and less than any key input value.
|
||||
@see FUDaeInfinity
|
||||
@param infinity The pre-infinity behavior of the curve. */
|
||||
inline void SetPreInfinity(FUDaeInfinity::Infinity infinity) { preInfinity = infinity; }
|
||||
|
||||
/** Retrieves the type of behavior for the curve if the input value is
|
||||
outside the input interval defined by the curve keys and greater than any key input value.
|
||||
@see FUDaeInfinity
|
||||
@return The post-infinity behavior of the curve. */
|
||||
inline FUDaeInfinity::Infinity GetPostInfinity() const { return postInfinity; }
|
||||
|
||||
/** Sets the behavior of the curve if the input value is
|
||||
outside the input interval defined by the curve keys and greater than any key input value.
|
||||
@see FUDaeInfinity
|
||||
@param infinity The post-infinity behavior of the curve. */
|
||||
inline void SetPostInfinity(FUDaeInfinity::Infinity infinity) { postInfinity = infinity; }
|
||||
|
||||
/** Retrieves the value pointer that drives this animation curve.
|
||||
@return The driver value pointer. This pointer will be NULL to indicate
|
||||
that time drives the animation curve. */
|
||||
inline const float* GetDriver() const { return inputDriver; }
|
||||
|
||||
/** Sets the value pointer that drives the animation curve.
|
||||
@param driver The driver value pointer. Set this pointer to NULL
|
||||
to indicate that time drives the animation curve. */
|
||||
inline void SetDriver(const float* driver) { inputDriver = driver; }
|
||||
|
||||
/** Retrieves the list of animation clips that use this animation curve.
|
||||
@return The list of animation clips. */
|
||||
inline FCDAnimationClipList& GetClips() { return clips; }
|
||||
inline const FCDAnimationClipList& GetClips() const { return clips; } /**< See above. */
|
||||
|
||||
/** Readies this curve for evaluation.
|
||||
This will create the tangents and the tangent weights, if necessary. */
|
||||
void Ready();
|
||||
|
||||
/** Clones the animation curve.
|
||||
@return The cloned animation curve. */
|
||||
FCDAnimationCurve* Clone();
|
||||
|
||||
/** Applies a conversion function to the keys output values of the animation curve.
|
||||
@param valueConversion The conversion function to use on the key outputs.
|
||||
@param tangentConversion The conversion function to use on the key tangents. */
|
||||
void ConvertValues(FCDConversionFunction valueConversion, FCDConversionFunction tangentConversion);
|
||||
|
||||
/** Applies a conversion function to the keys input values of the animation curve.
|
||||
@param timeConversion The conversion function to use on the key inputs.
|
||||
@param tangentWeightConversion The conversion function to use on the key tangent weights. */
|
||||
void ConvertInputs(FCDConversionFunction timeConversion, FCDConversionFunction tangentWeightConversion);
|
||||
|
||||
/** Evaluates the animation curve.
|
||||
@param input An input value.
|
||||
@return The sampled value of the curve at the given input value. */
|
||||
float Evaluate(float input) const;
|
||||
|
||||
/** [INTERNAL] Adds an animation clip to the list of animation clips that use this curve.
|
||||
@param clip An animation clip. */
|
||||
inline void RegisterAnimationClip(FCDAnimationClip* clip) { clips.push_back(clip); }
|
||||
|
||||
/** [INTERNAL] Writes out the data sources necessary to import the animation curve
|
||||
to a given XML tree node.
|
||||
@param parentNode The XML tree node in which to create the data sources.
|
||||
@param baseId A COLLADA Id prefix to use when generating the source ids. */
|
||||
void WriteSourceToXML(xmlNode* parentNode, const string& baseId) const;
|
||||
|
||||
/** [INTERNAL] Writes out the sampler that puts together the data sources
|
||||
and generates a sampling function.
|
||||
@param parentNode The XML tree node in which to create the sampler.
|
||||
@param baseId The COLLADA id prefix used when generating the source ids.
|
||||
This prefix is also used to generate the sampler COLLADA id.
|
||||
@return The created XML tree node. */
|
||||
xmlNode* WriteSamplerToXML(xmlNode* parentNode, const string& baseId) const;
|
||||
|
||||
/** [INTERNAL] Writes out the animation channel that attaches the sampling function
|
||||
to the animatable value.
|
||||
@param parentNode The XML tree node in which to create the sampler.
|
||||
@param baseId The COLLADA Id prefix used when generating the source ids
|
||||
and the sampler id.
|
||||
@param targetPointer The target pointer prefix for the targeted animated element.
|
||||
@return The created XML tree node. */
|
||||
xmlNode* WriteChannelToXML(xmlNode* parentNode, const string& baseId, const char* targetPointer) const;
|
||||
|
||||
/** [INTERNAL] Retrieves the target element suffix for the curve.
|
||||
This will be -1 if the animated element does not belong to an
|
||||
animated element list.
|
||||
@return The target element suffix. */
|
||||
inline int32 GetTargetElement() const { return targetElement; }
|
||||
|
||||
/** [INTERNAL] Retrieves the target qualifier for the curve.
|
||||
This will be the empty string if that the curve affects
|
||||
a one-dimensional animated element.
|
||||
@return The target qualifier. */
|
||||
inline const string& GetTargetQualifier() const { return targetQualifier; }
|
||||
|
||||
/** [INTERNAL] Sets the target element suffix for the curve.
|
||||
@param e The target element suffix. Set to value to -1
|
||||
if the animated element does not belong to an animated element list. */
|
||||
inline void SetTargetElement(int32 e) { targetElement = e; }
|
||||
|
||||
/** [INTERNAL] Sets the target qualifier for the curve.
|
||||
@param q The target qualifier. You may sets this string to the empty string
|
||||
only if that the curve affects a one-dimensional animated element. */
|
||||
inline void SetTargetQualifier(const string& q) { targetQualifier = q; }
|
||||
|
||||
/** [INTERNAL] Retrieves the target pointer prefix of the driver.
|
||||
@return The driver's target pointer prefix. */
|
||||
inline const string& GetDriverPointer() const { return driverPointer; }
|
||||
|
||||
/** [INTERNAL] Sets the target pointer prefix of the driver.
|
||||
@param p The driver's target pointer prefix. Set this string to the
|
||||
empty string if the input of the animation curve is the time. */
|
||||
inline void SetDriverPointer(const string& p) { driverPointer = p; }
|
||||
};
|
||||
|
||||
#endif // _FCD_ANIMATION_CURVE_H_
|
||||
@@ -1,378 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDAnimationCurve.h"
|
||||
#include "FCDocument/FCDAnimationMultiCurve.h"
|
||||
#include "FUtils/FUDaeEnum.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
#define SMALL_DELTA 0.001f
|
||||
|
||||
FCDAnimationMultiCurve::FCDAnimationMultiCurve(FCDocument* document, uint32 _dimension) : FCDObject(document, "FCDAnimationMultiCurve")
|
||||
{
|
||||
dimension = _dimension;
|
||||
if (dimension == 0) dimension = 1;
|
||||
|
||||
// Prepare the target information
|
||||
targetElement = -1;
|
||||
targetQualifiers = new string[dimension];
|
||||
|
||||
// Allocate the key values and tangents to the wanted dimension
|
||||
keyValues = new FloatList[dimension];
|
||||
inTangents = new FloatList[dimension];
|
||||
outTangents = new FloatList[dimension];
|
||||
}
|
||||
|
||||
FCDAnimationMultiCurve::~FCDAnimationMultiCurve()
|
||||
{
|
||||
SAFE_DELETE_ARRAY(targetQualifiers);
|
||||
SAFE_DELETE_ARRAY(keyValues);
|
||||
SAFE_DELETE_ARRAY(inTangents);
|
||||
SAFE_DELETE_ARRAY(outTangents);
|
||||
}
|
||||
|
||||
// Samples all the curves for a given input
|
||||
void FCDAnimationMultiCurve::Evaluate(float input, float* output) const
|
||||
{
|
||||
// Single key curves imply a constant value
|
||||
if (keys.size() == 1)
|
||||
{
|
||||
for (uint32 i = 0; i < dimension; ++i) output[i] = keyValues[i].front();
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the current interval
|
||||
uint32 index = 0;
|
||||
FloatList::const_iterator it;
|
||||
for (it = keys.begin(); it != keys.end(); ++it, ++index)
|
||||
{
|
||||
if ((*it) > input) break;
|
||||
}
|
||||
|
||||
if (it == keys.end())
|
||||
{
|
||||
// We're sampling after the curve, return the last values
|
||||
for (uint32 i = 0; i < dimension; ++i) output[i] = keyValues[i].back();
|
||||
return;
|
||||
}
|
||||
else if (it == keys.begin())
|
||||
{
|
||||
// We're sampling before the curve, return the first values
|
||||
for (uint32 i = 0; i < dimension; ++i) output[i] = keyValues[i].front();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the keys and values for this interval
|
||||
float endKey = *it;
|
||||
float startKey = *(it - 1);
|
||||
|
||||
// Interpolate the outputs.
|
||||
// Similar code is found in FCDAnimationCurve.cpp. If you update this, update the other one too.
|
||||
uint32 interpolation = interpolations.empty() ? ((uint32) FUDaeInterpolation::DEFAULT) : interpolations[index];
|
||||
switch (FUDaeInterpolation::Interpolation(interpolation))
|
||||
{
|
||||
case FUDaeInterpolation::LINEAR: {
|
||||
for (uint32 i = 0; i < dimension; ++i)
|
||||
{
|
||||
float startValue = keyValues[i][index - 1];
|
||||
float endValue = keyValues[i][index];
|
||||
output[i] = (input - startKey) / (endKey - startKey) * (endValue - startValue) + startValue;
|
||||
}
|
||||
break; }
|
||||
|
||||
case FUDaeInterpolation::BEZIER: {
|
||||
for (uint32 i = 0; i < dimension; ++i)
|
||||
{
|
||||
float startValue = keyValues[i][index - 1];
|
||||
float endValue = keyValues[i][index];
|
||||
|
||||
float t = (input - startKey) / (endKey - startKey);
|
||||
float bValue = startValue + outTangents[i][index - 1];
|
||||
float cValue = endValue - inTangents[i][index];
|
||||
float ti = 1.0f - t;
|
||||
|
||||
output[i] = startValue * ti * ti * ti + 3.0f * bValue * ti * ti * t + 3.0f * cValue * ti * t * t + endValue * t * t * t;
|
||||
}
|
||||
break; }
|
||||
|
||||
case FUDaeInterpolation::UNKNOWN:
|
||||
case FUDaeInterpolation::STEP:
|
||||
default: {
|
||||
for (uint32 i = 0; i < dimension; ++i)
|
||||
{
|
||||
output[i] = keyValues[i][index - 1];
|
||||
}
|
||||
break; }
|
||||
}
|
||||
}
|
||||
|
||||
FCDAnimationMultiCurve* FCDAnimationMultiCurve::MergeCurves(const vector<FCDAnimationCurve*>& _toMerge, const FloatList& defaultValues)
|
||||
{
|
||||
vector<const FCDAnimationCurve*> toMerge(_toMerge.size());
|
||||
for (vector<FCDAnimationCurve*>::const_iterator itC = _toMerge.begin(); itC != _toMerge.end(); ++itC)
|
||||
{
|
||||
toMerge.push_back(*itC);
|
||||
}
|
||||
return MergeCurves(toMerge, defaultValues);
|
||||
}
|
||||
|
||||
// Non-standard constructor used to merge together animation curves
|
||||
FCDAnimationMultiCurve* FCDAnimationMultiCurve::MergeCurves(const vector<const FCDAnimationCurve*>& toMerge, const FloatList& defaultValues)
|
||||
{
|
||||
size_t dimension = toMerge.size();
|
||||
if (dimension == 0) return NULL;
|
||||
|
||||
// Look for the document pointer
|
||||
FCDocument* document = NULL;
|
||||
int32 targetElement = -1;
|
||||
for (size_t i = 0; i < dimension; ++i)
|
||||
{
|
||||
if (toMerge[i] != NULL)
|
||||
{
|
||||
document = toMerge[i]->GetDocument();
|
||||
targetElement = toMerge[i]->GetTargetElement();
|
||||
}
|
||||
}
|
||||
if (document == NULL) return NULL;
|
||||
|
||||
// Allocate the output multiCurve.
|
||||
FCDAnimationMultiCurve* multiCurve = new FCDAnimationMultiCurve(document, (uint32) dimension);
|
||||
multiCurve->targetElement = targetElement;
|
||||
|
||||
// Grab all the animation curve data element right away, to spare me some typing.
|
||||
FloatList& keys = multiCurve->GetKeys();
|
||||
FloatList* values = multiCurve->GetKeyValues();
|
||||
FloatList* inTangents = multiCurve->GetInTangents();
|
||||
FloatList* outTangents = multiCurve->GetOutTangents();
|
||||
UInt32List& interpolations = multiCurve->GetInterpolations();
|
||||
|
||||
// Calculate the merged input keys
|
||||
for (size_t i = 0; i < dimension; ++i)
|
||||
{
|
||||
const FCDAnimationCurve* curve = toMerge[i];
|
||||
if (curve == NULL) continue;
|
||||
|
||||
const FloatList& curveKeys = curve->GetKeys();
|
||||
|
||||
// Merge each curve's keys, which should already be sorted, into the multi-curve's
|
||||
size_t multiCurveKeyCount = keys.size(), m = 0;
|
||||
size_t curveKeyCount = curveKeys.size(), c = 0;
|
||||
while (m < multiCurveKeyCount && c < curveKeyCount)
|
||||
{
|
||||
if (IsEquivalent(keys[m], curveKeys[c])) { ++c; ++m; }
|
||||
else if (keys[m] < curveKeys[c]) { ++m; }
|
||||
else { keys.insert(keys.begin() + m, curveKeys[c++]); }
|
||||
}
|
||||
if (c < curveKeyCount) keys.insert(keys.end(), curveKeys.begin() + c, curveKeys.end());
|
||||
}
|
||||
size_t keyCount = keys.size();
|
||||
|
||||
// Start with the unknown interpolation everywhere
|
||||
interpolations.resize(keyCount);
|
||||
for (UInt32List::iterator it = interpolations.begin(); it != interpolations.end(); ++it)
|
||||
{
|
||||
(*it) = (uint32) FUDaeInterpolation::UNKNOWN;
|
||||
}
|
||||
|
||||
// Merge the curves one by one into the multi-curve
|
||||
for (size_t i = 0; i < dimension; ++i)
|
||||
{
|
||||
// Pre-allocate the value and tangent data arrays
|
||||
values[i].resize(keyCount);
|
||||
inTangents[i].resize(keyCount);
|
||||
outTangents[i].resize(keyCount);
|
||||
|
||||
const FCDAnimationCurve* curve = toMerge[i];
|
||||
if (curve == NULL)
|
||||
{
|
||||
// No curve, set the default value on all the keys
|
||||
float defaultValue = (i < defaultValues.size()) ? defaultValues[i] : 0.0f;
|
||||
for (size_t k = 0; k < keyCount; ++k)
|
||||
{
|
||||
values[i][k] = defaultValue;
|
||||
inTangents[i][k] = 0.0f;
|
||||
outTangents[i][k] = 0.0f;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
multiCurve->targetQualifiers[i] = curve->GetTargetQualifier();
|
||||
|
||||
// Does the curve have per-key interpolations?
|
||||
bool hasDefaultInterpolation = curve->GetInterpolations().empty();
|
||||
|
||||
// Merge in this curve's values, sampling when the multi-curve's key is not present in the curve.
|
||||
const FloatList& curveKeys = curve->GetKeys();
|
||||
size_t curveKeyCount = curveKeys.size();
|
||||
bool sampleNextInTangent = false;
|
||||
for (size_t k = 0, c = 0; k < keyCount; ++k)
|
||||
{
|
||||
uint32 interpolation;
|
||||
if (c >= curveKeyCount || !IsEquivalent(keys[k], curveKeys[c]))
|
||||
{
|
||||
// Sample the curve
|
||||
float value = values[i][k] = curve->Evaluate(keys[k]);
|
||||
|
||||
// Calculate the in-tangent and the previous key's out-tangent
|
||||
float span = ((k > 0) ? (keys[k] - keys[k - 1]) : (keys[k + 1] - keys[k])) / 3.0f;
|
||||
inTangents[i][k] = value - curve->Evaluate(keys[k] - SMALL_DELTA) / SMALL_DELTA * span;
|
||||
if (k > 0) outTangents[i][k-1] = curve->Evaluate(keys[k - 1] + SMALL_DELTA) / SMALL_DELTA * span - values[i][k-1];
|
||||
|
||||
// Calculate the out-tangent and force the sampling of the next key's in-tangent
|
||||
span = (c < curveKeyCount - 1) ? (keys[k + 1] - keys[k]) / 3.0f : span;
|
||||
outTangents[i][k] = curve->Evaluate(keys[k] + SMALL_DELTA) / SMALL_DELTA * span - value;
|
||||
interpolation = FUDaeInterpolation::BEZIER;
|
||||
sampleNextInTangent = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keys match, grab the values directly
|
||||
values[i][k] = curve->GetKeyValues()[c];
|
||||
outTangents[i][k] = curve->GetOutTangents()[c];
|
||||
interpolation = hasDefaultInterpolation ? ((uint32) FUDaeInterpolation::DEFAULT) : curve->GetInterpolations()[c];
|
||||
|
||||
// Sampling the previous key would require that we sample the inTangent
|
||||
if (!sampleNextInTangent) inTangents[i][k] = curve->GetInTangents()[c];
|
||||
else
|
||||
{
|
||||
float span = (keys[k] - keys[k - 1]) / 3.0f;
|
||||
inTangents[i][k] = values[i][k] - curve->Evaluate(keys[k] - SMALL_DELTA) / SMALL_DELTA * span;
|
||||
}
|
||||
++c;
|
||||
}
|
||||
|
||||
// Merge the interpolation values, where bezier wins whenever interpolation values differ
|
||||
uint32& oldInterpolation = interpolations[k];
|
||||
if (oldInterpolation == FUDaeInterpolation::UNKNOWN) oldInterpolation = interpolation;
|
||||
else if (oldInterpolation != interpolation) oldInterpolation = FUDaeInterpolation::BEZIER;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset any unknown interpolation left
|
||||
for (UInt32List::iterator it = interpolations.begin(); it != interpolations.end(); ++it)
|
||||
{
|
||||
if ((*it) == (uint32) FUDaeInterpolation::UNKNOWN) (*it) = FUDaeInterpolation::DEFAULT;
|
||||
}
|
||||
|
||||
return multiCurve;
|
||||
}
|
||||
|
||||
// Collapse this multi-dimensional curve into a one-dimensional curve, given a collapsing function
|
||||
FCDAnimationCurve* FCDAnimationMultiCurve::Collapse(FCDCollapsingFunction collapse) const
|
||||
{
|
||||
size_t keyCount = keys.size();
|
||||
if (keyCount == 0 || dimension == 0) return NULL;
|
||||
if (collapse == NULL) collapse = Average;
|
||||
|
||||
// Create the output one-dimensional curve and retrieve its data list
|
||||
FCDAnimationCurve* out = new FCDAnimationCurve(GetDocument(), NULL);
|
||||
out->SetTargetElement(targetElement);
|
||||
FloatList& outKeys = out->GetKeys();
|
||||
FloatList& outKeyValues = out->GetKeyValues();
|
||||
FloatList& outInTangents = out->GetInTangents();
|
||||
FloatList& outOutTangents = out->GetOutTangents();
|
||||
UInt32List& outInterpolations = out->GetInterpolations();
|
||||
|
||||
// Pre-allocate the output arrays
|
||||
outKeys.resize(keyCount);
|
||||
outKeyValues.resize(keyCount);
|
||||
outInTangents.resize(keyCount);
|
||||
outOutTangents.resize(keyCount);
|
||||
outInterpolations.resize(keyCount);
|
||||
|
||||
// Copy the key data over, collapsing the values
|
||||
float* buffer = new float[dimension];
|
||||
for (size_t i = 0; i < keyCount; ++i)
|
||||
{
|
||||
outKeys[i] = keys[i];
|
||||
outInterpolations[i] = interpolations[i];
|
||||
|
||||
// Collapse the values and the tangents
|
||||
# define COLLAPSE(outArray, inArray) \
|
||||
for (uint32 j = 0; j < dimension; ++j) buffer[j] = inArray[j][i]; \
|
||||
outArray[i] = (*collapse)(buffer, dimension)
|
||||
|
||||
COLLAPSE(outKeyValues, keyValues);
|
||||
COLLAPSE(outInTangents, inTangents);
|
||||
COLLAPSE(outOutTangents, outTangents);
|
||||
# undef COLLAPSE
|
||||
}
|
||||
SAFE_DELETE_ARRAY(buffer);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// Write out the specific animation elements to the COLLADA xml tree node
|
||||
void FCDAnimationMultiCurve::WriteSourceToXML(xmlNode* parentNode, const string& baseId)
|
||||
{
|
||||
if (keys.empty() || dimension == 0 || keyValues[0].empty()) return;
|
||||
|
||||
// Generate the list of the parameters
|
||||
typedef const char* pchar;
|
||||
pchar* parameters = new pchar[dimension];
|
||||
for (size_t i = 0; i < dimension; ++i)
|
||||
{
|
||||
parameters[i] = targetQualifiers[i].c_str();
|
||||
if (*(parameters[i]) == '.') ++(parameters[i]);
|
||||
}
|
||||
|
||||
// Export the key times
|
||||
AddSourceFloat(parentNode, baseId + "-input", keys, "TIME");
|
||||
|
||||
// Interlace the key values and tangents for the export
|
||||
size_t valueCount = keyValues[0].size();
|
||||
FloatList sourceData; sourceData.reserve(dimension * valueCount);
|
||||
for (size_t v = 0; v < valueCount; ++v) for (uint32 n = 0; n < dimension; ++n) sourceData.push_back(keyValues[n].at(v));
|
||||
AddSourceFloat(parentNode, baseId + "-output", sourceData, dimension, parameters);
|
||||
|
||||
sourceData.clear();
|
||||
for (size_t v = 0; v < valueCount; ++v) for (uint32 n = 0; n < dimension; ++n) sourceData.push_back(inTangents[n].at(v));
|
||||
AddSourceFloat(parentNode, baseId + "-intangents", sourceData, dimension, parameters);
|
||||
|
||||
sourceData.clear();
|
||||
for (size_t v = 0; v < valueCount; ++v) for (uint32 n = 0; n < dimension; ++n) sourceData.push_back(outTangents[n].at(v));
|
||||
AddSourceFloat(parentNode, baseId + "-outtangents", sourceData, dimension, parameters);
|
||||
|
||||
// Weights not yet supported on multi-curve
|
||||
|
||||
AddSourceInterpolation(parentNode, baseId + "-interpolations", *(FUDaeInterpolationList*)&interpolations);
|
||||
}
|
||||
|
||||
xmlNode* FCDAnimationMultiCurve::WriteSamplerToXML(xmlNode* parentNode, const string& baseId)
|
||||
{
|
||||
xmlNode* samplerNode = AddChild(parentNode, DAE_SAMPLER_ELEMENT);
|
||||
AddAttribute(samplerNode, DAE_ID_ATTRIBUTE, baseId + "-sampler");
|
||||
|
||||
// Add the sampler inputs
|
||||
AddInput(samplerNode, baseId + "-input", DAE_INPUT_ANIMATION_INPUT);
|
||||
AddInput(samplerNode, baseId + "-output", DAE_OUTPUT_ANIMATION_INPUT);
|
||||
AddInput(samplerNode, baseId + "-intangents", DAE_INTANGENT_ANIMATION_INPUT);
|
||||
AddInput(samplerNode, baseId + "-outtangents", DAE_OUTTANGENT_ANIMATION_INPUT);
|
||||
AddInput(samplerNode, baseId + "-interpolations", DAE_INTERPOLATION_ANIMATION_INPUT);
|
||||
return samplerNode;
|
||||
}
|
||||
|
||||
xmlNode* FCDAnimationMultiCurve::WriteChannelToXML(xmlNode* parentNode, const string& baseId, const string& pointer)
|
||||
{
|
||||
xmlNode* channelNode = AddChild(parentNode, DAE_CHANNEL_ELEMENT);
|
||||
AddAttribute(channelNode, DAE_SOURCE_ATTRIBUTE, baseId + "-sampler");
|
||||
|
||||
// Generate and export the full target [no qualifiers]
|
||||
globalSBuilder.set(pointer);
|
||||
if (targetElement >= 0)
|
||||
{
|
||||
globalSBuilder.append('('); globalSBuilder.append(targetElement); globalSBuilder.append(')');
|
||||
}
|
||||
AddAttribute(channelNode, DAE_TARGET_ATTRIBUTE, globalSBuilder);
|
||||
return channelNode;
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDAnimationMultiCurve.h
|
||||
This file contains the FCDAnimationMultiCurve class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_ANIMATION_MULTI_CURVE_H_
|
||||
#define _FCD_ANIMATION_MULTI_CURVE_H_
|
||||
|
||||
class FCDocument;
|
||||
|
||||
#include "FCDocument/FCDObject.h"
|
||||
|
||||
typedef float (*FCDConversionFunction)(float v); /**< A simple conversion function. */
|
||||
typedef float (*FCDCollapsingFunction)(float* values, uint32 count); /**< A collapsing function. It converts multiple floating-point values into one floating-point value. */
|
||||
|
||||
/**
|
||||
A COLLADA multi-dimensional animation curve.
|
||||
|
||||
This is a utility class that is used to convert multiple
|
||||
animation curves into one animation curve that has multiple
|
||||
dimensions, but only one list of key inputs.
|
||||
|
||||
FCollada will never create a multi-dimensional animation curve
|
||||
during the import of a COLLADA document.
|
||||
|
||||
@ingroup FCDocument
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDAnimationMultiCurve : public FCDObject
|
||||
{
|
||||
private:
|
||||
// The number of merged curves
|
||||
uint32 dimension;
|
||||
|
||||
// Target information
|
||||
int32 targetElement;
|
||||
string* targetQualifiers;
|
||||
|
||||
// Input information
|
||||
FloatList keys,* keyValues;
|
||||
FloatList* inTangents,* outTangents;
|
||||
|
||||
// The interpolation values follow the FUDaeInterpolation enum (FUDaeEnum.h)
|
||||
UInt32List interpolations;
|
||||
|
||||
public:
|
||||
/** Constructor.
|
||||
The number of dimensions will not change in the lifetime of a
|
||||
multi-dimensional curve.
|
||||
@param document The COLLADA document that owns the animation curve.
|
||||
@param dimension The number of dimensions for the animation curve. */
|
||||
FCDAnimationMultiCurve(FCDocument* document, uint32 dimension);
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~FCDAnimationMultiCurve();
|
||||
|
||||
/** Merges multiple single-dimensional animation curves into one
|
||||
multi-dimensional animation curve.
|
||||
For each NULL element found within the 'toMerge' list, the corresponding
|
||||
default value is used. If there are not enough default values provided, zero is assumed.
|
||||
The number of dimensions for the output animation curve is taken as the size of the 'toMerge' list.
|
||||
@param toMerge The list of single-dimensional animation curves to merge. This list may
|
||||
contain NULL elements, as explained above.
|
||||
@param defaultValues The list of default values to use when a NULL element is encountered.
|
||||
Default values should be provided even for the elements that are not NULL. */
|
||||
static FCDAnimationMultiCurve* MergeCurves(const vector<FCDAnimationCurve*>& toMerge, const FloatList& defaultValues);
|
||||
static FCDAnimationMultiCurve* MergeCurves(const vector<const FCDAnimationCurve*>& toMerge, const FloatList& defaultValues); /**< See above. */
|
||||
|
||||
/** Retrieves the number of dimensions for the curve.
|
||||
@return The number of dimensions for the curve. */
|
||||
inline uint32 GetDimension() const { return dimension; }
|
||||
|
||||
/** Retrieves the list of key inputs for the animation curve.
|
||||
@return The list of key inputs. */
|
||||
inline FloatList& GetKeys() { return keys; }
|
||||
inline const FloatList& GetKeys() const { return keys; } /**< See above. */
|
||||
|
||||
/** Retrieves the lists of key outputs for the animation curve.
|
||||
There is one separate list of key outputs for each dimension of the curve.
|
||||
@return The lists of key outputs. */
|
||||
inline FloatList* GetKeyValues() { return keyValues; }
|
||||
inline const FloatList* GetKeyValues() const { return keyValues; } /**< See above. */
|
||||
|
||||
/** Retrieves the lists of key in-tangent values for the animation curve.
|
||||
These lists have data only if the curve includes segments with the bezier interpolation.
|
||||
There is one separate list of key in-tangent values for each dimension of the curve.
|
||||
@return The lists of in-tangent values. */
|
||||
inline FloatList* GetInTangents() { return inTangents; }
|
||||
inline const FloatList* GetInTangents() const { return inTangents; } /**< See above. */
|
||||
|
||||
/** Retrieves the lists of key out-tangent values for the animation curve.
|
||||
These lists have data only if the curve includes segments with the bezier interpolation.
|
||||
There is one separate list of key out-tangent values for each dimension of the curve.
|
||||
@return The lists of out-tangent values. */
|
||||
inline FloatList* GetOutTangents() { return outTangents; }
|
||||
inline const FloatList* GetOutTangents() const { return outTangents; } /**< See above. */
|
||||
|
||||
/** Retrieves the list of interpolation type for the segments of the animation curve.
|
||||
There is always one interpolation type for each key in the curve. The interpolation type
|
||||
of a segment of the curve is set at the key at which begins the segment.
|
||||
@see FUDaeInterpolation
|
||||
@return The list of interpolation types. */
|
||||
inline UInt32List& GetInterpolations() { return interpolations; }
|
||||
inline const UInt32List& GetInterpolations() const { return interpolations; } /**< See above. */
|
||||
|
||||
/** Evaluates the animation curve.
|
||||
@param input An input value.
|
||||
@param output An array of floating-point values to fill in with the sampled values. */
|
||||
void Evaluate(float input, float* output) const;
|
||||
|
||||
/** Collapses this multi-dimensional curve into a one-dimensional curve.
|
||||
@param collapse The function to use to collapse multiple floating-point
|
||||
values into one. Set this to NULL to use the default collapsing
|
||||
function, which averages all the values.
|
||||
@see Average TakeFirst */
|
||||
FCDAnimationCurve* Collapse(FCDCollapsingFunction collapse=NULL) const;
|
||||
|
||||
/** [INTERNAL] Writes out the data sources necessary to import the animation curve
|
||||
to a given XML tree node.
|
||||
@param parentNode The XML tree node in which to create the data sources.
|
||||
@param baseId A COLLADA Id prefix to use when generating the source ids. */
|
||||
void WriteSourceToXML(xmlNode* parentNode, const string& baseId);
|
||||
|
||||
/** [INTERNAL] Writes out the sampler that puts together the data sources
|
||||
and generates a sampling function.
|
||||
@param parentNode The XML tree node in which to create the sampler.
|
||||
@param baseId The COLLADA id prefix used when generating the source ids.
|
||||
This prefix is also used to generate the sampler COLLADA id.
|
||||
@return The created XML tree node. */
|
||||
xmlNode* WriteSamplerToXML(xmlNode* parentNode, const string& baseId);
|
||||
|
||||
/** [INTERNAL] Writes out the animation channel that attaches the sampling function
|
||||
to the animatable value.
|
||||
@param parentNode The XML tree node in which to create the sampler.
|
||||
@param baseId The COLLADA Id prefix used when generating the source ids
|
||||
and the sampler id.
|
||||
@param pointer The target pointer prefix for the targeted animated element.
|
||||
@return The created XML tree node. */
|
||||
xmlNode* WriteChannelToXML(xmlNode* parentNode, const string& baseId, const string& pointer);
|
||||
|
||||
/** [INTERNAL] Retrieves the target element suffix for the curve.
|
||||
This will be -1 if the animated element does not belong to an
|
||||
animated element list.
|
||||
@return The target element suffix. */
|
||||
inline int32 GetTargetElement() const { return targetElement; }
|
||||
|
||||
/** [INTERNAL] Sets the target element suffix for the curve.
|
||||
@param e The target element suffix. Set to value to -1
|
||||
if the animated element does not belong to an animated element list. */
|
||||
inline void SetTargetElement(int32 e) { targetElement = e; }
|
||||
};
|
||||
|
||||
/**
|
||||
Retrieves the first floating-point value of a list of floating-point values.
|
||||
This is a typical conversion function.
|
||||
@param values The list of floating-point values.
|
||||
@param count The number of values within the given list.
|
||||
*/
|
||||
inline float TakeFirst(float* values, uint32 count) { return (count > 0) ? *values : 0.0f; }
|
||||
|
||||
/**
|
||||
Retrieves the average value of a list of floating-point values.
|
||||
This is a typical conversion function.
|
||||
@param values The list of floating-point values.
|
||||
@param count The number of values within the given list.
|
||||
*/
|
||||
inline float Average(float* values, uint32 count) { float v = 0.0f; for (uint32 i = 0; i < count; ++i) v += values[i]; v /= float(count); return v; }
|
||||
|
||||
#endif // _FCD_ANIMATION_MULTI_CURVE_H_
|
||||
@@ -1,207 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FUtils/FUDateTime.h"
|
||||
#include "FCDocument/FCDAsset.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDAsset::FCDAsset(FCDocument* document) : FCDObject(document, "FCDAsset")
|
||||
{
|
||||
unitConversionFactor = 1.0f;
|
||||
unitName = FC("meter");
|
||||
upAxis = FMVector3::YAxis;
|
||||
creationDateTime = modifiedDateTime = FUDateTime::GetNow();
|
||||
}
|
||||
|
||||
FCDAsset::~FCDAsset()
|
||||
{
|
||||
while(!contributors.empty())
|
||||
{
|
||||
SAFE_DELETE(contributors.back());
|
||||
contributors.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
// Insert a new contributor within the list
|
||||
FCDAssetContributor* FCDAsset::AddContributor()
|
||||
{
|
||||
FCDAssetContributor* contributor = new FCDAssetContributor(GetDocument());
|
||||
contributors.push_back(contributor);
|
||||
return contributor;
|
||||
}
|
||||
|
||||
// Read in the <asset> element from a COLLADA xml document
|
||||
FUStatus FCDAsset::LoadFromXML(xmlNode* assetNode)
|
||||
{
|
||||
FUStatus status;
|
||||
bool isPreCollada1_4 = false;
|
||||
for (xmlNode* child = assetNode->children; child != NULL; child = child->next)
|
||||
{
|
||||
if (child->type != XML_ELEMENT_NODE) continue;
|
||||
|
||||
const char* content = ReadNodeContentDirect(child);
|
||||
if (IsEquivalent(child->name, DAE_CONTRIBUTOR_ASSET_ELEMENT))
|
||||
{
|
||||
FCDAssetContributor* contributor = new FCDAssetContributor(GetDocument());
|
||||
contributors.push_back(contributor);
|
||||
status.AppendStatus(contributor->LoadFromXML(child, false));
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_CREATED_ASSET_PARAMETER))
|
||||
{
|
||||
FUStringConversion::ToDateTime(content, creationDateTime);
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_KEYWORDS_ASSET_PARAMETER))
|
||||
{
|
||||
keywords = TO_FSTRING(content);
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_MODIFIED_ASSET_PARAMETER))
|
||||
{
|
||||
FUStringConversion::ToDateTime(content, modifiedDateTime );
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_REVISION_ASSET_PARAMETER))
|
||||
{
|
||||
revision = TO_FSTRING(content);
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_SUBJECT_ASSET_PARAMETER))
|
||||
{
|
||||
subject = TO_FSTRING(content);
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_TITLE_ASSET_PARAMETER))
|
||||
{
|
||||
title = TO_FSTRING(content);
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_UNITS_ASSET_PARAMETER))
|
||||
{
|
||||
unitName = TO_FSTRING(ReadNodeName(child));
|
||||
unitConversionFactor = FUStringConversion::ToFloat(ReadNodeProperty(child, DAE_METERS_ATTRIBUTE));
|
||||
if (unitName.empty()) unitName = FC("UNKNOWN");
|
||||
if (IsEquivalent(unitConversionFactor, 0.0f) || unitConversionFactor < 0.0f) unitConversionFactor = 1.0f;
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_UPAXIS_ASSET_PARAMETER))
|
||||
{
|
||||
if (IsEquivalent(content, DAE_X_UP)) upAxis = FMVector3::XAxis;
|
||||
else if (IsEquivalent(content, DAE_Y_UP)) upAxis = FMVector3::YAxis;
|
||||
else if (IsEquivalent(content, DAE_Z_UP)) upAxis = FMVector3::ZAxis;
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_AUTHOR_ASSET_PARAMETER) || IsEquivalent(child->name, DAE_AUTHORINGTOOL_ASSET_PARAMETER)
|
||||
|| IsEquivalent(child->name, DAE_COMMENTS_ASSET_PARAMETER) || IsEquivalent(child->name, DAE_SOURCEDATA_ASSET_PARAMETER)
|
||||
|| IsEquivalent(child->name, DAE_COPYRIGHT_ASSET_PARAMETER))
|
||||
{
|
||||
isPreCollada1_4 = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
status.Warning(FS("Unknown <asset> child element: ") + TO_FSTRING((const char*) child->name), child->line);
|
||||
}
|
||||
}
|
||||
|
||||
// COLLADA 1.3 Backward Compatibility: Look for the contributor information within the <asset> element
|
||||
if (isPreCollada1_4)
|
||||
{
|
||||
FCDAssetContributor* contributor = new FCDAssetContributor(GetDocument());
|
||||
contributor->LoadFromXML(assetNode, true);
|
||||
if (!contributor->IsEmpty()) contributors.push_back(contributor);
|
||||
else SAFE_DELETE(contributor);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out the <asset> element to a COLLADA xml node tree
|
||||
xmlNode* FCDAsset::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* assetNode = AddChild(parentNode, DAE_ASSET_ELEMENT);
|
||||
|
||||
// Update the 'last modified time'
|
||||
FCDAsset* hackedAsset = const_cast<FCDAsset*>(this);
|
||||
hackedAsset->modifiedDateTime = FUDateTime::GetNow();
|
||||
|
||||
// Write out the contributors first.
|
||||
for (FCDAssetContributorList::const_iterator itC = contributors.begin(); itC != contributors.end(); ++itC)
|
||||
{
|
||||
(*itC)->WriteToXML(assetNode);
|
||||
}
|
||||
|
||||
// Write out the parameters, one by one and in the correct order.
|
||||
AddChild(assetNode, DAE_CREATED_ASSET_PARAMETER, FUStringConversion::ToString(creationDateTime));
|
||||
if (!keywords.empty()) AddChild(assetNode, DAE_KEYWORDS_ASSET_PARAMETER, keywords);
|
||||
AddChild(assetNode, DAE_MODIFIED_ASSET_PARAMETER, FUStringConversion::ToString(modifiedDateTime));
|
||||
if (!revision.empty()) AddChild(assetNode, DAE_REVISION_ASSET_PARAMETER, revision);
|
||||
if (!subject.empty()) AddChild(assetNode, DAE_SUBJECT_ASSET_PARAMETER, subject);
|
||||
if (!title.empty()) AddChild(assetNode, DAE_TITLE_ASSET_PARAMETER, title);
|
||||
|
||||
// Finally: <unit> and <up_axis>
|
||||
xmlNode* unitNode = AddChild(assetNode, DAE_UNITS_ASSET_PARAMETER);
|
||||
AddAttribute(unitNode, DAE_METERS_ATTRIBUTE, unitConversionFactor);
|
||||
AddAttribute(unitNode, DAE_NAME_ATTRIBUTE, unitName);
|
||||
AddChild(assetNode, DAE_UPAXIS_ASSET_PARAMETER, FUStringConversion::ToString(subject));
|
||||
return assetNode;
|
||||
}
|
||||
|
||||
FCDAssetContributor::FCDAssetContributor(FCDocument* document) : FCDObject(document, "FCDAssetContributor") {}
|
||||
FCDAssetContributor::~FCDAssetContributor() {}
|
||||
|
||||
// Returns whether this contributor element contain any valid data
|
||||
bool FCDAssetContributor::IsEmpty() const
|
||||
{
|
||||
return author.empty() && authoringTool.empty() && comments.empty() && copyright.empty() && sourceData.empty();
|
||||
}
|
||||
|
||||
// Read in the <asset><contributor> element from a COLLADA xml document
|
||||
FUStatus FCDAssetContributor::LoadFromXML(xmlNode* contributorNode, bool isPreCollada1_4)
|
||||
{
|
||||
FUStatus status;
|
||||
for (xmlNode* child = contributorNode->children; child != NULL; child = child->next)
|
||||
{
|
||||
if (child->type != XML_ELEMENT_NODE) continue;
|
||||
|
||||
const char* content = ReadNodeContentDirect(child);
|
||||
if (IsEquivalent(child->name, DAE_AUTHOR_ASSET_PARAMETER))
|
||||
{
|
||||
author = TO_FSTRING(content);
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_AUTHORINGTOOL_ASSET_PARAMETER))
|
||||
{
|
||||
authoringTool = TO_FSTRING(content);
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_COMMENTS_ASSET_PARAMETER))
|
||||
{
|
||||
comments = TO_FSTRING(content);
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_COPYRIGHT_ASSET_PARAMETER))
|
||||
{
|
||||
copyright = TO_FSTRING(content);
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_SOURCEDATA_ASSET_PARAMETER))
|
||||
{
|
||||
sourceData = TO_FSTRING(content);
|
||||
}
|
||||
else if (!isPreCollada1_4)
|
||||
{
|
||||
status.Warning(FS("Unknown <asset><contributor> child element: ") + TO_FSTRING((const char*) child->name), child->line);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out the <asset><contributor> element to a COLLADA xml node tree
|
||||
xmlNode* FCDAssetContributor::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* contributorNode = NULL;
|
||||
if (!IsEmpty())
|
||||
{
|
||||
contributorNode = AddChild(parentNode, DAE_CONTRIBUTOR_ASSET_ELEMENT);
|
||||
if (!author.empty()) AddChild(contributorNode, DAE_AUTHOR_ASSET_PARAMETER, author);
|
||||
if (!authoringTool.empty()) AddChild(contributorNode, DAE_AUTHORINGTOOL_ASSET_PARAMETER, authoringTool);
|
||||
if (!comments.empty()) AddChild(contributorNode, DAE_COMMENTS_ASSET_PARAMETER, comments);
|
||||
if (!copyright.empty()) AddChild(contributorNode, DAE_COPYRIGHT_ASSET_PARAMETER, copyright);
|
||||
if (!sourceData.empty()) AddChild(contributorNode, DAE_SOURCEDATA_ASSET_PARAMETER, sourceData);
|
||||
}
|
||||
return contributorNode;
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#ifndef _FCD_ASSET_H_
|
||||
#define _FCD_ASSET_H_
|
||||
|
||||
#include "FCDocument/FCDObject.h"
|
||||
#include "FUtils/FUDateTime.h"
|
||||
|
||||
class FCDAssetContributor;
|
||||
|
||||
typedef vector<FCDAssetContributor*> FCDAssetContributorList;
|
||||
|
||||
class FCOLLADA_EXPORT FCDAsset : public FCDObject
|
||||
{
|
||||
FCDAssetContributorList contributors;
|
||||
FUDateTime creationDateTime;
|
||||
FUDateTime modifiedDateTime;
|
||||
fstring keywords;
|
||||
fstring revision;
|
||||
fstring subject;
|
||||
fstring title;
|
||||
FMVector3 upAxis;
|
||||
|
||||
// <unit>
|
||||
fstring unitName;
|
||||
float unitConversionFactor;
|
||||
|
||||
public:
|
||||
FCDAsset(FCDocument* document);
|
||||
virtual ~FCDAsset();
|
||||
|
||||
// Direct contributor list access
|
||||
inline FCDAssetContributorList& GetContributors() { return contributors; }
|
||||
inline const FCDAssetContributorList& GetContributors() const { return contributors; }
|
||||
inline size_t GetContributorCount() const { return contributors.size(); }
|
||||
inline FCDAssetContributor* GetContributor(size_t index) { return index < contributors.size() ? contributors[index] : NULL; }
|
||||
inline const FCDAssetContributor* GetContributor(size_t index) const { return index < contributors.size() ? contributors[index] : NULL; }
|
||||
FCDAssetContributor* AddContributor();
|
||||
|
||||
// Direct accessors
|
||||
inline const FUDateTime& GetCreationDateTime() const { return creationDateTime; }
|
||||
inline const FUDateTime& GetModifiedDateTime() const { return modifiedDateTime; }
|
||||
inline const fstring& GetKeywords() const { return keywords; }
|
||||
inline const fstring& GetRevision() const { return revision; }
|
||||
inline const fstring& GetSubject() const { return subject; }
|
||||
inline const fstring& GetTitle() const { return title; }
|
||||
inline const FMVector3& GetUpAxis() const { return upAxis; }
|
||||
inline const fstring& GetUnitName() const { return unitName; }
|
||||
inline float GetUnitConversionFactor() const { return unitConversionFactor; }
|
||||
|
||||
// Direct mutators
|
||||
inline void SetKeywords(const fstring& _keywords) { keywords = _keywords; }
|
||||
inline void SetRevision(const fstring& _revision) { revision = _revision; }
|
||||
inline void SetSubject(const fstring& _subject) { subject = _subject; }
|
||||
inline void SetTitle(const fstring& _title) { title = _title; }
|
||||
inline void SetUpAxis(const FMVector3& _upAxis) { upAxis = _upAxis; }
|
||||
inline void SetUnitName(const fstring& _unitName) { unitName = _unitName; }
|
||||
inline void SetUnitConversionFactor(float factor) { unitConversionFactor = factor; }
|
||||
|
||||
// Read in the <asset> element from a COLLADA xml document
|
||||
FUStatus LoadFromXML(xmlNode* assetNode);
|
||||
|
||||
// Write out the <asset> element to a COLLADA xml node tree
|
||||
// Calling this function will update the 'last modified' timestamp.
|
||||
xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
// Encapsulates the <asset><contributor> element
|
||||
class FCOLLADA_EXPORT FCDAssetContributor : public FCDObject
|
||||
{
|
||||
private:
|
||||
fstring author;
|
||||
fstring authoringTool;
|
||||
fstring comments;
|
||||
fstring copyright;
|
||||
fstring sourceData;
|
||||
|
||||
public:
|
||||
FCDAssetContributor(FCDocument* document);
|
||||
virtual ~FCDAssetContributor();
|
||||
|
||||
// Direct accessors
|
||||
inline const fstring& GetAuthor() const { return author; }
|
||||
inline const fstring& GetAuthoringTool() const { return authoringTool; }
|
||||
inline const fstring& GetComments() const { return comments; }
|
||||
inline const fstring& GetCopyright() const { return copyright; }
|
||||
inline const fstring& GetSourceData() const { return sourceData; }
|
||||
|
||||
// Direct mutators
|
||||
inline void SetAuthor(const fstring& _author) { author = _author; }
|
||||
inline void SetAuthoringTool(const fstring& _authoringTool) { authoringTool = _authoringTool; }
|
||||
inline void SetComments(const fstring& _comments) { comments = _comments; }
|
||||
inline void SetCopyright(const fstring& _copyright) { copyright = _copyright; }
|
||||
inline void SetSourceData(const fstring& _sourceData) { sourceData = _sourceData; }
|
||||
|
||||
// Returns whether this contributor element contain any valid data
|
||||
bool IsEmpty() const;
|
||||
|
||||
// Read in the <asset><contributor> element from a COLLADA xml document
|
||||
FUStatus LoadFromXML(xmlNode* contributorNode, bool isPreCollada1_4=false);
|
||||
|
||||
// Write out the <asset><contributor> element to a COLLADA xml node tree
|
||||
xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif // _FCD_ASSET_H_
|
||||
@@ -1,268 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDCamera.h"
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDAnimated.h"
|
||||
#include "FCDocument/FCDSceneNode.h"
|
||||
#include "FUtils/FUStringConversion.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDCamera::FCDCamera(FCDocument* document) : FCDTargetedEntity(document, "Camera")
|
||||
{
|
||||
isPerspective = true;
|
||||
isOrthographic = false;
|
||||
viewY = viewX = 60.0f;
|
||||
hasAperture = hasHorizontalView = hasVerticalView = false;
|
||||
nearZ = 1.0f;
|
||||
farZ = 1000.0f;
|
||||
aspectRatio = 1.0f;
|
||||
horizontalAperture = verticalAperture = lensSqueeze = 1.0f;
|
||||
}
|
||||
|
||||
FCDCamera::~FCDCamera()
|
||||
{
|
||||
}
|
||||
|
||||
void FCDCamera::SetFovX(float _viewX)
|
||||
{
|
||||
viewX = _viewX;
|
||||
if (hasVerticalView && !IsEquivalent(viewX, 0.0f)) aspectRatio = viewY / viewX;
|
||||
hasHorizontalView = true;
|
||||
}
|
||||
|
||||
void FCDCamera::SetFovY(float _viewY)
|
||||
{
|
||||
viewY = _viewY;
|
||||
if (hasHorizontalView && !IsEquivalent(viewX, 0.0f)) aspectRatio = viewY / viewX;
|
||||
hasVerticalView = true;
|
||||
}
|
||||
|
||||
void FCDCamera::SetAspectRatio(float _aspectRatio)
|
||||
{
|
||||
aspectRatio = _aspectRatio;
|
||||
}
|
||||
|
||||
// Load this camera from the given COLLADA document's node
|
||||
FUStatus FCDCamera::LoadFromXML(xmlNode* cameraNode)
|
||||
{
|
||||
FUStatus status = FCDEntity::LoadFromXML(cameraNode);
|
||||
if (!status) return status;
|
||||
if (!IsEquivalent(cameraNode->name, DAE_CAMERA_ELEMENT))
|
||||
{
|
||||
return status.Warning(FS("Camera library contains unknown element."), cameraNode->line);
|
||||
}
|
||||
|
||||
// COLLADA 1.3: Grab the techniques and their <optics><program> children
|
||||
xmlNode* commonTechniqueNode1_3 = FindTechnique(cameraNode, DAE_COMMON_PROFILE);
|
||||
xmlNode* commonOpticsNode1_3 = FindChildByType(commonTechniqueNode1_3, DAE_OPTICS_ELEMENT);
|
||||
xmlNode* commonProgramNode1_3 = FindChildByType(commonOpticsNode1_3, DAE_PROGRAM_ELEMENT);
|
||||
xmlNode* maxTechniqueNode1_3 = FindTechnique(cameraNode, DAEMAX_MAX_PROFILE);
|
||||
xmlNode* maxOpticsNode1_3 = FindChildByType(maxTechniqueNode1_3, DAE_OPTICS_ELEMENT);
|
||||
xmlNode* maxProgramNode1_3 = FindChildByType(maxOpticsNode1_3, DAE_PROGRAM_ELEMENT);
|
||||
xmlNode* mayaTechniqueNode = FindTechnique(cameraNode, DAEMAYA_MAYA_PROFILE);
|
||||
xmlNode* mayaOpticsNode = FindChildByType(mayaTechniqueNode, DAE_OPTICS_ELEMENT);
|
||||
xmlNode* mayaProgramNode = FindChildByType(mayaOpticsNode, DAE_PROGRAM_ELEMENT);
|
||||
bool isCollada1_3 = commonTechniqueNode1_3 != NULL;
|
||||
|
||||
// COLLADA 1.4: Grab the <optics> element's techniques
|
||||
xmlNode* opticsNode = FindChildByType(cameraNode, DAE_OPTICS_ELEMENT);
|
||||
xmlNode* commonTechniqueNode = FindChildByType(opticsNode, DAE_TECHNIQUE_COMMON_ELEMENT);
|
||||
xmlNode* maxTechniqueNode = FindTechnique(opticsNode, DAEMAX_MAX_PROFILE);
|
||||
xmlNode* cameraContainerNode = (isCollada1_3) ? ((maxProgramNode1_3 != NULL) ? maxProgramNode1_3 : commonProgramNode1_3) : NULL;
|
||||
if (mayaProgramNode == NULL) mayaProgramNode = FindTechnique(opticsNode, DAEMAYA_MAYA_PROFILE);
|
||||
|
||||
// Figure out the camera type
|
||||
if (isCollada1_3)
|
||||
{
|
||||
FUUri programType = ReadNodeUrl(maxProgramNode1_3);
|
||||
if (programType.prefix.empty()) programType = ReadNodeUrl(commonProgramNode1_3);
|
||||
if (programType.prefix.empty())
|
||||
{
|
||||
return status.Fail(FS("No standard program type for camera: ") + TO_FSTRING(GetDaeId()), cameraNode->line);
|
||||
}
|
||||
string cameraType = TO_STRING(programType.prefix);
|
||||
isOrthographic = cameraType == DAE_ORTHOGRAPHIC_CAMERA_TYPE;
|
||||
isPerspective = cameraType == DAE_PERSPECTIVE_CAMERA_TYPE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Retrieve the <perspective> or <orthographic> element
|
||||
cameraContainerNode = FindChildByType(commonTechniqueNode, DAE_CAMERA_ORTHO_ELEMENT);
|
||||
isOrthographic = cameraContainerNode != NULL;
|
||||
if (!isOrthographic)
|
||||
{
|
||||
cameraContainerNode = FindChildByType(commonTechniqueNode, DAE_CAMERA_PERSP_ELEMENT);
|
||||
isPerspective = cameraContainerNode != NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
isPerspective = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the necessary camera structures
|
||||
if (cameraContainerNode == NULL)
|
||||
{
|
||||
return status.Fail(FS("Cannot find parameter root node for camera: ") + TO_FSTRING(GetDaeId()), cameraNode->line);
|
||||
}
|
||||
if (!(isPerspective ^ isOrthographic))
|
||||
{
|
||||
return status.Fail(FS("Unknown program type for camera: ") + TO_FSTRING(GetDaeId()), cameraContainerNode->line);
|
||||
}
|
||||
|
||||
// Setup the camera according to the type and its parameters
|
||||
// Retrieve all the camera parameters
|
||||
StringList parameterNames;
|
||||
xmlNodeList parameterNodes;
|
||||
FindParameters(cameraContainerNode, parameterNames, parameterNodes);
|
||||
FindParameters(maxTechniqueNode, parameterNames, parameterNodes);
|
||||
FindParameters(mayaProgramNode, parameterNames, parameterNodes);
|
||||
|
||||
#define CAM_PARAMETER(colladaParam, memberFunction, animatedMember) \
|
||||
if (parameterName == colladaParam) { \
|
||||
memberFunction(FUStringConversion::ToFloat(parameterValue)); \
|
||||
FCDAnimatedFloat::Create(GetDocument(), parameterNode, &animatedMember); } else
|
||||
|
||||
size_t parameterCount = parameterNodes.size();
|
||||
for (size_t i = 0; i < parameterCount; ++i)
|
||||
{
|
||||
xmlNode* parameterNode = parameterNodes[i];
|
||||
const string& parameterName = parameterNames[i];
|
||||
const char* parameterValue = ReadNodeContentDirect(parameterNode);
|
||||
|
||||
// Process the camera parameters
|
||||
CAM_PARAMETER(DAE_ZNEAR_CAMERA_PARAMETER, SetNearZ, nearZ)
|
||||
CAM_PARAMETER(DAE_ZFAR_CAMERA_PARAMETER, SetFarZ, farZ)
|
||||
CAM_PARAMETER(DAE_XFOV_CAMERA_PARAMETER, SetFovX, viewX)
|
||||
CAM_PARAMETER(DAE_YFOV_CAMERA_PARAMETER, SetFovY, viewY)
|
||||
CAM_PARAMETER(DAE_XMAG_CAMERA_PARAMETER, SetMagX, viewX)
|
||||
CAM_PARAMETER(DAE_YMAG_CAMERA_PARAMETER, SetMagY, viewY)
|
||||
CAM_PARAMETER(DAE_ASPECT_CAMERA_PARAMETER, SetAspectRatio, aspectRatio)
|
||||
CAM_PARAMETER(DAEMAYA_VAPERTURE_PARAMETER, SetVerticalAperture, verticalAperture)
|
||||
CAM_PARAMETER(DAEMAYA_HAPERTURE_PARAMETER, SetHorizontalAperture, horizontalAperture)
|
||||
CAM_PARAMETER(DAEMAYA_LENSSQUEEZE_PARAMETER, SetLensSqueeze, lensSqueeze)
|
||||
if (parameterName == DAEMAX_TARGET_CAMERA_PARAMETER)
|
||||
SetTargetId(parameterValue);
|
||||
else
|
||||
|
||||
// COLLADA 1.3 backward compatibility
|
||||
CAM_PARAMETER(DAE_ZNEAR_CAMERA_PARAMETER1_3, SetNearZ, nearZ)
|
||||
CAM_PARAMETER(DAE_ZFAR_CAMERA_PARAMETER1_3, SetFarZ, farZ)
|
||||
CAM_PARAMETER(DAE_XFOV_CAMERA_PARAMETER1_3, SetFovX, viewX)
|
||||
CAM_PARAMETER(DAE_YFOV_CAMERA_PARAMETER1_3, SetFovY, viewY)
|
||||
CAM_PARAMETER(DAE_RIGHT_CAMERA_PARAMETER1_3, SetMagX, viewX)
|
||||
CAM_PARAMETER(DAE_TOP_CAMERA_PARAMETER1_3, SetMagY, viewY)
|
||||
CAM_PARAMETER(DAEMAYA_VAPERTURE_PARAMETER1_3, SetVerticalAperture, verticalAperture)
|
||||
CAM_PARAMETER(DAEMAYA_HAPERTURE_PARAMETER1_3, SetHorizontalAperture, horizontalAperture)
|
||||
CAM_PARAMETER(DAEMAYA_LENSSQUEEZE_PARAMETER1_3, SetLensSqueeze, lensSqueeze)
|
||||
if (parameterName == DAE_LEFT_CAMERA_PARAMETER1_3) {} // Don't process
|
||||
else if (parameterName == DAE_BOTTOM_CAMERA_PARAMETER1_3) {} // Don't process
|
||||
|
||||
// Max-specific parameter: target
|
||||
else if (parameterName == DAEMAX_TARGET_CAMERA_PARAMETER
|
||||
|| parameterName == DAEMAX_TARGET_CAMERA_PARAMETER1_3)
|
||||
{
|
||||
SetTargetId(parameterValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
status.Warning(FS("Unknown parameter for camera: ") + TO_FSTRING(GetDaeId()), parameterNode->line);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out this camera to the COLLADA XML document
|
||||
xmlNode* FCDCamera::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
// Create the base camera node
|
||||
xmlNode* cameraNode = WriteToEntityXML(parentNode, DAE_CAMERA_ELEMENT);
|
||||
xmlNode* opticsNode = AddChild(cameraNode, DAE_OPTICS_ELEMENT);
|
||||
xmlNode* baseNode = AddChild(opticsNode, DAE_TECHNIQUE_COMMON_ELEMENT);
|
||||
const char* baseNodeName;
|
||||
if (isPerspective) baseNodeName = DAE_CAMERA_PERSP_ELEMENT;
|
||||
else if (isOrthographic) baseNodeName = DAE_CAMERA_ORTHO_ELEMENT;
|
||||
else baseNodeName = DAEERR_UNKNOWN_ELEMENT;
|
||||
baseNode = AddChild(baseNode, baseNodeName);
|
||||
|
||||
// Write out the basic camera parameters
|
||||
if (isPerspective)
|
||||
{
|
||||
if (hasHorizontalView)
|
||||
{
|
||||
xmlNode* viewNode = AddChild(baseNode, DAE_XFOV_CAMERA_PARAMETER, viewX);
|
||||
GetDocument()->WriteAnimatedValueToXML(&viewX, viewNode, "horizontal_fov");
|
||||
}
|
||||
if (!hasHorizontalView || hasVerticalView)
|
||||
{
|
||||
xmlNode* viewNode = AddChild(baseNode, DAE_YFOV_CAMERA_PARAMETER, viewY);
|
||||
GetDocument()->WriteAnimatedValueToXML(&viewY, viewNode, "vertical_fov");
|
||||
}
|
||||
if (!hasHorizontalView || !hasVerticalView)
|
||||
{
|
||||
xmlNode* aspectNode = AddChild(baseNode, DAE_ASPECT_CAMERA_PARAMETER, aspectRatio);
|
||||
GetDocument()->WriteAnimatedValueToXML(&aspectRatio, aspectNode, "aspect_ratio");
|
||||
}
|
||||
}
|
||||
if (isOrthographic)
|
||||
{
|
||||
if (hasHorizontalView)
|
||||
{
|
||||
xmlNode* viewNode = AddChild(baseNode, DAE_XMAG_CAMERA_PARAMETER, viewX);
|
||||
GetDocument()->WriteAnimatedValueToXML(&viewX, viewNode, "horizontal_zoom");
|
||||
}
|
||||
if (!hasHorizontalView || hasVerticalView)
|
||||
{
|
||||
xmlNode* viewNode = AddChild(baseNode, DAE_YMAG_CAMERA_PARAMETER, viewY);
|
||||
GetDocument()->WriteAnimatedValueToXML(&viewY, viewNode, "vertical_zoom");
|
||||
}
|
||||
if (!hasHorizontalView || !hasVerticalView)
|
||||
{
|
||||
xmlNode* aspectNode = AddChild(baseNode, DAE_ASPECT_CAMERA_PARAMETER, aspectRatio);
|
||||
GetDocument()->WriteAnimatedValueToXML(&aspectRatio, aspectNode, "aspect_ratio");
|
||||
}
|
||||
}
|
||||
|
||||
// Near/Far clip plane distance
|
||||
xmlNode* clipNode = AddChild(baseNode, DAE_ZNEAR_CAMERA_PARAMETER, nearZ);
|
||||
GetDocument()->WriteAnimatedValueToXML(&nearZ, clipNode, "near_clip");
|
||||
clipNode = AddChild(baseNode, DAE_ZFAR_CAMERA_PARAMETER, farZ);
|
||||
GetDocument()->WriteAnimatedValueToXML(&farZ, clipNode, "near_clip");
|
||||
|
||||
// Add the application-specific technique/parameters
|
||||
// Maya has extra aperture information
|
||||
if (hasAperture)
|
||||
{
|
||||
xmlNode* techniqueMayaNode = AddTechniqueChild(opticsNode, DAEMAYA_MAYA_PROFILE);
|
||||
xmlNode* apertureNode = AddChild(techniqueMayaNode, DAEMAYA_VAPERTURE_PARAMETER, verticalAperture);
|
||||
GetDocument()->WriteAnimatedValueToXML(&verticalAperture, apertureNode, "vertical_aperture");
|
||||
apertureNode = AddChild(techniqueMayaNode, DAEMAYA_HAPERTURE_PARAMETER, horizontalAperture);
|
||||
GetDocument()->WriteAnimatedValueToXML(&horizontalAperture, apertureNode, "horizontal_aperture");
|
||||
apertureNode = AddChild(techniqueMayaNode, DAEMAYA_LENSSQUEEZE_PARAMETER, lensSqueeze);
|
||||
GetDocument()->WriteAnimatedValueToXML(&lensSqueeze, apertureNode, "lens_squeeze");
|
||||
}
|
||||
|
||||
// Max has target information
|
||||
if (GetTargetNode() != NULL)
|
||||
{
|
||||
xmlNode* techniqueMaxNode = AddTechniqueChild(opticsNode, DAEMAX_MAX_PROFILE);
|
||||
AddChild(techniqueMaxNode, DAEMAX_TARGET_CAMERA_PARAMETER, GetTargetNode()->GetDaeId());
|
||||
}
|
||||
|
||||
FCDEntity::WriteToExtraXML(cameraNode);
|
||||
return cameraNode;
|
||||
}
|
||||
@@ -1,255 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDCamera.h
|
||||
This file contains the FCDCamera class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_CAMERA_H_
|
||||
#define _FCD_CAMERA_H_
|
||||
|
||||
#include "FCDocument/FCDTargetedEntity.h"
|
||||
|
||||
class FCDocument;
|
||||
class FCDSceneNode;
|
||||
|
||||
/**
|
||||
A COLLADA camera.
|
||||
Based on the FCDTargetedEntity class to support aimed cameras.
|
||||
COLLADA defines two types of cameras: perspective and orthographic.
|
||||
Both types are fully handled by this class.
|
||||
|
||||
A COLLADA perspective camera defines two of the three following parameters: horizontal field of view,
|
||||
vertical field of view and aspect ratio. The missing parameter can be calculated using the following formulae:
|
||||
aspect ratio = vertical field of view / horizontal field of view. The vertical and horizontal field
|
||||
of view are in degrees.
|
||||
|
||||
A COLLADA orthographic camera defines two of the three following parameters: horizontal magnification,
|
||||
vertical magnification and aspect ratio. The missing parameter can be calculated using the following formulae:
|
||||
aspect ratio = vertical magnification / horizontal magnification. You can calculate the viewport width
|
||||
and height using the following formulas: viewport width = horizontal magnification * 2, viewport height
|
||||
= vertical magnification * 2.
|
||||
|
||||
@ingroup FCDocument
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDCamera : public FCDTargetedEntity
|
||||
{
|
||||
private:
|
||||
// Camera flags
|
||||
bool isPerspective;
|
||||
bool isOrthographic;
|
||||
bool hasHorizontalView;
|
||||
bool hasVerticalView;
|
||||
|
||||
// Camera parameters
|
||||
float viewY;
|
||||
float viewX;
|
||||
float nearZ;
|
||||
float farZ;
|
||||
float aspectRatio;
|
||||
|
||||
// Maya parameters
|
||||
bool hasAperture;
|
||||
float verticalAperture;
|
||||
float horizontalAperture;
|
||||
float lensSqueeze;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly. Create new cameras using the FCDLibrary::AddEntity function.
|
||||
@param document The COLLADA document that contains this camera entity.*/
|
||||
FCDCamera(FCDocument* document);
|
||||
|
||||
/** Destructor: do not release directly. Release cameras using the FCDLibrary::ReleaseEntity function.
|
||||
All cameras are released with the document that they belong to. */
|
||||
virtual ~FCDCamera();
|
||||
|
||||
/** Retrieves the entity type for this class. This function is part of the FCDEntity interface.
|
||||
@return The entity type: CAMERA. */
|
||||
virtual Type GetType() const { return CAMERA; }
|
||||
|
||||
/** Retrieves whether this camera is a perspective camera.
|
||||
This is the default type of camera.
|
||||
@return Whether this camera is a perspective camera.*/
|
||||
inline bool IsPerspective() const { return isPerspective; }
|
||||
|
||||
/** Sets the type of this camera to perspective. */
|
||||
inline void SetPerspective() { isPerspective = true; isOrthographic = false; }
|
||||
|
||||
/** Retrieves whether the perspective camera defines an horizontal field of view.
|
||||
If the camera does not define the horizontal field of view, you can calculate
|
||||
it using the following formula: horizontal field of view = vertical field of view / aspect ratio.
|
||||
@return Whether the perspective camera defines an horizontal field of view. */
|
||||
inline bool HasHorizontalFov() const { return hasHorizontalView; }
|
||||
|
||||
/** Retrieves whether the perspective camera defines a vertical field of view.
|
||||
If the camera does not define the vertical field of view, you can calculate
|
||||
it using the following formula: vertical field of view = aspect ratio * horizontal field of view.
|
||||
@return Whether the perspective camera defines a vertical field of view. */
|
||||
inline bool HasVerticalFov() const { return hasVerticalView; }
|
||||
|
||||
/** Retrieves the horizontal field of view. Before retrieving this value,
|
||||
check whether the camera defines the horizontal field of view using the
|
||||
HasHorizontalFov function.
|
||||
@return The horizontal field of view, in degrees. */
|
||||
inline float& GetFovX() { return viewX; }
|
||||
inline const float& GetFovX() const { return viewX; } /**< See above. */
|
||||
|
||||
/** Retrieves the vertical field of view. Before retrieving this value,
|
||||
check whether the camera defines the vertical field of view using the
|
||||
HasVerticalFov function.
|
||||
@return The horizontal field of view, in degrees. */
|
||||
inline float& GetFovY() { return viewY; }
|
||||
inline const float& GetFovY() const { return viewY; } /**< See above. */
|
||||
|
||||
/** Sets the horizontal field of view value for this camera.
|
||||
@param fovX The new horizontal field of view, in degrees. */
|
||||
void SetFovX(float fovX);
|
||||
|
||||
/** Sets the vertical field of view value for this camera.
|
||||
@param fovY The new vertical field of view, in degrees. */
|
||||
void SetFovY(float fovY);
|
||||
|
||||
/** Retrieves whether this camera is an orthographic camera.
|
||||
@return Whether this camera is an orthographic camera. */
|
||||
inline bool IsOrthographic() const { return isOrthographic; }
|
||||
|
||||
/** Sets the type of this camera to orthographic. */
|
||||
inline void SetOrthographic() { isPerspective = false; isOrthographic = true; }
|
||||
|
||||
/** Retrieves whether the orthographic camera defines an horizontal magnification.
|
||||
If the camera does not define the horizontal magnification, you can calculate
|
||||
it using the following formula: horizontal magnification = vertical magnification / aspect ratio.
|
||||
@return Whether the orthographic camera defines an horizontal magnification. */
|
||||
inline bool HasHorizontalMag() const { return hasHorizontalView; }
|
||||
|
||||
/** Retrieves whether the perspective camera defines a vertical magnification.
|
||||
If the camera does not define the vertical magnification, you can calculate
|
||||
it using the following formula: vertical magnification = aspect ratio * horizontal magnification.
|
||||
@return Whether the perspective camera defines a vertical magnification. */
|
||||
inline bool HasVerticalMag() const { return hasVerticalView; }
|
||||
|
||||
/** Retrieves the horizontal magnification. Before retrieving this value,
|
||||
check whether the camera defines the horizontal magnification using the
|
||||
HasHorizontalMag function.
|
||||
@return The horizontal magnification. */
|
||||
inline float& GetMagX() { return viewX; }
|
||||
inline const float& GetMagX() const { return viewX; } /**< See above. */
|
||||
|
||||
/** Retrieves the vertical magnification. Before retrieving this value,
|
||||
check whether the camera defines the vertical magnification using the
|
||||
HasVerticalMag function.
|
||||
@return The vertical magnification. */
|
||||
inline float& GetMagY() { return viewY; }
|
||||
inline const float& GetMagY() const { return viewY; } /**< See above. */
|
||||
|
||||
/** Sets the horizontal magnification for this camera.
|
||||
@param magX The new horizontal magnification, in degrees. */
|
||||
inline void SetMagX(float magX) { return SetFovX(magX); }
|
||||
|
||||
/** Sets the vertical magnification value for this camera.
|
||||
@param magY The new vertical magnification, in degrees. */
|
||||
inline void SetMagY(float magY) { return SetFovY(magY); }
|
||||
|
||||
/** Retrieves the near-z value for this camera.
|
||||
The near-z value represent how close the near-clip
|
||||
plane of the view frustrum is. For orthographic cameras,
|
||||
this value is solely used for depth-buffering.
|
||||
@return The near-z value for this camera. */
|
||||
inline float& GetNearZ() { return nearZ; }
|
||||
inline const float& GetNearZ() const { return nearZ; } /**< See above. */
|
||||
|
||||
/** Retrieves the far-z value for this camera. The far-z value represent
|
||||
how close the far-clip plane of the view frustrum is.
|
||||
For orthographic cameras, this value is solely used for depth-buffering.
|
||||
@return The far-z value for this camera. */
|
||||
inline float& GetFarZ() { return farZ; }
|
||||
inline const float& GetFarZ() const { return farZ; } /**< See above. */
|
||||
|
||||
/** Retrieves the aspect ratio for the view of this camera. Before using this value,
|
||||
check if there are only one of the horizontal and vertical view ratios.
|
||||
If there are both of the view ratios provided for the camera, you will
|
||||
need to calculate the aspect ratio using the following formula:
|
||||
aspect ratio = vertical field of view / horizontal field of view.
|
||||
@return The view aspect ratio. */
|
||||
inline float& GetAspectRatio() { return aspectRatio; }
|
||||
inline const float& GetAspectRatio() const { return aspectRatio; } /**< See above. */
|
||||
|
||||
/** Sets the near-z value for this camera.
|
||||
The near-z value represent how close the near-clip
|
||||
plane of the view frustrum is. For orthographic cameras,
|
||||
this value is solely used for depth-buffering.
|
||||
@param _nearZ A valid near-z value. No check is made to verify that the
|
||||
near-z value is greather than the far-z value.*/
|
||||
inline void SetNearZ(float _nearZ) { nearZ = _nearZ; }
|
||||
|
||||
/** Sets the far-z value for this camera. The far-z value represent
|
||||
how close the far-clip plane of the view frustrum is.
|
||||
For orthographic cameras, this value is solely used for depth-buffering.
|
||||
@param _farZ A valid far-z value. No check is made to verify that the
|
||||
far-z value is greather than the near-z value.*/
|
||||
inline void SetFarZ(float _farZ) { farZ = _farZ; }
|
||||
|
||||
/** Sets the aspect ratio for the view of this camera.
|
||||
@param aspectRatio The new view aspect ratio. */
|
||||
void SetAspectRatio(float aspectRatio);
|
||||
|
||||
/** Retrieves whether the camera provides aperture information. This information is specific
|
||||
to COLLADA documents exported from ColladaMaya.
|
||||
@return Whether the camera provides aperture information. */
|
||||
inline bool HasAperture() const { return hasAperture; }
|
||||
|
||||
/** Retrieves the vertical aperture of the camera. This information is specific to
|
||||
COLLADA documents exported from ColladaMaya.
|
||||
@return The vertical aperture of the camera. */
|
||||
inline float& GetVerticalAperture() { return verticalAperture; }
|
||||
inline const float& GetVerticalAperture() const { return verticalAperture; } /**< See above. */
|
||||
|
||||
/** Retrieves the horizontal aperture of the camera. This information is specific to
|
||||
COLLADA documents exported from ColladaMaya.
|
||||
@return The horizontal aperture of the camera. */
|
||||
inline float& GetHorizontalAperture() { return horizontalAperture; }
|
||||
inline const float& GetHorizontalAperture() const { return horizontalAperture; } /**< See above. */
|
||||
|
||||
/** Retrieves the lens squeeze of the camera. This information is specific to
|
||||
COLLADA documents exported from ColladaMaya. The lens squeeze of the camera
|
||||
is a multiplier that acts directly on the horizontal aperture, following this
|
||||
formula: real horizontal aperture = given horizontal aperture * lens squeeze.
|
||||
@return The lens squeeze of the camera. */
|
||||
inline float& GetLensSqueeze() { return lensSqueeze; }
|
||||
inline const float& GetLensSqueeze() const { return lensSqueeze; } /**< See above. */
|
||||
|
||||
/** Sets the vertical aperture of the camera.
|
||||
@param aperture The vertical aperture of the camera. */
|
||||
inline void SetVerticalAperture(float aperture) { verticalAperture = aperture; hasAperture = true; }
|
||||
|
||||
/** Sets the horizontal aperture of the camera.
|
||||
@param aperture The horizontal aperture of the camera. */
|
||||
inline void SetHorizontalAperture(float aperture) { horizontalAperture = aperture; hasAperture = true; }
|
||||
|
||||
/** Sets the lens squeeze of the camera.
|
||||
@param factor The lense squeeze of the camera. */
|
||||
inline void SetLensSqueeze(float factor) { lensSqueeze = factor; }
|
||||
|
||||
/** [INTERNAL] Reads in the \<camera\> element from a given COLLADA XML tree node.
|
||||
@param cameraNode A COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the camera.*/
|
||||
FUStatus LoadFromXML(xmlNode* cameraNode);
|
||||
|
||||
/** [INTERNAL] Writes out the \<camera\> element to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the geometry information.
|
||||
@return The created XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif // _FCD_CAMERA_H_
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDController.h"
|
||||
#include "FCDocument/FCDSkinController.h"
|
||||
#include "FCDocument/FCDMorphController.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
using namespace FUDaeParser;
|
||||
|
||||
FCDController::FCDController(FCDocument* document) : FCDEntity(document, "Controller")
|
||||
{
|
||||
skinController = NULL;
|
||||
morphController = NULL;
|
||||
}
|
||||
|
||||
FCDController::~FCDController()
|
||||
{
|
||||
SAFE_DELETE(skinController);
|
||||
SAFE_DELETE(morphController);
|
||||
}
|
||||
|
||||
|
||||
// Sets the type of this controller to a skin controller.
|
||||
FCDSkinController* FCDController::CreateSkinController()
|
||||
{
|
||||
SAFE_DELETE(skinController);
|
||||
SAFE_DELETE(morphController);
|
||||
skinController = new FCDSkinController(GetDocument(), this);
|
||||
return skinController;
|
||||
}
|
||||
|
||||
// Sets the type of this controller to a morph controller.
|
||||
FCDMorphController* FCDController::CreateMorphController()
|
||||
{
|
||||
SAFE_DELETE(skinController);
|
||||
SAFE_DELETE(morphController);
|
||||
morphController = new FCDMorphController(GetDocument(), this);
|
||||
return morphController;
|
||||
}
|
||||
|
||||
FCDEntity* FCDController::GetBaseTarget()
|
||||
{
|
||||
if (skinController != NULL) return skinController->GetTarget();
|
||||
else if (morphController != NULL) return morphController->GetBaseTarget();
|
||||
else return NULL;
|
||||
}
|
||||
|
||||
const FCDEntity* FCDController::GetBaseTarget() const
|
||||
{
|
||||
if (skinController != NULL) return skinController->GetTarget();
|
||||
else if (morphController != NULL) return morphController->GetBaseTarget();
|
||||
else return NULL;
|
||||
}
|
||||
|
||||
// Load this controller from a Collada <controller> node
|
||||
FUStatus FCDController::LoadFromXML(xmlNode* controllerNode)
|
||||
{
|
||||
FUStatus status = FCDEntity::LoadFromXML(controllerNode);
|
||||
if (!status) return status;
|
||||
if (!IsEquivalent(controllerNode->name, DAE_CONTROLLER_ELEMENT))
|
||||
{
|
||||
return status.Warning(FS("Unexpected node in controller library: <") + TO_FSTRING((const char*) controllerNode->name) + FC(">."), controllerNode->line);
|
||||
}
|
||||
|
||||
// COLLADA 1.3 backward compatiblity: read in the 'target' attribute
|
||||
targetId = ReadNodeProperty(controllerNode, DAE_TARGET_ATTRIBUTE);
|
||||
|
||||
// Find the <skin> or <morph> element and process it
|
||||
xmlNode* skinNode = FindChildByType(controllerNode, DAE_CONTROLLER_SKIN_ELEMENT);
|
||||
xmlNode* morphNode = FindChildByType(controllerNode, DAE_CONTROLLER_MORPH_ELEMENT);
|
||||
if (skinNode != NULL && morphNode != NULL)
|
||||
{
|
||||
status.Warning(FS("A controller cannot be both a skin and a morpher: ") + TO_FSTRING(GetDaeId()), controllerNode->line);
|
||||
}
|
||||
if (skinNode != NULL)
|
||||
{
|
||||
// Create and parse in the skin controller
|
||||
FCDSkinController* controller = CreateSkinController();
|
||||
status.AppendStatus(controller->LoadFromXML(skinNode));
|
||||
}
|
||||
else if (morphNode != NULL)
|
||||
{
|
||||
// Create and parse in the morph controller
|
||||
FCDMorphController* controller = CreateMorphController();
|
||||
status.AppendStatus(controller->LoadFromXML(morphNode));
|
||||
}
|
||||
else
|
||||
{
|
||||
status.Warning(FS("No base type element, <skin> or <morph>, found for controller: ") + TO_FSTRING(GetDaeId()), controllerNode->line);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out this controller to a COLLADA xml node tree
|
||||
xmlNode* FCDController::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* controllerNode = FCDEntity::WriteToEntityXML(parentNode, DAE_CONTROLLER_ELEMENT);
|
||||
if (skinController != NULL) skinController->WriteToXML(controllerNode);
|
||||
if (morphController != NULL) morphController->WriteToXML(controllerNode);
|
||||
FCDEntity::WriteToExtraXML(controllerNode);
|
||||
return controllerNode;
|
||||
}
|
||||
|
||||
// Link this controller to the rest of the document: joints/base geometry...
|
||||
FUStatus FCDController::Link()
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// Link the controller
|
||||
if (skinController != NULL) status.AppendStatus(skinController->Link());
|
||||
if (morphController != NULL) status.AppendStatus(morphController->Link());
|
||||
return status;
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDController.h
|
||||
This file contains the FCDController class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_CONTROLLER_H_
|
||||
#define _FCD_CONTROLLER_H_
|
||||
|
||||
#include "FCDocument/FCDEntity.h"
|
||||
|
||||
class FCDocument;
|
||||
class FCDSkinController;
|
||||
class FCDMorphController;
|
||||
|
||||
/**
|
||||
A generic COLLADA controller.
|
||||
A COLLADA controller is used to influence a mesh.
|
||||
COLLADA defines two types of controller:
|
||||
skins (FCDSkinController) and morphers (FCDMorphController).
|
||||
|
||||
@ingroup FCDGeometry
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDController : public FCDEntity
|
||||
{
|
||||
private:
|
||||
string targetId; // COLLADA 1.3 backward compatibility
|
||||
|
||||
FCDSkinController* skinController;
|
||||
FCDMorphController* morphController;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDLibrary::AddEntity function.
|
||||
@param document The COLLADA document that owns the controller. */
|
||||
FCDController(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDLibrary::ReleaseEntity function. */
|
||||
virtual ~FCDController();
|
||||
|
||||
/** Retrieves the entity class type.
|
||||
This function is a part of the FCDEntity interface.
|
||||
@return The entity class type: CONTROLLER. */
|
||||
virtual Type GetType() const { return CONTROLLER; };
|
||||
|
||||
/** Retrieves whether this controller is a skin controller.
|
||||
@return Whether this controller is a skin controller. */
|
||||
bool HasSkinController() const { return skinController != NULL; }
|
||||
|
||||
/** Retrieves whether this controller is a morph controller.
|
||||
@return Whether this controller is a morph controller. */
|
||||
bool HasMorphController() const { return morphController != NULL; }
|
||||
|
||||
/** Sets the type of this controller to a skin controller.
|
||||
This function will release any previously created morpher or skin.
|
||||
@return The new skin controller. */
|
||||
FCDSkinController* CreateSkinController();
|
||||
|
||||
/** Sets the type of this controller to a morph controller.
|
||||
This function will release any previously created morpher or skin.
|
||||
@return The new morph controller. */
|
||||
FCDMorphController* CreateMorphController();
|
||||
|
||||
/** Retrieves the skin controller.
|
||||
This pointer is only valid for skins. To verify that this is a skin,
|
||||
check the HasSkinController function.
|
||||
@return The skin controller. This pointer will be NULL, if the controller
|
||||
is not a skin. */
|
||||
FCDSkinController* GetSkinController() { return skinController; }
|
||||
const FCDSkinController* GetSkinController() const { return skinController; } /**< See above. */
|
||||
|
||||
/** Retrieves the morph controller.
|
||||
This pointer is only valid for skins. To verify that this is a morpher,
|
||||
check the HasMorphController function.
|
||||
@return The morph controller. This pointer will be NULL, if the controller
|
||||
is not a morpher. */
|
||||
FCDMorphController* GetMorphController() { return morphController; }
|
||||
const FCDMorphController* GetMorphController() const { return morphController; } /**< See above. */
|
||||
|
||||
/** Retrieves the base target entity for this controller.
|
||||
The base target entity may be another controller or a geometry entity.
|
||||
To change the base target, use the FCDMorphController::SetBaseTarget
|
||||
or the FCDSkinController::SetTarget functions.
|
||||
@return The base target entity. This pointer will be NULL, if no base target is defined. */
|
||||
FCDEntity* GetBaseTarget();
|
||||
const FCDEntity* GetBaseTarget() const; /**< See above. */
|
||||
|
||||
/** [INTERNAL] Retrieves the COLLADA id of the target entity.
|
||||
This value is only useful for COLLADA 1.3 backward compatibility.
|
||||
For more recent COLLADA documents, this value is unused.
|
||||
@return The COLLADA id of the target entity. */
|
||||
const string& GetTargetId() const { return targetId; }
|
||||
|
||||
/** [INTERNAL] Reads in the \<controller\> element from a given COLLADA XML tree node.
|
||||
@param controllerNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the controller.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* controllerNode);
|
||||
|
||||
/** [INTERNAL] Writes out the \<controller\> element to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the controller information.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
|
||||
/** [INTERNAL] Links the controller entities with their many targets/influences.
|
||||
This function is executed for all the controllers, after the scene graph has been imported.
|
||||
It is mainly used to link the skin and its bones.
|
||||
@return The status of the linkage.*/
|
||||
FUStatus Link();
|
||||
};
|
||||
|
||||
#endif // _FCD_CONTROLLER_H_
|
||||
|
||||
@@ -1,268 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDAnimated.h"
|
||||
#include "FCDocument/FCDEffect.h"
|
||||
#include "FCDocument/FCDEffectStandard.h"
|
||||
#include "FCDocument/FCDEffectProfileFX.h"
|
||||
#include "FCDocument/FCDEffectParameter.h"
|
||||
#include "FCDocument/FCDEffectParameterFactory.h"
|
||||
#include "FCDocument/FCDEffectParameterList.h"
|
||||
#include "FCDocument/FCDLibrary.h"
|
||||
#include "FCDocument/FCDImage.h"
|
||||
#include "FUtils/FUStringConversion.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDEffect::FCDEffect(FCDocument* document) : FCDEntity(document, "Effect")
|
||||
{
|
||||
parameters = new FCDEffectParameterList(GetDocument(), true);
|
||||
}
|
||||
|
||||
FCDEffect::~FCDEffect()
|
||||
{
|
||||
SAFE_DELETE(parameters);
|
||||
CLEAR_POINTER_VECTOR(profiles);
|
||||
}
|
||||
|
||||
void FCDEffect::AddParameter(FCDEffectParameter* parameter)
|
||||
{
|
||||
parameters->push_back(parameter);
|
||||
}
|
||||
|
||||
// Flatten this effect: trickling down all the parameters to the technique level
|
||||
void FCDEffect::Flatten()
|
||||
{
|
||||
for (FCDEffectParameterList::iterator itP = parameters->begin(); itP != parameters->end(); ++itP)
|
||||
{
|
||||
FCDEffectParameterList generators;
|
||||
if ((*itP)->IsModifier())
|
||||
{
|
||||
// Overwrite the generators
|
||||
FindParametersByReference((*itP)->GetReference(), generators);
|
||||
for (FCDEffectParameterList::iterator itQ = generators.begin(); itQ != generators.end(); ++itQ)
|
||||
{
|
||||
if ((*itP) != (*itQ))
|
||||
{
|
||||
(*itP)->Overwrite(*itQ);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add this parameter to hierarchies below
|
||||
for (FCDEffectProfileList::iterator itR = profiles.begin(); itR != profiles.end(); ++itR)
|
||||
{
|
||||
if ((*itR)->GetType() != FUDaeProfileType::COMMON)
|
||||
{
|
||||
((FCDEffectProfileFX*) (*itR))->AddParameter((*itP)->Clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
CLEAR_POINTER_VECTOR(*parameters);
|
||||
|
||||
for (FCDEffectProfileList::iterator itR = profiles.begin(); itR != profiles.end(); ++itR)
|
||||
{
|
||||
(*itR)->Flatten();
|
||||
}
|
||||
}
|
||||
|
||||
// Search for a profile of the given type
|
||||
FCDEffectProfile* FCDEffect::FindProfile(FUDaeProfileType::Type type)
|
||||
{
|
||||
for (FCDEffectProfileList::iterator itR = profiles.begin(); itR != profiles.end(); ++itR)
|
||||
{
|
||||
if ((*itR)->GetType() == type) return (*itR);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const FCDEffectProfile* FCDEffect::FindProfile(FUDaeProfileType::Type type) const
|
||||
{
|
||||
for (FCDEffectProfileList::const_iterator itR = profiles.begin(); itR != profiles.end(); ++itR)
|
||||
{
|
||||
if ((*itR)->GetType() == type) return (*itR);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create a new effect profile.
|
||||
FCDEffectProfile* FCDEffect::AddProfile(FUDaeProfileType::Type type)
|
||||
{
|
||||
// Delete any old profile of the same type
|
||||
FCDEffectProfile* profile = FindProfile(type);
|
||||
if (profile != NULL)
|
||||
{
|
||||
ReleaseProfile(profile);
|
||||
profile = NULL;
|
||||
}
|
||||
|
||||
// Create the correct profile for this type.
|
||||
if (type == FUDaeProfileType::COMMON) profile = new FCDEffectStandard(GetDocument(), this);
|
||||
else profile = new FCDEffectProfileFX(GetDocument(), this, type);
|
||||
|
||||
profiles.push_back(profile);
|
||||
return profile;
|
||||
}
|
||||
|
||||
// Releases the effect profile.
|
||||
void FCDEffect::ReleaseProfile(FCDEffectProfile* profile)
|
||||
{
|
||||
FCDEffectProfileList::iterator itR = std::find(profiles.begin(), profiles.end(), profile);
|
||||
if (itR != profiles.end())
|
||||
{
|
||||
delete *itR;
|
||||
profiles.erase(itR);
|
||||
}
|
||||
}
|
||||
|
||||
// Look for the effect parameter with the correct semantic, in order to bind/set its value
|
||||
FCDEffectParameter* FCDEffect::FindParameterBySemantic(const string& semantic)
|
||||
{
|
||||
FCDEffectParameter* p = parameters->FindSemantic(semantic);
|
||||
for (FCDEffectProfileList::iterator itR = profiles.begin(); itR != profiles.end() && p == NULL; ++itR)
|
||||
{
|
||||
p = (*itR)->FindParameterBySemantic(semantic);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void FCDEffect::FindParametersBySemantic(const string& semantic, FCDEffectParameterList& _parameters)
|
||||
{
|
||||
parameters->FindSemantic(semantic, _parameters);
|
||||
for (FCDEffectProfileList::iterator itR = profiles.begin(); itR != profiles.end(); ++itR)
|
||||
{
|
||||
(*itR)->FindParametersBySemantic(semantic, _parameters);
|
||||
}
|
||||
}
|
||||
|
||||
void FCDEffect::FindParametersByReference(const string& reference, FCDEffectParameterList& _parameters)
|
||||
{
|
||||
parameters->FindReference(reference, _parameters);
|
||||
for (FCDEffectProfileList::iterator itR = profiles.begin(); itR != profiles.end(); ++itR)
|
||||
{
|
||||
(*itR)->FindParametersBySemantic(reference, _parameters);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse COLLADA document's <effect> element
|
||||
// Also parses the <material> element for COLLADA 1.3 backward compatibility
|
||||
FUStatus FCDEffect::LoadFromXML(xmlNode* effectNode)
|
||||
{
|
||||
FUStatus status = FCDEntity::LoadFromXML(effectNode);
|
||||
if (!status) return status;
|
||||
|
||||
CLEAR_POINTER_VECTOR(*parameters);
|
||||
|
||||
// COLLADA 1.3 backward compatibility: look for a <material><shader> node and parse this into a standard effect.
|
||||
if (IsEquivalent(effectNode->name, DAE_MATERIAL_ELEMENT))
|
||||
{
|
||||
xmlNode* shaderNode = FindChildByType(effectNode, DAE_SHADER_ELEMENT);
|
||||
if (shaderNode != NULL)
|
||||
{
|
||||
FCDEffectProfile* profile = AddProfile(FUDaeProfileType::COMMON);
|
||||
status.AppendStatus(profile->LoadFromXML(shaderNode));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Accept solely <effect> elements at this point.
|
||||
if (!IsEquivalent(effectNode->name, DAE_EFFECT_ELEMENT))
|
||||
{
|
||||
return status.Warning(FS("Unknown element in effect library."), effectNode->line);
|
||||
}
|
||||
|
||||
for (xmlNode* child = effectNode->children; child != NULL; child = child->next)
|
||||
{
|
||||
if (child->type != XML_ELEMENT_NODE) continue;
|
||||
|
||||
if (IsEquivalent(child->name, DAE_IMAGE_ELEMENT))
|
||||
{
|
||||
FCDImage* image = GetDocument()->GetImageLibrary()->AddEntity();
|
||||
status.AppendStatus(image->LoadFromXML(child));
|
||||
images.push_back(image);
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_SETPARAM_ELEMENT) || IsEquivalent(child->name, DAE_FXCMN_NEWPARAM_ELEMENT))
|
||||
{
|
||||
AddParameter(FCDEffectParameterFactory::LoadFromXML(GetDocument(), child, &status));
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_EXTRA_ELEMENT))
|
||||
{
|
||||
// Valid element.. but not processed.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check for a valid profile element.
|
||||
FUDaeProfileType::Type type = FUDaeProfileType::FromString((const char*) child->name);
|
||||
if (type != FUDaeProfileType::UNKNOWN)
|
||||
{
|
||||
FCDEffectProfile* profile = AddProfile(type);
|
||||
status.AppendStatus(profile->LoadFromXML(child));
|
||||
}
|
||||
else
|
||||
{
|
||||
status.Warning(FS("Unsupported profile or unknown element in effect: ") + TO_FSTRING(GetDaeId()), child->line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Returns a copy of the effect, with all the animations/textures attached
|
||||
FCDEffect* FCDEffect::Clone()
|
||||
{
|
||||
FCDEffect* clone = new FCDEffect(GetDocument());
|
||||
FCDEntity::Clone(clone);
|
||||
|
||||
for (FCDEffectProfileList::iterator itR = profiles.begin(); itR != profiles.end(); ++itR)
|
||||
{
|
||||
FCDEffectProfile* p = (*itR)->Clone(clone);
|
||||
clone->profiles.push_back(p);
|
||||
}
|
||||
|
||||
for (FCDEffectImageList::iterator itI = images.begin(); itI != images.end(); ++itI)
|
||||
{
|
||||
FCDImage* p = *itI;
|
||||
clone->images.push_back(p);
|
||||
}
|
||||
|
||||
SAFE_DELETE(clone->parameters);
|
||||
clone->parameters = parameters->Clone();
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Write out the <material> element to the COLLADA xml tree
|
||||
xmlNode* FCDEffect::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* effectNode = WriteToEntityXML(parentNode, DAE_EFFECT_ELEMENT);
|
||||
|
||||
// Write out the parameters
|
||||
for (FCDEffectParameterList::iterator itP = parameters->begin(); itP != parameters->end(); ++itP)
|
||||
{
|
||||
(*itP)->WriteToXML(effectNode);
|
||||
}
|
||||
|
||||
// Write out the profiles
|
||||
for (FCDEffectProfileList::const_iterator itR = profiles.begin(); itR != profiles.end(); ++itR)
|
||||
{
|
||||
(*itR)->WriteToXML(effectNode);
|
||||
}
|
||||
|
||||
FCDEffect::WriteToExtraXML(effectNode);
|
||||
return effectNode;
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDEffect.h
|
||||
This file contains the FCDEffect class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_EFFECT_H_
|
||||
#define _FCD_EFFECT_H_
|
||||
|
||||
#include "FUtils/FUDaeEnum.h"
|
||||
#include "FCDocument/FCDEntity.h"
|
||||
|
||||
class FCDocument;
|
||||
class FCDEffectStandard;
|
||||
class FCDEffectParameter;
|
||||
class FCDEffectProfile;
|
||||
class FCDEffectParameterList;
|
||||
|
||||
/**
|
||||
@defgroup FCDEffect COLLADA Effect Classes [ColladaFX]
|
||||
*/
|
||||
|
||||
class FCDEffectProfile;
|
||||
class FCDEffectParameterList;
|
||||
class FCDImage;
|
||||
|
||||
/** A dynamically-sized array of effect profiles. */
|
||||
typedef vector<FCDEffectProfile*> FCDEffectProfileList;
|
||||
typedef vector<FCDImage*> FCDEffectImageList;
|
||||
|
||||
/**
|
||||
A COLLADA effect.
|
||||
|
||||
A COLLADA effect is one of many abstraction level that defines how
|
||||
to render mesh polygon sets. It contains one or more rendering profile
|
||||
that the application can choose to support. In theory, all the rendering
|
||||
profiles should reach the same render output, using different
|
||||
rendering technologies.
|
||||
|
||||
An effect may also declare new general purpose parameters that are common
|
||||
to all the profiles.
|
||||
|
||||
@ingroup FCDEffect
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffect : public FCDEntity
|
||||
{
|
||||
private:
|
||||
FCDEffectProfileList profiles;
|
||||
FCDEffectParameterList* parameters;
|
||||
FCDEffectImageList images;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead use the FCDMaterialLibrary::AddEffect function.
|
||||
@param document The COLLADA document that owns this effect. */
|
||||
FCDEffect(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead use the FCDMaterialLibrary::ReleaseEffect function. */
|
||||
virtual ~FCDEffect();
|
||||
|
||||
/** Retrieves the type for this entity class.
|
||||
This function is a part of the FCDEntity interface.
|
||||
@return The entity type: EFFECT. */
|
||||
virtual Type GetType() const { return FCDEntity::EFFECT; }
|
||||
|
||||
/** Retrieves the number of profiles contained within the effect.
|
||||
@return The number of profiles within the effect. */
|
||||
size_t GetProfileCount() const { return profiles.size(); }
|
||||
|
||||
/** Retrieves a profile contained within the effect.
|
||||
@param index The index of the profile.
|
||||
@return The profile. This pointer will be NULL, if the given index is out-of-bounds. */
|
||||
FCDEffectProfile* GetProfile(size_t index) { FUAssert(index < GetProfileCount(), return NULL); return profiles.at(index); }
|
||||
const FCDEffectProfile* GetProfile(size_t index) const { FUAssert(index < GetProfileCount(), return NULL); return profiles.at(index); } /**< See above. */
|
||||
|
||||
/** Retrieves the list of the profiles contained within the effect.
|
||||
@return The list of effect profiles. */
|
||||
FCDEffectProfileList& GetProfiles() { return profiles; }
|
||||
const FCDEffectProfileList& GetProfiles() const { return profiles; } /**< See above. */
|
||||
|
||||
/** Retrieves the profile for a specific profile type.
|
||||
There should only be one profile of each type within an effect. This
|
||||
function allows you to retrieve the profile for a given type.
|
||||
@param type The profile type.
|
||||
@return The profile of this type. This pointer will be NULL if the effect
|
||||
does not have any profile of this type. */
|
||||
FCDEffectProfile* FindProfile(FUDaeProfileType::Type type);
|
||||
const FCDEffectProfile* FindProfile(FUDaeProfileType::Type type) const; /**< See above. */
|
||||
|
||||
/** Retrieves whether the effect contains a profile of the given type.
|
||||
@param type The profile type.
|
||||
@return Whether the effect has a profile of this type. */
|
||||
inline bool HasProfile(FUDaeProfileType::Type type) const { return FindProfile(type) != NULL; }
|
||||
|
||||
/** Creates a profile of the given type.
|
||||
If a profile of this type already exists, it will be released, as
|
||||
a COLLADA effect should only contain one profile of each type.
|
||||
@param type The profile type.
|
||||
@return The new effect profile. */
|
||||
FCDEffectProfile* AddProfile(FUDaeProfileType::Type type);
|
||||
|
||||
/** Releases the given effect profile.
|
||||
@param profile The effect profile. */
|
||||
void ReleaseProfile(FCDEffectProfile* profile);
|
||||
|
||||
/** Retrieves the list of common effect parameters declared at the effect level.
|
||||
According to the COLLADA 1.4 schema, you should expect only parameter generators
|
||||
at this abstraction level.
|
||||
@return The list of effect parameters. */
|
||||
FCDEffectParameterList* GetParameters() { return parameters; }
|
||||
const FCDEffectParameterList* GetParameters() const { return parameters; } /**< See above. */
|
||||
|
||||
/** [INTERNAL] Inserts an existing parameter into the list of common effect parameters
|
||||
at this abstraction level. This function is used during the flattening of a material.
|
||||
@param parameter The effect parameter to insert. */
|
||||
void AddParameter(FCDEffectParameter* parameter);
|
||||
|
||||
/** Retrieves a common effect parameter. Looks for the common effect parameter with the correct
|
||||
semantic, in order to bind or override its value.
|
||||
This function searches through the effect and the level of abstractions below.
|
||||
@param semantic The effect parameter semantic to match.
|
||||
@return The first effect parameter that matches the semantic.
|
||||
This pointer will be NULL if no effect parameter matches the given semantic. */
|
||||
FCDEffectParameter* FindParameterBySemantic(const string& semantic);
|
||||
|
||||
/** Retrieves a subset of the common effect parameter list.
|
||||
Look for the effect parameter generators with the correct semantic.
|
||||
This function searches through the effect and the level of abstractions below.
|
||||
@param semantic The effect parameter semantic to match.
|
||||
@param parameters The list of parameters to fill in. This list is not cleared. */
|
||||
void FindParametersBySemantic(const string& semantic, FCDEffectParameterList& parameters);
|
||||
|
||||
/** Retrieves a subset of the common effect parameter list.
|
||||
Look for the effect parameter generators with the correct reference.
|
||||
This function searches through the effect and the level of abstractions below.
|
||||
@param reference The effect parameter reference to match. In the case of effect
|
||||
parameter generators, the reference is replaced by the sub-id.
|
||||
@param parameters The list of parameters to fill in. This list is not cleared. */
|
||||
void FindParametersByReference(const string& reference, FCDEffectParameterList& parameters);
|
||||
|
||||
/** Clones the effect object. Everything is cloned, including the effect parameter
|
||||
and their animations. You will need release the cloned effect directly, by deleting the pointer.
|
||||
@return The cloned effect object. You will must delete this pointer. */
|
||||
FCDEffect* Clone();
|
||||
|
||||
/** [INTERNAL] Flattens the effect, pushing all the common effect parameters
|
||||
into to the effect technique level of abstraction. To correctly flatten a
|
||||
material, use the FCDMaterialInstance::FlattenMaterial function. */
|
||||
void Flatten();
|
||||
|
||||
/** [INTERNAL] Reads in the \<effect\> element from a given COLLADA XML tree node.
|
||||
@param effectNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the effect.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* effectNode);
|
||||
|
||||
/** [INTERNAL] Writes out the \<effect\> element to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the effect.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
|
||||
/** Retrieves the list of the images contained within the effect.
|
||||
@return The list of effect images. */
|
||||
FCDEffectImageList& GetImages() { return images; }
|
||||
const FCDEffectImageList& GetImages() const { return images; } /**< See above. */
|
||||
};
|
||||
|
||||
#endif // _FCD_MATERIAL_H_
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
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/FCDEffectCode.h"
|
||||
#include "FUtils/FUFileManager.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDEffectCode::FCDEffectCode(FCDocument* document) : FCDObject(document, "FCDEffectCode")
|
||||
{
|
||||
type = INCLUDE;
|
||||
}
|
||||
|
||||
FCDEffectCode::~FCDEffectCode()
|
||||
{
|
||||
}
|
||||
|
||||
// Clone
|
||||
FCDEffectCode* FCDEffectCode::Clone() const
|
||||
{
|
||||
FCDEffectCode* clone = new FCDEffectCode(GetDocument());
|
||||
clone->type = type;
|
||||
clone->sid = sid;
|
||||
clone->filename = filename;
|
||||
clone->code = code;
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Read in the code/include from the xml node tree
|
||||
FUStatus FCDEffectCode::LoadFromXML(xmlNode* codeNode)
|
||||
{
|
||||
FUStatus status;
|
||||
if (IsEquivalent(codeNode->name, DAE_FXCMN_INCLUDE_ELEMENT)) type = INCLUDE;
|
||||
else if (IsEquivalent(codeNode->name, DAE_FXCMN_CODE_ELEMENT)) type = CODE;
|
||||
else
|
||||
{
|
||||
return status.Fail(FS("Unknown effect code type."), codeNode->line);
|
||||
}
|
||||
|
||||
// Read in the code identifier and the actual code or filename
|
||||
sid = ReadNodeProperty(codeNode, DAE_SID_ATTRIBUTE);
|
||||
if (type == INCLUDE && sid.empty())
|
||||
{
|
||||
status.Warning(FS("<code>/<include> nodes must have an 'sid' attribute to identify them."), codeNode->line);
|
||||
}
|
||||
if (type == INCLUDE)
|
||||
{
|
||||
filename = ReadNodeUrl(codeNode).prefix;
|
||||
filename = GetDocument()->GetFileManager()->GetFilePath(filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
code = TO_FSTRING(ReadNodeContentDirect(codeNode));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out the code/include to the COLLADA xml node tree
|
||||
xmlNode* FCDEffectCode::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
// In COLLADA 1.4, the 'sid' and 'url' attributes are required.
|
||||
// In the case of the sub-id, save it for later use.
|
||||
xmlNode* codeNode;
|
||||
switch (type)
|
||||
{
|
||||
case CODE:
|
||||
codeNode = AddChild(parentNode, DAE_FXCMN_CODE_ELEMENT, code);
|
||||
const_cast<FCDEffectCode*>(this)->sid = AddNodeSid(codeNode, !sid.empty() ? sid.c_str() : "code");
|
||||
break;
|
||||
|
||||
case INCLUDE:
|
||||
codeNode = AddChild(parentNode, DAE_FXCMN_INCLUDE_ELEMENT);
|
||||
const_cast<FCDEffectCode*>(this)->sid = AddNodeSid(codeNode, !sid.empty() ? sid.c_str() : "include");
|
||||
AddAttribute(codeNode, DAE_URL_ATTRIBUTE, filename);
|
||||
break;
|
||||
|
||||
default:
|
||||
codeNode = NULL;
|
||||
}
|
||||
return codeNode;
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDEffectCode.h
|
||||
This file contains the FCDEffectCode class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_EFFECT_CODE_H_
|
||||
#define _FCD_EFFECT_CODE_H_
|
||||
|
||||
#include "FCDocument/FCDObject.h"
|
||||
|
||||
class FCDocument;
|
||||
|
||||
/**
|
||||
A COLLADA code inclusion.
|
||||
|
||||
Code inclusions come in two forms: file includes and inline code.
|
||||
For file includes, you will want to grab the filename of the file
|
||||
using the GetFilename function and for inline code, you can get
|
||||
the code directly through the GetCode function.
|
||||
|
||||
Code inclusions are referenced through sub-ids by the effect pass
|
||||
shaders. Regardless of the extension of the filename of file
|
||||
includes, the code inclusions' language is solely determined by
|
||||
the effect profile they belong to.
|
||||
*/
|
||||
class FCDEffectCode : public FCDObject
|
||||
{
|
||||
public:
|
||||
/** The list of support code inclusion types. */
|
||||
enum Type
|
||||
{
|
||||
INCLUDE, /** A file include. @see GetFilename */
|
||||
CODE /** Inlined code. @see GetCode */
|
||||
};
|
||||
|
||||
private:
|
||||
Type type;
|
||||
string sid;
|
||||
fstring code;
|
||||
fstring filename;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDEffectProfile::AddCode
|
||||
or the FCDEffectTechnique::AddCode functions.
|
||||
@param document The COLLADA document that owns this code inclusion. */
|
||||
FCDEffectCode(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDEffectProfile::ReleaseCode
|
||||
or the FCDEffectTechnique::ReleaseCode functions. */
|
||||
~FCDEffectCode();
|
||||
|
||||
/** Retrieves the form of the code inclusion.
|
||||
@return The form. */
|
||||
inline Type GetType() const { return type; }
|
||||
|
||||
/** Sets the form of the code inclusion.
|
||||
Changing the form of the code inclusion will not
|
||||
remove the inline code or the filename.
|
||||
@param _type The form. */
|
||||
inline void SetType(Type _type) { type = _type; }
|
||||
|
||||
/** Retrieves the sub-id of the code inclusion.
|
||||
Used to match the code inclusion within the effect pass shaders.
|
||||
@return The sub-id. */
|
||||
const string& GetSid() const { return sid; }
|
||||
|
||||
/** Sets the sub-id of the code inclusion.
|
||||
This value may change on export, as the sub-id must be unique within its scope.
|
||||
@param _sid The sub-id. */
|
||||
void SetSid(const string& _sid) { sid = _sid; }
|
||||
|
||||
/** Retrieves the inlined code.
|
||||
First verify that this code inclusion contains inlined code
|
||||
using the GetType function.
|
||||
@return The inlined code. */
|
||||
const fstring& GetCode() const { return code; }
|
||||
|
||||
/** Sets the inlined code.
|
||||
As a side-effect, calling this function forces the type of the code inclusion.
|
||||
@param _code The inlined code. */
|
||||
void SetCode(const fstring& _code) { code = _code; type = CODE; }
|
||||
|
||||
/** Retrieves the filename of the code file to open.
|
||||
First verify that this code inclusion contains a filename
|
||||
using the GetType function.
|
||||
@return The code filename. */
|
||||
const fstring& GetFilename() const { return filename; }
|
||||
|
||||
/** Sets the filename of the code file.
|
||||
As a side-effect, calling this function forces the type of the code inclusion.
|
||||
@param _filename The code filename. */
|
||||
void SetFilename(const fstring& _filename) { filename = _filename; type = INCLUDE; }
|
||||
|
||||
/** [INTERNAL] Clones the code inclusion.
|
||||
@return The cloned effect object. You will must delete this pointer. */
|
||||
FCDEffectCode* Clone() const;
|
||||
|
||||
/** [INTERNAL] Reads in the code inclusion from a given COLLADA XML tree node.
|
||||
Code inclusions cover the \<code\> element and the \<include\> element.
|
||||
@param codeNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the code inclusion.*/
|
||||
FUStatus LoadFromXML(xmlNode* codeNode);
|
||||
|
||||
/** [INTERNAL] Writes out the code inclusion to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the code inclusion.
|
||||
@return The created element XML tree node. */
|
||||
xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif // _FCD_EFFECT_CODE_H_
|
||||
@@ -1,646 +0,0 @@
|
||||
/*
|
||||
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/FCDEffectPass.h"
|
||||
#include "FCDocument/FCDEffectProfile.h"
|
||||
#include "FCDocument/FCDEffectTechnique.h"
|
||||
#include "FCDocument/FCDEffectParameter.h"
|
||||
#include "FCDocument/FCDImage.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDEffectParameter::FCDEffectParameter(FCDocument* document) : FCDObject(document, "FCDEffectParameter")
|
||||
{
|
||||
isGenerator = true;
|
||||
isFragment = false;
|
||||
reference = "";
|
||||
semantic = "";
|
||||
bindSymbol = "";
|
||||
}
|
||||
|
||||
FCDEffectParameter::~FCDEffectParameter()
|
||||
{
|
||||
}
|
||||
|
||||
FUStatus FCDEffectParameter::LoadFromXML(xmlNode* parameterNode)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// This parameter is a generator if this is a <newparam> element. Otherwise, it modifies
|
||||
// an existing parameter (<bind>, <bind_semantic> or <setparam>.
|
||||
isGenerator = IsEquivalent(parameterNode->name, DAE_FXCMN_NEWPARAM_ELEMENT);
|
||||
if (isGenerator)
|
||||
{
|
||||
reference = ReadNodeProperty(parameterNode, DAE_SID_ATTRIBUTE);
|
||||
if (reference.empty())
|
||||
{
|
||||
return status.Warning(FS("No reference attribute on generator parameter."), parameterNode->line);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
reference = ReadNodeProperty(parameterNode, DAE_REF_ATTRIBUTE);
|
||||
if (reference.empty())
|
||||
{
|
||||
return status.Warning(FS("No reference attribute on modifier parameter."), parameterNode->line);
|
||||
}
|
||||
}
|
||||
|
||||
xmlNode* valueNode = FindChildByType(parameterNode, DAE_FXCMN_SEMANTIC_ELEMENT);
|
||||
if (valueNode != NULL)
|
||||
{
|
||||
semantic = ReadNodeContentDirect(valueNode);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out this ColladaFX parameter to the xml node tree
|
||||
xmlNode* FCDEffectParameter::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* parameterNode;
|
||||
if (isGenerator)
|
||||
{
|
||||
parameterNode = AddChild(parentNode, DAE_FXCMN_NEWPARAM_ELEMENT);
|
||||
if (!reference.empty()) AddAttribute(parameterNode, DAE_SID_ATTRIBUTE, reference);
|
||||
if (!semantic.empty()) AddChild(parameterNode, DAE_FXCMN_SEMANTIC_ELEMENT, semantic);
|
||||
}
|
||||
else
|
||||
{
|
||||
parameterNode = AddChild(parentNode, DAE_FXCMN_SETPARAM_ELEMENT);
|
||||
if (!reference.empty()) AddAttribute(parameterNode, DAE_REF_ATTRIBUTE, reference);
|
||||
}
|
||||
return parameterNode;
|
||||
}
|
||||
|
||||
void FCDEffectParameter::Clone(FCDEffectParameter* clone)
|
||||
{
|
||||
clone->bindSymbol = bindSymbol;
|
||||
clone->reference = reference;
|
||||
clone->semantic = semantic;
|
||||
clone->isFragment = isFragment;
|
||||
clone->isGenerator = isGenerator;
|
||||
}
|
||||
|
||||
// Flattening: overwrite the target parameter with this parameter
|
||||
void FCDEffectParameter::Overwrite(FCDEffectParameter* UNUSED(target))
|
||||
{
|
||||
// Do nothing on the base class, only values and animations should be overwritten
|
||||
}
|
||||
|
||||
FCDEffectParameterSampler::FCDEffectParameterSampler(FCDocument* document) : FCDEffectParameter(document)
|
||||
{
|
||||
samplerType = SAMPLER2D;
|
||||
}
|
||||
|
||||
FCDEffectParameterSampler::~FCDEffectParameterSampler()
|
||||
{
|
||||
}
|
||||
|
||||
// Clone
|
||||
FCDEffectParameter* FCDEffectParameterSampler::Clone()
|
||||
{
|
||||
FCDEffectParameterSampler* clone = new FCDEffectParameterSampler(GetDocument());
|
||||
FCDEffectParameter::Clone(clone);
|
||||
clone->surfaceSid = surfaceSid;
|
||||
clone->samplerType = samplerType;
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Flattening: overwrite the target parameter with this parameter
|
||||
void FCDEffectParameterSampler::Overwrite(FCDEffectParameter* target)
|
||||
{
|
||||
if (target->GetType() == SAMPLER)
|
||||
{
|
||||
FCDEffectParameterSampler* s = (FCDEffectParameterSampler*) target;
|
||||
if (samplerType == s->samplerType)
|
||||
{
|
||||
s->surfaceSid = surfaceSid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FUStatus FCDEffectParameterSampler::LoadFromXML(xmlNode* parameterNode)
|
||||
{
|
||||
FUStatus status = FCDEffectParameter::LoadFromXML(parameterNode);
|
||||
|
||||
// Find the sampler node
|
||||
xmlNode* samplerNode = NULL;
|
||||
for (xmlNode* child = parameterNode->children; child != NULL; child = child->next)
|
||||
{
|
||||
if (child->type != XML_ELEMENT_NODE) continue;
|
||||
|
||||
if (IsEquivalent(child->name, DAE_FXCMN_SAMPLER1D_ELEMENT)) { samplerType = SAMPLER1D; samplerNode = child; break; }
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_SAMPLER2D_ELEMENT)) { samplerType = SAMPLER2D; samplerNode = child; break; }
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_SAMPLER3D_ELEMENT)) { samplerType = SAMPLER3D; samplerNode = child; break; }
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_SAMPLERCUBE_ELEMENT)) { samplerType = SAMPLERCUBE; samplerNode = child; break; }
|
||||
}
|
||||
|
||||
if (samplerNode == NULL)
|
||||
{
|
||||
return status.Warning(FS("Unable to find sampler node for sampler parameter: ") + TO_FSTRING(GetReference()), parameterNode->line);
|
||||
}
|
||||
|
||||
// Parse the source node
|
||||
xmlNode* sourceNode = FindChildByType(samplerNode, DAE_SOURCE_ELEMENT);
|
||||
surfaceSid = ReadNodeContentDirect(sourceNode);
|
||||
if (surfaceSid.empty())
|
||||
{
|
||||
return status.Fail(FS("Empty surface source value for sampler parameter: ") + TO_FSTRING(GetReference()), parameterNode->line);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
xmlNode* FCDEffectParameterSampler::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* parameterNode = FCDEffectParameter::WriteToXML(parentNode);
|
||||
const char* samplerName;
|
||||
switch(samplerType)
|
||||
{
|
||||
case SAMPLER1D: samplerName = DAE_FXCMN_SAMPLER1D_ELEMENT; break;
|
||||
case SAMPLER2D: samplerName = DAE_FXCMN_SAMPLER2D_ELEMENT; break;
|
||||
case SAMPLER3D: samplerName = DAE_FXCMN_SAMPLER3D_ELEMENT; break;
|
||||
case SAMPLERCUBE: samplerName = DAE_FXCMN_SAMPLERCUBE_ELEMENT; break;
|
||||
default: samplerName = DAEERR_UNKNOWN_ELEMENT; break;
|
||||
}
|
||||
xmlNode* samplerNode = AddChild(parameterNode, samplerName);
|
||||
if (!surfaceSid.empty()) AddChild(samplerNode, DAE_SOURCE_ELEMENT, surfaceSid);
|
||||
return parameterNode;
|
||||
}
|
||||
|
||||
FCDEffectParameterInt::FCDEffectParameterInt(FCDocument* document) : FCDEffectParameter(document) { value = 0; }
|
||||
FCDEffectParameterInt::~FCDEffectParameterInt()
|
||||
{
|
||||
value = 0;
|
||||
}
|
||||
|
||||
// Clone
|
||||
FCDEffectParameter* FCDEffectParameterInt::Clone()
|
||||
{
|
||||
FCDEffectParameterInt* clone = new FCDEffectParameterInt(GetDocument());
|
||||
FCDEffectParameter::Clone(clone);
|
||||
clone->value = value;
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Flattening: overwrite the target parameter with this parameter
|
||||
void FCDEffectParameterInt::Overwrite(FCDEffectParameter* target)
|
||||
{
|
||||
if (target->GetType() == INTEGER)
|
||||
{
|
||||
FCDEffectParameterInt* s = (FCDEffectParameterInt*) target;
|
||||
s->value = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse in this ColladaFX integer from the document's XML node
|
||||
FUStatus FCDEffectParameterInt::LoadFromXML(xmlNode* parameterNode)
|
||||
{
|
||||
FUStatus status = FCDEffectParameter::LoadFromXML(parameterNode);
|
||||
xmlNode* valueNode = FindChildByType(parameterNode, DAE_FXCMN_INT_ELEMENT);
|
||||
const char* valueString = ReadNodeContentDirect(valueNode);
|
||||
if (valueString == NULL || *valueString == 0)
|
||||
{
|
||||
return status.Fail(FS("Bad value for float parameter in integer parameter: ") + TO_FSTRING(GetReference()), parameterNode->line);
|
||||
}
|
||||
value = FUStringConversion::ToInt32(valueString);
|
||||
return status;
|
||||
}
|
||||
|
||||
xmlNode* FCDEffectParameterInt::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* parameterNode = FCDEffectParameter::WriteToXML(parentNode);
|
||||
AddChild(parameterNode, DAE_FXCMN_INT_ELEMENT, value);
|
||||
return parameterNode;
|
||||
}
|
||||
|
||||
// boolean type parameter
|
||||
FCDEffectParameterBool::FCDEffectParameterBool(FCDocument* document) : FCDEffectParameter(document)
|
||||
{
|
||||
value = 0;
|
||||
}
|
||||
|
||||
FCDEffectParameterBool::~FCDEffectParameterBool() {}
|
||||
|
||||
// Clone
|
||||
FCDEffectParameter* FCDEffectParameterBool::Clone()
|
||||
{
|
||||
FCDEffectParameterBool* clone = new FCDEffectParameterBool(GetDocument());
|
||||
FCDEffectParameter::Clone(clone);
|
||||
clone->value = value;
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Flattening: overwrite the target parameter with this parameter
|
||||
void FCDEffectParameterBool::Overwrite(FCDEffectParameter* target)
|
||||
{
|
||||
if (target->GetType() == BOOLEAN)
|
||||
{
|
||||
FCDEffectParameterBool* s = (FCDEffectParameterBool*) target;
|
||||
s->value = value;
|
||||
}
|
||||
}
|
||||
|
||||
FUStatus FCDEffectParameterBool::LoadFromXML(xmlNode* parameterNode)
|
||||
{
|
||||
FUStatus status = FCDEffectParameter::LoadFromXML(parameterNode);
|
||||
xmlNode* valueNode = FindChildByType(parameterNode, DAE_FXCMN_BOOL_ELEMENT);
|
||||
const char* valueString = ReadNodeContentDirect(valueNode);
|
||||
if (valueString == NULL || *valueString == 0)
|
||||
{
|
||||
return status.Fail(FS("Bad value for boolean parameter in effect: ") + TO_FSTRING(GetReference()), parameterNode->line);
|
||||
}
|
||||
value = FUStringConversion::ToBoolean(valueString);
|
||||
return status;
|
||||
}
|
||||
|
||||
xmlNode* FCDEffectParameterBool::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* parameterNode = FCDEffectParameter::WriteToXML(parentNode);
|
||||
AddChild(parameterNode, DAE_FXCMN_BOOL_ELEMENT, value);
|
||||
return parameterNode;
|
||||
}
|
||||
|
||||
// string type parameter
|
||||
FCDEffectParameterString::FCDEffectParameterString(FCDocument* document) : FCDEffectParameter(document)
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
FCDEffectParameterString::~FCDEffectParameterString()
|
||||
{
|
||||
}
|
||||
|
||||
// Clone
|
||||
FCDEffectParameter* FCDEffectParameterString::Clone()
|
||||
{
|
||||
FCDEffectParameterString* clone = new FCDEffectParameterString(GetDocument());
|
||||
FCDEffectParameter::Clone(clone);
|
||||
clone->value = value;
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Flattening: overwrite the target parameter with this parameter
|
||||
void FCDEffectParameterString::Overwrite(FCDEffectParameter* target)
|
||||
{
|
||||
if (target->GetType() == STRING)
|
||||
{
|
||||
FCDEffectParameterString* s = (FCDEffectParameterString*) target;
|
||||
s->value = value;
|
||||
}
|
||||
}
|
||||
|
||||
FUStatus FCDEffectParameterString::LoadFromXML(xmlNode* parameterNode)
|
||||
{
|
||||
FUStatus status = FCDEffectParameter::LoadFromXML(parameterNode);
|
||||
xmlNode* valueNode = FindChildByType(parameterNode, DAE_FXCMN_STRING_ELEMENT);
|
||||
const char* valueString = ReadNodeContentDirect(valueNode);
|
||||
value = valueString;
|
||||
return status;
|
||||
}
|
||||
|
||||
xmlNode* FCDEffectParameterString::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* parameterNode = FCDEffectParameter::WriteToXML(parentNode);
|
||||
AddChild(parameterNode, DAE_FXCMN_STRING_ELEMENT, value);
|
||||
return parameterNode;
|
||||
}
|
||||
|
||||
// float type parameter
|
||||
FCDEffectParameterFloat::FCDEffectParameterFloat(FCDocument* document) : FCDEffectParameter(document)
|
||||
{
|
||||
floatType = FLOAT;
|
||||
value = 0.0f;
|
||||
min = 0.0f;
|
||||
max = 1.0f;
|
||||
}
|
||||
|
||||
FCDEffectParameterFloat::~FCDEffectParameterFloat()
|
||||
{
|
||||
}
|
||||
|
||||
// Clone
|
||||
FCDEffectParameter* FCDEffectParameterFloat::Clone()
|
||||
{
|
||||
FCDEffectParameterFloat* clone = new FCDEffectParameterFloat(GetDocument());
|
||||
FCDEffectParameter::Clone(clone);
|
||||
clone->floatType = floatType;
|
||||
clone->value = value;
|
||||
clone->min = min;
|
||||
clone->max = max;
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Flattening: overwrite the target parameter with this parameter
|
||||
void FCDEffectParameterFloat::Overwrite(FCDEffectParameter* target)
|
||||
{
|
||||
if (target->GetType() == FCDEffectParameter::FLOAT)
|
||||
{
|
||||
FCDEffectParameterFloat* s = (FCDEffectParameterFloat*) target;
|
||||
if (s->floatType == floatType) s->value = value;
|
||||
}
|
||||
}
|
||||
|
||||
FUStatus FCDEffectParameterFloat::LoadFromXML(xmlNode* parameterNode)
|
||||
{
|
||||
FUStatus status = FCDEffectParameter::LoadFromXML(parameterNode);
|
||||
xmlNode* valueNode = FindChildByType(parameterNode, DAE_FXCMN_FLOAT_ELEMENT);
|
||||
if (valueNode == NULL)
|
||||
{
|
||||
valueNode = FindChildByType(parameterNode, DAE_FXCMN_HALF_ELEMENT);
|
||||
floatType = HALF;
|
||||
}
|
||||
else floatType = FLOAT;
|
||||
|
||||
const char* valueString = ReadNodeContentDirect(valueNode);
|
||||
if (valueString == NULL || *valueString == 0)
|
||||
{
|
||||
return status.Fail(FS("Bad float value for float parameter: ") + TO_FSTRING(GetReference()), parameterNode->line);
|
||||
}
|
||||
value = FUStringConversion::ToFloat(valueString);
|
||||
|
||||
FCDAnimatedFloat::Create(GetDocument(), parameterNode, &value);
|
||||
|
||||
xmlNode* minannNode = FindChildByName(parameterNode, "UIMin");
|
||||
if(minannNode) {
|
||||
xmlNode* minNode = FindChildByType(minannNode, DAE_FXCMN_FLOAT_ELEMENT);
|
||||
valueString = ReadNodeContentDirect(minNode);
|
||||
if (valueString != NULL) min = FUStringConversion::ToFloat(valueString);
|
||||
}
|
||||
|
||||
xmlNode* maxannNode = FindChildByName(parameterNode, "UIMax");
|
||||
if(maxannNode) {
|
||||
xmlNode* maxNode = FindChildByType(maxannNode, DAE_FXCMN_FLOAT_ELEMENT);
|
||||
valueString = ReadNodeContentDirect(maxNode);
|
||||
if (valueString != NULL) max = FUStringConversion::ToFloat(valueString);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
xmlNode* FCDEffectParameterFloat::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* parameterNode = FCDEffectParameter::WriteToXML(parentNode);
|
||||
AddChild(parameterNode, (floatType == FLOAT) ? DAE_FXCMN_FLOAT_ELEMENT : DAE_FXCMN_HALF_ELEMENT, value);
|
||||
return parameterNode;
|
||||
}
|
||||
|
||||
// float2 type parameter
|
||||
FCDEffectParameterFloat2::FCDEffectParameterFloat2(FCDocument* document) : FCDEffectParameter(document)
|
||||
{
|
||||
floatType = FLOAT;
|
||||
value_x = 0.0f;
|
||||
value_y = 0.0f;
|
||||
}
|
||||
|
||||
FCDEffectParameterFloat2::~FCDEffectParameterFloat2()
|
||||
{
|
||||
}
|
||||
|
||||
// Clone
|
||||
FCDEffectParameter* FCDEffectParameterFloat2::Clone()
|
||||
{
|
||||
FCDEffectParameterFloat2* clone = new FCDEffectParameterFloat2(GetDocument());
|
||||
FCDEffectParameter::Clone(clone);
|
||||
clone->floatType = floatType;
|
||||
clone->value_x = value_x;
|
||||
clone->value_y = value_y;
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Flattening: overwrite the target parameter with this parameter
|
||||
void FCDEffectParameterFloat2::Overwrite(FCDEffectParameter* target)
|
||||
{
|
||||
if (target->GetType() == FLOAT2)
|
||||
{
|
||||
FCDEffectParameterFloat2* s = (FCDEffectParameterFloat2*) target;
|
||||
if (s->floatType == floatType)
|
||||
{
|
||||
s->value_x = value_x;
|
||||
s->value_y = value_y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FUStatus FCDEffectParameterFloat2::LoadFromXML(xmlNode* parameterNode)
|
||||
{
|
||||
FUStatus status = FCDEffectParameter::LoadFromXML(parameterNode);
|
||||
xmlNode* valueNode = FindChildByType(parameterNode, DAE_FXCMN_FLOAT2_ELEMENT);
|
||||
if (valueNode == NULL)
|
||||
{
|
||||
valueNode = FindChildByType(parameterNode, DAE_FXCMN_HALF2_ELEMENT);
|
||||
floatType = HALF;
|
||||
}
|
||||
else floatType = FLOAT;
|
||||
|
||||
const char* valueString = ReadNodeContentDirect(valueNode);
|
||||
if (valueString == NULL || *valueString == 0)
|
||||
{
|
||||
return status.Fail(FS("Bad value for float2 parameter: ") + TO_FSTRING(GetReference()), parameterNode->line);
|
||||
}
|
||||
value_x = FUStringConversion::ToFloat(&valueString);
|
||||
value_y = FUStringConversion::ToFloat(&valueString);
|
||||
return status;
|
||||
}
|
||||
|
||||
xmlNode* FCDEffectParameterFloat2::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* parameterNode = FCDEffectParameter::WriteToXML(parentNode);
|
||||
globalSBuilder.set(value_x); globalSBuilder.append(' '); globalSBuilder.append(value_y);
|
||||
AddChild(parameterNode, (floatType == FLOAT) ? DAE_FXCMN_FLOAT2_ELEMENT : DAE_FXCMN_HALF2_ELEMENT, globalSBuilder);
|
||||
return parameterNode;
|
||||
}
|
||||
|
||||
// float3 type parameter
|
||||
FCDEffectParameterFloat3::FCDEffectParameterFloat3(FCDocument* document) : FCDEffectParameter(document)
|
||||
{
|
||||
floatType = FLOAT;
|
||||
value = FMVector3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
FCDEffectParameterFloat3::~FCDEffectParameterFloat3()
|
||||
{
|
||||
}
|
||||
|
||||
// Clone
|
||||
FCDEffectParameter* FCDEffectParameterFloat3::Clone()
|
||||
{
|
||||
FCDEffectParameterFloat3* clone = new FCDEffectParameterFloat3(GetDocument());
|
||||
FCDEffectParameter::Clone(clone);
|
||||
clone->floatType = floatType;
|
||||
clone->value = value;
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Flattening: overwrite the target parameter with this parameter
|
||||
void FCDEffectParameterFloat3::Overwrite(FCDEffectParameter* target)
|
||||
{
|
||||
if (target->GetType() == FLOAT3)
|
||||
{
|
||||
FCDEffectParameterFloat3* s = (FCDEffectParameterFloat3*) target;
|
||||
if (s->floatType == floatType)
|
||||
{
|
||||
s->value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FUStatus FCDEffectParameterFloat3::LoadFromXML(xmlNode* parameterNode)
|
||||
{
|
||||
FUStatus status = FCDEffectParameter::LoadFromXML(parameterNode);
|
||||
xmlNode* valueNode = FindChildByType(parameterNode, DAE_FXCMN_FLOAT3_ELEMENT);
|
||||
if (valueNode == NULL)
|
||||
{
|
||||
valueNode = FindChildByType(parameterNode, DAE_FXCMN_HALF3_ELEMENT);
|
||||
floatType = HALF;
|
||||
}
|
||||
else floatType = FLOAT;
|
||||
|
||||
const char* valueString = ReadNodeContentDirect(valueNode);
|
||||
if (valueString == NULL || *valueString == 0)
|
||||
{
|
||||
return status.Fail(FS("Bad value for float3 parameter: ") + TO_FSTRING(GetReference()), parameterNode->line);
|
||||
}
|
||||
value = FUStringConversion::ToPoint(valueString);
|
||||
FCDAnimatedColor::Create(GetDocument(), parameterNode, &value);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
xmlNode* FCDEffectParameterFloat3::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* parameterNode = FCDEffectParameter::WriteToXML(parentNode);
|
||||
string s = FUStringConversion::ToString(value);
|
||||
AddChild(parameterNode, (floatType == FLOAT) ? DAE_FXCMN_FLOAT3_ELEMENT : DAE_FXCMN_HALF3_ELEMENT, s);
|
||||
return parameterNode;
|
||||
}
|
||||
|
||||
FCDEffectParameterVector::FCDEffectParameterVector(FCDocument* document) : FCDEffectParameter(document)
|
||||
{
|
||||
floatType = FLOAT;
|
||||
vector[0] = vector[1] = vector[2] = vector[3] = 0.0f;
|
||||
}
|
||||
|
||||
FCDEffectParameterVector::~FCDEffectParameterVector() {}
|
||||
|
||||
// Clone
|
||||
FCDEffectParameter* FCDEffectParameterVector::Clone()
|
||||
{
|
||||
FCDEffectParameterVector* clone = new FCDEffectParameterVector(GetDocument());
|
||||
FCDEffectParameter::Clone(clone);
|
||||
clone->floatType = floatType;
|
||||
memcpy(clone->vector, vector, sizeof(float) * 4);
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Flattening: overwrite the target parameter with this parameter
|
||||
void FCDEffectParameterVector::Overwrite(FCDEffectParameter* target)
|
||||
{
|
||||
if (target->GetType() == VECTOR)
|
||||
{
|
||||
FCDEffectParameterVector* s = (FCDEffectParameterVector*) target;
|
||||
if (s->floatType == floatType)
|
||||
{
|
||||
memcpy(s->vector, vector, sizeof(float) * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FUStatus FCDEffectParameterVector::LoadFromXML(xmlNode* parameterNode)
|
||||
{
|
||||
FUStatus status = FCDEffectParameter::LoadFromXML(parameterNode);
|
||||
xmlNode* valueNode = FindChildByType(parameterNode, DAE_FXCMN_FLOAT4_ELEMENT);
|
||||
if (valueNode == NULL)
|
||||
{
|
||||
valueNode = FindChildByType(parameterNode, DAE_FXCMN_HALF4_ELEMENT);
|
||||
floatType = HALF;
|
||||
}
|
||||
else floatType = FLOAT;
|
||||
|
||||
const char* valueString = ReadNodeContentDirect(valueNode);
|
||||
if (valueString == NULL || *valueString == 0)
|
||||
{
|
||||
return status.Fail(FS("Bad value for float4 parameter: ") + TO_FSTRING(GetReference()), parameterNode->line);
|
||||
}
|
||||
vector[0] = FUStringConversion::ToFloat(&valueString);
|
||||
vector[1] = FUStringConversion::ToFloat(&valueString);
|
||||
vector[2] = FUStringConversion::ToFloat(&valueString);
|
||||
vector[3] = FUStringConversion::ToFloat(&valueString);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
xmlNode* FCDEffectParameterVector::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* parameterNode = FCDEffectParameter::WriteToXML(parentNode);
|
||||
globalSBuilder.set(vector[0]); globalSBuilder.append(' '); globalSBuilder.append(vector[1]); globalSBuilder.append(' ');
|
||||
globalSBuilder.append(vector[2]); globalSBuilder.append(' '); globalSBuilder.append(vector[3]);
|
||||
AddChild(parameterNode, (floatType == FLOAT) ? DAE_FXCMN_FLOAT4_ELEMENT : DAE_FXCMN_HALF4_ELEMENT, globalSBuilder);
|
||||
return parameterNode;
|
||||
}
|
||||
|
||||
FCDEffectParameterMatrix::FCDEffectParameterMatrix(FCDocument* document) : FCDEffectParameter(document)
|
||||
{
|
||||
floatType = FLOAT;
|
||||
matrix = FMMatrix44::Identity;
|
||||
}
|
||||
|
||||
FCDEffectParameterMatrix::~FCDEffectParameterMatrix()
|
||||
{
|
||||
}
|
||||
|
||||
// Clone
|
||||
FCDEffectParameter* FCDEffectParameterMatrix::Clone()
|
||||
{
|
||||
FCDEffectParameterMatrix* clone = new FCDEffectParameterMatrix(GetDocument());
|
||||
FCDEffectParameter::Clone(clone);
|
||||
clone->floatType = floatType;
|
||||
clone->matrix = matrix;
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Flattening: overwrite the target parameter with this parameter
|
||||
void FCDEffectParameterMatrix::Overwrite(FCDEffectParameter* target)
|
||||
{
|
||||
if (target->GetType() == MATRIX)
|
||||
{
|
||||
FCDEffectParameterMatrix* s = (FCDEffectParameterMatrix*) target;
|
||||
s->matrix = matrix;
|
||||
}
|
||||
}
|
||||
|
||||
FUStatus FCDEffectParameterMatrix::LoadFromXML(xmlNode* parameterNode)
|
||||
{
|
||||
FUStatus status = FCDEffectParameter::LoadFromXML(parameterNode);
|
||||
xmlNode* valueNode = FindChildByType(parameterNode, DAE_FXCMN_FLOAT4X4_ELEMENT);
|
||||
if (valueNode == NULL)
|
||||
{
|
||||
valueNode = FindChildByType(parameterNode, DAE_FXCMN_HALF4X4_ELEMENT);
|
||||
floatType = HALF;
|
||||
}
|
||||
else floatType = FLOAT;
|
||||
|
||||
const char* valueString = ReadNodeContentDirect(valueNode);
|
||||
if (valueString == NULL || *valueString == 0)
|
||||
{
|
||||
return status.Fail(FS("Bad value for matrix parameter: ") + TO_FSTRING(GetReference()), parameterNode->line);
|
||||
}
|
||||
FUStringConversion::ToMatrix(valueString, matrix, GetDocument()->GetLengthUnitConversion());
|
||||
return status;
|
||||
}
|
||||
|
||||
xmlNode* FCDEffectParameterMatrix::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* parameterNode = FCDEffectParameter::WriteToXML(parentNode);
|
||||
string s = FUStringConversion::ToString(matrix);
|
||||
AddChild(parameterNode, (floatType == FLOAT) ? DAE_FXCMN_FLOAT4X4_ELEMENT : DAE_FXCMN_HALF4X4_ELEMENT, s);
|
||||
return parameterNode;
|
||||
}
|
||||
@@ -1,844 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDEffectParameter.h
|
||||
This file contains the FCDEffectParameter interface and most of its derivate classes:
|
||||
FCDEffectParameterSampler, FCDEffectParameterFloat, FCDEffectParameterVector...
|
||||
*/
|
||||
|
||||
#ifndef _FCD_EFFECT_PARAMETER_H_
|
||||
#define _FCD_EFFECT_PARAMETER_H_
|
||||
|
||||
#include "FCDocument/FCDObject.h"
|
||||
|
||||
class FCDEffectPass;
|
||||
class FCDocument;
|
||||
class FCDEffectParameterSurface;
|
||||
|
||||
/**
|
||||
A COLLADA effect parameter.
|
||||
|
||||
This interface class is used to define all the valid
|
||||
ColladaFX parameter types. There are many types of
|
||||
parameters: integers, booleans, floating-point
|
||||
values, 2D, 3D and 4D vectors of floating-point values,
|
||||
matrices, strings, surfaces and their samplers.
|
||||
|
||||
A COLLADA effect parameter may generate a new
|
||||
effect parameter, in which case it will declare a semantic
|
||||
and a reference: to represent it within the COLLADA document.
|
||||
|
||||
@ingroup FCDEffect
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameter : public FCDObject
|
||||
{
|
||||
public:
|
||||
/** The type of the effect parameter class. */
|
||||
enum Type
|
||||
{
|
||||
SAMPLER, /**< A sampler effect parameter. Points towards a surface parameter and adds extra texturing parameters. */
|
||||
INTEGER, /**< A single integer effect parameter. */
|
||||
BOOLEAN, /**< A single boolean effect parameter. */
|
||||
FLOAT, /**< A single floating-pointer value effect parameter. */
|
||||
FLOAT2, /**< A 2D vector of floating-pointer values. */
|
||||
FLOAT3, /**< A 3D vector of floating-pointer values. */
|
||||
VECTOR, /**< A 4D vector of floating-pointer values. */
|
||||
MATRIX, /**< A 4x4 matrix. */
|
||||
STRING, /**< A string effect parameter. */
|
||||
SURFACE /**< A surface effect parameter. Contains a COLLADA image pointer. */
|
||||
};
|
||||
|
||||
private:
|
||||
bool isGenerator; // whether this effect parameter structure generates a new value or modifies an existing value (is <newparam>?)
|
||||
string reference;
|
||||
string semantic; // this is a Collada Semantic, not a Cg semantic
|
||||
|
||||
// [glaforte] These two members should be somewhere else
|
||||
string bindSymbol; // this can be used in Cg to bind to the correct variable
|
||||
bool isFragment; // parameter bound to the fragment program or the vertex one
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::AddParameter function.
|
||||
@param document The COLLADA document that owns the effect parameter. */
|
||||
FCDEffectParameter(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::ReleaseParameter function.
|
||||
When released, the effect parameter list will also release all
|
||||
its parameters, if it owns them. */
|
||||
virtual ~FCDEffectParameter();
|
||||
|
||||
/** Retrieves the type of effect parameter class.
|
||||
@return The type of the effect parameter class.*/
|
||||
virtual Type GetType() const = 0;
|
||||
|
||||
/** Retrieves the reference for this effect parameter.
|
||||
In the case of generators, the reference string contains the sub-id.
|
||||
@return The reference. */
|
||||
const string& GetReference() const { return reference; }
|
||||
|
||||
/** Retrieves the semantic for this effect parameter.
|
||||
@return The semantic. */
|
||||
const string& GetSemantic() const { return semantic; }
|
||||
|
||||
/** Sets the semantic for this effect parameter.
|
||||
@param _semantic The semantic. */
|
||||
void SetSemantic(const string& _semantic) { semantic = _semantic; }
|
||||
|
||||
/** Retrieves whether this effect parameter is a parameter generator.
|
||||
A ColladaFX parameter must be generated to be modified or bound at
|
||||
higher abstraction levels.
|
||||
@return Whether this is a generator. */
|
||||
bool IsGenerator() const { return isGenerator; }
|
||||
|
||||
/** Retrieves whether this effect parameter is a parameter modifier.
|
||||
A ColladaFX parameter must be generated to be modified or bound at
|
||||
higher abstraction levels.
|
||||
@return Whether this is a modifier. */
|
||||
bool IsModifier() const { return !isGenerator; }
|
||||
|
||||
/** @deprecated Retrieves the program bind symbol for
|
||||
this parameter. This information should be available
|
||||
per-shader, in the FCDEffectPassShader class.
|
||||
@return The program bind symbol. */
|
||||
const string& GetBindSymbol() const { return bindSymbol; }
|
||||
|
||||
/** @deprecated Sets the program bind symbol for this parameter.
|
||||
This information is available per-shader, in the FCDEffectPassShader class.
|
||||
@param _bindSymbol The program bind symbol. */
|
||||
void SetBindSymbol(const string& _bindSymbol) { bindSymbol = _bindSymbol; }
|
||||
|
||||
/** @deprecated Retrieves whether the program bind symbol attached
|
||||
to this parameter belongs to a fragment/pixel shader.
|
||||
This information is available per-shader, in the FCDEffectPassShader class.
|
||||
@return Whether it belongs to a fragment/pixel shader. */
|
||||
bool IsFragment() const { return isFragment; }
|
||||
|
||||
/** @deprecated Sets whether the program bind symbol attached to this
|
||||
parameter belongs to a fragment/pixel shader.
|
||||
This information is available per-shader, in the FCDEffectPassShader class.
|
||||
@param _isFragment Whether it belongs to a fragment/pixel shader. */
|
||||
void SetFragment(bool _isFragment) { isFragment = _isFragment;}
|
||||
|
||||
/** Creates a full copy of the effect parameter.
|
||||
@return The cloned effect parameter. You will need to delete this pointer. */
|
||||
virtual FCDEffectParameter* Clone() = 0;
|
||||
|
||||
/** [INTERNAL] Overwrites the target parameter with this parameter.
|
||||
This function is used during the flattening of materials.
|
||||
@param target The target parameter to overwrite. */
|
||||
virtual void Overwrite(FCDEffectParameter* target);
|
||||
|
||||
/** [INTERNAL] Reads in the effect parameter from a given COLLADA XML tree node.
|
||||
@param parameterNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the parameter.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* parameterNode);
|
||||
|
||||
/** [INTERNAL] Writes out the effect parameter to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the parameter.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
|
||||
protected:
|
||||
/** [INTERNAL] Copies into the given effect parameters, the variables
|
||||
held by the FCDEffectParameter interface. This function is used by the classes
|
||||
based on this interface during the cloning process.
|
||||
@param clone The parameter to clone. */
|
||||
void Clone(FCDEffectParameter* clone);
|
||||
};
|
||||
|
||||
/**
|
||||
A COLLADA sampler effect parameter.
|
||||
A sampler parameter provides the extra texturing information necessary
|
||||
to correctly sample a surface parameter.
|
||||
There are four types of samplers supported: 1D, 2D, 3D and cube.
|
||||
|
||||
@ingroup FCDEffect
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterSampler : public FCDEffectParameter
|
||||
{
|
||||
public:
|
||||
/** The type of sampling to execute. */
|
||||
enum SamplerType
|
||||
{
|
||||
SAMPLER1D, /** 1D sampling. */
|
||||
SAMPLER2D, /** 2D sampling. */
|
||||
SAMPLER3D, /** 3D sampling. */
|
||||
SAMPLERCUBE /** Cube-map sampling. */
|
||||
};
|
||||
|
||||
private:
|
||||
SamplerType samplerType;
|
||||
string surfaceSid;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::AddParameter function.
|
||||
@param document The COLLADA document that owns the effect parameter. */
|
||||
FCDEffectParameterSampler(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::ReleaseParameter function.
|
||||
When released, the effect parameter list will also release all
|
||||
its parameters, if it owns them. */
|
||||
virtual ~FCDEffectParameterSampler();
|
||||
|
||||
/** Retrieves the type of effect parameter class.
|
||||
@return The parameter class type: SAMPLER. */
|
||||
virtual Type GetType() const { return SAMPLER; }
|
||||
|
||||
/** Retrieves the sub-id of the surface parameter.
|
||||
You will want to search for that sub-id within the parameters to find the
|
||||
FCDEffectParameterSurface object.
|
||||
@return The sub-id. */
|
||||
const char* GetSurfaceSid() const { return surfaceSid.c_str(); }
|
||||
|
||||
/** Sets the sub-id of the surface parameter to sample.
|
||||
@param sid The surface parameter sub-id. */
|
||||
void SetSurfaceSid(const char* sid) { surfaceSid = sid; }
|
||||
|
||||
/** Retrieves the type of sampling to do.
|
||||
@return The sampling type. */
|
||||
SamplerType GetSamplerType() const { return samplerType; }
|
||||
|
||||
/** Sets the type of sampling to do.
|
||||
@param type The sampling type. */
|
||||
void SetSamplerType(SamplerType type) { samplerType = type; }
|
||||
|
||||
/** Creates a full copy of the effect parameter.
|
||||
@return The cloned effect parameter. You will need to delete this pointer. */
|
||||
virtual FCDEffectParameter* Clone();
|
||||
|
||||
/** [INTERNAL] Overwrites the target parameter with this parameter.
|
||||
This function is used during the flattening of materials.
|
||||
@param target The target parameter to overwrite. */
|
||||
virtual void Overwrite(FCDEffectParameter* target);
|
||||
|
||||
/** [INTERNAL] Reads in the effect parameter from a given COLLADA XML tree node.
|
||||
@param parameterNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the parameter.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* parameterNode);
|
||||
|
||||
/** [INTERNAL] Writes out the effect parameter to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the parameter.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
/**
|
||||
A COLLADA integer effect parameter.
|
||||
Contains a single, unanimated integer.
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterInt : public FCDEffectParameter
|
||||
{
|
||||
private:
|
||||
int value;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::AddParameter function.
|
||||
@param document The COLLADA document that owns the effect parameter. */
|
||||
FCDEffectParameterInt(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::ReleaseParameter function.
|
||||
When released, the effect parameter list will also release all
|
||||
its parameters, if it owns them. */
|
||||
virtual ~FCDEffectParameterInt();
|
||||
|
||||
/** Retrieves the type of effect parameter class.
|
||||
@return The parameter class type: INTEGER. */
|
||||
virtual Type GetType() const { return INTEGER; }
|
||||
|
||||
/** Retrieves the value of the effect parameter.
|
||||
@return The integer value. */
|
||||
int GetValue() const { return value; }
|
||||
|
||||
/** Sets the integer value of the effect parameter.
|
||||
@param _value The integer value. */
|
||||
void SetValue(int _value) { value = _value; }
|
||||
|
||||
/** Creates a full copy of the effect parameter.
|
||||
@return The cloned effect parameter. You will need to delete this pointer. */
|
||||
virtual FCDEffectParameter* Clone();
|
||||
|
||||
/** [INTERNAL] Overwrites the target parameter with this parameter.
|
||||
This function is used during the flattening of materials.
|
||||
@param target The target parameter to overwrite. */
|
||||
virtual void Overwrite(FCDEffectParameter* target);
|
||||
|
||||
/** [INTERNAL] Reads in the effect parameter from a given COLLADA XML tree node.
|
||||
@param parameterNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the parameter.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* parameterNode);
|
||||
|
||||
/** [INTERNAL] Writes out the effect parameter to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the parameter.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
/**
|
||||
A COLLADA boolean effect parameter.
|
||||
Contains a single, unanimated boolean.
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterBool : public FCDEffectParameter
|
||||
{
|
||||
private:
|
||||
bool value;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::AddParameter function.
|
||||
@param document The COLLADA document that owns the effect parameter. */
|
||||
FCDEffectParameterBool(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::ReleaseParameter function.
|
||||
When released, the effect parameter list will also release all
|
||||
its parameters, if it owns them. */
|
||||
virtual ~FCDEffectParameterBool();
|
||||
|
||||
/** Retrieves the type of effect parameter class.
|
||||
@return The parameter class type: BOOLEAN. */
|
||||
virtual Type GetType() const { return BOOLEAN; }
|
||||
|
||||
/** Retrieves the boolean value of the effect parameter.
|
||||
@return The boolean value. */
|
||||
bool GetValue() const { return value; }
|
||||
|
||||
/** Sets the boolean value of the effect parameter.
|
||||
@param _value The boolean value. */
|
||||
void SetValue(bool _value) { value = _value; }
|
||||
|
||||
/** Creates a full copy of the effect parameter.
|
||||
@return The cloned effect parameter. You will need to delete this pointer. */
|
||||
virtual FCDEffectParameter* Clone();
|
||||
|
||||
/** [INTERNAL] Overwrites the target parameter with this parameter.
|
||||
This function is used during the flattening of materials.
|
||||
@param target The target parameter to overwrite. */
|
||||
virtual void Overwrite(FCDEffectParameter* target);
|
||||
|
||||
/** [INTERNAL] Reads in the effect parameter from a given COLLADA XML tree node.
|
||||
@param parameterNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the parameter.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* parameterNode);
|
||||
|
||||
/** [INTERNAL] Writes out the effect parameter to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the parameter.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
/**
|
||||
A COLLADA string effect parameter.
|
||||
Contains a single, unanimated string.
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterString : public FCDEffectParameter
|
||||
{
|
||||
private:
|
||||
string value;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::AddParameter function.
|
||||
@param document The COLLADA document that owns the effect parameter. */
|
||||
FCDEffectParameterString(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::ReleaseParameter function.
|
||||
When released, the effect parameter list will also release all
|
||||
its parameters, if it owns them. */
|
||||
virtual ~FCDEffectParameterString();
|
||||
|
||||
/** Retrieves the type of effect parameter class.
|
||||
@return The parameter class type: STRING. */
|
||||
virtual Type GetType() const { return STRING; }
|
||||
|
||||
/** Retrieves the string contained in the effect parameter.
|
||||
@return The string. */
|
||||
const string& GetValue() const { return value; }
|
||||
|
||||
/** Sets the string contained in the effect parameter.
|
||||
@param _value The string. */
|
||||
void SetValue(const string& _value) { value = _value; }
|
||||
|
||||
/** Creates a full copy of the effect parameter.
|
||||
@return The cloned effect parameter. You will need to delete this pointer. */
|
||||
virtual FCDEffectParameter* Clone();
|
||||
|
||||
/** [INTERNAL] Overwrites the target parameter with this parameter.
|
||||
This function is used during the flattening of materials.
|
||||
@param target The target parameter to overwrite. */
|
||||
virtual void Overwrite(FCDEffectParameter* target);
|
||||
|
||||
/** [INTERNAL] Reads in the effect parameter from a given COLLADA XML tree node.
|
||||
@param parameterNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the parameter.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* parameterNode);
|
||||
|
||||
/** [INTERNAL] Writes out the effect parameter to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the parameter.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
/**
|
||||
A COLLADA float effect parameter.
|
||||
Contains a single, possibly animated, floating-point value.
|
||||
The type of the floating-point value may be HALF or FLOAT.
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterFloat : public FCDEffectParameter
|
||||
{
|
||||
public:
|
||||
/** The supported types of float-point values. */
|
||||
enum FloatType
|
||||
{
|
||||
FLOAT, /** A full-fledged floating-point value. This is the default. */
|
||||
HALF /** Probably implies a 16-bit floating-point value. */
|
||||
};
|
||||
|
||||
private:
|
||||
FloatType floatType;
|
||||
float value;
|
||||
float min;
|
||||
float max;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::AddParameter function.
|
||||
@param document The COLLADA document that owns the effect parameter. */
|
||||
FCDEffectParameterFloat(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::ReleaseParameter function.
|
||||
When released, the effect parameter list will also release all
|
||||
its parameters, if it owns them. */
|
||||
virtual ~FCDEffectParameterFloat();
|
||||
|
||||
/** Retrieves the type of effect parameter class.
|
||||
@return The parameter class type: FLOAT. */
|
||||
virtual FCDEffectParameter::Type GetType() const { return FCDEffectParameter::FLOAT; }
|
||||
|
||||
/** Retrieves the type of floating-point value held by this effect parameter.
|
||||
@return The type of floating-point value. */
|
||||
FloatType GetFloatType() const { return floatType; }
|
||||
|
||||
/** Sets the type of floating-point value held by this effect parameter.
|
||||
@param type The type of floating-point value. */
|
||||
void SetFloatType(FloatType type) { floatType = type; }
|
||||
|
||||
/** Retrieves the floating-point value of the effect parameter.
|
||||
@return The floating-point value. */
|
||||
float& GetValue() { return value; }
|
||||
const float& GetValue() const { return value; } /**< See above. */
|
||||
|
||||
/** Sets the floating-point value of the effect parameter.
|
||||
@param _value The floating-point value. */
|
||||
void SetValue(float _value) { value = _value; }
|
||||
|
||||
/** Retrieves the minimum value for the UI widget created for this effect parameter.
|
||||
This value is for UI purposes only and has no real impact on the value.
|
||||
@return The minimum value. */
|
||||
float GetMin() const { return min; }
|
||||
|
||||
/** Sets the minimum value for the UI widget created for this effect parameter.
|
||||
This value is for UI purposes only and has no real impact on the value.
|
||||
@param _min The minimum value. */
|
||||
void SetMin(float _min) { min = _min; }
|
||||
|
||||
/** Retrieves the maximum value for the UI widget created for this effect parameter.
|
||||
This value is for UI purposes only and has no real impact on the value.
|
||||
@return The maximum value. */
|
||||
float GetMax() const { return max; }
|
||||
|
||||
/** Sets the maximum value for the UI widget created for this effect parameter.
|
||||
This value is for UI purposes only and has no real impact on the value.
|
||||
@param _max The maximum value. */
|
||||
void SetMax(float _max) { max = _max; }
|
||||
|
||||
/** Creates a full copy of the effect parameter.
|
||||
@return The cloned effect parameter. You will need to delete this pointer. */
|
||||
virtual FCDEffectParameter* Clone();
|
||||
|
||||
/** [INTERNAL] Overwrites the target parameter with this parameter.
|
||||
This function is used during the flattening of materials.
|
||||
@param target The target parameter to overwrite. */
|
||||
virtual void Overwrite(FCDEffectParameter* target);
|
||||
|
||||
/** [INTERNAL] Reads in the effect parameter from a given COLLADA XML tree node.
|
||||
@param parameterNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the parameter.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* parameterNode);
|
||||
|
||||
/** [INTERNAL] Writes out the effect parameter to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the parameter.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
/**
|
||||
A COLLADA 2D vector of floats.
|
||||
Contains two, possibly animated, floating-point values.
|
||||
The type of the floating-point values may be HALF or FLOAT.
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterFloat2 : public FCDEffectParameter
|
||||
{
|
||||
public:
|
||||
/** The supported types of float-point values. */
|
||||
enum FloatType
|
||||
{
|
||||
FLOAT, /** A full-fledged floating-point value. This is the default. */
|
||||
HALF /** Probably implies a 16-bit floating-point value. */
|
||||
};
|
||||
|
||||
private:
|
||||
FloatType floatType;
|
||||
float value_x;
|
||||
float value_y;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::AddParameter function.
|
||||
@param document The COLLADA document that owns the effect parameter. */
|
||||
FCDEffectParameterFloat2(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::ReleaseParameter function.
|
||||
When released, the effect parameter list will also release all
|
||||
its parameters, if it owns them. */
|
||||
virtual ~FCDEffectParameterFloat2();
|
||||
|
||||
/** Retrieves the type of effect parameter class.
|
||||
@return The parameter class type: FLOAT2. */
|
||||
virtual Type GetType() const { return FLOAT2; }
|
||||
|
||||
/** Retrieves the type of floating-point value held by this effect parameter.
|
||||
@return The type of floating-point value. */
|
||||
FloatType GetFloatType() const { return floatType; }
|
||||
|
||||
/** Sets the type of floating-point value held by this effect parameter.
|
||||
@param type The type of floating-point value. */
|
||||
void SetFloatType(FloatType type) { floatType = type; }
|
||||
|
||||
/** Retrieves the first floating-point value of the effect parameter.
|
||||
@return The first floating-point value. */
|
||||
float& GetValueX() { return value_x; }
|
||||
const float& GetValueX() const { return value_x; } /**< See above. */
|
||||
|
||||
/** Sets the first floating-point value of the effect parameter.
|
||||
@param value The first floating-point value. */
|
||||
void SetValueX(float value) { value_x = value; }
|
||||
|
||||
/** Retrieves the second floating-point value of the effect parameter.
|
||||
@return The second floating-point value. */
|
||||
float& GetValueY() { return value_y; }
|
||||
const float& GetValueY() const { return value_y; } /**< See above. */
|
||||
|
||||
/** Sets the second floating-point value of the effect parameter.
|
||||
@param value The second floating-point value. */
|
||||
void SetValueY(float value) { value_y = value; }
|
||||
|
||||
/** Creates a full copy of the effect parameter.
|
||||
@return The cloned effect parameter. You will need to delete this pointer. */
|
||||
virtual FCDEffectParameter* Clone();
|
||||
|
||||
/** [INTERNAL] Overwrites the target parameter with this parameter.
|
||||
This function is used during the flattening of materials.
|
||||
@param target The target parameter to overwrite. */
|
||||
virtual void Overwrite(FCDEffectParameter* target);
|
||||
|
||||
/** [INTERNAL] Reads in the effect parameter from a given COLLADA XML tree node.
|
||||
@param parameterNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the parameter.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* parameterNode);
|
||||
|
||||
/** [INTERNAL] Writes out the effect parameter to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the parameter.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
/**
|
||||
A COLLADA 3D vector of floats.
|
||||
Contains three, possibly animated, floating-point values.
|
||||
The type of the floating-point values may be HALF or FLOAT.
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterFloat3 : public FCDEffectParameter
|
||||
{
|
||||
public:
|
||||
/** The supported types of float-point values. */
|
||||
enum FloatType
|
||||
{
|
||||
FLOAT, /** A full-fledged floating-point value. This is the default. */
|
||||
HALF /** Probably implies a 16-bit floating-point value. */
|
||||
};
|
||||
|
||||
private:
|
||||
FloatType floatType;
|
||||
FMVector3 value;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::AddParameter function.
|
||||
@param document The COLLADA document that owns the effect parameter. */
|
||||
FCDEffectParameterFloat3(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::ReleaseParameter function.
|
||||
When released, the effect parameter list will also release all
|
||||
its parameters, if it owns them. */
|
||||
virtual ~FCDEffectParameterFloat3();
|
||||
|
||||
/** Retrieves the type of effect parameter class.
|
||||
@return The parameter class type: FLOAT3. */
|
||||
virtual Type GetType() const { return FLOAT3; }
|
||||
|
||||
/** Retrieves the type of floating-point value held by this effect parameter.
|
||||
@return The type of floating-point value. */
|
||||
FloatType GetFloatType() const { return floatType; }
|
||||
|
||||
/** Sets the type of floating-point value held by this effect parameter.
|
||||
@param type The type of floating-point value. */
|
||||
void SetFloatType(FloatType type) { floatType = type; }
|
||||
|
||||
/** Retrieves the first floating-point value of the effect parameter.
|
||||
@return The first floating-point value. */
|
||||
float& GetValueX() { return value.x; }
|
||||
const float& GetValueX() const { return value.x; } /**< See above. */
|
||||
|
||||
/** Sets the first floating-point value of the effect parameter.
|
||||
@param _value The first floating-point value. */
|
||||
void SetValueX(float _value) { value.x = _value; }
|
||||
|
||||
/** Retrieves the second floating-point value of the effect parameter.
|
||||
@return The second floating-point value. */
|
||||
float& GetValueY() { return value.y; }
|
||||
const float& GetValueY() const { return value.y; } /**< See above. */
|
||||
|
||||
/** Sets the second floating-point value of the effect parameter.
|
||||
@param _value The second floating-point value. */
|
||||
void SetValueY(float _value) { value.y = _value; }
|
||||
|
||||
/** Retrieves the third floating-point value of the effect parameter.
|
||||
@return The third floating-point value. */
|
||||
float& GetValueZ() { return value.z; }
|
||||
const float& GetValueZ() const { return value.z; } /**< See above. */
|
||||
|
||||
/** Sets the third floating-point value of the effect parameter.
|
||||
@param _value The third floating-point value. */
|
||||
void SetValueZ(float _value) { value.z = _value; }
|
||||
|
||||
/** Creates a full copy of the effect parameter.
|
||||
@return The cloned effect parameter. You will need to delete this pointer. */
|
||||
virtual FCDEffectParameter* Clone();
|
||||
|
||||
/** [INTERNAL] Overwrites the target parameter with this parameter.
|
||||
This function is used during the flattening of materials.
|
||||
@param target The target parameter to overwrite. */
|
||||
virtual void Overwrite(FCDEffectParameter* target);
|
||||
|
||||
/** [INTERNAL] Reads in the effect parameter from a given COLLADA XML tree node.
|
||||
@param parameterNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the parameter.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* parameterNode);
|
||||
|
||||
/** [INTERNAL] Writes out the effect parameter to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the parameter.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
/**
|
||||
A COLLADA 4D vector of floats.
|
||||
Contains four, possibly animated, floating-point values.
|
||||
The type of the floating-point values may be HALF or FLOAT.
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterVector : public FCDEffectParameter
|
||||
{
|
||||
public:
|
||||
/** The supported types of float-point values. */
|
||||
enum FloatType
|
||||
{
|
||||
FLOAT, /** A full-fledged floating-point value. This is the default. */
|
||||
HALF /** Probably implies a 16-bit floating-point value. */
|
||||
};
|
||||
|
||||
private:
|
||||
FloatType floatType;
|
||||
float vector[4];
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::AddParameter function.
|
||||
@param document The COLLADA document that owns the effect parameter. */
|
||||
FCDEffectParameterVector(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::ReleaseParameter function.
|
||||
When released, the effect parameter list will also release all
|
||||
its parameters, if it owns them. */
|
||||
virtual ~FCDEffectParameterVector();
|
||||
|
||||
/** Retrieves the type of effect parameter class.
|
||||
@return The parameter class type: VECTOR. */
|
||||
virtual Type GetType() const { return VECTOR; }
|
||||
|
||||
/** Retrieves the type of floating-point value held by this effect parameter.
|
||||
@return The type of floating-point value. */
|
||||
FloatType GetFloatType() const { return floatType; }
|
||||
|
||||
/** Sets the type of floating-point value held by this effect parameter.
|
||||
@param type The type of floating-point value. */
|
||||
void SetFloatType(FloatType type) { floatType = type; }
|
||||
|
||||
/** Sets the vector value of the effect parameter.
|
||||
@return The vector value. */
|
||||
float* GetVector() { return vector; }
|
||||
const float* GetVector() const { return vector; } /**< See above. */
|
||||
|
||||
/** Retrieves the first floating-point value of the effect parameter.
|
||||
@return The first floating-point value. */
|
||||
float& GetValueX() { return vector[0]; }
|
||||
const float& GetValueX() const { return vector[0]; } /**< See above. */
|
||||
|
||||
/** Sets the first floating-point value of the effect parameter.
|
||||
@param _value The first floating-point value. */
|
||||
void SetValueX(float _value) { vector[0] = _value; }
|
||||
|
||||
/** Retrieves the second floating-point value of the effect parameter.
|
||||
@return The second floating-point value. */
|
||||
float& GetValueY() { return vector[1]; }
|
||||
const float& GetValueY() const { return vector[1]; } /**< See above. */
|
||||
|
||||
/** Sets the second floating-point value of the effect parameter.
|
||||
@param _value The second floating-point value. */
|
||||
void SetValueY(float _value) { vector[1] = _value; }
|
||||
|
||||
/** Retrieves the third floating-point value of the effect parameter.
|
||||
@return The third floating-point value. */
|
||||
float& GetValueZ() { return vector[2]; }
|
||||
const float& GetValueZ() const { return vector[2]; } /**< See above. */
|
||||
|
||||
/** Sets the third floating-point value of the effect parameter.
|
||||
@param _value The third floating-point value. */
|
||||
void SetValueZ(float _value) { vector[2] = _value; }
|
||||
|
||||
/** Retrieves the fourth floating-point value of the effect parameter.
|
||||
@return The fourth floating-point value. */
|
||||
float& GetValueW() { return vector[3]; }
|
||||
const float& GetValueW() const { return vector[3]; } /**< See above. */
|
||||
|
||||
/** Sets the fourth floating-point value of the effect parameter.
|
||||
@param _value The fourth floating-point value. */
|
||||
void SetValueW(float _value) { vector[3] = _value; }
|
||||
|
||||
/** Creates a full copy of the effect parameter.
|
||||
@return The cloned effect parameter. You will need to delete this pointer. */
|
||||
virtual FCDEffectParameter* Clone();
|
||||
|
||||
/** [INTERNAL] Overwrites the target parameter with this parameter.
|
||||
This function is used during the flattening of materials.
|
||||
@param target The target parameter to overwrite. */
|
||||
virtual void Overwrite(FCDEffectParameter* target);
|
||||
|
||||
/** [INTERNAL] Reads in the effect parameter from a given COLLADA XML tree node.
|
||||
@param parameterNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the parameter.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* parameterNode);
|
||||
|
||||
/** [INTERNAL] Writes out the effect parameter to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the parameter.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
/**
|
||||
A COLLADA 4x4 matrix.
|
||||
Contains 16 floating-point values that represent a COLLADA column-major 4x4 matrix.
|
||||
The type of the floating-point values may be HALF or FLOAT.
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterMatrix : public FCDEffectParameter
|
||||
{
|
||||
public:
|
||||
/** The supported types of float-point values. */
|
||||
enum FloatType
|
||||
{
|
||||
FLOAT, /** A full-fledged floating-point value. This is the default. */
|
||||
HALF /** Probably implies a 16-bit floating-point value. */
|
||||
};
|
||||
|
||||
private:
|
||||
FloatType floatType;
|
||||
FMMatrix44 matrix;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::AddParameter function.
|
||||
@param document The COLLADA document that owns the effect parameter. */
|
||||
FCDEffectParameterMatrix(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::ReleaseParameter function.
|
||||
When released, the effect parameter list will also release all
|
||||
its parameters, if it owns them. */
|
||||
virtual ~FCDEffectParameterMatrix();
|
||||
|
||||
/** Retrieves the type of effect parameter class.
|
||||
@return The parameter class type: MATRIX. */
|
||||
virtual Type GetType() const { return MATRIX; }
|
||||
|
||||
/** Retrieves the type of floating-point value held by this effect parameter.
|
||||
@return The type of floating-point value. */
|
||||
FloatType GetFloatType() const { return floatType; }
|
||||
|
||||
/** Sets the type of floating-point value held by this effect parameter.
|
||||
@param type The type of floating-point value. */
|
||||
void SetFloatType(FloatType type) { floatType = type; }
|
||||
|
||||
/** Retrieves the matrix contained within this effect parameter.
|
||||
@return The matrix. */
|
||||
FMMatrix44& GetMatrix() { return matrix; }
|
||||
const FMMatrix44& GetMatrix() const { return matrix; } /**< See above. */
|
||||
|
||||
/** Sets the matrix contained within this effect parameter.
|
||||
@param mx The matrix. */
|
||||
void SetMatrix(const FMMatrix44& mx) { matrix = mx; }
|
||||
|
||||
/** Creates a full copy of the effect parameter.
|
||||
@return The cloned effect parameter. You will need to delete this pointer. */
|
||||
virtual FCDEffectParameter* Clone();
|
||||
|
||||
/** [INTERNAL] Overwrites the target parameter with this parameter.
|
||||
This function is used during the flattening of materials.
|
||||
@param target The target parameter to overwrite. */
|
||||
virtual void Overwrite(FCDEffectParameter* target);
|
||||
|
||||
/** [INTERNAL] Reads in the effect parameter from a given COLLADA XML tree node.
|
||||
@param parameterNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the parameter.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* parameterNode);
|
||||
|
||||
/** [INTERNAL] Writes out the effect parameter to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the parameter.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif // _FCD_EFFECT_PARAMETER_H_
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDEffectParameter.h"
|
||||
#include "FCDocument/FCDEffectParameterFactory.h"
|
||||
#include "FCDocument/FCDEffectParameterSurface.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
|
||||
// Creates a new effect parameter, given a type.
|
||||
FCDEffectParameter* FCDEffectParameterFactory::Create(FCDocument* document, uint32 type)
|
||||
{
|
||||
FCDEffectParameter* parameter = NULL;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FCDEffectParameter::SAMPLER: parameter = new FCDEffectParameterSampler(document); break;
|
||||
case FCDEffectParameter::INTEGER: parameter = new FCDEffectParameterInt(document); break;
|
||||
case FCDEffectParameter::BOOLEAN: parameter = new FCDEffectParameterBool(document); break;
|
||||
case FCDEffectParameter::FLOAT: parameter = new FCDEffectParameterFloat(document); break;
|
||||
case FCDEffectParameter::FLOAT2: parameter = new FCDEffectParameterFloat2(document); break;
|
||||
case FCDEffectParameter::FLOAT3: parameter = new FCDEffectParameterFloat3(document); break;
|
||||
case FCDEffectParameter::VECTOR: parameter = new FCDEffectParameterVector(document); break;
|
||||
case FCDEffectParameter::MATRIX: parameter = new FCDEffectParameterMatrix(document); break;
|
||||
case FCDEffectParameter::STRING: parameter = new FCDEffectParameterString(document); break;
|
||||
case FCDEffectParameter::SURFACE: parameter = new FCDEffectParameterSurface(document); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
// Generates the effect parameter object for the given XML node tree
|
||||
FCDEffectParameter* FCDEffectParameterFactory::LoadFromXML(FCDocument* document, xmlNode* parameterNode, FUStatus* status)
|
||||
{
|
||||
// Look for the type of the parameter.
|
||||
FCDEffectParameter* parameter = NULL;
|
||||
for (xmlNode* child = parameterNode->children; child != NULL && parameter == NULL; child = child->next)
|
||||
{
|
||||
if (child->type != XML_ELEMENT_NODE) continue;
|
||||
|
||||
if (IsEquivalent(child->name, DAE_FXCMN_BOOL_ELEMENT)) parameter = new FCDEffectParameterBool(document);
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_FLOAT_ELEMENT)) parameter = new FCDEffectParameterFloat(document);
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_FLOAT2_ELEMENT)) parameter = new FCDEffectParameterFloat2(document);
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_FLOAT3_ELEMENT)) parameter = new FCDEffectParameterFloat3(document);
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_FLOAT4_ELEMENT)) parameter = new FCDEffectParameterVector(document);
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_FLOAT4X4_ELEMENT)) parameter = new FCDEffectParameterMatrix(document);
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_HALF_ELEMENT)) parameter = new FCDEffectParameterFloat(document);
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_HALF2_ELEMENT)) parameter = new FCDEffectParameterFloat2(document);
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_HALF3_ELEMENT)) parameter = new FCDEffectParameterFloat3(document);
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_HALF4_ELEMENT)) parameter = new FCDEffectParameterVector(document);
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_HALF4X4_ELEMENT)) parameter = new FCDEffectParameterMatrix(document);
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_INT_ELEMENT)) parameter = new FCDEffectParameterInt(document);
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_SAMPLER1D_ELEMENT)) parameter = new FCDEffectParameterSampler(document);
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_SAMPLER2D_ELEMENT)) parameter = new FCDEffectParameterSampler(document);
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_SAMPLER3D_ELEMENT)) parameter = new FCDEffectParameterSampler(document);
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_SAMPLERCUBE_ELEMENT)) parameter = new FCDEffectParameterSampler(document);
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_SURFACE_ELEMENT)) parameter = new FCDEffectParameterSurface(document);
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_STRING_ELEMENT)) parameter = new FCDEffectParameterString(document);
|
||||
}
|
||||
|
||||
if (parameter != NULL)
|
||||
{
|
||||
FUStatus s = parameter->LoadFromXML(parameterNode);
|
||||
if (status != NULL) status->AppendStatus(s);
|
||||
}
|
||||
return parameter;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDEffectParameterFactory.h
|
||||
This file contains the FCDEffectParameterFactory class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_EFFECT_PARAMETER_FACTORY_H_
|
||||
#define _FCD_EFFECT_PARAMETER_FACTORY_H_
|
||||
|
||||
class FCDocument;
|
||||
|
||||
/**
|
||||
[INTERNAL] The factory for COLLADA effect parameters.
|
||||
|
||||
Takes in a COLLADA XML tree and returns a new
|
||||
parameter that represent it, if one is possible.
|
||||
|
||||
@ingroup FCDEffect
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterFactory
|
||||
{
|
||||
private:
|
||||
// Never instantiate: this is a static class
|
||||
FCDEffectParameterFactory() {}
|
||||
|
||||
public:
|
||||
/** [INTERNAL] Creates a new effect parameter, given a type.
|
||||
To create new effect parameters, use the FCDEffectParameterList::AddParameter function.
|
||||
@param document The COLLADA document that will own the effect parameter.
|
||||
@param type The type of effect to create.
|
||||
This value should reflect the FCDEffectParameter::Type enum. */
|
||||
static FCDEffectParameter* Create(FCDocument* document, uint32 type);
|
||||
|
||||
/** [INTERNAL] Generates the effect parameter object for the given XML node tree.
|
||||
@param document The COLLADA document that will own the effect parameter.
|
||||
@param parameterNode The COLLADA XML tree node.
|
||||
@param status An optional return status.
|
||||
@return The new effect parameter. This pointer will be NULL if no parameter can be generated
|
||||
from the given COLLADA XML tree node. */
|
||||
static FCDEffectParameter* LoadFromXML(FCDocument* document, xmlNode* parameterNode, FUStatus* status);
|
||||
};
|
||||
|
||||
#endif // _FCD_EFFECT_PARAMETER_FACTORY_H_
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDEffectParameter.h"
|
||||
#include "FCDocument/FCDEffectParameterFactory.h"
|
||||
#include "FCDocument/FCDEffectParameterList.h"
|
||||
|
||||
FCDEffectParameterList::FCDEffectParameterList(FCDocument* document, bool _ownParameters)
|
||||
: FCDObject(document, "FCDEffectParameterList")
|
||||
{
|
||||
ownParameters = _ownParameters;
|
||||
}
|
||||
|
||||
FCDEffectParameterList::~FCDEffectParameterList()
|
||||
{
|
||||
if (ownParameters)
|
||||
{
|
||||
size_t l = size();
|
||||
for (size_t i = 0; i < l; ++i)
|
||||
{
|
||||
FCDEffectParameter* p = at(i);
|
||||
SAFE_DELETE(p);
|
||||
}
|
||||
}
|
||||
clear();
|
||||
ownParameters = false;
|
||||
}
|
||||
|
||||
FCDEffectParameter* FCDEffectParameterList::AddParameter(uint32 type)
|
||||
{
|
||||
FCDEffectParameter* parameter = NULL;
|
||||
if (ownParameters)
|
||||
{
|
||||
parameter = FCDEffectParameterFactory::Create(GetDocument(), type);
|
||||
push_back(parameter);
|
||||
}
|
||||
return parameter;
|
||||
}
|
||||
|
||||
void FCDEffectParameterList::ReleaseParameter(FCDEffectParameter* parameter)
|
||||
{
|
||||
iterator it = std::find(begin(), end(), parameter);
|
||||
if (it != end())
|
||||
{
|
||||
if (ownParameters) delete *it;
|
||||
erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
FCDEffectParameter* FCDEffectParameterList::FindReference(const char* reference)
|
||||
{
|
||||
for (iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
if ((*it)->GetReference() == reference) return (*it);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
const FCDEffectParameter* FCDEffectParameterList::FindReference(const char* reference) const
|
||||
{
|
||||
for (const_iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
if ((*it)->GetReference() == reference) return (*it);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FCDEffectParameter* FCDEffectParameterList::FindSemantic(const char* semantic)
|
||||
{
|
||||
for (iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
if ((*it)->GetSemantic() == semantic) return (*it);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
const FCDEffectParameter* FCDEffectParameterList::FindSemantic(const char* semantic) const
|
||||
{
|
||||
for (const_iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
if ((*it)->GetSemantic() == semantic) return (*it);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FCDEffectParameterList::FindReference(const char* reference, FCDEffectParameterList& list)
|
||||
{
|
||||
for (iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
if ((*it)->GetReference() == reference) list.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
void FCDEffectParameterList::FindSemantic(const char* semantic, FCDEffectParameterList& list)
|
||||
{
|
||||
for (iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
if ((*it)->GetSemantic() == semantic) list.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy this list
|
||||
FCDEffectParameterList* FCDEffectParameterList::Clone() const
|
||||
{
|
||||
FCDEffectParameterList* clone = new FCDEffectParameterList(GetDocument(), ownParameters);
|
||||
if (!empty())
|
||||
{
|
||||
clone->reserve(size());
|
||||
|
||||
if (ownParameters)
|
||||
{
|
||||
for (const_iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
clone->push_back((*it)->Clone());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(*clone) = (*this);
|
||||
}
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDEffectParameterList.h
|
||||
This file contains the FCDEffectParameterList class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_EFFECT_PARAMETER_LIST_H_
|
||||
#define _FCD_EFFECT_PARAMETER_LIST_H_
|
||||
|
||||
class FCDEffectParameter;
|
||||
|
||||
/**
|
||||
A searchable list of COLLADA effect parameters.
|
||||
|
||||
This class is based on the STL vector class and adds some
|
||||
useful search methods: by reference and by semantic.
|
||||
|
||||
@ingroup FCDEffect
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterList : public vector<FCDEffectParameter*>, public FCDObject
|
||||
{
|
||||
private:
|
||||
bool ownParameters;
|
||||
|
||||
public:
|
||||
/** Constructor.
|
||||
All the objects that need a parameter list will create it when necessary.
|
||||
You may also create new lists for the retrieval of parameters during a search.
|
||||
@param document The COLLADA document that owns this parameter list. This pointer
|
||||
can remain NULL unless you expect to create new parameters within this list.
|
||||
@param ownParameters Whether this list should release the contained parameters
|
||||
during its destruction. */
|
||||
FCDEffectParameterList(FCDocument* document = NULL, bool ownParameters = false);
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~FCDEffectParameterList();
|
||||
|
||||
/** Creates a new parameters within this list.
|
||||
@param type The effect parameter type.
|
||||
@return The new effect parameter. This pointer will be NULL if this list does not own its parameters. */
|
||||
FCDEffectParameter* AddParameter(uint32 type);
|
||||
|
||||
/** Releases a parameter contained within this list.
|
||||
The memory used by this parameter will be released only if this list owns the parameters.
|
||||
@param parameter The effect parameter to release. */
|
||||
void ReleaseParameter(FCDEffectParameter* parameter);
|
||||
|
||||
/** Retrieves the first effect parameter with the given reference.
|
||||
For effect parameter generators, the sub-id is used instead of the reference.
|
||||
@param reference A reference to match.
|
||||
@return The effect parameter that matches the reference. This pointer will be NULL,
|
||||
if no parameter matches the reference. */
|
||||
FCDEffectParameter* FindReference(const char* reference);
|
||||
const FCDEffectParameter* FindReference(const char* reference) const; /**< See above. */
|
||||
inline FCDEffectParameter* FindReference(const string& reference) { return FindReference(reference.c_str()); } /**< See above. */
|
||||
inline const FCDEffectParameter* FindReference(const string& reference) const { return FindReference(reference.c_str()); } /**< See above. */
|
||||
|
||||
/** Retrieves the first effect parameter with the given semantic.
|
||||
@param semantic A semantic to match.
|
||||
@return The effect parameter that matches the semantic. This pointer will be NULL
|
||||
if no parameter matches the semantic. */
|
||||
FCDEffectParameter* FindSemantic(const char* semantic);
|
||||
const FCDEffectParameter* FindSemantic(const char* semantic) const; /**< See above. */
|
||||
inline FCDEffectParameter* FindSemantic(const string& semantic) { return FindReference(semantic.c_str()); } /**< See above. */
|
||||
inline const FCDEffectParameter* FindSemantic(const string& semantic) const { return FindReference(semantic.c_str()); } /**< See above. */
|
||||
|
||||
/** Retrieves a subset of this parameter list.
|
||||
All the effects that match the given reference will be added to the given list.
|
||||
For effect parameter generators, the sub-id is used instead of the reference.
|
||||
@param reference A reference to match.
|
||||
@param list The effect parameter list to fill in with the matched parameters.
|
||||
This list is not clear. */
|
||||
void FindReference(const char* reference, FCDEffectParameterList& list);
|
||||
inline void FindReference(const string& reference, FCDEffectParameterList& list) { return FindReference(reference.c_str(), list); } /**< See above. */
|
||||
|
||||
/** Retrieves a subset of this parameter list.
|
||||
All the effects that match the given semantic will be added to the given list.
|
||||
@param semantic A semantic to match.
|
||||
@param list The effect parameter list to fill in with the matched parameters.
|
||||
This list is not clear. */
|
||||
void FindSemantic(const char* semantic, FCDEffectParameterList& list);
|
||||
inline void FindSemantic(const string& semantic, FCDEffectParameterList& list) { return FindReference(semantic.c_str(), list); } /**< See above. */
|
||||
|
||||
/** Creates a full copy of the list of parameters and its content.
|
||||
@return The cloned list. You will need to delete this pointer.*/
|
||||
FCDEffectParameterList* Clone() const;
|
||||
};
|
||||
|
||||
#endif // _FCD_EFFECT_PARAMETER_LIST_H_
|
||||
@@ -1,589 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 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/FCDEffectPass.h"
|
||||
#include "FCDocument/FCDEffectProfile.h"
|
||||
#include "FCDocument/FCDEffectTechnique.h"
|
||||
#include "FCDocument/FCDEffectParameter.h"
|
||||
#include "FCDocument/FCDEffectParameterSurface.h"
|
||||
#include "FCDocument/FCDImage.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
// surface type parameter
|
||||
FCDEffectParameterSurface::FCDEffectParameterSurface(FCDocument* document) : FCDEffectParameter(document)
|
||||
{
|
||||
initMethod = NULL;
|
||||
}
|
||||
|
||||
FCDEffectParameterSurface::~FCDEffectParameterSurface()
|
||||
{
|
||||
SAFE_DELETE(initMethod);
|
||||
names.clear();
|
||||
images.clear();
|
||||
}
|
||||
|
||||
void FCDEffectParameterSurface::SetInitMethod(FCDEffectParameterSurfaceInit* method)
|
||||
{
|
||||
SAFE_DELETE(initMethod);
|
||||
initMethod = method;
|
||||
}
|
||||
|
||||
// Retrieves the index that matches the given image.
|
||||
size_t FCDEffectParameterSurface::FindImage(const FCDImage* image) const
|
||||
{
|
||||
FCDImageList::const_iterator it = std::find(images.begin(), images.end(), image);
|
||||
if (it != images.end())
|
||||
{
|
||||
return it - images.begin();
|
||||
}
|
||||
else return (size_t) -1;
|
||||
}
|
||||
|
||||
// Adds an image to the list.
|
||||
size_t FCDEffectParameterSurface::AddImage(FCDImage* image)
|
||||
{
|
||||
size_t index = FindImage(image);
|
||||
if (index == (size_t) -1)
|
||||
{
|
||||
index = images.size();
|
||||
images.push_back(image);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
// Removes an image from the list.
|
||||
void FCDEffectParameterSurface::RemoveImage(FCDImage* image)
|
||||
{
|
||||
size_t index = FindImage(image);
|
||||
if (index != (size_t) -1)
|
||||
{
|
||||
images.erase(images.begin() + index);
|
||||
|
||||
if (initMethod != NULL && initMethod->GetInitType() == FCDEffectParameterSurfaceInitFactory::CUBE)
|
||||
{
|
||||
// Shift down all the indexes found within the cube map initialization.
|
||||
FCDEffectParameterSurfaceInitCube* cube = (FCDEffectParameterSurfaceInitCube*) initMethod;
|
||||
for (UInt16List::iterator itI = cube->order.begin(); itI != cube->order.end(); ++itI)
|
||||
{
|
||||
if ((*itI) == index) (*itI) = 0;
|
||||
else if ((*itI) > index) --(*itI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clone
|
||||
FCDEffectParameter* FCDEffectParameterSurface::Clone()
|
||||
{
|
||||
FCDEffectParameterSurface* clone = new FCDEffectParameterSurface(GetDocument());
|
||||
FCDEffectParameter::Clone(clone);
|
||||
clone->images.clear();
|
||||
for(uint32 i=0; i<images.size(); i++)
|
||||
clone->images.push_back(images[i]);
|
||||
clone->names.clear();
|
||||
for(uint32 i=0; i<names.size(); i++)
|
||||
clone->names.push_back(names[i]);
|
||||
|
||||
if(initMethod)
|
||||
clone->initMethod = initMethod->Clone();
|
||||
|
||||
clone->size = size;
|
||||
clone->viewportRatio = viewportRatio;
|
||||
clone->mipLevelCount = mipLevelCount;
|
||||
clone->generateMipmaps = generateMipmaps;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Flattening: overwrite the target parameter with this parameter
|
||||
void FCDEffectParameterSurface::Overwrite(FCDEffectParameter* target)
|
||||
{
|
||||
if (target->GetType() == SURFACE)
|
||||
{
|
||||
FCDEffectParameterSurface* s = (FCDEffectParameterSurface*) target;
|
||||
s->images.clear();
|
||||
for(uint32 i=0; i<images.size(); i++)
|
||||
s->images.push_back(images[i]);
|
||||
s->names.clear();
|
||||
for(uint32 i=0; i<names.size(); i++)
|
||||
s->names.push_back(names[i]);
|
||||
|
||||
// s->initMethod->initType = initMethod->GetInitType();
|
||||
s->size = size;
|
||||
s->viewportRatio = viewportRatio;
|
||||
s->mipLevelCount = mipLevelCount;
|
||||
s->generateMipmaps = generateMipmaps;
|
||||
}
|
||||
}
|
||||
|
||||
FUStatus FCDEffectParameterSurface::LoadFromXML(xmlNode* parameterNode)
|
||||
{
|
||||
FUStatus status = FCDEffectParameter::LoadFromXML(parameterNode);
|
||||
xmlNode* surfaceNode = FindChildByType(parameterNode, DAE_FXCMN_SURFACE_ELEMENT);
|
||||
|
||||
bool initialized = false;
|
||||
xmlNode* valueNode = NULL;
|
||||
//The surface can now contain many init_from elements (1.4.1)
|
||||
xmlNodeList valueNodes;
|
||||
FindChildrenByType(surfaceNode, DAE_INITFROM_ELEMENT, valueNodes);
|
||||
for (xmlNodeList::iterator it = valueNodes.begin(); it != valueNodes.end(); ++it)
|
||||
{
|
||||
initialized = true;
|
||||
if(!initMethod)
|
||||
initMethod = new FCDEffectParameterSurfaceInitFrom();
|
||||
|
||||
FCDEffectParameterSurfaceInitFrom* ptrInit = (FCDEffectParameterSurfaceInitFrom*)initMethod;
|
||||
StringList tempNames;
|
||||
FUStringConversion::ToStringList(ReadNodeContentDirect(*it), tempNames);
|
||||
|
||||
if (tempNames.size() == 0 || tempNames[0].empty())
|
||||
{
|
||||
return status.Fail(FS("<init_from> element is empty in surface parameter: ") + TO_FSTRING(GetReference()), parameterNode->line);
|
||||
}
|
||||
|
||||
if(tempNames.size() == 1) //might be 1.4.1, so allow the attributes mip, slice, face
|
||||
{
|
||||
if(HasNodeProperty(*it, DAE_MIP_ATTRIBUTE))
|
||||
{
|
||||
string mip = ReadNodeProperty(*it, DAE_MIP_ATTRIBUTE);
|
||||
ptrInit->mip.push_back(mip);
|
||||
}
|
||||
if(HasNodeProperty(*it, DAE_SLICE_ATTRIBUTE))
|
||||
{
|
||||
string slice = ReadNodeProperty(*it, DAE_SLICE_ATTRIBUTE);
|
||||
ptrInit->slice.push_back(slice);
|
||||
}
|
||||
if(HasNodeProperty(*it, DAE_FACE_ATTRIBUTE))
|
||||
{
|
||||
string face = ReadNodeProperty(*it, DAE_FACE_ATTRIBUTE);
|
||||
ptrInit->face.push_back(face);
|
||||
}
|
||||
}
|
||||
|
||||
//go through the new names, get their images, and add update the image and name lists
|
||||
for(uint32 i=0; i<tempNames.size(); i++)
|
||||
{
|
||||
names.push_back(tempNames[i]);
|
||||
FCDImage* image = GetDocument()->FindImage(tempNames[i]);
|
||||
if (image != NULL)
|
||||
{
|
||||
images.push_back(image);
|
||||
|
||||
}
|
||||
//else return status.Fail(FS("Unable to find image source for surface parameter: ") + TO_FSTRING(GetReference()), parameterNode->line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Check if it's initialized AS NULL
|
||||
if(!initialized)
|
||||
{
|
||||
valueNode = FindChildByType(surfaceNode, DAE_INITASNULL_ELEMENT);
|
||||
if(valueNode)
|
||||
{
|
||||
initialized = true;
|
||||
initMethod = FCDEffectParameterSurfaceInitFactory::Create(FCDEffectParameterSurfaceInitFactory::AS_NULL);
|
||||
}
|
||||
}
|
||||
//Check if it's initialized AS TARGET
|
||||
if(!initialized)
|
||||
{
|
||||
valueNode = FindChildByType(surfaceNode, DAE_INITASTARGET_ELEMENT);
|
||||
if(valueNode)
|
||||
{
|
||||
initialized = true;
|
||||
initMethod = FCDEffectParameterSurfaceInitFactory::Create(FCDEffectParameterSurfaceInitFactory::AS_TARGET);
|
||||
}
|
||||
}
|
||||
//Check if it's initialized AS CUBE
|
||||
if(!initialized)
|
||||
{
|
||||
valueNode = FindChildByType(surfaceNode, DAE_INITCUBE_ELEMENT);
|
||||
if(valueNode)
|
||||
{
|
||||
initialized = true;
|
||||
initMethod = FCDEffectParameterSurfaceInitFactory::Create(FCDEffectParameterSurfaceInitFactory::CUBE);
|
||||
FCDEffectParameterSurfaceInitCube* ptrInit = (FCDEffectParameterSurfaceInitCube*) initMethod;
|
||||
|
||||
//Check if it's an ALL reference
|
||||
xmlNode* refNode = FindChildByType(valueNode, DAE_ALL_ELEMENT);
|
||||
if(refNode)
|
||||
{
|
||||
ptrInit->cubeType = FCDEffectParameterSurfaceInitCube::ALL;
|
||||
string name = ReadNodeProperty(refNode, DAE_REF_ATTRIBUTE);
|
||||
if (name.empty())
|
||||
{
|
||||
return status.Fail(FS("<init_cube>'s all reference is empty in surface parameter: ") + TO_FSTRING(GetReference()), surfaceNode->line);
|
||||
}
|
||||
names.push_back(name);
|
||||
|
||||
FCDImage* image = GetDocument()->FindImage(name);
|
||||
if (image == NULL)
|
||||
{
|
||||
return status.Fail(FS("Unable to find image source for surface parameter: ") + TO_FSTRING(GetReference()), surfaceNode->line);
|
||||
}
|
||||
images.push_back(image);
|
||||
}
|
||||
|
||||
//Check if it's a PRIMARY reference
|
||||
if(!refNode)
|
||||
{
|
||||
refNode = FindChildByType(valueNode, DAE_PRIMARY_ELEMENT);
|
||||
if(refNode)
|
||||
{
|
||||
ptrInit->cubeType = FCDEffectParameterSurfaceInitCube::PRIMARY;
|
||||
string name = ReadNodeProperty(refNode, DAE_REF_ATTRIBUTE);
|
||||
if (name.empty())
|
||||
{
|
||||
return status.Fail(FS("<init_cube>'s primary reference is empty in surface parameter: ") + TO_FSTRING(GetReference()), valueNode->line);
|
||||
}
|
||||
names.push_back(name);
|
||||
|
||||
FCDImage* image = GetDocument()->FindImage(name);
|
||||
if (image == NULL)
|
||||
{
|
||||
return status.Fail(FS("Unable to find image source for surface parameter: ") + TO_FSTRING(GetReference()), valueNode->line);
|
||||
}
|
||||
images.push_back(image);
|
||||
|
||||
xmlNode* orderNode = FindChildByType(refNode, DAE_ORDER_ELEMENT);
|
||||
if(orderNode)
|
||||
{
|
||||
//FIXME: complete when the spec has more info
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Check if it's a FACE reference
|
||||
if(!refNode)
|
||||
{
|
||||
xmlNodeList faceNodes;
|
||||
FindChildrenByType(valueNode, DAE_FACE_ELEMENT, faceNodes);
|
||||
if(faceNodes.size()==6)
|
||||
{
|
||||
ptrInit->cubeType = FCDEffectParameterSurfaceInitCube::FACE;
|
||||
for(uint8 ii=0; ii<faceNodes.size(); ii++)
|
||||
{
|
||||
string valueName = ReadNodeProperty(faceNodes[ii], DAE_REF_ATTRIBUTE);
|
||||
if (valueName.empty())
|
||||
{
|
||||
return status.Fail(FS("<init_cube>'s face reference is empty in surface parameter: ") + TO_FSTRING(GetReference()), refNode->line);
|
||||
}
|
||||
names.push_back(valueName);
|
||||
FCDImage* image = GetDocument()->FindImage(valueName);
|
||||
|
||||
if (image == NULL)
|
||||
{
|
||||
return status.Fail(FS("Unable to find image source for surface parameter: ") + TO_FSTRING(GetReference()), refNode->line);
|
||||
}
|
||||
images.push_back(image);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Check if it's initialized AS VOLUME
|
||||
if(!initialized)
|
||||
{
|
||||
valueNode = FindChildByType(surfaceNode, DAE_INITVOLUME_ELEMENT);
|
||||
if(valueNode)
|
||||
{
|
||||
initialized = true;
|
||||
initMethod = FCDEffectParameterSurfaceInitFactory::Create(FCDEffectParameterSurfaceInitFactory::VOLUME);
|
||||
FCDEffectParameterSurfaceInitVolume* ptrInit = (FCDEffectParameterSurfaceInitVolume*) initMethod;
|
||||
|
||||
//Check if it's an ALL reference
|
||||
xmlNode* refNode = FindChildByType(valueNode, DAE_ALL_ELEMENT);
|
||||
if(refNode)
|
||||
{
|
||||
ptrInit->volumeType = FCDEffectParameterSurfaceInitVolume::ALL;
|
||||
string name = ReadNodeProperty(refNode, DAE_REF_ATTRIBUTE);
|
||||
if (name.empty())
|
||||
{
|
||||
return status.Fail(FS("<init_cube>'s all reference is empty in surface parameter: ") + TO_FSTRING(GetReference()), refNode->line);
|
||||
}
|
||||
names.push_back(name);
|
||||
|
||||
FCDImage* image = GetDocument()->FindImage(name);
|
||||
if (image == NULL)
|
||||
{
|
||||
return status.Fail(FS("Unable to find image source for surface parameter: ") + TO_FSTRING(GetReference()), refNode->line);
|
||||
}
|
||||
images.push_back(image);
|
||||
}
|
||||
|
||||
//Check if it's a PRIMARY reference
|
||||
if(!refNode)
|
||||
{
|
||||
refNode = FindChildByType(valueNode, DAE_PRIMARY_ELEMENT);
|
||||
if(refNode)
|
||||
{
|
||||
ptrInit->volumeType = FCDEffectParameterSurfaceInitVolume::PRIMARY;
|
||||
string name = ReadNodeProperty(refNode, DAE_REF_ATTRIBUTE);
|
||||
if (name.empty())
|
||||
{
|
||||
return status.Fail(FS("<init_cube>'s primary reference is empty in surface parameter: ") + TO_FSTRING(GetReference()), valueNode->line);
|
||||
}
|
||||
names.push_back(name);
|
||||
|
||||
FCDImage* image = GetDocument()->FindImage(name);
|
||||
if (image == NULL)
|
||||
{
|
||||
return status.Fail(FS("Unable to find image source for surface parameter: ") + TO_FSTRING(GetReference()), valueNode->line);
|
||||
}
|
||||
images.push_back(image);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Check if it's initialized as PLANAR
|
||||
if(!initialized)
|
||||
{
|
||||
valueNode = FindChildByType(surfaceNode, DAE_INITPLANAR_ELEMENT);
|
||||
if(valueNode)
|
||||
{
|
||||
initialized = true;
|
||||
initMethod = FCDEffectParameterSurfaceInitFactory::Create(FCDEffectParameterSurfaceInitFactory::PLANAR);
|
||||
|
||||
//Check if it's an ALL reference
|
||||
xmlNode* refNode = FindChildByType(valueNode, DAE_ALL_ELEMENT);
|
||||
if(refNode)
|
||||
{
|
||||
string name = ReadNodeProperty(refNode, DAE_REF_ATTRIBUTE);
|
||||
if (name.empty())
|
||||
{
|
||||
return status.Fail(FS("<init_planar>'s all reference is empty in surface parameter: ") + TO_FSTRING(GetReference()), refNode->line);
|
||||
}
|
||||
names.push_back(name);
|
||||
|
||||
FCDImage* image = GetDocument()->FindImage(name);
|
||||
if (image == NULL)
|
||||
{
|
||||
return status.Fail(FS("Unable to find image source for surface parameter: ") + TO_FSTRING(GetReference()), refNode->line);
|
||||
}
|
||||
images.push_back(image);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// It is acceptable for a surface not to have an initialization option
|
||||
//but we should flag a warning
|
||||
if(!initialized)
|
||||
{
|
||||
DebugOut("Warning: surface %s not initialized", GetReference().c_str());
|
||||
}
|
||||
|
||||
xmlNode* sizeNode = FindChildByType(parameterNode, DAE_SIZE_ELEMENT);
|
||||
size = FUStringConversion::ToPoint(ReadNodeContentDirect(sizeNode));
|
||||
xmlNode* viewportRatioNode = FindChildByType(parameterNode, DAE_VIEWPORT_RATIO);
|
||||
viewportRatio = FUStringConversion::ToFloat(ReadNodeContentDirect(viewportRatioNode));
|
||||
xmlNode* mipLevelsNode = FindChildByType(parameterNode, DAE_MIP_LEVELS);
|
||||
mipLevelCount = (uint16) FUStringConversion::ToInt32(ReadNodeContentDirect(mipLevelsNode));
|
||||
xmlNode* mipmapGenerateNode = FindChildByType(parameterNode, DAE_MIPMAP_GENERATE);
|
||||
generateMipmaps = FUStringConversion::ToBoolean(ReadNodeContentDirect(mipmapGenerateNode));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
xmlNode* FCDEffectParameterSurface::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* parameterNode = FCDEffectParameter::WriteToXML(parentNode);
|
||||
xmlNode* surfaceNode = AddChild(parameterNode, DAE_FXCMN_SURFACE_ELEMENT);
|
||||
if (!images.empty() && initMethod != NULL)
|
||||
{
|
||||
switch (initMethod->GetInitType())
|
||||
{
|
||||
case FCDEffectParameterSurfaceInitFactory::FROM:
|
||||
{
|
||||
//Since 1.4.1, there are two possibilities here.
|
||||
//Possibility 1
|
||||
//<init_from> image1 image2...imageN </init_from>
|
||||
|
||||
//Possibility 2
|
||||
//<init_from mip=... face=... slice=...> image1 </init_from>
|
||||
//<init_from mip=... face=... slice=...> image2 </init_from>
|
||||
|
||||
FCDEffectParameterSurfaceInitFrom* in = (FCDEffectParameterSurfaceInitFrom*)initMethod;
|
||||
size_t size = images.size(); //images.size() should always be equal to names.size()
|
||||
|
||||
if( size == in->face.size() || size == in->mip.size() || size == in->slice.size())
|
||||
{
|
||||
//This is possibility 2
|
||||
for(uint32 i=0; i<size; i++)
|
||||
{
|
||||
xmlNode* childNode = AddChild(surfaceNode, DAE_INITFROM_ELEMENT, images[i]->GetDaeId());
|
||||
AddAttribute(childNode, DAE_MIP_ATTRIBUTE, in->mip[i]);
|
||||
AddAttribute(childNode, DAE_SLICE_ATTRIBUTE, in->slice[i]);
|
||||
AddAttribute(childNode, DAE_FACE_ATTRIBUTE, in->face[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//This is possibility 1
|
||||
globalSBuilder.reserve(size * 18); // Pulled out of a hat
|
||||
StringList::const_iterator itV = names.begin();
|
||||
globalSBuilder.set(*itV);
|
||||
for (++itV; itV != names.end(); ++itV)
|
||||
{
|
||||
globalSBuilder.append(' ');
|
||||
globalSBuilder.append(*itV);
|
||||
}
|
||||
|
||||
xmlNode* childNode = AddChild(surfaceNode, DAE_INITFROM_ELEMENT);
|
||||
AddContent(childNode, globalSBuilder.ToString());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FCDEffectParameterSurfaceInitFactory::AS_NULL:
|
||||
{
|
||||
AddChild(surfaceNode, DAE_INITASNULL_ELEMENT);
|
||||
break;
|
||||
}
|
||||
case FCDEffectParameterSurfaceInitFactory::AS_TARGET:
|
||||
{
|
||||
AddChild(surfaceNode, DAE_INITASTARGET_ELEMENT);
|
||||
break;
|
||||
}
|
||||
case FCDEffectParameterSurfaceInitFactory::VOLUME:
|
||||
{
|
||||
FCDEffectParameterSurfaceInitVolume* in = (FCDEffectParameterSurfaceInitVolume*)initMethod;
|
||||
xmlNode* childNode = AddChild(surfaceNode, DAE_INITVOLUME_ELEMENT);
|
||||
if(in->volumeType == FCDEffectParameterSurfaceInitVolume::ALL)
|
||||
{
|
||||
xmlNode* typeNode = AddChild(childNode, DAE_ALL_ELEMENT);
|
||||
AddAttribute(typeNode, DAE_REF_ATTRIBUTE, names[0]);
|
||||
}
|
||||
else if(in->volumeType == FCDEffectParameterSurfaceInitVolume::PRIMARY)
|
||||
{
|
||||
xmlNode* typeNode = AddChild(childNode, DAE_PRIMARY_ELEMENT);
|
||||
AddAttribute(typeNode, DAE_REF_ATTRIBUTE, names[0]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FCDEffectParameterSurfaceInitFactory::CUBE:
|
||||
{
|
||||
FCDEffectParameterSurfaceInitCube* in = (FCDEffectParameterSurfaceInitCube*)initMethod;
|
||||
xmlNode* childNode = AddChild(surfaceNode, DAE_INITCUBE_ELEMENT);
|
||||
if(in->cubeType == FCDEffectParameterSurfaceInitCube::ALL)
|
||||
{
|
||||
xmlNode* typeNode = AddChild(childNode, DAE_ALL_ELEMENT);
|
||||
AddAttribute(typeNode, DAE_REF_ATTRIBUTE, names[0]);
|
||||
}
|
||||
else if(in->cubeType == FCDEffectParameterSurfaceInitCube::PRIMARY)
|
||||
{
|
||||
xmlNode* typeNode = AddChild(childNode, DAE_PRIMARY_ELEMENT);
|
||||
AddChild(typeNode, DAE_ORDER_ELEMENT); //FIXME: complete when the spec gets more info.
|
||||
AddAttribute(typeNode, DAE_REF_ATTRIBUTE, names[0]);
|
||||
}
|
||||
if(in->cubeType == FCDEffectParameterSurfaceInitCube::FACE)
|
||||
{
|
||||
xmlNode* childNode = AddChild(surfaceNode, DAE_FACE_ELEMENT);
|
||||
AddAttribute(childNode, DAE_REF_ATTRIBUTE, names[0]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FCDEffectParameterSurfaceInitFactory::PLANAR:
|
||||
{
|
||||
xmlNode* childNode = AddChild(surfaceNode, DAE_INITPLANAR_ELEMENT);
|
||||
xmlNode* typeNode = AddChild(childNode, DAE_ALL_ELEMENT);
|
||||
AddAttribute(typeNode, DAE_REF_ATTRIBUTE, names[0]);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return parameterNode;
|
||||
}
|
||||
|
||||
|
||||
void FCDEffectParameterSurfaceInit::Clone(FCDEffectParameterSurfaceInit* UNUSED(clone))
|
||||
{
|
||||
//no member variables to copy in this class, but leave this for future use.
|
||||
}
|
||||
|
||||
FCDEffectParameterSurfaceInitCube::FCDEffectParameterSurfaceInitCube()
|
||||
{
|
||||
cubeType = ALL;
|
||||
}
|
||||
|
||||
FCDEffectParameterSurfaceInit* FCDEffectParameterSurfaceInitCube::Clone()
|
||||
{
|
||||
FCDEffectParameterSurfaceInitCube* clone = new FCDEffectParameterSurfaceInitCube();
|
||||
FCDEffectParameterSurfaceInit::Clone(clone);
|
||||
clone->cubeType = cubeType;
|
||||
return clone;
|
||||
}
|
||||
|
||||
FCDEffectParameterSurfaceInit* FCDEffectParameterSurfaceInitFrom::Clone()
|
||||
{
|
||||
FCDEffectParameterSurfaceInitFrom* clone = new FCDEffectParameterSurfaceInitFrom();
|
||||
FCDEffectParameterSurfaceInit::Clone(clone);
|
||||
clone->face = face;
|
||||
clone->mip = mip;
|
||||
clone->slice = slice;
|
||||
return clone;
|
||||
}
|
||||
|
||||
FCDEffectParameterSurfaceInitVolume::FCDEffectParameterSurfaceInitVolume()
|
||||
{
|
||||
volumeType = ALL;
|
||||
}
|
||||
|
||||
FCDEffectParameterSurfaceInit* FCDEffectParameterSurfaceInitVolume::Clone()
|
||||
{
|
||||
FCDEffectParameterSurfaceInitVolume* clone = new FCDEffectParameterSurfaceInitVolume();
|
||||
FCDEffectParameterSurfaceInit::Clone(clone);
|
||||
clone->volumeType = volumeType;
|
||||
return clone;
|
||||
}
|
||||
|
||||
FCDEffectParameterSurfaceInit* FCDEffectParameterSurfaceInitAsNull::Clone()
|
||||
{
|
||||
FCDEffectParameterSurfaceInitAsNull* clone = new FCDEffectParameterSurfaceInitAsNull();
|
||||
FCDEffectParameterSurfaceInit::Clone(clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
FCDEffectParameterSurfaceInit* FCDEffectParameterSurfaceInitAsTarget::Clone()
|
||||
{
|
||||
FCDEffectParameterSurfaceInitAsTarget* clone = new FCDEffectParameterSurfaceInitAsTarget();
|
||||
FCDEffectParameterSurfaceInit::Clone(clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
FCDEffectParameterSurfaceInit* FCDEffectParameterSurfaceInitPlanar::Clone()
|
||||
{
|
||||
FCDEffectParameterSurfaceInitPlanar* clone = new FCDEffectParameterSurfaceInitPlanar();
|
||||
FCDEffectParameterSurfaceInit::Clone(clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
FCDEffectParameterSurfaceInit* FCDEffectParameterSurfaceInitFactory::Create(InitType type)
|
||||
{
|
||||
FCDEffectParameterSurfaceInit* parameter = NULL;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FCDEffectParameterSurfaceInitFactory::AS_NULL: parameter = new FCDEffectParameterSurfaceInitAsNull(); break;
|
||||
case FCDEffectParameterSurfaceInitFactory::AS_TARGET: parameter = new FCDEffectParameterSurfaceInitAsTarget(); break;
|
||||
case FCDEffectParameterSurfaceInitFactory::CUBE: parameter = new FCDEffectParameterSurfaceInitCube(); break;
|
||||
case FCDEffectParameterSurfaceInitFactory::FROM: parameter = new FCDEffectParameterSurfaceInitFrom(); break;
|
||||
case FCDEffectParameterSurfaceInitFactory::PLANAR: parameter = new FCDEffectParameterSurfaceInitPlanar(); break;
|
||||
case FCDEffectParameterSurfaceInitFactory::VOLUME: parameter = new FCDEffectParameterSurfaceInitVolume(); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return parameter;
|
||||
}
|
||||
@@ -1,435 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDEffectParameterSurface.h
|
||||
This file contains the FCDEffectParameterSurface class,
|
||||
the FCDEffectParameterSurfaceInit interface and its derivate classes.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_EFFECT_PARAMETER_SURFACE_H_
|
||||
#define _FCD_EFFECT_PARAMETER_SURFACE_H_
|
||||
|
||||
#include "FCDocument/FCDEffectParameter.h"
|
||||
|
||||
class FCDEffectParameterSurfaceInit;
|
||||
|
||||
/** A dynamically-sized array of COLLADA images */
|
||||
typedef std::vector<FCDImage*> FCDImageList;
|
||||
|
||||
/**
|
||||
A COLLADA surface parameter.
|
||||
This parameters hold the texture loading information. The texture
|
||||
placement information should be held by the sampler parameter.
|
||||
|
||||
@see FCDEffectParameterSampler
|
||||
|
||||
@ingroup FCDEffect
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterSurface : public FCDEffectParameter
|
||||
{
|
||||
private:
|
||||
StringList names;
|
||||
FCDImageList images;
|
||||
FCDEffectParameterSurfaceInit* initMethod;
|
||||
FMVector3 size;
|
||||
float viewportRatio;
|
||||
uint16 mipLevelCount;
|
||||
bool generateMipmaps;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::AddParameter function.
|
||||
@param document The COLLADA document that owns the effect parameter. */
|
||||
FCDEffectParameterSurface(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDEffectParameterList::ReleaseParameter function.
|
||||
When released, the effect parameter list will also release all
|
||||
its parameters, if it owns them. */
|
||||
virtual ~FCDEffectParameterSurface();
|
||||
|
||||
/** Retrieves the type of effect parameter class.
|
||||
@return The parameter class type: SURFACE. */
|
||||
virtual Type GetType() const { return SURFACE; }
|
||||
|
||||
/** Retrieves the initialization method for the surface parameter.
|
||||
The initialization method is a powerful method of describing how
|
||||
to build complex textures, such as cube maps, from one or
|
||||
multiple image files.
|
||||
@return The surface initialization method. This pointer will be NULL,
|
||||
if no initialization method is provided. */
|
||||
FCDEffectParameterSurfaceInit* GetInitMethod() { return initMethod; }
|
||||
const FCDEffectParameterSurfaceInit* GetInitMethod() const { return initMethod; } /**< See above. */
|
||||
|
||||
/** Sets the initialization method for the surface parameter.
|
||||
The initialization method is a powerful method of describing how
|
||||
to build complex textures, such as cube maps, from one or
|
||||
multiple image files.
|
||||
@param method The new initialization method.
|
||||
The old initialization method will be released.
|
||||
You should create a new initialization method
|
||||
for each surface parameter. */
|
||||
void SetInitMethod(FCDEffectParameterSurfaceInit* method);
|
||||
|
||||
/** Retrieves the number of COLLADA images that make up this surface.
|
||||
There should never be more than six images to build a surface.
|
||||
In the large majority of cases, expect one image.
|
||||
@return The number of images. */
|
||||
size_t GetImageCount() const { return images.size(); }
|
||||
|
||||
/** Retrieves the list of images that make up this surface.
|
||||
There should never be more than six images to build a surface.
|
||||
In the large majority of cases, expect one image.
|
||||
@return The list of images. */
|
||||
FCDImageList& GetImages() { return images; }
|
||||
const FCDImageList& GetImages() const { return images; } /**< See above. */
|
||||
|
||||
/** Retrieves a specific image.
|
||||
@param index The index of the image.
|
||||
@return The image. This pointer will be NULL if the index is out-of-bounds. */
|
||||
FCDImage* GetImage(size_t index = 0) { return index < images.size() ? images.at(index) : NULL; }
|
||||
const FCDImage* GetImage(size_t index = 0) const { return index < images.size() ? images.at(index) : NULL; } /**< See above. */
|
||||
|
||||
/** Retrieves the index that matches the given image.
|
||||
@param image The image to match.
|
||||
@return The index within the list for this image.
|
||||
This index may be -1 if no match was found. */
|
||||
size_t FindImage(const FCDImage* image) const;
|
||||
|
||||
/** Adds an image to the list.
|
||||
The initialization method indexes the images from this list.
|
||||
This function will verify that this image does not already exist within the list,
|
||||
so use the returned index.
|
||||
@param image The new image.
|
||||
@return The index of the image within the list. */
|
||||
size_t AddImage(FCDImage* image);
|
||||
|
||||
/** Removes an image from the list.
|
||||
The initialization method indexes the images from this list.
|
||||
This function will shift all the indexes in the initialization method
|
||||
so that they continue matching the correct image.
|
||||
@param image The image to remove. Its memory is not released. */
|
||||
void RemoveImage(FCDImage* image);
|
||||
|
||||
/** Retrieves the wanted dimensions of the surface.
|
||||
This parameter is optional and may contain all zeroes to indicate
|
||||
that you should read the surface dimensions from the image file(s).
|
||||
@return The wanted dimensions. */
|
||||
const FMVector3& GetSize() const { return size; }
|
||||
|
||||
/** Sets the wanted dimensions of the surface.
|
||||
This parameter is optional and can contain all zeroes to indicate
|
||||
that you should read the surface dimensions from the image file(s).
|
||||
@param dimensions The wanted dimensions. */
|
||||
void SetSize(const FMVector3& dimensions) { size = dimensions; }
|
||||
|
||||
/** Retrieves the viewport ratio to use when the surface is a render target.
|
||||
@return The viewport ratio. */
|
||||
float GetViewportRatio() const { return viewportRatio; }
|
||||
|
||||
/** Sets the viewport ratio to use when the surface is a render target.
|
||||
@param ratio The viewport ratio. */
|
||||
void SetViewportRatio(float ratio) { viewportRatio = ratio; }
|
||||
|
||||
/** Retrieves the wanted number of mip-levels.
|
||||
This parameter is optional and may be zero to indicate that you should
|
||||
retrieve the mip-levels from the image file(s) or generate a full
|
||||
mip-chain, depending on the mip-map generate flag.
|
||||
@see GetMipMapGenerate
|
||||
@return The wanted number of mip-levels. */
|
||||
uint16 GetMipLevelCount() const { return mipLevelCount; }
|
||||
|
||||
/** Sets the wanted number of mip-levels.
|
||||
This parameter is optional and can be zero to indicate that you should
|
||||
retrieve the mip-levels from the image file(s) or generate a full
|
||||
mip-chain, depending on the mip-map generate flag.
|
||||
@param levelCount The wanted number of mip-levels. */
|
||||
void SetMipLevelCount(uint16 levelCount) { mipLevelCount = levelCount; }
|
||||
|
||||
/** Retrieves whether to generate the mip-map levels on load.
|
||||
The alternative is to load the mip-map levels from the image files.
|
||||
@return Whether to generate the mip-map levels on load. */
|
||||
bool IsGenerateMipMaps() const { return generateMipmaps; }
|
||||
|
||||
/** Sets whether to generate the mip-map levels of load.
|
||||
The alternative is to load the mip-map levels from the image files.
|
||||
@param _generateMipmaps Whether to generate the mip-map levels on load. */
|
||||
void SetGenerateMipMaps(bool _generateMipmaps) { generateMipmaps = _generateMipmaps; }
|
||||
|
||||
/** Retrieves a specific sub-id.
|
||||
@todo I'm not too sure of the implications of the names,
|
||||
at this level of abstraction: once I'm clear why they exists, add the
|
||||
necessary interface to access/pull/push items from/to the list.
|
||||
@param index The sub-id index.
|
||||
@return The sub-id. This pointer will be NULL if the index is out-of-bounds. */
|
||||
const char* GetName(size_t index = 0) const { return (index < names.size()) ? names[index].c_str() : NULL; }
|
||||
|
||||
/** Creates a full copy of the effect parameter.
|
||||
@todo The cloning does not clone the initialization method correctly.
|
||||
@return The cloned effect parameter. You will need to delete this pointer. */
|
||||
virtual FCDEffectParameter* Clone();
|
||||
|
||||
/** [INTERNAL] Overwrites the target parameter with this parameter.
|
||||
This function is used during the flattening of materials.
|
||||
@param target The target parameter to overwrite. */
|
||||
virtual void Overwrite(FCDEffectParameter* target);
|
||||
|
||||
/** [INTERNAL] Reads in the effect parameter from a given COLLADA XML tree node.
|
||||
@param parameterNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the parameter.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* parameterNode);
|
||||
|
||||
/** [INTERNAL] Writes out the effect parameter to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the parameter.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
[INTERNAL] The factory for COLLADA effect parameter surface initialization.
|
||||
|
||||
@ingroup FCDEffect
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterSurfaceInitFactory
|
||||
{
|
||||
private:
|
||||
// Never instantiate: this is a static class
|
||||
FCDEffectParameterSurfaceInitFactory() {}
|
||||
|
||||
public:
|
||||
|
||||
/** The supported initialization types. */
|
||||
enum InitType
|
||||
{
|
||||
FROM, /**< Loads a surface from one simple image file. @see FCDEffectParameterSurfaceInitFrom */
|
||||
AS_NULL, /**< No initialization. This surface may be initialized by some future effect parameter override. */
|
||||
AS_TARGET, /**< Initializes an engine-specific render target for offscreen rendering. In this case, the dimensions should be provided by the surface effect parameter. */
|
||||
CUBE, /**< Loads a cube-map from one complex image file or six simple image files. @see FCDEffectParameterSurfaceInitCube */
|
||||
VOLUME, /**< Loads a 3D images for one image file. @see FCDEffectParameterSurfaceInitVolume */
|
||||
PLANAR /**< Loads a surface from one simple image file. */
|
||||
};
|
||||
|
||||
/** [INTERNAL] Creates a new effect surface initialization parameter, given a type.
|
||||
@param type The type of initialization parameter to create.*/
|
||||
static FCDEffectParameterSurfaceInit* Create(InitType type);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
A surface initialization method.
|
||||
In COLLADA 1.4.1, this information was added to support complex surface types.
|
||||
There are six types of initialization methods, described in the InitType enumerated type.
|
||||
Expect the FROM initialization type in the large majority of cases.
|
||||
|
||||
@ingroup FCDEffect
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterSurfaceInit
|
||||
{
|
||||
public:
|
||||
|
||||
/** Constructor: builds a new surface initialization method. */
|
||||
FCDEffectParameterSurfaceInit() {}
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~FCDEffectParameterSurfaceInit() {}
|
||||
|
||||
/** Retrieves the initialization type. You cannot modify this value.
|
||||
To change the initialization type of a surface parameter, create a new
|
||||
surface initialization structure of the correct type.
|
||||
@return The initialization type. */
|
||||
virtual FCDEffectParameterSurfaceInitFactory::InitType GetInitType() const = 0;
|
||||
|
||||
/** Copies all member variables into clone.
|
||||
@param clone a valid pointer to a FCDEffectParameterSurfaceInit object*/
|
||||
void Clone(FCDEffectParameterSurfaceInit* clone);
|
||||
|
||||
/** Creates a full copy of the surface initialization parameter.
|
||||
@return The surface initialization parameter. You will need to delete this pointer. */
|
||||
virtual FCDEffectParameterSurfaceInit* Clone() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
A cube-map surface initialization method.
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterSurfaceInitCube : public FCDEffectParameterSurfaceInit
|
||||
{
|
||||
public:
|
||||
/** The types of cube-map initializations. */
|
||||
enum CubeType
|
||||
{
|
||||
ALL, /** Load all the mip-levels of all the cube-map faces from one image file. */
|
||||
PRIMARY, /** Load the first mip-level of all the cube-map faces from one image file. */
|
||||
FACE /** Load all the cube-map faces from separate image files. */
|
||||
};
|
||||
|
||||
public:
|
||||
/** Constructor: builds a new cube-map initialization method. */
|
||||
FCDEffectParameterSurfaceInitCube();
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~FCDEffectParameterSurfaceInitCube() {}
|
||||
|
||||
/** Retrieves the initialization type. You cannot modify this value.
|
||||
To change the initialization type of a surface parameter, create a new
|
||||
surface initialization structure of the correct type.
|
||||
@return The initialization type. */
|
||||
virtual FCDEffectParameterSurfaceInitFactory::InitType GetInitType() const {return FCDEffectParameterSurfaceInitFactory::CUBE;}
|
||||
|
||||
/** Creates a full copy of the surface initialization parameter.
|
||||
@return The surface initialization parameter. You will need to delete this pointer. */
|
||||
virtual FCDEffectParameterSurfaceInit* Clone();
|
||||
|
||||
/** The type of cube-map initialization. */
|
||||
CubeType cubeType;
|
||||
|
||||
/** The list of image indices.
|
||||
The images are contained within the surface effect parameter.
|
||||
This is used only for the FACE cube-map initialization type and indicates
|
||||
how to match the faces of faces of the cube-map with the images in the surface effect parameter. */
|
||||
UInt16List order;
|
||||
};
|
||||
|
||||
/**
|
||||
A volumetric surface initialization method.
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterSurfaceInitVolume : public FCDEffectParameterSurfaceInit
|
||||
{
|
||||
public:
|
||||
/** The types of volumetric surfaces initialization. */
|
||||
enum VolumeType
|
||||
{
|
||||
ALL, /** Load all the mip-levels from the image file. */
|
||||
PRIMARY /** Load the first mip-level from the image file. */
|
||||
};
|
||||
|
||||
public:
|
||||
/** Constructor: builds a new volumetric surface initialization method. */
|
||||
FCDEffectParameterSurfaceInitVolume();
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~FCDEffectParameterSurfaceInitVolume() {}
|
||||
|
||||
/** Retrieves the initialization type. You cannot modify this value.
|
||||
To change the initialization type of a surface parameter, create a new
|
||||
surface initialization structure of the correct type.
|
||||
@return The initialization type. */
|
||||
virtual FCDEffectParameterSurfaceInitFactory::InitType GetInitType() const {return FCDEffectParameterSurfaceInitFactory::VOLUME;}
|
||||
|
||||
/** Creates a full copy of the surface initialization parameter.
|
||||
@return The surface initialization parameter. You will need to delete this pointer. */
|
||||
virtual FCDEffectParameterSurfaceInit* Clone();
|
||||
|
||||
/** The type of volumetric initialization. */
|
||||
VolumeType volumeType;
|
||||
};
|
||||
|
||||
/**
|
||||
A simple file surface initialization method.
|
||||
This is the method used for backward-compatibility.
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterSurfaceInitFrom : public FCDEffectParameterSurfaceInit
|
||||
{
|
||||
public:
|
||||
/** Constructor: builds a new file surface initialization method. */
|
||||
FCDEffectParameterSurfaceInitFrom() {}
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~FCDEffectParameterSurfaceInitFrom() {}
|
||||
|
||||
/** Retrieves the initialization type. You cannot modify this value.
|
||||
To change the initialization type of a surface parameter, create a new
|
||||
surface initialization structure of the correct type.
|
||||
@return The initialization type. */
|
||||
virtual FCDEffectParameterSurfaceInitFactory::InitType GetInitType() const {return FCDEffectParameterSurfaceInitFactory::FROM;}
|
||||
|
||||
/** Creates a full copy of the surface initialization parameter.
|
||||
@return The surface initialization parameter. You will need to delete this pointer. */
|
||||
virtual FCDEffectParameterSurfaceInit* Clone();
|
||||
|
||||
/** The list of mip levels. */
|
||||
StringList mip;
|
||||
|
||||
/** The list of matching slices. */
|
||||
StringList slice;
|
||||
|
||||
/** The list of matching faces. */
|
||||
StringList face;
|
||||
};
|
||||
|
||||
/**
|
||||
This method allows to initialize the surface at a later point.
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterSurfaceInitAsNull : public FCDEffectParameterSurfaceInit
|
||||
{
|
||||
public:
|
||||
/** Constructor: builds a new file surface initialization method. */
|
||||
FCDEffectParameterSurfaceInitAsNull() {}
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~FCDEffectParameterSurfaceInitAsNull() {}
|
||||
|
||||
/** Retrieves the initialization type. You cannot modify this value.
|
||||
To change the initialization type of a surface parameter, create a new
|
||||
surface initialization structure of the correct type.
|
||||
@return The initialization type. */
|
||||
virtual FCDEffectParameterSurfaceInitFactory::InitType GetInitType() const {return FCDEffectParameterSurfaceInitFactory::AS_NULL;}
|
||||
|
||||
/** Creates a full copy of the surface initialization parameter.
|
||||
@return The surface initialization parameter. You will need to delete this pointer. */
|
||||
virtual FCDEffectParameterSurfaceInit* Clone();
|
||||
};
|
||||
|
||||
/**
|
||||
This method allows to initialize the surface as a rendering target.
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterSurfaceInitAsTarget : public FCDEffectParameterSurfaceInit
|
||||
{
|
||||
public:
|
||||
/** Constructor: builds a new file surface initialization method. */
|
||||
FCDEffectParameterSurfaceInitAsTarget() {};
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~FCDEffectParameterSurfaceInitAsTarget() {}
|
||||
|
||||
/** Retrieves the initialization type. You cannot modify this value.
|
||||
To change the initialization type of a surface parameter, create a new
|
||||
surface initialization structure of the correct type.
|
||||
@return The initialization type. */
|
||||
virtual FCDEffectParameterSurfaceInitFactory::InitType GetInitType() const {return FCDEffectParameterSurfaceInitFactory::AS_TARGET;}
|
||||
|
||||
/** Creates a full copy of the surface initialization parameter.
|
||||
@return The surface initialization parameter. You will need to delete this pointer. */
|
||||
virtual FCDEffectParameterSurfaceInit* Clone();
|
||||
};
|
||||
|
||||
/**
|
||||
This method allows to initialize the surface as planar.
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectParameterSurfaceInitPlanar : public FCDEffectParameterSurfaceInit
|
||||
{
|
||||
public:
|
||||
/** Constructor: builds a new file surface initialization method. */
|
||||
FCDEffectParameterSurfaceInitPlanar() {};
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~FCDEffectParameterSurfaceInitPlanar() {}
|
||||
|
||||
/** Retrieves the initialization type. You cannot modify this value.
|
||||
To change the initialization type of a surface parameter, create a new
|
||||
surface initialization structure of the correct type.
|
||||
@return The initialization type. */
|
||||
virtual FCDEffectParameterSurfaceInitFactory::InitType GetInitType() const {return FCDEffectParameterSurfaceInitFactory::PLANAR;}
|
||||
|
||||
/** Creates a full copy of the surface initialization parameter.
|
||||
@return The surface initialization parameter. You will need to delete this pointer. */
|
||||
virtual FCDEffectParameterSurfaceInit* Clone();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // _FCD_EFFECT_PARAMETER_SURFACE_H_
|
||||
@@ -1,194 +0,0 @@
|
||||
/*
|
||||
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;
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDEffectPass.h
|
||||
This file contains the FCDEffectPass class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_EFFECT_PASS_H_
|
||||
#define _FCD_EFFECT_PASS_H_
|
||||
|
||||
#include "FCDocument/FCDObject.h"
|
||||
|
||||
class FCDEffectTechnique;
|
||||
class FCDEffectParameter;
|
||||
class FCDEffectParameterList;
|
||||
class FCDEffectPassShader;
|
||||
|
||||
typedef vector<FCDEffectPassShader*> FCDEffectPassShaderList; /**< A dynamically-sized array of shaders. */
|
||||
typedef vector<string> MeshDataList; /**< @deprecated A dynamically-sized array of mesh bindings. These should be bound using the \<bind\> element, at the instantiation level! */
|
||||
|
||||
/**
|
||||
A COLLADA effect pass.
|
||||
|
||||
The effect pass contains a list of effect shaders. While they
|
||||
may be missing, it does not make sense for the effect pass to
|
||||
contain more than two shaders: a vertex shader and a fragment/pixel shader.
|
||||
|
||||
For this reason, we provide the GetVertexShader and the GetFragmentShader
|
||||
which we expect will be used for most applications, rather than looking
|
||||
through the list of shader objects.
|
||||
|
||||
@ingroup FCDEffect
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectPass : public FCDObject
|
||||
{
|
||||
private:
|
||||
fstring name;
|
||||
FCDEffectTechnique* parent;
|
||||
FCDEffectPassShaderList shaders;
|
||||
MeshDataList meshdata;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDEffectTechnique::AddPass function.
|
||||
@param document The COLLADA document that owns this effect pass.
|
||||
@param _parent The effect technique that contains this effect pass. */
|
||||
FCDEffectPass(FCDocument* document, FCDEffectTechnique *_parent);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDEffectTechnique::ReleasePass function. */
|
||||
virtual ~FCDEffectPass();
|
||||
|
||||
/** Retrieves the effect techniques which contains this effect pass.
|
||||
@return The parent technique. */
|
||||
FCDEffectTechnique* GetParent() { return parent; }
|
||||
const FCDEffectTechnique* GetParent() const { return parent; } /**< See above. */
|
||||
|
||||
/** Retrieves the COLLADA id of the parent effect.
|
||||
This function is mostly useful as a shortcut for debugging and reporting.
|
||||
@return The COLLADA id of the parent effect. */
|
||||
const string& GetDaeId() const;
|
||||
|
||||
/** Retrieves the sub-id of the effect pass.
|
||||
This sub-id is optional.
|
||||
@return The sub-id. */
|
||||
const fstring& GetPassName() const { return name; }
|
||||
|
||||
/** Sets the optional sub-id for the effect pass.
|
||||
This sub-id is optional.
|
||||
@param _name The sub-id. */
|
||||
void SetPassName(const fstring& _name) { name = _name; }
|
||||
|
||||
/** @deprecated Retrieves the list of mesh data bindings.
|
||||
This patches bad export data in ColladaMaya and will be removed soon.
|
||||
@return The list of mesh data bindings. */
|
||||
const MeshDataList& GetMeshData() const { return meshdata; }
|
||||
|
||||
/** Retrieves the number of shaders contained within the effect pass.
|
||||
@return The number of shaders. */
|
||||
size_t GetShaderCount() const { return shaders.size(); }
|
||||
|
||||
/** Retrieves a specific shader.
|
||||
@param index The index of the shader.
|
||||
@return The shader. This pointer will be NULL if the index is out-of-bounds. */
|
||||
FCDEffectPassShader* GetShader(size_t index) { FUAssert(index < GetShaderCount(), return NULL); return shaders.at(index); }
|
||||
const FCDEffectPassShader* GetShader(size_t index) const { FUAssert(index < GetShaderCount(), return NULL); return shaders.at(index); } /**< See above. */
|
||||
|
||||
/** Adds a new shader to the pass.
|
||||
@return The new shader. */
|
||||
FCDEffectPassShader* AddShader();
|
||||
|
||||
/** Releases a shader contained within the pass.
|
||||
@param shader The shader to release. */
|
||||
void ReleaseShader(FCDEffectPassShader* shader);
|
||||
|
||||
/** Retrieves the vertex shader for this effect pass.
|
||||
@return The vertex shader. This pointer will be NULL if no
|
||||
shader within the pass affects vertices. */
|
||||
FCDEffectPassShader* GetVertexShader();
|
||||
const FCDEffectPassShader* GetVertexShader() const; /**< See above. */
|
||||
|
||||
/** Retrieves the fragment shader for this effect pass.
|
||||
@return The fragment shader. This pointer will be NULL if no
|
||||
shader within the pass affects pixels/fragments. */
|
||||
FCDEffectPassShader* GetFragmentShader();
|
||||
const FCDEffectPassShader* GetFragmentShader() const; /**< See above. */
|
||||
|
||||
/** Adds a new vertex shader to the pass.
|
||||
If a vertex shader already exists within the pass, it will be released.
|
||||
@return The new vertex shader. */
|
||||
FCDEffectPassShader* AddVertexShader();
|
||||
|
||||
/** Adds a new fragment shader to the pass.
|
||||
If a fragment shader already exists within the pass, it will be released.
|
||||
@return The new fragment shader. */
|
||||
FCDEffectPassShader* AddFragmentShader();
|
||||
|
||||
/** [INTERNAL] Clones the full effect pass.
|
||||
@param newParent The effect technique that will contain the cloned profile.
|
||||
@return The cloned pass. This pointer will never be NULL. */
|
||||
FCDEffectPass* Clone(FCDEffectTechnique* newParent) const;
|
||||
|
||||
/** [INTERNAL] Reads in the effect pass from a given COLLADA XML tree node.
|
||||
@param passNode The COLLADA XML tree node.
|
||||
@param techniqueNode X @deprecated bad interface : this dependency must be taken out[3]
|
||||
@param profileNode X @deprecated bad interface : this dependency must be taken out[2]
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the effect pass.*/
|
||||
FUStatus LoadFromXML(xmlNode* passNode, xmlNode* techniqueNode, xmlNode* profileNode);
|
||||
|
||||
/** [INTERNAL] Writes out the effect pass to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the effect pass.
|
||||
@return The created element XML tree node. */
|
||||
xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
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/FCDEffectCode.h"
|
||||
#include "FCDocument/FCDEffectPass.h"
|
||||
#include "FCDocument/FCDEffectPassShader.h"
|
||||
#include "FCDocument/FCDEffectProfileFX.h"
|
||||
#include "FCDocument/FCDEffectTechnique.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDEffectPassShader::FCDEffectPassShader(FCDocument* document, FCDEffectPass* _parent) : FCDObject(document, "FCDEffectPassShader")
|
||||
{
|
||||
parent = _parent;
|
||||
isFragment = false;
|
||||
code = NULL;
|
||||
}
|
||||
|
||||
FCDEffectPassShader::~FCDEffectPassShader()
|
||||
{
|
||||
parent = NULL;
|
||||
code = NULL;
|
||||
}
|
||||
|
||||
|
||||
// Adds a new binding to this shader.
|
||||
FCDEffectPassBind* FCDEffectPassShader::AddBinding()
|
||||
{
|
||||
bindings.push_back(FCDEffectPassBind());
|
||||
return &bindings.back();
|
||||
}
|
||||
|
||||
// Releases a binding contained within this shader.
|
||||
void FCDEffectPassShader::ReleaseBinding(FCDEffectPassBind* binding)
|
||||
{
|
||||
for (FCDEffectPassBindList::iterator it = bindings.begin(); it != bindings.end(); ++it)
|
||||
{
|
||||
if (&(*it) == binding)
|
||||
{
|
||||
bindings.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cloning
|
||||
FCDEffectPassShader* FCDEffectPassShader::Clone(FCDEffectPass* newParent) const
|
||||
{
|
||||
FCDEffectPassShader* clone = new FCDEffectPassShader(GetDocument(), newParent);
|
||||
clone->isFragment = isFragment;
|
||||
clone->bindings = bindings;
|
||||
clone->compilerTarget = compilerTarget;
|
||||
clone->compilerOptions = compilerOptions;
|
||||
clone->name = name;
|
||||
|
||||
// Look for the new code within the parent.
|
||||
if (code != NULL)
|
||||
{
|
||||
clone->code = newParent->GetParent()->FindCode(code->GetSid());
|
||||
if (clone->code == NULL) clone->code = newParent->GetParent()->GetParent()->FindCode(code->GetSid());
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Read in the ColladaFX pass shader from the xml node tree
|
||||
FUStatus FCDEffectPassShader::LoadFromXML(xmlNode* shaderNode)
|
||||
{
|
||||
FUStatus status;
|
||||
if (!IsEquivalent(shaderNode->name, DAE_SHADER_ELEMENT))
|
||||
{
|
||||
return status.Warning(FS("Pass shader contains unknown element."), shaderNode->line);
|
||||
}
|
||||
|
||||
// Read in the shader's name and stage
|
||||
xmlNode* nameNode = FindChildByType(shaderNode, DAE_FXCMN_NAME_ELEMENT);
|
||||
name = ReadNodeContentDirect(nameNode);
|
||||
string codeSource = ReadNodeProperty(nameNode, DAE_SOURCE_ATTRIBUTE);
|
||||
if (name.empty())
|
||||
{
|
||||
return status.Warning(FS("Unnamed effect pass shader found."), shaderNode->line);
|
||||
}
|
||||
string stage = ReadNodeStage(shaderNode);
|
||||
isFragment = stage == DAE_FXCMN_FRAGMENT_SHADER;
|
||||
if (!isFragment && stage != DAE_FXCMN_VERTEX_SHADER)
|
||||
{
|
||||
return status.Warning(FS("Unknown stage for effect pass shader: ") + TO_FSTRING(name), shaderNode->line);
|
||||
}
|
||||
|
||||
// Look-up the code filename for this shader, if available
|
||||
code = parent->GetParent()->FindCode(codeSource);
|
||||
if (code == NULL) code = parent->GetParent()->GetParent()->FindCode(codeSource);
|
||||
|
||||
// Read in the compiler-related elements
|
||||
xmlNode* compilerTargetNode = FindChildByType(shaderNode, DAE_FXCMN_COMPILERTARGET_ELEMENT);
|
||||
compilerTarget = TO_FSTRING(ReadNodeContentDirect(compilerTargetNode));
|
||||
xmlNode* compilerOptionsNode = FindChildByType(shaderNode, DAE_FXCMN_COMPILEROPTIONS_ELEMENT);
|
||||
compilerOptions = TO_FSTRING(ReadNodeContentDirect(compilerOptionsNode));
|
||||
|
||||
// Read in the bind parameters
|
||||
xmlNodeList bindNodes;
|
||||
FindChildrenByType(shaderNode, DAE_FXCMN_BIND_ELEMENT, bindNodes);
|
||||
for (xmlNodeList::iterator itB = bindNodes.begin(); itB != bindNodes.end(); ++itB)
|
||||
{
|
||||
xmlNode* paramNode = FindChildByType(*itB, DAE_PARAMETER_ELEMENT);
|
||||
|
||||
FCDEffectPassBind& bind = *(bindings.insert(bindings.end(), FCDEffectPassBind()));
|
||||
bind.symbol = ReadNodeProperty((*itB), DAE_SYMBOL_ATTRIBUTE);
|
||||
bind.reference = ReadNodeProperty(paramNode, DAE_REF_ATTRIBUTE);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out the pass shader to the COLLADA xml node tree
|
||||
xmlNode* FCDEffectPassShader::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* shaderNode = AddChild(parentNode, DAE_SHADER_ELEMENT);
|
||||
|
||||
// Write out the compiler information and the shader's name/stage
|
||||
if (!compilerTarget.empty()) AddChild(shaderNode, DAE_FXCMN_COMPILERTARGET_ELEMENT, compilerTarget);
|
||||
if (!compilerOptions.empty()) AddChild(shaderNode, DAE_FXCMN_COMPILEROPTIONS_ELEMENT, compilerOptions);
|
||||
AddAttribute(shaderNode, DAE_STAGE_ATTRIBUTE, isFragment ? DAE_FXCMN_FRAGMENT_SHADER : DAE_FXCMN_VERTEX_SHADER);
|
||||
if (!name.empty())
|
||||
{
|
||||
xmlNode* nameNode = AddChild(shaderNode, DAE_FXCMN_NAME_ELEMENT, name);
|
||||
if (code != NULL) AddAttribute(nameNode, DAE_SOURCE_ATTRIBUTE, code->GetSid());
|
||||
}
|
||||
|
||||
// Write out the bindings
|
||||
for (FCDEffectPassBindList::const_iterator itB = bindings.begin(); itB != bindings.end(); ++itB)
|
||||
{
|
||||
const FCDEffectPassBind& b = (*itB);
|
||||
if (!b.reference.empty() && !b.symbol.empty())
|
||||
{
|
||||
xmlNode* bindNode = AddChild(shaderNode, DAE_BIND_ELEMENT);
|
||||
AddAttribute(bindNode, DAE_SYMBOL_ATTRIBUTE, b.symbol);
|
||||
xmlNode* paramNode = AddChild(bindNode, DAE_PARAMETER_ELEMENT);
|
||||
AddAttribute(paramNode, DAE_REF_ATTRIBUTE, b.reference);
|
||||
}
|
||||
}
|
||||
return shaderNode;
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDEffectPassShader.h
|
||||
This file contains the FCDEffectPassShader and the FCDEffectPassBind classes.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_EFFECT_PASS_SHADER_H_
|
||||
#define _FCD_EFFECT_PASS_SHADER_H_
|
||||
|
||||
#include "FCDocument/FCDObject.h"
|
||||
|
||||
class FCDocument;
|
||||
class FCDEffectCode;
|
||||
|
||||
/**
|
||||
A COLLADA shader binding.
|
||||
|
||||
Binds an external symbol to a COLLADA effect parameter, by reference.
|
||||
|
||||
@ingroup FCDEffect
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectPassBind
|
||||
{
|
||||
public:
|
||||
string reference; /**< A COLLADA effect parameter reference. */
|
||||
string symbol; /**< An external symbol, used within the shader code. */
|
||||
};
|
||||
|
||||
typedef vector<FCDEffectPassBind> FCDEffectPassBindList; /**< A dynamically-sized array of shader bindings. */
|
||||
|
||||
/**
|
||||
A COLLADA shader.
|
||||
|
||||
The shader abstraction level in ColladaFX is contained within the effect passes.
|
||||
There are two types of shaders: vertex shaders and fragment/pixel shaders.
|
||||
A COLLADA shader contains a list of bindings to attach the effect parameters to the
|
||||
shader input parameters.
|
||||
|
||||
The shader object also contains the compiler information necessary to build
|
||||
the shader: its code, the compiler target and the compiler options.
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectPassShader : public FCDObject
|
||||
{
|
||||
private:
|
||||
FCDEffectPass* parent;
|
||||
|
||||
FCDEffectPassBindList bindings;
|
||||
fstring compilerTarget;
|
||||
fstring compilerOptions;
|
||||
string name;
|
||||
bool isFragment;
|
||||
FCDEffectCode* code;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly. Instead, use the FCDEffectPass::AddShader,
|
||||
FCDEffectPass::AddVertexShader or FCDEffectPass::AddFragmentShader functions.
|
||||
@param document The COLLADA document that owns this shader.
|
||||
@param parent The effect pass that contains this shader. */
|
||||
FCDEffectPassShader(FCDocument* document, FCDEffectPass* parent);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDEffectPass::ReleaseShader function. */
|
||||
virtual ~FCDEffectPassShader();
|
||||
|
||||
/** Retrieves the effect pass that contains this shader.
|
||||
@return The effect pass. */
|
||||
inline FCDEffectPass* GetParent() { return parent; }
|
||||
inline const FCDEffectPass* GetParent() const { return parent; } /**< See above. */
|
||||
|
||||
/** Sets this shader as affecting vertices.
|
||||
This sets the stage of the shader to the vertex pipeline. */
|
||||
inline void AffectsVertices() { isFragment = false; }
|
||||
|
||||
/** Sets this shader as affecting fragments/pixels.
|
||||
This sets the stage of the shader to the fragment/pixel pipeline. */
|
||||
inline void AffectsFragments() { isFragment = true; }
|
||||
|
||||
/** Retrieves whether this shader affects fragments/pixels.
|
||||
@return Whether this shader affects fragments/pixels. */
|
||||
inline bool IsFragmentShader() const { return isFragment; }
|
||||
|
||||
/** Retrieves whether this shader affects vertices.
|
||||
@return Whether this shader affects vertices. */
|
||||
inline bool IsVertexShader() const { return !isFragment; }
|
||||
|
||||
/** Retrieves the list of bindings for this shader.
|
||||
@return The list of bindings. */
|
||||
inline FCDEffectPassBindList& GetBindings() { return bindings; }
|
||||
inline const FCDEffectPassBindList& GetBindings() const { return bindings; } /**< See above. */
|
||||
|
||||
/** Retrieves the number of bindings for this shader.
|
||||
@return The number of bindings. */
|
||||
inline size_t GetBindingCount() const { return bindings.size(); }
|
||||
|
||||
/** Retrieves a binding contained in this shader.
|
||||
@param index The index of the binding.
|
||||
@return The binding. This pointer will be NULL if the index is out-of-bounds. */
|
||||
inline FCDEffectPassBind* GetBinding(size_t index) { FUAssert(index < GetBindingCount(), return NULL); return &bindings.at(index); }
|
||||
inline const FCDEffectPassBind* GetBinding(size_t index) const { FUAssert(index < GetBindingCount(), return NULL); return &bindings.at(index); } /**< See above. */
|
||||
|
||||
/** Adds a new binding to this shader.
|
||||
@return The new binding. */
|
||||
FCDEffectPassBind* AddBinding();
|
||||
|
||||
/** Releases a binding contained within this shader.
|
||||
@param binding The binding to release. */
|
||||
void ReleaseBinding(FCDEffectPassBind* binding);
|
||||
|
||||
/** Retrieves the compiler target information.
|
||||
The validity of this string depends on the type of the profile that contains this shader.
|
||||
@return The compiler target information string. */
|
||||
inline const fstring& GetCompilerTarget() const { return compilerTarget; }
|
||||
|
||||
/** Sets the compiler target information string.
|
||||
The validity of this string depends on the type of the profile that contains this shader.
|
||||
@param _compilerTarget The compiler target information. */
|
||||
inline void SetCompilerTarget(const fstring& _compilerTarget) { compilerTarget = _compilerTarget; }
|
||||
|
||||
/** Retrieves the compiler option string.
|
||||
The validity of this string depends on the type of the profile that contains this shader.
|
||||
@return The compiler option string. */
|
||||
inline const fstring& GetCompilerOptions() const { return compilerOptions; }
|
||||
|
||||
/** Sets the compiler option string.
|
||||
The validity of this string depends on the type of the profile that contains this shader.
|
||||
@param _compilerOptions The compiler option string. */
|
||||
inline void SetCompilerOptions(const fstring& _compilerOptions) { compilerOptions = _compilerOptions; }
|
||||
|
||||
/** Retrieves the sub-id of the shader.
|
||||
@return The sub-id. */
|
||||
inline const string& GetName() const { return name; }
|
||||
|
||||
/** Sets the sub-id of the shader.
|
||||
@param _name The sub-id. */
|
||||
inline void SetName(const string& _name) { name = _name; }
|
||||
|
||||
/** Retrieves the code inclusion that contains the code for this shader.
|
||||
@return The code inclusion. This pointer will be NULL if this shader
|
||||
is not yet attached to any code. */
|
||||
inline FCDEffectCode* GetCode() { return code; }
|
||||
inline const FCDEffectCode* GetCode() const { return code; } /**< See above. */
|
||||
|
||||
/** Sets the code inclusion that contains the code for this shader.
|
||||
@param _code The code inclusion. This pointer will be NULL to detach
|
||||
a shader from its code. */
|
||||
inline void SetCode(FCDEffectCode* _code) { code = _code; }
|
||||
|
||||
/** [INTERNAL] Clones this shader. You must manually delete the clone.
|
||||
@param newParent The effect pass that will contain the clone.
|
||||
@return The cloned shader. */
|
||||
FCDEffectPassShader* Clone(FCDEffectPass* newParent) const;
|
||||
|
||||
/** [INTERNAL] Reads in the pass shader from a given COLLADA XML tree node.
|
||||
@param shaderNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the shader.*/
|
||||
FUStatus LoadFromXML(xmlNode* shaderNode);
|
||||
|
||||
/** [INTERNAL] Writes out the pass shader to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the effect profile.
|
||||
@return The created element XML tree node. */
|
||||
xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif // _FCD_EFFECT_PASS_SHADER_H_
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
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/FCDEffect.h"
|
||||
#include "FCDocument/FCDEffectProfile.h"
|
||||
|
||||
FCDEffectProfile::FCDEffectProfile(FCDocument* document, FCDEffect* _parent) : FCDObject(document, "FCDEffectProfile")
|
||||
{
|
||||
parent = _parent;
|
||||
}
|
||||
|
||||
FCDEffectProfile::~FCDEffectProfile()
|
||||
{
|
||||
parent = NULL;
|
||||
}
|
||||
|
||||
const string& FCDEffectProfile::GetDaeId() const
|
||||
{
|
||||
return parent->GetDaeId();
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDEffectProfile.h
|
||||
This file contains the FCDEffectProfile abstract class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_EFFECT_PROFILE_H_
|
||||
#define _FCD_EFFECT_PROFILE_H_
|
||||
|
||||
#include "FUtils/FUDaeEnum.h"
|
||||
#include "FCDocument/FCDObject.h"
|
||||
|
||||
class FCDocument;
|
||||
class FCDEffect;
|
||||
|
||||
/**
|
||||
The base for a COLLADA effect profile.
|
||||
|
||||
COLLADA has multiple effect profiles: CG, HLSL, GLSL, GLES and the COMMON profile.
|
||||
For each profile, there is a class which implements this abstract class.
|
||||
This abstract class solely holds the parent effect and allows access to the
|
||||
profile type.
|
||||
|
||||
@see FCDEffectProfileFX FCDEffectStandard
|
||||
|
||||
@ingroup FCDEffect
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectProfile : public FCDObject
|
||||
{
|
||||
private:
|
||||
FCDEffect* parent;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDEffect::AddProfile function.
|
||||
@param document The COLLADA document that owns this effect profile.
|
||||
@param parent The effect which contains this profile. */
|
||||
FCDEffectProfile(FCDocument* document, FCDEffect* parent);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDEffect::ReleaseProfile function. */
|
||||
virtual ~FCDEffectProfile();
|
||||
|
||||
/** Retrieves the profile type for this effect.
|
||||
This function allows you to up-cast the pointer safely to a more specific
|
||||
effect profile class.
|
||||
@return The profile type. */
|
||||
virtual FUDaeProfileType::Type GetType() const = 0;
|
||||
|
||||
/** Retrieves the parent effect.
|
||||
This is the effect which contains this profile.
|
||||
@return The parent effect. This pointer will never be NULL. */
|
||||
FCDEffect* GetParent() { return parent; }
|
||||
const FCDEffect* GetParent() const { return parent; } /**< See above. */
|
||||
|
||||
/** [INTERNAL] Retrieves the COLLADA id of the parent effect.
|
||||
This function is useful when reporting errors and warnings.
|
||||
@return The COLLADA id of the parent effect. */
|
||||
const string& GetDaeId() const;
|
||||
|
||||
/** Retrieves an effect parameter. Looks for the effect parameter with the correct
|
||||
semantic, in order to bind or override its value.
|
||||
This function searches through the effect profile and the level of abstractions below.
|
||||
@param semantic The effect parameter semantic to match.
|
||||
@return The effect parameter that matches the semantic. This pointer will be NULL
|
||||
if no effect parameter matches the given semantic. */
|
||||
virtual FCDEffectParameter* FindParameterBySemantic(const string& semantic) = 0;
|
||||
|
||||
/** Retrieves a subset of the effect parameter list.
|
||||
Look for effect parameters with the correct semantic.
|
||||
This function searches through the effect profile and the level of abstractions below.
|
||||
@param semantic The effect parameter semantic to match.
|
||||
@param parameters The list of parameters to fill in. This list is not cleared. */
|
||||
virtual void FindParametersBySemantic(const string& semantic, FCDEffectParameterList& parameters) = 0;
|
||||
|
||||
/** Retrieves a subset of the effect parameter list.
|
||||
Look for effect parameters with the correct reference.
|
||||
This function searches through the effect profile and the level of abstractions below.
|
||||
@param reference The effect parameter reference to match. In the case of effect
|
||||
parameter generators, the reference is replaced by the sub-id.
|
||||
@param parameters The list of parameters to fill in. This list is not cleared. */
|
||||
virtual void FindParametersByReference(const string& reference, FCDEffectParameterList& parameters) = 0;
|
||||
|
||||
/** [INTERNAL] Clones the profile effect and its parameters.
|
||||
@param newParent The effect that will contain the cloned profile.
|
||||
@return The cloned profile. This pointer will never be NULL. */
|
||||
virtual FCDEffectProfile* Clone(FCDEffect* newParent) = 0;
|
||||
|
||||
/** [INTERNAL] Flattens this effect profile, pushing all the effect parameter overrides
|
||||
into the effect parameter generators and moving all the parameters to the
|
||||
effect technique level of abstraction. To flatten the material, use the
|
||||
FCDMaterialInstance::FlattenMaterial function. */
|
||||
virtual void Flatten() = 0;
|
||||
|
||||
/** [INTERNAL] Reads in the effect profile from a given COLLADA XML tree node.
|
||||
@param profileNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the effect profile.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* profileNode) = 0;
|
||||
|
||||
/** [INTERNAL] Writes out the effect profile to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the effect profile.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const = 0;
|
||||
};
|
||||
|
||||
#endif // _FCD_EFFECT_PROFILE_H_
|
||||
@@ -1,282 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDEffect.h"
|
||||
#include "FCDocument/FCDEffectCode.h"
|
||||
#include "FCDocument/FCDEffectProfileFX.h"
|
||||
#include "FCDocument/FCDEffectParameter.h"
|
||||
#include "FCDocument/FCDEffectParameterList.h"
|
||||
#include "FCDocument/FCDEffectParameterFactory.h"
|
||||
#include "FCDocument/FCDEffectTechnique.h"
|
||||
#include "FCDocument/FCDLibrary.h"
|
||||
#include "FCDocument/FCDImage.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDEffectProfileFX::FCDEffectProfileFX(FCDocument* document, FCDEffect* _parent, FUDaeProfileType::Type _type) : FCDEffectProfile(document, _parent)
|
||||
{
|
||||
type = _type;
|
||||
parameters = new FCDEffectParameterList(GetDocument(), true);
|
||||
}
|
||||
|
||||
FCDEffectProfileFX::~FCDEffectProfileFX()
|
||||
{
|
||||
CLEAR_POINTER_VECTOR(techniques);
|
||||
CLEAR_POINTER_VECTOR(codes);
|
||||
SAFE_DELETE(parameters);
|
||||
}
|
||||
|
||||
FCDEffectTechnique* FCDEffectProfileFX::AddTechnique()
|
||||
{
|
||||
FCDEffectTechnique* technique = new FCDEffectTechnique(GetDocument(), this);
|
||||
techniques.push_back(technique);
|
||||
return technique;
|
||||
}
|
||||
|
||||
void FCDEffectProfileFX::ReleaseTechnique(FCDEffectTechnique* technique)
|
||||
{
|
||||
FCDEffectTechniqueList::iterator it = std::find(techniques.begin(), techniques.end(), technique);
|
||||
if (it != techniques.end())
|
||||
{
|
||||
delete *it;
|
||||
techniques.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void FCDEffectProfileFX::AddParameter(FCDEffectParameter* parameter)
|
||||
{
|
||||
parameters->push_back(parameter);
|
||||
}
|
||||
|
||||
// Look for the parameter with the given reference.
|
||||
const FCDEffectParameter* FCDEffectProfileFX::FindParameter(const char* ref) const
|
||||
{
|
||||
const FCDEffectParameter* parameter = parameters->FindReference(ref);
|
||||
for (FCDEffectTechniqueList::const_iterator it = techniques.begin(); it != techniques.end() && parameter == NULL; ++it)
|
||||
{
|
||||
parameter = (*it)->FindParameter(ref);
|
||||
}
|
||||
return parameter;
|
||||
}
|
||||
|
||||
// Look for the effect parameter with the correct semantic, in order to bind/set its value
|
||||
FCDEffectParameter* FCDEffectProfileFX::FindParameterBySemantic(const string& semantic)
|
||||
{
|
||||
FCDEffectParameter* parameter = parameters->FindSemantic(semantic);
|
||||
for (FCDEffectTechniqueList::iterator it = techniques.begin(); it != techniques.end() && parameter == NULL; ++it)
|
||||
{
|
||||
parameter = (*it)->FindParameterBySemantic(semantic);
|
||||
}
|
||||
return parameter;
|
||||
}
|
||||
|
||||
void FCDEffectProfileFX::FindParametersBySemantic(const string& semantic, FCDEffectParameterList& _parameters)
|
||||
{
|
||||
// Look in the local parameters
|
||||
parameters->FindSemantic(semantic, _parameters);
|
||||
|
||||
// Look in the techniques
|
||||
for( FCDEffectTechniqueList::iterator it = techniques.begin(); it != techniques.end(); ++it)
|
||||
{
|
||||
(*it)->FindParametersBySemantic(semantic, _parameters);
|
||||
}
|
||||
}
|
||||
|
||||
void FCDEffectProfileFX::FindParametersByReference(const string& reference, FCDEffectParameterList& _parameters)
|
||||
{
|
||||
// Look in the local parameters
|
||||
parameters->FindReference(reference, _parameters);
|
||||
|
||||
// Look in the techniques
|
||||
for( FCDEffectTechniqueList::iterator it = techniques.begin(); it != techniques.end(); ++it)
|
||||
{
|
||||
(*it)->FindParametersBySemantic(reference, _parameters);
|
||||
}
|
||||
}
|
||||
|
||||
FCDEffectCode* FCDEffectProfileFX::FindCode(const string& sid)
|
||||
{
|
||||
for (FCDEffectCodeList::iterator itC = codes.begin(); itC != codes.end(); ++itC)
|
||||
{
|
||||
if ((*itC)->GetSid() == sid) return (*itC);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
const FCDEffectCode* FCDEffectProfileFX::FindCode(const string& sid) const
|
||||
{
|
||||
for (FCDEffectCodeList::const_iterator itC = codes.begin(); itC != codes.end(); ++itC)
|
||||
{
|
||||
if ((*itC)->GetSid() == sid) return (*itC);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Adds a new code inclusion to this effect profile.
|
||||
FCDEffectCode* FCDEffectProfileFX::AddCode()
|
||||
{
|
||||
FCDEffectCode* code = new FCDEffectCode(GetDocument());
|
||||
codes.push_back(code);
|
||||
return code;
|
||||
}
|
||||
|
||||
// Releases a code inclusion contained within this effect profile.
|
||||
void FCDEffectProfileFX::ReleaseCode(FCDEffectCode* code)
|
||||
{
|
||||
FCDEffectCodeList::iterator itC = std::find(codes.begin(), codes.end(), code);
|
||||
if (itC != codes.end())
|
||||
{
|
||||
delete *itC;
|
||||
codes.erase(itC);
|
||||
}
|
||||
}
|
||||
|
||||
// Clone the profile effect and its parameters
|
||||
FCDEffectProfile* FCDEffectProfileFX::Clone(FCDEffect* newParent)
|
||||
{
|
||||
// Hack, because I'm time-bound right now.
|
||||
FCDEffectProfileFX* clone = new FCDEffectProfileFX(GetDocument(), newParent, type);
|
||||
SAFE_DELETE(clone->parameters);
|
||||
clone->parameters = parameters->Clone();
|
||||
clone->includeFilename = includeFilename;
|
||||
|
||||
// Clone the codes: needs to happen before the techniques are cloned.
|
||||
clone->codes.reserve(codes.size());
|
||||
for (FCDEffectCodeList::const_iterator itC = codes.begin(); itC != codes.end(); ++itC)
|
||||
{
|
||||
clone->codes.push_back((*itC)->Clone());
|
||||
}
|
||||
|
||||
// Clone the techniques
|
||||
clone->techniques.reserve(techniques.size());
|
||||
for (FCDEffectTechniqueList::iterator itPs = techniques.begin(); itPs != techniques.end(); ++itPs)
|
||||
{
|
||||
clone->techniques.push_back((*itPs)->Clone(clone));
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Flatten this effect profile: trickling down all the parameters to the techniques
|
||||
void FCDEffectProfileFX::Flatten()
|
||||
{
|
||||
for (FCDEffectParameterList::iterator itP = parameters->begin(); itP != parameters->end(); ++itP)
|
||||
{
|
||||
FCDEffectParameterList generators;
|
||||
if ((*itP)->IsModifier())
|
||||
{
|
||||
// Overwrite the generators
|
||||
FindParametersByReference((*itP)->GetReference(), generators);
|
||||
for (FCDEffectParameterList::iterator itQ = generators.begin(); itQ != generators.end(); ++itQ)
|
||||
{
|
||||
if ((*itP) != (*itQ))
|
||||
{
|
||||
(*itP)->Overwrite(*itQ);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add this parameter to the techniques
|
||||
for (FCDEffectTechniqueList::iterator itT = techniques.begin(); itT != techniques.end(); ++itT)
|
||||
{
|
||||
(*itT)->AddParameter((*itP)->Clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
CLEAR_POINTER_VECTOR(*parameters);
|
||||
|
||||
// Flatten the techniques
|
||||
for (FCDEffectTechniqueList::iterator itT = techniques.begin(); itT != techniques.end(); ++itT)
|
||||
{
|
||||
(*itT)->Flatten();
|
||||
}
|
||||
}
|
||||
|
||||
// Read a <profile_X> node for a given COLLADA effect
|
||||
// Note that this function should do most of the work, except for profile-specific states
|
||||
FUStatus FCDEffectProfileFX::LoadFromXML(xmlNode* profileNode)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// Verify that we are given a valid XML input node.
|
||||
const char* profileName = FUDaeProfileType::ToString(type);
|
||||
if (!IsEquivalent(profileNode->name, profileName))
|
||||
{
|
||||
return status.Warning(FS("Invalid profile input node for effect") + TO_FSTRING(GetDaeId()), profileNode->line);
|
||||
}
|
||||
|
||||
// Read in the target platform for this effect profile
|
||||
platform = TO_FSTRING(ReadNodeProperty(profileNode, DAE_PLATFORM_ATTRIBUTE));
|
||||
|
||||
// Parse in the child elements: parameters and techniques
|
||||
SAFE_DELETE(parameters);
|
||||
parameters = new FCDEffectParameterList(GetDocument(), true);
|
||||
|
||||
for (xmlNode* child = profileNode->children; child != NULL; child = child->next)
|
||||
{
|
||||
if (child->type != XML_ELEMENT_NODE) continue;
|
||||
|
||||
if (IsEquivalent(child->name, DAE_TECHNIQUE_ELEMENT))
|
||||
{
|
||||
FCDEffectTechnique* technique = AddTechnique();
|
||||
status.AppendStatus(technique->LoadFromXML(child, profileNode));
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_NEWPARAM_ELEMENT))
|
||||
{
|
||||
AddParameter(FCDEffectParameterFactory::LoadFromXML(GetDocument(), child, &status));
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_CODE_ELEMENT) || IsEquivalent(child->name, DAE_FXCMN_INCLUDE_ELEMENT))
|
||||
{
|
||||
FCDEffectCode* code = AddCode();
|
||||
status.AppendStatus(code->LoadFromXML(child));
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_IMAGE_ELEMENT))
|
||||
{
|
||||
// You can create images within the ColladaFX profile: tell the image library about it.
|
||||
FCDImage* image = GetDocument()->GetImageLibrary()->AddEntity();
|
||||
status.AppendStatus(image->LoadFromXML(child));
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
xmlNode* FCDEffectProfileFX::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* profileNode = AddChild(parentNode, FUDaeProfileType::ToString(type));
|
||||
|
||||
// Write out the profile properties/base elements
|
||||
if (!platform.empty()) AddAttribute(profileNode, DAE_PLATFORM_ATTRIBUTE, platform);
|
||||
if (!includeFilename.empty()) AddChild(profileNode, DAE_FXCMN_INCLUDE_ELEMENT, includeFilename);
|
||||
|
||||
// Write out the code/includes
|
||||
for (FCDEffectCodeList::const_iterator itC = codes.begin(); itC != codes.end(); ++itC)
|
||||
{
|
||||
(*itC)->WriteToXML(profileNode);
|
||||
}
|
||||
|
||||
// Write out the parameters
|
||||
for (FCDEffectParameterList::const_iterator itP = parameters->begin(); itP != parameters->end(); ++itP)
|
||||
{
|
||||
(*itP)->WriteToXML(profileNode);
|
||||
}
|
||||
|
||||
// Write out the techniques
|
||||
for (FCDEffectTechniqueList::const_iterator itT = techniques.begin(); itT != techniques.end(); ++itT)
|
||||
{
|
||||
(*itT)->WriteToXML(profileNode);
|
||||
}
|
||||
|
||||
return profileNode;
|
||||
}
|
||||
@@ -1,219 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDEffectProfileFX.h
|
||||
This file declares the FCDEffectProfileFX class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_EFFECT_PROFILE_FX_H_
|
||||
#define _FCD_EFFECT_PROFILE_FX_H_
|
||||
|
||||
#include "FUtils/FUDaeEnum.h"
|
||||
#include "FCDocument/FCDEffectProfile.h"
|
||||
|
||||
class FCDocument;
|
||||
class FCDEffect;
|
||||
class FCDEffectCode;
|
||||
class FCDEffectParameter;
|
||||
class FCDEffectParameterSurface;
|
||||
class FCDEffectTechnique;
|
||||
class FCDEffectParameterList;
|
||||
|
||||
typedef vector<FCDEffectTechnique*> FCDEffectTechniqueList; /**< A dynamically-sized array of effect techniques. */
|
||||
typedef vector<FCDEffectCode*> FCDEffectCodeList; /**< A dynamically-sized array of effect code inclusion. */
|
||||
|
||||
/**
|
||||
A general effect profile description.
|
||||
|
||||
The general effect profile contains all the information necessary
|
||||
to implement the advanced effect profiles, such as CG, HLSL, GLSL and GLES.
|
||||
Since these effect profiles contains extremely similar information, they
|
||||
use the same description structure. For the COMMON profile,
|
||||
see the FCDEffectStandard class.
|
||||
|
||||
You should use the GetType function to figure out which profile this structure
|
||||
addresses. You can then retrieve one or many of the FCDEffectTechnique objects
|
||||
that describe how to render for this profile. You may want to check the
|
||||
FCDEffectMaterialTechniqueHint objects at the FCDMaterial level, in order to
|
||||
determine which technique(s) to use for your platform. At the profile
|
||||
level of abstraction, parameters may be generated within the FCDEffectParamterList.
|
||||
|
||||
@ingroup FCDEffect
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectProfileFX : public FCDEffectProfile
|
||||
{
|
||||
private:
|
||||
FUDaeProfileType::Type type;
|
||||
string includeFilename;
|
||||
fstring platform;
|
||||
|
||||
FCDEffectCodeList codes;
|
||||
FCDEffectTechniqueList techniques;
|
||||
FCDEffectParameterList* parameters;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly. Instead, use the FCDEffect::AddProfile function.
|
||||
@param document The COLLADA document which owns the effect profile.
|
||||
@param parent The effect which contains this profile.
|
||||
@param type The type of profile. */
|
||||
FCDEffectProfileFX(FCDocument* document, FCDEffect* parent, FUDaeProfileType::Type type);
|
||||
|
||||
/** Destructor: do not use directly. Instead, use the FCDEffect:RemoveProfile function. */
|
||||
virtual ~FCDEffectProfileFX();
|
||||
|
||||
/** Retrieves the profile type for this effect.
|
||||
This function is a part of the FCDEffectProfile interface and allows you
|
||||
to up-cast an effect profile pointer safely to this class.
|
||||
@return The profile type. This should never be the value: 'COMMON',
|
||||
but all other profiles currently derive from this class. */
|
||||
virtual FUDaeProfileType::Type GetType() const { return type; }
|
||||
|
||||
/** @deprecated Retrieves the filename of the file that contains the code for this effect profile.
|
||||
Instead, look through the FCDEffectCode object, using the GetCodeList function and retrieve
|
||||
the correct object and its filename string.
|
||||
@return The filename of the file to import. */
|
||||
const string& GetIncludeFilename() const { return includeFilename; }
|
||||
|
||||
/** Retrieves the name of the platform in which to use the effect profile.
|
||||
This parameter is very optional.
|
||||
@return The platform name. */
|
||||
const fstring& GetPlatform() const { return platform; }
|
||||
|
||||
/** Sets the name of the platform in which to use the effect profile.
|
||||
This parameter is very optional.
|
||||
@param _platform The platform name. */
|
||||
void SetPlatform(fstring& _platform) { platform = _platform; }
|
||||
|
||||
/** Retrieves the list of techniques contained within this effect profile.
|
||||
You may want to check the FCDEffectMaterialTechniqueHint objects at the FCDMaterial level,
|
||||
in order to determine which technique(s) to use for your platform.
|
||||
@return The list of inner techniques. */
|
||||
FCDEffectTechniqueList& GetTechniqueList() { return techniques; }
|
||||
const FCDEffectTechniqueList& GetTechniqueList() const { return techniques; } /**< See above. */
|
||||
|
||||
/** Retrieves the number of techniques contained within this effect profile.
|
||||
@return The number of inner techniques. */
|
||||
size_t GetTechniqueCount() const { return techniques.size(); }
|
||||
|
||||
/** Retrieves a technique contained within this effect profile.
|
||||
You may want to check the FCDEffectMaterialTechniqueHint objects at the FCDMaterial level,
|
||||
in order to determine which technique(s) to use for your platform.
|
||||
@param index The index of the technique.
|
||||
@return The inner technique. This pointer will be NULL if the index is out-of-bounds. */
|
||||
FCDEffectTechnique* GetTechnique(size_t index) { FUAssert(index < GetTechniqueCount(), return NULL); return techniques.at(index); }
|
||||
const FCDEffectTechnique* GetTechnique(size_t index) const { FUAssert(index < GetTechniqueCount(), return NULL); return techniques.at(index); } /**< See above. */
|
||||
|
||||
/** Adds a new technique to this effect profile.
|
||||
@return The new technique object. */
|
||||
FCDEffectTechnique* AddTechnique();
|
||||
|
||||
/** Releases a technique contained within this effect profile.
|
||||
@param technique The technique to release. */
|
||||
void ReleaseTechnique(FCDEffectTechnique* technique);
|
||||
|
||||
/** Retrieves the list of code inclusions.
|
||||
@return The list of code inclusions. */
|
||||
FCDEffectCodeList& GetCodeList() { return codes; }
|
||||
const FCDEffectCodeList& GetCodeList() const { return codes; } /**< See above. */
|
||||
|
||||
/** Retrieves the number of code inclusions contained within the effect profile.
|
||||
@return The number of code inclusions. */
|
||||
size_t GetCodeCount() const { return codes.size(); }
|
||||
|
||||
/** Retrieves a code inclusion contained within the effect profile.
|
||||
@param index The index of the code inclusion.
|
||||
@return The code inclusion. This pointer will be NULL if the index is out-of-bounds. */
|
||||
FCDEffectCode* GetCode(size_t index) { FUAssert(index < GetCodeCount(), return NULL); return codes.at(index); }
|
||||
const FCDEffectCode* GetCode(size_t index) const { FUAssert(index < GetCodeCount(), return NULL); return codes.at(index); } /**< See above. */
|
||||
|
||||
/** Retrieves the code inclusion with the given sub-id.
|
||||
@param sid A COLLADA sub-id.
|
||||
@return The code inclusion with the given sub-id. This pointer will be NULL,
|
||||
if there are no code inclusions that match the given sub-id. */
|
||||
FCDEffectCode* FindCode(const string& sid);
|
||||
const FCDEffectCode* FindCode(const string& sid) const; /**< See above. */
|
||||
|
||||
/** Adds a new code inclusion to this effect profile.
|
||||
@return The new code inclusion. */
|
||||
FCDEffectCode* AddCode();
|
||||
|
||||
/** Releases a code inclusion contained within this effect profile.
|
||||
@param code The code inclusion to release. */
|
||||
void ReleaseCode(FCDEffectCode* code);
|
||||
|
||||
/** Retrieves the list of effect parameters contained within the effect profile.
|
||||
At this level of abstraction, there should be only effect parameter generators.
|
||||
@return The list of effect parameters. */
|
||||
FCDEffectParameterList* GetParameters() { return parameters; }
|
||||
const FCDEffectParameterList* GetParameters() const { return parameters; } /**< See above. */
|
||||
|
||||
/** [INTERNAL] Inserts an existing parameter into the list of effect parameters
|
||||
at this abstraction level. This function is used during the flattening of a material.
|
||||
@param parameter The effect parameter to insert. */
|
||||
void AddParameter(FCDEffectParameter* parameter);
|
||||
|
||||
/** Retrieves an effect parameter.
|
||||
Looks for the effect parameter with the correct reference, in order to bind or override its value.
|
||||
This function searches through the effect profile and the level of abstractions below.
|
||||
@param reference The reference to match. In the case of effect parameter generators,
|
||||
the sub-id is used to match.
|
||||
@return The first effect parameter that matches the reference.
|
||||
This pointer will be NULL if no effect parameter matches the given semantic. */
|
||||
const FCDEffectParameter* FindParameter(const char* reference) const;
|
||||
|
||||
/** Retrieves an effect parameter.
|
||||
Looks for the effect parameter with the correct semantic, in order to bind or override its value.
|
||||
This function searches through the effect profile and the level of abstractions below.
|
||||
@param semantic The effect parameter semantic to match.
|
||||
@return The first effect parameter that matches the semantic.
|
||||
This pointer will be NULL if no effect parameter matches the given semantic. */
|
||||
virtual FCDEffectParameter* FindParameterBySemantic(const string& semantic);
|
||||
|
||||
/** Retrieves a subset of the effect parameter list.
|
||||
Look for the effect parameter generators with the correct semantic.
|
||||
This function searches through the effect profile and the level of abstractions below.
|
||||
@param semantic The effect parameter semantic to match.
|
||||
@param parameters The list of parameters to fill in. This list is not cleared. */
|
||||
virtual void FindParametersBySemantic(const string& semantic, FCDEffectParameterList& parameters);
|
||||
|
||||
/** Retrieves a subset of the effect parameter list.
|
||||
Look for the effect parameter generators with the correct reference.
|
||||
This function searches through the effect profile and the level of abstractions below.
|
||||
@param reference The effect parameter reference to match. In the case of effect
|
||||
parameter generators, the reference is replaced by the sub-id.
|
||||
@param parameters The list of parameters to fill in. This list is not cleared. */
|
||||
virtual void FindParametersByReference(const string& reference, FCDEffectParameterList& parameters);
|
||||
|
||||
/** [INTERNAL] Clones the full effect profile.
|
||||
@param newParent The effect that will contain the cloned profile.
|
||||
@return The cloned profile. This pointer will never be NULL. */
|
||||
virtual FCDEffectProfile* Clone(FCDEffect* newParent);
|
||||
|
||||
/** [INTERNAL] Flattens this effect profile. Pushes all the effect parameter overrides
|
||||
into the effect parameter generators and moves all the parameters to the
|
||||
effect technique level of abstraction. To flatten the material, use the
|
||||
FCDMaterialInstance::FlattenMaterial function. */
|
||||
virtual void Flatten();
|
||||
|
||||
/** [INTERNAL] Reads in the effect profile from a given COLLADA XML tree node.
|
||||
@param profileNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the effect profile.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* profileNode);
|
||||
|
||||
/** [INTERNAL] Writes out the effect profile to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the material declaration.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif // _FCD_EFFECT_PROFILE_H_
|
||||
@@ -1,572 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDAnimated.h"
|
||||
#include "FCDocument/FCDEffect.h"
|
||||
#include "FCDocument/FCDEffectStandard.h"
|
||||
#include "FCDocument/FCDMaterial.h"
|
||||
#include "FCDocument/FCDTexture.h"
|
||||
#include "FUtils/FUDaeEnum.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
#include "FUtils/FUStringConversion.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDEffectStandard::FCDEffectStandard(FCDocument* document, FCDEffect* _parent) : FCDEffectProfile(document, _parent)
|
||||
{
|
||||
emissionColor = translucencyColor = diffuseColor = ambientColor = specularColor = FMVector3::Origin;
|
||||
reflectivityFactor = translucencyFactor = specularFactor = emissionFactor = 1.0f;
|
||||
reflectivityColor = translucencyColor = FMVector3(1.0f, 1.0f, 1.0f);
|
||||
shininess = 20.0f;
|
||||
type = CONSTANT;
|
||||
isWireframe = isFaceMap = isDoubleSided = isFaceted = isEmissionFactor = false;
|
||||
textureBuckets = new FCDTextureList[FUDaeTextureChannel::COUNT];
|
||||
}
|
||||
|
||||
FCDEffectStandard::~FCDEffectStandard()
|
||||
{
|
||||
for (uint32 i = 0; i < FUDaeTextureChannel::COUNT; ++i)
|
||||
{
|
||||
FCDTextureList& t = textureBuckets[i];
|
||||
CLEAR_POINTER_VECTOR(t);
|
||||
}
|
||||
SAFE_DELETE_ARRAY(textureBuckets);
|
||||
}
|
||||
|
||||
// Retrieve one of the buckets
|
||||
const FCDTextureList& FCDEffectStandard::GetTextureBucket(uint32 bucket) const
|
||||
{
|
||||
if (bucket < FUDaeTextureChannel::COUNT) return textureBuckets[bucket];
|
||||
else return textureBuckets[FUDaeTextureChannel::FILTER]; // Because I think this one will almost always be empty. ;)
|
||||
}
|
||||
|
||||
// Adds a texture to a specific channel.
|
||||
FCDTexture* FCDEffectStandard::AddTexture(uint32 bucket)
|
||||
{
|
||||
FUAssert(bucket < FUDaeTextureChannel::COUNT, return NULL);
|
||||
FCDTexture* texture = new FCDTexture(GetDocument());
|
||||
textureBuckets[bucket].push_back(texture);
|
||||
return texture;
|
||||
}
|
||||
|
||||
// Releases a texture contained within this effect profile.
|
||||
void FCDEffectStandard::ReleaseTexture(FCDTexture* texture)
|
||||
{
|
||||
for (uint32 i = 0; i < FUDaeTextureChannel::COUNT; ++i)
|
||||
{
|
||||
FCDTextureList::iterator it = std::find(textureBuckets[i].begin(), textureBuckets[i].end(), texture);
|
||||
if (it != textureBuckets[i].end())
|
||||
{
|
||||
delete *it;
|
||||
textureBuckets[i].erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the opacity for this material
|
||||
float FCDEffectStandard::GetOpacity() const
|
||||
{
|
||||
return 1.0f - (translucencyColor.x + translucencyColor.y + translucencyColor.z) / 3.0f * translucencyFactor;
|
||||
}
|
||||
|
||||
// Calculate the overall reflectivity for this material
|
||||
float FCDEffectStandard::GetReflectivity() const
|
||||
{
|
||||
return (reflectivityColor.x + reflectivityColor.y + reflectivityColor.z) / 3.0f * reflectivityFactor;
|
||||
}
|
||||
|
||||
// Look for the effect parameter with the correct semantic, in order to bind/set its value
|
||||
FCDEffectParameter* FCDEffectStandard::FindParameterBySemantic(const string& semantic)
|
||||
{
|
||||
// Check only the texture buckets, for now.
|
||||
for (uint32 i = 0; i < FUDaeTextureChannel::COUNT; ++i)
|
||||
{
|
||||
for (FCDTextureList::iterator itT = textureBuckets[i].begin(); itT != textureBuckets[i].end(); ++itT)
|
||||
{
|
||||
FCDEffectParameter* p = (*itT)->FindParameterBySemantic(semantic);
|
||||
if (p != NULL) return p;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FCDEffectStandard::FindParametersBySemantic(const string& semantic, FCDEffectParameterList& parameters)
|
||||
{
|
||||
// Check only the texture buckets, for now.
|
||||
for (uint32 i = 0; i < FUDaeTextureChannel::COUNT; ++i)
|
||||
{
|
||||
for (FCDTextureList::iterator itT = textureBuckets[i].begin(); itT != textureBuckets[i].end(); ++itT)
|
||||
{
|
||||
(*itT)->FindParametersBySemantic(semantic, parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FCDEffectStandard::FindParametersByReference(const string& reference, FCDEffectParameterList& parameters)
|
||||
{
|
||||
// Check only the texture buckets, for now.
|
||||
for (uint32 i = 0; i < FUDaeTextureChannel::COUNT; ++i)
|
||||
{
|
||||
for (FCDTextureList::iterator itT = textureBuckets[i].begin(); itT != textureBuckets[i].end(); ++itT)
|
||||
{
|
||||
(*itT)->FindParametersByReference(reference, parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clone the standard effect
|
||||
FCDEffectProfile* FCDEffectStandard::Clone(FCDEffect* newParent)
|
||||
{
|
||||
FCDEffectStandard* clone = new FCDEffectStandard(GetDocument(), newParent);
|
||||
clone->type = type;
|
||||
for (uint32 i = 0; i < FUDaeTextureChannel::COUNT; ++i)
|
||||
{
|
||||
for (FCDTextureList::iterator itT = textureBuckets[i].begin(); itT != textureBuckets[i].end(); ++itT)
|
||||
{
|
||||
clone->textureBuckets[i].push_back((*itT)->Clone());
|
||||
}
|
||||
}
|
||||
|
||||
# define CLONE_ANIMATED_F(flt) clone->flt = flt; FCDAnimatedFloat::Clone(GetDocument(), &flt, &clone->flt);
|
||||
# define CLONE_ANIMATED_C(flt) clone->flt = flt; FCDAnimatedColor::Clone(GetDocument(), &flt, &clone->flt);
|
||||
|
||||
CLONE_ANIMATED_C(emissionColor); CLONE_ANIMATED_F(emissionFactor); clone->isEmissionFactor = isEmissionFactor;
|
||||
CLONE_ANIMATED_C(translucencyColor); CLONE_ANIMATED_F(translucencyFactor);
|
||||
CLONE_ANIMATED_C(diffuseColor); CLONE_ANIMATED_C(ambientColor);
|
||||
CLONE_ANIMATED_C(specularColor); CLONE_ANIMATED_F(specularFactor); CLONE_ANIMATED_F(shininess);
|
||||
CLONE_ANIMATED_C(reflectivityColor); CLONE_ANIMATED_F(reflectivityFactor);
|
||||
clone->isFaceted = isFaceted;
|
||||
clone->isDoubleSided = isDoubleSided;
|
||||
clone->isWireframe = isWireframe;
|
||||
clone->isFaceMap = isFaceMap;
|
||||
|
||||
# undef CLONE_ANIMATED_F
|
||||
# undef CLONE_ANIMATED_C
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Read in a <material> node from the COLLADA document
|
||||
FUStatus FCDEffectStandard::LoadFromXML(xmlNode* baseNode)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// <shader> support is for COLLADA 1.3 backward compatibility
|
||||
bool isCollada1_3 = IsEquivalent(baseNode->name, DAE_SHADER_ELEMENT);
|
||||
if (!isCollada1_3 && !IsEquivalent(baseNode->name, DAE_FX_PROFILE_COMMON_ELEMENT))
|
||||
{
|
||||
return status.Warning(FS("Unknown element as standard material base."), baseNode->line);
|
||||
}
|
||||
|
||||
// For COLLADA 1.3 backward compatibility: find the correct base node for the profile.
|
||||
// While we're digging, find the node with the Max-specific parameters
|
||||
xmlNode* maxParameterNode = NULL;
|
||||
xmlNode* mayaParameterNode = NULL;
|
||||
if (isCollada1_3)
|
||||
{
|
||||
// COLLADA 1.3 backward compatibility: the base node is <shader><technique><pass>
|
||||
// and the Max-specific parameters are in <shader><technique><pass><program>.
|
||||
xmlNode* commonTechniqueNode = FindTechnique(baseNode, DAE_COMMON_PROFILE);
|
||||
xmlNode* maxTechniqueNode = FindTechnique(baseNode, DAEMAX_MAX_PROFILE);
|
||||
baseNode = FindChildByType(commonTechniqueNode, DAE_PASS_ELEMENT);
|
||||
xmlNode* maxPassNode = FindChildByType(maxTechniqueNode, DAE_PASS_ELEMENT);
|
||||
maxParameterNode = FindChildByType(maxPassNode, DAE_PROGRAM_ELEMENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bump the base node up the first <technique> element
|
||||
xmlNode* techniqueNode = FindChildByType(baseNode, DAE_TECHNIQUE_ELEMENT);
|
||||
if (techniqueNode == NULL)
|
||||
{
|
||||
return status.Warning(FS("Expecting <technique> within the <profile_COMMON> element for effect: ") + TO_FSTRING(GetDaeId()), baseNode->line);
|
||||
}
|
||||
baseNode = techniqueNode;
|
||||
|
||||
// Look for an <extra><technique> node for Max-specific parameter
|
||||
xmlNode* extraNode = FindChildByType(baseNode, DAE_EXTRA_ELEMENT);
|
||||
maxParameterNode = FindTechnique(extraNode, DAEMAX_MAX_PROFILE);
|
||||
mayaParameterNode = FindTechnique(extraNode, DAEMAYA_MAYA_PROFILE);
|
||||
}
|
||||
|
||||
if (isCollada1_3)
|
||||
{
|
||||
// COLLADA 1.3 backward compatibility: look for <input> elements pointing to textures
|
||||
xmlNodeList textureInputNodes;
|
||||
FindChildrenByType(baseNode, DAE_INPUT_ELEMENT, textureInputNodes);
|
||||
for (xmlNodeList::iterator it = textureInputNodes.begin(); it != textureInputNodes.end(); ++it)
|
||||
{
|
||||
string semantic = ReadNodeSemantic(*it);
|
||||
if (semantic != DAE_TEXTURE_INPUT)
|
||||
{
|
||||
status.Warning(FS("Unknown input semantic in material: ") + TO_FSTRING(GetDaeId()), (*it)->line);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Retrieve the texture and bucket it
|
||||
string textureId = ReadNodeSource(*it);
|
||||
FCDTexture* texture = GetDocument()->FindTexture(textureId);
|
||||
if (texture != NULL)
|
||||
{
|
||||
uint32 channel = (uint32) texture->GetTextureChannel();
|
||||
textureBuckets[(uint32) channel].push_back(texture->Clone());
|
||||
}
|
||||
else
|
||||
{
|
||||
status.Warning(FS("Unknown input texture '") + TO_FSTRING(textureId) + FS("' in material: ") + TO_FSTRING(GetDaeId()), (*it)->line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the material's program node and figure out the correct shader type
|
||||
xmlNode* commonParameterNode = NULL;
|
||||
if (isCollada1_3)
|
||||
{
|
||||
// COLLADA 1.3 backward compatibility: read in the type attribute of the <program> node
|
||||
commonParameterNode = FindChildByType(baseNode, DAE_PROGRAM_ELEMENT);
|
||||
FUUri programUrl = ReadNodeUrl(commonParameterNode);
|
||||
string materialType = FUStringConversion::ToString(programUrl.prefix);
|
||||
if (materialType == DAE_CONSTANT_MATERIAL_PROGRAM) type = CONSTANT;
|
||||
else if (materialType == DAE_LAMBERT_MATERIAL_PROGRAM) type = LAMBERT;
|
||||
else if (materialType == DAE_PHONG_MATERIAL_PROGRAM) type = PHONG;
|
||||
else
|
||||
{
|
||||
return status.Warning(FS("Unsupported shader program type: '") + programUrl.prefix + FS("' in material: ") + TO_FSTRING(GetDaeId()), commonParameterNode->line);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Either <phong>, <lambert> or <constant> are expected
|
||||
for (commonParameterNode = baseNode->children; commonParameterNode != NULL; commonParameterNode = commonParameterNode->next)
|
||||
{
|
||||
if (commonParameterNode->type != XML_ELEMENT_NODE) continue;
|
||||
if (IsEquivalent(commonParameterNode->name, DAE_FXSTD_CONSTANT_ELEMENT)) { type = CONSTANT; break; }
|
||||
else if (IsEquivalent(commonParameterNode->name, DAE_FXSTD_LAMBERT_ELEMENT)) { type = LAMBERT; break; }
|
||||
else if (IsEquivalent(commonParameterNode->name, DAE_FXSTD_PHONG_ELEMENT)) { type = PHONG; break; }
|
||||
else if (IsEquivalent(commonParameterNode->name, DAE_FXSTD_BLINN_ELEMENT)) { type = BLINN; break; }
|
||||
}
|
||||
}
|
||||
if (commonParameterNode == NULL)
|
||||
{
|
||||
return status.Fail(FS("Unable to find the program node for standard effect: ") + TO_FSTRING(GetDaeId()), baseNode->line);
|
||||
}
|
||||
|
||||
bool hasTranslucency = false, hasReflectivity = false;
|
||||
FCDTextureList emptyBucket;
|
||||
|
||||
// Read in the parameters for the common program types and apply them to the shader
|
||||
StringList parameterNames;
|
||||
xmlNodeList parameterNodes;
|
||||
FindParameters(commonParameterNode, parameterNames, parameterNodes);
|
||||
FindParameters(maxParameterNode, parameterNames, parameterNodes);
|
||||
FindParameters(mayaParameterNode, parameterNames, parameterNodes);
|
||||
size_t parameterCount = parameterNodes.size();
|
||||
for (size_t i = 0; i < parameterCount; ++i)
|
||||
{
|
||||
xmlNode* parameterNode = parameterNodes[i];
|
||||
const string& parameterName = parameterNames[i];
|
||||
const char* parameterContent = ReadNodeContentDirect(parameterNode);
|
||||
if (parameterName == DAE_EMISSION_MATERIAL_PARAMETER || parameterName == DAE_EMISSION_MATERIAL_PARAMETER1_3)
|
||||
{
|
||||
status.AppendStatus(ParseColorTextureParameter(parameterNode, emissionColor, textureBuckets[FUDaeTextureChannel::EMISSION]));
|
||||
}
|
||||
else if (parameterName == DAE_DIFFUSE_MATERIAL_PARAMETER || parameterName == DAE_DIFFUSE_MATERIAL_PARAMETER1_3)
|
||||
{
|
||||
status.AppendStatus(ParseColorTextureParameter(parameterNode, diffuseColor, textureBuckets[FUDaeTextureChannel::DIFFUSE]));
|
||||
}
|
||||
else if (parameterName == DAE_AMBIENT_MATERIAL_PARAMETER || parameterName == DAE_AMBIENT_MATERIAL_PARAMETER1_3)
|
||||
{
|
||||
status.AppendStatus(ParseColorTextureParameter(parameterNode, ambientColor, textureBuckets[FUDaeTextureChannel::AMBIENT]));
|
||||
}
|
||||
else if (parameterName == DAE_TRANSPARENT_MATERIAL_PARAMETER || parameterName == DAE_TRANSPARENT_MATERIAL_PARAMETER1_3)
|
||||
{
|
||||
status.AppendStatus(ParseColorTextureParameter(parameterNode, translucencyColor, textureBuckets[FUDaeTextureChannel::TRANSPARENT]));
|
||||
hasTranslucency = true;
|
||||
}
|
||||
else if (parameterName == DAE_TRANSPARENCY_MATERIAL_PARAMETER || parameterName == DAE_TRANSPARENCY_MATERIAL_PARAMETER1_3)
|
||||
{
|
||||
status.AppendStatus(ParseFloatTextureParameter(parameterNode, translucencyFactor, textureBuckets[FUDaeTextureChannel::OPACITY]));
|
||||
hasTranslucency = true;
|
||||
}
|
||||
else if (parameterName == DAE_SPECULAR_MATERIAL_PARAMETER || parameterName == DAE_SPECULAR_MATERIAL_PARAMETER1_3)
|
||||
{
|
||||
status.AppendStatus(ParseColorTextureParameter(parameterNode, specularColor, textureBuckets[FUDaeTextureChannel::SPECULAR]));
|
||||
}
|
||||
else if (parameterName == DAE_SPECULAR_MATERIAL_PARAMETER || parameterName == DAE_SPECULAR_MATERIAL_PARAMETER1_3)
|
||||
{
|
||||
status.AppendStatus(ParseColorTextureParameter(parameterNode, specularColor, textureBuckets[FUDaeTextureChannel::SPECULAR]));
|
||||
}
|
||||
else if (parameterName == DAE_SHININESS_MATERIAL_PARAMETER || parameterName == DAE_SHININESS_MATERIAL_PARAMETER1_3)
|
||||
{
|
||||
status.AppendStatus(ParseFloatTextureParameter(parameterNode, shininess, textureBuckets[FUDaeTextureChannel::SHININESS]));
|
||||
}
|
||||
else if (parameterName == DAE_REFLECTIVE_MATERIAL_PARAMETER || parameterName == DAE_REFLECTIVE_MATERIAL_PARAMETER1_3)
|
||||
{
|
||||
status.AppendStatus(ParseColorTextureParameter(parameterNode, reflectivityColor, textureBuckets[FUDaeTextureChannel::REFLECTION]));
|
||||
hasReflectivity = true;
|
||||
}
|
||||
else if (parameterName == DAE_REFLECTIVITY_MATERIAL_PARAMETER || parameterName == DAE_REFLECTIVITY_MATERIAL_PARAMETER1_3)
|
||||
{
|
||||
status.AppendStatus(ParseFloatTextureParameter(parameterNode, reflectivityFactor, emptyBucket));
|
||||
hasReflectivity = true;
|
||||
}
|
||||
else if (parameterName == DAE_BUMP_MATERIAL_PARAMETER)
|
||||
{
|
||||
status.AppendStatus(ParseSimpleTextureParameter(parameterNode, textureBuckets[FUDaeTextureChannel::BUMP]));
|
||||
}
|
||||
else if (parameterName == DAEMAX_SPECLEVEL_MATERIAL_PARAMETER || parameterName == DAEMAX_SPECLEVEL_MATERIAL_PARAMETER1_3)
|
||||
{
|
||||
status.AppendStatus(ParseFloatTextureParameter(parameterNode, specularFactor, textureBuckets[FUDaeTextureChannel::SPECULAR_LEVEL]));
|
||||
}
|
||||
else if (parameterName == DAEMAX_EMISSIONLEVEL_MATERIAL_PARAMETER || parameterName == DAEMAX_EMISSIONLEVEL_MATERIAL_PARAMETER1_3)
|
||||
{
|
||||
status.AppendStatus(ParseFloatTextureParameter(parameterNode, emissionFactor, textureBuckets[FUDaeTextureChannel::EMISSION]));
|
||||
isEmissionFactor = true;
|
||||
}
|
||||
else if (parameterName == DAEMAX_FACETED_MATERIAL_PARAMETER || parameterName == DAEMAX_FACETED_MATERIAL_PARAMETER1_3)
|
||||
{
|
||||
isFaceted = FUStringConversion::ToBoolean(parameterContent);
|
||||
}
|
||||
else if (parameterName == DAESHD_DOUBLESIDED_PARAMETER)
|
||||
{
|
||||
isDoubleSided = FUStringConversion::ToBoolean(parameterContent);
|
||||
}
|
||||
else if (parameterName == DAEMAX_WIREFRAME_MATERIAL_PARAMETER)
|
||||
{
|
||||
isWireframe = FUStringConversion::ToBoolean(parameterContent);
|
||||
}
|
||||
else if (parameterName == DAEMAX_FACEMAP_MATERIAL_PARAMETER)
|
||||
{
|
||||
isFaceMap = FUStringConversion::ToBoolean(parameterContent);
|
||||
}
|
||||
else if (parameterName == DAEMAX_INDEXOFREFRACTION_MATERIAL_PARAMETER)
|
||||
{
|
||||
status.AppendStatus(ParseSimpleTextureParameter(parameterNode, textureBuckets[FUDaeTextureChannel::REFRACTION]));
|
||||
}
|
||||
else if (parameterName == DAEMAX_DISPLACEMENT_MATERIAL_PARAMETER)
|
||||
{
|
||||
status.AppendStatus(ParseSimpleTextureParameter(parameterNode, textureBuckets[FUDaeTextureChannel::DISPLACEMENT]));
|
||||
}
|
||||
else if (parameterName == DAEMAX_FILTERCOLOR_MATERIAL_PARAMETER)
|
||||
{
|
||||
status.AppendStatus(ParseSimpleTextureParameter(parameterNode, textureBuckets[FUDaeTextureChannel::FILTER]));
|
||||
}
|
||||
else
|
||||
{
|
||||
status.Warning(FS("Unknown parameter name for material ") + TO_FSTRING(GetDaeId()), parameterNode->line);
|
||||
}
|
||||
}
|
||||
|
||||
bool isEmptyBucketEmpty = emptyBucket.empty();
|
||||
CLEAR_POINTER_VECTOR(emptyBucket);
|
||||
if (!isEmptyBucketEmpty)
|
||||
{
|
||||
return status.Fail(FS("Unexpected texture sampler on some parameters for material ") + TO_FSTRING(GetDaeId()), baseNode->line);
|
||||
}
|
||||
|
||||
// Although the default COLLADA materials gives, wrongly, a transparent material,
|
||||
// when neither the TRANSPARENT or TRANSPARENCY parameters are set, assume an opaque material.
|
||||
// Similarly for reflectivity
|
||||
if (!hasTranslucency)
|
||||
{
|
||||
translucencyColor = FMVector3::Origin;
|
||||
translucencyFactor = 0.0f;
|
||||
}
|
||||
if (!hasReflectivity)
|
||||
{
|
||||
reflectivityColor = FMVector3::Origin;
|
||||
reflectivityFactor = 0.0f;
|
||||
}
|
||||
|
||||
// Convert some of the values that may appear in different formats
|
||||
if (!isEmissionFactor)
|
||||
{
|
||||
emissionFactor = (emissionColor.x + emissionColor.y + emissionColor.z) / 3.0f;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
xmlNode* FCDEffectStandard::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* profileCommonNode = AddChild(parentNode, DAE_FX_PROFILE_COMMON_ELEMENT);
|
||||
xmlNode* techniqueCommonNode = AddChild(profileCommonNode, DAE_TECHNIQUE_ELEMENT);
|
||||
AddNodeSid(techniqueCommonNode, "common");
|
||||
|
||||
const char* materialName;
|
||||
switch (type)
|
||||
{
|
||||
case CONSTANT: materialName = DAE_FXSTD_CONSTANT_ELEMENT; break;
|
||||
case LAMBERT: materialName = DAE_FXSTD_LAMBERT_ELEMENT; break;
|
||||
case PHONG: materialName = DAE_FXSTD_PHONG_ELEMENT; break;
|
||||
case BLINN: materialName = DAE_FXSTD_BLINN_ELEMENT; break;
|
||||
case UNKNOWN:
|
||||
default: materialName = DAEERR_UNKNOWN_ELEMENT; break;
|
||||
}
|
||||
xmlNode* materialNode = AddChild(techniqueCommonNode, materialName);
|
||||
xmlNode* techniqueNode = AddExtraTechniqueChild(techniqueCommonNode, DAEMAYA_MAYA_PROFILE);
|
||||
|
||||
// Export the color/float parameters
|
||||
FCDTextureList emptyBucket; float emptyValue = 0.0f; FMVector3 emptyColor;
|
||||
WriteColorTextureParameterToXML(materialNode, DAE_EMISSION_MATERIAL_PARAMETER, emissionColor, textureBuckets[FUDaeTextureChannel::EMISSION]);
|
||||
if (type != CONSTANT)
|
||||
{
|
||||
WriteColorTextureParameterToXML(materialNode, DAE_AMBIENT_MATERIAL_PARAMETER, emissionColor, textureBuckets[FUDaeTextureChannel::AMBIENT]);
|
||||
WriteColorTextureParameterToXML(materialNode, DAE_DIFFUSE_MATERIAL_PARAMETER, diffuseColor, textureBuckets[FUDaeTextureChannel::DIFFUSE]);
|
||||
if (type != LAMBERT)
|
||||
{
|
||||
WriteColorTextureParameterToXML(materialNode, DAE_SPECULAR_MATERIAL_PARAMETER, specularColor, textureBuckets[FUDaeTextureChannel::SPECULAR]);
|
||||
WriteFloatTextureParameterToXML(materialNode, DAE_SHININESS_MATERIAL_PARAMETER, shininess, emptyBucket);
|
||||
if (!textureBuckets[FUDaeTextureChannel::SHININESS].empty())
|
||||
{
|
||||
WriteFloatTextureParameterToXML(techniqueNode, DAE_SHININESS_MATERIAL_PARAMETER, shininess, textureBuckets[FUDaeTextureChannel::SHININESS]);
|
||||
WriteFloatTextureParameterToXML(techniqueNode, DAEMAX_SPECLEVEL_MATERIAL_PARAMETER, specularFactor, textureBuckets[FUDaeTextureChannel::SPECULAR_LEVEL]);
|
||||
}
|
||||
}
|
||||
}
|
||||
WriteColorTextureParameterToXML(materialNode, DAE_REFLECTIVE_MATERIAL_PARAMETER, reflectivityColor, textureBuckets[FUDaeTextureChannel::REFLECTION]);
|
||||
WriteFloatTextureParameterToXML(materialNode, DAE_REFLECTIVITY_MATERIAL_PARAMETER, reflectivityFactor, emptyBucket);
|
||||
|
||||
// Translucency includes both transparent and opacity textures
|
||||
FCDTextureList translucencyBucket = textureBuckets[FUDaeTextureChannel::TRANSPARENT];
|
||||
translucencyBucket.insert(translucencyBucket.end(), textureBuckets[FUDaeTextureChannel::OPACITY].begin(), textureBuckets[FUDaeTextureChannel::OPACITY].end());
|
||||
WriteColorTextureParameterToXML(materialNode, DAE_TRANSPARENT_MATERIAL_PARAMETER, translucencyColor, translucencyBucket);
|
||||
WriteFloatTextureParameterToXML(materialNode, DAE_TRANSPARENCY_MATERIAL_PARAMETER, translucencyFactor, emptyBucket);
|
||||
WriteFloatTextureParameterToXML(materialNode, DAEMAX_INDEXOFREFRACTION_MATERIAL_PARAMETER, emptyValue, textureBuckets[FUDaeTextureChannel::REFRACTION]);
|
||||
|
||||
// Non-COLLADA parameters
|
||||
if (!textureBuckets[FUDaeTextureChannel::BUMP].empty())
|
||||
{
|
||||
WriteFloatTextureParameterToXML(techniqueNode, DAE_BUMP_MATERIAL_PARAMETER, emptyValue, textureBuckets[FUDaeTextureChannel::BUMP]);
|
||||
}
|
||||
if (!textureBuckets[FUDaeTextureChannel::DISPLACEMENT].empty())
|
||||
{
|
||||
WriteFloatTextureParameterToXML(techniqueNode, DAEMAX_DISPLACEMENT_MATERIAL_PARAMETER, emptyValue, textureBuckets[FUDaeTextureChannel::DISPLACEMENT]);
|
||||
}
|
||||
if (!textureBuckets[FUDaeTextureChannel::FILTER].empty())
|
||||
{
|
||||
WriteColorTextureParameterToXML(techniqueNode, DAEMAX_FILTERCOLOR_MATERIAL_PARAMETER, emptyColor, textureBuckets[FUDaeTextureChannel::FILTER]);
|
||||
}
|
||||
|
||||
return profileCommonNode;
|
||||
}
|
||||
|
||||
xmlNode* FCDEffectStandard::WriteColorTextureParameterToXML(xmlNode* parentNode, const char* parameterNodeName, const FMVector3& value, const FCDTextureList& textureBucket) const
|
||||
{
|
||||
xmlNode* parameterNode = AddChild(parentNode, parameterNodeName);
|
||||
if (WriteTextureParameterToXML(parameterNode, textureBucket) == NULL)
|
||||
{
|
||||
// The color value expected by the profile_COMMON <color> element has four floating-point values.
|
||||
string colorValue = FUStringConversion::ToString(value) + " 1.0";
|
||||
xmlNode* valueNode = AddChild(parameterNode, DAE_FXSTD_COLOR_ELEMENT, colorValue);
|
||||
GetDocument()->WriteAnimatedValueToXML(&value.x, valueNode, parameterNodeName);
|
||||
}
|
||||
return parameterNode;
|
||||
}
|
||||
|
||||
xmlNode* FCDEffectStandard::WriteFloatTextureParameterToXML(xmlNode* parentNode, const char* parameterNodeName, const float& value, const FCDTextureList& textureBucket) const
|
||||
{
|
||||
xmlNode* parameterNode = AddChild(parentNode, parameterNodeName);
|
||||
if (WriteTextureParameterToXML(parameterNode, textureBucket) == NULL)
|
||||
{
|
||||
xmlNode* valueNode = AddChild(parameterNode, DAE_FXSTD_FLOAT_ELEMENT, value);
|
||||
GetDocument()->WriteAnimatedValueToXML(&value, valueNode, parameterNodeName);
|
||||
}
|
||||
return parameterNode;
|
||||
}
|
||||
|
||||
xmlNode* FCDEffectStandard::WriteTextureParameterToXML(xmlNode* parentNode, const FCDTextureList& textureBucket) const
|
||||
{
|
||||
xmlNode* textureNode = NULL;
|
||||
for (FCDTextureList::const_iterator itT = textureBucket.begin(); itT != textureBucket.end(); ++itT)
|
||||
{
|
||||
xmlNode* newTextureNode = (*itT)->WriteToXML(parentNode);
|
||||
if (newTextureNode != NULL && textureNode == NULL) textureNode = newTextureNode;
|
||||
}
|
||||
return textureNode;
|
||||
}
|
||||
|
||||
// Parse in the different standard effect parameters, bucketing the textures
|
||||
FUStatus FCDEffectStandard::ParseColorTextureParameter(xmlNode* parameterNode, FMVector3& value, FCDTextureList& textureBucket)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// Look for <texture> elements, they pre-empt everything else
|
||||
size_t originalSize = textureBucket.size();
|
||||
ParseSimpleTextureParameter(parameterNode, textureBucket);
|
||||
if (originalSize < textureBucket.size()) { value = FMVector3(1.0f, 1.0f, 1.0f); return status; }
|
||||
|
||||
// Next, look for a <color> element
|
||||
// COLLADA 1.3 backward compatibility: also look for the color value directly inside the parameter node.
|
||||
xmlNode* colorNode = FindChildByType(parameterNode, DAE_FXSTD_COLOR_ELEMENT);
|
||||
const char* content = ReadNodeContentDirect(colorNode);
|
||||
if (content == NULL || *content == 0) content = ReadNodeContentDirect(parameterNode);
|
||||
|
||||
// Parse the color value and allow for an animation of it
|
||||
value = FUStringConversion::ToPoint(content);
|
||||
if (HasNodeProperty(colorNode, DAE_ID_ATTRIBUTE) || HasNodeProperty(colorNode, DAE_SID_ATTRIBUTE))
|
||||
FCDAnimatedColor::Create(GetDocument(), colorNode, &value);
|
||||
else
|
||||
FCDAnimatedColor::Create(GetDocument(), parameterNode, &value);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
FUStatus FCDEffectStandard::ParseFloatTextureParameter(xmlNode* parameterNode, float& value, FCDTextureList& textureBucket)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// Look for <texture> elements, they pre-empt everything else
|
||||
size_t originalSize = textureBucket.size();
|
||||
ParseSimpleTextureParameter(parameterNode, textureBucket);
|
||||
if (originalSize < textureBucket.size()) { value = 1.0f; return status; }
|
||||
|
||||
// Next, look for a <float> element
|
||||
// COLLADA 1.3 backward compatibility: also look for the value directly inside the parameter node.
|
||||
xmlNode* floatNode = FindChildByType(parameterNode, DAE_FXSTD_FLOAT_ELEMENT);
|
||||
const char* content = ReadNodeContentDirect(floatNode);
|
||||
if (content == NULL || *content == 0) content = ReadNodeContentDirect(parameterNode);
|
||||
|
||||
// Parse the value and register it for an animation.
|
||||
value = FUStringConversion::ToFloat(content);
|
||||
if (HasNodeProperty(floatNode, DAE_ID_ATTRIBUTE) || HasNodeProperty(floatNode, DAE_SID_ATTRIBUTE))
|
||||
FCDAnimatedFloat::Create(GetDocument(), floatNode, &value);
|
||||
else
|
||||
FCDAnimatedFloat::Create(GetDocument(), parameterNode, &value);
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
FUStatus FCDEffectStandard::ParseSimpleTextureParameter(xmlNode* parameterNode, FCDTextureList& textureBucket)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// Parse in all the <texture> elements as standard effect samplers
|
||||
xmlNodeList samplerNodes;
|
||||
FindChildrenByType(parameterNode, DAE_FXSTD_SAMPLER_ELEMENT, samplerNodes);
|
||||
if (!samplerNodes.empty())
|
||||
{
|
||||
for (xmlNodeList::iterator itS = samplerNodes.begin(); itS != samplerNodes.end(); ++itS)
|
||||
{
|
||||
// Parse in the texture element and bucket them
|
||||
FCDTexture* texture = new FCDTexture(GetDocument());
|
||||
status.AppendStatus(texture->LoadFromTextureXML(*itS));
|
||||
if (status) textureBucket.push_back(texture);
|
||||
else { SAFE_DELETE(texture); }
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -1,415 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDEffectStandard.h
|
||||
This file contains the FCDEffectStandard class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_MATERIAL_STANDARD_H_
|
||||
#define _FCD_MATERIAL_STANDARD_H_
|
||||
|
||||
#include "FUtils/FUDaeEnum.h"
|
||||
#include "FCDocument/FCDEffectProfile.h"
|
||||
|
||||
class FCDocument;
|
||||
class FCDEffect;
|
||||
class FCDEffectParameter;
|
||||
class FCDTexture;
|
||||
class FCDEffectParameterList;
|
||||
|
||||
/** A dynamically-sized array of texture objects. */
|
||||
typedef vector<FCDTexture*> FCDTextureList;
|
||||
|
||||
/**
|
||||
A COMMON profile effect description.
|
||||
|
||||
The COMMON effect profile holds the information necessary
|
||||
to render your polygon sets using the well-defined lighting models.
|
||||
|
||||
COLLADA supports four lighting models: constant, Lambert, Phong and Blinn.
|
||||
|
||||
@ingroup FCDEffect
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectStandard : public FCDEffectProfile
|
||||
{
|
||||
public:
|
||||
/** The list of the lighting models supported by the COMMON profile of COLLADA. */
|
||||
enum LightingType
|
||||
{
|
||||
/** The constant lighting model.
|
||||
This lighting model uses the emissive color everywhere, without
|
||||
any complex lighting calculations. It also uses the translucency
|
||||
factor and the translucency color, by multiplying them together
|
||||
and applying them to your standard alpha channel according to the
|
||||
final lighting color.*/
|
||||
CONSTANT,
|
||||
|
||||
/** The Lambert lighting model.
|
||||
This lighting model improves on the constant lighting model by
|
||||
using the dot-product between the normalized light vectors and the
|
||||
polygon normals to determine how much light should affect each polygon.
|
||||
This value is multiplied to the diffuse color and (1 + the ambient color). */
|
||||
LAMBERT,
|
||||
|
||||
/** The Phong lighting model.
|
||||
This lighting model improves on the Lambert lighting model by
|
||||
calculating how much light is reflected by the polygons into the viewer's eye.
|
||||
For this calculation, the shininess, the specular color and the reflectivity is used. */
|
||||
PHONG,
|
||||
|
||||
/** The Blinn lighting model.
|
||||
This lighting model improves on the Lambert lighting model by
|
||||
calculating how much light is reflected by the polygons into the viewer's eye.
|
||||
For this calculation, the shininess, the specular color and the reflectivity is used. */
|
||||
BLINN,
|
||||
|
||||
/** Not a valid lighting model. */
|
||||
UNKNOWN
|
||||
};
|
||||
|
||||
private:
|
||||
LightingType type;
|
||||
FCDTextureList* textureBuckets;
|
||||
|
||||
// Common material parameter: Emission
|
||||
FMVector3 emissionColor;
|
||||
float emissionFactor; // Max-specific
|
||||
|
||||
// Common material parameter: Translucency
|
||||
FMVector3 translucencyColor;
|
||||
float translucencyFactor;
|
||||
|
||||
// Lambert material parameters
|
||||
FMVector3 diffuseColor;
|
||||
FMVector3 ambientColor;
|
||||
|
||||
// Phong material parameters: Specular
|
||||
FMVector3 specularColor;
|
||||
float specularFactor; // Max-specific
|
||||
float shininess;
|
||||
|
||||
// Phong material parameter: Reflectivity
|
||||
FMVector3 reflectivityColor; // Maya-specific
|
||||
float reflectivityFactor; // Maya-specific
|
||||
|
||||
// Geometry modifier
|
||||
bool isFaceted; // Max-specific
|
||||
bool isDoubleSided; // Max-specific for now
|
||||
bool isWireframe; // Max-specific
|
||||
bool isFaceMap; // Max-specific
|
||||
bool isEmissionFactor; // Max-specific
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly. Instead, use the FCDEffect::AddProfile function
|
||||
with the FUDaeProfileType::COMMON parameter.
|
||||
@param document The COLLADA document that owns this effect profile.
|
||||
@param parent The effect that contains this profile. */
|
||||
FCDEffectStandard(FCDocument* document, FCDEffect* parent);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDEffect::ReleaseProfile function. */
|
||||
virtual ~FCDEffectStandard();
|
||||
|
||||
/** Retrieves the lighting model to be used for this profile.
|
||||
@return The lighting model. */
|
||||
inline LightingType GetLightingType() const { return type; }
|
||||
|
||||
/** Sets the lighting model to be used for this profile.
|
||||
Note that which parameters are exported depends on the lighting model.
|
||||
@param _type The lighting model. */
|
||||
inline void SetLightingType(LightingType _type) { type = _type; }
|
||||
|
||||
/** Retrieves the profile type for this effect.
|
||||
This function is a part of the FCDEffectProfile interface and allows you
|
||||
to up-cast an effect profile pointer safely to this class.
|
||||
@return The profile type: COMMON. */
|
||||
virtual FUDaeProfileType::Type GetType() const { return FUDaeProfileType::COMMON; }
|
||||
|
||||
/** Retrieves the list of textures belonging to a specific channel.
|
||||
@param bucket A texture channel index. This index should match one
|
||||
of the values in the FUDaeTextureChannel enum.
|
||||
@return The list of textures for this channel. */
|
||||
const FCDTextureList& GetTextureBucket(uint32 bucket) const;
|
||||
|
||||
/** Retrieves the number of textures belonging to a specific channel.
|
||||
@param bucket A texture channel index. This index should match one
|
||||
of the values in the FUDaeTextureChannel enum.
|
||||
@return The number of textures in that channel. */
|
||||
size_t GetTextureCount(uint32 bucket) const { FUAssert(bucket < FUDaeTextureChannel::COUNT, return 0); return textureBuckets[bucket].size(); }
|
||||
|
||||
/** Retrieves a texture
|
||||
@param bucket A texture channel index. This index should match one
|
||||
of the values in the FUDaeTextureChannel enum.
|
||||
@param index The index of a texture within this channel.
|
||||
@return The texture. This pointer will be NULL if either the bucket or the index is out-of-bounds. */
|
||||
inline FCDTexture* GetTexture(uint32 bucket, size_t index) { FUAssert(index < GetTextureCount(bucket), return NULL); return textureBuckets[bucket].at(index); }
|
||||
inline const FCDTexture* GetTexture(uint32 bucket, size_t index) const { FUAssert(index < GetTextureCount(bucket), return NULL); return textureBuckets[bucket].at(index); } /**< See above. */
|
||||
|
||||
/** Adds a texture to a specific channel.
|
||||
@param bucket A texture channel index. This index should match one
|
||||
of the values in the FUDaeTextureChannel enum.
|
||||
@return The new texture. This pointer will be NULL if the bucket is out-of-bounds. */
|
||||
FCDTexture* AddTexture(uint32 bucket);
|
||||
|
||||
/** Releases a texture contained within this effect profile.
|
||||
@param texture The texture to release. */
|
||||
void ReleaseTexture(FCDTexture* texture);
|
||||
|
||||
/** Retrieves the base translucency color.
|
||||
This value must be multiplied with the translucency factor
|
||||
to get the real translucency color.
|
||||
This value is used in all lighting models.
|
||||
@return The base translucency color. */
|
||||
inline const FMVector3& GetTranslucencyColor() const { return translucencyColor; }
|
||||
|
||||
/** Sets the base translucency color.
|
||||
@param color The base translucency color. */
|
||||
inline void SetTranslucencyColor(const FMVector3& color) { translucencyColor = color; }
|
||||
|
||||
/** Retrieves the translucency factor.
|
||||
This value must be multiplied with the translucency color
|
||||
to get the real translucency color.
|
||||
This value is used in all lighting models.
|
||||
@return The translucency factor. */
|
||||
inline const float& GetTranslucencyFactor() const { return translucencyFactor; }
|
||||
|
||||
/** Sets the translucency factor.
|
||||
@param factor The translucency factor. */
|
||||
inline void SetTranslucencyFactor(float factor) { translucencyFactor = factor; }
|
||||
|
||||
/** Retrieves the flat opacity.
|
||||
This is a calculated value and will not take into consideration any animations
|
||||
that affect either the base translucency color or the translucency factor.
|
||||
This value can be used in all lighting models.
|
||||
@return The flat opacity. */
|
||||
float GetOpacity() const;
|
||||
|
||||
/** Retrieves the base emission/self-illumination color.
|
||||
This value must be multiplied with the emission factor to get the real emission color.
|
||||
This value is used in all lighting models.
|
||||
@return The base emission color. */
|
||||
inline const FMVector3& GetEmissionColor() const { return emissionColor; }
|
||||
|
||||
/** Sets the base emission/self-illumination color.
|
||||
@param color The base emission color. */
|
||||
inline void SetEmissionColor(const FMVector3& color) { emissionColor = color; }
|
||||
|
||||
/** Retrieves the emission/self-illumination factor.
|
||||
This value must be multiplied with the base emission color to get the real emission color.
|
||||
@return The emission factor. */
|
||||
inline const float& GetEmissionFactor() const { return emissionFactor; }
|
||||
|
||||
/** Sets the emission/self-illumination factor.
|
||||
@param factor The emission factor. */
|
||||
inline void SetEmissionFactor(float factor) { emissionFactor = factor; }
|
||||
|
||||
/** Retrieves whether the emission factor was used, rather than the emission color.
|
||||
This value is used in conjunction with 3dsMax, in which the self-illumination color
|
||||
and the self-illumination factor are mutually exclusive.
|
||||
@return Whether the emission factor is to be used. */
|
||||
inline bool IsEmissionFactor() const { return isEmissionFactor; }
|
||||
|
||||
/** Sets whether the emission factor is to be used, rather than the emission color.
|
||||
This value is used in conjunction with 3dsMax, in which the self-illumination color
|
||||
and the self-illumination factor are mutually exclusive.
|
||||
@param useFactor Whether the emission factor should be used. */
|
||||
inline void SetIsEmissionFactor(bool useFactor) { isEmissionFactor = useFactor; }
|
||||
|
||||
/** Retrieves the diffuse color.
|
||||
This value is used in the Lambert lighting model.
|
||||
@return The diffuse color. */
|
||||
inline const FMVector3& GetDiffuseColor() const { return diffuseColor; }
|
||||
|
||||
/** Sets the diffuse color.
|
||||
@param color The diffuse color. */
|
||||
inline void SetDiffuseColor(const FMVector3& color) { diffuseColor = color; }
|
||||
|
||||
/** Retrieves the ambient color.
|
||||
This value is used in the Lambert lighting model.
|
||||
@return The ambient color. */
|
||||
inline const FMVector3& GetAmbientColor() const { return ambientColor; }
|
||||
|
||||
/** Sets the ambient color.
|
||||
@param color The ambient color. */
|
||||
inline void SetAmbientColor(const FMVector3& color) { ambientColor = color; }
|
||||
|
||||
/** Retrieves the base specular color.
|
||||
This value must be multiplied with the specular factor
|
||||
to get the real specular color.
|
||||
This value is used in the Phong and Blinn lighting models.
|
||||
@return The specular color. */
|
||||
inline const FMVector3& GetSpecularColor() const { return specularColor; }
|
||||
|
||||
/** Sets the specular color.
|
||||
@param color The specular color. */
|
||||
inline void SetSpecularColor(const FMVector3& color) { specularColor = color; }
|
||||
|
||||
/** Retrieves the specular factor.
|
||||
This value must be multiplied with the base specular color
|
||||
to get the real specular color.
|
||||
This value is used in the Phong and Blinn lighting models.
|
||||
@return The specular factor. */
|
||||
inline const float& GetSpecularFactor() const { return specularFactor; }
|
||||
|
||||
/** Sets the specular factor.
|
||||
@param factor The specular factor. */
|
||||
inline void SetSpecularFactor(float factor) { specularFactor = factor; }
|
||||
|
||||
/** Retrieves the specular shininess.
|
||||
This value represents the exponent to which you must raise
|
||||
the dot-product between the view vector and reflected light vectors:
|
||||
as such, it is usually a number greater than 1.
|
||||
This value is used in the Phong and Blinn lighting models.
|
||||
@return The specular shininess. */
|
||||
inline const float& GetShininess() const { return shininess; }
|
||||
|
||||
/** Sets the specular shininess.
|
||||
This value represents the exponent to which you must raise
|
||||
the dot-product between the view vector and reflected light vectors:
|
||||
as such, it is usually a number greater than 1.
|
||||
@param _shininess The specular shininess. */
|
||||
inline void SetShininess(float _shininess) { shininess = _shininess; }
|
||||
|
||||
/** Retrieves the base reflectivity color.
|
||||
This value must be multiplied to the reflectivity factor to
|
||||
get the real reflectivity color.
|
||||
This value is used in the Phong and Blinn lighting models.
|
||||
@return The base reflectivity color. */
|
||||
inline const FMVector3& GetReflectivityColor() const { return reflectivityColor; }
|
||||
|
||||
/** Sets the base reflectivity color.
|
||||
@param color The base reflectivity color. */
|
||||
inline void SetReflectivityColor(const FMVector3& color) { reflectivityColor = color; }
|
||||
|
||||
/** Retrieves the reflectivity factor.
|
||||
This value must be multiplied to the base reflectivity color
|
||||
to get the real reflectivity color.
|
||||
This value is used in the Phong and Blinn lighting models.
|
||||
@return The reflectivity factor. */
|
||||
inline const float& GetReflectivityFactor() const { return reflectivityFactor; }
|
||||
|
||||
/** Sets the reflectivity factor.
|
||||
@param factor The reflectivity factor. */
|
||||
inline void SetReflectivityFactor(float factor) { reflectivityFactor = factor; }
|
||||
|
||||
/** Retrieves the flat reflectivity.
|
||||
This is a calculated value and will not take into consideration any animations
|
||||
that affect either the base reflectivity color or the reflectivity factor.
|
||||
This value can be used in the Phong and Blinn lighting models.
|
||||
@return The flat reflectivity. */
|
||||
float GetReflectivity() const;
|
||||
|
||||
/** Retrieves the 'faceted' flag.
|
||||
This flag is used in conjunction with 3dsMax. It represents whether all the edges
|
||||
of the polygon sets using this effect profile should be hard. The final result
|
||||
of using this flag is a mesh where all the faces stand out.
|
||||
@return The status of the 'faceted' flag. */
|
||||
inline bool GetFacetedFlag() const { return isFaceted; }
|
||||
|
||||
/** Sets the 'faceted' flag.
|
||||
This flag is used in conjunction with 3dsMax. It represents whether all the edges
|
||||
of the polygon sets using this effect profile should be hard. The final result
|
||||
of using this flag is a mesh where all the faces stand out.
|
||||
@param flag The status of the 'faceted' flag. */
|
||||
inline void SetFacetedFlag(bool flag) { isFaceted = flag; }
|
||||
|
||||
/** Retrieves the 'double-sided' flag.
|
||||
This flag is used in conjunction with 3dsMax. It represents whether all the faces
|
||||
of the polygon sets should be treated as two-sided and have normals in both directions.
|
||||
@return The status of the 'double-sided' flag. */
|
||||
inline bool GetDoubleSidedFlag() const { return isDoubleSided; }
|
||||
|
||||
/** Sets the 'double-sided' flag.
|
||||
This flag is used in conjunction with 3dsMax. It represents whether all the faces
|
||||
of the polygon sets should be treated as two-sided and have normals in both directions.
|
||||
@param flag The status of the 'double-sided' flag. */
|
||||
inline bool SetDoubleSidedFlag(bool flag) { isDoubleSided = flag; }
|
||||
|
||||
/** Retrieves the 'wireframe' flag.
|
||||
This flag is used in conjunction with 3dsMax. It represents whether all the edges
|
||||
of the polygon sets should be rendered, rather than the faces.
|
||||
@return The status of the 'wireframe' flag. */
|
||||
inline bool GetWireframeFlag() const { return isWireframe; }
|
||||
|
||||
/** Sets the 'wireframe' flag.
|
||||
This flag is used in conjunction with 3dsMax. It represents whether all the edges
|
||||
of the polygon sets should be rendered, rather than the faces.
|
||||
@param flag The status of the 'wireframe' flag. */
|
||||
inline bool SetWireframeFlag(bool flag) { isWireframe = flag; }
|
||||
|
||||
/** Retrieves the 'face-map' flag.
|
||||
This is a pure 3dsMax flag and I have no idea what it does.
|
||||
@return The status of the 'face-map' flag. */
|
||||
inline bool GetFaceMapFlag() const { return isFaceMap; }
|
||||
|
||||
/** Sets the 'face-map' flag.
|
||||
This is a pure 3dsMax flag and I have no idea what it does.
|
||||
@param flag The status of the 'face-map' flag. */
|
||||
inline void SetFaceMapFlag(bool flag) { isFaceMap = flag; }
|
||||
|
||||
/** Retrieves an effect parameter.
|
||||
Looks for the effect parameter with the correct semantic, in order to bind or override its value.
|
||||
This function searches through the effect profile and the level of abstractions below.
|
||||
@param semantic The effect parameter semantic to match.
|
||||
@return The effect parameter that matches the semantic. This pointer may be
|
||||
NULL if no effect parameter matches the given semantic. */
|
||||
virtual FCDEffectParameter* FindParameterBySemantic(const string& semantic);
|
||||
|
||||
/** Retrieves a subset of the effect parameter list.
|
||||
Look for effect parameters with the correct semantic.
|
||||
This function searches through the effect profile and the level of abstractions below.
|
||||
@param semantic The effect parameter semantic to match.
|
||||
@param parameters The list of parameters to fill in. This list is not cleared. */
|
||||
virtual void FindParametersBySemantic(const string& semantic, FCDEffectParameterList& parameters);
|
||||
|
||||
/** Retrieves a subset of the effect parameter list.
|
||||
Look for effect parameters with the correct reference.
|
||||
This function searches through the effect profile and the level of abstractions below.
|
||||
@param reference The effect parameter reference to match. In the case of effect
|
||||
parameter, the reference is replaced by the sub-id.
|
||||
@param parameters The list of parameters to fill in. This list is not cleared. */
|
||||
virtual void FindParametersByReference(const string& reference, FCDEffectParameterList& parameters);
|
||||
|
||||
/** [INTERNAL] Clones the COMMON profile effect.
|
||||
You will need release the cloned effect directly, by deleting the pointer.
|
||||
@param newParent The effect that contains the cloned effect profile.
|
||||
@return The cloned effect profile. You will must delete this pointer. */
|
||||
virtual FCDEffectProfile* Clone(FCDEffect* newParent);
|
||||
|
||||
/** [INTERNAL] Flattens the profile.
|
||||
Does nothing on the common profile. */
|
||||
virtual void Flatten() {}
|
||||
|
||||
/** [INTERNAL] Reads in the \<profile_COMMON\> element from a given COLLADA XML tree node.
|
||||
For COLLADA 1.3 backward-compatibility, this function can also read in \<material\> elements.
|
||||
@param baseNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the effect profile.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* baseNode);
|
||||
|
||||
/** [INTERNAL] Writes out the \<profile_COMMON\> element to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the effect profile.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
|
||||
private:
|
||||
xmlNode* WriteColorTextureParameterToXML(xmlNode* parentNode, const char* parameterNodeName, const FMVector3& value, const FCDTextureList& textureBucket) const;
|
||||
xmlNode* WriteFloatTextureParameterToXML(xmlNode* parentNode, const char* parameterNodeName, const float& value, const FCDTextureList& textureBucket) const;
|
||||
xmlNode* WriteTextureParameterToXML(xmlNode* parentNode, const FCDTextureList& textureBucket) const;
|
||||
|
||||
FUStatus ParseColorTextureParameter(xmlNode* parameterNode, FMVector3& value, FCDTextureList& textureBucket);
|
||||
FUStatus ParseFloatTextureParameter(xmlNode* parameterNode, float& value, FCDTextureList& textureBucket);
|
||||
FUStatus ParseSimpleTextureParameter(xmlNode* parameterNode, FCDTextureList& textureBucket);
|
||||
};
|
||||
|
||||
#endif //_FCD_MATERIAL_STANDARD_H_
|
||||
|
||||
@@ -1,254 +0,0 @@
|
||||
/*
|
||||
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/FCDEffectCode.h"
|
||||
#include "FCDocument/FCDEffectPass.h"
|
||||
#include "FCDocument/FCDEffectProfileFX.h"
|
||||
#include "FCDocument/FCDEffectParameter.h"
|
||||
#include "FCDocument/FCDEffectParameterFactory.h"
|
||||
#include "FCDocument/FCDEffectParameterList.h"
|
||||
#include "FCDocument/FCDEffectTechnique.h"
|
||||
#include "FCDocument/FCDLibrary.h"
|
||||
#include "FCDocument/FCDImage.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDEffectTechnique::FCDEffectTechnique(FCDocument* document, FCDEffectProfileFX *_parent) : FCDObject(document, "FCDEffectTechnique")
|
||||
{
|
||||
parent = _parent;
|
||||
parameters = new FCDEffectParameterList(GetDocument(), true);;
|
||||
}
|
||||
|
||||
FCDEffectTechnique::~FCDEffectTechnique()
|
||||
{
|
||||
CLEAR_POINTER_VECTOR(codes);
|
||||
CLEAR_POINTER_VECTOR(passes);
|
||||
SAFE_DELETE(parameters);
|
||||
parent = NULL;
|
||||
}
|
||||
|
||||
// Adds a new pass to this effect technique.
|
||||
FCDEffectPass* FCDEffectTechnique::AddPass()
|
||||
{
|
||||
FCDEffectPass* pass = new FCDEffectPass(GetDocument(), this);
|
||||
passes.push_back(pass);
|
||||
return pass;
|
||||
}
|
||||
|
||||
// Releases a pass contaied within this effect technique.
|
||||
void FCDEffectTechnique::ReleasePass(FCDEffectPass* pass)
|
||||
{
|
||||
FCDEffectPassList::iterator it = std::find(passes.begin(), passes.end(), pass);
|
||||
if (it != passes.end())
|
||||
{
|
||||
delete *it;
|
||||
passes.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a new code inclusion to this effect profile.
|
||||
FCDEffectCode* FCDEffectTechnique::AddCode()
|
||||
{
|
||||
FCDEffectCode* code = new FCDEffectCode(GetDocument());
|
||||
codes.push_back(code);
|
||||
return code;
|
||||
}
|
||||
|
||||
// Releases a code inclusion contained within this effect profile.
|
||||
void FCDEffectTechnique::ReleaseCode(FCDEffectCode* code)
|
||||
{
|
||||
FCDEffectCodeList::iterator itC = std::find(codes.begin(), codes.end(), code);
|
||||
if (itC != codes.end())
|
||||
{
|
||||
delete *itC;
|
||||
codes.erase(itC);
|
||||
}
|
||||
}
|
||||
|
||||
FCDEffectTechnique* FCDEffectTechnique::Clone(FCDEffectProfileFX* newParent)
|
||||
{
|
||||
FCDEffectTechnique* clone = new FCDEffectTechnique(GetDocument(), newParent);
|
||||
clone->name = name;
|
||||
SAFE_DELETE(clone->parameters);
|
||||
clone->parameters = parameters->Clone();
|
||||
|
||||
// Clone the codes: need to happen before the passes are cloned
|
||||
clone->codes.reserve(codes.size());
|
||||
for (FCDEffectCodeList::const_iterator itC = codes.begin(); itC != codes.end(); ++itC)
|
||||
{
|
||||
clone->codes.push_back((*itC)->Clone());
|
||||
}
|
||||
|
||||
// Clone the passes
|
||||
for (FCDEffectPassList::iterator itP = passes.begin(); itP != passes.end(); ++itP)
|
||||
{
|
||||
clone->passes.push_back((*itP)->Clone(clone));
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
const string& FCDEffectTechnique::GetDaeId() const
|
||||
{
|
||||
return parent->GetDaeId();
|
||||
}
|
||||
|
||||
void FCDEffectTechnique::AddParameter(FCDEffectParameter* parameter)
|
||||
{
|
||||
parameters->push_back(parameter);
|
||||
}
|
||||
|
||||
// Flatten this effect technique: merge the parameter modifiers and generators
|
||||
void FCDEffectTechnique::Flatten()
|
||||
{
|
||||
for (FCDEffectParameterList::iterator itP = parameters->begin(); itP != parameters->end();)
|
||||
{
|
||||
FCDEffectParameterList generators(GetDocument());
|
||||
if ((*itP)->IsModifier())
|
||||
{
|
||||
// Overwrite the generators
|
||||
FindParametersByReference((*itP)->GetReference(), generators);
|
||||
for (FCDEffectParameterList::iterator itQ = generators.begin(); itQ != generators.end(); ++itQ)
|
||||
{
|
||||
if ((*itQ)->IsGenerator())
|
||||
{
|
||||
(*itP)->Overwrite(*itQ);
|
||||
}
|
||||
}
|
||||
SAFE_DELETE(*itP);
|
||||
parameters->erase(itP);
|
||||
}
|
||||
else
|
||||
{
|
||||
++itP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FUStatus FCDEffectTechnique::LoadFromXML(xmlNode* techniqueNode, xmlNode* profileNode)
|
||||
{
|
||||
FUStatus status;
|
||||
if (!IsEquivalent(techniqueNode->name, DAE_TECHNIQUE_ELEMENT))
|
||||
{
|
||||
return status.Warning(FS("Technique contains unknown element."), techniqueNode->line);
|
||||
}
|
||||
|
||||
string techniqueName = ReadNodeProperty(techniqueNode, DAE_SID_ATTRIBUTE);
|
||||
name = TO_FSTRING(techniqueName);
|
||||
|
||||
// Look for the pass and parameter elements
|
||||
SAFE_DELETE(parameters);
|
||||
parameters = new FCDEffectParameterList(GetDocument(), true);
|
||||
for (xmlNode* child = techniqueNode->children; child != NULL; child = child->next)
|
||||
{
|
||||
if (child->type != XML_ELEMENT_NODE) continue;
|
||||
|
||||
if (IsEquivalent(child->name, DAE_PASS_ELEMENT))
|
||||
{
|
||||
FCDEffectPass* pass = AddPass();
|
||||
status.AppendStatus(pass->LoadFromXML(child, techniqueNode, profileNode));
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_NEWPARAM_ELEMENT) || IsEquivalent(child->name, DAE_FXCMN_SETPARAM_ELEMENT))
|
||||
{
|
||||
AddParameter(FCDEffectParameterFactory::LoadFromXML(GetDocument(), child, &status));
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_CODE_ELEMENT) || IsEquivalent(child->name, DAE_FXCMN_INCLUDE_ELEMENT))
|
||||
{
|
||||
FCDEffectCode* code = new FCDEffectCode(GetDocument());
|
||||
codes.push_back(code);
|
||||
status.AppendStatus(code->LoadFromXML(child));
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_IMAGE_ELEMENT))
|
||||
{
|
||||
FCDImage* image = GetDocument()->GetImageLibrary()->AddEntity();
|
||||
status.AppendStatus(image->LoadFromXML(child));
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out the effect techniques to the COLLADA xml node tree
|
||||
xmlNode* FCDEffectTechnique::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* techniqueNode = AddChild(parentNode, DAE_TECHNIQUE_ELEMENT);
|
||||
const_cast<FCDEffectTechnique*>(this)->name = TO_FSTRING(AddNodeSid(techniqueNode, !name.empty() ? TO_STRING(name).c_str() : "common"));
|
||||
|
||||
// Write out the code/includes
|
||||
for (FCDEffectCodeList::const_iterator itC = codes.begin(); itC != codes.end(); ++itC)
|
||||
{
|
||||
(*itC)->WriteToXML(techniqueNode);
|
||||
}
|
||||
|
||||
// Write out the effect parameters at this level
|
||||
for (FCDEffectParameterList::const_iterator itP = parameters->begin(); itP != parameters->end(); ++itP)
|
||||
{
|
||||
(*itP)->WriteToXML(techniqueNode);
|
||||
}
|
||||
|
||||
// Write out the passes.
|
||||
// In COLLADA 1.4: there should always be at least one pass.
|
||||
if (!passes.empty())
|
||||
{
|
||||
for (FCDEffectPassList::const_iterator itP = passes.begin(); itP != passes.end(); ++itP)
|
||||
{
|
||||
(*itP)->WriteToXML(techniqueNode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UNUSED(xmlNode* dummyPassNode =) AddChild(techniqueNode, DAE_PASS_ELEMENT);
|
||||
}
|
||||
|
||||
return techniqueNode;
|
||||
}
|
||||
|
||||
// Look for the parameter with the given reference.
|
||||
const FCDEffectParameter* FCDEffectTechnique::FindParameter(const char* ref) const
|
||||
{
|
||||
return parameters->FindReference(ref);
|
||||
}
|
||||
|
||||
// Look for the effect parameter with the correct semantic, in order to bind/set its value
|
||||
FCDEffectParameter* FCDEffectTechnique::FindParameterBySemantic(const string& semantic)
|
||||
{
|
||||
return parameters->FindSemantic(semantic);
|
||||
}
|
||||
|
||||
void FCDEffectTechnique::FindParametersBySemantic(const string& semantic, FCDEffectParameterList& _parameters)
|
||||
{
|
||||
for (FCDEffectParameterList::iterator it = parameters->begin(); it != parameters->end(); ++it)
|
||||
{
|
||||
if ((*it)->GetSemantic() == semantic) _parameters.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
void FCDEffectTechnique::FindParametersByReference(const string& reference, FCDEffectParameterList& _parameters)
|
||||
{
|
||||
for (FCDEffectParameterList::iterator it = parameters->begin(); it != parameters->end(); ++it)
|
||||
{
|
||||
if ((*it)->GetReference() == reference) _parameters.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
FCDEffectCode* FCDEffectTechnique::FindCode(const string& sid)
|
||||
{
|
||||
for (FCDEffectCodeList::iterator itC = codes.begin(); itC != codes.end(); ++itC)
|
||||
{
|
||||
if ((*itC)->GetSid() == sid) return (*itC);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
const FCDEffectCode* FCDEffectTechnique::FindCode(const string& sid) const
|
||||
{
|
||||
for (FCDEffectCodeList::const_iterator itC = codes.begin(); itC != codes.end(); ++itC)
|
||||
{
|
||||
if ((*itC)->GetSid() == sid) return (*itC);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,195 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDEffectTechnique.h
|
||||
This file declares the FCDEffectTechnique class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_EFFECT_TECHNIQUE_H_
|
||||
#define _FCD_EFFECT_TECHNIQUE_H_
|
||||
|
||||
#include "FCDocument/FCDObject.h"
|
||||
|
||||
class FCDEffectCode;
|
||||
class FCDEffectPass;
|
||||
class FCDEffectParameter;
|
||||
class FCDEffectParameterList;
|
||||
class FCDEffectProfileFX;
|
||||
|
||||
typedef vector<FCDEffectPass*> FCDEffectPassList; /**< A dynamically-sized array of effect passes. */
|
||||
typedef vector<FCDEffectCode*> FCDEffectCodeList; /**< A dynamically-sized array of effect code inclusions. */
|
||||
|
||||
/**
|
||||
A COLLADA effect technique.
|
||||
|
||||
The COLLADA effect technique contains the passes to be used in the rendering of
|
||||
polygon sets.
|
||||
|
||||
It also contains a list of effect parameters: both generators and overrides
|
||||
and it is the lowest level of abstraction in which you can access effect parameters. For
|
||||
flattened materials, this means that all the effect parameters will be accessible at this level.
|
||||
|
||||
It also contains a list of effect code inclusions.
|
||||
|
||||
@ingroup FCDEffect
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDEffectTechnique : public FCDObject
|
||||
{
|
||||
private:
|
||||
FCDEffectProfileFX* parent;
|
||||
|
||||
fstring name;
|
||||
FCDEffectCodeList codes;
|
||||
FCDEffectPassList passes;
|
||||
FCDEffectParameterList* parameters;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDEffectProfileFX::AddTechnique function.
|
||||
@param document The COLLADA document which owns this technique.
|
||||
@param _parent The effect profile which contains the technique. */
|
||||
FCDEffectTechnique(FCDocument* document, FCDEffectProfileFX *_parent);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDEffectProfileFX::ReleaseTechnique function. */
|
||||
virtual ~FCDEffectTechnique();
|
||||
|
||||
/** Retrieves the effect profile that contains this technique.
|
||||
@return The parent effect profile. */
|
||||
FCDEffectProfileFX* GetParent() { return parent; }
|
||||
const FCDEffectProfileFX* GetParent() const { return parent; } /**< See above. */
|
||||
|
||||
/** Retrieves the COLLADA id of the parent effect.
|
||||
This function is mostly useful as a shortcut for debugging and reporting.
|
||||
@return The COLLADA id of the parent effect. */
|
||||
const string& GetDaeId() const;
|
||||
|
||||
/** Retrieves the sub-id of the technique.
|
||||
@return The sub-id of the technique. */
|
||||
const fstring& GetName() const { return name; }
|
||||
|
||||
/** Sets the sub-id of the technique.
|
||||
The effect technique must have a valid sub-id that is unique
|
||||
within its scope. Otherwise, one will be provided on XML export.
|
||||
@param _name A valid sub-id. */
|
||||
void SetName(const fstring& _name) { name = _name; }
|
||||
|
||||
/** Retrieves the list of passes.
|
||||
@return The list of passes. */
|
||||
FCDEffectPassList& GetPassList() { return passes; }
|
||||
const FCDEffectPassList& GetPassList() const { return passes; } /**< See above. */
|
||||
|
||||
/** Retrieves the number of passes contained within this effect technique.
|
||||
@return The number of passes. */
|
||||
size_t GetPassCount() const { return passes.size(); }
|
||||
|
||||
/** Retrieves a specific pass contained within this effect technique.
|
||||
@param index The index of the pass.
|
||||
@return The pass. This pointer will be NULL if the index is out-of-bounds. */
|
||||
FCDEffectPass* GetPass(size_t index) { FUAssert(index < GetPassCount(), return NULL); return passes.at(index); }
|
||||
const FCDEffectPass* GetPass(size_t index) const { FUAssert(index < GetPassCount(), return NULL); return passes.at(index); } /**< See above. */
|
||||
|
||||
/** Adds a new pass to this effect technique.
|
||||
@return The new pass. */
|
||||
FCDEffectPass* AddPass();
|
||||
|
||||
/** Releases a pass contaied within this effect technique.
|
||||
@param pass The pass to release. */
|
||||
void ReleasePass(FCDEffectPass* pass);
|
||||
|
||||
/** Retrieves the list of code inclusions.
|
||||
@return The list of code inclusions. */
|
||||
FCDEffectCodeList& GetCodeList() { return codes; }
|
||||
const FCDEffectCodeList& GetCodeList() const { return codes; } /**< See above. */
|
||||
|
||||
/** Retrieves the number of code inclusions contained within the effect profile.
|
||||
@return The number of code inclusions. */
|
||||
size_t GetCodeCount() const { return codes.size(); }
|
||||
|
||||
/** Retrieves a code inclusion contained within the effect profile.
|
||||
@param index The index of the code inclusion.
|
||||
@return The code inclusion. This pointer will be NULL if the index is out-of-bounds. */
|
||||
FCDEffectCode* GetCode(size_t index) { FUAssert(index < GetCodeCount(), return NULL); return codes.at(index); }
|
||||
const FCDEffectCode* GetCode(size_t index) const { FUAssert(index < GetCodeCount(), return NULL); return codes.at(index); } /**< See above. */
|
||||
|
||||
/** Retrieves the code inclusion with the given sub-id.
|
||||
@param sid A COLLADA sub-id.
|
||||
@return The code inclusion with the given sub-id. This pointer will be NULL,
|
||||
if there are no code inclusions that match the given sub-id. */
|
||||
FCDEffectCode* FindCode(const string& sid);
|
||||
const FCDEffectCode* FindCode(const string& sid) const; /**< See above. */
|
||||
|
||||
/** Adds a new code inclusion to this effect profile.
|
||||
@return The new code inclusion. */
|
||||
FCDEffectCode* AddCode();
|
||||
|
||||
/** Releases a code inclusion contained within this effect profile.
|
||||
@param code The code inclusion to release. */
|
||||
void ReleaseCode(FCDEffectCode* code);
|
||||
|
||||
/** Retrieves the list of effect parameters contained within the effect profile.
|
||||
This is the lowest level of abstraction and may contain either effect parameter
|
||||
generators or effect parameter overrides.
|
||||
@return The list of effect parameters. */
|
||||
FCDEffectParameterList* GetParameterList() { return parameters; }
|
||||
const FCDEffectParameterList* GetParameterList() const { return parameters; } /**< See above. */
|
||||
|
||||
/** [INTERNAL] Inserts an existing parameter into the list of effect parameters
|
||||
at this abstraction level. This function is used during the flattening of a material.
|
||||
@param parameter The effect parameter to insert. */
|
||||
void AddParameter(FCDEffectParameter* parameter);
|
||||
|
||||
/** Retrieves an effect parameter.
|
||||
Looks for the effect parameter with the correct reference, in order to bind or override its value.
|
||||
@param reference The reference to match. In the case of effect parameter generators,
|
||||
the sub-id is used to match.
|
||||
@return The first effect parameter that matches the reference.
|
||||
This pointer will be NULL if no effect parameter matches the given semantic. */
|
||||
const FCDEffectParameter* FindParameter(const char* reference) const;
|
||||
|
||||
/** Retrieves an effect parameter.
|
||||
Looks for the effect parameter with the correct semantic, in order to bind or override its value.
|
||||
@param semantic The effect parameter semantic to match.
|
||||
@return The first effect parameter that matches the semantic.
|
||||
This pointer will be NULL if no effect parameter matches the given semantic. */
|
||||
virtual FCDEffectParameter* FindParameterBySemantic(const string& semantic);
|
||||
|
||||
/** Retrieves a subset of the effect parameter list.
|
||||
Look for the effect parameter generators with the correct semantic.
|
||||
@param semantic The effect parameter semantic to match.
|
||||
@param parameters The list of parameters to fill in. This list is not cleared. */
|
||||
virtual void FindParametersBySemantic(const string& semantic, FCDEffectParameterList& parameters);
|
||||
|
||||
/** Retrieves a subset of the effect parameter list.
|
||||
Look for the effect parameter generators with the correct reference.
|
||||
@param reference The effect parameter reference to match. In the case of effect
|
||||
parameter generators, the reference is replaced by the sub-id.
|
||||
@param parameters The list of parameters to fill in. This list is not cleared. */
|
||||
virtual void FindParametersByReference(const string& reference, FCDEffectParameterList& parameters);
|
||||
|
||||
/** [INTERNAL] Clones the full effect technique.
|
||||
@param newParent The effect profile that will contain the cloned technique.
|
||||
@return The cloned technique. This pointer will never be NULL. */
|
||||
FCDEffectTechnique* Clone(FCDEffectProfileFX* newParent);
|
||||
|
||||
/** [INTERNAL] Flattens this effect technique.
|
||||
Merges the parameter overrides into the parameter generators. */
|
||||
void Flatten();
|
||||
|
||||
/** [INTERNAL] Reads in the effect technique from a given COLLADA XML tree node.
|
||||
@param techniqueNode The COLLADA XML tree node.
|
||||
@param profileNode X @deprecated bad interface : this dependency must be taken out.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the effect technique.*/
|
||||
FUStatus LoadFromXML(xmlNode* techniqueNode, xmlNode* profileNode);
|
||||
|
||||
/** [INTERNAL] Writes out the effect technique to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the effect technique.
|
||||
@return The created element XML tree node. */
|
||||
xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDEntity.h"
|
||||
#include "FCDocument/FCDExtra.h"
|
||||
#include "FCDocument/FCDSceneNode.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
#include "FUtils/FUUniqueStringMap.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDEntity::FCDEntity(FCDocument* document, const char* baseId) : FCDObjectWithId(document, baseId)
|
||||
{
|
||||
extra = new FCDExtra(document);
|
||||
}
|
||||
|
||||
FCDEntity::~FCDEntity()
|
||||
{
|
||||
SAFE_DELETE(extra);
|
||||
}
|
||||
|
||||
// Structure cloning
|
||||
void FCDEntity::Clone(FCDEntity* clone)
|
||||
{
|
||||
FCDObjectWithId::Clone(clone);
|
||||
clone->name = name;
|
||||
clone->note = note;
|
||||
}
|
||||
|
||||
void FCDEntity::SetName(const fstring& _name)
|
||||
{
|
||||
name = CleanName(_name);
|
||||
}
|
||||
|
||||
// Parse this entity information from the COLLADA XML document
|
||||
FUStatus FCDEntity::LoadFromXML(xmlNode* entityNode)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
string fileId = FUDaeParser::ReadNodeId(entityNode);
|
||||
if (!fileId.empty()) SetDaeId(fileId);
|
||||
else RemoveDaeId();
|
||||
|
||||
name = TO_FSTRING(FUDaeParser::ReadNodeName(entityNode));
|
||||
if (name.empty()) name = TO_FSTRING(fileId);
|
||||
|
||||
xmlNode* extraNode = FindChildByType(entityNode, DAE_EXTRA_ELEMENT);
|
||||
if (extraNode != NULL)
|
||||
{
|
||||
extra->LoadFromXML(extraNode);
|
||||
|
||||
// Look for an extra node at this level and a Max/Maya-specific technique
|
||||
FCDETechnique* mayaTechnique = extra->FindTechnique(DAEMAYA_MAYA_PROFILE);
|
||||
FCDETechnique* maxTechnique = extra->FindTechnique(DAEMAX_MAX_PROFILE);
|
||||
|
||||
// Read in all the extra parameters
|
||||
StringList parameterNames;
|
||||
FCDENodeList parameterNodes;
|
||||
if (mayaTechnique != NULL) mayaTechnique->FindParameters(parameterNodes, parameterNames);
|
||||
if (maxTechnique != NULL) maxTechnique->FindParameters(parameterNodes, parameterNames);
|
||||
|
||||
// Look for the note and user-properties, which is the only parameter currently supported at this level
|
||||
size_t parameterCount = parameterNodes.size();
|
||||
for (size_t i = 0; i < parameterCount; ++i)
|
||||
{
|
||||
FCDENode* parameterNode = parameterNodes[i];
|
||||
const string& parameterName = parameterNames[i];
|
||||
|
||||
if (parameterName == DAEMAX_USERPROPERTIES_NODE_PARAMETER || parameterName == DAEMAYA_NOTE_PARAMETER
|
||||
|| parameterName == DAEMAX_USERPROPERTIES_NODE_PARAMETER1_3 || parameterName == DAEMAYA_MAYA_NOTE_PARAMETER1_3)
|
||||
{
|
||||
note = parameterNode->GetContent();
|
||||
parameterNode->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Look for a children with the given COLLADA Id.
|
||||
FCDEntity* FCDEntity::FindDaeId(const string& _daeId)
|
||||
{
|
||||
if (GetDaeId() == _daeId) return this;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xmlNode* FCDEntity::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
return WriteToEntityXML(parentNode, DAEERR_UNKNOWN_ELEMENT);
|
||||
}
|
||||
|
||||
xmlNode* FCDEntity::WriteToEntityXML(xmlNode* parentNode, const char* nodeName) const
|
||||
{
|
||||
// Create the entity node and write out the id and name attributes
|
||||
xmlNode* entityNode = AddChild(parentNode, nodeName);
|
||||
AddAttribute(entityNode, DAE_ID_ATTRIBUTE, GetDaeId());
|
||||
if (!name.empty())
|
||||
{
|
||||
AddAttribute(entityNode, DAE_NAME_ATTRIBUTE, name);
|
||||
}
|
||||
|
||||
return entityNode;
|
||||
}
|
||||
|
||||
void FCDEntity::WriteToExtraXML(xmlNode* entityNode) const
|
||||
{
|
||||
// Write out the note
|
||||
if (HasNote())
|
||||
{
|
||||
xmlNode* techniqueNode = AddExtraTechniqueChild(entityNode, DAEMAX_MAX_PROFILE);
|
||||
AddChild(techniqueNode, DAEMAX_USERPROPERTIES_NODE_PARAMETER, note);
|
||||
}
|
||||
|
||||
// Write out the user-defined extra information.
|
||||
extra->WriteToXML(entityNode);
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDEntity.h
|
||||
This file contains the FCDEntity class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_ENTITY_H_
|
||||
#define _FCD_ENTITY_H_
|
||||
|
||||
#include "FCDocument/FCDObject.h"
|
||||
|
||||
class FCDocument;
|
||||
class FCDExtra;
|
||||
|
||||
/**
|
||||
A COLLADA entity.
|
||||
|
||||
A COLLADA entity is an object contained within a COLLADA library.
|
||||
As such, it is based on the FCDObjectWithId class so that it
|
||||
can be accessed by other entities, such as the scene graph.
|
||||
|
||||
The entity adds to the FCDObjectWithId class: a name,
|
||||
an extra tree and an optional note, as well as a way
|
||||
to identity the type of the entity, in order to up-cast it
|
||||
to its correct class.
|
||||
|
||||
@ingroup FCDocument
|
||||
*/
|
||||
|
||||
class FCOLLADA_EXPORT FCDEntity : public FCDObjectWithId
|
||||
{
|
||||
public:
|
||||
/** The types of entity classes.
|
||||
Each type corresponds directly to one class that contains the
|
||||
FCDEntity class as a parent, so you can up-cast FCDEntity pointers. */
|
||||
enum Type
|
||||
{
|
||||
ENTITY, /**< A generic entity (FCDEntity). Should never be used. */
|
||||
ANIMATION, /**< An animation (FCDAnimation). */
|
||||
ANIMATION_CLIP, /**< An animation clip (FCDAnimationClip). */
|
||||
CAMERA, /**< A camera (FCDCamera). */
|
||||
LIGHT, /**< A light (FCDLight). */
|
||||
IMAGE, /**< An image (FCDImage). */
|
||||
TEXTURE, /**< A texture (FCDTexture). Used for COLLADA 1.3 backward compatibility only! */
|
||||
MATERIAL, /**< A visual material definition (FCDMaterial). */
|
||||
EFFECT, /**< An effect definition (FCDEffect). */
|
||||
GEOMETRY, /**< A geometric object (FCDGeometry). Includes splines and meshes. */
|
||||
CONTROLLER, /**< A geometric controller (FCDController). Includes skins and morphers. */
|
||||
SCENE_NODE, /**< A visual scene node (FCDSceneNode). */
|
||||
PHYSICS_RIGID_CONSTRAINT, /**< A physics rigid constraint (FCDPhysicsRigidConstraint). */
|
||||
PHYSICS_MATERIAL, /**< A physics material definiton (FCDPhysicsMaterial). */
|
||||
PHYSICS_RIGID_BODY, /**< A physics rigid body (FCDPhysicsRigidBody). */
|
||||
PHYSICS_SHAPE, /**< A physics shape (FCDPhysicsShape). */
|
||||
PHYSICS_ANALYTICAL_GEOMETRY, /**< A physics analytical geometric object (FCDPhysicsAnalyticalGeometry). */
|
||||
PHYSICS_MODEL, /**< A physics model (FCDPhysicsModel). */
|
||||
PHYSICS_SCENE_NODE /**< A physics scene node (FCDPhysicsSceneNode). */
|
||||
};
|
||||
|
||||
private:
|
||||
fstring name;
|
||||
|
||||
// Extra information for the entity.
|
||||
FCDExtra* extra;
|
||||
|
||||
// Maya and Max both support custom strings for objects.
|
||||
fstring note;
|
||||
|
||||
// Deprecated ColladaMaya post-processing information.
|
||||
StringList postCmds;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, create objects of the up-classes.
|
||||
@param document The COLLADA document that owns the entity.
|
||||
@param baseId The prefix COLLADA id to be used if no COLLADA id is provided. */
|
||||
FCDEntity(FCDocument* document, const char* baseId = "GenericEntity");
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, release objects through their libraries or their parent entities. */
|
||||
virtual ~FCDEntity();
|
||||
|
||||
/** Retrieves the entity class type for an entity.
|
||||
You can use the entity class type of up-cast an entity pointer
|
||||
to the correct up-class.
|
||||
This function should be overwritten by all up-classes.
|
||||
@return The entity class type. */
|
||||
virtual Type GetType() const { return ENTITY; }
|
||||
|
||||
/** Retrieves the name of the entity.
|
||||
This value has no direct use in COLLADA but is useful
|
||||
to track the user-friendly name of an entity.
|
||||
@return The name. */
|
||||
const fstring& GetName() const { return name; }
|
||||
|
||||
/** Sets the name of the entity.
|
||||
This value has no direct use in COLLADA but is useful
|
||||
to track the user-friendly name of an entity.
|
||||
@param _name The name. */
|
||||
void SetName(const fstring& _name);
|
||||
|
||||
/** Retrieves the extra information tree for this entity.
|
||||
The prefered way to save extra information in FCollada is at
|
||||
the entity level. Use this extra information tree to store
|
||||
any information you want exported and imported back.
|
||||
@return The extra information tree. */
|
||||
FCDExtra* GetExtra() { return extra; }
|
||||
const FCDExtra* GetExtra() const { return extra; } /**< See above. */
|
||||
|
||||
/** Retrieves whether the entity has a user-defined note.
|
||||
This value is a simpler way, than the extra tree, to store
|
||||
user-defined information that does not belong in COLLADA.
|
||||
@return Whether the entity has an user-defined note. */
|
||||
bool HasNote() const { return !note.empty(); }
|
||||
|
||||
/** Retrieves the user-defined note for this entity.
|
||||
This value is a simpler way, than the extra tree, to store
|
||||
user-defined information that does not belong in COLLADA.
|
||||
@return The user-defined note. */
|
||||
const fstring& GetNote() const { return note; }
|
||||
|
||||
/** Sets the user-defined note for this entity.
|
||||
This value is a simpler way, than the extra tree, to store
|
||||
user-defined information that does not belong in COLLADA.
|
||||
@param _note The user-defined note. */
|
||||
void SetNote(const fstring& _note) { note = _note; }
|
||||
|
||||
/** Retrieves the child entity that has the given COLLADA id.
|
||||
This function is only useful for entities that are hierarchical:
|
||||
visual/physics scene nodes and animations.
|
||||
@param daeId A COLLADA id.
|
||||
@return The child entity with the given id. This pointer will be NULL
|
||||
if no child entity matches the given id. */
|
||||
virtual FCDEntity* FindDaeId(const string& daeId);
|
||||
|
||||
/** [INTERNAL] Reads in the entity from a given COLLADA XML tree node.
|
||||
This function should be overwritten by all up-classes.
|
||||
@param entityNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the entity.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* entityNode);
|
||||
|
||||
/** [INTERNAL] Writes out the entity to the given COLLADA XML tree node.
|
||||
This function should be overwritten by all up-classes.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the entity.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
|
||||
/** @deprecated Retrieves the like of post-processing commands.
|
||||
Used only in ColladaMaya and should be taken out.
|
||||
@return The list of post-processing commands. */
|
||||
StringList& GetPostProcessCmds() { return postCmds; }
|
||||
|
||||
protected:
|
||||
/** [INTERNAL] Writes out the top entity XML node for the entity.
|
||||
This function should be used by all up-classes within the
|
||||
WriteToXML overwritting function to create the top XML node,
|
||||
as it will write out the name and COLLADA id of the entity.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the entity.
|
||||
@param nodeName The COLLADA XML node name for the top entity XML node.
|
||||
@return The created element XML tree node. */
|
||||
xmlNode* WriteToEntityXML(xmlNode* parentNode, const char* nodeName) const;
|
||||
|
||||
/** [INTERNAL] Writes out the extra information for the entity.
|
||||
This function should be used by all up-classes within the
|
||||
WriteToXML overwritting function, at the very end, to write
|
||||
the user-defined note and the extra tree to the COLLADA document.
|
||||
@param entityNode The created element XML tree node returned
|
||||
by the WriteToEntityXML function. */
|
||||
void WriteToExtraXML(xmlNode* entityNode) const;
|
||||
|
||||
/** [INTERNAL] Copies the entity information into a cloned entity.
|
||||
This function should be used by all up-classes when cloning an entity
|
||||
to copy the COLLADA id and the other entity-level information into a clone.
|
||||
@param clone The cloned entity. */
|
||||
void Clone(FCDEntity* clone);
|
||||
};
|
||||
|
||||
#endif // _FCD_ENTITY_H_
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#ifndef _FCD_ENTITY_INSTANCE_H_
|
||||
#define _FCD_ENTITY_INSTANCE_H_
|
||||
|
||||
class FCDocument;
|
||||
class FCDEntity;
|
||||
|
||||
#include "FCDocument/FCDObject.h"
|
||||
|
||||
class FCOLLADA_EXPORT FCDEntityInstance : public FCDObject
|
||||
{
|
||||
public:
|
||||
enum Type { SIMPLE, EXTERNAL_REFERENCE, GEOMETRY, MATERIAL, PHYSICS_MODEL, PHYSICS_RIGID_BODY, PHYSICS_RIGID_CONSTRAINT };
|
||||
|
||||
protected:
|
||||
FCDEntity* entity;
|
||||
|
||||
public:
|
||||
FCDEntityInstance(FCDocument* document, FCDEntity* _entity = NULL) : FCDObject(document, "FCDEntityInstance") { entity = _entity; }
|
||||
virtual ~FCDEntityInstance() { entity = NULL; }
|
||||
|
||||
// Accessors
|
||||
FCDEntity* GetEntity() { return entity; }
|
||||
const FCDEntity* GetEntity() const { return entity; }
|
||||
virtual Type GetType() const { return SIMPLE; }
|
||||
|
||||
// Load the per-instance information from the xml node tree
|
||||
virtual FUStatus LoadFromXML(xmlNode* UNUSED(instanceNode)) { return FUStatus(true); }
|
||||
|
||||
// Write out the instantiation information to the xml node tree
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif // _FCD_ENTITY_INSTANCE_H_
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#ifndef _FCD_XREF_ENTITY_H_
|
||||
#define _FCD_XREF_ENTITY_H_
|
||||
|
||||
#include "FCDocument/FCDEntityInstance.h"
|
||||
#include "FUtils/FUStringConversion.h"
|
||||
#include "FUtils/FUUri.h"
|
||||
|
||||
class FCOLLADA_EXPORT FCDExternalReference : public FCDEntityInstance
|
||||
{
|
||||
private:
|
||||
FUUri uri;
|
||||
|
||||
public:
|
||||
FCDExternalReference(FCDocument* document, const FUUri& _uri) : FCDEntityInstance(document) { uri = _uri; }
|
||||
virtual ~FCDExternalReference() {}
|
||||
|
||||
// FCDEntity override for RTTI-like
|
||||
virtual Type GetType() const { return EXTERNAL_REFERENCE; }
|
||||
|
||||
// Accessors
|
||||
const FUUri& GetUri() const { return uri; }
|
||||
const fstring& GetFilename() const { return uri.prefix; }
|
||||
fstring GetObjectName() const { return TO_FSTRING(uri.suffix); }
|
||||
};
|
||||
|
||||
#endif // _FCD_XREF_ENTITY_H_
|
||||
@@ -1,366 +0,0 @@
|
||||
/*
|
||||
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/FCDExtra.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDExtra::FCDExtra(FCDocument* document) : FCDObject(document, "FCDExtra")
|
||||
{
|
||||
}
|
||||
|
||||
FCDExtra::~FCDExtra()
|
||||
{
|
||||
CLEAR_POINTER_VECTOR(techniques);
|
||||
}
|
||||
|
||||
// Adds a technique of the given profile (or return the existing technique with this profile).
|
||||
FCDETechnique* FCDExtra::AddTechnique(const char* profile)
|
||||
{
|
||||
FCDETechnique* technique = FindTechnique(profile);
|
||||
if (technique == NULL)
|
||||
{
|
||||
technique = new FCDETechnique(GetDocument(), profile);
|
||||
techniques.push_back(technique);
|
||||
}
|
||||
return technique;
|
||||
}
|
||||
|
||||
// Releases a technique contained within the extra tree.
|
||||
void FCDExtra::ReleaseTechnique(FCDETechnique* technique)
|
||||
{
|
||||
FCDETechniqueList::iterator it = std::find(techniques.begin(), techniques.end(), technique);
|
||||
if (it != techniques.end())
|
||||
{
|
||||
delete (*it);
|
||||
techniques.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
// Search for a profile-specific technique
|
||||
FCDETechnique* FCDExtra::FindTechnique(const char* profile)
|
||||
{
|
||||
for (FCDETechniqueList::iterator itT = techniques.begin(); itT != techniques.end(); ++itT)
|
||||
{
|
||||
if (IsEquivalent((*itT)->GetProfile(), profile)) return *itT;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
const FCDETechnique* FCDExtra::FindTechnique(const char* profile) const
|
||||
{
|
||||
for (FCDETechniqueList::const_iterator itT = techniques.begin(); itT != techniques.end(); ++itT)
|
||||
{
|
||||
if (IsEquivalent((*itT)->GetProfile(), profile)) return *itT;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Search for a root node with a specific element name
|
||||
FCDENode* FCDExtra::FindRootNode(const char* name)
|
||||
{
|
||||
FCDENode* rootNode = NULL;
|
||||
for (FCDETechniqueList::iterator itT = techniques.begin(); itT != techniques.end(); ++itT)
|
||||
{
|
||||
rootNode = (*itT)->FindChildNode(name);
|
||||
if (rootNode != NULL) break;
|
||||
}
|
||||
return rootNode;
|
||||
}
|
||||
const FCDENode* FCDExtra::FindRootNode(const char* name) const
|
||||
{
|
||||
FCDENode* rootNode = NULL;
|
||||
for (FCDETechniqueList::const_iterator itT = techniques.begin(); itT != techniques.end(); ++itT)
|
||||
{
|
||||
rootNode = (*itT)->FindChildNode(name);
|
||||
if (rootNode != NULL) break;
|
||||
}
|
||||
return rootNode;
|
||||
}
|
||||
|
||||
// Read in/Write to a COLLADA xml document
|
||||
FUStatus FCDExtra::LoadFromXML(xmlNode* extraNode)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// Read in the techniques
|
||||
xmlNodeList techniqueNodes;
|
||||
FindChildrenByType(extraNode, DAE_TECHNIQUE_ELEMENT, techniqueNodes);
|
||||
for (xmlNodeList::iterator itN = techniqueNodes.begin(); itN != techniqueNodes.end(); ++itN)
|
||||
{
|
||||
xmlNode* techniqueNode = (*itN);
|
||||
FCDETechnique* technique = AddTechnique(ReadNodeProperty(techniqueNode, DAE_PROFILE_ATTRIBUTE));
|
||||
status.AppendStatus(technique->LoadFromXML(techniqueNode));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
xmlNode* FCDExtra::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
if (techniques.empty()) return NULL;
|
||||
|
||||
// Add the <extra> element and its techniques
|
||||
xmlNode* extraNode = AddChildOnce(parentNode, DAE_EXTRA_ELEMENT);
|
||||
for (FCDETechniqueList::const_iterator itT = techniques.begin(); itT != techniques.end(); ++itT)
|
||||
{
|
||||
(*itT)->WriteToXML(extraNode);
|
||||
}
|
||||
return extraNode;
|
||||
}
|
||||
|
||||
FCDENode::FCDENode(FCDocument* document, FCDENode* _parent) : FCDObject(document, "FCDENode")
|
||||
{
|
||||
parent = _parent;
|
||||
animated = NULL;
|
||||
}
|
||||
|
||||
FCDENode::~FCDENode()
|
||||
{
|
||||
GetDocument()->UnregisterAnimatedValue(animated);
|
||||
SAFE_DELETE(animated);
|
||||
parent = NULL;
|
||||
|
||||
CLEAR_POINTER_VECTOR(children);
|
||||
CLEAR_POINTER_VECTOR(attributes);
|
||||
}
|
||||
|
||||
void FCDENode::Release()
|
||||
{
|
||||
if (parent != NULL)
|
||||
{
|
||||
parent->ReleaseChildNode(this);
|
||||
}
|
||||
|
||||
// Otherwise, we have a technique so don't release
|
||||
}
|
||||
|
||||
void FCDENode::SetContent(const fchar* _content)
|
||||
{
|
||||
// As COLLADA doesn't allow for mixed content, release all the children.
|
||||
while (!children.empty())
|
||||
{
|
||||
children.back()->Release();
|
||||
}
|
||||
|
||||
content = _content;
|
||||
}
|
||||
|
||||
// Search for a children with a specific name
|
||||
FCDENode* FCDENode::FindChildNode(const char* name)
|
||||
{
|
||||
for (FCDENodeList::iterator itN = children.begin(); itN != children.end(); ++itN)
|
||||
{
|
||||
if (IsEquivalent((*itN)->GetName(), name)) return (*itN);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const FCDENode* FCDENode::FindChildNode(const char* name) const
|
||||
{
|
||||
for (FCDENodeList::const_iterator itN = children.begin(); itN != children.end(); ++itN)
|
||||
{
|
||||
if (IsEquivalent((*itN)->GetName(), name)) return (*itN);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Adds a new child node
|
||||
FCDENode* FCDENode::AddChildNode()
|
||||
{
|
||||
FCDENode* node = new FCDENode(GetDocument(), this);
|
||||
children.push_back(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
// Releases a child node
|
||||
void FCDENode::ReleaseChildNode(FCDENode* childNode)
|
||||
{
|
||||
FCDENodeList::iterator itN = std::find(children.begin(), children.end(), childNode);
|
||||
if (itN != children.end())
|
||||
{
|
||||
delete (*itN);
|
||||
children.erase(itN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FCDENode* FCDENode::FindParameter(const char* name)
|
||||
{
|
||||
for (FCDENodeList::iterator itN = children.begin(); itN != children.end(); ++itN)
|
||||
{
|
||||
FCDENode* node = (*itN);
|
||||
if (IsEquivalent(node->GetName(), name)) return node;
|
||||
else if (IsEquivalent(node->GetName(), DAE_PARAMETER_ELEMENT))
|
||||
{
|
||||
FCDEAttribute* nameAttribute = node->FindAttribute(DAE_NAME_ATTRIBUTE);
|
||||
if (nameAttribute != NULL && nameAttribute->value == TO_FSTRING(name)) return node;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FCDENode::FindParameters(FCDENodeList& nodes, StringList& names)
|
||||
{
|
||||
for (FCDENodeList::iterator itN = children.begin(); itN != children.end(); ++itN)
|
||||
{
|
||||
FCDENode* node = (*itN);
|
||||
if (node->GetChildNodeCount() > 1) continue;
|
||||
|
||||
if (IsEquivalent(node->GetName(), DAE_PARAMETER_ELEMENT))
|
||||
{
|
||||
FCDEAttribute* nameAttribute = node->FindAttribute(DAE_NAME_ATTRIBUTE);
|
||||
if (nameAttribute != NULL)
|
||||
{
|
||||
nodes.push_back(node);
|
||||
names.push_back(FUStringConversion::ToString(nameAttribute->value));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nodes.push_back(node);
|
||||
names.push_back(node->GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a new attribute to this extra tree node.
|
||||
FCDEAttribute* FCDENode::AddAttribute(const char* _name, const fchar* _value)
|
||||
{
|
||||
FCDEAttribute* attribute = FindAttribute(_name);
|
||||
if (attribute == NULL)
|
||||
{
|
||||
attribute = new FCDEAttribute();
|
||||
attribute->name = _name;
|
||||
attributes.push_back(attribute);
|
||||
}
|
||||
|
||||
attribute->value = _value;
|
||||
return attribute;
|
||||
}
|
||||
|
||||
// Releases an attribute
|
||||
void FCDENode::ReleaseAttribute(FCDEAttribute* attribute)
|
||||
{
|
||||
FCDEAttributeList::iterator it = std::find(attributes.begin(), attributes.end(), attribute);
|
||||
if (it != attributes.end())
|
||||
{
|
||||
delete *it;
|
||||
attributes.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
// Search for an attribute with a specific name
|
||||
FCDEAttribute* FCDENode::FindAttribute(const char* name)
|
||||
{
|
||||
for (FCDEAttributeList::iterator itA = attributes.begin(); itA != attributes.end(); ++itA)
|
||||
{
|
||||
if ((*itA)->name == name) return (*itA);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
const FCDEAttribute* FCDENode::FindAttribute(const char* name) const
|
||||
{
|
||||
for (FCDEAttributeList::const_iterator itA = attributes.begin(); itA != attributes.end(); ++itA)
|
||||
{
|
||||
if ((*itA)->name == name) return (*itA);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read in this extra node from a COLLADA xml document
|
||||
FUStatus FCDENode::LoadFromXML(xmlNode* customNode)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// Read in the node's name and children
|
||||
name = (const char*) customNode->name;
|
||||
ReadChildrenFromXML(customNode);
|
||||
|
||||
// If there are no child nodes, we have a tree leaf: parse in the content and its animation
|
||||
content = (children.empty()) ? TO_FSTRING(ReadNodeContentDirect(customNode)) : FS("");
|
||||
animated = FCDAnimatedCustom::Create(GetDocument(), customNode);
|
||||
|
||||
// Read in the node's attributes
|
||||
for (xmlAttr* a = customNode->properties; a != NULL; a = a->next)
|
||||
{
|
||||
AddAttribute((const char*) a->name, (a->children != NULL) ? TO_FSTRING((const char*) (a->children->content)) : FS(""));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out this extra to a COLLADA xml document
|
||||
xmlNode* FCDENode::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* customNode = AddChild(parentNode, name.c_str(), content);
|
||||
|
||||
// Write out the attributes
|
||||
for (FCDEAttributeList::const_iterator itA = attributes.begin(); itA != attributes.end(); ++itA)
|
||||
{
|
||||
const FCDEAttribute* attribute = (*itA);
|
||||
FUXmlWriter::AddAttribute(customNode, attribute->name.c_str(), attribute->value);
|
||||
}
|
||||
|
||||
// Write out the children
|
||||
WriteChildrenToXML(customNode);
|
||||
return customNode;
|
||||
}
|
||||
|
||||
// Read in the child nodes from the xml tree node
|
||||
FUStatus FCDENode::ReadChildrenFromXML(xmlNode* customNode)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// Read in the node's children
|
||||
for (xmlNode* k = customNode->children; k != NULL; k = k->next)
|
||||
{
|
||||
if (k->type != XML_ELEMENT_NODE) continue;
|
||||
|
||||
FCDENode* node = AddChildNode();
|
||||
status.AppendStatus(node->LoadFromXML(k));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out the child nodes to the xml tree node
|
||||
void FCDENode::WriteChildrenToXML(xmlNode* customNode) const
|
||||
{
|
||||
for (FCDENodeList::const_iterator itN = children.begin(); itN != children.end(); ++itN)
|
||||
{
|
||||
(*itN)->WriteToXML(customNode);
|
||||
}
|
||||
}
|
||||
|
||||
FCDETechnique::FCDETechnique(FCDocument* document, const char* _profile) : FCDENode(document, NULL)
|
||||
{
|
||||
profile = _profile;
|
||||
}
|
||||
|
||||
FCDETechnique::~FCDETechnique() {}
|
||||
|
||||
// Read in/Write to a COLLADA xml document
|
||||
FUStatus FCDETechnique::LoadFromXML(xmlNode* techniqueNode)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// Read in only the child elements: none of the attributes
|
||||
status.AppendStatus(ReadChildrenFromXML(techniqueNode));
|
||||
return status;
|
||||
}
|
||||
|
||||
xmlNode* FCDETechnique::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
// Create the technique for this profile and write out the children
|
||||
xmlNode* customNode = AddTechniqueChild(parentNode, profile.c_str());
|
||||
WriteChildrenToXML(customNode);
|
||||
return customNode;
|
||||
}
|
||||
|
||||
@@ -1,357 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDExtra.h
|
||||
This file contains the FCDExtra class and its sub-classes:
|
||||
FCDENode, FCDETechnique and FCDEAttribute.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_EXTRA_H_
|
||||
#define _FCD_EXTRA_H_
|
||||
|
||||
#include "FCDocument/FCDObject.h"
|
||||
|
||||
class FCDAnimated;
|
||||
class FCDAnimatedCustom;
|
||||
class FCDETechnique;
|
||||
class FCDENode;
|
||||
|
||||
/**
|
||||
An extra tree attribute.
|
||||
Contains a name and a value string.
|
||||
*/
|
||||
struct FCDEAttribute
|
||||
{
|
||||
string name; /**< The attribute name. Must be provided. */
|
||||
fstring value; /**< The attribute value. Is optional. */
|
||||
};
|
||||
|
||||
typedef vector<FCDETechnique*> FCDETechniqueList; /**< A dynamically-sized array of extra tree techniques. */
|
||||
typedef vector<FCDENode*> FCDENodeList; /**< A dynamically-sized array of extra tree nodes. */
|
||||
typedef vector<FCDEAttribute*> FCDEAttributeList; /**< A dynamically-sized array of extra tree attributes. */
|
||||
|
||||
/**
|
||||
A COLLADA extra tree.
|
||||
|
||||
An extra tree contains the user-defined COLLADA information
|
||||
contained within \<extra\> elements. For this, the extra tree
|
||||
root simply contains a list of techniques. Each technique
|
||||
belongs to a different application-specific profile.
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDExtra : public FCDObject
|
||||
{
|
||||
private:
|
||||
FCDETechniqueList techniques;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
The structures that contain extra trees will create them.
|
||||
@param document The COLLADA document that owns the extra tree. */
|
||||
FCDExtra(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
The structures that contain extra trees will release them. */
|
||||
virtual ~FCDExtra();
|
||||
|
||||
/** Retrieves the list of techniques contained by this extra tree.
|
||||
@return The list of techniques. */
|
||||
FCDETechniqueList& GetTechniques() { return techniques; }
|
||||
const FCDETechniqueList& GetTechniques() const { return techniques; } /**< See above. */
|
||||
|
||||
/** Retrieves the number of techniques contained by this extra tree.
|
||||
@return The number of techniques. */
|
||||
size_t GetTechniqueCount() const { return techniques.size(); }
|
||||
|
||||
/** Retrieves a specific technique contained by this extra tree.
|
||||
@param index The index of the technique.
|
||||
@return The technique. This pointer will be NULL if the
|
||||
index is out-of-bounds. */
|
||||
FCDETechnique* GetTechnique(size_t index) { FUAssert(index < techniques.size(), return NULL); return techniques.at(index); }
|
||||
const FCDETechnique* GetTechnique(size_t index) const { FUAssert(index < techniques.size(), return NULL); return techniques.at(index); } /**< See above. */
|
||||
|
||||
/** Adds a new application-specific profile technique to the extra tree.
|
||||
If the given application-specific profile already exists
|
||||
within the extra tree, the old technique will be returned.
|
||||
@param profile The application-specific profile name.
|
||||
@return A technique for this application-specific profile. */
|
||||
FCDETechnique* AddTechnique(const char* profile);
|
||||
inline FCDETechnique* AddTechnique(const string& profile) { return AddTechnique(profile.c_str()); } /**< See above. */
|
||||
|
||||
/** Releases a technique contained within the extra tree.
|
||||
@param technique The technique to release. */
|
||||
void ReleaseTechnique(FCDETechnique* technique);
|
||||
|
||||
/** Retrieves a specific technique contained by this extra tree.
|
||||
@param profile The application-specific profile name of the technique.
|
||||
@return The technique that matches the profile name. This pointer may
|
||||
be NULL if no technique matches the profile name. */
|
||||
FCDETechnique* FindTechnique(const char* profile);
|
||||
const FCDETechnique* FindTechnique(const char* profile) const; /**< See above. */
|
||||
inline FCDETechnique* FindTechnique(const string& profile) { return FindTechnique(profile.c_str()); } /**< See above. */
|
||||
inline const FCDETechnique* FindTechnique(const string& profile) const { return FindTechnique(profile.c_str()); } /**< See above. */
|
||||
|
||||
/** Retrieves the extra tree node that has a given element name.
|
||||
This function searches for the extra tree node within all the
|
||||
techniques.
|
||||
@param name An element name.
|
||||
@return The extra tree node that matches the element name. This pointer
|
||||
will be NULL if no extra tree node matches the element name. */
|
||||
FCDENode* FindRootNode(const char* name);
|
||||
const FCDENode* FindRootNode(const char* name) const; /**< See above. */
|
||||
inline FCDENode* FindRootNode(const string& name) { return FindRootNode(name.c_str()); } /**< See above. */
|
||||
inline const FCDENode* FindRootNode(const string& name) const { return FindRootNode(name.c_str()); } /**< See above. */
|
||||
|
||||
/** [INTERNAL] Reads in the extra tree from a given COLLADA XML tree node.
|
||||
@param extraNode The COLLADA \<extra\> element XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the entity.*/
|
||||
FUStatus LoadFromXML(xmlNode* extraNode);
|
||||
|
||||
/** [INTERNAL] Writes out the extra tree to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the \<extra\> element.
|
||||
@return The created element XML tree node. */
|
||||
xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
/**
|
||||
A COLLADA extra tree node.
|
||||
|
||||
The extra tree node is a hierarchical structure that contains child
|
||||
extra tree nodes as well as attributes. If the extra tree node is a leaf
|
||||
of the tree, it may contain textual content.
|
||||
|
||||
The extra tree node leaf may be animated, if it has the 'sid' attribute.
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDENode : public FCDObject
|
||||
{
|
||||
private:
|
||||
string name;
|
||||
fstring content;
|
||||
|
||||
FCDENode* parent;
|
||||
FCDENodeList children;
|
||||
FCDEAttributeList attributes;
|
||||
|
||||
FCDAnimatedCustom* animated;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, call the FCDENode::AddChild function of the parent within the hierarchy.
|
||||
@param document The COLLADA document that owns the extra tree node.
|
||||
@param parent The extra tree node that contains this extra tree node. */
|
||||
FCDENode(FCDocument* document, FCDENode* parent);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, for hierarchical nodes: call the Release function
|
||||
or the parent's ReleaseChildNode function and for techniques:
|
||||
call the FCDExtra::ReleaseTechnique function. */
|
||||
virtual ~FCDENode();
|
||||
|
||||
/** Releases this extra tree node.
|
||||
This function is a shortcut to the parent's FCDENode::ReleaseChildNode function. */
|
||||
void Release();
|
||||
|
||||
/** Retrieves the name of the extra tree node.
|
||||
The name of the extra tree node is the name of the equivalent XML tree node.
|
||||
@return The name of the extra tree node. */
|
||||
inline const char* GetName() const { return name.c_str(); }
|
||||
|
||||
/** Sets the name of the extra tree node.
|
||||
The name of the extra tree node is the name of the equivalent XML tree node.
|
||||
@param _name The name of the extra tree node. */
|
||||
inline void SetName(const char* _name) { name = _name; }
|
||||
inline void SetName(const string& _name) { name = _name; } /**< See above. */
|
||||
|
||||
/** Retrieves the textual content of the extra tree node.
|
||||
This value is only valid for extra tree node that have no children,
|
||||
as COLLADA doesn't allow for mixed-content.
|
||||
@return The textual content of the extra tree node. */
|
||||
const fchar* GetContent() const { return content.c_str(); }
|
||||
|
||||
/** Sets the textual content of the extra tree node.
|
||||
This function will release all the child node of this extra tree node,
|
||||
as COLLADA doesn't allow for mixed-content.
|
||||
@param _content The textual content. */
|
||||
void SetContent(const fchar* _content);
|
||||
inline void SetContent(const fstring& _content) { return SetContent(_content.c_str()); } /**< See above. */
|
||||
|
||||
/** Retrieves the animated values associated with this extra tree node.
|
||||
Extra tree node leaves may be animated. If this extra tree node leaf
|
||||
is animated, this animated value will contain the animation curves.
|
||||
@return The animated value. */
|
||||
FCDAnimatedCustom* GetAnimated() { return animated; }
|
||||
const FCDAnimatedCustom* GetAnimated() const { return animated; } /**< See above. */
|
||||
|
||||
/** Retrieves the parent of an extra tree node.
|
||||
The hierarchy cannot be changed dynamically. If you to move an extra tree node,
|
||||
you will need to clone it manually and release the old extra tree node.
|
||||
@return The parent extra tree node within the hierarchy. This pointer
|
||||
will be NULL if the extra tree node is a extra tree technique. */
|
||||
FCDENode* GetParent() { return parent; }
|
||||
const FCDENode* GetParent() const { return parent; } /**< See above. */
|
||||
|
||||
/** Retrieves the children of an extra tree node.
|
||||
@return The list of child extra tree nodes. */
|
||||
FCDENodeList& GetChildNodes() { return children; }
|
||||
const FCDENodeList& GetChildNodes() const { return children; } /**< See above. */
|
||||
|
||||
/** Retrieves the number of children of an extra tree node.
|
||||
@return The number of children. */
|
||||
size_t GetChildNodeCount() const { return children.size(); }
|
||||
|
||||
/** Retrieves a specific child extra tree node.
|
||||
@param index The index of the child extra tree node.
|
||||
@return The child extra tree node. This pointer will be NULL if the index
|
||||
is out-of-bounds. */
|
||||
FCDENode* GetChildNode(size_t index) { FUAssert(index < children.size(), return NULL); return children.at(index); }
|
||||
const FCDENode* GetChildNode(size_t index) const { FUAssert(index < children.size(), return NULL); return children.at(index); } /**< See above. */
|
||||
|
||||
/** Adds a new child extra tree to this extra tree node.
|
||||
@return The new child extra tree node. */
|
||||
FCDENode* AddChildNode();
|
||||
|
||||
/** Releases a child extra tree node of this extra tree node.
|
||||
@param childNode The child to release. */
|
||||
void ReleaseChildNode(FCDENode* childNode);
|
||||
|
||||
/** Retrieves the child extra tree node with the given name.
|
||||
@param name A name.
|
||||
@return The child extra tree node that matches the given name.
|
||||
This pointer will be NULL if no child extra tree node matches
|
||||
the given name. */
|
||||
FCDENode* FindChildNode(const char* name);
|
||||
const FCDENode* FindChildNode(const char* name) const; /**< See above. */
|
||||
inline FCDENode* FindChildNode(const string& name) { return FindChildNode(name.c_str()); } /**< See above. */
|
||||
inline const FCDENode* FindChildNode(const string& name) const { return FindChildNode(name.c_str()); } /**< See above. */
|
||||
|
||||
/** Retrieves the child extra tree node with the given name.
|
||||
This function is used for COLLADA 1.3 backward compatibility,
|
||||
where all parameters were described as \<param name='X'>value\</param\>.
|
||||
So, if the child extra tree node with the name 'X' as searched for:
|
||||
both the above COLLADA 1.3 parameter and the COLLADA 1.4+
|
||||
\<X\>value\</X\> parameters will be returned.
|
||||
@param name The parameter name.
|
||||
@return The first child extra tree node holding the wanted parameter within the hierarchy.
|
||||
This pointer will be NULL to indicate that no parameter matches the given name. */
|
||||
FCDENode* FindParameter(const char* name);
|
||||
|
||||
/** Retrieves a list of all the parameters contained within the hierarchy.
|
||||
This function is used for COLLADA 1.3 backward compatibility,
|
||||
where all parameters were described as \<param name='X'>value\</param\>.
|
||||
In COLLADA 1.4+, the same parameter should be described as: \<X\>value\</X\>.
|
||||
Using this function, both parameters would be returned with the name 'X'.
|
||||
@param nodes The list of parameters to fill in. This list is not emptied by the function.
|
||||
@param names The list of names of the parameters. This list is not emptied by the function. */
|
||||
void FindParameters(FCDENodeList& nodes, StringList& names);
|
||||
|
||||
/** Retrieves the list of attributes for this extra tree node.
|
||||
@return The list of attributes. */
|
||||
FCDEAttributeList& GetAttributes() { return attributes; }
|
||||
const FCDEAttributeList& GetAttributes() const { return attributes; } /**< See above. */
|
||||
|
||||
/** Retrieves the number of attributes for this extra tree node.
|
||||
@return The number of attributes. */
|
||||
size_t GetAttributeCount() const { return attributes.size(); }
|
||||
|
||||
/** Retrieves a specific attribute of this extra tree node.
|
||||
@param index The index.
|
||||
@return The attribute at this index. This pointer will be NULL
|
||||
if the index is out-of-bounds. */
|
||||
FCDEAttribute* GetAttribute(size_t index) { FUAssert(index < attributes.size(), return NULL); return attributes.at(index); }
|
||||
const FCDEAttribute* GetAttribute(size_t index) const { FUAssert(index < attributes.size(), return NULL); return attributes.at(index); } /**< See above. */
|
||||
|
||||
/** Adds a new attribute to this extra tree node.
|
||||
If an attribute with the same name already exists, this function simply
|
||||
assigns the new value to the existing attribute and returns the existing attribute.
|
||||
@param _name The name of the attribute.
|
||||
@param _value The value of the attribute.
|
||||
@return The new attribute. */
|
||||
FCDEAttribute* AddAttribute(const char* _name, const fchar* _value);
|
||||
inline FCDEAttribute* AddAttribute(const string& _name, const fchar* _value) { return AddAttribute(_name.c_str(), _value); } /**< See above. */
|
||||
inline FCDEAttribute* AddAttribute(const char* _name, const fstring& _value) { return AddAttribute(_name, _value.c_str()); } /**< See above. */
|
||||
inline FCDEAttribute* AddAttribute(const string& _name, const fstring& _value) { return AddAttribute(_name.c_str(), _value.c_str()); } /**< See above. */
|
||||
template <typename T> inline FCDEAttribute* AddAttribute(const char* _name, const T& _value) { return AddAttribute(_name, TO_FSTRING(_value)); } /**< See above. */
|
||||
template <typename T> inline FCDEAttribute* AddAttribute(const string& _name, const T& _value) { return AddAttribute(_name.c_str(), TO_FSTRING(_value)); } /**< See above. */
|
||||
|
||||
/** Releases an attribute of this extra tree node.
|
||||
@param attribute The attribute to release. */
|
||||
void ReleaseAttribute(FCDEAttribute* attribute);
|
||||
|
||||
/** Retrieve the attribute of this extra tree node with the given name.
|
||||
Attribute names are unique within an extra tree node.
|
||||
@param name The attribute name.
|
||||
@return The attribute that matches the name. This pointer will be NULL if
|
||||
there is no attribute with the given name. */
|
||||
FCDEAttribute* FindAttribute(const char* name);
|
||||
const FCDEAttribute* FindAttribute(const char* name) const; /**< See above. */
|
||||
|
||||
/** [INTERNAL] Reads in the extra tree node from a given COLLADA XML tree node.
|
||||
@param customNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the extra tree node.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* customNode);
|
||||
|
||||
/** [INTERNAL] Writes out the extra tree node to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the extra tree node.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
|
||||
protected:
|
||||
/** [INTERNAL] Reads in the children nodes of the extra tree node.
|
||||
Used by the FCDETechnique class exclusively.
|
||||
@param customNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the extra tree node.*/
|
||||
FUStatus ReadChildrenFromXML(xmlNode* customNode);
|
||||
|
||||
/** [INTERNAL] Writes out the children nodes of extra tree node.
|
||||
Used by the FCDETechnique class exclusively.
|
||||
@param customNode The COLLADA XML node for the extra tree node. */
|
||||
void WriteChildrenToXML(xmlNode* customNode) const;
|
||||
};
|
||||
|
||||
/**
|
||||
A COLLADA extra tree technique.
|
||||
|
||||
For convenience, this extra tree technique is based on top of the FCDENode class.
|
||||
An extra tree technique is the root of the extra tree specific to
|
||||
the profile of an application.
|
||||
|
||||
@ingroup FCDocument
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDETechnique : public FCDENode
|
||||
{
|
||||
private:
|
||||
string profile;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDExtra::AddTechnique function.
|
||||
@param document The COLLADA document that owns the technique.
|
||||
@param profile The application-specific profile name. */
|
||||
FCDETechnique(FCDocument* document, const char* profile);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, release a technique using the FCDExtra::ReleaseTechnique function. */
|
||||
virtual ~FCDETechnique();
|
||||
|
||||
/** Retrieves the name of the application-specific profile of the technique.
|
||||
@return The name of the application-specific profile. */
|
||||
const char* GetProfile() const { return profile.c_str(); }
|
||||
|
||||
/** [INTERNAL] Reads in the extra tree technique from a given COLLADA XML tree node.
|
||||
@param techniqueNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the extra tree technique.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* techniqueNode);
|
||||
|
||||
/** [INTERNAL] Writes out the extra tree technique to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the extra tree technique.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif // _FCD_EXTRA_H_
|
||||
@@ -1,151 +0,0 @@
|
||||
/*
|
||||
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/FCDGeometry.h"
|
||||
#include "FCDocument/FCDGeometryMesh.h"
|
||||
#include "FCDocument/FCDGeometrySpline.h"
|
||||
#include "FUtils/FUStringConversion.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDGeometry::FCDGeometry(FCDocument* document) : FCDEntity(document, "Geometry")
|
||||
{
|
||||
spline = NULL;
|
||||
mesh = NULL;
|
||||
}
|
||||
|
||||
FCDGeometry::~FCDGeometry()
|
||||
{
|
||||
SAFE_DELETE(spline);
|
||||
SAFE_DELETE(mesh);
|
||||
}
|
||||
|
||||
// Sets the type of this geometry to mesh and creates an empty mesh structure.
|
||||
FCDGeometryMesh* FCDGeometry::CreateMesh()
|
||||
{
|
||||
SAFE_DELETE(spline);
|
||||
SAFE_DELETE(mesh);
|
||||
|
||||
mesh = new FCDGeometryMesh(GetDocument(), this);
|
||||
return mesh;
|
||||
}
|
||||
|
||||
// Sets the type of this geometry to spline and creates an empty spline structure.
|
||||
FCDGeometrySpline* FCDGeometry::CreateSpline()
|
||||
{
|
||||
SAFE_DELETE(spline);
|
||||
SAFE_DELETE(mesh);
|
||||
|
||||
spline = new FCDGeometrySpline(GetDocument(), this);
|
||||
return spline;
|
||||
}
|
||||
|
||||
// Create a copy of this geometry, with the vertices overwritten
|
||||
FCDGeometry* FCDGeometry::Clone(FloatList& newPositions, uint32 newPositionsStride, FloatList& newNormals, uint32 newNormalsStride)
|
||||
{
|
||||
// Clone only mesh geometries. This function is necessary for COLLADA 1.3 backward compatibility and should not be used
|
||||
// in some other way (yet)
|
||||
if (!IsMesh()) return NULL;
|
||||
|
||||
FCDGeometry* clone = new FCDGeometry(GetDocument());
|
||||
clone->mesh = mesh->Clone(newPositions, newPositionsStride, newNormals, newNormalsStride);
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Load from a XML node the given geometry
|
||||
FUStatus FCDGeometry::LoadFromXML(xmlNode* geometryNode)
|
||||
{
|
||||
SAFE_DELETE(mesh);
|
||||
SAFE_DELETE(spline);
|
||||
|
||||
FUStatus status = FCDEntity::LoadFromXML(geometryNode);
|
||||
if (!status) return status;
|
||||
if (!IsEquivalent(geometryNode->name, DAE_GEOMETRY_ELEMENT))
|
||||
{
|
||||
return status.Warning(FS("Geometry library contains unknown element."), geometryNode->line);
|
||||
}
|
||||
|
||||
// Read in the first valid child element found
|
||||
for (xmlNode* child = geometryNode->children; child != NULL; child = child->next)
|
||||
{
|
||||
if (child->type != XML_ELEMENT_NODE) continue;
|
||||
|
||||
if (IsEquivalent(child->name, DAE_MESH_ELEMENT))
|
||||
{
|
||||
// Create a new mesh
|
||||
FCDGeometryMesh* m = CreateMesh();
|
||||
status.AppendStatus(m->LoadFromXML(child));
|
||||
break;
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_SPLINE_ELEMENT))
|
||||
{
|
||||
// Create a new spline
|
||||
FCDGeometrySpline* s = CreateSpline();
|
||||
status.AppendStatus(s->LoadFromXML(child));
|
||||
break;
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_CONVEX_MESH_ELEMENT))
|
||||
{
|
||||
//several cases can exist here...
|
||||
//wait for fixed version of FCollada?
|
||||
//assume <convex_hull_of> and do instantiate?
|
||||
|
||||
// Create a new mesh
|
||||
FCDGeometryMesh* m = CreateMesh();
|
||||
m->m_convex = true;
|
||||
FUUri url;
|
||||
char hullname[] = "convex_hull_of";
|
||||
|
||||
url = ReadNodeUrl(child,hullname);
|
||||
|
||||
if (!url.prefix.empty())
|
||||
{
|
||||
|
||||
FCDGeometry* entity = GetDocument()->FindGeometry(url.prefix);
|
||||
if (entity)
|
||||
{
|
||||
printf("found convex_mesh\n");
|
||||
//quick hack
|
||||
this->mesh = entity->GetMesh();
|
||||
mesh->m_convex = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//status.AppendStatus(m->LoadFromXML(child));
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
return status.Fail(FS("Unknown child in <geometry> with id: ") + TO_FSTRING(GetDaeId()), child->line);
|
||||
}
|
||||
}
|
||||
|
||||
if (mesh == NULL && spline == NULL)
|
||||
{
|
||||
status.Warning(FS("No mesh or spline found within geometry: ") + TO_FSTRING(GetDaeId()), geometryNode->line);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out the <geometry> node
|
||||
xmlNode* FCDGeometry::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* geometryNode = WriteToEntityXML(parentNode, DAE_GEOMETRY_ELEMENT);
|
||||
|
||||
if (mesh != NULL) mesh->WriteToXML(geometryNode);
|
||||
else if (spline != NULL) spline->WriteToXML(geometryNode);
|
||||
|
||||
FCDEntity::WriteToExtraXML(geometryNode);
|
||||
return geometryNode;
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDGeometry.h
|
||||
This file contains the FCDGeometry class.
|
||||
The FCDGeometry class holds the information for one mesh or spline
|
||||
entity, within the COLLADA geometry library.
|
||||
*/
|
||||
#ifndef _FCD_GEOMETRY_H_
|
||||
#define _FCD_GEOMETRY_H_
|
||||
|
||||
#include "FCDocument/FCDEntity.h"
|
||||
#include "FUtils/FUDaeEnum.h"
|
||||
|
||||
class FCDocument;
|
||||
class FCDGeometryMesh;
|
||||
class FCDGeometrySpline;
|
||||
|
||||
/**
|
||||
@defgroup FCDGeometry COLLADA Document Geometry Entity
|
||||
@addtogroup FCDocument
|
||||
*/
|
||||
|
||||
/**
|
||||
A COLLADA geometry entity.
|
||||
There are two types of COLLADA geometry entities: meshes and splines.
|
||||
|
||||
Meshes are collections of polygons where the vertices always have a position,
|
||||
usually have a normal to define smooth or hard edges and may be colored or textured.
|
||||
|
||||
Splines are a sequence of control points used to generate a smooth curve.
|
||||
|
||||
@ingroup FCDGeometry
|
||||
*/
|
||||
|
||||
class FCOLLADA_EXPORT FCDGeometry : public FCDEntity
|
||||
{
|
||||
private:
|
||||
// Contains only one of the following, in order of importance.
|
||||
FCDGeometryMesh* mesh;
|
||||
FCDGeometrySpline* spline;
|
||||
|
||||
public:
|
||||
/** Contructor: do not use directly. Create new geometries using the FCDocument::AddGeometry function,
|
||||
or the FCDLibrary::AddEntity function.
|
||||
@param document The COLLADA document which owns the new geometry entity. */
|
||||
FCDGeometry(FCDocument* document);
|
||||
|
||||
/** Destructor: only release cloned geometries directly.
|
||||
Release original geometries using the FCDLibrary::ReleaseEntity function.
|
||||
All original geometries are released with the document that they belong to. */
|
||||
virtual ~FCDGeometry();
|
||||
|
||||
/** Retrieves the entity class type.
|
||||
This function is a part of the FCDEntity interface.
|
||||
@return The entity class type: GEOMETRY. */
|
||||
virtual Type GetType() const { return GEOMETRY; }
|
||||
|
||||
/** Retrieves whether the type of this geometry is a mesh.
|
||||
@return Whether this geometry is a mesh. */
|
||||
bool IsMesh() const { return mesh != NULL; }
|
||||
|
||||
/** Retrieves the mesh information structure for this geometry.
|
||||
Verify that this geometry is a mesh using the IsMesh function prior to calling this function.
|
||||
@return The mesh information structure. This pointer will be NULL when the geometry is a spline or is undefined. */
|
||||
FCDGeometryMesh* GetMesh() { return mesh; }
|
||||
const FCDGeometryMesh* GetMesh() const { return mesh; } /**< See above. */
|
||||
|
||||
/** Sets the type of this geometry to mesh and creates an empty mesh structure.
|
||||
This function will release any mesh or spline structure that the geometry may already contain
|
||||
@return The mesh information structure. This pointer will always be valid. */
|
||||
FCDGeometryMesh* CreateMesh();
|
||||
|
||||
/** Retrieves whether the type of this geometry is a spline.
|
||||
@return Whether this geometry is a spline. */
|
||||
bool IsSpline() const { return spline != NULL; }
|
||||
|
||||
/** Retrieves the spline information structure for this geometry.
|
||||
Verify that this geometry is a spline using the IsSpline function prior to calling this function.
|
||||
@return The spline information structure. This pointer will be NULL when the geometry is a mesh or is undefined. */
|
||||
FCDGeometrySpline* GetSpline() { return spline; }
|
||||
const FCDGeometrySpline* GetSpline() const { return spline; } /**< See above. */
|
||||
|
||||
/** Sets the type of this geometry to spline and creates an empty spline structure.
|
||||
This function will release any mesh or spline structure that the geometry may already contain.
|
||||
@return The spline information structure. This pointer will always be valid. */
|
||||
FCDGeometrySpline* CreateSpline();
|
||||
|
||||
/** @deprecated [INTERNAL] Clones the geometry entity.
|
||||
Works only on mesh geometry. Creates a full copy of the geometry, with the vertices overwritten
|
||||
by the given data: this is used when importing COLLADA 1.3 skin controllers.
|
||||
You will need to release the cloned entity.
|
||||
@param newPositions The list of vertex position that will
|
||||
overwrite the current mesh vertex positions. This list may be empty.
|
||||
@param newPositionsStride The stride, in bytes, of the newPositions list.
|
||||
For an empty newPositions list, this value is discarded.
|
||||
@param newNormals The list of vertex normals that will overwrite
|
||||
the current mesh vertex normals. This list may be empty.
|
||||
@param newNormalsStride The stride, in bytes, of the newNormals list.
|
||||
For an empty newNormals list, this value is discarded.
|
||||
@return The cloned geometry entity. This pointer will be NULL,
|
||||
if the geometry is not a mesh. You will need to release this pointer. */
|
||||
FCDGeometry* Clone(FloatList& newPositions, uint32 newPositionsStride, FloatList& newNormals, uint32 newNormalsStride);
|
||||
|
||||
/** [INTERNAL] Reads in the \<geometry\> element from a given COLLADA XML tree node.
|
||||
@param node The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the geometry.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* node);
|
||||
|
||||
/** [INTERNAL] Writes out the \<geometry\> element to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the geometry information.
|
||||
@return The created \<geometry\> element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif // _FCD_GEOMETRY_H_
|
||||
@@ -1,168 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDController.h"
|
||||
#include "FCDocument/FCDEntity.h"
|
||||
#include "FCDocument/FCDGeometry.h"
|
||||
#include "FCDocument/FCDGeometryInstance.h"
|
||||
#include "FCDocument/FCDGeometryMesh.h"
|
||||
#include "FCDocument/FCDGeometryPolygons.h"
|
||||
#include "FCDocument/FCDMaterialInstance.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
// Parasitic: Write out the instantiation information to the xml node tree
|
||||
xmlNode* FCDEntityInstance::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* instanceNode = NULL;
|
||||
if (entity != NULL)
|
||||
{
|
||||
const char* instanceEntityName;
|
||||
switch (entity->GetType())
|
||||
{
|
||||
case FCDEntity::ANIMATION: instanceEntityName = DAE_INSTANCE_ANIMATION_ELEMENT; break;
|
||||
case FCDEntity::CAMERA: instanceEntityName = DAE_INSTANCE_CAMERA_ELEMENT; break;
|
||||
case FCDEntity::CONTROLLER: instanceEntityName = DAE_INSTANCE_CONTROLLER_ELEMENT; break;
|
||||
case FCDEntity::EFFECT: instanceEntityName = DAE_INSTANCE_EFFECT_ELEMENT; break;
|
||||
case FCDEntity::GEOMETRY: instanceEntityName = DAE_INSTANCE_GEOMETRY_ELEMENT; break;
|
||||
case FCDEntity::LIGHT: instanceEntityName = DAE_INSTANCE_LIGHT_ELEMENT; break;
|
||||
case FCDEntity::MATERIAL: instanceEntityName = DAE_INSTANCE_MATERIAL_ELEMENT; break;
|
||||
case FCDEntity::PHYSICS_MODEL: instanceEntityName = DAE_INSTANCE_PHYSICS_MODEL_ELEMENT; break;
|
||||
case FCDEntity::PHYSICS_RIGID_BODY: instanceEntityName = DAE_INSTANCE_RIGID_BODY_ELEMENT; break;
|
||||
case FCDEntity::PHYSICS_RIGID_CONSTRAINT: instanceEntityName = DAE_INSTANCE_RIGID_CONSTRAINT_ELEMENT; break;
|
||||
case FCDEntity::SCENE_NODE: instanceEntityName = DAE_INSTANCE_NODE_ELEMENT; break;
|
||||
|
||||
case FCDEntity::ANIMATION_CLIP:
|
||||
case FCDEntity::ENTITY:
|
||||
case FCDEntity::IMAGE:
|
||||
case FCDEntity::TEXTURE:
|
||||
default: instanceEntityName = DAEERR_UNKNOWN_ELEMENT;
|
||||
}
|
||||
|
||||
instanceNode = AddChild(parentNode, instanceEntityName);
|
||||
AddAttribute(instanceNode, DAE_URL_ATTRIBUTE, string("#") + entity->GetDaeId());
|
||||
}
|
||||
return instanceNode;
|
||||
}
|
||||
|
||||
FCDGeometryInstance::FCDGeometryInstance(FCDocument* document, FCDEntity* entity) : FCDEntityInstance(document, entity)
|
||||
{
|
||||
}
|
||||
|
||||
FCDGeometryInstance::~FCDGeometryInstance()
|
||||
{
|
||||
CLEAR_POINTER_VECTOR(materials);
|
||||
}
|
||||
|
||||
// Access Bound Materials
|
||||
FCDMaterialInstance* FCDGeometryInstance::FindMaterialInstance(const fstring& semantic)
|
||||
{
|
||||
for (FCDMaterialInstanceList::iterator itB = materials.begin(); itB != materials.end(); ++itB)
|
||||
{
|
||||
if ((*itB)->GetSemantic() == semantic) return (*itB);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const FCDMaterialInstance* FCDGeometryInstance::FindMaterialInstance(const fstring& semantic) const
|
||||
{
|
||||
for (FCDMaterialInstanceList::const_iterator itB = materials.begin(); itB != materials.end(); ++itB)
|
||||
{
|
||||
if ((*itB)->GetSemantic() == semantic) return (*itB);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Load the geometry instance from the COLLADA document
|
||||
FUStatus FCDGeometryInstance::LoadFromXML(xmlNode* instanceNode)
|
||||
{
|
||||
FUStatus status = FCDEntityInstance::LoadFromXML(instanceNode);
|
||||
if (!status) return status;
|
||||
|
||||
if (entity == NULL)
|
||||
{
|
||||
return status.Fail(FS("Trying to instantiate non-valid geometric entity."), instanceNode->line);
|
||||
}
|
||||
|
||||
// Check for the expected instantiation node type
|
||||
if (!IsEquivalent(instanceNode->name, DAE_INSTANCE_GEOMETRY_ELEMENT) && !IsEquivalent(instanceNode->name, DAE_INSTANCE_CONTROLLER_ELEMENT)
|
||||
&& !IsEquivalent(instanceNode->name, DAE_INSTANCE_ELEMENT))
|
||||
{
|
||||
return status.Fail(FS("Unknown element for instantiation of entity: ") + TO_FSTRING(entity->GetDaeId()), instanceNode->line);
|
||||
}
|
||||
|
||||
// Look for the <bind_material> element. The others are discarded for now.
|
||||
xmlNode* bindMaterialNode = FindChildByType(instanceNode, DAE_BINDMATERIAL_ELEMENT);
|
||||
if (bindMaterialNode != NULL)
|
||||
{
|
||||
// Retrieve the list of the <technique_common><instance_material> elements.
|
||||
xmlNode* techniqueNode = FindChildByType(bindMaterialNode, DAE_TECHNIQUE_COMMON_ELEMENT);
|
||||
xmlNodeList materialNodes;
|
||||
FindChildrenByType(techniqueNode, DAE_INSTANCE_MATERIAL_ELEMENT, materialNodes);
|
||||
for (xmlNodeList::iterator itM = materialNodes.begin(); itM != materialNodes.end(); ++itM)
|
||||
{
|
||||
FCDMaterialInstance* material = new FCDMaterialInstance(GetDocument(), this);
|
||||
status.AppendStatus(material->LoadFromXML(*itM));
|
||||
materials.push_back(material);
|
||||
}
|
||||
}
|
||||
|
||||
if (materials.empty())
|
||||
{
|
||||
// COLLADA 1.3 backward compatibility: Create blank material instances for all the geometry's
|
||||
// polygons that have a valid material semantic
|
||||
FCDEntity* itE = entity;
|
||||
while (itE != NULL && itE->GetType() == FCDEntity::CONTROLLER) itE = ((FCDController*) itE)->GetBaseTarget();
|
||||
if (itE != NULL)
|
||||
{
|
||||
FCDGeometry* geometry = (FCDGeometry*) itE;
|
||||
if (geometry->IsMesh())
|
||||
{
|
||||
FCDGeometryMesh* mesh = geometry->GetMesh();
|
||||
size_t polygonsCount = mesh->GetPolygonsCount();
|
||||
for (size_t i = 0; i < polygonsCount; ++i)
|
||||
{
|
||||
FCDGeometryPolygons* polygons = mesh->GetPolygons(i);
|
||||
const fstring& materialSemantic = polygons->GetMaterialSemantic();
|
||||
|
||||
if (!materialSemantic.empty())
|
||||
{
|
||||
FCDMaterialInstance* material = new FCDMaterialInstance(GetDocument(), this);
|
||||
status.AppendStatus(material->LoadFromId(FUStringConversion::ToString(materialSemantic)));
|
||||
materials.push_back(material);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out the instantiation information to the xml node tree
|
||||
xmlNode* FCDGeometryInstance::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* instanceNode = FCDEntityInstance::WriteToXML(parentNode);
|
||||
if (!materials.empty())
|
||||
{
|
||||
xmlNode* bindMaterialNode = AddChild(instanceNode, DAE_BINDMATERIAL_ELEMENT);
|
||||
xmlNode* techniqueCommonNode = AddChild(bindMaterialNode, DAE_TECHNIQUE_COMMON_ELEMENT);
|
||||
for (FCDMaterialInstanceList::const_iterator itM = materials.begin(); itM != materials.end(); ++itM)
|
||||
{
|
||||
(*itM)->WriteToXML(techniqueCommonNode);
|
||||
}
|
||||
}
|
||||
return instanceNode;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#ifndef _FCD_GEOMETRY_ENTITY_H_
|
||||
#define _FCD_GEOMETRY_ENTITY_H_
|
||||
|
||||
#include "FCDocument/FCDEntityInstance.h"
|
||||
|
||||
class FCDocument;
|
||||
class FCDMaterialInstance;
|
||||
|
||||
typedef vector<FCDMaterialInstance*> FCDMaterialInstanceList;
|
||||
|
||||
class FCOLLADA_EXPORT FCDGeometryInstance : public FCDEntityInstance
|
||||
{
|
||||
private:
|
||||
FCDMaterialInstanceList materials;
|
||||
|
||||
public:
|
||||
FCDGeometryInstance(FCDocument* document, FCDEntity* entity);
|
||||
virtual ~FCDGeometryInstance();
|
||||
|
||||
// FCDEntity override for RTTI-like
|
||||
virtual Type GetType() const { return GEOMETRY; }
|
||||
|
||||
// Access Bound Materials
|
||||
FCDMaterialInstance* FindMaterialInstance(const fstring& semantic);
|
||||
const FCDMaterialInstance* FindMaterialInstance(const fstring& semantic) const;
|
||||
const FCDMaterialInstanceList& GetMaterialInstanceList() const { return materials; }
|
||||
|
||||
// Load the geometry instance from the COLLADA document
|
||||
virtual FUStatus LoadFromXML(xmlNode* instanceNode);
|
||||
|
||||
// Write out the instantiation information to the xml node tree
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif // _FCD_GEOMETRY_ENTITY_H_
|
||||
@@ -1,358 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDGeometry.h"
|
||||
#include "FCDocument/FCDGeometryMesh.h"
|
||||
#include "FCDocument/FCDGeometryPolygons.h"
|
||||
#include "FCDocument/FCDGeometrySource.h"
|
||||
#include "FUtils/FUStringConversion.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDGeometryMesh::FCDGeometryMesh(FCDocument* document, FCDGeometry* _parent) : FCDObject(document, "FCDGeometryMesh")
|
||||
{
|
||||
m_convex = false;
|
||||
parent = _parent;
|
||||
faceVertexCount = faceCount = holeCount = 0;
|
||||
isDoubleSided = true;
|
||||
}
|
||||
|
||||
FCDGeometryMesh::~FCDGeometryMesh()
|
||||
{
|
||||
CLEAR_POINTER_VECTOR(sources);
|
||||
CLEAR_POINTER_VECTOR(polygons);
|
||||
faceVertexCount = faceCount = 0;
|
||||
parent = NULL;
|
||||
}
|
||||
|
||||
// Retrieve the parent's id
|
||||
const string& FCDGeometryMesh::GetDaeId() const
|
||||
{
|
||||
return parent->GetDaeId();
|
||||
}
|
||||
|
||||
// Search for a data source in the geometry node
|
||||
FCDGeometrySource* FCDGeometryMesh::FindSourceById(const string& id)
|
||||
{
|
||||
const char* localId = id.c_str();
|
||||
if (localId[0] == '#') ++localId;
|
||||
for (FCDGeometrySourceList::iterator it = sources.begin(); it != sources.end(); ++it)
|
||||
{
|
||||
if ((*it)->GetSourceId() == localId) return (*it);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Search for a data source in the geometry node
|
||||
const FCDGeometrySource* FCDGeometryMesh::FindSourceById(const string& id) const
|
||||
{
|
||||
const char* localId = id.c_str();
|
||||
if (localId[0] == '#') ++localId;
|
||||
for (FCDGeometrySourceList::const_iterator it = sources.begin(); it != sources.end(); ++it)
|
||||
{
|
||||
if ((*it)->GetSourceId() == localId) return (*it);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Retrieve the source for the vertex position
|
||||
FCDGeometrySource* FCDGeometryMesh::GetPositionSource()
|
||||
{
|
||||
string vertexSourceId;
|
||||
for (FCDGeometrySourceList::iterator itS = vertexSources.begin(); itS != vertexSources.end(); ++itS)
|
||||
{
|
||||
if ((*itS)->GetSourceType() == FUDaeGeometryInput::POSITION) return (*itS);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Retrieve the source of the vertex position
|
||||
const FCDGeometrySource* FCDGeometryMesh::GetPositionSource() const
|
||||
{
|
||||
string vertexSourceId;
|
||||
for (FCDGeometrySourceList::const_iterator itS = vertexSources.begin(); itS != vertexSources.end(); ++itS)
|
||||
{
|
||||
if ((*itS)->GetSourceType() == FUDaeGeometryInput::POSITION) return (*itS);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Creates a new polygon group.
|
||||
FCDGeometryPolygons* FCDGeometryMesh::AddPolygons()
|
||||
{
|
||||
FCDGeometryPolygons* polys = new FCDGeometryPolygons(GetDocument(), this);
|
||||
polygons.push_back(polys);
|
||||
|
||||
// Add to this new polygons all the per-vertex sources.
|
||||
for (FCDGeometrySourceList::iterator itS = vertexSources.begin(); itS != vertexSources.end(); ++itS)
|
||||
{
|
||||
polys->AddInput(*itS, 0);
|
||||
}
|
||||
|
||||
return polys;
|
||||
}
|
||||
|
||||
// Creates a new per-vertex data source
|
||||
FCDGeometrySource* FCDGeometryMesh::AddVertexSource()
|
||||
{
|
||||
FCDGeometrySource* vertexSource = AddSource();
|
||||
vertexSources.push_back(vertexSource);
|
||||
|
||||
// Add this new per-vertex data source to all the existing polygon groups, at offset 0.
|
||||
for (FCDGeometryPolygonsList::iterator itP = polygons.begin(); itP != polygons.end(); ++itP)
|
||||
{
|
||||
(*itP)->AddInput(vertexSource, 0);
|
||||
}
|
||||
return vertexSource;
|
||||
}
|
||||
|
||||
// Creates a new data source
|
||||
FCDGeometrySource* FCDGeometryMesh::AddSource()
|
||||
{
|
||||
FCDGeometrySource* source = new FCDGeometrySource(GetDocument());
|
||||
sources.push_back(source);
|
||||
return source;
|
||||
}
|
||||
|
||||
// Forces the triangulation of the mesh polygons
|
||||
void FCDGeometryMesh::Triangulate()
|
||||
{
|
||||
for (FCDGeometryPolygonsList::iterator itP = polygons.begin(); itP != polygons.end(); ++itP)
|
||||
{
|
||||
(*itP)->Triangulate();
|
||||
}
|
||||
|
||||
// Recalculate the mesh/polygons statistics
|
||||
Recalculate();
|
||||
}
|
||||
|
||||
// Recalculates all the hole/vertex/face-vertex counts and offsets within the mesh and its polygons
|
||||
void FCDGeometryMesh::Recalculate()
|
||||
{
|
||||
faceCount = holeCount = faceVertexCount = 0;
|
||||
for (FCDGeometryPolygonsList::iterator itP = polygons.begin(); itP != polygons.end(); ++itP)
|
||||
{
|
||||
FCDGeometryPolygons* polygons = *itP;
|
||||
polygons->Recalculate();
|
||||
|
||||
polygons->SetFaceOffset(faceCount);
|
||||
polygons->SetHoleOffset(holeCount);
|
||||
polygons->SetFaceVertexOffset(faceVertexCount);
|
||||
faceCount += polygons->GetFaceCount();
|
||||
holeCount += polygons->GetHoleCount();
|
||||
faceVertexCount += polygons->GetFaceVertexCount();
|
||||
}
|
||||
}
|
||||
|
||||
// Create a copy of this geometry, with the vertices overwritten
|
||||
FCDGeometryMesh* FCDGeometryMesh::Clone(FloatList& newPositions, uint32 newPositionsStride, FloatList& newNormals, uint32 newNormalsStride)
|
||||
{
|
||||
// Create the clone and fill it with the known information
|
||||
FCDGeometryMesh* clone = new FCDGeometryMesh(GetDocument(), NULL);
|
||||
clone->faceCount = faceCount;
|
||||
|
||||
// Clone the source data
|
||||
size_t sourceCount = sources.size();
|
||||
clone->sources.reserve(sourceCount);
|
||||
for (FCDGeometrySourceList::const_iterator itS = sources.begin(); itS != sources.end(); ++itS)
|
||||
{
|
||||
clone->sources.push_back((*itS)->Clone());
|
||||
if (std::find(vertexSources.begin(), vertexSources.end(), (*itS)) != vertexSources.end())
|
||||
{
|
||||
clone->vertexSources.push_back(clone->sources.back());
|
||||
}
|
||||
}
|
||||
|
||||
// Clone the polygons data
|
||||
// Gather up the position and normal data sources
|
||||
FCDGeometrySourceList positionSources, normalSources;
|
||||
size_t polygonsCount = polygons.size();
|
||||
clone->polygons.resize(polygonsCount);
|
||||
for (size_t i = 0; i < polygonsCount; ++i)
|
||||
{
|
||||
clone->polygons[i] = polygons[i]->Clone(clone);
|
||||
|
||||
// Retrieve the position data source
|
||||
FCDGeometryPolygonsInput* positionInput = clone->polygons[i]->FindInput(FUDaeGeometryInput::POSITION);
|
||||
if (positionInput != NULL)
|
||||
{
|
||||
FCDGeometrySource* dataSource = positionInput->source;
|
||||
FUAssert(dataSource != NULL, continue);
|
||||
if (std::find(positionSources.begin(), positionSources.end(), dataSource) == positionSources.end())
|
||||
{
|
||||
positionSources.push_back(dataSource);
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve the normal data source
|
||||
FCDGeometryPolygonsInput* normalInput = clone->polygons[i]->FindInput(FUDaeGeometryInput::NORMAL);
|
||||
if (normalInput != NULL)
|
||||
{
|
||||
FCDGeometrySource* dataSource = normalInput->source;
|
||||
FUAssert(dataSource != NULL, continue);
|
||||
if (std::find(normalSources.begin(), normalSources.end(), dataSource) == normalSources.end())
|
||||
{
|
||||
normalSources.push_back(dataSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Override the position and normal data sources with the given data (from the controller's bind shape)
|
||||
# define OVERWRITE_SOURCES(cloneSources, newSourceData, newSourceStride) { \
|
||||
size_t dataSourceCount = min(cloneSources.size(), newSourceData.size()), offset = 0; \
|
||||
for (size_t i = 0; i < dataSourceCount; ++i) { \
|
||||
FCDGeometrySource* dataSource = cloneSources[i]; \
|
||||
size_t dataCount = dataSource->GetSourceData().size() / dataSource->GetSourceStride(); \
|
||||
if (offset + dataCount > newSourceData.size() / newSourceStride) dataCount = newSourceData.size() / newSourceStride - offset; \
|
||||
if (dataCount == 0) break; \
|
||||
/* Insert the relevant data in this source */ \
|
||||
dataSource->SetSourceData(newSourceData, newSourceStride, offset * newSourceStride, (offset + dataCount) * newSourceStride); \
|
||||
offset += dataCount; \
|
||||
} }
|
||||
|
||||
OVERWRITE_SOURCES(positionSources, newPositions, newPositionsStride);
|
||||
OVERWRITE_SOURCES(normalSources, newNormals, newNormalsStride);
|
||||
# undef OVERWRITE_SOURCES
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Read in the <mesh> node of the COLLADA document
|
||||
FUStatus FCDGeometryMesh::LoadFromXML(xmlNode* meshNode)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// Read in the data sources
|
||||
xmlNodeList sourceDataNodes;
|
||||
FindChildrenByType(meshNode, DAE_SOURCE_ELEMENT, sourceDataNodes);
|
||||
for (xmlNodeList::iterator it = sourceDataNodes.begin(); it != sourceDataNodes.end(); ++it)
|
||||
{
|
||||
FCDGeometrySource* source = AddSource();
|
||||
status.AppendStatus(source->LoadFromXML(*it));
|
||||
if (source->GetSourceStride() < 3) continue;
|
||||
|
||||
// COLLADA 1.3 backward compatibility
|
||||
// Maya-specific: Look for the double-sided flag in the normals source
|
||||
StringList parameterNames; xmlNodeList parameterNodes;
|
||||
xmlNode* mayaTechniqueNode = FindTechnique((*it), DAEMAYA_MAYA_PROFILE);
|
||||
FindParameters(mayaTechniqueNode, parameterNames, parameterNodes);
|
||||
size_t parameterCount = parameterNodes.size();
|
||||
for (size_t i = 0; i < parameterCount; ++i)
|
||||
{
|
||||
const char* content = ReadNodeContentDirect(parameterNodes[i]);
|
||||
if (parameterNames[i] == DAEMAYA_DOUBLE_SIDED_PARAMETER) isDoubleSided = FUStringConversion::ToBoolean(content);
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve the <vertices> node
|
||||
xmlNode* verticesNode = FindChildByType(meshNode, DAE_VERTICES_ELEMENT);
|
||||
if (verticesNode == NULL)
|
||||
{
|
||||
return status.Warning(FS("No <vertices> element in mesh: ") + TO_FSTRING(parent->GetDaeId()), meshNode->line);
|
||||
}
|
||||
|
||||
// Read in the per-vertex inputs
|
||||
bool hasPositions = false;
|
||||
|
||||
xmlNodeList vertexInputNodes;
|
||||
FindChildrenByType(verticesNode, DAE_INPUT_ELEMENT, vertexInputNodes);
|
||||
for (xmlNodeList::iterator it = vertexInputNodes.begin(); it < vertexInputNodes.end(); ++it)
|
||||
{
|
||||
xmlNode* vertexInputNode = *it;
|
||||
string inputSemantic = ReadNodeSemantic(vertexInputNode);
|
||||
FUDaeGeometryInput::Semantic semantic = FUDaeGeometryInput::FromString(inputSemantic);
|
||||
if (semantic == FUDaeGeometryInput::POSITION || semantic == FUDaeGeometryInput::NORMAL
|
||||
|| semantic == FUDaeGeometryInput::COLOR || semantic == FUDaeGeometryInput::TEXCOORD)
|
||||
{
|
||||
string sourceId = ReadNodeSource(vertexInputNode);
|
||||
FCDGeometrySource* source = FindSourceById(sourceId);
|
||||
if (source == NULL)
|
||||
{
|
||||
return status.Fail(FS("Mesh has source with an unknown id: ") + TO_FSTRING(parent->GetDaeId()), vertexInputNode->line);
|
||||
}
|
||||
source->SetSourceType(semantic);
|
||||
if (semantic == FUDaeGeometryInput::POSITION) hasPositions = true;
|
||||
vertexSources.push_back(source);
|
||||
}
|
||||
}
|
||||
if (!hasPositions)
|
||||
{
|
||||
return status.Warning(FS("No vertex position input node in mesh: ") + TO_FSTRING(parent->GetDaeId()), verticesNode->line);
|
||||
}
|
||||
|
||||
// Create our rendering object and read in the tessellation
|
||||
xmlNodeList polygonsNodes;
|
||||
FindChildrenByType(meshNode, DAE_POLYGONS_ELEMENT, polygonsNodes);
|
||||
FindChildrenByType(meshNode, DAE_TRIANGLES_ELEMENT, polygonsNodes);
|
||||
FindChildrenByType(meshNode, DAE_POLYLIST_ELEMENT, polygonsNodes);
|
||||
if (polygonsNodes.empty())
|
||||
{
|
||||
return status.Warning(FS("No tessellation found for mesh: ") + TO_FSTRING(parent->GetDaeId()), meshNode->line);
|
||||
}
|
||||
for (xmlNodeList::iterator it = polygonsNodes.begin(); it != polygonsNodes.end(); ++it)
|
||||
{
|
||||
// Create the geometry polygons object
|
||||
xmlNode* polygonsNode = *it;
|
||||
FCDGeometryPolygons* polygon = new FCDGeometryPolygons(GetDocument(), this);
|
||||
polygons.push_back(polygon);
|
||||
status = polygon->LoadFromXML(polygonsNode);
|
||||
if (!status) return status;
|
||||
}
|
||||
|
||||
// Calculate the important statistics/offsets/counts
|
||||
Recalculate();
|
||||
|
||||
// Apply the length factor on the vertex positions
|
||||
float lengthFactor = GetDocument()->GetLengthUnitConversion();
|
||||
FCDGeometrySource* positionSource = GetPositionSource();
|
||||
if (positionSource == NULL)
|
||||
{
|
||||
return status.Fail(FS("Cannot process the vertex POSITION source for mesh: ") + TO_FSTRING(parent->GetDaeId()), meshNode->line);
|
||||
}
|
||||
FloatList& positionData = positionSource->GetSourceData();
|
||||
for (FloatList::iterator it = positionData.begin(); it != positionData.end(); ++it) (*it) *= lengthFactor;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out the <mesh> node to the COLLADA xml tree
|
||||
xmlNode* FCDGeometryMesh::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* meshNode = AddChild(parentNode, DAE_MESH_ELEMENT);
|
||||
|
||||
// Write out the sources
|
||||
for (FCDGeometrySourceList::const_iterator itS = sources.begin(); itS != sources.end(); ++itS)
|
||||
{
|
||||
(*itS)->WriteToXML(meshNode);
|
||||
}
|
||||
|
||||
// Write out the <vertices> element
|
||||
xmlNode* verticesNode = AddChild(meshNode, DAE_VERTICES_ELEMENT);
|
||||
for (FCDGeometrySourceList::const_iterator itS = vertexSources.begin(); itS != vertexSources.end(); ++itS)
|
||||
{
|
||||
const char* semantic = FUDaeGeometryInput::ToString((*itS)->GetSourceType());
|
||||
AddInput(verticesNode, (*itS)->GetSourceId(), semantic);
|
||||
}
|
||||
FUSStringBuilder verticesNodeId(GetDaeId()); verticesNodeId.append("-vertices");
|
||||
AddAttribute(verticesNode, DAE_ID_ATTRIBUTE, verticesNodeId);
|
||||
|
||||
// Write out the polygons
|
||||
for (FCDGeometryPolygonsList::const_iterator itP = polygons.begin(); itP != polygons.end(); ++itP)
|
||||
{
|
||||
(*itP)->WriteToXML(meshNode);
|
||||
}
|
||||
|
||||
return meshNode;
|
||||
}
|
||||
@@ -1,211 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDGeometryMesh.h
|
||||
This file contains the FCDGeometryMesh class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_GEOMETRY_MESH_H_
|
||||
#define _FCD_GEOMETRY_MESH_H_
|
||||
|
||||
#include "FCDocument/FCDObject.h"
|
||||
#include "FUtils/FUDaeEnum.h"
|
||||
|
||||
class FCDocument;
|
||||
class FCDGeometry;
|
||||
class FCDGeometryPolygons;
|
||||
class FCDGeometrySource;
|
||||
|
||||
/** A dynamically-sized array of FCDGeometrySource objects. */
|
||||
typedef vector<FCDGeometrySource*> FCDGeometrySourceList;
|
||||
/** A dynamically-sized array of FCDGeometryPolygons objects. */
|
||||
typedef vector<FCDGeometryPolygons*> FCDGeometryPolygonsList;
|
||||
|
||||
/**
|
||||
A COLLADA geometric mesh.
|
||||
A COLLADA geometric mesh is a list of vertices tied together in polygons.
|
||||
A set of per-vertex data is used to determine the vertices of the mesh.
|
||||
This data usually includes a single list: of vertex positions, but it may also
|
||||
contain per-vertex colors, per-vertex normals or per-vertex texture coordinates.
|
||||
The other data sources declare per-vertex-face data.
|
||||
|
||||
The faces of a mesh may be split across different groups, as they may have
|
||||
different materials assigned to them. The FCDGeometryPolygons objects contains one such group
|
||||
of faces.
|
||||
|
||||
@ingroup FCDGeometry
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDGeometryMesh : public FCDObject
|
||||
{
|
||||
private:
|
||||
FCDGeometry* parent;
|
||||
FCDGeometrySourceList sources;
|
||||
FCDGeometryPolygonsList polygons;
|
||||
|
||||
FCDGeometrySourceList vertexSources;
|
||||
size_t faceCount, holeCount;
|
||||
size_t faceVertexCount;
|
||||
bool isDoubleSided; // Maya-specific, defaults to true
|
||||
|
||||
public:
|
||||
/** Contructor: do not use directly. Use FCDGeometry::AddMesh instead.
|
||||
@param document The COLLADA document which owns this mesh.
|
||||
@param parent The geometry entity which contains this mesh. */
|
||||
FCDGeometryMesh(FCDocument* document, FCDGeometry* parent);
|
||||
|
||||
/** Destructor: do not use directly. All geometric meshes are released with the geometry that they belong to. */
|
||||
virtual ~FCDGeometryMesh();
|
||||
|
||||
/** Retrieves the number of faces within the geometric mesh.
|
||||
@return The number of faces within the geometric mesh. */
|
||||
inline size_t GetFaceCount() const { return faceCount; }
|
||||
|
||||
/** Retrieves the number of holes within the faces of the geometric mesh.
|
||||
As one face may contain multiple holes, this value may be larger than the number of faces.
|
||||
@return The number of holes within the faces of the geometric mesh. */
|
||||
inline size_t GetHoleCount() const { return holeCount; }
|
||||
|
||||
/** Retrieves the total number of per-face vertices in the mesh.
|
||||
This function makes no assumption about the uniqueness of the per-face vertices.
|
||||
@return The total number of per-face vertices in the mesh. */
|
||||
inline size_t GetFaceVertexCount() const { return faceVertexCount; }
|
||||
|
||||
/** Retrieves whether the mesh should be treated as double-sided.
|
||||
This flag does not belong to COLLADA but is exported at the geometric-level by ColladaMaya.
|
||||
@return Whether the mesh is double-sided. */
|
||||
inline bool IsDoubleSided() const { return isDoubleSided; }
|
||||
|
||||
/** Retrieves the COLLADA id of the mesh.
|
||||
This is a shortcut to the parent geometry's COLLADA id.
|
||||
@return The COLLADA id of the mesh. */
|
||||
const string& GetDaeId() const;
|
||||
|
||||
/** Retrieves the number of independent polygon groups.
|
||||
Each polygon group is represented within a FCDGeometryPolygons object.
|
||||
An independent polygon group is usually created to assign a different material to different parts of the mesh
|
||||
or to assign partial texture coordinates and texture tangents to different parts of the mesh.
|
||||
@return The number of independent polygon groups. */
|
||||
inline size_t GetPolygonsCount() const { return polygons.size(); }
|
||||
|
||||
/** Retrieves a specific polygon group.
|
||||
Each polygon group is represented within a FCDGeometryPolygons object.
|
||||
An independent polygon group is usually created to assign a different material to different parts of the mesh
|
||||
or to assign partial texture coordinates and texture tangents to different parts of the mesh.
|
||||
@param index The index of the polygon group. This index should be less than the number
|
||||
of independent polygon groups returned by the GetPolygonsCount function.
|
||||
@return The polygon group. This pointer will be NULL if the index is out-of-bounds. */
|
||||
inline FCDGeometryPolygons* GetPolygons(size_t index) { FUAssert(index < GetPolygonsCount(), return NULL); return polygons.at(index); }
|
||||
inline const FCDGeometryPolygons* GetPolygons(size_t index) const { FUAssert(index < GetPolygonsCount(), return NULL); return polygons.at(index); } /**< See above. */
|
||||
|
||||
/** Creates a new polygon group.
|
||||
Each polygon group is represented within a FCDGeometryPolygons object.
|
||||
The new polygon group will be assigned all the existing per-vertex data sources.
|
||||
No material will be assigned to the new polygon group.
|
||||
@return The new polygon group. This pointer should never be NULL. */
|
||||
FCDGeometryPolygons* AddPolygons();
|
||||
|
||||
/** [INTERNAL] Retrieves the list of per-vertex data sources.
|
||||
There should usually be one per-vertex data source that contains positions.
|
||||
All the sources within this list are also present within the data source list.
|
||||
@return The list of per-vertex data sources. */
|
||||
inline FCDGeometrySourceList& GetVertexSources() { return vertexSources; }
|
||||
inline const FCDGeometrySourceList& GetVertexSources() const { return vertexSources; } /**< See above. */
|
||||
|
||||
/** Retrieves the number of per-vertex data sources.
|
||||
This number should always be lesser or equal to the number of data sources, as each per-vertex
|
||||
data source is also included within the list of data sources.
|
||||
@return The number of per-vertex data sources. */
|
||||
inline size_t GetVertexSourceCount() const { return vertexSources.size(); }
|
||||
|
||||
/** Retrieves a specific per-vertex data source.
|
||||
All the per-vertex data sources are also included in the list of data sources.
|
||||
@param index The index of the per-vertex data source. This index should be less than the number of
|
||||
per-vertex data sources returns by the GetVertexSourceCount function.
|
||||
@return The per-vertex data source. This pointer will be NULL if the index is out-of-bounds. */
|
||||
inline FCDGeometrySource* GetVertexSource(size_t index) { FUAssert(index < GetVertexSourceCount(), return NULL); return vertexSources.at(index); }
|
||||
inline const FCDGeometrySource* GetVertexSource(size_t index) const { FUAssert(index < GetVertexSourceCount(), return NULL); return vertexSources.at(index); } /**< See above. */
|
||||
|
||||
/** Creates a new per-vertex data source for this geometric mesh.
|
||||
The per-vertex data source will be added to both the per-vertex data source list and the data source list.
|
||||
The new per-vertex data source will automatically be added to all the existing polygon groups.
|
||||
@return The new per-vertex data source. This pointer should never be NULL. */
|
||||
FCDGeometrySource* AddVertexSource();
|
||||
|
||||
/** [INTERNAL] Retrieves the data source that matches the given COLLADA id.
|
||||
@param id A valid COLLADA id.
|
||||
@return The data source. This pointer will be NULL if no matching data source was found. */
|
||||
FCDGeometrySource* FindSourceById(const string& id);
|
||||
const FCDGeometrySource* FindSourceById(const string& id) const; /**< See above. */
|
||||
|
||||
/** Retrieves the per-vertex data that specifically contains the vertex positions.
|
||||
If there are more than one per-vertex data source that contains vertex positions, the first one is returned.
|
||||
@return A per-vertex data source that contains vertex positions. This pointer will be NULL
|
||||
in the unlikely possibility that there are no per-vertex data source that contains vertex positions. */
|
||||
FCDGeometrySource* GetPositionSource();
|
||||
const FCDGeometrySource* GetPositionSource() const; /**< See above. */
|
||||
|
||||
/** Retrieves the number of data sources contained within this geometric mesh.
|
||||
@return The number of data sources within the mesh. */
|
||||
inline size_t GetSourceCount() const { return sources.size(); }
|
||||
|
||||
/** Retrieves a specific data source.
|
||||
@param index The index of the data source. This index should be less than the number of
|
||||
data sources returns by the GetSourceCount function.
|
||||
@return The data source. This pointer will be NULL if the index is out-of-bounds. */
|
||||
inline FCDGeometrySource* GetSource(size_t index) { FUAssert(index < GetSourceCount(), return NULL); return sources.at(index); }
|
||||
inline const FCDGeometrySource* GetSource(size_t index) const { FUAssert(index < GetSourceCount(), return NULL); return sources.at(index); } /**< See above. */
|
||||
|
||||
/** Creates a new data source for this geometric mesh.
|
||||
The new data source will not be added to any of the existing polygon groups.
|
||||
@return The new per-vertex data source. This pointer should never be NULL. */
|
||||
FCDGeometrySource* AddSource();
|
||||
|
||||
/** Triangulates the mesh.
|
||||
A simple fanning techique is currently used: holes will not be triangulated correctly. */
|
||||
void Triangulate();
|
||||
|
||||
/** [INTERNAL] Forces the recalculation of the hole count, vertex count, face-vertex counts and their offsets.
|
||||
Since the counts and offsets are buffered at the geometric mesh object level, this function allows the polygon
|
||||
groups to force the recalculation of the buffered values, when they are modified. */
|
||||
void Recalculate();
|
||||
|
||||
/** [INTERNAL] Creates a copy of this mesh. You may use the FCDGeometry::Clone function instead of this function.
|
||||
Creates a full copy of the geometry, with the vertices overwritten
|
||||
by the given data: this is used when importing COLLADA 1.3 skin controllers.
|
||||
You will need to release the cloned entity.
|
||||
@see FCDGeometry::Clone.
|
||||
@param newPositions The list of vertex position that will
|
||||
overwrite the current mesh vertex positions. This list may be empty.
|
||||
@param newPositionsStride The stride, in bytes, of the newPositions list.
|
||||
For an empty newPositions list, this value is discarded.
|
||||
@param newNormals The list of vertex normals that will overwrite
|
||||
the current mesh vertex normals. This list may be empty.
|
||||
@param newNormalsStride The stride, in bytes, of the newNormals list.
|
||||
For an empty newNormals list, this value is discarded.
|
||||
@return The cloned geometry entity. You will need to release this pointer. */
|
||||
FCDGeometryMesh* Clone(FloatList& newPositions, uint32 newPositionsStride, FloatList& newNormals, uint32 newNormalsStride);
|
||||
|
||||
/** [INTERNAL] Reads in the \<mesh\> element from a given COLLADA XML tree node.
|
||||
@param meshNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the geometric mesh.*/
|
||||
FUStatus LoadFromXML(xmlNode* meshNode);
|
||||
|
||||
/** [INTERNAL] Writes out the \<mesh\> element to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the geometric mesh.
|
||||
@return The created \<mesh\> element XML tree node. */
|
||||
xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
|
||||
bool m_convex;
|
||||
};
|
||||
|
||||
#endif // _FCD_GEOMETRY_MESH_H_
|
||||
@@ -1,811 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDGeometryMesh.h"
|
||||
#include "FCDocument/FCDGeometryPolygons.h"
|
||||
#include "FCDocument/FCDGeometrySource.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
#include "FUtils/FUStringConversion.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
typedef vector<UInt32List> UniqueVerticesTable;
|
||||
|
||||
FCDGeometryPolygons::FCDGeometryPolygons(FCDocument* document, FCDGeometryMesh* _parent) : FCDObject(document, "FCDGeometryPolygons")
|
||||
{
|
||||
parent = _parent;
|
||||
faceVertexCount = 0;
|
||||
faceOffset = faceVertexOffset = 0;
|
||||
}
|
||||
|
||||
FCDGeometryPolygons::~FCDGeometryPolygons()
|
||||
{
|
||||
CLEAR_POINTER_VECTOR(inputs);
|
||||
idxOwners.clear();
|
||||
holeFaces.clear();
|
||||
parent = NULL;
|
||||
}
|
||||
|
||||
|
||||
// Creates a new face.
|
||||
void FCDGeometryPolygons::AddFace(uint32 degree)
|
||||
{
|
||||
faceVertexCounts.push_back(degree);
|
||||
|
||||
// Inserts empty indices
|
||||
for (FCDGeometryPolygonsInputList::iterator it = idxOwners.begin(); it != idxOwners.end(); ++it)
|
||||
{
|
||||
FCDGeometryPolygonsInput* input = (*it);
|
||||
input->indices.resize(input->indices.size() + degree, 0);
|
||||
}
|
||||
|
||||
parent->Recalculate();
|
||||
}
|
||||
|
||||
// Removes a face
|
||||
void FCDGeometryPolygons::RemoveFace(size_t index)
|
||||
{
|
||||
FUAssert(index < GetFaceCount(), return);
|
||||
|
||||
// Remove the associated indices, if they exist.
|
||||
size_t offset = GetFaceVertexOffset(index);
|
||||
size_t indexCount = GetFaceVertexCount(index);
|
||||
for (FCDGeometryPolygonsInputList::iterator it = idxOwners.begin(); it != idxOwners.end(); ++it)
|
||||
{
|
||||
FCDGeometryPolygonsInput* input = (*it);
|
||||
size_t inputIndexCount = input->indices.size();
|
||||
if (offset < inputIndexCount)
|
||||
{
|
||||
UInt32List::iterator end, begin = input->indices.begin() + offset;
|
||||
if (offset + indexCount < inputIndexCount) end = begin + indexCount;
|
||||
else end = input->indices.end();
|
||||
input->indices.erase(begin, end);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the face and its holes
|
||||
size_t holeBefore = GetHoleCountBefore(index);
|
||||
UInt32List::iterator itFV = faceVertexCounts.begin() + index + holeBefore;
|
||||
size_t holeCount = GetHoleCount(index);
|
||||
faceVertexCounts.erase(itFV, itFV + holeCount + 1); // +1 in order to remove the polygon as well as the holes.
|
||||
|
||||
parent->Recalculate();
|
||||
}
|
||||
|
||||
// Calculates the offset of face-vertex pairs before the given face index within the polygon set.
|
||||
size_t FCDGeometryPolygons::GetFaceVertexOffset(size_t index) const
|
||||
{
|
||||
size_t offset = 0;
|
||||
|
||||
// We'll need to skip over the holes
|
||||
size_t holeCount = GetHoleCountBefore(index);
|
||||
if (index + holeCount < faceVertexCounts.size())
|
||||
{
|
||||
// Sum up the wanted offset
|
||||
UInt32List::const_iterator end = faceVertexCounts.begin() + index + holeCount;
|
||||
for (UInt32List::const_iterator it = faceVertexCounts.begin(); it != end; ++it)
|
||||
{
|
||||
offset += (*it);
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
// Calculates the number of holes within the polygon set that appear before the given face index.
|
||||
size_t FCDGeometryPolygons::GetHoleCountBefore(size_t index) const
|
||||
{
|
||||
size_t holeCount = 0;
|
||||
for (UInt32List::const_iterator it = holeFaces.begin(); it != holeFaces.end(); ++it)
|
||||
{
|
||||
if ((*it) < index) ++holeCount;
|
||||
}
|
||||
return holeCount;
|
||||
}
|
||||
|
||||
// Retrieves the number of holes within a given face.
|
||||
size_t FCDGeometryPolygons::GetHoleCount(size_t index) const
|
||||
{
|
||||
size_t holeCount = 0;
|
||||
for (size_t i = GetFaceVertexOffset(index) + 1; i < faceVertexCounts.size(); ++i)
|
||||
{
|
||||
bool isHoled = std::find(holeFaces.begin(), holeFaces.end(), i) != holeFaces.end();
|
||||
if (!isHoled) break;
|
||||
else ++holeCount;
|
||||
}
|
||||
return holeCount;
|
||||
}
|
||||
|
||||
// The number of face-vertex pairs for a given face.
|
||||
size_t FCDGeometryPolygons::GetFaceVertexCount(size_t index) const
|
||||
{
|
||||
size_t count = 0;
|
||||
if (index < GetFaceCount())
|
||||
{
|
||||
size_t holeCount = GetHoleCount(index);
|
||||
UInt32List::const_iterator it = faceVertexCounts.begin() + index + GetHoleCountBefore(index);
|
||||
UInt32List::const_iterator end = it + holeCount + 1; // +1 in order to sum the face-vertex pairs of the polygon as its holes.
|
||||
for (; it != end; ++it) count += (*it);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
FCDGeometryPolygonsInput* FCDGeometryPolygons::AddInput(FCDGeometrySource* source, uint32 offset)
|
||||
{
|
||||
FCDGeometryPolygonsInput* input = new FCDGeometryPolygonsInput();
|
||||
input->source = source;
|
||||
input->idx = offset;
|
||||
input->semantic = source->GetSourceType();
|
||||
|
||||
// Check if the offset is new
|
||||
input->ownsIdx = true;
|
||||
for (FCDGeometryPolygonsInputList::iterator it = inputs.begin(); it != inputs.end(); ++it)
|
||||
{
|
||||
if ((*it)->idx == input->idx)
|
||||
{
|
||||
input->ownsIdx = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inputs.push_back(input);
|
||||
if (input->ownsIdx) idxOwners.push_back(input);
|
||||
return input;
|
||||
}
|
||||
|
||||
void FCDGeometryPolygons::ReleaseInput(FCDGeometryPolygonsInput* input)
|
||||
{
|
||||
FCDGeometryPolygonsInputList::iterator itP = std::find(inputs.begin(), inputs.end(), input);
|
||||
if (itP != inputs.end())
|
||||
{
|
||||
// Before releasing the polygon set input, verify that shared indices are not lost
|
||||
if (input->ownsIdx)
|
||||
{
|
||||
for (FCDGeometryPolygonsInputList::iterator it = inputs.begin(); it != inputs.end(); ++it)
|
||||
{
|
||||
if ((*it)->idx == input->idx && !(*it)->ownsIdx)
|
||||
{
|
||||
(*it)->indices = input->indices;
|
||||
(*it)->ownsIdx = true;
|
||||
idxOwners.push_back(*it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FCDGeometryPolygonsInputList::iterator itO = std::find(idxOwners.begin(), idxOwners.end(), input);
|
||||
if (itO != idxOwners.end()) idxOwners.erase(itO);
|
||||
input->indices.clear();
|
||||
input->ownsIdx = false;
|
||||
}
|
||||
|
||||
// Release the polygon set input
|
||||
SAFE_DELETE(input);
|
||||
inputs.erase(itP);
|
||||
}
|
||||
}
|
||||
|
||||
FCDGeometryPolygonsInput* FCDGeometryPolygons::FindInput(FUDaeGeometryInput::Semantic semantic)
|
||||
{
|
||||
for (FCDGeometryPolygonsInputList::iterator it = inputs.begin(); it != inputs.end(); ++it)
|
||||
{
|
||||
if ((*it)->semantic == semantic) return (*it);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const FCDGeometryPolygonsInput* FCDGeometryPolygons::FindInput(FUDaeGeometryInput::Semantic semantic) const
|
||||
{
|
||||
for (FCDGeometryPolygonsInputList::const_iterator it = inputs.begin(); it != inputs.end(); ++it)
|
||||
{
|
||||
if ((*it)->semantic == semantic) return (*it);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FCDGeometryPolygonsInput* FCDGeometryPolygons::FindInput(FCDGeometrySource* source)
|
||||
{
|
||||
for (FCDGeometryPolygonsInputList::iterator it = inputs.begin(); it != inputs.end(); ++it)
|
||||
{
|
||||
if ((*it)->source == source) return (*it);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const FCDGeometryPolygonsInput* FCDGeometryPolygons::FindInput(const FCDGeometrySource* source) const
|
||||
{
|
||||
for (FCDGeometryPolygonsInputList::const_iterator it = inputs.begin(); it != inputs.end(); ++it)
|
||||
{
|
||||
if ((*it)->source == source) return (*it);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FCDGeometryPolygonsInput* FCDGeometryPolygons::FindInput(const string& sourceId)
|
||||
{
|
||||
const char* s = sourceId.c_str();
|
||||
if (*s == '#') ++s;
|
||||
for (FCDGeometryPolygonsInputList::iterator it = inputs.begin(); it != inputs.end(); ++it)
|
||||
{
|
||||
if ((*it)->source->GetDaeId() == s) return (*it);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FCDGeometryPolygons::FindInputs(FUDaeGeometryInput::Semantic semantic, FCDGeometryPolygonsInputList& _inputs)
|
||||
{
|
||||
for (FCDGeometryPolygonsInputList::iterator it = inputs.begin(); it != inputs.end(); ++it)
|
||||
{
|
||||
if ((*it)->semantic == semantic) _inputs.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
UInt32List* FCDGeometryPolygons::FindIndicesForIdx(uint32 idx)
|
||||
{
|
||||
for (FCDGeometryPolygonsInputList::iterator it = idxOwners.begin(); it != idxOwners.end(); ++it)
|
||||
{
|
||||
if ((*it)->idx == idx) return &(*it)->indices;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const UInt32List* FCDGeometryPolygons::FindIndicesForIdx(uint32 idx) const
|
||||
{
|
||||
for (FCDGeometryPolygonsInputList::const_iterator cit = idxOwners.begin(); cit != idxOwners.end(); ++cit)
|
||||
{
|
||||
if ((*cit)->idx == idx) return &(*cit)->indices;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UInt32List* FCDGeometryPolygons::FindIndices(FCDGeometrySource* source)
|
||||
{
|
||||
FCDGeometryPolygonsInput* input = FindInput(source);
|
||||
return (input != NULL) ? FindIndices(input) : NULL;
|
||||
}
|
||||
|
||||
const UInt32List* FCDGeometryPolygons::FindIndices(const FCDGeometrySource* source) const
|
||||
{
|
||||
const FCDGeometryPolygonsInput* input = FindInput(source);
|
||||
return (input != NULL) ? FindIndices(input) : NULL;
|
||||
}
|
||||
|
||||
UInt32List* FCDGeometryPolygons::FindIndices(FCDGeometryPolygonsInput* input)
|
||||
{
|
||||
FCDGeometryPolygonsInputList::iterator itP = std::find(inputs.begin(), inputs.end(), input);
|
||||
return itP != inputs.end() ? FindIndicesForIdx(input->idx) : NULL;
|
||||
}
|
||||
|
||||
const UInt32List* FCDGeometryPolygons::FindIndices(const FCDGeometryPolygonsInput* input) const
|
||||
{
|
||||
FCDGeometryPolygonsInputList::const_iterator itP = std::find(inputs.begin(), inputs.end(), input);
|
||||
return itP != inputs.end() ? FindIndicesForIdx(input->idx) : NULL;
|
||||
}
|
||||
|
||||
// Forces the triangulation of the polygons
|
||||
void FCDGeometryPolygons::Triangulate()
|
||||
{
|
||||
// Pre-allocate and ready the end index/count buffers
|
||||
UInt32List oldFaceVertexCounts = faceVertexCounts;
|
||||
faceVertexCounts.clear();
|
||||
vector<UInt32List*> dataIndices;
|
||||
vector<UInt32List> oldDataIndices;
|
||||
for (FCDGeometryPolygonsInputList::iterator itI = idxOwners.begin(); itI != idxOwners.end(); ++itI)
|
||||
{
|
||||
UInt32List* indices = &(*itI)->indices;
|
||||
oldDataIndices.push_back(*indices);
|
||||
dataIndices.push_back(indices);
|
||||
indices->clear();
|
||||
}
|
||||
size_t dataIndicesCount = oldDataIndices.size();
|
||||
|
||||
// Rebuild the index/count buffers through simple fan-triangulation.
|
||||
// Drop holes and polygons with less than two vertices.
|
||||
size_t oldOffset = 0, oldFaceCount = oldFaceVertexCounts.size();
|
||||
for (size_t oldFaceIndex = 0; oldFaceIndex < oldFaceCount; ++oldFaceIndex)
|
||||
{
|
||||
size_t oldFaceVertexCount = oldFaceVertexCounts[oldFaceIndex];
|
||||
bool isHole = std::find(holeFaces.begin(), holeFaces.end(), oldFaceIndex) != holeFaces.end();
|
||||
if (!isHole && oldFaceVertexCount >= 3)
|
||||
{
|
||||
// Fan-triangulation: works well on convex polygons.
|
||||
size_t triangleCount = oldFaceVertexCount - 2;
|
||||
for (size_t triangleIndex = 0; triangleIndex < triangleCount; ++triangleIndex)
|
||||
{
|
||||
for (size_t j = 0; j < dataIndicesCount; ++j)
|
||||
{
|
||||
UInt32List& oldData = oldDataIndices[j];
|
||||
UInt32List* newData = dataIndices[j];
|
||||
newData->push_back(oldData[oldOffset]);
|
||||
newData->push_back(oldData[oldOffset + triangleIndex + 1]);
|
||||
newData->push_back(oldData[oldOffset + triangleIndex + 2]);
|
||||
}
|
||||
faceVertexCounts.push_back(3);
|
||||
}
|
||||
}
|
||||
oldOffset += oldFaceVertexCount;
|
||||
}
|
||||
|
||||
holeFaces.clear();
|
||||
}
|
||||
|
||||
// Recalculates the face-vertex count within the polygons
|
||||
void FCDGeometryPolygons::Recalculate()
|
||||
{
|
||||
faceVertexCount = 0;
|
||||
for (UInt32List::iterator itC = faceVertexCounts.begin(); itC != faceVertexCounts.end(); ++itC) faceVertexCount += (*itC);
|
||||
}
|
||||
|
||||
FUStatus FCDGeometryPolygons::LoadFromXML(xmlNode* baseNode)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// Retrieve the expected face count from the base node's 'count' attribute
|
||||
size_t expectedFaceCount = ReadNodeCount(baseNode);
|
||||
|
||||
// Check the node's name to know whether to expect a <vcount> element
|
||||
size_t expectedVertexCount; bool isPolygons = false, isTriangles = false, isPolylist = false;
|
||||
if (IsEquivalent(baseNode->name, DAE_POLYGONS_ELEMENT)) { expectedVertexCount = 4; isPolygons = true; }
|
||||
else if (IsEquivalent(baseNode->name, DAE_TRIANGLES_ELEMENT)) { expectedVertexCount = 3 * expectedFaceCount; isTriangles = true; }
|
||||
else if (IsEquivalent(baseNode->name, DAE_POLYLIST_ELEMENT)) { expectedVertexCount = 0; isPolylist = true; }
|
||||
else
|
||||
{
|
||||
return status.Fail(FS("Unknown polygons element in geometry: ") + TO_FSTRING(parent->GetDaeId()), baseNode->line);
|
||||
}
|
||||
|
||||
// Retrieve the material symbol used by these polygons
|
||||
materialSemantic = TO_FSTRING(ReadNodeProperty(baseNode, DAE_MATERIAL_ATTRIBUTE));
|
||||
if (materialSemantic.empty())
|
||||
{
|
||||
status.Warning(FS("Unknown or missing polygonal material symbol in geometry: ") + TO_FSTRING(parent->GetDaeId()), baseNode->line);
|
||||
}
|
||||
|
||||
// Read in the per-face, per-vertex inputs
|
||||
uint32 idxCount = 1, tableIdx = 0;
|
||||
xmlNode* itNode = NULL;
|
||||
for (itNode = baseNode->children; itNode != NULL; itNode = itNode->next)
|
||||
{
|
||||
if (itNode->type != XML_ELEMENT_NODE) continue;
|
||||
if (IsEquivalent(itNode->name, DAE_INPUT_ELEMENT))
|
||||
{
|
||||
FCDGeometryPolygonsInput* input = new FCDGeometryPolygonsInput();
|
||||
string sourceId = ReadNodeSource(itNode);
|
||||
if (sourceId[0] == '#') sourceId.erase(0, 1);
|
||||
|
||||
// Parse input idx
|
||||
string idx = ReadNodeProperty(itNode, DAE_OFFSET_ATTRIBUTE);
|
||||
if (idx.empty()) idx = ReadNodeProperty(itNode, DAE_IDX_ATTRIBUTE); // COLLADA 1.3 Backward-compatibility
|
||||
input->idx = (!idx.empty()) ? FUStringConversion::ToUInt32(idx) : idxCount;
|
||||
idxCount = max(input->idx + 1, idxCount);
|
||||
|
||||
// Parse input set
|
||||
string setString = ReadNodeProperty(itNode, DAE_SET_ATTRIBUTE);
|
||||
input->set = setString.empty() ? -1 : FUStringConversion::ToInt32(setString);
|
||||
|
||||
// Parse input semantic
|
||||
string semanticString = ReadNodeSemantic(itNode);
|
||||
input->semantic = FUDaeGeometryInput::FromString(semanticString);
|
||||
if (input->semantic == FUDaeGeometryInput::UNKNOWN)
|
||||
{
|
||||
// Unknown input type
|
||||
SAFE_DELETE(input);
|
||||
continue;
|
||||
}
|
||||
else if (input->semantic == FUDaeGeometryInput::VERTEX)
|
||||
{
|
||||
tableIdx = input->idx;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Retrieve the source for this input
|
||||
input->source = parent->FindSourceById(sourceId);
|
||||
if (input->source == NULL)
|
||||
{
|
||||
status.Warning(FS("Unknown polygons set input with id: '") + TO_FSTRING(sourceId) + FS("' in geometry: ") + TO_FSTRING(parent->GetDaeId()), itNode->line);
|
||||
SAFE_DELETE(input);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Check uniqueness of idx
|
||||
input->ownsIdx = true;
|
||||
for (FCDGeometryPolygonsInputList::iterator it = inputs.begin(); it != inputs.end(); ++it)
|
||||
{
|
||||
if ((*it)->idx == input->idx)
|
||||
{
|
||||
input->ownsIdx = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add to our lists
|
||||
if (input->ownsIdx) idxOwners.push_back(input);
|
||||
inputs.push_back(input);
|
||||
}
|
||||
else if (IsEquivalent(itNode->name, DAE_POLYGON_ELEMENT)
|
||||
|| IsEquivalent(itNode->name, DAE_VERTEXCOUNT_ELEMENT)
|
||||
|| IsEquivalent(itNode->name, DAE_POLYGONHOLED_ELEMENT))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// COLLADA 1.3 backward compatibility: <param> is a valid node, but unused
|
||||
else if (IsEquivalent(itNode->name, DAE_PARAMETER_ELEMENT)) {}
|
||||
else
|
||||
{
|
||||
status.Warning(FS("Unknown polygon child element in geometry: ") + TO_FSTRING(parent->GetDaeId()), itNode->line);
|
||||
}
|
||||
}
|
||||
if (itNode == NULL)
|
||||
{
|
||||
return status.Fail(FS("No polygon <p>/<vcount> element found in geometry: ") + TO_FSTRING(parent->GetDaeId()), baseNode->line);
|
||||
}
|
||||
|
||||
// Look for the <vcount> element and parse it in
|
||||
xmlNode* vCountNode = FindChildByType(baseNode, DAE_VERTEXCOUNT_ELEMENT);
|
||||
const char* vCountDataString = ReadNodeContentDirect(vCountNode);
|
||||
if (vCountDataString != NULL) FUStringConversion::ToUInt32List(vCountDataString, faceVertexCounts);
|
||||
bool hasVertexCounts = !faceVertexCounts.empty();
|
||||
if (isPolylist && !hasVertexCounts)
|
||||
{
|
||||
return status.Fail(FS("No or empty <vcount> element found in geometry: ") + TO_FSTRING(parent->GetDaeId()), baseNode->line);
|
||||
}
|
||||
else if (!isPolylist && hasVertexCounts)
|
||||
{
|
||||
return status.Fail(FS("<vcount> is only expected with the <polylist> element in geometry: ") + TO_FSTRING(parent->GetDaeId()), baseNode->line);
|
||||
}
|
||||
else if (isPolylist)
|
||||
{
|
||||
// Count the total number of face-vertices expected, to pre-buffer the index lists
|
||||
expectedVertexCount = 0;
|
||||
for (UInt32List::iterator itC = faceVertexCounts.begin(); itC != faceVertexCounts.end(); ++itC)
|
||||
{
|
||||
expectedVertexCount += *itC;
|
||||
}
|
||||
}
|
||||
|
||||
string holeBuffer;
|
||||
UInt32List allIndices;
|
||||
// First pass, allocation for tessellation
|
||||
xmlNode* savedNode = itNode; // two pass process for performance
|
||||
uint32 indicesSize = 0;
|
||||
faceVertexCount = 0;
|
||||
allIndices.clear();
|
||||
allIndices.reserve(expectedVertexCount * idxCount);
|
||||
for (; itNode != NULL; itNode = itNode->next)
|
||||
{
|
||||
uint32 localFaceVertexCount;
|
||||
const char* content = NULL;
|
||||
xmlNode* holeNode = NULL;
|
||||
bool failed = false;
|
||||
if (!InitTessellation(itNode, &localFaceVertexCount, allIndices, content, holeNode, idxCount, &failed)) continue;
|
||||
|
||||
if (failed)
|
||||
{
|
||||
return status.Fail(FS("Unknown element found in <ph> element for geometry: ") + TO_FSTRING(parent->GetDaeId()), itNode->line);
|
||||
}
|
||||
|
||||
indicesSize += localFaceVertexCount;
|
||||
}
|
||||
for (FCDGeometryPolygonsInputList::iterator it = idxOwners.begin(); it != idxOwners.end(); ++it)
|
||||
{
|
||||
size_t currentIndexCount = (*it)->indices.size();
|
||||
(*it)->indices.reserve(currentIndexCount + indicesSize);
|
||||
}
|
||||
|
||||
// Second pass, saving the tessellation
|
||||
faceVertexCount = 0;
|
||||
allIndices.clear();
|
||||
allIndices.reserve(expectedVertexCount * idxCount);
|
||||
itNode = savedNode;
|
||||
for (; itNode != NULL; itNode = itNode->next)
|
||||
{
|
||||
uint32 localFaceVertexCount;
|
||||
const char* content = NULL;
|
||||
xmlNode* holeNode = NULL;
|
||||
bool failed = false;
|
||||
if (!InitTessellation(itNode, &localFaceVertexCount, allIndices, content, holeNode, idxCount, &failed)) continue;
|
||||
|
||||
if (failed)
|
||||
{
|
||||
return status.Fail(FS("Unknown element found in <ph> element for geometry: ") + TO_FSTRING(parent->GetDaeId()), itNode->line);
|
||||
}
|
||||
|
||||
if (isTriangles) for (uint32 i = 0; i < localFaceVertexCount / 3; ++i) faceVertexCounts.push_back(3);
|
||||
else if (isPolygons) faceVertexCounts.push_back(localFaceVertexCount);
|
||||
faceVertexCount += localFaceVertexCount;
|
||||
|
||||
// Append any hole indices found
|
||||
for (; holeNode != NULL; holeNode = holeNode->next)
|
||||
{
|
||||
if (holeNode->type != XML_ELEMENT_NODE) continue;
|
||||
|
||||
// Read in the hole indices and push them on top of the other indices
|
||||
UInt32List holeIndices; holeIndices.reserve(expectedVertexCount * idxCount);
|
||||
content = ReadNodeContentDirect(holeNode);
|
||||
FUStringConversion::ToUInt32List(content, holeIndices);
|
||||
allIndices.insert(allIndices.end(), holeIndices.begin(), holeIndices.end());
|
||||
|
||||
// Create the hole face and record its index
|
||||
size_t holeVertexCount = holeIndices.size() / idxCount;
|
||||
holeFaces.push_back((uint32) faceVertexCounts.size());
|
||||
faceVertexCounts.push_back((uint32) holeVertexCount);
|
||||
faceVertexCount += holeVertexCount;
|
||||
}
|
||||
|
||||
// Create a new entry for the vertex buffer
|
||||
for (size_t offset = 0; offset < allIndices.size(); offset += idxCount)
|
||||
{
|
||||
for (FCDGeometryPolygonsInputList::iterator it = idxOwners.begin(); it != idxOwners.end(); ++it)
|
||||
{
|
||||
(*it)->indices.push_back(allIndices[offset + (*it)->idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check the actual face count
|
||||
if (expectedFaceCount != faceVertexCounts.size() - holeFaces.size())
|
||||
{
|
||||
return status.Fail(FS("Face count for polygons node doesn't match actual number of faces found in <p> element(s) in geometry: ") + TO_FSTRING(parent->GetDaeId()), baseNode->line);
|
||||
}
|
||||
|
||||
// Merge the vertex input with the vertices node information
|
||||
FCDGeometryPolygonsInputList::iterator itVertex;
|
||||
for (itVertex = inputs.begin(); itVertex != inputs.end(); ++itVertex)
|
||||
{
|
||||
if ((*itVertex)->semantic == FUDaeGeometryInput::VERTEX) break;
|
||||
}
|
||||
if (itVertex == inputs.end())
|
||||
{
|
||||
return status.Fail(FS("Cannot find VERTEX polygons' input within geometry: ") + TO_FSTRING(parent->GetDaeId()), baseNode->line);
|
||||
}
|
||||
|
||||
FCDGeometrySourceList& vertexSources = parent->GetVertexSources();
|
||||
size_t vertexMergeCount = vertexSources.size();
|
||||
if (vertexMergeCount == 0)
|
||||
{
|
||||
return status.Fail(FS("Empty <vertices> element in geometry: ") + TO_FSTRING(parent->GetDaeId()), baseNode->line);
|
||||
}
|
||||
(*itVertex)->semantic = vertexSources.front()->GetSourceType();
|
||||
(*itVertex)->source = vertexSources.front();
|
||||
uint32 vertexIdx = (*itVertex)->idx;
|
||||
uint32 vertexPosition = (uint32) (itVertex - inputs.begin());
|
||||
for (uint32 i = 1; i < vertexMergeCount; ++i)
|
||||
{
|
||||
FCDGeometryPolygonsInput* perVertexInput = new FCDGeometryPolygonsInput();
|
||||
perVertexInput->source = vertexSources[i];
|
||||
perVertexInput->semantic = vertexSources[i]->GetSourceType();
|
||||
perVertexInput->ownsIdx = false;
|
||||
perVertexInput->idx = vertexIdx;
|
||||
perVertexInput->set = 0;
|
||||
inputs.insert(inputs.begin() + vertexPosition, perVertexInput);
|
||||
}
|
||||
|
||||
// Read in the polygons source animations
|
||||
for (FCDGeometryPolygonsInputList::iterator it = inputs.begin(); it != inputs.end(); ++it)
|
||||
{
|
||||
(*it)->source->SetSourceType((*it)->semantic);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool FCDGeometryPolygons::InitTessellation(xmlNode* itNode,
|
||||
uint32* localFaceVertexCount, UInt32List& allIndices,
|
||||
const char* content, xmlNode*& holeNode, uint32 idxCount,
|
||||
bool* failed)
|
||||
{
|
||||
if (itNode->type != XML_ELEMENT_NODE) return false;
|
||||
if (!IsEquivalent(itNode->name, DAE_POLYGON_ELEMENT)
|
||||
&& !IsEquivalent(itNode->name, DAE_POLYGONHOLED_ELEMENT)) return false;
|
||||
|
||||
// Retrieve the indices
|
||||
content = NULL;
|
||||
holeNode = NULL;
|
||||
if (!IsEquivalent(itNode->name, DAE_POLYGONHOLED_ELEMENT))
|
||||
{
|
||||
content = ReadNodeContentDirect(itNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Holed face found
|
||||
for (xmlNode* child = itNode->children; child != NULL; child = child->next)
|
||||
{
|
||||
if (child->type != XML_ELEMENT_NODE) continue;
|
||||
if (IsEquivalent(child->name, DAE_POLYGON_ELEMENT))
|
||||
{
|
||||
content = ReadNodeContentDirect(child);
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_HOLE_ELEMENT))
|
||||
{
|
||||
holeNode = child; break;
|
||||
}
|
||||
else
|
||||
{
|
||||
*failed = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the indices
|
||||
allIndices.clear();
|
||||
FUStringConversion::ToUInt32List(content, allIndices);
|
||||
*localFaceVertexCount = (uint32) allIndices.size() / idxCount;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Write out the polygons structure to the COLLADA xml tree
|
||||
xmlNode* FCDGeometryPolygons::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
// Are there holes? Then, export a <polygons> element.
|
||||
// Are there only non-triangles within the list? Then, export a <polylist> element.
|
||||
// Otherwise, you only have triangles: export a <triangles> element.
|
||||
bool hasHoles = !holeFaces.empty(), hasNPolys = true;
|
||||
if (!hasHoles)
|
||||
{
|
||||
UInt32List::const_iterator itC;
|
||||
for (itC = faceVertexCounts.begin(); itC != faceVertexCounts.end() && (*itC) == 3; ++itC) {}
|
||||
hasNPolys = (itC != faceVertexCounts.end());
|
||||
}
|
||||
|
||||
// Create the base node for these polygons
|
||||
const char* polygonNodeType;
|
||||
if (hasHoles) polygonNodeType = DAE_POLYGONS_ELEMENT;
|
||||
else if (hasNPolys) polygonNodeType = DAE_POLYLIST_ELEMENT;
|
||||
else polygonNodeType = DAE_TRIANGLES_ELEMENT;
|
||||
xmlNode* polygonsNode = AddChild(parentNode, polygonNodeType);
|
||||
|
||||
// Add the inputs
|
||||
// Find which input owner belongs to the <vertices> element. Replace the semantic and the source id accordingly.
|
||||
// Make sure to add that 'vertex' input only once.
|
||||
FUSStringBuilder verticesNodeId(parent->GetDaeId()); verticesNodeId.append("-vertices");
|
||||
const FCDGeometrySourceList& vertexSources = parent->GetVertexSources();
|
||||
bool isVertexInputFound = false;
|
||||
for (FCDGeometryPolygonsInputList::const_iterator itI = inputs.begin(); itI != inputs.end(); ++itI)
|
||||
{
|
||||
FCDGeometryPolygonsInput* input = *itI;
|
||||
if (std::find(vertexSources.begin(), vertexSources.end(), input->source) == vertexSources.end())
|
||||
{
|
||||
const char* semantic = FUDaeGeometryInput::ToString(input->semantic);
|
||||
FUDaeWriter::AddInput(polygonsNode, input->source->GetDaeId(), semantic, input->idx, input->set);
|
||||
}
|
||||
else if (!isVertexInputFound)
|
||||
{
|
||||
FUDaeWriter::AddInput(polygonsNode, verticesNodeId.ToCharPtr(), DAE_VERTEX_INPUT, input->idx);
|
||||
isVertexInputFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
FUSStringBuilder builder;
|
||||
builder.reserve(1024);
|
||||
|
||||
// For the poly-list case, export the list of vertex counts
|
||||
if (!hasHoles && hasNPolys)
|
||||
{
|
||||
FUStringConversion::ToString(builder, faceVertexCounts);
|
||||
AddChild(polygonsNode, DAE_VERTEXCOUNT_ELEMENT, builder.ToCharPtr());
|
||||
builder.clear();
|
||||
}
|
||||
|
||||
// For the non-holes cases, open only one <p> element for all the data indices
|
||||
xmlNode* pNode = NULL,* phNode = NULL;
|
||||
if (!hasHoles) pNode = AddChild(polygonsNode, DAE_POLYGON_ELEMENT);
|
||||
|
||||
// Export the data indices (tessellation information)
|
||||
size_t faceCount = faceVertexCounts.size();
|
||||
uint32 faceVertexOffset = 0;
|
||||
for (size_t faceIndex = 0; faceIndex < faceCount; ++faceIndex)
|
||||
{
|
||||
// For the holes cases, verify whether this face or the next one(s) are holes. We may need to open a new <ph>/<p> element
|
||||
bool isHole = false, isHoleNext = false;
|
||||
if (hasHoles)
|
||||
{
|
||||
for (UInt32List::const_iterator itH = holeFaces.begin(); itH != holeFaces.end(); ++itH)
|
||||
{
|
||||
isHole |= (*itH) == (uint32) faceIndex;
|
||||
isHoleNext |= (*itH) + 1 == (uint32) faceIndex;
|
||||
}
|
||||
|
||||
if (!isHole)
|
||||
{
|
||||
// Just open a <p> element: this is the most common case
|
||||
if (!isHoleNext) pNode = AddChild(polygonsNode, DAE_POLYGONHOLED_ELEMENT);
|
||||
else
|
||||
{
|
||||
// Open up a new <ph> element and its <p> element
|
||||
phNode = AddChild(polygonsNode, DAE_POLYGONHOLED_ELEMENT);
|
||||
pNode = AddChild(phNode, DAE_POLYGON_ELEMENT);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Open up a <h> element
|
||||
pNode = AddChild(phNode, DAE_HOLE_ELEMENT);
|
||||
}
|
||||
}
|
||||
|
||||
// Write out the tessellation information for all the vertices of this face
|
||||
uint32 faceVertexCount = faceVertexCounts[faceIndex];
|
||||
for (uint32 faceVertexIndex = faceVertexOffset; faceVertexIndex < faceVertexOffset + faceVertexCount; ++faceVertexIndex)
|
||||
{
|
||||
for (FCDGeometryPolygonsInputList::const_iterator itI = idxOwners.begin(); itI != idxOwners.end(); ++itI)
|
||||
{
|
||||
UInt32List& indices = (*itI)->indices;
|
||||
builder.append(indices[faceVertexIndex]);
|
||||
builder.append(' ');
|
||||
}
|
||||
}
|
||||
|
||||
// For the holes cases: write out the indices for every polygon element
|
||||
if (hasHoles)
|
||||
{
|
||||
if (!builder.empty()) builder.pop_back(); // take out the last space
|
||||
AddContent(pNode, builder);
|
||||
}
|
||||
faceVertexOffset += faceVertexCount;
|
||||
}
|
||||
|
||||
// For the non-holes cases: write out the indices at the very end, for the single <p> element
|
||||
if (!hasHoles)
|
||||
{
|
||||
if (!builder.empty()) builder.pop_back(); // take out the last space
|
||||
AddContent(pNode, builder);
|
||||
}
|
||||
|
||||
// Write out the material semantic and the number of polygons
|
||||
if (!materialSemantic.empty())
|
||||
{
|
||||
AddAttribute(polygonsNode, DAE_MATERIAL_ATTRIBUTE, materialSemantic);
|
||||
}
|
||||
AddAttribute(polygonsNode, DAE_COUNT_ATTRIBUTE, GetFaceCount() - GetHoleCount());
|
||||
|
||||
return polygonsNode;
|
||||
}
|
||||
|
||||
// Clone this list of polygons
|
||||
FCDGeometryPolygons* FCDGeometryPolygons::Clone(FCDGeometryMesh* cloneParent)
|
||||
{
|
||||
FCDGeometryPolygons* clone = new FCDGeometryPolygons(GetDocument(), cloneParent);
|
||||
clone->materialSemantic = materialSemantic;
|
||||
clone->faceVertexCounts = faceVertexCounts;
|
||||
clone->faceOffset = faceOffset;
|
||||
clone->faceVertexCount = faceVertexCount;
|
||||
clone->faceVertexOffset = faceVertexOffset;
|
||||
|
||||
// Clone the geometry inputs
|
||||
uint32 inputCount = (uint32) inputs.size();
|
||||
clone->inputs.resize(inputCount);
|
||||
for (uint32 i = 0; i < inputCount; ++i)
|
||||
{
|
||||
clone->inputs[i] = new FCDGeometryPolygonsInput();
|
||||
clone->inputs[i]->source = cloneParent->FindSourceById(inputs[i]->source->GetDaeId());
|
||||
clone->inputs[i]->idx = inputs[i]->idx;
|
||||
clone->inputs[i]->indices = inputs[i]->indices;
|
||||
clone->inputs[i]->ownsIdx = inputs[i]->ownsIdx;
|
||||
clone->inputs[i]->semantic = inputs[i]->semantic;
|
||||
clone->inputs[i]->set = inputs[i]->set;
|
||||
|
||||
// Regenerate the idxOwners list with the new inputs
|
||||
if (clone->inputs[i]->ownsIdx) clone->idxOwners.push_back(clone->inputs[i]);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
FCDGeometryPolygonsInput::FCDGeometryPolygonsInput()
|
||||
{
|
||||
idx = 0;
|
||||
ownsIdx = false;
|
||||
semantic = FUDaeGeometryInput::UNKNOWN;
|
||||
set = -1;
|
||||
source = NULL;
|
||||
}
|
||||
@@ -1,340 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDGeometryPolygons.h
|
||||
This file defines the FCDGeometryPolygons and the FCDGeometryPolygonsInput classes.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_GEOMETRY_POLYGONS_H_
|
||||
#define _FCD_GEOMETRY_POLYGONS_H_
|
||||
|
||||
#include "FCDocument/FCDObject.h"
|
||||
#include "FUtils/FUDaeEnum.h"
|
||||
|
||||
class FCDocument;
|
||||
class FRMeshPolygons;
|
||||
class FCDMaterial;
|
||||
class FCDGeometryMesh;
|
||||
class FCDGeometrySource;
|
||||
|
||||
/**
|
||||
An input data source for one mesh polygons set.
|
||||
This structure knows the type of input data in the data source
|
||||
as well as the set and offset for the data. It also contains a
|
||||
pointer to the mesh data source.
|
||||
|
||||
Many polygon set inputs may have the same offset (or 'idx') when multiple
|
||||
data sources are compressed together within the COLLADA document.
|
||||
In this case, one and only one of the polygon set input will have
|
||||
the 'ownsIdx' flag set. A polygon set input with this flag set will
|
||||
contain valid indices. To find the indices of any polygon set input,
|
||||
it is recommended that you use the FCDGeometryPolygons::FindIndicesForIdx function.
|
||||
|
||||
@ingroup FCDGeometry
|
||||
*/
|
||||
class FCDGeometryPolygonsInput
|
||||
{
|
||||
public:
|
||||
/** Constructor. */
|
||||
FCDGeometryPolygonsInput();
|
||||
|
||||
/** Determines the type of data to input. */
|
||||
FUDaeGeometryInput::Semantic semantic;
|
||||
|
||||
/** Offset within the COLLADA document for this input.
|
||||
All the inputs with the same offset value use the same indices within the COLLADA document. */
|
||||
uint32 idx;
|
||||
|
||||
/** [INTERNAL] Offset owner flags. One and only one polygon set input will have this flag set for each offset value.
|
||||
A polygon set input with this flag set will contain valid indices within the 'indices' member variable.
|
||||
You should not set or access this flag directly. Instead, use the FCDGeometryPolygons::FindIndicesForIdx function. */
|
||||
bool ownsIdx;
|
||||
|
||||
/** [INTERNAL] Tessellation indices. Use these indices to generate a list of unique vertices and generate your vertex buffers.
|
||||
You should not set or access the indices directly. Instead, use the FCDGeometryPolygons::FindIndicesForIdx function. */
|
||||
UInt32List indices;
|
||||
|
||||
/** Data source. This is the data source into which the indices are indexing. You need to take the data source
|
||||
stride into consideration when unindexing the data. */
|
||||
FCDGeometrySource* source;
|
||||
|
||||
/** Input set. Used to group together the texture coordinates with the texture tangents and binormals.
|
||||
ColladaMax: this value should also represent the map channel index or texture coordinates
|
||||
and vertex color channels. */
|
||||
int32 set;
|
||||
};
|
||||
|
||||
/** A dynamically-sized array of FCDGeometryPolygonsInput objects. */
|
||||
typedef vector<FCDGeometryPolygonsInput*> FCDGeometryPolygonsInputList;
|
||||
|
||||
/**
|
||||
A mesh polygon set.
|
||||
Each polygon set contains a list of inputs and the tessellation information
|
||||
to make polygons out of the data and indices of the input. FCollada
|
||||
supports triangle lists as well as polygon lists and lists of polygons with holes.
|
||||
This implies that each face has an undeterminate number of vertices.
|
||||
The tessellation information creates polygons, but may also creates holes within the polygons.
|
||||
|
||||
@ingroup FCDGeometry
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDGeometryPolygons : public FCDObject
|
||||
{
|
||||
private:
|
||||
FCDGeometryPolygonsInputList inputs;
|
||||
FCDGeometryPolygonsInputList idxOwners;
|
||||
UInt32List faceVertexCounts;
|
||||
FCDGeometryMesh* parent;
|
||||
size_t faceVertexCount;
|
||||
UInt32List holeFaces;
|
||||
|
||||
// Buffered statistics
|
||||
size_t faceOffset;
|
||||
size_t faceVertexOffset;
|
||||
size_t holeOffset;
|
||||
|
||||
// Material for this set of polygons
|
||||
fstring materialSemantic;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly. Instead, use the FCDGeometryMesh::AddPolygons function
|
||||
to create new polygon sets.
|
||||
@param document The COLLADA document which owns this polygon set.
|
||||
@param parent The geometric mesh which contains this polygon set.*/
|
||||
FCDGeometryPolygons(FCDocument* document, FCDGeometryMesh* parent);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
The mesh which contains this polygon set will handle its release. */
|
||||
virtual ~FCDGeometryPolygons();
|
||||
|
||||
/** Retrieves the list of face-vertex counts. Each face within the polygon set
|
||||
has one or more entry within this list, depending on the number of holes within that face.
|
||||
Each face-vertex count indicates the number of ordered indices
|
||||
within the polygon set inputs that are used to generate a face or its holes.
|
||||
To find out if a face-vertex count represents a face or its holes, check
|
||||
the hole-faces list retrieved using the GetHoleFaces function.
|
||||
Indirectly, the face-vertex count indicates the degree of the polygon.
|
||||
@see GetHoleFaces @see GetHoleCount
|
||||
@return The list of face-vertex counts.*/
|
||||
inline const UInt32List& GetFaceVertexCounts() const { return faceVertexCounts; }
|
||||
|
||||
/** Retrieves the number of holes within the faces of the polygon set.
|
||||
@return The number of holes within the faces of the polygon set. */
|
||||
inline size_t GetHoleCount() const { return holeFaces.size(); }
|
||||
|
||||
/** Retrieves the number of faces within the polygon set.
|
||||
@return The number of faces within the polygon set. */
|
||||
inline size_t GetFaceCount() const { return faceVertexCounts.size() - GetHoleCount(); }
|
||||
|
||||
/** Retrieves the number of faces which appear before this polygon set within the geometric mesh.
|
||||
This value is useful when traversing all the faces of a geometric mesh.
|
||||
@return The number of faces in previous polygon sets. */
|
||||
inline size_t GetFaceOffset() const { return faceOffset; }
|
||||
|
||||
/** Retrieves the total number of face-vertex pairs within the polygon set.
|
||||
This value is the total of all the values within the face-vertex count list.
|
||||
Do remember that the list of face-vertex pairs includes holes.
|
||||
@return The total number of face-vertex pairs within the polygon set. */
|
||||
inline size_t GetFaceVertexCount() const { return faceVertexCount; }
|
||||
|
||||
/** Retrieves the number of face-vertex pairs for a given face.
|
||||
This value includes face-vertex pairs that create the polygon and its holes.
|
||||
@param index A face index.
|
||||
@return The number of face-vertex pairs for a given face. */
|
||||
size_t GetFaceVertexCount(size_t index) const;
|
||||
|
||||
/** Retrieves the total number of face-vertex pairs which appear
|
||||
before this polygon set within the geometric mesh.
|
||||
This value is useful when traversing all the face-vertex pairs of a geometric mesh.
|
||||
@return The number of face-vertex pairs in previous polygon sets. */
|
||||
inline size_t GetFaceVertexOffset() const { return faceVertexOffset; }
|
||||
|
||||
/** Retrieves the number of holes which appear before this polygon set.
|
||||
This value is useful when traversing all the face-vertex pairs of a geometric mesh. */
|
||||
inline size_t GetHoleOffset() const { return holeOffset; }
|
||||
|
||||
/** Retrieves the number of face-vertex pairs which appear
|
||||
before a given face within the polygon set.
|
||||
This value is useful when doing per-vertex mesh operations within the polygon set.
|
||||
@param index The index of the face.
|
||||
@return The number of face-vertex pairs before the given face, within the polygon set. */
|
||||
size_t GetFaceVertexOffset(size_t index) const;
|
||||
|
||||
/** [INTERNAL] Sets the number of faces in previous polygon sets.
|
||||
Used by the FCDGeometryMesh::Recalculate function.
|
||||
@param offset The number of faces in previous polygon sets. */
|
||||
inline void SetFaceOffset(size_t offset) { faceOffset = offset; }
|
||||
|
||||
/** [INTERNAL] Sets the number of face-vertex pairs in previous polygon sets.
|
||||
Used by the FCDGeometryMesh::Recalculate function.
|
||||
@param offset The number of face-vertex pairs in previous polygon sets. */
|
||||
inline void SetFaceVertexOffset(size_t offset) { faceVertexOffset = offset; }
|
||||
|
||||
/** [INTERNAL] Sets the number of holes in previous polygon sets.
|
||||
Used by the FCDGeometryMesh::Recalculate function.
|
||||
@param offset The number of holes in previous polygon sets. */
|
||||
inline void SetHoleOffset(size_t offset) { holeOffset = offset; }
|
||||
|
||||
/** Creates a new face.
|
||||
Enough indices to fill the face will be added to the polygon set inputs: you will
|
||||
want to overwrite those, as they will all be set to zero.
|
||||
@param degree The degree of the polygon. This number implies the number of indices
|
||||
that will be expected, in order, within each of the input index lists. */
|
||||
void AddFace(uint32 degree);
|
||||
|
||||
/** Removes a face
|
||||
@param index The index of the face to remove. All the indices associated
|
||||
with this face will also be removed. */
|
||||
void RemoveFace(size_t index);
|
||||
|
||||
/** Retrieves the list of polygon set inputs.
|
||||
@see FCDGeometryPolygonsInput
|
||||
@return The list of polygon set inputs. */
|
||||
inline FCDGeometryPolygonsInputList& GetInputs() { return inputs; }
|
||||
inline const FCDGeometryPolygonsInputList& GetInputs() const { return inputs; } /**< See above. */
|
||||
|
||||
/** Retrieves the number of polygon set inputs.
|
||||
@return The number of polygon set inputs. */
|
||||
inline size_t GetInputCount() const { return inputs.size(); }
|
||||
|
||||
/** Retrieves a specific polygon set input.
|
||||
@param index The index of the polygon set input. This index should
|
||||
not be greater than or equal to the number of polygon set inputs.
|
||||
@return The specific polygon set input. This pointer will be NULL if the index is out-of-bounds. */
|
||||
inline FCDGeometryPolygonsInput* GetInput(size_t index) { FUAssert(index < GetInputCount(), return NULL); return inputs.at(index); }
|
||||
inline const FCDGeometryPolygonsInput* GetInput(size_t index) const { FUAssert(index < GetInputCount(), return NULL); return inputs.at(index); } /**< See above. */
|
||||
|
||||
/** Creates a new polygon set input.
|
||||
@param source The data source for the polygon set input.
|
||||
@param offset The tessellation indices offset for the polygon set input.
|
||||
If this value is new to the list of polygon inputs, you will need to fill in the indices.
|
||||
Please use the FindIndices function to verify that the offset is new and that indices need
|
||||
to be provided. The offset of zero is reserved for per-vertex data sources.
|
||||
@return The new polygon set input. */
|
||||
FCDGeometryPolygonsInput* AddInput(FCDGeometrySource* source, uint32 offset);
|
||||
|
||||
/** Deletes a polygon set input.
|
||||
This function releases the memory held by the polygon set input as well as moves
|
||||
the indices to another polygon set input with the same offset, if the offset is re-used.
|
||||
@param input The polygon set input to delete. */
|
||||
void ReleaseInput(FCDGeometryPolygonsInput* input);
|
||||
|
||||
/** Retrieves the list of entries within the face-vertex count list
|
||||
that are considered holes. COLLADA does not support holes within holes,
|
||||
so each entry within this list implies a hole within the previous face.
|
||||
@see GetFaceVertexCounts
|
||||
@return The list of hole entries within the face-vertex counts. */
|
||||
inline const UInt32List& GetHoleFaces() const { return holeFaces; }
|
||||
|
||||
/** Retrieves the number of holes within faces of the polygon set that appear
|
||||
before the given face index. This value is useful when trying to access
|
||||
a specific face of a mesh, as holes and faces appear together within the
|
||||
face-vertex degree list.
|
||||
@param index A face index.
|
||||
@return The number of holes within the polygon set that appear
|
||||
before the given face index. */
|
||||
size_t GetHoleCountBefore(size_t index) const;
|
||||
|
||||
/** Retrieves the number of holes within a given face.
|
||||
@param index A face index.
|
||||
@return The number of holes within the given face. */
|
||||
size_t GetHoleCount(size_t index) const;
|
||||
|
||||
/** Retrieves the first polygon set input found that has the given data type.
|
||||
@param semantic A type of geometry data.
|
||||
@return The polygon set input. This pointer will be NULL if
|
||||
no polygon set input matches the data type. */
|
||||
FCDGeometryPolygonsInput* FindInput(FUDaeGeometryInput::Semantic semantic);
|
||||
const FCDGeometryPolygonsInput* FindInput(FUDaeGeometryInput::Semantic semantic) const; /**< See above. */
|
||||
|
||||
/** Retrieves the polygon set input that points towards a given data source.
|
||||
@param source A geometry data source.
|
||||
@return The polygon set input. This pointer will be NULL if
|
||||
no polygon set input matches the data source. */
|
||||
FCDGeometryPolygonsInput* FindInput(FCDGeometrySource* source);
|
||||
const FCDGeometryPolygonsInput* FindInput(const FCDGeometrySource* source) const; /**< See above. */
|
||||
|
||||
/** [INTERNAL] Retrieves the polygon set input that points towards a given data source.
|
||||
@param sourceId The COLLADA id of a geometry data source.
|
||||
@return The polygon set input. This pointer will be NULL if
|
||||
no polygon set input matches the COLLADA id. */
|
||||
FCDGeometryPolygonsInput* FindInput(const string& sourceId);
|
||||
|
||||
/** Retrieves all the polygon set inputs that have the given data type.
|
||||
@param semantic A type of geometry data.
|
||||
@param inputs A list of polygon set inputs to fill in. This list is not emptied by the function
|
||||
and may remain untouched, if no polygon set input matches the given data type. */
|
||||
void FindInputs(FUDaeGeometryInput::Semantic semantic, FCDGeometryPolygonsInputList& inputs);
|
||||
|
||||
/** Retrieves the tessellation indices for a given polygon set input offset.
|
||||
@deprecated Instead, use the FindIndices function.
|
||||
@param idx A polygon set input offset.
|
||||
@return The tessellation indices corresponding to the offset. This pointer
|
||||
will be NULL if there are no polygon set input which uses the given offset. */
|
||||
UInt32List* FindIndicesForIdx(uint32 idx);
|
||||
const UInt32List* FindIndicesForIdx(uint32 idx) const; /**< See above. */
|
||||
|
||||
/** Retrieves the first tessellation index list for a given data source.
|
||||
@param source A data source.
|
||||
@return The first tessellation index list corresponding to the data source. This pointer
|
||||
will be NULL if the data source is not used within this polygon set. */
|
||||
UInt32List* FindIndices(FCDGeometrySource* source);
|
||||
const UInt32List* FindIndices(const FCDGeometrySource* source) const; /**< See above. */
|
||||
|
||||
/** Retrieves the tessellation indices for a given polygon set input.
|
||||
@param input A given polygon set input.
|
||||
@return The tessellation indices corresponding to the polygon set input. This pointer
|
||||
will be NULL if the polygon set input is not used within this polygon set. */
|
||||
UInt32List* FindIndices(FCDGeometryPolygonsInput* input);
|
||||
const UInt32List* FindIndices(const FCDGeometryPolygonsInput* input) const; /**< See above. */
|
||||
|
||||
/** Retrieves the symbolic name for the material used on this polygon set.
|
||||
Match this symbolic name within a FCDGeometryInstance to get the
|
||||
correct material instance.
|
||||
@return A symbolic material name. */
|
||||
inline const fstring& GetMaterialSemantic() const { return materialSemantic; }
|
||||
|
||||
/** Triangulates the polygon set.
|
||||
A simple fanning techique is currently used: holes will not be triangulated correctly. */
|
||||
void Triangulate();
|
||||
|
||||
/** [INTERNAL] Recalculates the buffered offset and count values for this polygon set. */
|
||||
void Recalculate();
|
||||
|
||||
/** [INTERNAL] Reads in the polygon set element from a given COLLADA XML tree node.
|
||||
COLLADA has multiple polygon set elements. The most common ones are \<triangles\> and \<polylist\>.
|
||||
@param polygonNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the polygon set.*/
|
||||
FUStatus LoadFromXML(xmlNode* polygonNode);
|
||||
|
||||
/** [INTERNAL] Writes out the correct polygon set element to the given COLLADA XML tree node.
|
||||
COLLADA has multiple polygon set elements. The most common ones are \<triangles\> and \<polylist\>.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the geometric mesh.
|
||||
@return The created XML tree node. */
|
||||
xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
|
||||
/** [INTERNAL] Creates a copy of this mesh.
|
||||
You should use the FCDGeometry::Clone function instead of this function.
|
||||
You will need to release the cloned entity.
|
||||
@param cloneParent The geometric mesh which will contain the cloned polygon set.
|
||||
@return An identical copy of the polygon set. */
|
||||
FCDGeometryPolygons* Clone(FCDGeometryMesh* cloneParent);
|
||||
|
||||
private:
|
||||
// Performs operations needed before tessellation
|
||||
bool InitTessellation(xmlNode* itNode,
|
||||
uint32* localFaceVertexCount, UInt32List& allIndices,
|
||||
const char* content, xmlNode*& holeNode, uint32 idxCount,
|
||||
bool* failed);
|
||||
};
|
||||
|
||||
#endif // _FCD_GEOMETRY_POLYGONS_H_
|
||||
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
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;
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDGeometrySource.h
|
||||
This file contains the FCDGeometrySource class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_GEOMETRY_SOURCE_H_
|
||||
#define _FCD_GEOMETRY_SOURCE_H_
|
||||
|
||||
|
||||
#include "FCDocument/FCDObject.h"
|
||||
#include "FUtils/FUDaeEnum.h"
|
||||
|
||||
class FCDAnimated;
|
||||
|
||||
/** A dynamically-sized array of FCDAnimated objects. */
|
||||
typedef vector<FCDAnimated*> FCDAnimatedList;
|
||||
|
||||
/**
|
||||
A COLLADA data source for geometric meshes.
|
||||
|
||||
A COLLADA data source for geometric meshes contains a list of floating-point values and the information
|
||||
to parse these floating-point values into meaningful content: the stride of the list and the type of data
|
||||
that the floating-point values represent. When the floating-point values are split according to the stride,
|
||||
you get multiple elemental values of the given type. A data source may also have a user-generated name to
|
||||
identify the data within. The name is optional and is used to keep around the user-friendly name for texture coordinate
|
||||
sets or color sets.
|
||||
|
||||
The values of the COLLADA data source may be animated individually, or together: as an element.
|
||||
|
||||
@ingroup FCDGeometry
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDGeometrySource : public FCDObjectWithId
|
||||
{
|
||||
private:
|
||||
fstring name;
|
||||
FloatList sourceData;
|
||||
uint32 sourceStride;
|
||||
xmlNode* sourceNode;
|
||||
FUDaeGeometryInput::Semantic sourceType;
|
||||
|
||||
// The animated values held here are contained within the document.
|
||||
FCDAnimatedList animatedValues;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Use FCDGeometryMesh::AddSource or FCDGeometryMesh::AddValueSource instead.
|
||||
@param document The COLLADA document which owns the data source. */
|
||||
FCDGeometrySource(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
The geometric mesh which contains the data source will release it. */
|
||||
virtual ~FCDGeometrySource();
|
||||
|
||||
/** Retrieves the name of the data source. The name is optional and is used to
|
||||
keep around a user-friendly name for texture coordinate sets or color sets.
|
||||
@return The name of the data source. */
|
||||
const fstring& GetName() const { return name; }
|
||||
|
||||
/** Retrieves the pure data of the data source. This is a dynamically-sized array of
|
||||
floating-point values that contains all the data of the source.
|
||||
@return The pure data of the data source. */
|
||||
FloatList& GetSourceData() { return sourceData; }
|
||||
const FloatList& GetSourceData() const { return sourceData; } /**< See above. */
|
||||
|
||||
/** Retrieves the stride of the data within the source.
|
||||
There is no guarantee that the number of data values within the source is a multiple of the stride,
|
||||
yet you should always verify that the stride is at least the wanted dimension. For example, there is
|
||||
no guarantee that your vertex position data source has a stride of 3. 3dsMax is known to always
|
||||
export 3D texture coordinate positions.
|
||||
@return The stride of the data. */
|
||||
uint32 GetSourceStride() const { return sourceStride; }
|
||||
|
||||
/** @deprecated Retrieves the COLLADA id for the source.
|
||||
Use the class parent's GetDaeId function instead.
|
||||
@return The COLLADA id. */
|
||||
const string& GetSourceId() const { return GetDaeId(); }
|
||||
|
||||
/** Retrieves the list of animated values for the data of the source.
|
||||
@return The list of animated values. */
|
||||
FCDAnimatedList& GetAnimatedValues() { return animatedValues; }
|
||||
const FCDAnimatedList& GetAnimatedValues() const { return animatedValues; } /**< See above. */
|
||||
|
||||
/** @deprecated [INTERNAL] Retrieves the XML tree node that represent this source.
|
||||
This is used when computing the list of animated values.
|
||||
@todo Take the XML tree node out of this class.
|
||||
@return The XML tree node. This pointer is invalid if accessed after the document is
|
||||
fully parsed. */
|
||||
xmlNode* GetSourceNode() { return sourceNode; } // Should be taken out of this class
|
||||
|
||||
/** Retrieves the type of data contained within the source.
|
||||
Common values for the type of data are POSITION, NORMAL, COLOR and TEXCOORD.
|
||||
Please see FUDaeGeometryInput for more information.
|
||||
@see FUDaeGeometryInput.
|
||||
@return The type of data contained within the source. */
|
||||
FUDaeGeometryInput::Semantic GetSourceType() const { return sourceType; }
|
||||
|
||||
/** Sets the user-friendly name of the data source. The name is optional and is used to
|
||||
keep around a user-friendly name for texture coordinate sets or color sets.
|
||||
@param _name The user-friendly name of the data source. */
|
||||
void SetName(const fstring& _name) { name = _name; }
|
||||
|
||||
/** Overwrites the data contained within the data source.
|
||||
@param _sourceData The new data for this source.
|
||||
@param _sourceStride The stride for the new data.
|
||||
@param offset The offset at which to start retrieving the new data.
|
||||
This argument defaults at 0 to indicate that the data copy should start from the beginning.
|
||||
@param count The number of data entries to copy into the data source.
|
||||
This argument defaults at 0 to indicate that the data copy should include everything. */
|
||||
void SetSourceData(const FloatList& _sourceData, uint32 _sourceStride, size_t offset=0, size_t count=0);
|
||||
|
||||
/** [INTERNAL] Sets the XML tree node associated with the data source.
|
||||
@todo Take the XML tree node out of this class.
|
||||
@param _sourceNode A XML tree node. */
|
||||
void SetSourceNode(xmlNode* _sourceNode) { sourceNode = _sourceNode; }
|
||||
|
||||
/** Sets the type of data contained within this data source.
|
||||
@param type The new type of data for this data source. */
|
||||
void SetSourceType(FUDaeGeometryInput::Semantic type);
|
||||
|
||||
/** [INTERNAL] Clones this data source. You will need to release this pointer manually.
|
||||
@return An identical copy of the data source. */
|
||||
FCDGeometrySource* Clone() const;
|
||||
|
||||
/** [INTERNAL] Reads in the \<source\> element from a given COLLADA XML tree node.
|
||||
@param sourceNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the data source.*/
|
||||
FUStatus LoadFromXML(xmlNode* sourceNode);
|
||||
|
||||
/** [INTERNAL] Writes out the \<source\> element to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the data source.
|
||||
@return The created \<source\> element XML tree node. */
|
||||
xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif // _FCD_GEOMETRY_SOURCE_H_
|
||||
@@ -1,163 +0,0 @@
|
||||
/*
|
||||
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;
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/**
|
||||
@file FCDGeometrySpline.h
|
||||
This file contains the FCDGeometrySpline class.
|
||||
The FCDGeometrySpline class hold the information for one COLLADA geometric spline.
|
||||
*/
|
||||
#ifndef _FCD_GEOMETRY_SPLINE_H_
|
||||
#define _FCD_GEOMETRY_SPLINE_H_
|
||||
|
||||
#include "FCDocument/FCDObject.h"
|
||||
|
||||
class FCDocument;
|
||||
class FCDGeometry;
|
||||
|
||||
/** A dynamically-sized array of geometric spline control points. Each control point is simply one 3D position. @ingroup FCDGeometry */
|
||||
typedef vector<FMVector3> FCDCVs;
|
||||
/** A dynamically-sized array of weight values. Each weigth value represents a knot of a control point. @ingroup FCDGeometry */
|
||||
typedef vector<double> FCDKnots;
|
||||
|
||||
/**
|
||||
A COLLADA geometric spline.
|
||||
|
||||
A COLLADA spline contains a list of control points (CVs) that define an ordered list of 3D coordinates
|
||||
that influence the spline. The spline also contains a matching list of knots: there should be as many control
|
||||
points as there are knots.
|
||||
|
||||
A COLLADA spline may be closed or open. If the spline is closed, then the first control point should be
|
||||
re-used when evaluating the last control point: the result should be a continuous curve, while an open
|
||||
spline will result in a discontinuity at each end.
|
||||
|
||||
@todo: Insert the mathematical formula to calculate the spline position.
|
||||
|
||||
@ingroup FCDGeometry
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDGeometrySpline : public FCDObject
|
||||
{
|
||||
private:
|
||||
FCDGeometry* parent;
|
||||
FCDCVs cvs;
|
||||
FCDKnots knots;
|
||||
bool isClosed;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly. Use the FCDGeometry::CreateMesh function instead.
|
||||
@param document The COLLADA document that owns the new spline.
|
||||
@param parent The geometry entity that contains the new spline. */
|
||||
FCDGeometrySpline(FCDocument* document, FCDGeometry* parent);
|
||||
|
||||
/** Destructor: do not use directly. All geometric splines are released with the geometry that they belong to. */
|
||||
virtual ~FCDGeometrySpline();
|
||||
|
||||
/** Retrieve the parent of this geometric spline: the geometry entity.
|
||||
@return The geometry entity that this spline belongs to. */
|
||||
FCDGeometry* GetParent() { return parent; }
|
||||
const FCDGeometry* GetParent() const { return parent; } /**< See above. */
|
||||
|
||||
/** Retrieves the list of control points for the spline.
|
||||
@return The list of control points. */
|
||||
inline FCDCVs& GetCVs() { return cvs; }
|
||||
inline const FCDCVs& GetCVs() const { return cvs; } /**< See above. */
|
||||
|
||||
/** Retrieves the number of control points for the spline.
|
||||
@return The control point count. */
|
||||
inline size_t GetCVCount() const { return cvs.size(); }
|
||||
|
||||
/** Retrieves a specific control point of the spline.
|
||||
@param index The index of the control point.
|
||||
The index should always be less than the number of control point.
|
||||
@return The control point. */
|
||||
inline FMVector3* GetCV(size_t index) { FUAssert(index < GetCVCount(), return NULL); return &(cvs.at(index)); }
|
||||
inline const FMVector3* GetCV(size_t index) const { FUAssert(index < GetCVCount(), return NULL); return &(cvs.at(index)); } /**< See above. */
|
||||
|
||||
/** Retrieves the list of knots for the spline.
|
||||
@return The list of knots. */
|
||||
inline FCDKnots& GetKnots() { return knots; }
|
||||
inline const FCDKnots& GetKnots() const { return knots; } /**< See above. */
|
||||
|
||||
/** Retrieves the number of knots for the spline.
|
||||
@return The knot count. */
|
||||
inline size_t GetKnotCount() const { return knots.size(); }
|
||||
|
||||
/** Retrieves a specific knot of the spline.
|
||||
@param index The index of the knot. The index should always be less than the number of knots.
|
||||
@return The knot value. */
|
||||
inline double GetKnot(size_t index) const { FUAssert(index < GetKnotCount(), return 0.0); return knots.at(index); }
|
||||
|
||||
/** Retrieves whether this spline is closed.
|
||||
@return Whether the spline is closed. */
|
||||
inline bool IsClosed() const { return isClosed; }
|
||||
|
||||
/** Retrieves whether this spline is open.
|
||||
@return Whether the spline is open. */
|
||||
inline bool IsOpen() const { return !isClosed; }
|
||||
|
||||
/** Overwrites the list of control points for this spline with a new ordered list of control points.
|
||||
@param _cvs The new control points. */
|
||||
inline void SetCVs(const FCDCVs& _cvs) { cvs = _cvs; }
|
||||
|
||||
/** Overwrites the list of knots for this spline with a new ordered list of knots.
|
||||
@param _knots The new knots. */
|
||||
inline void SetKnots(const FCDKnots& _knots) { knots = _knots; }
|
||||
|
||||
/** Sets the spline closed state.
|
||||
@param _isClosed The new closed state. */
|
||||
inline void SetClosed(bool _isClosed) { isClosed = _isClosed; }
|
||||
|
||||
/** [INTERNAL] Reads in the \<spline\> element from a given COLLADA XML tree node.
|
||||
@param splineNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the spline.*/
|
||||
FUStatus LoadFromXML(xmlNode* splineNode);
|
||||
|
||||
/** [INTERNAL] Writes out the \<spline\> element to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the spline information.
|
||||
@return The created \<spline\> element XML tree node. */
|
||||
xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif // _FCD_GEOMETRY_SPLINE_H_
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDImage.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
#include "FUtils/FUFileManager.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDImage::FCDImage(FCDocument* document) : FCDEntity(document, "Image")
|
||||
{
|
||||
width = 0;
|
||||
height = 0;
|
||||
depth = 0;
|
||||
}
|
||||
|
||||
FCDImage::~FCDImage()
|
||||
{
|
||||
}
|
||||
|
||||
// Read in the image information from the COLLADA document
|
||||
FUStatus FCDImage::LoadFromXML(xmlNode* imageNode)
|
||||
{
|
||||
FUStatus status = FCDEntity::LoadFromXML(imageNode);
|
||||
if (!status) return status;
|
||||
if (!IsEquivalent(imageNode->name, DAE_IMAGE_ELEMENT))
|
||||
{
|
||||
return status.Warning(FS("Image library contains unknown element."), imageNode->line);
|
||||
}
|
||||
|
||||
if(HasNodeProperty(imageNode, DAE_WIDTH_ELEMENT))
|
||||
width = FUStringConversion::ToUInt32(ReadNodeProperty(imageNode, DAE_WIDTH_ELEMENT));
|
||||
if(HasNodeProperty(imageNode, DAE_HEIGHT_ELEMENT))
|
||||
height = FUStringConversion::ToUInt32(ReadNodeProperty(imageNode, DAE_HEIGHT_ELEMENT));
|
||||
if(HasNodeProperty(imageNode, DAE_DEPTH_ELEMENT))
|
||||
depth = FUStringConversion::ToUInt32(ReadNodeProperty(imageNode, DAE_DEPTH_ELEMENT));
|
||||
|
||||
// Read in the image's filename, within the <init_from> element: binary images are not supported.
|
||||
xmlNode* filenameSourceNode = FindChildByType(imageNode, DAE_INITFROM_ELEMENT);
|
||||
filename = TO_FSTRING(ReadNodeContentDirect(filenameSourceNode));
|
||||
|
||||
// COLLADA 1.3 backward-compatibility
|
||||
if (filename.empty()) filename = TO_FSTRING(ReadNodeSource(imageNode));
|
||||
|
||||
// Convert the filename to something the OS can use
|
||||
filename = GetDocument()->GetFileManager()->GetFilePath(filename);
|
||||
if (filename.empty())
|
||||
{
|
||||
return status.Fail(FS("Invalid filename for image: ") + TO_FSTRING(GetDaeId()), imageNode->line);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out the image information to the COLLADA xml tree node
|
||||
xmlNode* FCDImage::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* imageNode = WriteToEntityXML(parentNode, DAE_IMAGE_ELEMENT);
|
||||
if (!filename.empty())
|
||||
{
|
||||
fstring url = GetDocument()->GetFileManager()->GetFileURL(filename, true);
|
||||
AddChild(imageNode, DAE_INITFROM_ELEMENT, url);
|
||||
}
|
||||
|
||||
if (width > 0) AddAttribute(imageNode, DAE_WIDTH_ELEMENT, width);
|
||||
if (height > 0) AddAttribute(imageNode, DAE_HEIGHT_ELEMENT, height);
|
||||
if (depth > 0) AddAttribute(imageNode, DAE_DEPTH_ELEMENT, depth);
|
||||
|
||||
WriteToExtraXML(imageNode);
|
||||
return imageNode;
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDImage.h
|
||||
This file contains the FCDImage class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_IMAGE_H_
|
||||
#define _FCD_IMAGE_H_
|
||||
|
||||
#include "FCDocument/FCDEntity.h"
|
||||
|
||||
class FCDocument;
|
||||
|
||||
/**
|
||||
A COLLADA image.
|
||||
|
||||
A COLLADA image encapsulates an image file and are contained
|
||||
within the image library. FCollada doesn't support inlined image bits.
|
||||
|
||||
An image is solely defined by its filename. For some
|
||||
image types and optionally, the width, height and depth of
|
||||
the image may be required and valid.
|
||||
|
||||
@ingroup FCDEffect
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDImage : public FCDEntity
|
||||
{
|
||||
private:
|
||||
fstring filename;
|
||||
uint32 width;
|
||||
uint32 height;
|
||||
uint32 depth;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDLibrary::AddEntity function.
|
||||
@param document The COLLADA document that owns the image. */
|
||||
FCDImage(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
Instead, use the FCDLibrary::ReleaseEntity function. */
|
||||
virtual ~FCDImage();
|
||||
|
||||
/** Retrieves the entity type for this class. This function is part
|
||||
of the FCDEntity class interface.
|
||||
@return The entity type: IMAGE. */
|
||||
virtual Type GetType() const { return IMAGE; }
|
||||
|
||||
/** Retrieves the filename of the image file.
|
||||
This is the image file that you should load when attempting
|
||||
to use the image bits. FCollada will deal with the filename
|
||||
internally and provide an absolute filename.
|
||||
@return The filename of the image file. */
|
||||
const fstring& GetFilename() const { return filename; }
|
||||
|
||||
/** Sets the filename of the image file.
|
||||
This is the image file that you should load when attempting
|
||||
to use the image bits. FCollada will deal with the filename
|
||||
internally and export a relative filename.
|
||||
@param _filename The filename of the image file. */
|
||||
void SetFilename(const fstring& _filename) { filename = _filename; }
|
||||
|
||||
/** Retrieves the width of the image.
|
||||
This parameter is useful for off-screen render targets and is
|
||||
optional for texture image files.
|
||||
@return The width of the image. This value will be zero to indicate
|
||||
that you should retrieve the width of the image from the image file. */
|
||||
const uint32& GetWidth() const { return width; }
|
||||
|
||||
/** Sets the width of the image.
|
||||
This parameter is useful for off-screen render targets and is
|
||||
optional for texture image files.
|
||||
@param _width The width of the image. This value can be zero to indicate
|
||||
that you should retrieve the width of the image from the image file. */
|
||||
void SetWidth(uint32 _width) { width = _width; }
|
||||
|
||||
/** Retrieves the height of the image.
|
||||
This parameter is useful for off-screen render targets and is
|
||||
optional for texture image files.
|
||||
@return The height of the image. This value will be zero to indicate
|
||||
that you should retrieve the height of the image from the image file. */
|
||||
const uint32& GetHeight() const { return height; }
|
||||
|
||||
/** Sets the height of the image.
|
||||
This parameter is useful for off-screen render targets and is
|
||||
optional for texture image files.
|
||||
@param _height The height of the image. This value can be zero to indicate
|
||||
that you should retrieve the width of the image from the image file. */
|
||||
void SetHeight(uint32 _height) { height = _height; }
|
||||
|
||||
/** Retrieves the depth of the 3D image.
|
||||
This parameter is optional for texture image files.
|
||||
@return The depth of the image. This value will be zero to indicate
|
||||
that you should retrieve the depth of the image from the image file. */
|
||||
const uint32& GetDepth() const { return depth; }
|
||||
|
||||
/** Sets the depth of the 3D image.
|
||||
This parameter is optional for texture image files.
|
||||
@param _depth The depth of the image. This value can be zero to indicate
|
||||
that you should retrieve the depth of the image from the image file. */
|
||||
void SetDepth(uint32 _depth) { depth = _depth; }
|
||||
|
||||
/** [INTERNAL] Reads in the \<image\> element from a given COLLADA XML tree node.
|
||||
@param imageNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the image.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* imageNode);
|
||||
|
||||
/** [INTERNAL] Writes out the \<image\> element to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the image.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif // _FCD_IMAGE_H_
|
||||
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDLibrary.h
|
||||
This file contains the FCDLibrary template class.
|
||||
See the FCDLibrary.hpp file for the template implementation.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_LIBRARY_
|
||||
#define _FCD_LIBRARY_
|
||||
|
||||
class FCDocument;
|
||||
class FCDEntity;
|
||||
|
||||
#include "FCDocument/FCDObject.h"
|
||||
|
||||
/**
|
||||
A COLLADA library.
|
||||
|
||||
A COLLADA library holds a list of entities. There are libraries for the following entities:
|
||||
animations (FCDAnimation), animation clips (FCDAnimationClip), meshes and splines (FCDGeometry),
|
||||
materials (FCDMaterial), effects (FCDEffect), images (FCDImage), skins and morphers (FCDController),
|
||||
cameras (FCDCamera), lights (FCDLight), physics models (FCDPhysicsModel), physics materials
|
||||
(FCDPhysicsMaterial), physics scenes (FCDPhysicsSceneNode) and visual scenes (FCDSceneNode).
|
||||
|
||||
The COLLADA libraries are contained within the FCDocument object.
|
||||
|
||||
@ingroup FCDocument
|
||||
*/
|
||||
template <class T>
|
||||
class FCDLibrary : public FCDObject
|
||||
{
|
||||
protected:
|
||||
/** The list type for the entities. */
|
||||
typedef vector<T*> FCDEntityList;
|
||||
|
||||
/** Entities list. This list should contain all the root entities of the correct type.
|
||||
Note that the following entity types are tree-based, rather than list-based: FCDAnimation,
|
||||
FCDSceneNode and FCDPhysicsSceneNode. */
|
||||
FCDEntityList entities;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
All the necessary libraries are created by the FCDocument object during its creation.
|
||||
@param document The parent document. */
|
||||
FCDLibrary(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
The libraries are released by the FCDocument, just before it is released. */
|
||||
virtual ~FCDLibrary();
|
||||
|
||||
/** Create a new entity within this library.
|
||||
@return The newly created entity. */
|
||||
T* AddEntity();
|
||||
|
||||
/** Releases an entity contained within this library.
|
||||
@param entity The entity to delete. */
|
||||
void ReleaseEntity(T* entity);
|
||||
|
||||
/** Retrieve the library entity with the given COLLADA id.
|
||||
@param daeId The COLLADA id of the entity.
|
||||
@return The library entity which matches the COLLADA id.
|
||||
This pointer will be NULL if no matching entity was found. */
|
||||
T* FindDaeId(const string& daeId);
|
||||
|
||||
/** Returns whether the library contains no entities.
|
||||
@return Whether the library is empty. */
|
||||
inline bool IsEmpty() const { return entities.empty(); }
|
||||
|
||||
/** [INTERNAL] Reads in the contents of the library from the COLLADA XML document.
|
||||
@param node The COLLADA XML tree node to parse into entities.
|
||||
@return The status of the import. If the status is not successful, it may be dangerous to
|
||||
extract information from the library. */
|
||||
virtual FUStatus LoadFromXML(xmlNode* node);
|
||||
|
||||
/** [INTERNAL] Writes out the library entities to the COLLADA XML document.
|
||||
@param node The COLLADA XML tree node in which to write the library entities. */
|
||||
virtual void WriteToXML(xmlNode* node) const;
|
||||
|
||||
/** @deprecated [INTERNAL] Retrieves the list of post-processing commands for the entities of this library.
|
||||
@return The list of post-processing commands. */
|
||||
StringList GetPostProcessCmds() const;
|
||||
|
||||
/** Retrieve the number of entities within the library.
|
||||
@return the number of entities contained within the library. */
|
||||
inline size_t GetEntityCount() const { return entities.size(); }
|
||||
|
||||
/** Retrieve an indexed entity from the library.
|
||||
@param index The index of the entity to retrieve.
|
||||
Should be within the range [0, GetEntityCount()[.
|
||||
@return The indexed entity. */
|
||||
inline T* GetEntity(size_t index) { FUAssert(index < GetEntityCount(), return NULL); return entities.at(index); }
|
||||
|
||||
/** Retrieve an indexed entity from the library.
|
||||
@param index The index of the entity to retrieve.
|
||||
Should be within the range [0, GetEntityCount()[.
|
||||
@return The indexed entity. */
|
||||
inline const T* GetEntity(size_t index) const { FUAssert(index < GetEntityCount(), return NULL); return entities.at(index); }
|
||||
};
|
||||
|
||||
#include "FCDocument/FCDLibrary.hpp"
|
||||
|
||||
#endif // _FCD_LIBRARY_
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
|
||||
template <class T>
|
||||
FCDLibrary<T>::FCDLibrary(FCDocument* document) : FCDObject(document, "FCDLibrary")
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
FCDLibrary<T>::~FCDLibrary()
|
||||
{
|
||||
CLEAR_POINTER_VECTOR(entities);
|
||||
}
|
||||
|
||||
|
||||
// Create a new entity within this library
|
||||
template <class T>
|
||||
T* FCDLibrary<T>::AddEntity()
|
||||
{
|
||||
T* entity = new T(GetDocument());
|
||||
entities.push_back(entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
// Deletes a entity of this library
|
||||
template <class T>
|
||||
void FCDLibrary<T>::ReleaseEntity(T* entity)
|
||||
{
|
||||
// Not yet implemented, as this will most likely result in dangling pointers!
|
||||
// Needs more structure...
|
||||
}
|
||||
|
||||
|
||||
// Read in a list of entities for a library of a COLLADA document
|
||||
template <class T>
|
||||
FUStatus FCDLibrary<T>::LoadFromXML(xmlNode* node)
|
||||
{
|
||||
FUStatus status;
|
||||
for (xmlNode* entityNode = node->children; entityNode != NULL; entityNode = entityNode->next)
|
||||
{
|
||||
if (entityNode->type == XML_ELEMENT_NODE)
|
||||
{
|
||||
T* entity = AddEntity();
|
||||
status.AppendStatus(entity->LoadFromXML(entityNode));
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out the library to the COLLADA xml document
|
||||
template <class T>
|
||||
void FCDLibrary<T>::WriteToXML(xmlNode* node) const
|
||||
{
|
||||
for (typename FCDEntityList::const_iterator itEntity = entities.begin(); itEntity != entities.end(); ++itEntity)
|
||||
{
|
||||
const T* entity = (const T*) (*itEntity);
|
||||
entity->WriteToXML(node);
|
||||
}
|
||||
}
|
||||
|
||||
// Search for the entity in this library with a given COLLADA id.
|
||||
template <class T>
|
||||
T* FCDLibrary<T>::FindDaeId(const string& _daeId)
|
||||
{
|
||||
const char* daeId = FUDaeParser::SkipPound(_daeId);
|
||||
for (typename FCDEntityList::iterator itEntity = entities.begin(); itEntity != entities.end(); ++itEntity)
|
||||
{
|
||||
if ((*itEntity)->GetDaeId() == daeId) return (*itEntity);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
StringList FCDLibrary<T>::GetPostProcessCmds() const
|
||||
{
|
||||
StringList res;
|
||||
for (typename FCDEntityList::const_iterator itEntity = entities.begin(); itEntity != entities.end(); ++itEntity)
|
||||
{
|
||||
res = (*itEntity)->GetPostProcessCmds();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -1,282 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDAnimated.h"
|
||||
#include "FCDocument/FCDLight.h"
|
||||
#include "FCDocument/FCDSceneNode.h"
|
||||
#include "FUtils/FUStringConversion.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDLight::FCDLight(FCDocument* document) : FCDTargetedEntity(document, "Light")
|
||||
{
|
||||
color = FMVector3(1.0f, 1.0f, 1.0f);
|
||||
intensity = 1.0f;
|
||||
lightType = POINT;
|
||||
constantAttenuationFactor = linearAttenuationFactor = quadracticAttenuationFactor = 0.0f;
|
||||
fallOffExponent = 1.0f;
|
||||
outerAngle = fallOffAngle = 30.0f;
|
||||
penumbraAngle = 0.0f;
|
||||
dropoff = 10.0f;
|
||||
overshoots = true;
|
||||
}
|
||||
|
||||
FCDLight::~FCDLight()
|
||||
{
|
||||
}
|
||||
|
||||
// Load this light from the given COLLADA document's node
|
||||
FUStatus FCDLight::LoadFromXML(xmlNode* lightNode)
|
||||
{
|
||||
FUStatus status = FCDEntity::LoadFromXML(lightNode);
|
||||
if (!status) return status;
|
||||
if (!IsEquivalent(lightNode->name, DAE_LIGHT_ELEMENT))
|
||||
{
|
||||
return status.Warning(FS("Light library contains unknown element."), lightNode->line);
|
||||
}
|
||||
|
||||
// Grab the <technique_common> element. If not present, assume COLLADA 1.3
|
||||
xmlNode* commonTechniqueNode = FindChildByType(lightNode, DAE_TECHNIQUE_COMMON_ELEMENT);
|
||||
bool isCollada1_3 = commonTechniqueNode == NULL;
|
||||
xmlNode* maxTechniqueNode = FindTechnique(lightNode, DAEMAX_MAX_PROFILE);
|
||||
xmlNode* mayaTechniqueNode = FindTechnique(lightNode, DAEMAYA_MAYA_PROFILE);
|
||||
|
||||
// Create the correct light source
|
||||
xmlNode* lightParameterNode = NULL;
|
||||
if (isCollada1_3)
|
||||
{
|
||||
// COLLADA 1.3 backward-compatibility: read the 'type' attribute of the <light> element
|
||||
string type = ReadNodeProperty(lightNode, DAE_TYPE_ATTRIBUTE);
|
||||
if (type == DAE_AMBIENT_LIGHT_TYPE) lightType = AMBIENT;
|
||||
else if (type == DAE_DIRECTIONAL_LIGHT_TYPE) lightType = DIRECTIONAL;
|
||||
else if (type == DAE_POINT_LIGHT_TYPE) lightType = POINT;
|
||||
else if (type == DAE_SPOT_LIGHT_TYPE) lightType = SPOT;
|
||||
else
|
||||
{
|
||||
status.Warning(FS("Unknown light type value for light: ") + TO_FSTRING(GetDaeId()), lightNode->line);
|
||||
}
|
||||
|
||||
// COLLADA 1.3.2 backward-compatibility: look for this hack for the parameters under a common-profile technique
|
||||
lightParameterNode = FindTechnique(lightNode, DAE_COMMON_PROFILE);
|
||||
if (lightParameterNode == NULL) lightParameterNode = lightNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Look for the <point>, <directional>, <spot> or <ambient> element under the common-profile technique
|
||||
for (xmlNode* child = commonTechniqueNode->children; child != NULL; child = child->next)
|
||||
{
|
||||
if (child->type != XML_ELEMENT_NODE) continue;
|
||||
if (IsEquivalent(child->name, DAE_LIGHT_POINT_ELEMENT)) { lightParameterNode = child; lightType = POINT; break; }
|
||||
else if (IsEquivalent(child->name, DAE_LIGHT_SPOT_ELEMENT)) { lightParameterNode = child; lightType = SPOT; break; }
|
||||
else if (IsEquivalent(child->name, DAE_LIGHT_AMBIENT_ELEMENT)) { lightParameterNode = child; lightType = AMBIENT; break; }
|
||||
else if (IsEquivalent(child->name, DAE_LIGHT_DIRECTIONAL_ELEMENT)) { lightParameterNode = child; lightType = DIRECTIONAL; break; }
|
||||
else
|
||||
{
|
||||
status.Warning(FS("Unknown element under <light><technique_common> for light: ") + TO_FSTRING(GetDaeId()), child->line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify the light's basic structures are found
|
||||
if (lightParameterNode == NULL)
|
||||
{
|
||||
return status.Fail(FS("Unable to find the parameter root node for light: ") + TO_FSTRING(GetDaeId()), lightNode->line);
|
||||
}
|
||||
|
||||
// Retrieve the light parameters
|
||||
StringList parameterNames;
|
||||
xmlNodeList parameterNodes;
|
||||
FindParameters(lightParameterNode, parameterNames, parameterNodes);
|
||||
FindParameters(maxTechniqueNode, parameterNames, parameterNodes);
|
||||
FindParameters(mayaTechniqueNode, parameterNames, parameterNodes);
|
||||
xmlNode* extraNode = FindChildByType(lightNode, DAE_EXTRA_ELEMENT);
|
||||
xmlNode* maxExtraNode = FindTechnique(extraNode, DAEMAX_MAX_PROFILE);
|
||||
FindParameters(maxExtraNode, parameterNames, parameterNodes);
|
||||
|
||||
// Parse the light parameters
|
||||
FUDaeFunction::Function attenuationFunction = FUDaeFunction::CONSTANT;
|
||||
float attenuationFactor = 0.0f;
|
||||
xmlNode* attenuationFactorNode = NULL;
|
||||
|
||||
size_t parameterCount = parameterNodes.size();
|
||||
for (size_t i = 0; i < parameterCount; ++i)
|
||||
{
|
||||
xmlNode* parameterNode = parameterNodes[i];
|
||||
const string& parameterName = parameterNames[i];
|
||||
const char* content = ReadNodeContentDirect(parameterNode);
|
||||
if (parameterName == DAE_COLOR_LIGHT_PARAMETER || parameterName == DAE_COLOR_LIGHT_PARAMETER1_3)
|
||||
{
|
||||
color = FUStringConversion::ToPoint(content);
|
||||
FCDAnimatedColor::Create(GetDocument(), parameterNode, &color);
|
||||
}
|
||||
else if (parameterName == DAE_CONST_ATTENUATION_LIGHT_PARAMETER)
|
||||
{
|
||||
constantAttenuationFactor = FUStringConversion::ToFloat(content);
|
||||
FCDAnimatedFloat::Create(GetDocument(), parameterNode, &constantAttenuationFactor);
|
||||
}
|
||||
else if (parameterName == DAE_LIN_ATTENUATION_LIGHT_PARAMETER)
|
||||
{
|
||||
linearAttenuationFactor = FUStringConversion::ToFloat(content);
|
||||
FCDAnimatedFloat::Create(GetDocument(), parameterNode, &linearAttenuationFactor);
|
||||
}
|
||||
else if (parameterName == DAE_QUAD_ATTENUATION_LIGHT_PARAMETER)
|
||||
{
|
||||
quadracticAttenuationFactor = FUStringConversion::ToFloat(content);
|
||||
FCDAnimatedFloat::Create(GetDocument(), parameterNode, &quadracticAttenuationFactor);
|
||||
}
|
||||
else if (parameterName == DAE_ATTENUATION_LIGHT_PARAMETER1_3)
|
||||
{
|
||||
attenuationFunction = FUDaeFunction::FromString(content);
|
||||
}
|
||||
else if (parameterName == DAE_ATTENUATIONSCALE_LIGHT_PARAMETER1_3)
|
||||
{
|
||||
attenuationFactor = FUStringConversion::ToFloat(content);
|
||||
attenuationFactorNode = parameterNode;
|
||||
}
|
||||
else if (parameterName == DAE_FALLOFFEXPONENT_LIGHT_PARAMETER)
|
||||
{
|
||||
fallOffExponent = FUStringConversion::ToFloat(content);
|
||||
FCDAnimatedFloat::Create(GetDocument(), parameterNode, &fallOffExponent);
|
||||
}
|
||||
else if (parameterName == DAE_FALLOFF_LIGHT_PARAMETER1_3)
|
||||
{
|
||||
fallOffExponent = (float) FUDaeFunction::FromString(content);
|
||||
}
|
||||
else if (parameterName == DAE_FALLOFFANGLE_LIGHT_PARAMETER || parameterName == DAE_ANGLE_LIGHT_PARAMETER1_3)
|
||||
{
|
||||
fallOffAngle = FUStringConversion::ToFloat(content);
|
||||
FCDAnimatedFloat::Create(GetDocument(), parameterNode, &fallOffAngle);
|
||||
}
|
||||
else if (parameterName == DAESHD_INTENSITY_LIGHT_PARAMETER || parameterName == DAESHD_INTENSITY_LIGHT_PARAMETER1_3)
|
||||
{
|
||||
intensity = FUStringConversion::ToFloat(content);
|
||||
FCDAnimatedFloat::Create(GetDocument(), parameterNode, &intensity);
|
||||
}
|
||||
else if (parameterName == DAEMAX_OUTERCONE_LIGHT_PARAMETER || parameterName == DAEMAX_OUTERCONE_LIGHT_PARAMETER1_3)
|
||||
{
|
||||
outerAngle = FUStringConversion::ToFloat(content);
|
||||
FCDAnimatedFloat::Create(GetDocument(), parameterNode, &outerAngle);
|
||||
}
|
||||
else if (parameterName == DAEMAX_OVERSHOOT_LIGHT_PARAMETER || parameterName == DAEMAX_OVERSHOOT_LIGHT_PARAMETER1_3)
|
||||
{
|
||||
overshoots = FUStringConversion::ToBoolean(content);
|
||||
}
|
||||
else if (parameterName == DAEMAX_TARGET_LIGHT_PARAMETER || parameterName == DAEMAX_TARGET_LIGHT_PARAMETER1_3)
|
||||
{
|
||||
SetTargetId(content);
|
||||
}
|
||||
else if (parameterName == DAEMAYA_PENUMBRA_LIGHT_PARAMETER || parameterName == DAEMAYA_PENUMBRA_LIGHT_PARAMETER1_3)
|
||||
{
|
||||
penumbraAngle = FUStringConversion::ToFloat(content);
|
||||
FCDAnimatedFloat::Create(GetDocument(), parameterNode, &penumbraAngle);
|
||||
}
|
||||
else if (parameterName == DAEMAYA_DROPOFF_LIGHT_PARAMETER || parameterName == DAE_FALLOFFSCALE_LIGHT_PARAMETER1_3)
|
||||
{
|
||||
dropoff = FUStringConversion::ToFloat(content);
|
||||
FCDAnimatedFloat::Create(GetDocument(), parameterNode, &dropoff);
|
||||
}
|
||||
else if (parameterName == DAEMAX_ASPECTRATIO_LIGHT_PARAMETER || parameterName == DAEMAX_ASPECTRATIO_LIGHT_PARAMETER1_3)
|
||||
{
|
||||
aspectRatio = FUStringConversion::ToFloat(content);
|
||||
FCDAnimatedFloat::Create(GetDocument(), parameterNode, &aspectRatio);
|
||||
}
|
||||
else
|
||||
{
|
||||
status.Warning(FS("Unknown program parameter for light: ") + TO_FSTRING(GetDaeId()), parameterNode->line);
|
||||
}
|
||||
}
|
||||
|
||||
if (attenuationFactorNode != NULL)
|
||||
{
|
||||
// Match the deprecated COLLADA 1.3 parameter's animation to the correct, new attenuation factor
|
||||
switch (attenuationFunction)
|
||||
{
|
||||
case FUDaeFunction::CONSTANT:
|
||||
constantAttenuationFactor = attenuationFactor;
|
||||
FCDAnimatedFloat::Create(GetDocument(), attenuationFactorNode, &constantAttenuationFactor);
|
||||
break;
|
||||
case FUDaeFunction::LINEAR:
|
||||
linearAttenuationFactor = attenuationFactor;
|
||||
FCDAnimatedFloat::Create(GetDocument(), attenuationFactorNode, &linearAttenuationFactor);
|
||||
break;
|
||||
case FUDaeFunction::QUADRATIC:
|
||||
quadracticAttenuationFactor = attenuationFactor;
|
||||
FCDAnimatedFloat::Create(GetDocument(), attenuationFactorNode, &quadracticAttenuationFactor);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out this light to the COLLADA XML document
|
||||
xmlNode* FCDLight::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
// Create the base light node
|
||||
xmlNode* lightNode = WriteToEntityXML(parentNode, DAE_LIGHT_ELEMENT);
|
||||
xmlNode* baseNode = AddChild(lightNode, DAE_TECHNIQUE_COMMON_ELEMENT);
|
||||
const char* baseNodeName;
|
||||
switch (lightType)
|
||||
{
|
||||
case POINT: baseNodeName = DAE_LIGHT_POINT_ELEMENT; break;
|
||||
case SPOT: baseNodeName = DAE_LIGHT_SPOT_ELEMENT; break;
|
||||
case AMBIENT: baseNodeName = DAE_LIGHT_AMBIENT_ELEMENT; break;
|
||||
case DIRECTIONAL: baseNodeName = DAE_LIGHT_DIRECTIONAL_ELEMENT; break;
|
||||
default: baseNodeName = DAEERR_UNKNOWN_INPUT; break;
|
||||
}
|
||||
baseNode = AddChild(baseNode, baseNodeName);
|
||||
|
||||
// Add the application-specific technique
|
||||
xmlNode* techniqueMayaNode = AddTechniqueChild(lightNode, DAEMAYA_MAYA_PROFILE);
|
||||
xmlNode* techniqueMaxNode = AddTechniqueChild(lightNode, DAEMAX_MAX_PROFILE);
|
||||
|
||||
// Write out the light parameters
|
||||
string colorValue = FUStringConversion::ToString(color);
|
||||
xmlNode* colorNode = AddChild(baseNode, DAE_COLOR_LIGHT_PARAMETER, colorValue);
|
||||
GetDocument()->WriteAnimatedValueToXML(&color.x, colorNode, "color");
|
||||
|
||||
xmlNode* attenuationBaseNode = (lightType == POINT || lightType == SPOT) ? baseNode : techniqueMaxNode;
|
||||
xmlNode* attenuationNode = AddChild(attenuationBaseNode, DAE_CONST_ATTENUATION_LIGHT_PARAMETER, constantAttenuationFactor);
|
||||
GetDocument()->WriteAnimatedValueToXML(&constantAttenuationFactor, attenuationNode, "constant_attenuation");
|
||||
attenuationNode = AddChild(attenuationBaseNode, DAE_LIN_ATTENUATION_LIGHT_PARAMETER, linearAttenuationFactor);
|
||||
GetDocument()->WriteAnimatedValueToXML(&linearAttenuationFactor, attenuationNode, "linear_attenuation");
|
||||
attenuationNode = AddChild(attenuationBaseNode, DAE_QUAD_ATTENUATION_LIGHT_PARAMETER, quadracticAttenuationFactor);
|
||||
GetDocument()->WriteAnimatedValueToXML(&quadracticAttenuationFactor, attenuationNode, "quadratic_attenuation");
|
||||
|
||||
xmlNode* falloffBaseNode = (lightType == SPOT) ? baseNode : techniqueMaxNode;
|
||||
xmlNode* falloffNode = AddChild(falloffBaseNode, DAE_FALLOFFANGLE_LIGHT_PARAMETER, fallOffAngle);
|
||||
GetDocument()->WriteAnimatedValueToXML(&fallOffAngle, falloffNode, "falloff_angle");
|
||||
falloffNode = AddChild(falloffBaseNode, DAE_FALLOFFEXPONENT_LIGHT_PARAMETER, fallOffExponent);
|
||||
GetDocument()->WriteAnimatedValueToXML(&fallOffExponent, falloffNode, "falloff_exponent");
|
||||
|
||||
xmlNode* intensityNode = AddChild(techniqueMaxNode, DAESHD_INTENSITY_LIGHT_PARAMETER, intensity);
|
||||
AddChild(techniqueMayaNode, DAESHD_INTENSITY_LIGHT_PARAMETER, intensity);
|
||||
GetDocument()->WriteAnimatedValueToXML(&intensity, intensityNode, "intensity");
|
||||
xmlNode* outerAngleNode = AddChild(techniqueMaxNode, DAEMAX_OUTERCONE_LIGHT_PARAMETER, outerAngle);
|
||||
GetDocument()->WriteAnimatedValueToXML(&outerAngle, outerAngleNode, "outer_angle");
|
||||
xmlNode* penumbraAngleNode = AddChild(techniqueMayaNode, DAEMAYA_PENUMBRA_LIGHT_PARAMETER, penumbraAngle);
|
||||
GetDocument()->WriteAnimatedValueToXML(&penumbraAngle, penumbraAngleNode, "penumbra_angle");
|
||||
xmlNode* aspectRatioNode = AddChild(techniqueMaxNode, DAEMAX_ASPECTRATIO_LIGHT_PARAMETER, aspectRatio);
|
||||
GetDocument()->WriteAnimatedValueToXML(&aspectRatio, aspectRatioNode, "aspect_ratio");
|
||||
xmlNode* dropoffNode = AddChild(techniqueMayaNode, DAEMAYA_DROPOFF_LIGHT_PARAMETER, dropoff);
|
||||
GetDocument()->WriteAnimatedValueToXML(&dropoff, dropoffNode, "dropoff");
|
||||
AddChild(techniqueMaxNode, DAEMAX_OVERSHOOT_LIGHT_PARAMETER, overshoots);
|
||||
|
||||
if (GetTargetNode() != NULL) AddChild(techniqueMaxNode, DAEMAX_TARGET_LIGHT_PARAMETER, GetTargetNode()->GetDaeId());
|
||||
|
||||
FCDEntity::WriteToExtraXML(lightNode);
|
||||
return lightNode;
|
||||
}
|
||||
@@ -1,286 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDLight.h
|
||||
This file contains the FCDLight class.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_LIGHT_H_
|
||||
#define _FCD_LIGHT_H_
|
||||
|
||||
#include "FCDocument/FCDTargetedEntity.h"
|
||||
#include "FUtils/FUDaeEnum.h"
|
||||
|
||||
class FCDocument;
|
||||
class FCDSceneNode;
|
||||
|
||||
/**
|
||||
A COLLADA light.
|
||||
Based on the FCDTargetedEntity class to supported aimed lights.
|
||||
COLLADA defines four types of native lights: point, spot, ambient and directional.
|
||||
These four types are fully handled by this class: make sure to check the type flag
|
||||
as well as which information to expect for each light type.
|
||||
|
||||
A COLLADA ambient light has a global color, which should be added to
|
||||
all other lighting on all geometry.
|
||||
|
||||
A COLLADA directional light has a global color, which should be multiplied
|
||||
to the cosine of the angle between the normal vector of a triangle
|
||||
and the direction of the light. Note that the direction will be calculated
|
||||
from the transforms, for each instance, and is not provided by this class.
|
||||
|
||||
A COLLADA point light has a color which attenuates as the distance increases
|
||||
between the light position and the vertex being shaded. Note that the position
|
||||
will be calculated from the transforms, for each instance,
|
||||
and is not provided by this class.
|
||||
|
||||
A COLLADA spot light is a point light which lights only the objects that
|
||||
appear within a specific angle, with respect to the direction of the light.
|
||||
Note that the position and the direction will be calculated from the
|
||||
transforms, for each instance, and is not provided by this class.
|
||||
|
||||
@ingroup FCDocument
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDLight : public FCDTargetedEntity
|
||||
{
|
||||
public:
|
||||
/** The types of lights supported by this class. */
|
||||
enum LightType
|
||||
{
|
||||
POINT, /**< A point light. This is the default type. */
|
||||
SPOT, /**< A spot light. */
|
||||
AMBIENT, /**< An ambient light. */
|
||||
DIRECTIONAL /**< A directional light. */
|
||||
};
|
||||
|
||||
private:
|
||||
// Common Light parameters
|
||||
FMVector3 color;
|
||||
float intensity; // Max and Maya
|
||||
LightType lightType;
|
||||
|
||||
// Point and spot light parameters
|
||||
float constantAttenuationFactor;
|
||||
float linearAttenuationFactor;
|
||||
float quadracticAttenuationFactor;
|
||||
|
||||
// Spot-specific light parameters
|
||||
float fallOffExponent;
|
||||
float fallOffAngle;
|
||||
float outerAngle; // Max-specific
|
||||
float penumbraAngle; // Maya-specifc: these last two are are related as 'penumbra = outerAngle - fallOffAngle'.
|
||||
float aspectRatio; // Max-specific, for rectangle lights
|
||||
float dropoff; // Maya-specific
|
||||
|
||||
// Directional light parameters
|
||||
// Overshoot is a Max-specific flag that sets a directional light to cover everything,
|
||||
// rather than to be restricted to a cylinder defined by the fallOffAngle/outerAngle.
|
||||
bool overshoots; // Max-specific
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly. Create new lights using the FCDLibrary::AddEntity function.
|
||||
@param document The COLLADA document that contains this light entity. */
|
||||
FCDLight(FCDocument* document);
|
||||
|
||||
/** Destructor: do not release directly. Release lights using the FCDLibrary::ReleaseEntity function.
|
||||
All lights are also released with the document that they belong to. */
|
||||
virtual ~FCDLight();
|
||||
|
||||
/** Retrieves the entity type for this class. This function is part of the FCDEntity interface.
|
||||
@return The entity type: LIGHT. */
|
||||
virtual Type GetType() const { return LIGHT; }
|
||||
|
||||
/** Retrieves the base color for the light. To calculate the light color,
|
||||
multiply the base color with the intensity.
|
||||
@return The base color for the light. */
|
||||
FMVector3& GetColor() { return color; }
|
||||
const FMVector3& GetColor() const { return color; } /**< See above. */
|
||||
|
||||
/** Sets the base color for the light. To calculate the light color,
|
||||
multiply the base color with the intensity.
|
||||
@param col The base color for the light. */
|
||||
void SetColor(const FMVector3& col) { color = col; }
|
||||
|
||||
/** Retrieves the intensity of the light. To calculate the light color,
|
||||
multiply the base color with the intensity.
|
||||
@return The intensity of the light. */
|
||||
float& GetIntensity() { return intensity; }
|
||||
const float& GetIntensity() const { return intensity; } /**< See above. */
|
||||
|
||||
/** Sets the intensity of the light. To calculate the light color,
|
||||
multiply the base color with the intensity.
|
||||
@param _intensity The intensity of the light. */
|
||||
void SetIntensity(float _intensity) { intensity = _intensity; }
|
||||
|
||||
/** Retrieves the type of the light.
|
||||
Make sure to check the type of light before using the values, as some values
|
||||
may not make sense with some types of light.
|
||||
@return The light type. */
|
||||
LightType GetLightType() const { return lightType; }
|
||||
|
||||
/** Sets the type of the light. The default type of a new light is POINT.
|
||||
@param type The light type. */
|
||||
void SetLightType(LightType type) { lightType = type; }
|
||||
|
||||
/** Retrieves the constant attenuation factor for the light.
|
||||
This value is valid only for point and spot lights.
|
||||
@return The constant attenuation factor. */
|
||||
float& GetConstantAttenuationFactor() { return constantAttenuationFactor; }
|
||||
const float& GetConstantAttenuationFactor() const { return constantAttenuationFactor; } /**< See above. */
|
||||
|
||||
/** Sets the constant attenuation factor for the light.
|
||||
This value is valid only for point and spot lights.
|
||||
@param factor The constant attenuation factor. */
|
||||
void SetConstantAttenuationFactor(float factor) { constantAttenuationFactor = factor; }
|
||||
|
||||
/** Retrieves the linear attenuation factor for the light.
|
||||
This value is valid only for point and spot lights.
|
||||
@return The linear attenuation factor. */
|
||||
float& GetLinearAttenuationFactor() { return linearAttenuationFactor; }
|
||||
const float& GetLinearAttenuationFactor() const { return linearAttenuationFactor; } /**< See above. */
|
||||
|
||||
/** Sets the linear attenuation factor for the light.
|
||||
This value is valid only for point and spot lights.
|
||||
@param factor The linear attenuation factor. */
|
||||
void SetLinearAttenuationFactor(float factor) { linearAttenuationFactor = factor; }
|
||||
|
||||
/** Retrieves the quadratic attenuation factor for the light.
|
||||
This value is valid only for point and spot lights.
|
||||
@return The quadratic attenuation factor. */
|
||||
float& GetQuadraticAttenuationFactor() { return quadracticAttenuationFactor; }
|
||||
const float& GetQuadraticAttenuationFactor() const { return quadracticAttenuationFactor; } /**< See above. */
|
||||
|
||||
/** Sets the quadratic attenuation factor for the light.
|
||||
This value is valid only for point and spot lights.
|
||||
@param factor The quadratic attenuation factor. */
|
||||
void SetQuadraticAttenuationFactor(float factor) { quadracticAttenuationFactor = factor; }
|
||||
|
||||
/** Retrieves the fall-off exponent for the light.
|
||||
This value is valid only for spot lights. It determines
|
||||
how fast the lighting turns off, with respect to
|
||||
angles greater than the fall-off angle. This results in a smooth
|
||||
lighting at the spot light's edges.
|
||||
|
||||
IMPORTANT NOTE: Neither ColladaMaya or ColladaMax use this value
|
||||
as neither Maya or 3dsMax use this technique for soft lighting.
|
||||
|
||||
@return The spot light fall-off exponent. */
|
||||
float& GetFallOffExponent() { return fallOffExponent; }
|
||||
const float& GetFallOffExponent() const { return fallOffExponent; } /**< See above. */
|
||||
|
||||
/** Sets the fall-off exponent for the light.
|
||||
@see GetFallOffExponent
|
||||
@param exponent The spot light fall-off exponent. */
|
||||
void SetFallOffExponent(float exponent) { fallOffExponent = exponent; }
|
||||
|
||||
/** Retrieves the fall-off angle for the light.
|
||||
This value is valid only for spot lights. It defines
|
||||
the cone of the spot light.
|
||||
@return The spot light fall-off angle. */
|
||||
float& GetFallOffAngle() { return fallOffAngle; }
|
||||
const float& GetFallOffAngle() const { return fallOffAngle; } /**< See above. */
|
||||
|
||||
/** Sets the fall-off angle for the light.
|
||||
@see GetFallOffAngle
|
||||
@param angle The spot light fall-off angle. */
|
||||
void SetFallOffAngle(float angle) { fallOffAngle = angle; }
|
||||
|
||||
/** Retrieves the outer angle for the light.
|
||||
This value is valid only for spot lights. This value is only used
|
||||
by documents exported by ColladaMax. This value should always be
|
||||
greater than the fall-off angle. It represents the angle at which
|
||||
the lighting is black. All lighting between the fall-off angle and
|
||||
the outer angle is a linear interpolation between the light color
|
||||
and black.
|
||||
@return The spot light outer angle. */
|
||||
float& GetOuterAngle() { return outerAngle; }
|
||||
const float& GetOuterAngle() const { return outerAngle; } /**< See above. */
|
||||
|
||||
/** Sets the outer angle for the light.
|
||||
@see GetOuterAngle
|
||||
@param angle The spot light outer angle. */
|
||||
void SetOuterAngle(float angle) { outerAngle = angle; }
|
||||
|
||||
/** Retrieves the penumbra angle for the light.
|
||||
This value is valid only for spot lights. The value is only used
|
||||
by documents exported by ColladaMaya. This value is relative to
|
||||
the fall-off angle and may be negative. If this value is positive,
|
||||
it determines the outer angle, as described above. If this value
|
||||
is negative, the fall-off angle is used as the outer angle and the
|
||||
fall-off angle + the penumbra angle is used as the full-lighting
|
||||
angle.
|
||||
@see GetOuterAngle
|
||||
@return The spot light penumbra angle. */
|
||||
float& GetPenumbraAngle() { return penumbraAngle; }
|
||||
const float& GetPenumbraAngle() const { return penumbraAngle; } /**< See above. */
|
||||
|
||||
/** Sets the penumbra angle for the light.
|
||||
@see GetPenumbraAngle
|
||||
@param angle The spot light penumbra angle. */
|
||||
void SetPenumbraAngle(float angle) { penumbraAngle = angle; }
|
||||
|
||||
/** Retrieves the aspect ratio for the light.
|
||||
This value is only used by documents exported by ColladaMax.
|
||||
This value is valid only for spot lights and directional lights
|
||||
which project a rectangle (for pyramidal projection). It represents the ratio
|
||||
of the projection's height to the projection's width and defines
|
||||
the projection's rectangle. For pyramidal projections, the fall-off and outer angles
|
||||
represent the width of the projection.
|
||||
Note that there is no way to know if the projection is conic or pyramidal.
|
||||
@return The aspect ratio of the light pyramidal projection. */
|
||||
float& GetAspectRatio() { return aspectRatio; }
|
||||
const float& GetAspectRatio() const { return aspectRatio; } /**< See above. */
|
||||
|
||||
/** Sets the aspect ratio for the light.
|
||||
@see GetAspectRatio
|
||||
@param ratio The aspect ratio of the light pyramidal projection. */
|
||||
void SetAspectRatio(float ratio) { aspectRatio = ratio; }
|
||||
|
||||
/** Retrieves the drop-off for the light.
|
||||
This value is only used by documents exported by ColladaMaya.
|
||||
@return The drop-off for the light. */
|
||||
float& GetDropoff() { return dropoff; }
|
||||
const float& GetDropoff() const { return dropoff; } /**< See above. */
|
||||
|
||||
/** Sets the drop-off for the light.
|
||||
This value is only used by documents exported by ColladaMaya.
|
||||
@param factor The drop-off for the light. */
|
||||
void SetDropoff(float factor) { dropoff = factor; }
|
||||
|
||||
/** Retrieves whether the directional light overshoots.
|
||||
This value is only used by documents exported by ColladaMax.
|
||||
This value is valid only for directional lights. This flag
|
||||
represents whether the directional light has a global projection,
|
||||
as defined in COLLADA, or a cylinder/prism projection.
|
||||
Note that there is no way to know if the projection is conic or pyramidal.
|
||||
@return Whether the directional light overshoots. */
|
||||
bool DoesOvershoot() const { return overshoots; }
|
||||
|
||||
/** Sets whether the directional light overshoots.
|
||||
@see DoesOvershoot
|
||||
@param _overshoots The overshoot flag for the directional light. */
|
||||
void SetOvershoot(bool _overshoots) { overshoots = _overshoots; }
|
||||
|
||||
/** [INTERNAL] Reads in the \<light\> element from a given COLLADA XML tree node.
|
||||
@param lightNode A COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the light.*/
|
||||
FUStatus LoadFromXML(xmlNode* lightNode);
|
||||
|
||||
/** [INTERNAL] Writes out the \<light\> element to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the geometry information.
|
||||
@return The created XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif // _FCD_LIGHT_H_
|
||||
|
||||
@@ -1,211 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDAnimated.h"
|
||||
#include "FCDocument/FCDEffect.h"
|
||||
#include "FCDocument/FCDEffectParameter.h"
|
||||
#include "FCDocument/FCDEffectParameterFactory.h"
|
||||
#include "FCDocument/FCDEffectParameterList.h"
|
||||
#include "FCDocument/FCDMaterial.h"
|
||||
#include "FUtils/FUStringConversion.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
#include "FUtils/FUUniqueStringMap.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDMaterial::FCDMaterial(FCDocument* document) : FCDEntity(document, "VisualMaterial")
|
||||
{
|
||||
effect = NULL;
|
||||
parameters = new FCDEffectParameterList(GetDocument(), true);
|
||||
ownsEffect = false;
|
||||
}
|
||||
|
||||
FCDMaterial::~FCDMaterial()
|
||||
{
|
||||
if (ownsEffect) SAFE_DELETE(effect);
|
||||
effect = NULL;
|
||||
SAFE_DELETE(parameters);
|
||||
techniqueHints.clear();
|
||||
}
|
||||
|
||||
// Cloning
|
||||
FCDMaterial* FCDMaterial::Clone()
|
||||
{
|
||||
FCDMaterial* clone = new FCDMaterial(GetDocument());
|
||||
FCDEntity::Clone(clone);
|
||||
if (effect != NULL)
|
||||
{
|
||||
clone->ownsEffect = true;
|
||||
clone->effect = effect->Clone();
|
||||
}
|
||||
SAFE_DELETE(clone->parameters);
|
||||
clone->parameters = parameters->Clone();
|
||||
return clone;
|
||||
}
|
||||
|
||||
#ifdef __VISUALC__
|
||||
#include <crtdbg.h>
|
||||
#endif // __VISUALC__
|
||||
|
||||
// Flatten the material: remove all the modifier parameters from the parameter list, permanently modifying their base parameter
|
||||
void FCDMaterial::Flatten()
|
||||
{
|
||||
for (FCDEffectParameterList::iterator itP = parameters->begin(); itP != parameters->end(); ++itP)
|
||||
{
|
||||
FCDEffectParameterList generators;
|
||||
if ((*itP)->IsModifier())
|
||||
{
|
||||
// Overwrite the generators
|
||||
FindParametersByReference((*itP)->GetReference(), generators);
|
||||
for (FCDEffectParameterList::iterator itQ = generators.begin(); itQ != generators.end(); ++itQ)
|
||||
{
|
||||
if ((*itP) != (*itQ))
|
||||
{
|
||||
(*itP)->Overwrite(*itQ);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add this parameter to hierarchy below
|
||||
if (effect != NULL) effect->AddParameter((*itP)->Clone());
|
||||
}
|
||||
}
|
||||
CLEAR_POINTER_VECTOR(*parameters);
|
||||
|
||||
if (effect != NULL) effect->Flatten();
|
||||
}
|
||||
|
||||
void FCDMaterial::AddParameter(FCDEffectParameter* parameter)
|
||||
{
|
||||
parameters->push_back(parameter);
|
||||
}
|
||||
|
||||
// Look for the effect parameter with the correct semantic, in order to bind/set its value
|
||||
FCDEffectParameter* FCDMaterial::FindParameterBySemantic(const string& semantic)
|
||||
{
|
||||
return (effect != NULL) ? effect->FindParameterBySemantic(semantic) : NULL;
|
||||
}
|
||||
|
||||
void FCDMaterial::FindParametersBySemantic(const string& semantic, FCDEffectParameterList& _parameters)
|
||||
{
|
||||
parameters->FindSemantic(semantic, _parameters);
|
||||
if (effect != NULL) effect->FindParametersBySemantic(semantic, _parameters);
|
||||
}
|
||||
|
||||
void FCDMaterial::FindParametersByReference(const string& reference, FCDEffectParameterList& _parameters)
|
||||
{
|
||||
parameters->FindReference(reference, _parameters);
|
||||
if (effect != NULL) effect->FindParametersByReference(reference, _parameters);
|
||||
}
|
||||
|
||||
// Parse COLLADA document's <material> element
|
||||
FUStatus FCDMaterial::LoadFromXML(xmlNode* materialNode)
|
||||
{
|
||||
CLEAR_POINTER_VECTOR(*parameters);
|
||||
|
||||
FUStatus status = FCDEntity::LoadFromXML(materialNode);
|
||||
if (!status) return status;
|
||||
if (!IsEquivalent(materialNode->name, DAE_MATERIAL_ELEMENT))
|
||||
{
|
||||
return status.Warning(FS("Unknown element in material library."), materialNode->line);
|
||||
}
|
||||
|
||||
// Read in the effect pointer node
|
||||
xmlNode* effectNode = FindChildByType(materialNode, DAE_INSTANCE_EFFECT_ELEMENT);
|
||||
if (effectNode != NULL)
|
||||
{
|
||||
FUUri url = ReadNodeUrl(effectNode);
|
||||
if (!url.prefix.empty())
|
||||
{
|
||||
return status.Warning(FS("Externally referenced effects are not supported. Material: ") + TO_FSTRING(GetDaeId()), effectNode->line);
|
||||
}
|
||||
else if (url.suffix.empty())
|
||||
{
|
||||
return status.Warning(FS("Empty material's <instance_effect> definition. Should instantiate an effect from the effect's library. Material: ") + TO_FSTRING(GetDaeId()), effectNode->line);
|
||||
}
|
||||
effect = GetDocument()->FindEffect(url.suffix);
|
||||
|
||||
// Read in the parameter modifications
|
||||
for (xmlNode* child = effectNode->children; child != NULL; child = child->next)
|
||||
{
|
||||
if (child->type != XML_ELEMENT_NODE) continue;
|
||||
|
||||
if (IsEquivalent(child->name, DAE_FXCMN_SETPARAM_ELEMENT))
|
||||
{
|
||||
AddParameter(FCDEffectParameterFactory::LoadFromXML(GetDocument(), child, &status));
|
||||
}
|
||||
else if (IsEquivalent(child->name, DAE_FXCMN_HINT_ELEMENT))
|
||||
{
|
||||
FCDMaterialTechniqueHint& hint = *(techniqueHints.insert(techniqueHints.end(), FCDMaterialTechniqueHint()));
|
||||
hint.platform = TO_FSTRING(ReadNodeProperty(child, DAE_PLATFORM_ATTRIBUTE));
|
||||
hint.technique = ReadNodeProperty(child, DAE_REF_ATTRIBUTE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// COLLADA 1.3 backward compatibility: look for the effect.
|
||||
if(effect != NULL)
|
||||
{
|
||||
//kind of a hack: swap the ids between the material and the effect and append
|
||||
//some weird extension to the effect id so that it doesn't conflict with anybody else.
|
||||
effect->RemoveDaeId();
|
||||
status = FCDEntity::LoadFromXML(materialNode);
|
||||
if (!status) return status;
|
||||
effect->SetDaeId(GetDaeId() + "_effect1.3");
|
||||
}
|
||||
}
|
||||
|
||||
if (effect == NULL)
|
||||
{
|
||||
return status.Warning(FS("Unable to find effect for material: ") + TO_FSTRING(GetDaeId()), materialNode->line);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out the <material> element to the COLLADA xml tree
|
||||
xmlNode* FCDMaterial::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
xmlNode* materialNode = WriteToEntityXML(parentNode, DAE_MATERIAL_ELEMENT);
|
||||
|
||||
// The <instance_effect> element is required in COLLADA 1.4
|
||||
xmlNode* instanceEffectNode = AddChild(materialNode, DAE_INSTANCE_EFFECT_ELEMENT);
|
||||
if (effect != NULL)
|
||||
{
|
||||
AddAttribute(instanceEffectNode, DAE_URL_ATTRIBUTE, string("#") + effect->GetDaeId());
|
||||
|
||||
// Write out the technique hints
|
||||
for (FCDMaterialTechniqueHintList::const_iterator itH = techniqueHints.begin(); itH != techniqueHints.end(); ++itH)
|
||||
{
|
||||
xmlNode* hintNode = AddChild(instanceEffectNode, DAE_FXCMN_HINT_ELEMENT);
|
||||
AddAttribute(hintNode, DAE_PLATFORM_ATTRIBUTE, (*itH).platform);
|
||||
AddAttribute(hintNode, DAE_REF_ATTRIBUTE, (*itH).technique);
|
||||
}
|
||||
|
||||
// Write out the parameters
|
||||
for (FCDEffectParameterList::const_iterator itP = parameters->begin(); itP != parameters->end(); ++itP)
|
||||
{
|
||||
(*itP)->WriteToXML(instanceEffectNode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddAttribute(instanceEffectNode, DAE_URL_ATTRIBUTE, string("#"));
|
||||
}
|
||||
|
||||
FCDEntity::WriteToExtraXML(materialNode);
|
||||
return materialNode;
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
@file FCDMaterial.h
|
||||
This file contains the FCDMaterail class and the FCDMaterialTechniqueHint structure.
|
||||
*/
|
||||
|
||||
#ifndef _FCD_MATERIAL_H_
|
||||
#define _FCD_MATERIAL_H_
|
||||
|
||||
#include "FCDocument/FCDEntity.h"
|
||||
|
||||
class FCDocument;
|
||||
class FCDEffect;
|
||||
class FCDEffectParameter;
|
||||
class FCDEffectParameterList;
|
||||
|
||||
/**
|
||||
A technique usage hint for a material.
|
||||
This structure contains two strings to help applications
|
||||
choose a technique within the material's instantiated effect
|
||||
according to their application platform.
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDMaterialTechniqueHint
|
||||
{
|
||||
public:
|
||||
fstring platform; /**< A platform semantic. COLLADA defines no platform semantics. */
|
||||
string technique; /**< The sid for the technique to choose for the platform. */
|
||||
};
|
||||
|
||||
/** A dynamically-sized list of material platform-technique hints. */
|
||||
typedef vector<FCDMaterialTechniqueHint> FCDMaterialTechniqueHintList;
|
||||
|
||||
/**
|
||||
A COLLADA material.
|
||||
|
||||
A COLLADA material is one of many abstraction level that defines how
|
||||
to render mesh polygon sets. It instantiates an effect and may
|
||||
overrides some of the effect parameters with its own values.
|
||||
|
||||
Unless you care about the construction history or memory, you should probably
|
||||
use the FCDMaterialInstance::FlattenMaterial function.
|
||||
|
||||
@ingroup FCDocument
|
||||
*/
|
||||
class FCOLLADA_EXPORT FCDMaterial : public FCDEntity
|
||||
{
|
||||
private:
|
||||
bool ownsEffect;
|
||||
FCDEffect* effect;
|
||||
FCDEffectParameterList* parameters;
|
||||
FCDMaterialTechniqueHintList techniqueHints;
|
||||
|
||||
public:
|
||||
/** Constructor: do not use directly.
|
||||
Instead, use the FCDMaterialLibrary::AddMaterial function.
|
||||
@param document The COLLADA document that owns the material. */
|
||||
FCDMaterial(FCDocument* document);
|
||||
|
||||
/** Destructor: do not use directly.
|
||||
The material library will release all the materials when it is
|
||||
released. If you want to remove a material from the material library:
|
||||
use the FCDMaterialLibrary::RemoveMaterial function. */
|
||||
virtual ~FCDMaterial();
|
||||
|
||||
/** Retrieves the entity type for this class. This function is part
|
||||
of the FCDEntity class interface.
|
||||
@return The entity type: MATERIAL. */
|
||||
virtual Type GetType() const { return FCDEntity::MATERIAL; }
|
||||
|
||||
/** Retrieves the effect instantiated for this material.
|
||||
The parameters of the effect may be overwritten by this material.
|
||||
You should either flatten the material using the FlattenMaterial function
|
||||
or verify the parameter values manually using the parameter list accessors.
|
||||
@return The instantiated effect. This pointer will be NULL if the material has no rendering. */
|
||||
FCDEffect* GetEffect() { return effect; }
|
||||
const FCDEffect* GetEffect() const { return effect; } /**< See above. */
|
||||
|
||||
/** Sets the effect instantiated for this material.
|
||||
@param _effect The effect instantiated for this material. */
|
||||
void SetEffect(FCDEffect* _effect) { effect = _effect; }
|
||||
|
||||
/** Retrieves the list of the material platform-technique hints.
|
||||
@return The list of material platform-technique hints. */
|
||||
FCDMaterialTechniqueHintList& GetTechniqueHints() { return techniqueHints; }
|
||||
const FCDMaterialTechniqueHintList& GetTechniqueHints() const { return techniqueHints; } /**< See above. */
|
||||
|
||||
/** Retrieves the list of effect parameter overrides.
|
||||
@return The list of effect parameter overrides. */
|
||||
FCDEffectParameterList* GetParameters() { return parameters; }
|
||||
const FCDEffectParameterList* GetParameters() const { return parameters; } /**< See above. */
|
||||
|
||||
/** Retrieves an effect parameter override. Looks for the effect parameter override with the correct
|
||||
semantic, in order to bind or set its value. This function searches through the material and the
|
||||
level of abstractions below.
|
||||
@param semantic The effect parameter semantic to match.
|
||||
@return The effect parameter override that matches the semantic.
|
||||
This pointer will be NULL if no effect parameter override matches
|
||||
the given semantic. */
|
||||
FCDEffectParameter* FindParameterBySemantic(const string& semantic);
|
||||
|
||||
/** Retrieves a subset of the effect parameter override list.
|
||||
Look for the effect parameter overrides with the correct semantic.
|
||||
This function searches through the material and the level of abstractions below.
|
||||
@param semantic The effect parameter semantic to match.
|
||||
@param parameters The list of parameters to fill in. This list is not cleared. */
|
||||
void FindParametersBySemantic(const string& semantic, FCDEffectParameterList& parameters);
|
||||
|
||||
/** Retrieves a subset of the effect parameter override list.
|
||||
Look for the effect parameter overrides with the correct reference.
|
||||
This function searches through the material and the level of abstractions below.
|
||||
@param reference The effect parameter reference to match. In the case of effect
|
||||
parameter generators, the reference is replaced by the sub-id.
|
||||
@param parameters The list of parameters to fill in. This list is not cleared. */
|
||||
void FindParametersByReference(const string& reference, FCDEffectParameterList& parameters);
|
||||
|
||||
/** [INTERNAL] Clones the material object. Everything is cloned, including the effect parameter.
|
||||
You will need release the cloned material directly, by deleting the pointer.
|
||||
@return The cloned material object. You will must delete this pointer. */
|
||||
FCDMaterial* Clone();
|
||||
|
||||
/** [INTERNAL] Flattens the material, pushing all the effect parameter overrides
|
||||
into the effect parameter generators and moving all the parameters to the
|
||||
effect technique level of abstraction. To flatten the material, use the
|
||||
FCDMaterialInstance::FlattenMaterial function. */
|
||||
void Flatten();
|
||||
|
||||
/** [INTERNAL] Reads in the \<material\> element from a given COLLADA XML tree node.
|
||||
@param materialNode The COLLADA XML tree node.
|
||||
@return The status of the import. If the status is not successful,
|
||||
it may be dangerous to extract information from the material.*/
|
||||
virtual FUStatus LoadFromXML(xmlNode* materialNode);
|
||||
|
||||
/** [INTERNAL] Writes out the \<material\> element to the given COLLADA XML tree node.
|
||||
@param parentNode The COLLADA XML parent node in which to insert the material declaration.
|
||||
@return The created element XML tree node. */
|
||||
virtual xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
|
||||
private:
|
||||
void AddParameter(FCDEffectParameter* parameter);
|
||||
};
|
||||
|
||||
#endif // _FCD_MATERIAL_H_
|
||||
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDEffectParameter.h"
|
||||
#include "FCDocument/FCDEffectParameterFactory.h"
|
||||
#include "FCDocument/FCDEffectParameterList.h"
|
||||
#include "FCDocument/FCDGeometry.h"
|
||||
#include "FCDocument/FCDController.h"
|
||||
#include "FCDocument/FCDGeometryInstance.h"
|
||||
#include "FCDocument/FCDGeometryMesh.h"
|
||||
#include "FCDocument/FCDGeometryPolygons.h"
|
||||
#include "FCDocument/FCDMaterial.h"
|
||||
#include "FCDocument/FCDMaterialInstance.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDMaterialInstance::FCDMaterialInstance(FCDocument* document, FCDGeometryInstance* _parent) : FCDEntityInstance(document, NULL)
|
||||
{
|
||||
material = NULL;
|
||||
parent = _parent;
|
||||
}
|
||||
|
||||
FCDMaterialInstance::~FCDMaterialInstance()
|
||||
{
|
||||
bindings.clear();
|
||||
parent = NULL;
|
||||
material = NULL;
|
||||
}
|
||||
|
||||
// Create a flattened version of the instantiated material: this is the
|
||||
// prefered way to generate DCC/viewer materials from a COLLADA document
|
||||
FCDMaterial* FCDMaterialInstance::FlattenMaterial()
|
||||
{
|
||||
FCDGeometry* geometry = NULL;
|
||||
|
||||
// Retrieve the necessary geometry and material information
|
||||
if(parent->GetEntity()->GetType() == FCDEntity::CONTROLLER)
|
||||
{
|
||||
FCDController* controller = (FCDController*) parent->GetEntity();
|
||||
FCDEntity* baseTarget = controller->GetBaseTarget();
|
||||
if(baseTarget->GetType() == FCDEntity::GEOMETRY)
|
||||
geometry = (FCDGeometry*) baseTarget;
|
||||
}
|
||||
else if(parent->GetEntity()->GetType() == FCDEntity::GEOMETRY)
|
||||
{
|
||||
geometry = (FCDGeometry*) parent->GetEntity();
|
||||
}
|
||||
|
||||
if (material == NULL || geometry == NULL || !geometry->IsMesh()) return NULL;
|
||||
|
||||
// Retrieve the correct polygons for this material semantic
|
||||
FCDGeometryMesh* mesh = geometry->GetMesh();
|
||||
size_t polygonsCount = mesh->GetPolygonsCount();
|
||||
FCDGeometryPolygons* polygons = NULL;
|
||||
for (size_t i = 0; i < polygonsCount; ++i)
|
||||
{
|
||||
FCDGeometryPolygons* p = mesh->GetPolygons(i);
|
||||
if (semantic == p->GetMaterialSemantic()) { polygons = p; break; }
|
||||
}
|
||||
if (polygons == NULL) return NULL;
|
||||
|
||||
FCDMaterial* clone = material->Clone();
|
||||
clone->Flatten();
|
||||
|
||||
// Flatten: Apply the bindings to the cloned material
|
||||
for (FCDMaterialInstanceBindList::iterator itB = bindings.begin(); itB != bindings.end(); ++itB)
|
||||
{
|
||||
FCDEffectParameterList parameters;
|
||||
clone->FindParametersBySemantic((*itB).semantic, parameters);
|
||||
for (FCDEffectParameterList::iterator itP = parameters.begin(); itP != parameters.end(); ++itP)
|
||||
{
|
||||
FCDEffectParameter* param = (*itP);
|
||||
if (param->GetType() == FCDEffectParameter::INTEGER)
|
||||
{
|
||||
FCDEffectParameterInt* intParam = (FCDEffectParameterInt*) param;
|
||||
|
||||
// Fairly hacky: only supported bind type right now is the texture-texture coordinate sets, which are never animated
|
||||
|
||||
// Resolve the target as a geometry source
|
||||
FCDGeometryPolygonsInput* input = polygons->FindInput((*itB).target);
|
||||
if (input != NULL) intParam->SetValue(input->set);
|
||||
}
|
||||
}
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Read in the <instance_material> element from the COLLADA document
|
||||
FUStatus FCDMaterialInstance::LoadFromXML(xmlNode* instanceNode)
|
||||
{
|
||||
FUStatus status = FCDEntityInstance::LoadFromXML(instanceNode);
|
||||
if (!status) return status;
|
||||
bindings.clear();
|
||||
|
||||
semantic = TO_FSTRING(ReadNodeProperty(instanceNode, DAE_SYMBOL_ATTRIBUTE));
|
||||
string materialId = ReadNodeProperty(instanceNode, DAE_TARGET_ATTRIBUTE);
|
||||
entity = material = GetDocument()->FindMaterial(materialId);
|
||||
if (material == NULL)
|
||||
{
|
||||
return status.Warning(FS("Invalid material binding in geometry instantiation."), instanceNode->line);
|
||||
}
|
||||
|
||||
// Read in the ColladaFX bindings
|
||||
xmlNodeList bindNodes;
|
||||
FindChildrenByType(instanceNode, DAE_BIND_ELEMENT, bindNodes);
|
||||
for (xmlNodeList::iterator itB = bindNodes.begin(); itB != bindNodes.end(); ++itB)
|
||||
{
|
||||
FCDMaterialInstanceBind& bind = (*bindings.insert(bindings.end(), FCDMaterialInstanceBind()));
|
||||
bind.semantic = ReadNodeProperty(*itB, DAE_SEMANTIC_ATTRIBUTE);
|
||||
bind.target = ReadNodeProperty(*itB, DAE_TARGET_ATTRIBUTE);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
FUStatus FCDMaterialInstance::LoadFromId(const string& materialId)
|
||||
{
|
||||
FUStatus status;
|
||||
bindings.clear();
|
||||
|
||||
// Copy the semantic over
|
||||
semantic = TO_FSTRING(materialId);
|
||||
|
||||
// Find the material associated with this Id and clone it.
|
||||
entity = material = GetDocument()->FindMaterial(materialId);
|
||||
if (material == NULL)
|
||||
{
|
||||
return status.Warning(FS("Unknown material id or semantic: ") + TO_FSTRING(materialId));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out the instantiation information to the xml node tree
|
||||
xmlNode* FCDMaterialInstance::WriteToXML(xmlNode* parentNode) const
|
||||
{
|
||||
// Intentionally skip the parent WriteToXML class
|
||||
xmlNode* instanceNode = AddChild(parentNode, DAE_INSTANCE_MATERIAL_ELEMENT);
|
||||
const FCDMaterial* material = GetMaterial();
|
||||
if (material != NULL)
|
||||
{
|
||||
AddAttribute(instanceNode, DAE_SYMBOL_ATTRIBUTE, semantic);
|
||||
AddAttribute(instanceNode, DAE_TARGET_ATTRIBUTE, material->GetDaeId());
|
||||
}
|
||||
return instanceNode;
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#ifndef _FCD_MATERIAL_BIND_H_
|
||||
#define _FCD_MATERIAL_BIND_H_
|
||||
|
||||
#include "FCDocument/FCDEntityInstance.h"
|
||||
|
||||
class FCDocument;
|
||||
class FCDGeometryInstance;
|
||||
|
||||
class FCOLLADA_EXPORT FCDMaterialInstanceBind
|
||||
{
|
||||
public:
|
||||
string semantic;
|
||||
string target;
|
||||
};
|
||||
|
||||
typedef vector<FCDMaterialInstanceBind> FCDMaterialInstanceBindList;
|
||||
|
||||
class FCOLLADA_EXPORT FCDMaterialInstance : public FCDEntityInstance
|
||||
{
|
||||
private:
|
||||
FCDGeometryInstance* parent;
|
||||
fstring semantic;
|
||||
FCDMaterial* material;
|
||||
FCDMaterialInstanceBindList bindings;
|
||||
|
||||
public:
|
||||
FCDMaterialInstance(FCDocument* document, FCDGeometryInstance* parent);
|
||||
virtual ~FCDMaterialInstance();
|
||||
|
||||
// Accessors
|
||||
virtual Type GetType() const { return MATERIAL; }
|
||||
const fstring& GetSemantic() const { return semantic; }
|
||||
FCDMaterial* GetMaterial() { return material; }
|
||||
const FCDMaterial* GetMaterial() const { return material; }
|
||||
FCDMaterialInstanceBindList& GetBindings() { return bindings; }
|
||||
const FCDMaterialInstanceBindList& GetBindings() const { return bindings; }
|
||||
|
||||
// Create a flattened version of the instantiated material: this is the
|
||||
// prefered way to generate viewer materials from a COLLADA document
|
||||
FCDMaterial* FlattenMaterial();
|
||||
|
||||
// Read in the materal instantiation from the COLLADA document
|
||||
virtual FUStatus LoadFromXML(xmlNode* instanceNode);
|
||||
FUStatus LoadFromId(const string& materialId); // COLLADA 1.3 backward compatibility
|
||||
|
||||
// Write out the instantiation information to the xml node tree
|
||||
xmlNode* WriteToXML(xmlNode* parentNode) const;
|
||||
};
|
||||
|
||||
#endif // _FCD_MATERIAL_BIND_H_
|
||||
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Feeling Software Inc.
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
/*
|
||||
Based on the FS Import classes:
|
||||
Copyright (C) 2005-2006 Feeling Software Inc
|
||||
Copyright (C) 2005-2006 Autodesk Media Entertainment
|
||||
MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/*
|
||||
* FCDMaterialLibrary covers the material and effect libraries.
|
||||
* Covers as well the texture library for COLLADA 1.3 backward compatibility
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FCDocument/FCDocument.h"
|
||||
#include "FCDocument/FCDMaterial.h"
|
||||
#include "FCDocument/FCDMaterialLibrary.h"
|
||||
#include "FCDocument/FCDEffect.h"
|
||||
#include "FCDocument/FCDTexture.h"
|
||||
#include "FUtils/FUStringConversion.h"
|
||||
#include "FUtils/FUDaeParser.h"
|
||||
#include "FUtils/FUDaeWriter.h"
|
||||
using namespace FUDaeParser;
|
||||
using namespace FUDaeWriter;
|
||||
|
||||
FCDMaterialLibrary::FCDMaterialLibrary(FCDocument* document) : FCDLibrary<FCDEntity>(document)
|
||||
{
|
||||
}
|
||||
|
||||
FCDMaterialLibrary::~FCDMaterialLibrary()
|
||||
{
|
||||
// Textures, effects and material entities are deleted by the parent's destructor
|
||||
textures.clear();
|
||||
effects.clear();
|
||||
materials.clear();
|
||||
}
|
||||
|
||||
// Search for specific material elements
|
||||
FCDTexture* FCDMaterialLibrary::FindTexture(const string& _daeId)
|
||||
{
|
||||
const char* daeId = SkipPound(_daeId);
|
||||
for (FCDTextureList::iterator it = textures.begin(); it != textures.end(); ++it)
|
||||
{
|
||||
if ((*it)->GetDaeId() == FUDaeWriter::CleanId(daeId)) return *it;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
FCDEffect* FCDMaterialLibrary::FindEffect(const string& _daeId)
|
||||
{
|
||||
const char* daeId = SkipPound(_daeId);
|
||||
for (FCDEffectList::iterator it = effects.begin(); it != effects.end(); ++it)
|
||||
{
|
||||
if ((*it)->GetDaeId() == FUDaeWriter::CleanId(daeId)) return *it;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
FCDMaterial* FCDMaterialLibrary::FindMaterial(const string& _daeId)
|
||||
{
|
||||
const char* daeId = SkipPound(_daeId);
|
||||
for (FCDMaterialList::iterator it = materials.begin(); it != materials.end(); ++it)
|
||||
{
|
||||
if ((*it)->GetDaeId() == FUDaeWriter::CleanId(daeId)) return *it;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Add new entities
|
||||
FCDEffect* FCDMaterialLibrary::AddEffect()
|
||||
{
|
||||
FCDEffect* effect = new FCDEffect(GetDocument());
|
||||
effects.push_back(effect);
|
||||
entities.push_back(effect);
|
||||
return effect;
|
||||
}
|
||||
|
||||
FCDMaterial* FCDMaterialLibrary::AddMaterial()
|
||||
{
|
||||
FCDMaterial* material = new FCDMaterial(GetDocument());
|
||||
materials.push_back(material);
|
||||
entities.push_back(material);
|
||||
return material;
|
||||
}
|
||||
|
||||
// Releases entities
|
||||
void FCDMaterialLibrary::ReleaseEffect(FCDEffect* UNUSED(effect))
|
||||
{
|
||||
// TODO: IMPLEMENT!
|
||||
}
|
||||
|
||||
// Releases entities
|
||||
void FCDMaterialLibrary::ReleaseMaterial(FCDMaterial* UNUSED(material))
|
||||
{
|
||||
// TODO: IMPLEMENT!
|
||||
}
|
||||
|
||||
// Read in the COLLADA material/effect library nodes
|
||||
// Also read in the texture library for COLLADA 1.3 backward compatibility
|
||||
FUStatus FCDMaterialLibrary::LoadFromXML(xmlNode* node)
|
||||
{
|
||||
FUStatus status;
|
||||
|
||||
// Determine the library type
|
||||
string libraryType = ReadNodeProperty(node, DAE_TYPE_ATTRIBUTE);
|
||||
|
||||
bool loadEffect = (IsEquivalent(node->name, DAE_LIBRARY_EFFECT_ELEMENT) ||
|
||||
IsEquivalent(node->name, DAE_LIBRARY_ELEMENT) && (libraryType == DAE_EFFECT_TYPE || libraryType == DAE_MATERIAL_TYPE));
|
||||
bool loadMaterial = (IsEquivalent(node->name, DAE_LIBRARY_MATERIAL_ELEMENT) ||
|
||||
IsEquivalent(node->name, DAE_LIBRARY_ELEMENT) && libraryType == DAE_MATERIAL_TYPE);
|
||||
bool loadTexture = (IsEquivalent(node->name, DAE_LIBRARY_ELEMENT) && libraryType == DAE_TEXTURE_TYPE);
|
||||
|
||||
for (xmlNode* child = node->children; child != NULL; child = child->next)
|
||||
{
|
||||
if (child->type != XML_ELEMENT_NODE) continue;
|
||||
|
||||
FCDEffect* effect = NULL;
|
||||
|
||||
if(loadEffect)
|
||||
{
|
||||
// Parse the <effect> elements
|
||||
// COLLADA 1.3. backward compatibility: also parse the <material> elements to generate the standard effects.
|
||||
effect = AddEffect();
|
||||
status.AppendStatus(effect->LoadFromXML(child));
|
||||
}
|
||||
if(loadMaterial)
|
||||
{
|
||||
// Parse the <material> elements
|
||||
FCDMaterial* material = AddMaterial();
|
||||
if (effect != NULL) material->SetEffect(effect);
|
||||
status.AppendStatus(material->LoadFromXML(child));
|
||||
}
|
||||
if(loadTexture)
|
||||
{
|
||||
// Parse the <texture> elements
|
||||
FCDTexture* texture = new FCDTexture(GetDocument());
|
||||
status.AppendStatus(texture->LoadFromXML(child));
|
||||
textures.push_back(texture);
|
||||
entities.push_back(texture);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Write out the COLLADA material and effect library nodes
|
||||
void FCDMaterialLibrary::WriteToXML(xmlNode* libraryNode) const
|
||||
{
|
||||
// Write out the materials
|
||||
for (FCDMaterialList::const_iterator itM = materials.begin(); itM != materials.end(); ++itM)
|
||||
{
|
||||
(*itM)->WriteToXML(libraryNode);
|
||||
}
|
||||
|
||||
// Also write out the effects in their library, as a sibling of this node
|
||||
xmlNode* effectLibraryNode = AddSibling(libraryNode, DAE_LIBRARY_EFFECT_ELEMENT);
|
||||
for (FCDEffectList::const_iterator itE = effects.begin(); itE != effects.end(); ++itE)
|
||||
{
|
||||
(*itE)->WriteToXML(effectLibraryNode);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user