370 lines
15 KiB
C++
370 lines
15 KiB
C++
/*
|
|
Copyright (C) 2006 Feeling Software Inc.
|
|
Available only to licensees.
|
|
Distribution of this file or its content is strictly prohibited.
|
|
*/
|
|
|
|
#include "StdAfx.h"
|
|
#include "FCDocument/FCDController.h"
|
|
#include "FCDocument/FCDGeometry.h"
|
|
#include "FCDocument/FCDGeometryMesh.h"
|
|
#include "FCDocument/FCDGeometryPolygons.h"
|
|
#include "FCDocument/FCDGeometrySource.h"
|
|
#include "FCDocument/FCDGeometrySpline.h"
|
|
#include "FCDocument/FCDMorphController.h"
|
|
#include "FCDocument/FCDSceneNode.h"
|
|
#include "FCDocument/FCDSkinController.h"
|
|
#include "FCTestExportImport.h"
|
|
|
|
static const float positionData[12] = { 0.0f, 0.0f, 3.0f, 5.0f, 0.0f, -2.0f, -3.0f, 4.0f, -2.0f, -3.0f, -4.0f, -2.0f };
|
|
static const float colorData[12] = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f };
|
|
static const float dummyData[10] = { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f };
|
|
static const uint32 positionIndices[12] = { 0, 1, 2, 0, 2, 3, 0, 3, 1, 3, 2, 1 };
|
|
static const uint32 colorIndices[12] = { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2 };
|
|
|
|
static const float sampleBindPose1[16] = { 1.0f, 0.4f, 0.4f, 0.0f, 7.77f, 0.0f, 0.3f, 2.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f };
|
|
static const float sampleBindPose2[16] = { 0.3f, 0.0f, -0.3f, -21.0f, 0.96f, 0.0f, 2.0f, 2.5f, 0.0f, -5.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f };
|
|
static string splineId, meshId, jointId1, jointId2;
|
|
|
|
namespace FCTestExportImport
|
|
{
|
|
void FillGeometryLibrary(FCDGeometryLibrary* library)
|
|
{
|
|
FCDGeometry* geometry = library->AddEntity();
|
|
PassIf(geometry->GetType() == FCDEntity::GEOMETRY);
|
|
FailIf(geometry->IsMesh());
|
|
FailIf(geometry->IsSpline());
|
|
meshId = geometry->GetDaeId();
|
|
FailIf(meshId.empty());
|
|
|
|
// Creates a mesh to export
|
|
FCDGeometryMesh* mesh = geometry->CreateMesh();
|
|
FailIf(geometry->IsSpline());
|
|
PassIf(geometry->IsMesh());
|
|
PassIf(geometry->GetMesh() == mesh);
|
|
PassIf(geometry->GetSpline() == NULL);
|
|
FillGeometryMesh(mesh);
|
|
|
|
// Create a spline to export
|
|
geometry = library->AddEntity();
|
|
geometry->CreateMesh();
|
|
FCDGeometrySpline* spline = geometry->CreateSpline();
|
|
PassIf(geometry->IsSpline());
|
|
FailIf(geometry->IsMesh());
|
|
PassIf(geometry->GetMesh() == NULL);
|
|
PassIf(geometry->GetSpline() == spline);
|
|
FillGeometrySpline(spline);
|
|
splineId = geometry->GetDaeId();
|
|
FailIf(splineId.empty());
|
|
}
|
|
|
|
void FillGeometryMesh(FCDGeometryMesh* mesh)
|
|
{
|
|
FCDGeometrySource* posSource = mesh->AddVertexSource();
|
|
FailIf(posSource == NULL);
|
|
posSource->SetName(FC("TestPositionSource"));
|
|
posSource->SetSourceType(FUDaeGeometryInput::POSITION);
|
|
posSource->SetSourceData(FloatList(positionData, 12), 3);
|
|
|
|
FCDGeometrySource* colorSource = mesh->AddSource();
|
|
FailIf(colorSource == NULL);
|
|
colorSource->SetName(FC("TestColorSource"));
|
|
colorSource->SetSourceType(FUDaeGeometryInput::COLOR);
|
|
colorSource->SetSourceData(FloatList(colorData, 12), 4);
|
|
|
|
FCDGeometrySource* dummySource = mesh->AddSource();
|
|
FailIf(dummySource == NULL);
|
|
dummySource->SetName(FC("TestDummySource"));
|
|
dummySource->SetSourceType(FUDaeGeometryInput::EXTRA);
|
|
dummySource->SetSourceData(FloatList(dummyData, 10), 3);
|
|
|
|
FCDGeometryPolygons* polys1 = mesh->AddPolygons();
|
|
FailIf(polys1 == NULL || polys1->GetInputCount() != 1);
|
|
FCDGeometryPolygons* polys2 = mesh->AddPolygons();
|
|
FailIf(polys2 == NULL || polys2->GetInputCount() != 1);
|
|
FCDGeometryPolygonsInput* pInput1 = polys1->AddInput(colorSource, 1);
|
|
PassIf(polys1->GetInputCount() == 2);
|
|
PassIf(pInput1 != NULL && pInput1->source == colorSource && pInput1->idx == 1);
|
|
FCDGeometryPolygonsInput* pInput2 = polys2->AddInput(colorSource, 1);
|
|
PassIf(polys2->GetInputCount() == 2);
|
|
PassIf(pInput2 != NULL && pInput2->source == colorSource && pInput2->idx == 1);
|
|
FCDGeometryPolygonsInput* pInput3 = polys1->AddInput(dummySource, 2);
|
|
PassIf(pInput3 != NULL && pInput3->source == dummySource && pInput3->idx == 2);
|
|
|
|
// Fill in some indices in order to form a tetrahedron
|
|
polys1->AddFace(3); polys1->AddFace(3); polys1->AddFace(3); polys1->AddFace(3);
|
|
UInt32List* posIndices = polys1->FindIndices(posSource);
|
|
UInt32List* colIndices = polys1->FindIndices(colorSource);
|
|
FailIf(posIndices == NULL || posIndices->size() != 12);
|
|
FailIf(colIndices == NULL || colIndices == posIndices || colIndices->size() != 12);
|
|
*posIndices = UInt32List(positionIndices, 12);
|
|
*colIndices = UInt32List(colorIndices, 12);
|
|
}
|
|
|
|
void FillGeometrySpline(FCDGeometrySpline* spline)
|
|
{
|
|
FCDCVs cvs;
|
|
cvs.push_back(FMVector3(1.0f, 2.0f, 4.0f));
|
|
cvs.push_back(FMVector3::XAxis);
|
|
spline->SetCVs(cvs);
|
|
PassIf(spline->GetCVCount() == 2);
|
|
|
|
FCDKnots knots;
|
|
knots.push_back(1.4);
|
|
knots.push_back(7.4);
|
|
spline->SetKnots(knots);
|
|
PassIf(spline->GetKnotCount() == 2);
|
|
}
|
|
|
|
void CheckGeometryLibrary(FCDGeometryLibrary* library)
|
|
{
|
|
PassIf(library->GetEntityCount() == 2);
|
|
|
|
// Find the one mesh and the one spline geometries.
|
|
FCDGeometryMesh* mesh = NULL; FCDGeometrySpline* spline = NULL;
|
|
for (size_t i = 0; i < 2; ++i)
|
|
{
|
|
FCDGeometry* g = library->GetEntity(i);
|
|
if (g->IsMesh()) mesh = g->GetMesh();
|
|
else if (g->IsSpline()) spline = g->GetSpline();
|
|
else FailIf(true);
|
|
}
|
|
FailIf(mesh == NULL || spline == NULL);
|
|
|
|
CheckGeometryMesh(mesh);
|
|
CheckGeometrySpline(spline);
|
|
}
|
|
|
|
void CheckGeometryMesh(FCDGeometryMesh* mesh)
|
|
{
|
|
// Verify the mesh and its sources
|
|
PassIf(mesh->GetSourceCount() == 3);
|
|
FCDGeometrySource* posSource = NULL,* colorSource = NULL,* dummySource = NULL;
|
|
for (size_t i = 0; i < 3; ++i)
|
|
{
|
|
FCDGeometrySource* source = mesh->GetSource(i);
|
|
FailIf(source == NULL);
|
|
switch (source->GetSourceType())
|
|
{
|
|
case FUDaeGeometryInput::POSITION: posSource = source; PassIf(source->GetName() == FC("TestPositionSource")); break;
|
|
case FUDaeGeometryInput::COLOR: colorSource = source; PassIf(source->GetName() == FC("TestColorSource")); break;
|
|
case FUDaeGeometryInput::EXTRA: dummySource = source; PassIf(source->GetName() == FC("TestDummySource")); break;
|
|
default: FailIf(true); break;
|
|
}
|
|
}
|
|
FailIf(posSource == NULL || colorSource == NULL || dummySource == NULL);
|
|
PassIf(IsEquivalent(posSource->GetSourceData(), positionData, 12));
|
|
PassIf(posSource->GetSourceStride() == 3);
|
|
PassIf(IsEquivalent(colorSource->GetSourceData(), colorData, 12));
|
|
PassIf(colorSource->GetSourceStride() == 4);
|
|
PassIf(IsEquivalent(dummySource->GetSourceData(), dummyData, 10));
|
|
PassIf(dummySource->GetSourceStride() == 3);
|
|
|
|
// Find the non-empty polygon set and verify that one of the polygon set is, in fact, empty.
|
|
FCDGeometryPolygons* polys1 = NULL,* polysEmpty = NULL;
|
|
for (size_t i = 0; i < mesh->GetPolygonsCount(); ++i)
|
|
{
|
|
FCDGeometryPolygons* p = mesh->GetPolygons(i);
|
|
if (p->GetFaceCount() == 0) { PassIf(polysEmpty == NULL); polysEmpty = p; }
|
|
else { PassIf(polys1 == NULL); polys1 = p; }
|
|
}
|
|
PassIf(polys1 != NULL && polysEmpty != NULL);
|
|
|
|
// Check that we have the wanted tetrahedron in the non-empty polygon set.
|
|
PassIf(polys1->GetFaceCount() == 4);
|
|
PassIf(polys1->GetHoleCount() == 0);
|
|
PassIf(polys1->GetFaceVertexCount(0) == 3 && polys1->GetFaceVertexCount(1) == 3 && polys1->GetFaceVertexCount(2) == 3 && polys1->GetFaceVertexCount(3) == 3);
|
|
UInt32List* posIndices = polys1->FindIndices(posSource);
|
|
UInt32List* colIndices = polys1->FindIndices(colorSource);
|
|
FailIf(posIndices == NULL || posIndices->size() != 12);
|
|
FailIf(colIndices == NULL || colIndices == posIndices || colIndices->size() != 12);
|
|
PassIf(IsEquivalent(*posIndices, positionIndices, 12));
|
|
PassIf(IsEquivalent(*colIndices, colorIndices, 12));
|
|
}
|
|
|
|
void CheckGeometrySpline(FCDGeometrySpline* spline)
|
|
{
|
|
// Verify the spline and its data
|
|
FailIf(spline->GetCVCount() != 2);
|
|
FailIf(spline->GetKnotCount() != 2);
|
|
PassIf(IsEquivalent(*spline->GetCV(0), FMVector3(1.0f, 2.0f, 4.0f)));
|
|
PassIf(IsEquivalent(*spline->GetCV(1), FMVector3::XAxis));
|
|
PassIf(IsEquivalent(spline->GetKnot(0), 1.4));
|
|
PassIf(IsEquivalent(spline->GetKnot(1), 7.4));
|
|
}
|
|
|
|
void FillControllerLibrary(FCDControllerLibrary* library)
|
|
{
|
|
FailIf(library == NULL);
|
|
|
|
// Create a morph controller on the previously created spline.
|
|
FCDController* morpher = library->AddEntity();
|
|
FillControllerMorph(morpher->CreateMorphController());
|
|
|
|
// Create a skin controller on the previously created mesh.
|
|
FCDController* skin = library->AddEntity();
|
|
skin->SetNote(FS("A nicey skinny controller. "));
|
|
FillControllerSkin(skin->CreateSkinController());
|
|
}
|
|
|
|
void FillControllerMorph(FCDMorphController* controller)
|
|
{
|
|
FailIf(controller == NULL);
|
|
controller->SetMethod(FUDaeMorphMethod::RELATIVE);
|
|
|
|
// Retrieve the base spline entity that will be morphed
|
|
// (and for this test only: it'll be the morph targets)
|
|
// Also retrieve the mesh, for similarity checks.
|
|
FCDGeometry* spline = controller->GetDocument()->FindGeometry(splineId);
|
|
FailIf(spline == NULL);
|
|
FCDGeometry* mesh = controller->GetDocument()->FindGeometry(meshId);
|
|
FailIf(mesh == NULL);
|
|
FailIf(controller->IsSimilar(mesh));
|
|
FailIf(controller->IsSimilar(spline));
|
|
|
|
controller->SetBaseTarget(spline);
|
|
PassIf(controller->IsSimilar(spline));
|
|
FailIf(controller->IsSimilar(mesh));
|
|
|
|
controller->AddTarget(spline, 0.3f);
|
|
controller->AddTarget(spline, 0.6f);
|
|
PassIf(controller->GetTargetCount() == 2);
|
|
}
|
|
|
|
void FillControllerSkin(FCDSkinController* controller)
|
|
{
|
|
FailIf(controller == NULL);
|
|
|
|
// Create two joints.
|
|
FCDSceneNode* visualScene = controller->GetDocument()->GetVisualSceneLibrary()->AddEntity();
|
|
PassIf(visualScene != NULL);
|
|
FCDSceneNode* joint1 = visualScene->AddChildNode();
|
|
PassIf(joint1 != NULL);
|
|
FCDSceneNode* joint2 = joint1->AddChildNode();
|
|
PassIf(joint2 != NULL);
|
|
jointId1 = joint1->GetDaeId();
|
|
jointId2 = joint2->GetDaeId();
|
|
FailIf(jointId1.empty() || jointId2.empty());
|
|
controller->AddJoint(joint1, FMMatrix44::Identity);
|
|
controller->AddJoint(joint2, FMMatrix44(sampleBindPose1));
|
|
controller->SetBindShapeTransform(FMMatrix44(sampleBindPose2));
|
|
PassIf(controller->GetJointCount() == 2);
|
|
|
|
// Retrieve and assign the base target
|
|
FCDGeometry* geometricTarget = controller->GetDocument()->FindGeometry(meshId);
|
|
controller->SetTarget(geometricTarget);
|
|
|
|
// Set some influences
|
|
PassIf(controller->GetVertexInfluenceCount() == 4);
|
|
FCDJointWeightPairList* influence = controller->GetInfluences(0);
|
|
FailIf(influence == NULL);
|
|
influence->push_back(FCDJointWeightPair(0, 0.5f));
|
|
influence->push_back(FCDJointWeightPair(1, 0.5f));
|
|
|
|
influence = controller->GetInfluences(3);
|
|
FailIf(influence == NULL);
|
|
influence->push_back(FCDJointWeightPair(1, 1.0f));
|
|
|
|
influence = controller->GetInfluences(2);
|
|
FailIf(influence == NULL);
|
|
influence->push_back(FCDJointWeightPair(0, 0.1f));
|
|
}
|
|
|
|
void CheckControllerLibrary(FCDControllerLibrary* library)
|
|
{
|
|
FailIf(library == NULL);
|
|
|
|
FCDController* morpher = NULL,* skin = NULL;
|
|
for (size_t i = 0; i < library->GetEntityCount(); ++i)
|
|
{
|
|
FCDController* c = library->GetEntity(i);
|
|
if (c->HasMorphController()) { PassIf(morpher == NULL); morpher = c; }
|
|
else if (c->HasSkinController()) { PassIf(skin == NULL); skin = c; }
|
|
else FailIf(true);
|
|
}
|
|
PassIf(morpher != NULL && skin != NULL);
|
|
|
|
// Check the morpher
|
|
FailIf(morpher->HasSkinController());
|
|
PassIf(morpher->GetMorphController() != NULL);
|
|
CheckControllerMorph(morpher->GetMorphController());
|
|
|
|
// Check the skin
|
|
PassIf(skin->GetSkinController() != NULL);
|
|
FailIf(skin->HasMorphController());
|
|
PassIf(skin->GetNote() == FC("A nicey skinny controller. "));
|
|
CheckControllerSkin(skin->GetSkinController());
|
|
}
|
|
|
|
void CheckControllerMorph(FCDMorphController* controller)
|
|
{
|
|
FailIf(controller == NULL);
|
|
PassIf(controller->GetMethod() == FUDaeMorphMethod::RELATIVE);
|
|
|
|
// Check that there are two targets, that the weights are correct, as well as the ids.
|
|
PassIf(controller->GetTargetCount() == 2);
|
|
PassIf(controller->GetBaseTarget() != NULL);
|
|
PassIf(controller->GetBaseTarget()->GetDaeId() == splineId);
|
|
|
|
FCDMorphTarget* target1 = controller->GetTarget(0);
|
|
FailIf(target1 == NULL);
|
|
FCDMorphTarget* target2 = controller->GetTarget(1);
|
|
FailIf(target2 == NULL);
|
|
PassIf(target1->GetGeometry() == controller->GetBaseTarget());
|
|
PassIf(target2->GetGeometry() == controller->GetBaseTarget());
|
|
PassIf(IsEquivalent(target1->GetWeight(), 0.6f) || IsEquivalent(target1->GetWeight(), 0.3f));
|
|
PassIf(IsEquivalent(target2->GetWeight(), 0.6f) || IsEquivalent(target2->GetWeight(), 0.3f));
|
|
FailIf(IsEquivalent(target1->GetWeight(), target2->GetWeight()));
|
|
}
|
|
|
|
void CheckControllerSkin(FCDSkinController* controller)
|
|
{
|
|
FailIf(controller == NULL);
|
|
|
|
// Check the base target's identity
|
|
FailIf(controller->GetTarget() == NULL);
|
|
PassIf(controller->GetTarget()->GetType() == FCDEntity::GEOMETRY);
|
|
PassIf(controller->GetTarget()->GetDaeId() == meshId);
|
|
|
|
// Retrieve the two joints and verify their ids/bind-pose.
|
|
PassIf(controller->GetJointCount() == 2);
|
|
FCDJointMatrixPair* joint1 = NULL,* joint2 = NULL;
|
|
for (size_t i = 0; i < 2; ++i)
|
|
{
|
|
FCDJointMatrixPair* p = controller->GetJoint(i);
|
|
FailIf(p->joint == NULL);
|
|
if (p->joint->GetDaeId() == jointId1) { FailIf(joint1 != NULL); joint1 = p; }
|
|
else if (p->joint->GetDaeId() == jointId2) { FailIf(joint2 != NULL); joint2 = p; }
|
|
else FailIf(true);
|
|
}
|
|
FailIf(joint1 == NULL || joint2 == NULL);
|
|
PassIf(IsEquivalent(joint1->invertedBindPose, FMMatrix44::Identity));
|
|
PassIf(IsEquivalent(joint2->invertedBindPose, FMMatrix44(sampleBindPose1).Inverted()));
|
|
|
|
// Verify the influences
|
|
PassIf(controller->GetVertexInfluenceCount() == 4);
|
|
FCDJointWeightPairList* influence = controller->GetInfluences(0);
|
|
FailIf(influence == NULL);
|
|
PassIf(influence->size() == 2);
|
|
PassIf(IsEquivalent(influence->at(0).jointIndex, 0));
|
|
PassIf(IsEquivalent(influence->at(0).weight, 0.5f));
|
|
PassIf(IsEquivalent(influence->at(1).jointIndex, 1));
|
|
PassIf(IsEquivalent(influence->at(1).weight, 0.5f));
|
|
|
|
influence = controller->GetInfluences(1);
|
|
FailIf(influence == NULL);
|
|
PassIf(influence->empty());
|
|
|
|
influence = controller->GetInfluences(2);
|
|
FailIf(influence == NULL);
|
|
PassIf(influence->size() == 1);
|
|
PassIf(IsEquivalent(influence->at(0).jointIndex, 0));
|
|
PassIf(IsEquivalent(influence->at(0).weight, 1.0f)); // the weight should have been normalized.
|
|
|
|
influence = controller->GetInfluences(3);
|
|
FailIf(influence == NULL);
|
|
PassIf(influence->size() == 1);
|
|
PassIf(IsEquivalent(influence->at(0).jointIndex, 1));
|
|
PassIf(IsEquivalent(influence->at(0).weight, 1.0f));
|
|
}
|
|
}; |