Exemple #1
0
Area    Ship::bounding() const
{
    // the idea in the following code is to calculate a bounding box
    // around the ship's triangle and use it for collision detection.

    // TODO: find a nicer way of rotating and translating
    // (-center_ and +center_ is not intuitive)

    // first calculate the triangle 'shadowing' the triangle on display
    // this means a rotation and translation needs to be applied to the
    // known points (see Ship::draw for comparison to the OpenGL code)
    const vector2 &RA = A_ - center_,
                   &RB = B_ - center_,
                    &RC = C_ - center_;

    // this is probably inefficient
    vector2 RRA(0, 0), RRB(0, 0), RRC(0, 0);

    float ra = to_radians(rot_angle_);
    rotate_vector(RA, ra, RRA);
    rotate_vector(RB, ra, RRB);
    rotate_vector(RC, ra, RRC);

    RRA += pos_ + center_;
    RRB += pos_ + center_;
    RRC += pos_ + center_;

    const vector2* points[3] = { &RRA, &RRB, &RRC } ;

    // no point storing the bounding box, because it depends on position
    // find a bounding box encompassing all points
    return Area::minimumArea(points, 3);
}
Exemple #2
0
void _marx_transform_ray (JDMVector_Type *x, JDMVector_Type *p, /*{{{*/
			  _Marx_Coord_Transform_Type *a)
{
   x->x -= a->dx;
   x->y -= a->dy;
   x->z -= a->dz;

   rotate_vector (a->matrix, x);
   rotate_vector (a->matrix, p);
}
Exemple #3
0
int fill_planet_data( PLANET_DATA *pdata, const int planet_no, const double jd,
                  const double observer_lat, const double observer_lon,
                  const char *vsop_data)
{
   double loc_sidereal_time = green_sidereal_time( jd) + observer_lon;
   double t_centuries = (jd - J2000) / 36525.;
   double obliquity = mean_obliquity( t_centuries);
   double loc[3];

   pdata->jd = jd;
   if( planet_no == 10)         /* get lunar data,  not VSOP */
      {
      double fund[N_FUND];

      lunar_fundamentals( vsop_data, t_centuries, fund);
      lunar_lon_and_dist( vsop_data, fund, &pdata->ecliptic_lon, &pdata->r, 0L);
      pdata->ecliptic_lon *= pi / 180.;
      pdata->ecliptic_lat = lunar_lat( vsop_data, fund, 0L) * pi / 180.;
      }
   else
      {
                  /* What we _really_ want is the location of the sun as */
                  /* seen from the earth.  VSOP gives us the opposite,   */
                  /* i.e.,  where the _earth_ is as seen from the _sun_. */
                  /* To evade this,  we add PI to the longitude and      */
                  /* negate the latitude.                                */
      pdata->ecliptic_lon =
               calc_vsop_loc( vsop_data, planet_no, 0, t_centuries, 0.) + pi;
      pdata->ecliptic_lat =
                  -calc_vsop_loc( vsop_data, planet_no, 1, t_centuries, 0.);
      pdata->r   = calc_vsop_loc( vsop_data, planet_no, 2, t_centuries, 0.);
      }


   polar3_to_cartesian( loc, pdata->ecliptic_lon, pdata->ecliptic_lat);
   memcpy( pdata->ecliptic_loc, loc, 3 * sizeof( double));

                  /* At this point,  loc is a unit vector in ecliptic */
                  /* coords of date.  Rotate it by 'obliquity' to get */
                  /* a vector in equatorial coords of date: */

   rotate_vector( loc, obliquity, 0);
   memcpy( pdata->equatorial_loc, loc, 3 * sizeof( double));

               /* The following two rotations take us from a vector in */
               /* equatorial coords of date to an alt/az vector: */
   rotate_vector( loc, -loc_sidereal_time, 2);
/* printf( "LST: %lf\n", fmod( loc_sidereal_time * 180. / pi, 360.)); */
   pdata->hour_angle = atan2( loc[1], loc[0]);
   rotate_vector( loc, observer_lat - pi / 2., 1);
   memcpy( pdata->altaz_loc, loc, 3 * sizeof( double));
   return( 0);
}
Exemple #4
0
void local_to_world(struct robot * robot, struct vect *world,
	struct vect *local)
{
	rotate_vector(world, local, &robot->position2.corrected_orientation);

	struct vect out;

	rotate_vector(&out, &camera_center, &robot->position2.corrected_orientation);

	//printf("%f, %f, %f\n", out.x, out.y, out.z);

	world->x += robot->position2.position.x;
	world->y += robot->position2.position.y;
}
Exemple #5
0
void object_render(object_t* object,camera_t camera)
{
const color_t white=get_color(255,255,255);
int i;
vector_t prev_point;
vector_t cur_point;

prev_point=vector_transform(vector_add(object->position,rotate_vector(object->points[object->num_points-1],object->rotation)),camera);
	for(i=0;i<object->num_points;i++)
	{
	cur_point=vector_transform(vector_add(object->position,rotate_vector(object->points[i],object->rotation)),camera);
	draw_line((unsigned int)prev_point.x,(unsigned int)prev_point.y,(unsigned int)cur_point.x,(unsigned int)cur_point.y,white);
	prev_point=cur_point;
	}
}
Exemple #6
0
void		move_object(t_cam *eye, t_obj *obj, int j)
{
  if (j == -1)
    {
      eye->pos = translate_vector(eye->pos, obj->trans, j);
      eye->pos = rotate_vector(eye->pos, obj->rot, j);
      eye->v = rotate_vector(eye->v, obj->rot, j);
    }
  else
    {
      eye->pos = rotate_vector(eye->pos, obj->rot, j);
      eye->pos = translate_vector(eye->pos, obj->trans, j);
      eye->v = rotate_vector(eye->v, obj->rot, j);
    }
}
// convert standard coordinates to half vector/difference vector coordinates
void std_coords_to_half_diff_coords(double theta_in, double fi_in, double theta_out, double fi_out,
								double& theta_half,double& fi_half,double& theta_diff,double& fi_diff )
{

	// compute in vector
	double in_vec_z = cos(theta_in);
	double proj_in_vec = sin(theta_in);
	double in_vec_x = proj_in_vec*cos(fi_in);
	double in_vec_y = proj_in_vec*sin(fi_in);
	double in[3]= {in_vec_x,in_vec_y,in_vec_z};
	normalize(in);


	// compute out vector
	double out_vec_z = cos(theta_out);
	double proj_out_vec = sin(theta_out);
	double out_vec_x = proj_out_vec*cos(fi_out);
	double out_vec_y = proj_out_vec*sin(fi_out);
	double out[3]= {out_vec_x,out_vec_y,out_vec_z};
	normalize(out);


	// compute halfway vector
	double half_x = (in_vec_x + out_vec_x)/2.0f;
	double half_y = (in_vec_y + out_vec_y)/2.0f;
	double half_z = (in_vec_z + out_vec_z)/2.0f;
	double half[3] = {half_x,half_y,half_z};
	normalize(half);

	// compute  theta_half, fi_half
	theta_half = acos(half[2]);
	fi_half = atan2(half[1], half[0]);


	double bi_normal[3] = {0.0, 1.0, 0.0};
	double normal[3] = { 0.0, 0.0, 1.0 };
	double temp[3];
	double diff[3];

	// compute diff vector
	rotate_vector(in, normal , -fi_half, temp);
	rotate_vector(temp, bi_normal, -theta_half, diff);
	
	// compute  theta_diff, fi_diff	
	theta_diff = acos(diff[2]);
	fi_diff = atan2(diff[1], diff[0]);

}
Exemple #8
0
void spacecraft_position_docked(spacecraft_t* spacecraft)
{
int i;
    for(i=0;i<spacecraft->num_docks;i++)
    {
    dock_t* dock=spacecraft->docks+i;
        if(dock->docked_spacecraft!=NULL)
        {
        dock_t* docked_dock=&dock->docked_spacecraft->docks[dock->docked_dock];

        vector_t dock_1_position=rotate_vector(dock->position,dock->orientation);
        vector_t dock_2_position=rotate_vector(docked_dock->position,docked_dock->orientation);
        dock->docked_spacecraft->base.position=vector_add(spacecraft->base.position,rotate_vector(vector_add(dock_1_position,dock_2_position),spacecraft->base.rotation));
        dock->docked_spacecraft->base.rotation=spacecraft->base.rotation+dock->orientation+docked_dock->orientation+M_PI;
        }
    }
}
Exemple #9
0
int DLL_FUNC calc_ssat_loc( const double t, double DLLPTR *ssat,
                                const int sat_wanted, const long precision)
{
   SAT_ELEMS elems;
   ELEMENTS orbit;
   double matrix[9];
   const double t_years = (t - J2000) / 365.25;

   if( precision == -1L)         /* just checking version # */
      return( 1);
   if( sat_wanted < 0 || sat_wanted > PHOEBE)
      return( -1);
   elems.jd = t;
   elems.sat_no = sat_wanted;
   set_ssat_elems( &elems, &orbit);

   setup_orbit_vectors( &orbit);
   comet_posn_part_ii( &orbit, IGNORED_DOUBLE, elems.loc, NULL);

   if( sat_wanted < RHEA)    /* inner 4 satellites are returned in Saturnic */
      {                            /*  coords so gotta rotate to B1950.0 */
      rotate_vector( elems.loc, INCL0, 0);
      rotate_vector( elems.loc, ASC_NODE0, 2);
      }
                        /* After above,  elems.loc is ecliptic 1950 coords */
   rotate_vector( elems.loc, OBLIQUITY_1950, 0);
                        /* Now,  elems.loc is equatorial 1950 coords */

#ifdef OUTPUT_IN_J2000
   setup_precession( matrix, 1950., 2000);
   precess_vector( matrix, elems.loc, ssat);
                        /* Now,  ssats is equatorial J2000... */
   rotate_vector( ssat, -OBLIQUITY_2000, 0);
                        /* And now,  ssats is ecliptical J2000 */
#else
   setup_precession( matrix, 1950., 2000. + t_years);
   precess_vector( matrix, elems.loc, ssat);
                        /* Now,  ssats is equatorial of epoch coords */
   rotate_vector( ssat, -mean_obliquity( t_years / 100.), 0);
                        /* And now,  ssats is ecliptical of epoch coords */
                        /* (which is what we really want anyway) */
#endif
   return( 0);
}
Exemple #10
0
static void pdf_write_arrow_appearance(fz_context *ctx, fz_buffer *buf, fz_rect *rect, float x, float y, float dx, float dy, float w)
{
	float r = fz_max(1, w);
	float angle = atan2f(dy, dx);
	fz_point v, a, b;

	v = rotate_vector(angle, 8.8f*r, 4.5f*r);
	a = fz_make_point(x + v.x, y + v.y);
	v = rotate_vector(angle, 8.8f*r, -4.5f*r);
	b = fz_make_point(x + v.x, y + v.y);

	*rect = fz_include_point_in_rect(*rect, a);
	*rect = fz_include_point_in_rect(*rect, b);
	*rect = fz_expand_rect(*rect, w);

	fz_append_printf(ctx, buf, "%g %g m\n", a.x, a.y);
	fz_append_printf(ctx, buf, "%g %g l\n", x, y);
	fz_append_printf(ctx, buf, "%g %g l\n", b.x, b.y);
}
Exemple #11
0
void update_balls(struct vector3d balls[], int size, float degrees) {

	
	int i;

	for (i = 0; i < size; i++) {
		
		rotate_vector(&balls[i], degrees);
	}
}
Exemple #12
0
/*
 * vect(x,y) must be normalized
 * gives the tangent point of the tangent to ellpise(da,db,dalpha) parallel to vect(x,y)
 * dalpha is in radians
 * ellipse center is in (0,0)
 */
