Spline::InterpolatedPT LoopingCubicHermiteSpline::getTangent(double x) const
{
    //use modular arithmetic to bring x into an acceptable range
    x = fmod(x, numSegments);
    if(x < 0)
        x += numSegments;

    //find the interpolation data for this t value
    InterpolationData segment = segmentData.at(getSegmentIndex(x));
    double t = (x - segment.t0) * segment.tDistanceInverse;

    return InterpolatedPT(
        computePosition(t, segment),
        computeTangent(t, segment)
        );
}
Spline::InterpolatedPTCW LoopingCubicHermiteSpline::getWiggle(double x) const
{
    //use modular arithmetic to bring x into an acceptable range
    x = fmod(x, numSegments);
    if(x < 0)
        x += numSegments;

    InterpolationData segment = segmentData.at(getSegmentIndex(x));
    double t = (x - segment.t0) * segment.tDistanceInverse;

    return InterpolatedPTCW(
                computePosition(t, segment),
                computeTangent(t, segment),
                computeCurvature(t, segment),
                computeWiggle(segment)
                );
}
示例#3
0
void generateTangents(MSubMesh * subMesh)
{
	MVector3 * vertices = subMesh->getVertices();
	MVector3 * normals = subMesh->getNormals();
	MVector2 * texCoords = subMesh->getTexCoords();

	if(! (vertices && normals && texCoords))
		return;


	bool generate = false;
	unsigned int mapChannel;

	// find normal mapChannel
	unsigned int d;
	unsigned int dSize = subMesh->getDisplaysNumber();
	for(d=0; d<dSize; d++)
	{
		MDisplay * display = subMesh->getDisplay(d);
		MMaterial * material = display->getMaterial();
		if(material)
		{
			if(material->getType() == 1) // standard
			{
				if(material->getTexturesPassNumber() > 2)
				{
					MTexturePass * texturePass = material->getTexturePass(2); // Normal map pass
					if(texturePass)
					{
						mapChannel = texturePass->getMapChannel();
						generate = true;
					}
				}
			}
			else
			{
				unsigned tSize = material->getTexturesPassNumber();
				unsigned int t;
				for(t=0; t<tSize; t++)
				{
					MTexturePass * texturePass = material->getTexturePass(t);
					if(texturePass)
					{
						if(texturePass->getCombineMode() == M_TEX_COMBINE_DOT)
						{
							mapChannel = texturePass->getMapChannel();
							generate = true;
						}
					}
				}
			}
		}
	}

	// generate
	if(generate)
	{
		M_TYPES indicesType = subMesh->getIndicesType();
		void * indices = subMesh->getIndices();
		MVector3 * tangents = subMesh->allocTangents(subMesh->getNormalsSize());

		// texCoord offset
		unsigned int offset = 0;
		if(subMesh->isMapChannelExist(mapChannel))
			offset = subMesh->getMapChannelOffset(mapChannel);

		texCoords = texCoords + offset;

		// scan triangles to generate tangents from vertices and texCoords
		for(d=0; d<dSize; d++)
		{
			MDisplay * display = subMesh->getDisplay(d);

			if(display->getPrimitiveType() == M_PRIMITIVE_TRIANGLES)
			{
				unsigned int begin = display->getBegin();
				unsigned int size = display->getSize();

				if(! indices)
				{
					for(unsigned int i=begin; i<(begin+size); i+=3)
					{
						MVector3 * P1 = &vertices[i];
						MVector3 * P2 = &vertices[i+1];
						MVector3 * P3 = &vertices[i+2];

						MVector3 * N1 = &normals[i];
						MVector3 * N2 = &normals[i+1];
						MVector3 * N3 = &normals[i+2];

						MVector2 * UV1 = &texCoords[i];
						MVector2 * UV2 = &texCoords[i+1];
						MVector2 * UV3 = &texCoords[i+2];

						MVector3 tangent = computeTangent(*P1, *P2, *P3, *UV1, *UV2, *UV3);

						tangents[i]   = (tangent - ((*N1) * tangent.dotProduct(*N1))).getNormalized();
						tangents[i+1] = (tangent - ((*N2) * tangent.dotProduct(*N2))).getNormalized();
						tangents[i+2] = (tangent - ((*N3) * tangent.dotProduct(*N3))).getNormalized();
					}
				}
				else if(indicesType == M_USHORT)
				{
					unsigned short * _indices = (unsigned short *)indices;
					for(unsigned int i=begin; i<(begin+size); i+=3)
					{
						unsigned short A = _indices[i];
						unsigned short B = _indices[i+1];
						unsigned short C = _indices[i+2];

						MVector3 * P1 = &vertices[A];
						MVector3 * P2 = &vertices[B];
						MVector3 * P3 = &vertices[C];

						MVector3 * N1 = &normals[A];
						MVector3 * N2 = &normals[B];
						MVector3 * N3 = &normals[C];

						MVector2 * UV1 = &texCoords[A];
						MVector2 * UV2 = &texCoords[B];
						MVector2 * UV3 = &texCoords[C];

						MVector3 tangent = computeTangent(*P1, *P2, *P3, *UV1, *UV2, *UV3);

						tangents[A] = (tangent - ((*N1) * tangent.dotProduct(*N1))).getNormalized();
						tangents[B] = (tangent - ((*N2) * tangent.dotProduct(*N2))).getNormalized();
						tangents[C] = (tangent - ((*N3) * tangent.dotProduct(*N3))).getNormalized();
					}
				}
				else if(indicesType == M_UINT)
				{
					unsigned int * _indices = (unsigned int *)indices;
					for(unsigned int i=begin; i<(begin+size); i+=3)
					{
						unsigned int A = _indices[i];
						unsigned int B = _indices[i+1];
						unsigned int C = _indices[i+2];

						MVector3 * P1 = &vertices[A];
						MVector3 * P2 = &vertices[B];
						MVector3 * P3 = &vertices[C];

						MVector3 * N1 = &normals[A];
						MVector3 * N2 = &normals[B];
						MVector3 * N3 = &normals[C];

						MVector2 * UV1 = &texCoords[A];
						MVector2 * UV2 = &texCoords[B];
						MVector2 * UV3 = &texCoords[C];

						MVector3 tangent = computeTangent(*P1, *P2, *P3, *UV1, *UV2, *UV3);

						tangents[A] = (tangent - ((*N1) * tangent.dotProduct(*N1))).getNormalized();
						tangents[B] = (tangent - ((*N2) * tangent.dotProduct(*N2))).getNormalized();
						tangents[C] = (tangent - ((*N3) * tangent.dotProduct(*N3))).getNormalized();
					}
				}
			}
		}
	}
}