void LoadFCurve(Chunk chunk, Chunk parent, BasicFCurve fcurve) { int args = chunk.Args; int target = ReadInt32(args + 0); int channel = ReadInt32(args + 4); //int index = ReadInt32( args + 8 ) ; int iFCurve = ReadIndex(args + 12); int pFCurve = FindChild(parent, ChunkType.FCurve, iFCurve); Chunk chunk2 = ReadChunk(pFCurve); int args2 = chunk2.Args; int format = ReadInt32(args2 + 0); int nDims = ReadInt32(args2 + 4); int nKeys = ReadInt32(args2 + 8); int data = chunk2.Data; int nData = chunk2.DataSize / 4; fcurve.KeyFrames = new float[nData]; for (int i = 0; i < nData; i++) { fcurve.KeyFrames[i] = ReadFloat(data + i * 4); } fcurve.DimCount = nDims; fcurve.KeyCount = nKeys; fcurve.InterpType = GetFCurveInterpType(format); fcurve.TargetType = GetFCurveTargetType(target); fcurve.ChannelType = GetFCurveChannelType(channel); fcurve.TargetIndex = GetReferenceIndex(target); }
void EvalFCurve(BasicFCurve fcurve, float frame, float[] result) { float[] data = fcurve.KeyFrames; int lower = 0; int upper = fcurve.KeyCount - 1; int elementStride = fcurveElementStrides[(int)fcurve.InterpType]; int stride = elementStride * fcurve.DimCount + 1; while (upper - lower > 1) { int center = (upper + lower) / 2; float frame2 = data[stride * center]; if (frame < frame2) { upper = center; } else { lower = center; } } int k1 = stride * lower; int k2 = stride * upper; float f1 = data[k1++]; float f2 = data[k2++]; float t = f2 - f1; if (t != 0.0f) { t = (frame - f1) / t; } BasicFCurveInterpType interp = fcurve.InterpType; if (t <= 0.0f) { interp = BasicFCurveInterpType.Constant; } if (t >= 1.0f) { interp = BasicFCurveInterpType.Constant; k1 = k2; } switch (interp) { case BasicFCurveInterpType.Constant: for (int i = 0; i < fcurve.DimCount; i++) { result[i] = data[k1]; k1 += elementStride; } break; case BasicFCurveInterpType.Linear: for (int i = 0; i < fcurve.DimCount; i++) { float v1 = data[k1++]; float v2 = data[k2++]; result[i] = (v2 - v1) * t + v1; } break; case BasicFCurveInterpType.Hermite: float s = 1.0f - t; float b1 = s * s * t * 3.0f; float b2 = t * t * s * 3.0f; float b0 = s * s * s + b1; float b3 = t * t * t + b2; for (int i = 0; i < fcurve.DimCount; i++) { result[i] = data[k1] * b0 + data[k1 + 2] * b1 + data[k2 + 1] * b2 + data[k2] * b3; k1 += 3; k2 += 3; } break; case BasicFCurveInterpType.Cubic: for (int i = 0; i < fcurve.DimCount; i++) { float fa = f1 + data[k1 + 3]; float fb = f2 + data[k2 + 1]; float u = FindCubicRoot(f1, fa, fb, f2, frame); float v = 1.0f - u; float c1 = v * v * u * 3.0f; float c2 = u * u * v * 3.0f; float c0 = v * v * v + c1; float c3 = u * u * u + c2; result[i] = data[k1] * c0 + data[k1 + 4] * c1 + data[k2 + 2] * c2 + data[k2] * c3; k1 += 5; k2 += 5; } break; case BasicFCurveInterpType.Spherical: var q1 = new Quaternion(data[k1 + 0], data[k1 + 1], data[k1 + 2], data[k1 + 3]); var q2 = new Quaternion(data[k2 + 0], data[k2 + 1], data[k2 + 2], data[k2 + 3]); // [note] 旧API // var q3 = Quaternion.Slerp( q1, q2, t, 0.0f ) ; var q3 = q1.Slerp(q2, t); result[0] = q3.X; result[1] = q3.Y; result[2] = q3.Z; result[3] = q3.W; break; } }
void EvalFCurve( BasicFCurve fcurve, float frame, float[] result ) { float[] data = fcurve.KeyFrames ; int lower = 0 ; int upper = fcurve.KeyCount - 1 ; int elementStride = fcurveElementStrides[ (int)fcurve.InterpType ] ; int stride = elementStride * fcurve.DimCount + 1 ; while ( upper - lower > 1 ) { int center = ( upper + lower ) / 2 ; float frame2 = data[ stride * center ] ; if ( frame < frame2 ) { upper = center ; } else { lower = center ; } } int k1 = stride * lower ; int k2 = stride * upper ; float f1 = data[ k1 ++ ] ; float f2 = data[ k2 ++ ] ; float t = f2 - f1 ; if ( t != 0.0f ) t = ( frame - f1 ) / t ; BasicFCurveInterpType interp = fcurve.InterpType ; if ( t <= 0.0f ) interp = BasicFCurveInterpType.Constant ; if ( t >= 1.0f ) { interp = BasicFCurveInterpType.Constant ; k1 = k2 ; } switch ( interp ) { case BasicFCurveInterpType.Constant : for ( int i = 0 ; i < fcurve.DimCount ; i ++ ) { result[ i ] = data[ k1 ] ; k1 += elementStride ; } break ; case BasicFCurveInterpType.Linear : for ( int i = 0 ; i < fcurve.DimCount ; i ++ ) { float v1 = data[ k1 ++ ] ; float v2 = data[ k2 ++ ] ; result[ i ] = ( v2 - v1 ) * t + v1 ; } break ; case BasicFCurveInterpType.Hermite : float s = 1.0f - t ; float b1 = s * s * t * 3.0f ; float b2 = t * t * s * 3.0f ; float b0 = s * s * s + b1 ; float b3 = t * t * t + b2 ; for ( int i = 0 ; i < fcurve.DimCount ; i ++ ) { result[ i ] = data[ k1 ] * b0 + data[ k1 + 2 ] * b1 + data[ k2 + 1 ] * b2 + data[ k2 ] * b3 ; k1 += 3 ; k2 += 3 ; } break ; case BasicFCurveInterpType.Cubic : for ( int i = 0 ; i < fcurve.DimCount ; i ++ ) { float fa = f1 + data[ k1 + 3 ] ; float fb = f2 + data[ k2 + 1 ] ; float u = FindCubicRoot( f1, fa, fb, f2, frame ) ; float v = 1.0f - u ; float c1 = v * v * u * 3.0f ; float c2 = u * u * v * 3.0f ; float c0 = v * v * v + c1 ; float c3 = u * u * u + c2 ; result[ i ] = data[ k1 ] * c0 + data[ k1 + 4 ] * c1 + data[ k2 + 2 ] * c2 + data[ k2 ] * c3 ; k1 += 5 ; k2 += 5 ; } break ; case BasicFCurveInterpType.Spherical : var q1 = new Quaternion( data[ k1 + 0 ], data[ k1 + 1 ], data[ k1 + 2 ], data[ k1 + 3 ] ) ; var q2 = new Quaternion( data[ k2 + 0 ], data[ k2 + 1 ], data[ k2 + 2 ], data[ k2 + 3 ] ) ; // [note] 旧API // var q3 = Quaternion.Slerp( q1, q2, t, 0.0f ) ; var q3 = q1.Slerp( q2, t ) ; result[ 0 ] = q3.X ; result[ 1 ] = q3.Y ; result[ 2 ] = q3.Z ; result[ 3 ] = q3.W ; break ; } }
void LoadFCurve( Chunk chunk, Chunk parent, BasicFCurve fcurve ) { int args = chunk.Args ; int target = ReadInt32( args + 0 ) ; int channel = ReadInt32( args + 4 ) ; //int index = ReadInt32( args + 8 ) ; int iFCurve = ReadIndex( args + 12 ) ; int pFCurve = FindChild( parent, ChunkType.FCurve, iFCurve ) ; Chunk chunk2 = ReadChunk( pFCurve ) ; int args2 = chunk2.Args ; int format = ReadInt32( args2 + 0 ) ; int nDims = ReadInt32( args2 + 4 ) ; int nKeys = ReadInt32( args2 + 8 ) ; int data = chunk2.Data ; int nData = chunk2.DataSize / 4 ; fcurve.KeyFrames = new float[ nData ] ; for ( int i = 0 ; i < nData ; i ++ ) { fcurve.KeyFrames[ i ] = ReadFloat( data + i * 4 ) ; } fcurve.DimCount = nDims ; fcurve.KeyCount = nKeys ; fcurve.InterpType = GetFCurveInterpType( format ) ; fcurve.TargetType = GetFCurveTargetType( target ) ; fcurve.ChannelType = GetFCurveChannelType( channel ) ; fcurve.TargetIndex = GetReferenceIndex( target ) ; }