Files
bullet3/Extras/FCollada/FColladaTest/FCTestExportImport/FCTEIGeometry.cpp
2006-05-25 19:18:29 +00:00

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));
}
};