Esempio n. 1
0
	bool CheckGeometryMesh(FULogFile& fileOut, 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->GetType())
			{
			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: Fail; break;
			}
		}
		FailIf(posSource == NULL || colorSource == NULL || dummySource == NULL);
		PassIf(IsEquivalent(posSource->GetData(), posSource->GetDataCount(), positionData, 12));
		PassIf(posSource->GetStride() == 3);
		PassIf(IsEquivalent(colorSource->GetData(), colorSource->GetDataCount(), colorData, 12));
		PassIf(colorSource->GetStride() == 4);
		PassIf(IsEquivalent(dummySource->GetData(), dummySource->GetDataCount(), dummyData, 10));
		PassIf(dummySource->GetStride() == 3);
		PassIf(CheckExtraTree(fileOut, dummySource->GetExtra(), false));

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

			CheckExtraTree(fileOut, p->GetExtra(), true);
		}
		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);
		FCDGeometryPolygonsInput* posInput = polys1->FindInput(posSource);
		FailIf(posInput == NULL || posInput->GetIndexCount() != 12);
		FCDGeometryPolygonsInput* colorInput = polys1->FindInput(colorSource);
		FailIf(colorInput == NULL || colorInput == posInput || colorInput->GetIndexCount() != 12);
		PassIf(IsEquivalent(posInput->GetIndices(), 12, positionIndices, 12));
		PassIf(IsEquivalent(colorInput->GetIndices(), 12, colorIndices, 12));
		return true;
	}
