示例#1
0
文件: envelope.c 项目: 2asoft/xray
float lwEvalEnvelope( lwEnvelope *env, float time )
{
   lwKey *key0, *key1, *skey, *ekey;
   float t, h1, h2, h3, h4, in, out, offset = 0.0f;
   int noff;


   /* if there's no key, the value is 0 */

   if ( env->nkeys == 0 ) return 0.0f;

   /* if there's only one key, the value is constant */

   if ( env->nkeys == 1 )
      return env->key->value;

   /* find the first and last keys */

   skey = ekey = env->key;
   while ( ekey->next ) ekey = ekey->next;

   /* use pre-behavior if time is before first key time */

   if ( time < skey->time ) {
      switch ( env->behavior[ 0 ] )
      {
         case BEH_RESET:
            return 0.0f;

         case BEH_CONSTANT:
            return skey->value;

         case BEH_REPEAT:
            time = range( time, skey->time, ekey->time, NULL );
            break;

         case BEH_OSCILLATE:
            time = range( time, skey->time, ekey->time, &noff );
            if ( noff % 2 )
               time = ekey->time - skey->time - time;
            break;

         case BEH_OFFSET:
            time = range( time, skey->time, ekey->time, &noff );
            offset = noff * ( ekey->value - skey->value );
            break;

         case BEH_LINEAR:
            switch ( skey->shape ) {
               case SHAPE_STEP:
                  return skey->value;
               case SHAPE_LINE:
                  return ( skey->value - skey->next->value )
                       / ( skey->time - skey->next->time )
                       * ( time - skey->next->time )
                       + skey->next->value;
               case SHAPE_TCB:
               case SHAPE_HERM:
               case SHAPE_BEZI:
                  out = outgoing( skey, (Key*)(skey->next) )
                      / ( skey->next->time - skey->time );
                  return out * ( time - skey->time ) + skey->value;
               case SHAPE_BEZ2:
                  return ( skey->param[ 1 ] - skey->param[ 3 ] )
                       / ( skey->param[ 0 ] - skey->param[ 2 ] )
                       * ( time - skey->time )
                       + skey->value;
            }
      }
   }

   /* use post-behavior if time is after last key time */

   else if ( time > ekey->time ) {
      switch ( env->behavior[ 1 ] )
      {
         case BEH_RESET:
            return 0.0f;

         case BEH_CONSTANT:
            return ekey->value;

         case BEH_REPEAT:
            time = range( time, skey->time, ekey->time, NULL );
            break;

         case BEH_OSCILLATE:
            time = range( time, skey->time, ekey->time, &noff );
            if ( noff % 2 )
               time = ekey->time - skey->time - time;
            break;

         case BEH_OFFSET:
            time = range( time, skey->time, ekey->time, &noff );
            offset = noff * ( ekey->value - skey->value );
            break;

         case BEH_LINEAR:
            switch ( ekey->shape ) {
               case SHAPE_STEP:
                  return ekey->value;
               case SHAPE_LINE:
                  return ( ekey->value - ekey->prev->value )
                       / ( ekey->time - ekey->prev->time )
                       * ( time - ekey->prev->time )
                       + ekey->prev->value;
               case SHAPE_TCB:
               case SHAPE_HERM:
               case SHAPE_BEZI:
                  in = incoming( (Key*)(ekey->prev), (Key*)ekey )
                     / ( ekey->time - ekey->prev->time );
                  return in * ( time - ekey->time ) + ekey->value;
               case SHAPE_BEZ2:
                  return ( ekey->param[ 3 ] - ekey->param[ 1 ] )
                       / ( ekey->param[ 2 ] - ekey->param[ 0 ] )
                       * ( time - ekey->time )
                       + ekey->value;
            }
      }
   }

   /* get the endpoints of the interval being evaluated */

   key0 = env->key;
   while ( time > key0->next->time )
      key0 = key0->next;
   key1 = key0->next;

   /* check for singularities first */

   if ( time == key0->time )
      return key0->value + offset;
   else if ( time == key1->time )
      return key1->value + offset;

   /* get interval length, time in [0, 1] */

   t = ( time - key0->time ) / ( key1->time - key0->time );

   /* interpolate */

   switch ( key1->shape )
   {
      case SHAPE_TCB:
      case SHAPE_BEZI:
      case SHAPE_HERM:
         out = outgoing( key0, (Key*)key1 );
         in = incoming( (Key*)key0, (Key*)key1 );
         hermite( t, &h1, &h2, &h3, &h4 );
         return h1 * key0->value + h2 * key1->value + h3 * out + h4 * in + offset;

      case SHAPE_BEZ2:
         return bez2( (Key*)key0, (Key*)key1, time ) + offset;

      case SHAPE_LINE:
         return key0->value + t * ( key1->value - key0->value ) + offset;

      case SHAPE_STEP:
         return key0->value + offset;

      default:
         return offset;
   }
}
示例#2
0
float bez3(float p0, float p1, float p2, float p3, float out){
    return bez2(lerp(p0, p1, out), lerp(p1, p2, out), lerp(p2, p3, out), out);
}