void USplineComponent::UpdateSpline()
{
	const int32 NumPoints = SplineInfo.Points.Num();
	check(SplineRotInfo.Points.Num() == NumPoints && SplineScaleInfo.Points.Num() == NumPoints);

	// Ensure input keys are ascending in steps of 1.0
	for (int32 Index = 0; Index < NumPoints; Index++)
	{
		const float InVal = static_cast<float>(Index);
		SplineInfo.Points[Index].InVal = InVal;
		SplineRotInfo.Points[Index].InVal = InVal;
		SplineScaleInfo.Points[Index].InVal = InVal;
	}

	// Nothing else to do if less than 2 points
	if (NumPoints < 2)
	{
		return;
	}

	// Ensure splines' looping status matches with that of the spline component
	if (bClosedLoop)
	{
		const float LoopKey = static_cast<float>(NumPoints);
		SplineInfo.SetLoopKey(LoopKey);
		SplineRotInfo.SetLoopKey(LoopKey);
		SplineScaleInfo.SetLoopKey(LoopKey);
	}
	else
	{
		SplineInfo.ClearLoopKey();
		SplineRotInfo.ClearLoopKey();
		SplineScaleInfo.ClearLoopKey();
	}

	// Automatically set the tangents on any CurveAuto keys
	SplineInfo.AutoSetTangents(0.0f, bStationaryEndpoints);
	SplineRotInfo.AutoSetTangents(0.0f, bStationaryEndpoints);
	SplineScaleInfo.AutoSetTangents(0.0f, bStationaryEndpoints);

	// Now initialize the spline reparam table
	const int32 NumSegments = bClosedLoop ? NumPoints : NumPoints - 1;

	// Start by clearing it
	SplineReparamTable.Points.Reset(NumSegments * ReparamStepsPerSegment + 1);
	float AccumulatedLength = 0.0f;
	for (int32 SegmentIndex = 0; SegmentIndex < NumSegments; ++SegmentIndex)
	{
		for (int32 Step = 0; Step < ReparamStepsPerSegment; ++Step)
		{
			const float Param = static_cast<float>(Step) / ReparamStepsPerSegment;
			const float SegmentLength = (Step == 0) ? 0.0f : GetSegmentLength(SegmentIndex, Param);

			SplineReparamTable.Points.Emplace(SegmentLength + AccumulatedLength, SegmentIndex + Param, 0.0f, 0.0f, CIM_Linear);
		}
		AccumulatedLength += GetSegmentLength(SegmentIndex, 1.0f);
	}

	SplineReparamTable.Points.Emplace(AccumulatedLength, static_cast<float>(NumSegments), 0.0f, 0.0f, CIM_Linear);
}
void USplineComponent::UpdateSpline()
{
	const int32 NumPoints = SplineInfo.Points.Num();
	check(!bClosedLoop || NumPoints == 0 || (NumPoints >= 2 && SplineInfo.Points[0].OutVal == SplineInfo.Points[NumPoints - 1].OutVal));

	// Automatically set the tangents on any CurveAuto keys
	SplineInfo.AutoSetTangents(0.0f, bStationaryEndpoints);

	// Nothing else to do if less than 2 points
	if (NumPoints < 2)
	{
		return;
	}

	// Adjust auto tangents for first and last keys to take into account the looping
	if (bClosedLoop)
	{
		auto& FirstPoint = SplineInfo.Points[0];
		auto& LastPoint = SplineInfo.Points[NumPoints - 1];
		const auto& SecondPoint = SplineInfo.Points[1];
		const auto& PenultimatePoint = SplineInfo.Points[NumPoints - 2];

		if (FirstPoint.InterpMode == CIM_CurveAuto || FirstPoint.InterpMode == CIM_CurveAutoClamped)
		{
			FVector Tangent;
			ComputeCurveTangent(
				PenultimatePoint.InVal - LastPoint.InVal, PenultimatePoint.OutVal,
				FirstPoint.InVal, FirstPoint.OutVal,
				SecondPoint.InVal, SecondPoint.OutVal,
				0.0f,
				FirstPoint.InterpMode == CIM_CurveAutoClamped,
				Tangent);

			FirstPoint.LeaveTangent = Tangent;
			FirstPoint.ArriveTangent = Tangent;
			LastPoint.LeaveTangent = Tangent;
			LastPoint.ArriveTangent = Tangent;
		}
	}

	const int32 NumSegments = NumPoints - 1;

	// Start by clearing it
	SplineReparamTable.Points.Reset(NumSegments * ReparamStepsPerSegment + 1);
	float AccumulatedLength = 0.0f;
	for (int32 SegmentIndex = 0; SegmentIndex < NumSegments; ++SegmentIndex)
	{
		for (int32 Step = 0; Step < ReparamStepsPerSegment; ++Step)
		{
			const float Param = static_cast<float>(Step) / ReparamStepsPerSegment;
			const float SegmentLength = (Step == 0) ? 0.0f : GetSegmentLength(SegmentIndex, Param);
			SplineReparamTable.AddPoint(SegmentLength + AccumulatedLength, SegmentIndex + Param);
		}
		AccumulatedLength += GetSegmentLength(SegmentIndex, 1.0f);
	}
	SplineReparamTable.AddPoint(AccumulatedLength, static_cast<float>(NumSegments));
}
Exemple #3
0
unsigned int SVGMotionPath::GetSegmentIndexAtLength(SVGNumber len)
{
	// FIXME: Return what index if input length > path length || input length < 0 ?
	// Returning last/first for now
	if (len < 0)
		return 0;

	if (m_vega_path && m_vega_line_segments > 0)
	{
		SVGNumber length_sum;
		unsigned int i = 0;
		length_sum = GetSegmentLength(i);
		while (len > length_sum && i < m_vega_line_segments)
		{
			i++;
			length_sum += GetSegmentLength(i);
		}
		if (i >= m_vega_line_segments)
			i = m_vega_line_segments-1;
		return i;
	}
	return 0;
}
Exemple #4
0
SVGNumber SVGMotionPath::GetAccumulatedSegmentLength(unsigned int idx)
{
	if (m_vega_path &&
		m_vega_line_segments > 0)
	{
		if (idx > m_vega_line_segments)
			idx = m_vega_line_segments;

		SVGNumber sum(0);
		for (unsigned int i = 0; i < idx; i++)
		{
			sum += GetSegmentLength(i);
		}
		return sum;
	}
	return 0;
}
float USplineComponent::GetSegmentParamFromLength(const int32 Index, const float Length, const float SegmentLength) const
{
	if (SegmentLength == 0.0f)
	{
		return 0.0f;
	}

	// Given a function P(x) which yields points along a spline with x = 0...1, we can define a function L(t) to be the
	// Euclidian length of the spline from P(0) to P(t):
	//
	//    L(t) = integral of |dP/dt| dt
	//         = integral of sqrt((dx/dt)^2 + (dy/dt)^2 + (dz/dt)^2) dt
	//
	// This method evaluates the inverse of this function, i.e. given a length d, it obtains a suitable value for t such that:
	//    L(t) - d = 0
	//
	// We use Newton-Raphson to iteratively converge on the result:
	//
	//    t' = t - f(t) / (df/dt)
	//
	// where: t is an initial estimate of the result, obtained through basic linear interpolation,
	//        f(t) is the function whose root we wish to find = L(t) - d,
	//        (df/dt) = d(L(t))/dt = |dP/dt|

	const int32 NumPoints = SplineInfo.Points.Num();
	const int32 LastPoint = NumPoints - 1;

	check(Index >= 0 && ((bClosedLoop && Index < NumPoints) || (!bClosedLoop && Index < LastPoint)));
	check(Length >= 0.0f && Length <= SegmentLength);
	check(Index == LastPoint || (static_cast<int32>(SplineInfo.Points[Index + 1].InVal) - static_cast<int32>(SplineInfo.Points[Index].InVal) == 1));

	float Param = Length / SegmentLength;  // initial estimate for t

	// two iterations of Newton-Raphson is enough
	for (int32 Iteration = 0; Iteration < 2; ++Iteration)
	{
		float TangentMagnitude = SplineInfo.EvalDerivative(Index + Param, FVector::ZeroVector).Size();
		if (TangentMagnitude > 0.0f)
		{
			Param -= (GetSegmentLength(Index, Param) - Length) / TangentMagnitude;
			Param = FMath::Clamp(Param, 0.0f, 1.0f);
		}
	}

	return Param;
}
Exemple #6
0
OP_STATUS
SVGMotionPath::CalculateCurrentDistanceAlongPath(PositionDescriptor& pos, SVGNumber& distance)
{
	switch(pos.calcMode)
	{
	case SVGCALCMODE_PACED:
		{
			distance = pos.where * m_path_length; // Paced calculation mode ignores keyTimes and keyPoints
			return OpStatus::OK;
		}
	case SVGCALCMODE_SPLINE:
	case SVGCALCMODE_LINEAR:
		{
			SVGNumber c;
			if (pos.keyTimes == NULL ||
				pos.keyPoints == NULL ||
				pos.keyTimes->GetCount() == 0 ||
				pos.keyPoints->GetCount() == 0)
			{
				unsigned int ic = m_path->GetCount(FALSE);        // how many subintervals
				if(ic > 1)
					ic--;

				// avoid division-by-zero
				if(ic == 0)
					return OpSVGStatus::INVALID_ANIMATION;

				SVGNumber il = SVGNumber(1) / (SVGNumber(ic)); // how long are each
				SVGNumber q;
				unsigned int a;
				if (pos.where.Equal(1)) // special-treatment
				{
					q = 1;
					a = ic - 1;
				}
				else
				{
					SVGNumber r = pos.where % il;                // how far along are we in the time subinterval
					q = r / il;                        // make that value relative (0-1)
					a = (unsigned int)(pos.where*ic).GetIntegerValue();  // which interval are we in
				}
				if (pos.calcMode == SVGCALCMODE_SPLINE)
				{
					q = CalculateKeySplines(pos, a, q);
				}
				SVGNumber p = GetSegmentLength(a);
				SVGNumber b = GetAccumulatedSegmentLength(a);
				c = b + q * p;                      // where are we in this interval
			}
			else
			{
				c = CalculateKeyTimes(pos) * m_vega_path_length;
			}
			distance = c / m_vega_path_length * m_path_length;
			return OpStatus::OK;
		}
	case SVGCALCMODE_DISCRETE:
		{
			unsigned int ic = m_path->GetCount(FALSE);           // how many subintervals
			// avoid division-by-zero
			if(ic == 0)
				return OpSVGStatus::INVALID_ANIMATION;

			unsigned int a = (unsigned int)(pos.where * ic).GetIntegerValue();
			SVGNumber b = GetAccumulatedSegmentLength(a); // how long are this interval relative to the total length

			SVGNumber c;
			if (pos.keyTimes == NULL ||
				pos.keyPoints == NULL ||
				pos.keyTimes->GetCount() == 0 ||
				pos.keyPoints->GetCount() == 0)
			{
				c = b;
			}
			else
			{
				c = CalculateKeyTimes(pos) * m_vega_path_length;
			}

			SVGNumber next_where = SVGNumber(a + 1) / SVGNumber(ic);
			if (next_where > SVGNumber(1))
				next_where = next_where - SVGNumber(1);
			pos.next_where = next_where;

			distance = c / m_vega_path_length * m_path_length;
			return OpStatus::OK;
		}
	default:
		break;
	}

	OP_ASSERT(!"Not reached");
	return OpStatus::ERR;
}
Exemple #7
0
//Made from XC3S200_FT256 bit file
//Code is based on code from http://panteltje.com/panteltje/raspberri_pi/
//And David Sullins BitInfo/BitFile code
void parse_header(FILE *f)
{
    //00 09  0F F0  0F F0  0F F0  0F F0  00 00 01
    unsigned int XilinxID13[] = {0x00,0x09, 0x0F,0xF0, 0x0F,0xF0, 0x0F,0xF0, 0x0F,0xF0, 0x00,0x00,0x01};
    unsigned int *HeaderBufferData;
    int segmentCheck = 0x61; //Start at a char(97)
    int segment = 0;
    int	segmentLength = 0;
    int offset = 0;
    unsigned char tempChar;

    //First 13 bits, so far all Xilinx Bitstream files, start with XilinxID13 bytes
    //Seems to be identifier for bitfile creator
    int t, x;
    HeaderBufferData = (unsigned int*)malloc( sizeof(unsigned int) *13);
    for(t=0; t<13; t++) HeaderBufferData[t] = fgetc(f);

    if(0==memcmp(HeaderBufferData,XilinxID13,sizeof(HeaderBufferData)*13))
        bitFileId = XILINX_BITFILE;
    else
        bitFileId = 0;
    //if(0==memcmp(HeaderBufferData,XilinxID13,sizeof(HeaderBufferData)*13)) bitFileId = Altera_BITFILE; else bitFileId = 0; //Future stuff
    free(HeaderBufferData);

    fprintf(stderr, "Bitfile type: %d\n",bitFileId);
    bitfileinfo.BitFile_Type = bitFileId;
//----------------------------------------------------------------------
    segmentLength = GetSegmentLength(segment,segmentCheck,f);
    segmentCheck++;
    fprintf(stderr, "Design Name: ");
    bitfileinfo.DesignName = (char*)malloc(sizeof(char)*segmentLength);
    for(x = 0; x < segmentLength; x++)
    {
        bitfileinfo.DesignName[x] = fgetc(f);
    }
    fprintf(stderr, "%s\n",bitfileinfo.DesignName);
//----------------------------------------------------------------------
    segmentLength = GetSegmentLength(segment,segmentCheck,f);
    segmentCheck++;
    fprintf(stderr, "Device: ");
    if(bitFileId==XILINX_BITFILE)
    {
        bitfileinfo.DeviceName = (char*)malloc(sizeof(char)*(segmentLength+2));
        bitfileinfo.DeviceName[0] = 'x'; //Xilinx XC not stored in bit file
        bitfileinfo.DeviceName[1] = 'c';
        offset=2;

    } else {
        bitfileinfo.DeviceName = (char*)malloc(sizeof(char)*segmentLength);
        offset=0;
    }
    for(x = 0; x < segmentLength; x++)
    {
        bitfileinfo.DeviceName[x+offset] = fgetc(f);
    }
    fprintf(stderr, "%s\n",bitfileinfo.DeviceName);
//----------------------------------------------------------------------
    segmentLength = GetSegmentLength(segment,segmentCheck,f);
    segmentCheck++;
    fprintf(stderr, "Date: ");
    for(x = 0; x < segmentLength; x++)
    {
        tempChar = fgetc(f);
        fprintf(stderr, "%c", tempChar);
    }
    fprintf(stderr, "\n");
//----------------------------------------------------------------------
    segmentLength = GetSegmentLength(segment,segmentCheck,f);
    segmentCheck++;
    fprintf(stderr, "Time: ");
    for(x = 0; x < segmentLength; x++)
    {
        tempChar = fgetc(f);
        fprintf(stderr, "%c", tempChar);
    }
    fprintf(stderr, "\n");
//----------------------------------------------------------------------
    segment = fgetc(f);
    if(segment != segmentCheck)	fprintf(stderr, "Error in header segment: %d, should be %d\n",segment,segmentCheck);
    segmentLength = (fgetc(f) << 24) + (fgetc(f) << 16) + (fgetc(f) << 8) + fgetc(f);
    fprintf(stderr, "Bitstream Length: %0d bits\n", segmentLength * 8);
    bitfileinfo.Bitstream_Length = segmentLength;

    //That's it for now, bitfile header info is stored in bitfileinfo, FILE *f, needs to be kept until we program
    //This leaves us at 0xFF FF FF FF (Dummy Word) and the Sync Cmd 0xAA 99 55 66 (XILINX)
}