Esempio n. 2
0
void ReindexGeometry(FCDGeometryPolygons* polys, FCDSkinController* skin)
{
	// Given geometry with:
	//   positions, normals, texcoords, bone blends
	// each with their own data array and index array, change it to
	// have a single optimised index array shared by all vertexes.

	FCDGeometryPolygonsInput* inputPosition = polys->FindInput(FUDaeGeometryInput::POSITION);
	FCDGeometryPolygonsInput* inputNormal   = polys->FindInput(FUDaeGeometryInput::NORMAL);
	FCDGeometryPolygonsInput* inputTexcoord = polys->FindInput(FUDaeGeometryInput::TEXCOORD);

	size_t numVertices = polys->GetFaceVertexCount();

	assert(inputPosition->GetIndexCount() == numVertices);
	assert(inputNormal  ->GetIndexCount() == numVertices);
	assert(inputTexcoord->GetIndexCount() == numVertices);

	const uint32* indicesPosition = inputPosition->GetIndices();
	const uint32* indicesNormal   = inputNormal->GetIndices();
	const uint32* indicesTexcoord = inputTexcoord->GetIndices();

	assert(indicesPosition);
	assert(indicesNormal);
	assert(indicesTexcoord); // TODO - should be optional, because textureless meshes aren't unreasonable

	FCDGeometrySourceList texcoordSources;
	polys->GetParent()->FindSourcesByType(FUDaeGeometryInput::TEXCOORD, texcoordSources);

	FCDGeometrySource* sourcePosition = inputPosition->GetSource();
	FCDGeometrySource* sourceNormal   = inputNormal  ->GetSource();

	const float* dataPosition = sourcePosition->GetData();
	const float* dataNormal   = sourceNormal  ->GetData();

	if (skin)
	{
#ifndef NDEBUG
		size_t numVertexPositions = sourcePosition->GetDataCount() / sourcePosition->GetStride();
		assert(skin->GetInfluenceCount() == numVertexPositions);
#endif
	}

	uint32 stridePosition = sourcePosition->GetStride();
	uint32 strideNormal   = sourceNormal  ->GetStride();

	std::vector<uint32> indicesCombined;
	std::vector<VertexData> vertexes;
	InserterWithoutDuplicates<VertexData> inserter(vertexes);

	for (size_t i = 0; i < numVertices; ++i)
	{
		std::vector<FCDJointWeightPair> weights;
		if (skin)
		{
			FCDSkinControllerVertex* influences = skin->GetVertexInfluence(indicesPosition[i]);
			assert(influences != NULL);
			for (size_t j = 0; j < influences->GetPairCount(); ++j)
			{
				FCDJointWeightPair* pair = influences->GetPair(j);
				assert(pair != NULL);
				weights.push_back(*pair);
			}
			CanonicaliseWeights(weights);
		}

		std::vector<uv_pair_type> uvs;
		for (size_t set = 0; set < texcoordSources.size(); ++set)
		{
			const float* dataTexcoord = texcoordSources[set]->GetData();
			uint32 strideTexcoord = texcoordSources[set]->GetStride();

			uv_pair_type p;
			p.first = dataTexcoord[indicesTexcoord[i]*strideTexcoord];
			p.second = dataTexcoord[indicesTexcoord[i]*strideTexcoord + 1];
			uvs.push_back(p);
		}

		VertexData vtx (
			&dataPosition[indicesPosition[i]*stridePosition],
			&dataNormal  [indicesNormal  [i]*strideNormal],
			uvs,
			weights
		);
		size_t idx = inserter.add(vtx);
		indicesCombined.push_back((uint32)idx);
	}

	// TODO: rearrange indicesCombined (and rearrange vertexes to match) to use
	// the vertex cache efficiently
	// (<http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html> etc)

	FloatList newDataPosition;
	FloatList newDataNormal;
	FloatList newDataTexcoord;
	std::vector<std::vector<FCDJointWeightPair> > newWeightedMatches;

	for (size_t i = 0; i < vertexes.size(); ++i)
	{
		newDataPosition.push_back(vertexes[i].x);
		newDataPosition.push_back(vertexes[i].y);
		newDataPosition.push_back(vertexes[i].z);
		newDataNormal  .push_back(vertexes[i].nx);
		newDataNormal  .push_back(vertexes[i].ny);
		newDataNormal  .push_back(vertexes[i].nz);
		newWeightedMatches.push_back(vertexes[i].weights);
	}

	// (Slightly wasteful to duplicate this array so many times, but FCollada
	// doesn't seem to support multiple inputs with the same source data)
	inputPosition->SetIndices(&indicesCombined.front(), indicesCombined.size());
	inputNormal  ->SetIndices(&indicesCombined.front(), indicesCombined.size());
	inputTexcoord->SetIndices(&indicesCombined.front(), indicesCombined.size());

	for (size_t set = 0; set < texcoordSources.size(); ++set)
	{
		newDataTexcoord.clear();
		for (size_t i = 0; i < vertexes.size(); ++i)
		{
			newDataTexcoord.push_back(vertexes[i].uvs[set].first);
			newDataTexcoord.push_back(vertexes[i].uvs[set].second);
		}
		texcoordSources[set]->SetData(newDataTexcoord, 2);
	}

	sourcePosition->SetData(newDataPosition, 3);
	sourceNormal  ->SetData(newDataNormal,   3);

	if (skin)
	{
		skin->SetInfluenceCount(newWeightedMatches.size());
		for (size_t i = 0; i < newWeightedMatches.size(); ++i)
		{
			skin->GetVertexInfluence(i)->SetPairCount(0);
			for (size_t j = 0; j < newWeightedMatches[i].size(); ++j)
				skin->GetVertexInfluence(i)->AddPair(newWeightedMatches[i][j].jointIndex, newWeightedMatches[i][j].weight);
		}
	}
}
Esempio n. 3
0
xmlNode* FArchiveXML::WriteGeometrySource(FCDObject* object, xmlNode* parentNode)
{
    FCDGeometrySource* geometrySource = (FCDGeometrySource*)object;

    xmlNode* sourceNode = NULL;

    // Export the source directly, using the correct parameters and the length factor
    FloatList& sourceData = geometrySource->GetSourceData().GetDataList();
    uint32 stride = geometrySource->GetStride();
    switch (geometrySource->GetType())
    {
    case FUDaeGeometryInput::POSITION:
        sourceNode = AddSourceFloat(parentNode, geometrySource->GetDaeId(), sourceData, stride, FUDaeAccessor::XYZW);
        break;
    case FUDaeGeometryInput::NORMAL:
        sourceNode = AddSourceFloat(parentNode, geometrySource->GetDaeId(), sourceData, stride, FUDaeAccessor::XYZW);
        break;
    case FUDaeGeometryInput::GEOTANGENT:
        sourceNode = AddSourceFloat(parentNode, geometrySource->GetDaeId(), sourceData, stride, FUDaeAccessor::XYZW);
        break;
    case FUDaeGeometryInput::GEOBINORMAL:
        sourceNode = AddSourceFloat(parentNode, geometrySource->GetDaeId(), sourceData, stride, FUDaeAccessor::XYZW);
        break;
    case FUDaeGeometryInput::TEXCOORD:
        sourceNode = AddSourceFloat(parentNode, geometrySource->GetDaeId(), sourceData, stride, FUDaeAccessor::STPQ);
        break;
    case FUDaeGeometryInput::TEXTANGENT:
        sourceNode = AddSourceFloat(parentNode, geometrySource->GetDaeId(), sourceData, stride, FUDaeAccessor::XYZW);
        break;
    case FUDaeGeometryInput::TEXBINORMAL:
        sourceNode = AddSourceFloat(parentNode, geometrySource->GetDaeId(), sourceData, stride, FUDaeAccessor::XYZW);
        break;
    case FUDaeGeometryInput::UV:
        sourceNode = AddSourceFloat(parentNode, geometrySource->GetDaeId(), sourceData, stride, FUDaeAccessor::XYZW);
        break;
    case FUDaeGeometryInput::COLOR:
        sourceNode = AddSourceFloat(parentNode, geometrySource->GetDaeId(), sourceData, stride, FUDaeAccessor::RGBA);
        break;
    case FUDaeGeometryInput::EXTRA:
        sourceNode = AddSourceFloat(parentNode, geometrySource->GetDaeId(), sourceData, stride, NULL);
        break;
    case FUDaeGeometryInput::UNKNOWN:
        sourceNode = AddSourceFloat(parentNode, geometrySource->GetDaeId(), sourceData, stride, NULL);
        break;

    case FUDaeGeometryInput::VERTEX: // Refuse to export these sources
    default:
        break;
    }

    if (!geometrySource->GetName().empty())
    {
        AddAttribute(sourceNode, DAE_NAME_ATTRIBUTE, geometrySource->GetName());
    }

    if (geometrySource->GetExtra() != NULL)
    {
        FArchiveXML::WriteTechniquesFCDExtra(geometrySource->GetExtra(), sourceNode);
    }

    for (size_t i = 0; i < geometrySource->GetAnimatedValues().size(); ++i)
    {
        FArchiveXML::WriteAnimatedValue(geometrySource->GetAnimatedValues()[i], sourceNode, "");
    }

    return sourceNode;
}