static void elliptic_tangent(double x, double y, double da, double db,
			     double dalpha, double *px, double *py)
{
    double cosa = cos(dalpha);
    double sina = sin(dalpha);
    double u, v, len;

    /* rotate (x,y) -dalpha radians */
    rotate_vector(x, y, cosa, -sina, &x, &y);
    /*u = (x + da*y/db)/2;
       v = (y - db*x/da)/2; */
    u = da * da * y;
    v = -db * db * x;
    len = da * db / sqrt(da * da * v * v + db * db * u * u);
    u *= len;
    v *= len;
    rotate_vector(u, v, cosa, sina, px, py);

    return;
}
Exemple #13
0
spacecraft_dock(spacecraft_t* a,int a_dock_index,spacecraft_t* b,int b_dock_index)
{
dock_t* a_dock=a->docks+a_dock_index;
dock_t* b_dock=b->docks+b_dock_index;
a_dock->docked_spacecraft=b;
a_dock->docked_dock=b_dock_index;
b_dock->docked_spacecraft=a;
b_dock->docked_dock=a_dock_index;
b->base.position=vector_add(a->base.position,vector_subtract(rotate_vector(a_dock->position,a_dock->orientation),rotate_vector(b_dock->position,b_dock->orientation)));
b->parent=a->parent==NULL?a:a->parent;
}
Exemple #14
0
void draw_arrow(vector_t centre,double angle,color_t color)
{
//Define shape
vector_t tip;
tip.x=0;
tip.y=10;
vector_t left;
left.x=-5;
left.y=5;
vector_t right;
right.x=5;
right.y=5;
//Rotate arrow
tip=vector_add(centre,rotate_vector(tip,angle));
left=vector_add(centre,rotate_vector(left,angle));
right=vector_add(centre,rotate_vector(right,angle));

draw_line((unsigned int)centre.x,(unsigned int)centre.y,(unsigned int)tip.x,(unsigned int)tip.y,color);
draw_line((unsigned int)tip.x,(unsigned int)tip.y,(unsigned int)left.x,(unsigned int)left.y,color);
draw_line((unsigned int)tip.x,(unsigned int)tip.y,(unsigned int)right.x,(unsigned int)right.y,color);
}
Exemple #15
0
void rotate_on_camera(struct turret *turret, struct vect *result,
		struct vect* input)
{
	struct vect diff;

	rotate_vector(&diff, input, &turret->turret_rotation);

	//printf("%f, %f, %f\n", diff.x, diff.y, diff.z);

	result->x = diff.x + camera_center.x;
	result->y = diff.y + camera_center.y;
	result->z = diff.z + camera_center.z;
}
Exemple #16
0
void ViewManager::mouseMotion(int x, int y){
    int centerX = hWidth;
    int centerY = hHeight;
    glutWarpPointer(centerX, centerY);

    dir = rotate_vector(dir, vector3(0.0, 1.0, 0.0), -((float)(x-centerX))*0.002);
    side = cross(-dir, up);
    side.normalize();

    dir1 += -0.001*(float)(y-centerY);
    at = pos + dir;
    at[1] += dir1;
}
Exemple #17
0
void world_to_local(struct robot * robot, struct vect *local,
	struct vect *world)
{
	struct quaternion backwards;

  struct vect temp = *world;

	temp.x -= robot->position2.position.x;
	temp.y -= robot->position2.position.y;

	get_conjugate(&backwards, &robot->position2.corrected_orientation);

	rotate_vector(local, &temp, &backwards);
}
Exemple #18
0
/*! 
  Interpolates between camera positions.
  \arg \c  plyr_pos1 \c pos1 is relative to this position
  \arg \c  plyr_pos2 \c pos2 is relative to this position
  \arg \c  max_vec_angle Maximum downward pitch of vector from camera to player
  \arg \c  pos1 original camera position
  \arg \c  pos2 target camera position
  \arg \c  dist distance of interpolated camera position from player
  \arg \c  dt time step size (s)
  \arg \c  time_constant time constant to use in interpolation (s)

  \return  Interpolated camera position
  \author  jfpatry
  \date    Created:  2000-08-26
  \date    Modified: 2000-08-26
*/
point_t interpolate_view_pos( point_t plyr_pos1, point_t plyr_pos2,
			      scalar_t max_vec_angle,
			      point_t pos1, point_t pos2,
			      scalar_t dist, scalar_t dt,
			      scalar_t time_constant )
{
    static vector_t y_vec = { 0.0, 1.0, 0.0 };

    quaternion_t q1, q2;
    vector_t vec1, vec2;
    scalar_t alpha;
    scalar_t theta;
    matrixgl_t rot_mat;
    vector_t axis;

    vec1 = subtract_points( pos1, plyr_pos1 );
    vec2 = subtract_points( pos2, plyr_pos2 );

    normalize_vector( &vec1 );
    normalize_vector( &vec2 );

    q1 = make_rotation_quaternion( y_vec, vec1 );
    q2 = make_rotation_quaternion( y_vec, vec2 );

    alpha = min( MAX_INTERPOLATION_VALUE,
		 1.0 - exp ( -dt / time_constant ) );

    q2 = interpolate_quaternions( q1, q2, alpha );

    vec2 = rotate_vector( q2, y_vec );

    /* Constrain angle with x-z plane */
    theta = RADIANS_TO_ANGLES( M_PI/2 - acos( dot_product( vec2, y_vec ) ) );

    if ( theta > max_vec_angle )
    {
	axis = cross_product( y_vec, vec2 );
	normalize_vector( &axis );

	make_rotation_about_vector_matrix( rot_mat, axis, 
					   theta-max_vec_angle );
	vec2 = transform_vector( rot_mat, vec2 );
    }

    return move_point( plyr_pos2, 
		       scale_vector( dist, vec2 ) );

}
Exemple #19
0
// initialise offsets to provided distance vector to other vehicle (in meters in NED frame) if required
void AP_Follow::init_offsets_if_required(const Vector3f &dist_vec_ned)
{
    // return immediately if offsets have already been set
    if (!_offset.get().is_zero()) {
        return;
    }

    float target_heading_deg;
    if ((_offset_type == AP_FOLLOW_OFFSET_TYPE_RELATIVE) && get_target_heading_deg(target_heading_deg)) {
        // rotate offsets from north facing to vehicle's perspective
        _offset = rotate_vector(-dist_vec_ned, -target_heading_deg);
    } else {
        // initialise offset in NED frame
        _offset = -dist_vec_ned;
        // ensure offset_type used matches frame of offsets saved
        _offset_type = AP_FOLLOW_OFFSET_TYPE_NED;
    }
}
Exemple #20
0
void Ball::bounce_rotate(float amount, bool tb) // amount = [-1..1]
{
  float angle;
  
  if(tb)
  {
    angle = atan(_dirY / _dirX);  
  }
  else
  {
    angle = atan(_dirX / _dirY);
  }
  
  
  angle *= (360/(2*3.1415));
  angle = fabs(angle);
  // a = [0..90]

  // if backspin, invert angle. _dirY is already inverted
  if(_dirY < 0 && _dirX > 0 && _spin > 0 ||
     _dirY < 0 && _dirX < 0 && _spin < 0 ||
     _dirY > 0 && _dirX > 0 && _spin < 0 ||
     _dirY > 0 && _dirX < 0 && _spin > 0)
  {
    angle = 90 - angle;
    // angle is now how much you can turn to go completely horizontal or vertical
    // lessen it more for back-spins (less back-spin allowed! difficult to foresee!)
    angle -= 30;
  }
  else
  {
    // angle is now how much you can turn to go completely horizontal or vertical
    // lessen it for top-spins (more top-spin allowed! not as difficult to counter)
    angle -= 8;  
  }

  // angle is now how much you can turn to go completely horizontal or vertical
  if(angle < 0) angle = 0;

  angle *= amount;

  rotate_vector(&_dirX, &_dirY, angle);

}
Exemple #21
0
///
/// \brief  "Fires" a round from the Ship's ammo collection. The count of
///         ammo is decremented thereafter.
/// \return void
///
void    Ship::fire()
{
    if (ammo_pos_ != ammo_.end()) {
        vector2 bP(0, 0);

        // calculate the position of the bullet at the 'nose' of the ship
        float ra = to_radians(rot_angle_);
        rotate_vector((C_ - center_), ra, bP);
        bP += pos_ + center_;

        (*ammo_pos_).fire(bP, vel_ * 5);

        ++ammo_pos_;
    } else {
        DEBUG_PRINT << ">>> OUT OF AMMO -- RELOADING!" << std::endl;

        reloadAmmo();
    }
}
void Triangle::draw_doodle()
{
	float rotate_angle = -1;
	for(int a = 0; a < 100; a++, rotate_angle-= 0.005)
	{
		for(int i = 0; i < 3; i++)
		{

			//[0] init vector from current
			//[1] rotate to some angle
			//[2] find intersection point of V and next line
			//[3] init second point of current with inters point values

			int cur = i;
			int next = i+1;
			if( 3 == next) next = 0;

	//[0]
			Line *vector = edges[cur];

	//[1]
			// can be negative with vx value in rotate point line:81
			rotate_vector(vector, this->center, rotate_angle);

	//[2]
			Point *inters_point = new Point();
			find_intersection_point(edges[cur], edges[next], inters_point);

	//[3]
			edges[next]->a = inters_point;

			//try to find problem with this pointer
			edges[cur]->b->x = inters_point->x;
			edges[cur]->b->y = inters_point->y;

			edges[cur]->draw();

//		sleep(2);
		usleep(10000);
		}
	}
}
Exemple #23
0
// get offsets in meters in NED frame
bool AP_Follow::get_offsets_ned(Vector3f &offset) const
{
    const Vector3f &off = _offset.get();

    // if offsets are zero or type is NED, simply return offset vector
    if (off.is_zero() || (_offset_type == AP_FOLLOW_OFFSET_TYPE_NED)) {
        offset = off;
        return true;
    }

    // offset type is relative, exit if we cannot get vehicle's heading
    float target_heading_deg;
    if (!get_target_heading_deg(target_heading_deg)) {
        return false;
    }

    // rotate offsets from vehicle's perspective to NED
    offset = rotate_vector(off, target_heading_deg);
    return true;
}
Exemple #24
0
void    Ship::rotateVelocity()
{
    //
    //
    //           C
    //           *
    //          *|*
    //         * | *
    //        *  |  *
    //       *   |   *
    //    A * * * * * * B
    //           M
    //
    //    M_C = C - M
    //
    //    M is the mid-point between A and B
    //
    //    The idea is to calculate the direction by calculating the
    //    vector M_C and rotating it
    //
    //       ^
    //       ^
    //       ^
    //       C
    //      *^*
    //     * ^ *
    //    *  ^  *
    // A * * * * * B
    //
    //

    const vector2 M((A_[0] + B_[0]) / 2, (A_[1] + B_[1]) / 2),
          M_C = (C_ - M).normalize();

    // use a 2D rotation matrix to rotate the M_C vector, so the ship
    // goes 'forwards' with C as the front of the ship, rather than
    // at some weird angle
    rotate_vector(M_C, to_radians(rot_angle_), vel_);

    vel_   *= speed_;
}
Exemple #25
0
void get_up_vector(struct robot *robot, struct vect *result)
{
	struct vect up, local_up, forward, look;

	up.x = robot->position2.position.x;
	up.y = robot->position2.position.y;
	up.z = 1;

	world_to_local(robot, &local_up, &up);

	forward.x = 0;
	forward.y = -1;
	forward.z = 0;

	struct vect normalized_look;

	rotate_vector(&look, &forward, &robot->turret.turret_rotation);

//	printf("%f, %f, %f\n", look.x, look.y, look.z);

	float normal;

	struct vect right_vector, raw;

	cross(&local_up, &look, &right_vector);

//	printf("%f, %f, %f\n", right_vector.x, right_vector.y, right_vector.z);
//	printf("%f\n", norm(&right_vector));

	cross(&right_vector, &look, &raw);

//	printf("%f, %f, %f\n", raw.x, raw.y, raw.z);

	normal = norm(&raw);

	result->x = raw.x / normal;
	result->y = raw.y / normal;
	result->z = raw.z / normal;
}
Exemple #26
0
/* Main program */
int main( const int argc, const char **argv)
{
   const char *tle_filename = ((argc == 1) ? "test.tle" : argv[1]);
   FILE *ifile = fopen( tle_filename, "rb");
   tle_t tle; /* Pointer to two-line elements set for satellite */
   char line1[100], line2[100];
   int ephem = 1;       /* default to SGP4 */
   int i;               /* Index for loops etc */
   int n_failures = 0, n_simple = 0, n_simplex = 0;
   bool failures_only = false;

   for( i = 2; i < argc; i++)
      if( argv[i][0] == '-')
         switch( argv[i][1])
            {
            case 'f':
               failures_only = true;
               break;
            case 'v':
               verbose = 1;
               break;
            case 'd':
               dist_offset = atof( argv[i] + 2);
               break;
            case 's':
               vel_offset = atof( argv[i] + 2);
               break;
            default:
               printf( "Option '%s' unrecognized\n", argv[i]);
               break;
            }
   if( !ifile)
      {
      printf( "Couldn't open input TLE file %s\n", tle_filename);
      exit( -1);
      }
   *line1 = '\0';
   while( fgets( line2, sizeof( line2), ifile))
      {
      int got_data = 0;
      double state_vect[6];

      set_tle_defaults( &tle);
      if( strlen( line2) > 110 && line2[7] == '.' && line2[18] == '.'
                     && line2[0] == '2' && line2[1] == '4')
         {
         got_data = 3;           /* Find_Orb state vector ephemeris */
         tle.epoch = atof( line2);
         sscanf( line2 + 13, "%lf %lf %lf %lf %lf %lf",
                    state_vect + 0, state_vect + 1, state_vect + 2,
                    state_vect + 3, state_vect + 4, state_vect + 5);
         }
      else if( strlen( line1) > 55 && !memcmp( line1 + 50, " (TDB)", 6))
         {                                  /* JPL Horizons vector */
         const double obliq_2000 = 23.4392911 * PI / 180.;

         tle.epoch = atof( line1);          /* get JD epoch from header... */
         strcpy( line1, line2);
         if( fgets( line2, sizeof( line2), ifile))
            got_data = 1;
         sscanf( line1, "%lf %lf %lf",
                    state_vect + 0, state_vect + 1, state_vect + 2);
         sscanf( line2, "%lf %lf %lf",
                    state_vect + 3, state_vect + 4, state_vect + 5);
                      /* Cvt ecliptic to equatorial 2000: */
         rotate_vector( state_vect    , obliq_2000, 0);
         rotate_vector( state_vect + 3, obliq_2000, 0);
         }
      else if( parse_elements( line1, line2, &tle) >= 0)
         got_data = 2;

      if( got_data == 1 || got_data == 3)
         tle.epoch -= 68.00 / 86400.;       /* rough convert TDT to UTC */

      if( got_data)     /* hey! we got a TLE! */
         {
         double sat_params[N_SAT_PARAMS],  trial_state[6];
         int simple_rval;
         bool failed = false;
         tle_t new_tle;

         if( got_data == 1 || got_data == 3)
            {
            ephem = 3;        /* Use SDP4 for JPL Horizons vectors */
            for( i = 0; i < 6 && fabs( state_vect[i]) < 1.; i++)
               ;
            if( i == 6)   /* all small quantities,  must be in AU & AU/day : */
               {
               for( i = 0; i < 6; i++)
                  state_vect[i] *= AU_IN_KM;
               for( i = 3; i < 6; i++)
                  state_vect[i] /= seconds_per_day;
               }
            for( i = 3; i < 6; i++)    /* cvt km/sec to km/min */
               state_vect[i] *= seconds_per_minute;
            if( !failures_only)
               show_results( "Before:", NULL, state_vect);
            }
         else
            {
            int is_deep = select_ephemeris( &tle);

            if( is_deep && (ephem == 1 || ephem == 2))
               ephem += 2;    /* switch to an SDx */
            if( !is_deep && (ephem == 3 || ephem == 4))
               ephem -= 2;    /* switch to an SGx */

            /* Calling of NORAD routines */
            /* Each NORAD routine (SGP, SGP4, SGP8, SDP4, SDP8)   */
            /* will be called in turn with the appropriate TLE set */
            switch( ephem)
               {
               case 0:
                  SGP_init( sat_params, &tle);
                  SGP( 0., &tle, sat_params, state_vect, state_vect + 3);
                  break;
               case 1:
                  SGP4_init( sat_params, &tle);
                  SGP4( 0., &tle, sat_params, state_vect, state_vect + 3);
                  break;
               case 2:
                  SGP8_init( sat_params, &tle);
                  SGP8( 0., &tle, sat_params, state_vect, state_vect + 3);
                  break;
               case 3:
                  SDP4_init( sat_params, &tle);
                  SDP4( 0., &tle, sat_params, state_vect, state_vect + 3);
                  break;
               case 4:
                  SDP8_init( sat_params, &tle);
                  SDP8( 0., &tle, sat_params, state_vect, state_vect + 3);
                  break;
               }
            if( !failures_only)
               show_results( "Before:", &tle, state_vect);
            }

         new_tle = tle;
         simple_rval = compute_tle_from_state_vector( &new_tle, state_vect, ephem, trial_state);
         if( simple_rval)
            {
            n_simplex++;
            find_tle_via_simplex_method( &new_tle, state_vect, trial_state, ephem);
            }
         else
            n_simple++;

         compute_new_state_vect( &new_tle, trial_state, ephem);
         for( i = 0; i < 6; i++)
            {
            trial_state[i] -= state_vect[i];
            if( fabs( trial_state[i]) > 1e-6)
               failed = true;
            }
         if( failed && failures_only)
            show_results( "Before:", &tle, state_vect);
         if( failed || !failures_only)
            show_results( (simple_rval ? "Simplex result:" : "Simplest method:"),
                                &new_tle, trial_state);
         if( failed)
            n_failures++;
         }
      strcpy( line1, line2);
      }
   fclose( ifile);
   printf( "%d solved with simple method; %d with simplex\n", n_simple, n_simplex);
   if( n_failures)
      printf( "%d failures\n", n_failures);
   return(0);
} /* End of main() */
	void main(void *arg)
	{
		const color WHITE(1.0f);
		//-----------------------------------------
		const color Cs(i_color());
		color diffuse_color(1.0f, 1.0f, 1.0f);
		scalar diffuse_weight = i_diffuse();
		color specular_color(i_specularColor());
		scalar specular_weight= 0.2f;//cosinePower
		scalar roughness = 0.0f;
		int specular_mode = 1;//[0,3]
		scalar glossiness = 1.0f;
		color reflection_color(i_reflectedColor());
		scalar reflection_weight = 0.5f;
		color  refraction_color(1.0f, 1.0f, 1.0f);
		scalar refraction_weight= 0.0f;//zero will lead a dark image
		scalar refraction_glossiness = 0.5f;
		scalar refraction_thickness= 2.0f;//surfaceThickness
		color  translucency_color(i_transparency());
		scalar translucency_weight = i_translucence();
		scalar anisotropy = 1.0f;
		scalar rotation = 0.0f;
		scalar ior = 1.5f;//refractiveIndex
		bool fresnel_by_ior = eiTRUE;
		scalar fresnel_0_degree_refl = 0.2f;
		scalar fresnel_90_degree_refl = 1.0f;
		scalar fresnel_curve= 5.0f;
		bool is_metal = eiTRUE;
		int diffuse_samples = 8;
		int reflection_samples= 4;
		int refraction_samples= 4;
		scalar cutoff_threshold = LIQ_SCALAR_EPSILON;
		eiTag bump_shader = eiNULL_TAG;
		scalar bump_factor= 0.3f;

  		if( liq_UserDefinedNormal() == 0 )
  		{
  			i_normalCamera() = N;
  		}
		//-----------------------------------------
		vector In = normalize( I );
		normal Nn = normalize( i_normalCamera() );
		normal Nf = ShadingNormal(Nn);
		vector V = -In;
		//-----------------------------------------



		// specular is the percentage of specular lighting
		// limit weights in range [0, 1]
		specular_weight = clamp(specular_weight, 0.0f, 1.0f);
		refraction_weight = clamp(refraction_weight, 0.0f, 1.0f);
		translucency_weight = clamp(translucency_weight, 0.0f, 1.0f);
		// automatically compute Kd, Ks, Kt in an energy conserving way
		diffuse_weight = clamp(diffuse_weight, 0.0f, 1.0f);
		reflection_weight = clamp(reflection_weight, 0.0f, 1.0f);
		// the energy balancing between reflection and refraction is 
		// dominated by Fresnel law
		//color Kt(refraction_color * (spec * refr * (1.0f - trans)) * (is_metal?Cs:WHITE));
		
		// this is a monolithic shader which also serves as shadow shader
		if (ray_type == EI_RAY_SHADOW)
		{
			main_shadow(arg, refraction_color * (specular_weight * refraction_weight * (1.0f - translucency_weight)), 
				refraction_thickness, cutoff_threshold);
			return;
		}

		// for surface shader, we call bump shader
		eiTag shader = bump_shader;
		if (shader != eiNULL_TAG)
		{
			call_bump_shader(shader, bump_factor);
		}

		//color Kc(refraction_color * (spec * refr * trans) * (is_metal?Cs:WHITE));
		// non-reflected energy is absorbed
		//color Ks(specular_color * spec * (1.0f - refl) * (is_metal?Cs:WHITE));
		//color Kr(reflection_color * (spec * refl) * (is_metal?Cs:WHITE));
		// surface color will impact specular for metal material
		//const color Cs(surface_color);

//		const color Kd( Cs *(1.0f - spec) * diff );
//		const int spec_mode = clamp(specular_mode, 0, 3);

		computeSurface(
			i_color(),//outColor(),//out->Ci,//
			i_transparency(),//out->Oi,//
			i_matteOpacityMode(),
			i_matteOpacity(),
			o_outColor(),//out->Ci,//
			o_outTransparency()//out->Oi//
		);
		out->Ci = o_outColor();
		out->Oi = o_outTransparency();

		// apply rotation
		scalar deg = rotation;
		if (deg != 0.0f)
		{
			dPdu = rotate_vector(dPdu, N, radians(deg));
			dPdv = cross(dPdu, N);
			u_axis = normalize(dPdu);
			v_axis = normalize(dPdv);
		}

		// set the glossiness scale based on the chosen BSDF
		scalar glossiness_scale = 370.37f;
		if (specular_mode == 1)
		{
			glossiness_scale = 125.0f;
		}
		else if (specular_mode == 3)
		{
			// scale to make the same glossiness parameter 
			// results in similar lobe for different BSDFs
			glossiness_scale = 22.88f;
		}

//		scalar aniso = anisotropy;
		int refl_samples = reflection_samples;
		int refr_samples = refraction_samples;

		// prepare outgoing direction in local frame
		const vector wo(normalize(to_local(V)));
		// construct BSDFs
		OrenNayar Rd(roughness);
		scalar shiny_u = glossiness;
		if (shiny_u < eiSCALAR_EPS)
		{
			shiny_u = eiSCALAR_EPS;
			refl_samples = 1;
		}
		shiny_u = max(0.0f, glossiness_scale / shiny_u);
		scalar shiny_v = max(0.0f, shiny_u * anisotropy);
		
		scalar IOR = ior;
		eiBool fresn_by_ior = fresnel_by_ior;
		scalar fresn_0_degree_refl = fresnel_0_degree_refl;
		scalar fresn_90_degree_refl = fresnel_90_degree_refl;
		scalar fresn_curve = fresnel_curve;

		union {
			eiByte by_ior[sizeof(FresnelByIOR)];
			eiByte schlick[sizeof(FresnelSchlick)];
		} F_storage;

		union {
			eiByte by_ior[sizeof(FresnelByIOR)];
			eiByte schlick[sizeof(FresnelSchlick)];
		} invF_storage;

		Fresnel *F = NULL;
		Fresnel *invF = NULL;
		if (fresn_by_ior)
		{
			F = new (F_storage.by_ior) FresnelByIOR(IOR);
			invF = new (invF_storage.by_ior) InvFresnelByIOR(IOR);
		}
		else
		{
			F = new (F_storage.schlick) FresnelSchlick(
				fresn_0_degree_refl, 
				fresn_90_degree_refl, 
				fresn_curve);
			invF = new (invF_storage.schlick) InvFresnelSchlick(
				fresn_0_degree_refl, 
				fresn_90_degree_refl, 
				fresn_curve);
		}

		union {
			eiByte ward[sizeof(Ward)];
			eiByte phong[sizeof(StretchedPhong)];
			eiByte blinn[sizeof(Blinn)];
			eiByte cooktorrance[sizeof(CookTorrance)];
		} Rs_storage;

		BSDF *Rs = NULL;
		switch (specular_mode)
		{
		case 0:
 			Rs = new (Rs_storage.ward) Ward(F, shiny_u, shiny_v);
			break;
		case 1:
			Rs = new (Rs_storage.phong) StretchedPhong(F, shiny_u);
			break;
		case 2:
			Rs = new (Rs_storage.blinn) Blinn(F, shiny_u);
			break;
		case 3:
			Rs = new (Rs_storage.cooktorrance) CookTorrance(F, 1.0f / shiny_u);
			break;
		}

		SpecularReflection Rr(F);

		scalar refr_shiny_u = refraction_glossiness;
		if (refr_shiny_u < eiSCALAR_EPS)
		{
			refr_shiny_u = eiSCALAR_EPS;
			refr_samples = 1;
		}
		refr_shiny_u = max(0.0f, glossiness_scale / refr_shiny_u);
		scalar refr_shiny_v = max(0.0f, shiny_u * anisotropy);

		union {
			eiByte ward[sizeof(Ward)];
			eiByte phong[sizeof(StretchedPhong)];
			eiByte blinn[sizeof(Blinn)];
			eiByte cooktorrance[sizeof(CookTorrance)];
		} Rts_storage;

		BSDF *Rts = NULL;
		switch (specular_mode)
		{
		case 0:
			Rts = new (Rts_storage.ward) Ward(invF, refr_shiny_u, refr_shiny_v);
			break;
		case 1:
			Rts = new (Rts_storage.phong) StretchedPhong(invF, refr_shiny_u);
			break;
		case 2:
			Rts = new (Rts_storage.blinn) Blinn(invF, refr_shiny_u);
			break;
		case 3:
			Rts = new (Rts_storage.cooktorrance) CookTorrance(invF, 1.0f / refr_shiny_u);
			break;
		}

		scalar refr_thickness = refraction_thickness;

		// internal scale for refraction thickness, make it smaller
		BRDFtoBTDF Rt(Rts, IOR, refr_thickness * 0.1f, this);
		
		color Cdiffuse(0.0f);
		color Cspecular(0.0f);

		// don't integrate direct lighting if the ray hits the back face
 		if (dot_nd < 0.0f)
 		{
 			// integrate direct lighting from the front side
 			//out->Ci += integrate_direct_lighting(/*Kd*/diffuse(), Rd, wo);
 			//out->Ci *= i_diffuse() * getDiffuse(Nf, eiFALSE, eiFALSE);
			Cdiffuse += i_diffuse() * getDiffuse(Nf, eiFALSE, eiFALSE);

 			//out->Ci += integrate_direct_lighting(Ks, *Rs, wo);
 			//out->Ci += i_specularColor() * getPhong (Nf, V, i_cosinePower(), eiFALSE, eiFALSE);
			Cspecular += i_specularColor() * getPhong (Nf, V, i_cosinePower(), eiFALSE, eiFALSE);

		}

		// integrate for translucency from the back side
		if (!almost_black( refraction_color * (specular_weight * refraction_weight * translucency_weight)*(is_metal?Cs:WHITE) ) && //almost_black(Kc)
			(refr_thickness > 0.0f || dot_nd > 0.0f))
		{
			vector old_dPdu(dPdu);
			vector old_dPdv(dPdv);
			vector old_u_axis(u_axis);
			vector old_v_axis(v_axis);
			normal old_N(N);
			vector new_wo(wo);

			if (dot_nd < 0.0f)
			{
				dPdu = old_dPdv;
				dPdv = old_dPdu;
				u_axis = old_v_axis;
				v_axis = old_u_axis;
				N = -N;
				new_wo = vector(wo.y, wo.x, -wo.z);
			}
			
			// integrate direct lighting from the back side
			//out->Ci += Kc * integrate_direct_lighting(/*Kd*/i_diffuse(), Rd, new_wo);
			//out->Ci += i_diffuse() * getDiffuse(Nf, eiFALSE, eiFALSE);
			Cdiffuse += i_diffuse() * getDiffuse(Nf, eiFALSE, eiFALSE);

			//out->Ci += Kc * integrate_direct_lighting(Ks, *Rs, new_wo);
			//out->Ci += i_specularColor() * getPhong (Nf, V, i_cosinePower(), eiFALSE, eiFALSE);
			Cspecular += i_specularColor() * getPhong (Nf, V, i_cosinePower(), eiFALSE, eiFALSE);

			N = old_N;
			u_axis = old_u_axis;
			v_axis = old_v_axis;
			dPdu = old_dPdu;
			dPdv = old_dPdv;
		}


		scalar cutoff_thresh = cutoff_threshold;
				
		color CReflectSpecular(0.0f);
 		// integrate indirect specular lighting
		if (!almost_black( specular_color * (specular_weight * (1.0f - reflection_weight))*(is_metal?Cs:WHITE) ) && dot_nd < 0.0f)//almost_black(Ks)
 		{
 			IntegrateOptions opt;
 			opt.ray_type = EI_RAY_REFLECT_GLOSSY;
 			opt.min_samples = opt.max_samples = refl_samples;
 			opt.cutoff_threshold = cutoff_thresh;

			CReflectSpecular = integrate(wo, *Rs, opt);
  		}

		color CSpecularReflection(0.0f);
		// integrate perfect specular reflection
		if (!almost_black(reflection_color * (specular_weight * reflection_weight) * (is_metal?Cs:WHITE)) && dot_nd < 0.0f)//almost_black(Kr)
		{
			IntegrateOptions opt;
			opt.ray_type = EI_RAY_REFLECT_GLOSSY;
			opt.min_samples = opt.max_samples = 1; // force one sample for reflection
			opt.cutoff_threshold = cutoff_thresh;
			// the direct lighting of this BRDF is not accounted, 
			// so we trace lights here to compensate
			opt.trace_lights = eiTRUE;
			
			CSpecularReflection = integrate(wo, Rr, opt);
		}

		color CReflectDiffuse(0.0f);
		// integrate indirect diffuse lighting (color bleeding)
		if (!almost_black( Cs *(1.0f - specular_weight) * diffuse_weight ) && dot_nd < 0.0f)//almost_black(Kd)
		{
			IntegrateOptions opt;
			opt.ray_type = EI_RAY_REFLECT_DIFFUSE;
			opt.min_samples = opt.max_samples = diffuse_samples;
			opt.cutoff_threshold = cutoff_thresh;

			CReflectDiffuse = integrate(wo, Rd, opt);
		}

		color CRefraction(0.0f);
		// integrate refraction
		if ( !almost_black(refraction_color * specular_weight * refraction_weight * (1.0f-translucency_weight)*(is_metal?Cs:WHITE)) ) //almost_black(Kt)
		{
			IntegrateOptions opt;
			opt.ray_type = EI_RAY_REFRACT_GLOSSY;
			if (IOR == 1.0f)
			{
				opt.ray_type = EI_RAY_TRANSPARENT;
			}
			opt.min_samples = opt.max_samples = refr_samples;
			opt.cutoff_threshold = cutoff_thresh;
			// account for refractive caustics
			opt.trace_lights = eiTRUE;

			CRefraction = integrate(wo, Rt, opt);
		}

		out->Ci *= (Cdiffuse 

					+ CReflectDiffuse *
					  Cs *(1.0f - specular_weight) * diffuse_weight//Kd
					);

		out->Ci += (Cspecular 

					+ CReflectSpecular* 
					  specular_color   * specular_weight * (1.0f - reflection_weight)*(is_metal?Cs:WHITE)//Ks
					
					+ CSpecularReflection* 
					  reflection_color * specular_weight * reflection_weight * (is_metal?Cs:WHITE)//Kr
					
					+ CRefraction*
					  refraction_color * specular_weight * refraction_weight * (1.0f-translucency_weight) * (is_metal?Cs:WHITE)//Kt			
					);

#ifdef USE_AOV_aov_ambient
		aov_ambient() += ( i_ambientColor() 
							*(CReflectDiffuse *
							  Cs *(1.0f - specular_weight) * diffuse_weight//Kd
							 )
						 ) * (1.0f - o_outTransparency());
#endif
#ifdef USE_AOV_aov_diffuse
		aov_diffuse() += ( Cdiffuse * i_color() ) * (1.0f - o_outTransparency());
#endif
#ifdef USE_AOV_aov_specular
		aov_specular() += (Cspecular
							+ CReflectSpecular* 
							specular_color   * specular_weight * (1.0f - reflection_weight)*(is_metal?Cs:WHITE)//Ks

							+ CSpecularReflection* 
							reflection_color * specular_weight * reflection_weight * (is_metal?Cs:WHITE)//Kr

							+ CRefraction*
							refraction_color * specular_weight * refraction_weight * (1.0f-translucency_weight) * (is_metal?Cs:WHITE)//Kt			
							);
#endif


		if ( ! less_than( &i_transparency(), LIQ_SCALAR_EPSILON ) )
		{//transparent
			out->Ci = out->Ci * ( 1.0f - i_transparency() ) + trace_transparent() * i_transparency();
		}//else{ opacity }

		Rs->~BSDF();
		Rts->~BSDF();
	}
//-----------------------------------------------------------------------------
// solve()
//-----------------------------------------------------------------------------
void LLJointSolverRP3::solve()
{
//	llinfos << llendl;
//	llinfos << "LLJointSolverRP3::solve()" << llendl;

	//-------------------------------------------------------------------------
	// setup joints in their base rotations
	//-------------------------------------------------------------------------
	mJointA->setRotation( mJointABaseRotation );
	mJointB->setRotation( mJointBBaseRotation );

	//-------------------------------------------------------------------------
	// get joint positions in world space
	//-------------------------------------------------------------------------
	LLVector3 aPos = mJointA->getWorldPosition();
	LLVector3 bPos = mJointB->getWorldPosition();
	LLVector3 cPos = mJointC->getWorldPosition();
	LLVector3 gPos = mJointGoal->getWorldPosition();

//	llinfos << "bPosLocal = " << mJointB->getPosition() << llendl;
//	llinfos << "cPosLocal = " << mJointC->getPosition() << llendl;
//	llinfos << "bRotLocal = " << mJointB->getRotation() << llendl;
//	llinfos << "cRotLocal = " << mJointC->getRotation() << llendl;

//	llinfos << "aPos : " << aPos << llendl;
//	llinfos << "bPos : " << bPos << llendl;
//	llinfos << "cPos : " << cPos << llendl;
//	llinfos << "gPos : " << gPos << llendl;

	//-------------------------------------------------------------------------
	// get the poleVector in world space
	//-------------------------------------------------------------------------
	LLMatrix4 worldJointAParentMat;
	if ( mJointA->getParent() )
	{
		worldJointAParentMat = mJointA->getParent()->getWorldMatrix();
	}
	LLVector3 poleVec = rotate_vector( mPoleVector, worldJointAParentMat );

	//-------------------------------------------------------------------------
	// compute the following:
	// vector from A to B
	// vector from B to C
	// vector from A to C
	// vector from A to G (goal)
	//-------------------------------------------------------------------------
	LLVector3 abVec = bPos - aPos;
	LLVector3 bcVec = cPos - bPos;
	LLVector3 acVec = cPos - aPos;
	LLVector3 agVec = gPos - aPos;

//	llinfos << "abVec : " << abVec << llendl;
//	llinfos << "bcVec : " << bcVec << llendl;
//	llinfos << "acVec : " << acVec << llendl;
//	llinfos << "agVec : " << agVec << llendl;

	//-------------------------------------------------------------------------
	// compute needed lengths of those vectors
	//-------------------------------------------------------------------------
	F32 abLen = abVec.magVec();
	F32 bcLen = bcVec.magVec();
	F32 agLen = agVec.magVec();

//	llinfos << "abLen : " << abLen << llendl;
//	llinfos << "bcLen : " << bcLen << llendl;
//	llinfos << "agLen : " << agLen << llendl;

	//-------------------------------------------------------------------------
	// compute component vector of (A->B) orthogonal to (A->C)
	//-------------------------------------------------------------------------
	LLVector3 abacCompOrthoVec = abVec - acVec * ((abVec * acVec)/(acVec * acVec));

//	llinfos << "abacCompOrthoVec : " << abacCompOrthoVec << llendl;

	//-------------------------------------------------------------------------
	// compute the normal of the original ABC plane (and store for later)
	//-------------------------------------------------------------------------
	LLVector3 abcNorm;
	if (!mbUseBAxis)
	{
		if( are_parallel(abVec, bcVec, 0.001f) )
		{
			// the current solution is maxed out, so we use the axis that is
			// orthogonal to both poleVec and A->B
			if ( are_parallel(poleVec, abVec, 0.001f) )
			{
				// ACK! the problem is singular
				if ( are_parallel(poleVec, agVec, 0.001f) )
				{
					// the solutions is also singular
					return;
				}
				else
				{
					abcNorm = poleVec % agVec;
				}
			}
			else
			{
				abcNorm = poleVec % abVec;
			}
		}
		else
		{
			abcNorm = abVec % bcVec;
		}
	}
	else
	{
		abcNorm = mBAxis * mJointB->getWorldRotation();
	}

	//-------------------------------------------------------------------------
	// compute rotation of B
	//-------------------------------------------------------------------------
	// angle between A->B and B->C
	F32 abbcAng = angle_between(abVec, bcVec);

	// vector orthogonal to A->B and B->C
	LLVector3 abbcOrthoVec = abVec % bcVec;
	if (abbcOrthoVec.magVecSquared() < 0.001f)
	{
		abbcOrthoVec = poleVec % abVec;
		abacCompOrthoVec = poleVec;
	}
	abbcOrthoVec.normVec();

	F32 agLenSq = agLen * agLen;

	// angle arm for extension
	F32 cosTheta =	(agLenSq - abLen*abLen - bcLen*bcLen) / (2.0f * abLen * bcLen);
	if (cosTheta > 1.0f)
		cosTheta = 1.0f;
	else if (cosTheta < -1.0f)
		cosTheta = -1.0f;

	F32 theta = acos(cosTheta);

	LLQuaternion bRot(theta - abbcAng, abbcOrthoVec);

//	llinfos << "abbcAng      : " << abbcAng << llendl;
//	llinfos << "abbcOrthoVec : " << abbcOrthoVec << llendl;
//	llinfos << "agLenSq      : " << agLenSq << llendl;
//	llinfos << "cosTheta     : " << cosTheta << llendl;
//	llinfos << "theta        : " << theta << llendl;
//	llinfos << "bRot         : " << bRot << llendl;
//	llinfos << "theta abbcAng theta-abbcAng: " << theta*180.0/F_PI << " " << abbcAng*180.0f/F_PI << " " << (theta - abbcAng)*180.0f/F_PI << llendl;

	//-------------------------------------------------------------------------
	// compute rotation that rotates new A->C to A->G
	//-------------------------------------------------------------------------
	// rotate B->C by bRot
	bcVec = bcVec * bRot;

	// update A->C
	acVec = abVec + bcVec;

	LLQuaternion cgRot;
	cgRot.shortestArc( acVec, agVec );

//	llinfos << "bcVec : " << bcVec << llendl;
//	llinfos << "acVec : " << acVec << llendl;
//	llinfos << "cgRot : " << cgRot << llendl;

	// update A->B and B->C with rotation from C to G
	abVec = abVec * cgRot;
	bcVec = bcVec * cgRot;
	abcNorm = abcNorm * cgRot;
	acVec = abVec + bcVec;

	//-------------------------------------------------------------------------
	// compute the normal of the APG plane
	//-------------------------------------------------------------------------
	if (are_parallel(agVec, poleVec, 0.001f))
	{
		// the solution plane is undefined ==> we're done
		return;
	}
	LLVector3 apgNorm = poleVec % agVec;
	apgNorm.normVec();

	if (!mbUseBAxis)
	{
		//---------------------------------------------------------------------
		// compute the normal of the new ABC plane
		// (only necessary if we're NOT using mBAxis)
		//---------------------------------------------------------------------
		if( are_parallel(abVec, bcVec, 0.001f) )
		{
			// G is either too close or too far away
			// we'll use the old ABCnormal 
		}
		else
		{
			abcNorm = abVec % bcVec;
		}
		abcNorm.normVec();
	}

	//-------------------------------------------------------------------------
	// calcuate plane rotation
	//-------------------------------------------------------------------------
	LLQuaternion pRot;
	if ( are_parallel( abcNorm, apgNorm, 0.001f) )
	{
		if (abcNorm * apgNorm < 0.0f)
		{
			// we must be PI radians off ==> rotate by PI around agVec
			pRot.setQuat(F_PI, agVec);
		}
		else
		{
			// we're done
		}
	}
	else
	{
		pRot.shortestArc( abcNorm, apgNorm );
	}

//	llinfos << "abcNorm = " << abcNorm << llendl;
//	llinfos << "apgNorm = " << apgNorm << llendl;
//	llinfos << "pRot = " << pRot << llendl;

	//-------------------------------------------------------------------------
	// compute twist rotation
	//-------------------------------------------------------------------------
	LLQuaternion twistRot( mTwist, agVec );

//	llinfos	<< "twist    : " << mTwist*180.0/F_PI << llendl;
//	llinfos << "agNormVec: " << agNormVec << llendl;
//	llinfos << "twistRot : " << twistRot << llendl;

	//-------------------------------------------------------------------------
	// compute rotation of A
	//-------------------------------------------------------------------------
	LLQuaternion aRot = cgRot * pRot * twistRot;

	//-------------------------------------------------------------------------
	// apply the rotations
	//-------------------------------------------------------------------------
	mJointB->setWorldRotation( mJointB->getWorldRotation() * bRot );
	mJointA->setWorldRotation( mJointA->getWorldRotation() * aRot );
}
Exemple #29
0
void update_view( player_data_t *plyr, scalar_t dt )
{
    point_t view_pt;
    vector_t view_dir, up_dir, vel_dir, view_vec;
    scalar_t ycoord;
    scalar_t course_angle;
    vector_t axis;
    matrixgl_t rot_mat;
    vector_t y_vec;
    vector_t mz_vec;
    vector_t vel_proj;
    quaternion_t rot_quat;
    scalar_t speed;
    vector_t vel_cpy;
    scalar_t time_constant_mult;

    vel_cpy = plyr->vel;
    speed = normalize_vector( &vel_cpy );

    time_constant_mult = 1.0 /
	min( 1.0, 
	     max( 0.0, 
		  ( speed - NO_INTERPOLATION_SPEED ) /
		  ( BASELINE_INTERPOLATION_SPEED - NO_INTERPOLATION_SPEED )));

    up_dir = make_vector( 0, 1, 0 );

    vel_dir = plyr->vel;
    normalize_vector( &vel_dir );

    course_angle = get_course_angle();

    switch( plyr->view.mode ) {
    case TUXEYE:
    {
        scalar_t f = 2;
        vector_t v = plyr->plane_nml;
        scalar_t n = 1.;

        view_pt = plyr->pos;

        view_pt.x += v.x / n  * 0.3;
        view_pt.y += v.y / n * 0.3;
        view_pt.y += 0.1;
        view_pt.z += v.z / n * 0.3;


        if(plyr->control.flip_factor || plyr->control.barrel_roll_factor) {
            matrixgl_t mat1, mat;
			vector_t right;

            scalar_t n = sqrt(plyr->viewdir_for_tuxeye.x * plyr->viewdir_for_tuxeye.x + plyr->viewdir_for_tuxeye.y * plyr->viewdir_for_tuxeye.y + plyr->viewdir_for_tuxeye.z * plyr->viewdir_for_tuxeye.z);
            plyr->viewdir_for_tuxeye.x /= n;
            plyr->viewdir_for_tuxeye.y /= n;
            plyr->viewdir_for_tuxeye.z /= n;
            n = sqrt(plyr->updir_for_tuxeye.x * plyr->updir_for_tuxeye.x + plyr->updir_for_tuxeye.y * plyr->updir_for_tuxeye.y + plyr->updir_for_tuxeye.z * plyr->updir_for_tuxeye.z);
            plyr->updir_for_tuxeye.x /= n;
            plyr->updir_for_tuxeye.y /= n;
            plyr->updir_for_tuxeye.z /= n;
            right = cross_product(plyr->updir_for_tuxeye, plyr->viewdir_for_tuxeye);
            make_rotation_about_vector_matrix( mat1, right, jump_from_time(plyr->control.flip_factor) * 360 );
            make_rotation_about_vector_matrix( mat, plyr->viewdir_for_tuxeye, jump_from_time(plyr->control.barrel_roll_factor)  * 360 );
            multiply_matrices(mat, mat1, mat);
            view_dir = transform_vector(mat, plyr->viewdir_for_tuxeye);
            up_dir = transform_vector(mat, plyr->updir_for_tuxeye);
        }
        else {
            view_dir = plyr->direction;
            view_dir.y += 0.1;

            view_dir.x = (plyr->view.dir.x * f +  view_dir.x) / (f + 1);
            view_dir.y = (plyr->view.dir.y * f + view_dir.y) / (f + 1);
            view_dir.z = (plyr->view.dir.z * f + view_dir.z) / (f + 1);
            plyr->viewdir_for_tuxeye = view_dir;

            up_dir = plyr->plane_nml;
            up_dir.x = (plyr->view.up.x * f +  up_dir.x) / (f + 1);
            up_dir.y = (plyr->view.up.y * f + up_dir.y) / (f + 1);
            up_dir.z = (plyr->view.up.z * f + up_dir.z) / (f + 1);
            plyr->updir_for_tuxeye = up_dir;
        }
        break;
    }
    case BEHIND:
    {
	/* Camera-on-a-string mode */

	/* Construct vector from player to camera */
	view_vec = make_vector( 0, 
				sin( ANGLES_TO_RADIANS( 
				    course_angle -
				    CAMERA_ANGLE_ABOVE_SLOPE + 
				    PLAYER_ANGLE_IN_CAMERA ) ),
				cos( ANGLES_TO_RADIANS( 
				    course_angle -
				    CAMERA_ANGLE_ABOVE_SLOPE + 
				    PLAYER_ANGLE_IN_CAMERA ) ) );

	view_vec = scale_vector( CAMERA_DISTANCE, view_vec );

	y_vec = make_vector( 0.0, 1.0, 0.0 );
	mz_vec = make_vector( 0.0, 0.0, -1.0 );
	vel_proj = project_into_plane( y_vec, vel_dir );

	normalize_vector( &vel_proj );

	/* Rotate view_vec so that it places the camera behind player */
	rot_quat = make_rotation_quaternion( mz_vec, vel_proj );

	view_vec = rotate_vector( rot_quat, view_vec );


	/* Construct view point */
	view_pt = move_point( plyr->pos, view_vec );

	/* Make sure view point is above terrain */
        ycoord = find_y_coord( view_pt.x, view_pt.z );

        if ( view_pt.y < ycoord + MIN_CAMERA_HEIGHT ) {
            view_pt.y = ycoord + MIN_CAMERA_HEIGHT;
        } 

	/* Interpolate view point */
	if ( plyr->view.initialized ) {
	    /* Interpolate twice to get a second-order filter */
	    int i;
	    for (i=0; i<2; i++) {
		view_pt = 
		    interpolate_view_pos( plyr->pos, plyr->pos, 
					  MAX_CAMERA_PITCH, plyr->view.pos, 
					  view_pt, CAMERA_DISTANCE, dt,
					  BEHIND_ORBIT_TIME_CONSTANT * 
					  time_constant_mult );
	    }
	}

	/* Make sure interpolated view point is above terrain */
        ycoord = find_y_coord( view_pt.x, view_pt.z );

        if ( view_pt.y < ycoord + ABSOLUTE_MIN_CAMERA_HEIGHT ) {
            view_pt.y = ycoord + ABSOLUTE_MIN_CAMERA_HEIGHT;
        } 

	/* Construct view direction */
	view_vec = subtract_points( view_pt, plyr->pos );
	
	axis = cross_product( y_vec, view_vec );
	normalize_vector( &axis );
	
	make_rotation_about_vector_matrix( rot_mat, axis,
					   PLAYER_ANGLE_IN_CAMERA );
	view_dir = scale_vector( -1.0, 
				 transform_vector( rot_mat, view_vec ) );

	/* Interpolate orientation of camera */
	if ( plyr->view.initialized ) {
	    /* Interpolate twice to get a second-order filter */
	    int i;
	    for (i=0; i<2; i++) {
		interpolate_view_frame( plyr->view.up, plyr->view.dir,
					&up_dir, &view_dir, dt,
					BEHIND_ORIENT_TIME_CONSTANT );
		up_dir = make_vector( 0.0, 1.0, 0.0 );
	    }
	}

        break;
    }

    case FOLLOW: 
    {
	/* Camera follows player (above and behind) */

	up_dir = make_vector( 0, 1, 0 );

	/* Construct vector from player to camera */
	view_vec = make_vector( 0, 
				sin( ANGLES_TO_RADIANS( 
				    course_angle -
				    CAMERA_ANGLE_ABOVE_SLOPE +
				    PLAYER_ANGLE_IN_CAMERA ) ),
				cos( ANGLES_TO_RADIANS( 
				    course_angle -
				    CAMERA_ANGLE_ABOVE_SLOPE + 
				    PLAYER_ANGLE_IN_CAMERA ) ) );
	view_vec = scale_vector( CAMERA_DISTANCE, view_vec );

	y_vec = make_vector( 0.0, 1.0, 0.0 );
	mz_vec = make_vector( 0.0, 0.0, -1.0 );
	vel_proj = project_into_plane( y_vec, vel_dir );

	normalize_vector( &vel_proj );

	/* Rotate view_vec so that it places the camera behind player */
	rot_quat = make_rotation_quaternion( mz_vec, vel_proj );

	view_vec = rotate_vector( rot_quat, view_vec );


	/* Construct view point */
	view_pt = move_point( plyr->pos, view_vec );


	/* Make sure view point is above terrain */
        ycoord = find_y_coord( view_pt.x, view_pt.z );

        if ( view_pt.y < ycoord + MIN_CAMERA_HEIGHT ) {
            view_pt.y = ycoord + MIN_CAMERA_HEIGHT;
	}

	/* Interpolate view point */
	if ( plyr->view.initialized ) {
	    /* Interpolate twice to get a second-order filter */
	    int i;
	    for ( i=0; i<2; i++ ) {
		view_pt = 
		    interpolate_view_pos( plyr->view.plyr_pos, plyr->pos, 
					  MAX_CAMERA_PITCH, plyr->view.pos, 
					  view_pt, CAMERA_DISTANCE, dt,
					  FOLLOW_ORBIT_TIME_CONSTANT *
					  time_constant_mult );
	    }
	}

	/* Make sure interpolate view point is above terrain */
        ycoord = find_y_coord( view_pt.x, view_pt.z );

        if ( view_pt.y < ycoord + ABSOLUTE_MIN_CAMERA_HEIGHT ) {
            view_pt.y = ycoord + ABSOLUTE_MIN_CAMERA_HEIGHT;
        } 

	/* Construct view direction */
	view_vec = subtract_points( view_pt, plyr->pos );
	
	axis = cross_product( y_vec, view_vec );
	normalize_vector( &axis );
	
	make_rotation_about_vector_matrix( rot_mat, axis,
					   PLAYER_ANGLE_IN_CAMERA );
	view_dir = scale_vector( -1.0, 
				 transform_vector( rot_mat, view_vec ) );

	/* Interpolate orientation of camera */
	if ( plyr->view.initialized ) {
	    /* Interpolate twice to get a second-order filter */
	    int i;
	    for ( i=0; i<2; i++ ) {
		interpolate_view_frame( plyr->view.up, plyr->view.dir,
					&up_dir, &view_dir, dt,
					FOLLOW_ORIENT_TIME_CONSTANT );
		up_dir = make_vector( 0.0, 1.0, 0.0 );
	    }
	}

        break;
    }

    case ABOVE:
    {
	/* Camera always uphill of player */

	up_dir = make_vector( 0, 1, 0 );


	/* Construct vector from player to camera */
	view_vec = make_vector( 0, 
				sin( ANGLES_TO_RADIANS( 
				    course_angle - 
				    CAMERA_ANGLE_ABOVE_SLOPE+
				    PLAYER_ANGLE_IN_CAMERA ) ),
				cos( ANGLES_TO_RADIANS( 
				    course_angle - 
				    CAMERA_ANGLE_ABOVE_SLOPE+ 
				    PLAYER_ANGLE_IN_CAMERA ) ) );
	view_vec = scale_vector( CAMERA_DISTANCE, view_vec );

	
	/* Construct view point */
	view_pt = move_point( plyr->pos, view_vec );


	/* Make sure view point is above terrain */
        ycoord = find_y_coord( view_pt.x, view_pt.z );

        if ( view_pt.y < ycoord + MIN_CAMERA_HEIGHT ) {
            view_pt.y = ycoord + MIN_CAMERA_HEIGHT;
	}

	/* Construct view direction */
	view_vec = subtract_points( view_pt, plyr->pos );

	make_rotation_matrix( rot_mat, PLAYER_ANGLE_IN_CAMERA, 'x' );
	view_dir = scale_vector( -1.0, 
				 transform_vector( rot_mat, view_vec ) );

        break;
    }

    default:
	code_not_reached();
    } 

    /* Create view matrix */
    plyr->view.pos = view_pt;
    plyr->view.dir = view_dir;
    plyr->view.up = up_dir;
    plyr->view.plyr_pos = plyr->pos;
    plyr->view.initialized = True;

    setup_view_matrix( plyr );
} 
Exemple #30
0
void pointer(struct robot *robot)
{
  struct vect point;

  point.x = (cosf(robot->rotational_target + (robot->rotational_velocity * 0)) * 1000) + robot->position2.position.x;
  point.y = (sinf(robot->rotational_target + (robot->rotational_velocity * 0)) * 1000) + robot->position2.position.y;
  point.z = -40;

  //fprintf(stderr, "%f, %f, %f\n\n", robot->turret.target.x, robot->turret.target.y, robot->turret.target.z);

	point_at_world(robot, &robot->turret.target);

  struct vect cam_in_world;

  local_to_world(robot, &cam_in_world, &camera_center);

//  fprintf(stderr, "%f, %f, %f\n", cam_in_world.x, cam_in_world.y, cam_in_world.z);
//  fprintf(stderr, "%f, %f\n", robot->position2.position.x, robot->position2.position.y);

  struct vect d;

  difference(&d, &cam_in_world, &point);

  float xx = d.x * d.x;

  float yy = d.y * d.y;

  float zz = d.z * d.z;

  float predicted_distance = sqrtf(xx + yy + zz) - 40;

  //fprintf(stderr, "%f, %f\n", predicted_distance, robot->range);

  if (predicted_distance < robot->range)
  {
    gpioWrite(14, 0);
  }
   else
  {
    gpioWrite(14, 0);
  }

	struct vect output;

	get_up_vector(robot, &output);

//	printf("%f, %f, %f\n", output.x, output.y, output.z);

	struct vect cam_up, up, look, cam_forward, product;

	up.x = 0;
	up.y = 0;
	up.z = 1.0;

	cam_forward.x = 0;
	cam_forward.y = -1;
	cam_forward.z = 0;

	rotate_vector(&cam_up, &up, &robot->turret.turret_rotation);
	rotate_vector(&look, &cam_forward, &robot->turret.turret_rotation);

	robot->turret.roll = acosf(dot(&cam_up, &output));

	cross(&cam_up, &output, &product);

	robot->turret.roll = -asinf(product.x / look.x);

  if (robot->turret.pitch > robot->turret.pitch_guess)
  {
    robot->turret.pitch_guess += 0.000000174532925;
 
    if (robot->turret.pitch_guess > robot->turret.pitch)
    {
      robot->turret.pitch_guess = robot->turret.pitch;
    }
  }

  if (robot->turret.pitch < robot->turret.pitch_guess)
  {
    robot->turret.pitch_guess -= 0.000000174532925;
 
    if (robot->turret.pitch_guess < robot->turret.pitch)
    {
      robot->turret.pitch_guess = robot->turret.pitch;
    }
  } 

  if (robot->turret.yaw > robot->turret.yaw_guess)
  {
    robot->turret.yaw_guess += 0.000000174532925;
 
    if (robot->turret.yaw_guess > robot->turret.yaw)
    {
      robot->turret.yaw_guess = robot->turret.yaw;
    }
  }

  if (robot->turret.yaw < robot->turret.yaw_guess)
  {
    robot->turret.yaw_guess -= 0.000000174532925;
 
    if (robot->turret.yaw_guess < robot->turret.yaw)
    {
      robot->turret.yaw_guess = robot->turret.yaw;
    }
  } 

	//printf("%f, %f, %f\n", local.x, local.y, local.z);
	//fprintf(stderr, "%f\n", robot->turret.roll);
}