Beispiel #1
0
bool separate_ball_from_segment(long double *x, long double *y, long double d, segment *seg){
    long double dist = point_distance_from_line(*x, *y, &seg->line_equation);
    if(dist == -1){
        return separate_ball_from_fixed_ball(x, y, seg->A.x, seg->A.y, d);
    }else{
        if(dist < d){
            long double ang = vector_angle(seg->line_equation.A, seg->line_equation.B),
                   cs = cos(ang);
                   ang = sin(ang);
            point helpy = {*x + 2 * d * cs,
                                  *y + 2 * d * ang},
                         begin = {*x, *y};
            d -= dist;
            if(do_segments_intersect(&seg->A, &seg->B, &helpy, &begin)){
                *x -= d * cs;
                *y -= d * ang;
                //-ang
            }else{
                *x += d * cs;
                *y += d * ang;
                //ang
            }
            return true;
        }else{
            return false;
        }
    }
}
Beispiel #2
0
int lua_CalcAngle( void* l ){
	float uv[3],pv[3];
	bool isok = true;
	if( Lua_isnumber(l,1) ){
		uv[0] = (float)Lua_tonumber(l,1);
	}else isok = false;
	if( Lua_isnumber(l,2) ){
		uv[1] = (float)Lua_tonumber(l,2);
	}else isok = false;
	if( Lua_isnumber(l,3) ){
		uv[2] = (float)Lua_tonumber(l,3);
	}else isok = false;
	if( Lua_isnumber(l,4) ){
		pv[0] = (float)Lua_tonumber(l,4);
	}else isok = false;
	if( Lua_isnumber(l,5) ){
		pv[1] = (float)Lua_tonumber(l,5);
	}else isok = false;
	if( Lua_isnumber(l,6) ){
		pv[2] = (float)Lua_tonumber(l,6);
	}else isok = false;

	if( isok ){
		double a = vector_angle(uv,pv);

		a *= 180/M_PI;
		Lua_pushnumber( l,a );
		return 1;
	}
	Lua_pushnil(l);
	return 1;
}
Beispiel #3
0
//计算x,y,z和你的角度a=GetAngle(x,y,z)
int lua_GetAngle( void* l ){
	float uv[3],pv[3],av[3],sv[3];

	bool isok = true;
	if( Lua_isnumber(l,1) ){
		uv[0] = (float)Lua_tonumber(l,1);
	}else isok = false;
	if( Lua_isnumber(l,2) ){
		uv[1] = (float)Lua_tonumber(l,2);
	}else isok = false;
	if( Lua_isnumber(l,3) ){
		uv[2] = (float)Lua_tonumber(l,3);
	}else isok = false;

	if( isok ){
		size_t len;
		const char * name = Lua_tolstring(l,1,&len);
		void* pplayer = GetUnitByName(sPlayer);
		if( pplayer ){
			GetUnitPosition( pplayer,pv );
			GetUnitDirection( pplayer,av );
			vector_sub( sv,uv,pv );
			sv[2] = 0;
			double a = vector_angle(av,sv);

			a *= 180/M_PI;
			Lua_pushnumber( l,a );
			return 1;
		}
	}
	Lua_pushnil(l);
	return 1;
}
Beispiel #4
0
long double check_exit(long double dx, long double dy, fixed_exit *ex){
    long double fi = vector_angle(dx, dy);
    if(sqrt(dx * dx + dy * dy) - radius_rectangle(ex, fi) < 0){
        return 0.01;
    }
    else{
        return EMPTY_COLLISION_TIME;
    }
}
Beispiel #5
0
Vector vector_interpolate_spherical(Vector a, Vector b, float t)
{
    float phi = vector_angle(a, b);
    float s = sin(phi);

    float factor_a = sin((1 - t) * phi) / s;
    float factor_b = sin(t * phi) / s;

    return vector_add(vector_scale(a, factor_a), vector_scale(b, factor_b));
}
Beispiel #6
0
/**
    I treat fixed points as ininitely small balls
    */
void get_velocity_after_ball_to_fixed_ball_collision(long double *vx, long double *vy, long double dx, long double dy, long double dr, long double restitution){
    long double ang = vector_angle(dx, dy),
           cs = cos(ang);
           ang = sin(ang);
    long double v_into = *vx * cs + *vy * ang,
           v_perp = *vy * cs - *vx * ang;
    v_into += dr * sign(v_into);
    v_into *= -restitution;
    *vx = v_into * cs - v_perp * ang;
    *vy = v_into * ang + v_perp * cs;
}
Beispiel #7
0
/**
    x1, y1 - coordinates of movable
    x2, y2 - coordinates of fixed ball
    d - sum of radiuses

    Of course works also for fixed points
    */
bool separate_ball_from_fixed_ball(long double *x1, long double *y1, long double x2, long double y2, long double d){
    long double dx = x2 - *x1,
           dy = y2 - *y1,
           ang = vector_angle(dx, dy);
    dx = sqrt(dx * dx + dy * dy);
    if(dx < d){
        d -= dx;
        //for some reason it doesn't work without:
        d *= 1.01;
        d += 1.3;
        *x1 -= d * cos(ang);
        *y1 -= d * sin(ang);
        return true;
    }
    return false;
}
Beispiel #8
0
/**
    Colliding
    */
void get_velocities_after_two_balls_collision(long double *v1x, long double *v1y, long double *v2x, long double *v2y,
                                              long double dx, long double dy, long double m1, long double m2, long double dr, long double restitution){
    *v1x -= *v2x;
    *v1y -= *v2y;
    dy = vector_angle(dx, dy);
    dx = cos(dy);
    dy = sin(dy);
    long double v_into = *v1x * dx + *v1y * dy,
           v_perp = *v1y * dx - *v1x * dy,
           mc = m1 + m2;
           v_into += dr * sign(v_into);
    *v1x = v_into * ((m1 - restitution * m2) / mc);
    *v1y = *v1x * dy + *v2y + v_perp * dx;
    *v1x = *v1x * dx + *v2x - v_perp * dy;
    v_perp = (((1 + restitution) * m1) / mc) * v_into;
    *v2x += v_perp * dx;
    *v2y += v_perp * dy;

}
Beispiel #9
0
/**
    Separating
    */
bool separate_two_balls(long double *x1, long double *y1, long double m1, long double *x2, long double *y2, long double m2, long double d){
    long double dx = *x2 - *x1,
           dy = *y2 - *y1,
           ang = vector_angle(dx, dy);
    dx = sqrt(dx * dx + dy * dy);
    if(dx < d){
        d -= dx;
        dx = d * sin(ang); //y
        d *= cos(ang); //x
        ang = m1 + m2;

        dy = m1 / ang; //m1 mass factor
        ang = m2 / ang; //m2 mass factor
        *x1 -= d * ang;
        *y1 -= dx * ang;
        *x2 += d * dy;
        *y2 += dx * dy;
        return true;
    }
    return false;
}
Beispiel #10
0
void test_vector()
{
  Vector *v = vector_new(1,2,3);
  CU_ASSERT(v->x == 1);
  CU_ASSERT(v->y == 2);
  CU_ASSERT(v->z == 3);

  Vector *vc = vector_copy(v);
  CU_ASSERT(vc->x == 1);
  CU_ASSERT(vc->y == 2);
  CU_ASSERT(vc->z == 3);

  Vector *u = vector_new(4,5,6);
  vector_add(v,u);
  CU_ASSERT(v->x == 5);
  CU_ASSERT(v->y == 7);
  CU_ASSERT(v->z == 9);

  vector_subtract(v,u);
  CU_ASSERT(v->x == 1);
  CU_ASSERT(v->y == 2);
  CU_ASSERT(v->z == 3);

  vector_multiply(v,2);
  CU_ASSERT(v->x == 2);
  CU_ASSERT(v->y == 4);
  CU_ASSERT(v->z == 6);

  Vector *w = vector_cross(v,u);
  CU_ASSERT(w->x == -6);
  CU_ASSERT(w->y == 12);
  CU_ASSERT(w->z == -6);

  vector_free(v);
  vector_free(u);
  vector_free(w);

  v = vector_new(3,4,0);
  u = vector_new(0,3,4);
  CU_ASSERT(v->x==u->y);
  CU_ASSERT(v->y==u->z);

  w = vector_cross(v,u);
  CU_ASSERT(w->x == 16);
  CU_ASSERT(w->y == -12);
  CU_ASSERT(w->z == 9);


  CU_ASSERT(within_tol(vector_magnitude(v),5));
  CU_ASSERT(within_tol(vector_magnitude(u),5));

  vector_free(v);
  vector_free(u);
  vector_free(w);

  v = vector_new(1,0,0);
  u = vector_new(0,0,1);

  double a = vector_angle(v,u)/D2R;
  CU_ASSERT(within_tol(a,90));
  CU_ASSERT(within_tol(vector_angle(u,v),90.*D2R));

  w = vector_cross(v,u);
  CU_ASSERT(within_tol(vector_magnitude(w),1));
  CU_ASSERT(w->x==0);
  CU_ASSERT(w->y==-1);
  CU_ASSERT(w->z==0);
}
Beispiel #11
0
static void test_vector_angle() {
  assert_within_delta(0.01, PI*0.25, vector_angle((Vector){ 1, 1 }));
}
Beispiel #12
0
bool intersection_test(const Bounding *b1, const Bounding *b2, double *intersection_time)
{
    assert(b1 && b2 && "Bad bounding pointers.");
    assert(intersection_time && "Bad intersection time pointer.");

    *intersection_time = nan(NULL);

    if (bounding_composite == b2->bounding_type &&
        bounding_composite != b1->bounding_type)
    {
        const Bounding *t = b1;
        b1 = b2;
        b2 = t;
    }

    if (bounding_composite == b1->bounding_type)
    {
        size_t intersections_count = b1->data.composite_data.children_count;
        double *intersection_times = _alloca(intersections_count * sizeof(double)); // compiler bug?
        bool *intersection_facts = _alloca(intersections_count * sizeof(bool)); // compiler bug?
        bool composite_intersection_result = false;

        for (size_t i = 0; i < intersections_count; i++)
        {
            intersection_times[i] = nan(NULL);
            intersection_facts[i] = intersection_test(b2, &b1->data.composite_data.children[i], &intersection_times[i]);
            composite_intersection_result |= intersection_facts[i];
        }

        *intersection_time = __get_min_intersection_time(intersection_times, intersection_facts, intersections_count);
        return composite_intersection_result;
    }

    assert(bounding_composite != b1->bounding_type &&
           bounding_composite != b2->bounding_type &&
           "Can't test composite boundings.");

    Vector axes[6];
    double intersection_times[15]; // 6 + 3 * 3.
    bool intersection_facts[15];

    __bounding_get_intersection_axes(b1, &axes[0]);
    __bounding_get_intersection_axes(b2, &axes[3]);

    bool intersection_result = true;
    for (size_t i = 0; i < 6; i++)
    {
        intersection_times[i] = nan(NULL);
        intersection_facts[i] = __bounding_axis_test(b1, b2, &axes[i], &intersection_times[i]);
        intersection_result &= intersection_facts[i];
    }

    size_t intersection_times_counter = 6;
    for (size_t i = 0; i < 3; i++)
    {
        for (size_t j = 3; j < 6; j++)
        {
            if (vector_eq(&axes[i], &axes[j]))
            {
                continue;
            }

            Vector t;
            if (!(vector_tolerance_eq(0.0, vector_angle(&axes[i], &axes[j])) ||
                  vector_tolerance_eq(M_PI, vector_angle(&axes[i], &axes[j]))))
            {
                vector_vector_mul(&axes[i], &axes[j], &t);
            }
            else
            {
                vector_get_orthogonal(&axes[i], &t);
            }
            VECTOR_NORMALIZE(&t);

            intersection_facts[intersection_times_counter] = __bounding_axis_test(b1, b2, &t, &intersection_times[intersection_times_counter]);
            intersection_result &= intersection_facts[intersection_times_counter];
            intersection_times_counter++;
        }
    }

    *intersection_time = __get_min_intersection_time(intersection_times, intersection_facts, intersection_times_counter);
    return intersection_result;
}
Beispiel #13
0
int main(void)
{
  system_init();
   
  printf ("\n\n****************************************************************************************************************\n");





  while (1)
  {
   
    frequency_input();

                   // printf ("V_s_an: %6.2f i_s_an: %6.2f psi_s_an: %6.2f hall_angle: %6.2f freq: %6.2f U_d: %6.2f\n", cita_V_s,cita_i_s, vector_angle(psi_sQ,psi_sD), angle_hall1,CUR_FREQ,U_d); 

    //------------------------------------------------------------------------------
    if (print_current==true )
    {
      current_counter=1;
printf ("\n\n****************************************************************************************************************\n");

      while (current_counter<SAMPLES-2)
      {
        //printf("\n %d %6.2f   %6.2f   %6.2f %6.2f   %6.2f   %6.2f ",current_counter,current_data_i_sA[current_counter],current_data_i_sB[current_counter],-current_data_i_sA[current_counter]-current_data_i_sB[current_counter],U_d*switching_data_SA[current_counter],U_d*switching_data_SB[current_counter],U_d*switching_data_SC[current_counter]);


        if (print_selection==0)
        {
          printf (":t:%5d:freq: %6.2f :i_sA: %6.2f :i_sB: %6.2f :i_sD: %6.2f :i_sQ: %6.2f :i_s: %6.2f :cita_i_s: %6.2f :U_d: %6.2f \n",timer[current_counter], data_CUR_FREQ[current_counter],data_i_sA[current_counter],data_i_sB[current_counter],data_i_sD[current_counter],data_i_sQ[current_counter],data_i_s[current_counter],data_cita_i_s[current_counter],data_U_d[current_counter]);
        }
        else if (print_selection==1)
        {
          printf ("freq: %6.2f V_sA: %6.2f V_sB: %6.2f VsC: %6.2f V_sD: %6.2f V_sQ: %6.2f V_s: %6.2f cita_V_s: %6.2f U_d: %6.2f \n", data_CUR_FREQ[current_counter],data_S_A_f[current_counter]*data_U_d[current_counter],data_S_B_f[current_counter]*data_U_d[current_counter],data_S_C_f[current_counter]*data_U_d[current_counter],data_V_sD[current_counter],data_V_sQ[current_counter],data_V_s[current_counter],data_cita_V_s[current_counter],data_U_d[current_counter]);
        }
        else if (print_selection==2)
        {
printf ("t:%5d:f:%6.2f:psi_sD:%9.6f:i_sQ:%6.2f:psi_sQ:%9.6f:i_sD:%6.2f:c_is:%6.2f:psi_an:%6.2f:te:%8.5f:U_d: %5.2f\n", 
timer[current_counter],
data_CUR_FREQ[current_counter],
data_psi_sD[current_counter],
data_i_sQ[current_counter],
data_psi_sQ[current_counter],
data_i_sD[current_counter],
data_cita_i_s[current_counter],
vector_angle(data_psi_sQ[current_counter],data_psi_sD[current_counter]),
data_t_e[current_counter],
data_U_d[current_counter]);
//data_psi_s[current_counter],
//data_psi_alpha[current_counter],

        }
        else if (print_selection==3)
        {
//printf ("t:%5d:f:%6.2f:r:%6.2f:er:%7.2f:tr:%8.4f:te:%8.4f:dt:%2d:pr:%8.6f:ps:%6.4f:pa:%1d:pn:%6.2f:dp:%2d:v:%3d:c:%6.2f",
printf ("t:%5d:f:%6.2f:tr:%8.4f:te:%8.4f:dt:%2d:pr:%8.6f:ps:%6.4f:pa:%1d:pn:%6.2f:dp:%2d:v:%3d:c:%6.2f",
timer[current_counter],
data_CUR_FREQ[current_counter],
data_t_e_ref[current_counter],
data_t_e[current_counter],
data_d_te[current_counter],
data_psi_s_ref[current_counter],
data_psi_s[current_counter],
data_psi_alpha[current_counter],
vector_angle(data_psi_sQ[current_counter],data_psi_sD[current_counter]),
data_d_psi[current_counter],
data_optimal_voltage_vector[current_counter],
data_cita_V_s[current_counter]);
//data_S_A[current_counter],data_S_B[current_counter],data_S_C[current_counter],
//:SA:%1d:SB:%1d:SC:



         printf (":iA:%6.2f:B:%6.2f:D:%6.2f:Q:%6.2f:s:%6.2f:c:%6.2f:U:%6.2f",
data_i_sA[current_counter],data_i_sB[current_counter],data_i_sD[current_counter],data_i_sQ[current_counter],data_i_s[current_counter],data_cita_i_s[current_counter],data_U_d[current_counter]);


         printf (":VA:%6.2f:B:%6.2f:C:%6.2f:D:%6.2f:Q: %6.2f:s:%6.2f:c:%6.2f", 
data_S_A_f[current_counter]*data_U_d[current_counter],data_S_B_f[current_counter]*data_U_d[current_counter],data_S_C_f[current_counter]*data_U_d[current_counter],data_V_sD[current_counter],data_V_sQ[current_counter],data_V_s[current_counter],data_cita_V_s[current_counter]);
        


        printf (":pD:%9.6f:pQ:%9.6f\n", 
data_psi_sD[current_counter],
data_psi_sQ[current_counter]
);
//data_psi_s[current_counter],
//data_psi_alpha[current_counter],

}

 else if (print_selection==4)
        {

          while (PID_angle[current_counter]>(2.0f*PI) )
            PID_angle[current_counter]=PID_angle[current_counter]-2.0*PI;
          float ang_PID=(180.0f/PI)*PID_angle[current_counter];
          if (ang_PID<0.0f)
            ang_PID=ang_PID+360.0f;
          float actual_hall_angle;
          actual_hall_angle=ang_PID*-1.0f;
          if (actual_hall_angle<0.0f)
            actual_hall_angle=actual_hall_angle+360.0f;
          if (actual_hall_angle>360.0f)
            actual_hall_angle=actual_hall_angle-360.0f;
          float diff;
          diff=actual_hall_angle-vector_angle(data_psi_sQ[current_counter],data_psi_sD[current_counter]);
          if (diff<0.0f)
            diff=diff+360.0f;
          if (actual_hall_angle>360.0f)
            diff=diff-360.0f;          

          printf ("Vsa: %6.2f isa: %6.2f psisan: %6.2f ha: %8.2f f: %6.2f Ud: %6.2f t: %5d w_r: %9.2f a_h: %6.2f diff: %6.2f\n", data_cita_V_s[current_counter],data_cita_i_s[current_counter], flux_linkage_angle_psi_s_angle(PID_angle[current_counter]), ang_PID,data_CUR_FREQ[current_counter],data_U_d  [current_counter],timer[current_counter],data_w_r[current_counter]/(2.0f*PI),actual_hall_angle,diff); 

        }


//else 
if (print_selection==5 )//&& data_V_s[current_counter] > 0.0f)
        {
/*
          float angle_delay=0.0f;
	  angle_delay=data_cita_i_s[current_counter]-data_cita_V_s[current_counter];
          if (angle_delay>=360.0f)
            angle_delay=angle_delay-360.0f;
	  else if (angle_delay<0.0f)
            angle_delay=angle_delay+360.0f;

          printf ("V_sD: %6.2f V_sQ: %6.2f V_s: %6.2f cita_V_s: %6.2f i_sD: %6.2f i_sQ: %6.2f i_s: %6.2f cita_i_s: %6.2f  diff: %6.2f\n", data_V_sD[current_counter],data_V_sQ[current_counter],data_V_s[current_counter],data_cita_V_s[current_counter],data_i_sD[current_counter],data_i_sQ[current_counter],data_i_s[current_counter],data_cita_i_s[current_counter],angle_delay);
*/

/*
          printf ("V_sD: %6.2f V_sQ: %6.2f i_sD: %6.2f i_sQ: %6.2f psi_sD: %f psi_sQ: %f psi_s: %6.5f psi_alpha: %2d R_s: %6.3f\n", data_V_sD[current_counter],data_V_sQ[current_counter],data_i_sD[current_counter],data_i_sQ[current_counter],data_psi_sD[current_counter],data_psi_sQ[current_counter],data_psi_s[current_counter],data_psi_alpha[current_counter],data_R_s[current_counter]);
*/
printf (":psi_sD:%9.6f:psi_sQ:%9.6f:psi_s:%6.5f:angle:%6.2f:psi_alpha:%2d:timer:%8d:freq: %6.2f:U_d: %6.2f\n", data_psi_sD[current_counter],data_psi_sQ[current_counter],data_psi_s[current_counter],vector_angle(data_psi_sQ[current_counter],data_psi_sD[current_counter]),data_psi_alpha[current_counter], timer[current_counter], data_CUR_FREQ[current_counter],data_U_d  [current_counter]);

        }

/*
        data_S_A[current_counter]=S_A;
        data_S_B[current_counter]=S_B;
        data_S_C[current_counter]=S_C;

        data_S_A_f[current_counter]=S_A_f;
        data_S_B_f[current_counter]=S_B_f;
        data_S_C_f[current_counter]=S_C_f;

        data_i_sA [current_counter]=i_sA;
        data_i_sB [current_counter]=i_sB;
        data_U_d  [current_counter]=U_d;

        data_i_sD[current_counter]=i_sD;
        data_i_sQ[current_counter]=i_sQ;
        data_i_s[current_counter]=i_s;
        data_cita_i_s[current_counter]=cita_i_s;

        data_V_sD[current_counter];
        data_V_sQ[current_counter];
        data_V_s [current_counter];
        data_cita_V_s[current_counter];

        data_psi_sD[current_counter];
        data_psi_sQ[current_counter];
        data_psi_s [current_counter];
        data_psi_alpha[current_counter];

        data_t_e[current_counter];

        data_psi_s_ref[current_counter];
        data_t_e_ref[current_counter];

        data_d_psi[current_counter];
        data_d_te[current_counter];
        data_psi_delta_percentage[current_counter];
        data_t_e_delta_percentage[current_counter];

        data_R_s[current_counter];
        data_pole_pairs[current_counter;
        data_L_sq[current_counter];
        data_psi_F[current_counter];

*/







        current_counter++;
      }
    
      print_current=false;
      current_counter=0;
    }


/*2
    if (motor_stop==false)
    {

      if (print_selection==0)
      {
        printf ("freq: %6.2f i_sA: %6.2f i_sB: %6.2f i_sD: %6.2f i_sQ: %6.2f i_s: %6.2f cita_i_s: %6.2f U_d: %6.2f \n", CUR_FREQ,i_sA,i_sB,i_sD,i_sQ,i_s,cita_i_s,U_d);
      }
      else if (print_selection==1)
      {
        printf ("freq: %6.2f V_sD: %6.2f V_sQ: %6.2f V_s: %6.2f cita_V_s: %6.2f U_d: %6.2f \n", CUR_FREQ,V_sD,V_sQ,V_s,cita_V_s,U_d);
      }
      else if (print_selection==2)
      {
        printf ("freq: %6.2f psi_sD: %6.2f psi_sQ: %6.2f psi_s: %6.2f psi_alpha: %4d U_d: %6.2f \n", CUR_FREQ,psi_sD,psi_sQ,psi_s,psi_alpha,U_d);
      }
      else if (print_selection==3)
      {
        printf ("freq: %6.2f t_e: %8.2f psi_s_ref: %6.2f t_e_ref: %6.2f d_psi: %4d d_te: %4d psi_delta: %6.2f t_e_delta: %6.2f \n", CUR_FREQ,t_e,psi_s_ref,t_e_ref,d_psi,d_te,psi_delta_percentage,t_e_delta_percentage);
      }
    }
*/



/*
S_A_f
S_B_f
S_C_f

i_sA
i_sB
U_d  

i_sD
i_sQ
i_s
cita_i_s

V_sD
V_sQ
V_s 
cita_V_s

psi_sD
psi_sQ
psi_s
psi_alpha

t_e

psi_s_ref
t_e_ref

d_psi
d_te
psi_delta_percentage
t_e_delta_percentage


//motor parameters;
R_s        
pole_pairs 
L_sq       
psi_F      
*/




    




    if(S_A!=2 && S_B!=2 && S_C!=2)
    {
      //printf ("freq: %6.2f i_sA: %6.2f i_sB: %6.2f U_d: %6.2f\n", CUR_FREQ,i_sA,i_sB,U_d);
    }

  }
}
Beispiel #14
0
int main(int argc, char *argv[]) {
	// Initialize randomness
	srand(time(NULL));
	// 7 parameters are required.
	if (argc != 13) {
		fprintf(stderr, "Usage: %s obj-file sx sy sz tx ty tz rx ry rz focal-dist hiding\n", argv[0]);
		return 0;
	}
	
	unsigned int i, j;

	double sx = atof( argv[2] );
	double sy = atof( argv[3] );
	double sz = atof( argv[4] );
	double tx = atof( argv[5] );
	double ty = atof( argv[6] );
	double tz = atof( argv[7] );
	double rx = atof( argv[8] );
	double ry = atof( argv[9] );
	double rz = atof( argv[10] );
	double fd = atof( argv[11] );

	int hiding = atoi( argv[12] );

	matrix_double scale = scale_by(sx, sy, sz);
	matrix_double tras = traslate(tx, ty, tz);
	matrix_double rot = rotate(rx, ry, rz);
	matrix_double proj = projection(fd);
	
	file_data vnf = readobj(argv[1]);

	// int p;
	// for (p = 0; p < vnf.vertices.num_elems; p++) {
	// 	point3d t = (vnf.vertices.data)[p];
	// 	fprintf(stderr, "(%f,%f,%f)\n", t.x, t.y, t.z);
	// }

	// Join all the transformations in a single matrix
	// Operation order: Scaling, rotation, traslation and projection
	matrix_double t1 = product(proj, tras);
	matrix_double t2 = product(t1, rot);
	matrix_double t3 = product(t2, scale);

	apply_matrix(t3, vnf.vertices);
		
	dispose_matrix(&t3);
	dispose_matrix(&t2);
	dispose_matrix(&t1);
	dispose_matrix(&scale);
	dispose_matrix(&tras);
	dispose_matrix(&rot);
	dispose_matrix(&proj);

	// Projection sets w = z, so divide everything by w.
	for (i = 0; i < vnf.vertices.num_elems; i++) {
		point3d tmp = (vnf.vertices.data)[i];
		tmp.x /= tmp.w;
		tmp.y /= tmp.w;
		tmp.z /= tmp.w;
		(vnf.vertices.data)[i] = tmp;
	}

	// The camera normal (taking advantage of perspective projection)
	vector camera_normal = new_vector( new_point3d(0.0, 0.0, 0.0, 1.0), new_point3d(0.0, 0.0, 1.0, 1.0) );

	// The z-buffer
	double **zbuf = calloc(HEIGHT, sizeof *zbuf);
	for (i = 0; i < HEIGHT; i++) {
		zbuf[i] = calloc(WIDTH, sizeof **zbuf);
		for (j = 0; j < WIDTH; j++)
			zbuf[i][j] = DBL_MAX;
	}
	
	color c = new_color( 255, 255, 255 );

	point center = { WIDTH >> 1, HEIGHT >> 1 };
	int invertX = 0, invertY = 1;
	
	raster tmp = new_raster(WIDTH, HEIGHT, 3);
	for (i = 0; i < vnf.faces.num_elems; i++) {
		point3d v1 = (vnf.vertices.data)[((vnf.faces.data)[i].v1) - 1];
		point3d v2 = (vnf.vertices.data)[((vnf.faces.data)[i].v2) - 1];
		point3d v3 = (vnf.vertices.data)[((vnf.faces.data)[i].v3) - 1];

		point pt[3] = { new_point(v1.x, v1.y), new_point(v2.x, v2.y), new_point(v3.x, v3.y) };

		for (j = 0; j < 3; j++)
			pt[j] = raster_translate(pt[j], center, invertX, invertY);

		// Hiding faces using face normals
		if (hiding == 1) {			
			vector va = new_vector( v1, v2 );
			vector vb = new_vector( v1, v3 );

			vector vn = vector_crossproduct( va, vb );

			if ( abs(vector_angle(vn, camera_normal)) < 90.0 ) continue;
		}

		// Drawing the face
		for (j = 0; j < 3; j++) {

			int curr = j;
			int next = (j+1) % 3;

			point ps = pt[curr];
			point pe = pt[next];

			// Use z-buffering if allowed
			// if (hiding == 2)
			// 	put_line_z(tmp, new_line( ps, pe ), c, bresenham, zbuf, vertices[3][curr], vertices[3][next]);
			// else
			put_line(tmp, new_line( ps, pe ), c, bresenham);
			
		}

		// Filling the face using a random, eye-pleasing colour
		color cr = { ((rand() % 255) + 255) >> 1, ((rand() % 255) + 255) >> 1, ((rand() % 255) + 255) >> 1 };
		// if (hiding == 2)
		// 	fill_face_z(tmp, pt[0], pt[1], pt[2], cr, zbuf, vertices[3][j], vertices[3][(j+1) % 3]);
		// elseelse
			fill_face(tmp, pt[0], pt[1], pt[2], cr);

	}
	raster_out(tmp);
	dispose_raster(tmp);

	for (i = 0; i < HEIGHT; i++) free(zbuf[i]);
	free(zbuf);

	free(vnf.vertices.data);
	free(vnf.faces.data);

	return 0;
}
Beispiel #15
0
static void
tick_camera (ModeInfo *mi, camera *c)
{
  camera_configuration *bp = &bps[MI_SCREEN(mi)];

  GLfloat X, Y, Z;
  set_camera_focus (mi, c);

  X = c->focus.x - c->pos.x;
  Y = c->focus.y - c->pos.y;
  Z = c->focus.z - c->pos.z - BEAM_ZOFF;

  if (X != 0 || Y != 0)
    {
      GLfloat ofacing = c->facing;
      GLfloat opitch  = c->pitch;

      GLfloat target_facing = atan2 (X, Y) * (180 / M_PI);
      GLfloat target_pitch  = atan2 (Z, sqrt(X*X + Y*Y)) * (180 / M_PI);

      /* Adjust the current velocity.
         If we are nearing the target, slow down (but don't stop).
         Otherwise, speed up (but don't break the speed limit).
       */
      {
        GLfloat accel = 0.5 * speed_arg;
        GLfloat decel_range = 20;
        GLfloat max_velocity = 5 * speed_arg;
        GLfloat close_enough = 0.5 * speed_arg;

        GLfloat dx = target_facing - c->facing;
        GLfloat dy = target_pitch  - c->pitch;
        GLfloat angular_distance = sqrt (dx*dx + dy*dy);

        /* Split the velocity into vx and vy components.  This isn't
           quite right since this treats them as Cartesian rather than
           polar, but it's close enough.
         */
        GLfloat r = (dx == 0) ? 1 : ABS(dy) / ABS(dx);
        GLfloat vx = 1-r;
        GLfloat vy = r;

        if (angular_distance < decel_range)  /* Nearing target, slow down */
          {
            c->velocity -= accel;
            if (c->velocity <= 0)
              c->velocity = accel;
          }
        else
          {
            c->velocity += accel;
            if (c->velocity > max_velocity)
              c->velocity = max_velocity;
          }

        /* Don't overshoot */
        if (vx > ABS(dx)) vx = ABS(dx);
        if (vy > ABS(dy)) vy = ABS(dy);


        /* Rotate toward target by current angular velocity. */
        c->facing += vx * c->velocity * (target_facing > c->facing ? 1 : -1);
        c->pitch  += vy * c->velocity * (target_pitch  > c->pitch  ? 1 : -1);

        /* If we are pointed *really close* to the target, just lock on,
           to avoid twitchy overshoot rounding errors.
         */
        if (angular_distance < close_enough)
          {
            c->facing = target_facing;
            c->pitch  = target_pitch;
          }

        /* Constrain to hinge's range of motion */
        c->facing = MAX (-90, MIN (90, c->facing));
        c->pitch  = MAX (-90, MIN (55, c->pitch));

        /* After this motion, our prevailing velocity (for next time)
           is the angular distance we actually moved.
         */
        dx = c->facing - ofacing;
        dy = c->pitch  - opitch;
        c->velocity = sqrt (dx*dx + dy*dy);
      }
    }

# ifdef DEBUG
  if (debug_p && 1)
    /* Mark the point on which this camera is focusing. */
    {
      glPushMatrix();
      glDisable (GL_LIGHTING);
      glColor3f(0.3, 0.3, 0.3);
      glBegin (GL_LINES);
      glVertex3f (c->pos.x,   c->pos.y,   c->pos.z + BEAM_ZOFF);
      glVertex3f (c->focus.x, c->focus.y, c->focus.z);
      glEnd();
      glColor3f(1,1,1);
      glBegin (GL_LINES);
      glVertex3f (c->focus.x-0.25, c->focus.y, c->focus.z);
      glVertex3f (c->focus.x+0.25, c->focus.y, c->focus.z);
      glVertex3f (c->focus.x, c->focus.y-0.25, c->focus.z);
      glVertex3f (c->focus.x, c->focus.y+0.25, c->focus.z);
      glVertex3f (c->focus.x, c->focus.y, c->focus.z-0.25);
      glVertex3f (c->focus.x, c->focus.y, c->focus.z+0.25);
      glEnd();
      if (!MI_IS_WIREFRAME(mi))
        glEnable (GL_LIGHTING);
      glPopMatrix();
    }
# endif

  /* If this camera is looking at another camera, get shy and look away
     if the target sees us looking.
   */
  if (c->focus_id < 0)
    {
      camera *c2 = &bp->cameras[-1 - c->focus_id];
      XYZ a, b;
      GLfloat aa = c->facing / (180 / M_PI);
      GLfloat bb = c->pitch  / (180 / M_PI);
      GLfloat angle;

      a.y = cos(aa)* cos(bb);
      a.x = sin(aa)* cos(bb);
      a.z = sin(bb);

      aa = c2->facing / (180 / M_PI);
      bb = c2->pitch  / (180 / M_PI);
      b.y = cos(aa)* cos(bb);
      b.x = sin(aa)* cos(bb);
      b.z = sin(bb);

      angle = vector_angle (normalize(a), normalize(b)) * (180 / M_PI);

      if (angle > 100)
        {
          c->focus_id = 0;
          /* Look "away" which means in the same direction. */
          c->focus.x = c->pos.x + (c2->focus.x - c2->pos.x);
          c->focus.y = c->pos.y + (c2->focus.y - c2->pos.y);
          c->focus.z = c->pos.z + (c2->focus.z - c2->pos.z);
          /* Look at either the sky or the ground.*/
          c->focus.z = c->focus.x * (random() & 1 ? 1 : -1) * 5;
          c->velocity = c2->velocity * 3;
        }
    }


  /* Randomly pick some other things to look at.
   */

  if (c->state == IDLE &&
      (c->focus_id <= 0
       ? !(random() % (int) MAX (1, (50 / speed_arg)))
       : !(random() % (int) MAX (1, (1000 / speed_arg)))))
    {

      /* Shiny! Start paying attention to something else. */

      if ((bp->ncameras > 1 && !(random() % 20)))	/* look at a camera */
        {
          int which = random() % 4;
          long i;
          for (i = 0; i < bp->ncameras; i++)
            if (c == &bp->cameras[i])
              break;

          /* Look at cameras 1 or 2 away in each direction, but not farther.
             Since we arrange them in 2 staggered lines, those are the only
             four that are in line of sight.
           */
          if (i >= 2 && which == 0)
            which = i-2;
          else if (i >= 1 && which == 1)
            which = i-1;
          else if (i < bp->ncameras-1 && which == 2)
            which = i+2;
          else /* (i < bp->ncameras-2 && which == 3) */
            which = i+1;

          c->focus_id = -1 - which;
        }
      else					/* look at a pedestrian */
        {
          int n = 0;
          pedestrian *p;
          for (p = bp->pedestrians; p; p = p->next)
            n++;
          if (n > 0)
            {
              n = random() % n;
              p = bp->pedestrians;
              while (n > 0 && p)
                p = p->next;
              if (p)
                c->focus_id = p->id;
            }
        }
    }

  /* Run the animation */

  if (c->state != IDLE)
    {
      pedestrian *p = bp->pedestrians; /* first one */
      if (p) c->focus_id = p->id;

      switch (c->state) {
      case WARM_UP:   c->tick -= 0.01 * speed_arg; break;
      case ZOT:       c->tick -= 0.006 * speed_arg; 
        if (p) p->speed *= 0.995;  /* target takes 1d6 HP damage */
        break;
      case COOL_DOWN: c->tick -= 0.02 * speed_arg; break;
      default: abort(); break;
      }

      if (c->tick <= 0)
        {
          c->tick = 1.0;
          switch (c->state) {
          case WARM_UP:   c->state = ZOT; break;
          case ZOT:       c->state = COOL_DOWN;
            c->focus_id = 0;
            if (p) p->ratio = 1.0;  /* threat eliminated */
            break;
          case COOL_DOWN: c->state = IDLE; break;
          default: abort(); break;
          }
        }
    }

  if (bp->cameras[0].state == IDLE &&
      bp->pedestrians &&
      bp->pedestrians[0].ratio < 0.3 &&
      !(random() % MAX (1, (int) (50000 / speed_arg))))
    {
      /* CASE NIGHTMARE RED detected, engage SCORPION STARE by authority
         of MAGINOT BLUE STARS. */
      int i;
      for (i = 0; i < bp->ncameras; i++)
        {
          bp->cameras[i].state = WARM_UP;
          bp->cameras[i].tick  = 1.0;
        }
    }
}
Beispiel #16
0
static void
build_ball (ModeInfo *mi)
{
  ball_configuration *bp = &bps[MI_SCREEN(mi)];
  int rows = MI_COUNT (mi);

  GLfloat tile_size = M_PI / rows;
  GLfloat th0, th1;

  struct { XYZ position; GLfloat strength; } dents[5];
  int dent_count = random() % countof(dents);
  int i;
  for (i = 0; i < dent_count; i++)
    {
      GLfloat dist;
      dents[i].position.x = RANDSIGN() * (2 - BELLRAND(0.2));
      dents[i].position.y = RANDSIGN() * (2 - BELLRAND(0.2));
      dents[i].position.z = RANDSIGN() * (2 - BELLRAND(0.2));
      dist = sqrt (dents[i].position.x * dents[i].position.x +
                   dents[i].position.y * dents[i].position.y +
                   dents[i].position.z * dents[i].position.z);
      dents[i].strength = dist - (1 - BELLRAND(0.3));
      dents[i].strength = dist - (1 - BELLRAND(0.3));
    }


  for (th1 = M_PI/2; th1 > -(M_PI/2 + tile_size/2); th1 -= tile_size)
    {
      GLfloat x  = cos (th1);
      GLfloat y  = sin (th1);
      GLfloat x0 = cos (th1 - tile_size/2);
      GLfloat x1 = cos (th1 + tile_size/2);
      GLfloat circ0 = M_PI * x0 * 2;
      GLfloat circ1 = M_PI * x1 * 2;
      GLfloat circ  = (circ0 < circ1 ? circ0 : circ1);
      int row_tiles = floor ((circ < 0 ? 0 : circ) / tile_size);
      GLfloat spacing;
      GLfloat dropsy = 0.13 + frand(0.04);

      if (row_tiles <= 0) row_tiles = 1;
      spacing = M_PI*2 / row_tiles;

      for (th0 = 0; th0 < M_PI*2; th0 += spacing)
        {
          tile *t = (tile *) calloc (1, sizeof(*t));
          t->size = tile_size * 0.85;
          t->position.x = cos (th0) * x;
          t->position.y = sin (th0) * x;
          t->position.z = y;

          t->normal = t->position;

          /* Apply pressure on position from the dents. */
          for (i = 0; i < dent_count; i++)
            {
              GLfloat dist;
              XYZ direction;

              if (! (random() % 150))	/* Drop tiles randomly */
                {
                  free (t);
                  goto SKIP;
                }

              direction.x = t->position.x - dents[i].position.x;
              direction.y = t->position.y - dents[i].position.y;
              direction.z = t->position.z - dents[i].position.z;
              dist = sqrt (direction.x * direction.x +
                           direction.y * direction.y +
                           direction.z * direction.z);
              if (dist < dents[i].strength)
                {
                  GLfloat s = 1 - (dents[i].strength - dist) * 0.66;
                  XYZ n2 = t->normal;
                  GLfloat angle = vector_angle (t->position, dents[i].position);

                  /* Drop out the tiles near the apex of the dent. */
                  if (angle < dropsy)
                    {
                      free (t);
                      goto SKIP;
                    }

                  t->position.x *= s;
                  t->position.y *= s;
                  t->position.z *= s;

                  direction = normalize (direction);
                  n2.x -= direction.x;
                  n2.y -= direction.y;
                  n2.z -= direction.z;

                  t->normal.x = (t->normal.x + n2.x) / 2;
                  t->normal.y = (t->normal.y + n2.y) / 2;
                  t->normal.z = (t->normal.z + n2.z) / 2;
                }
            }

          /* Skew the direction the tile is facing slightly. */
          t->normal.x += 0.12 - frand(0.06);
          t->normal.y += 0.12 - frand(0.06);
          t->normal.z += 0.12 - frand(0.06);
          t->tilt = 4 - BELLRAND(8);

          t->next = bp->tiles;
          bp->tiles = t;
        SKIP: ;
        }
    }

  bp->nrays = 5 + BELLRAND(10);
  bp->rays = (ray *) calloc (bp->nrays, sizeof(*bp->rays));
  for (i = 0; i < bp->nrays; i++)
    {
      GLfloat th = frand(M_PI * 2);
      bp->rays[i].normal.x = cos (th);
      bp->rays[i].normal.y = sin (th);
      bp->rays[i].normal.z = 1;
      bp->rays[i].normal = normalize (bp->rays[i].normal);
      bp->rays[i].color[0] = 0.9 + frand(0.1);
      bp->rays[i].color[1] = 0.6 + frand(0.4);
      bp->rays[i].color[2] = 0.6 + frand(0.2);
      bp->rays[i].color[3] = 1;
    }
}
Beispiel #17
0
static void
make_gasket (logo_configuration *dc, int wire)
{
  int i;
  int points_size;
  int npoints = 0;
  int nctrls = 0;
  int res = 360/8;
  GLfloat d2r = M_PI / 180;

  GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 2;

  GLfloat *pointsx0, *pointsy0, *pointsx1, *pointsy1, *normals;

  GLfloat r0  = 0.780;  /* 395 */
  GLfloat r1a = 0.855;                /* top of wall below upper left hole */
  GLfloat r1b = 0.890;                /* center of upper left hole */
  GLfloat r1c = 0.922;                /* bottom of wall above hole */
  GLfloat r1  = 0.928;  /* 471 */
  GLfloat r2  = 0.966;  /* 490 */
  GLfloat r3  = 0.984;  /* 499 */
  GLfloat r4  = 1.000;  /* 507 */
  GLfloat r5  = 1.090;  /* 553 */

  GLfloat ctrl_r[100], ctrl_th[100];

  glPushMatrix();

# define POINT(r,th) \
    ctrl_r [nctrls] = r, \
    ctrl_th[nctrls] = (th * d2r), \
    nctrls++

  POINT (0.829, 0);      /* top indentation, right half */
  POINT (0.831, 0.85);
  POINT (0.835, 1.81);
  POINT (0.841, 2.65);
  POINT (0.851, 3.30);
  POINT (0.862, 3.81);
  POINT (0.872, 3.95);

  POINT (r4,    4.0);   /* moving clockwise... */
  POINT (r4,   48.2);
  POINT (r1,   48.2);
  POINT (r1,   54.2);
  POINT (r2,   55.8);
  POINT (r2,   73.2);
  POINT (r1,   74.8);
  POINT (r1,  101.2);
  POINT (r3,  103.4);
  POINT (r3,  132.0);
  POINT (r1,  133.4);

  POINT (r1,  180.7);
  POINT (r2,  183.6);
  POINT (r2,  209.8);
  POINT (r1,  211.0);
  POINT (r1,  221.8);
  POINT (r5,  221.8);
  POINT (r5,  223.2);
  POINT (r4,  223.2);

  POINT (r4,  316.8);      /* upper left indentation */
  POINT (0.990, 326.87);
  POINT (0.880, 327.21);
  POINT (0.872, 327.45);
  POINT (0.869, 327.80);
  POINT (0.867, 328.10);

  POINT (0.867, 328.85);
  POINT (0.869, 329.15);
  POINT (0.872, 329.50);
  POINT (0.880, 329.74);
  POINT (0.990, 330.08);

  POINT (r4,  339.0);
  if (! wire)
    {
      POINT (r1a, 339.0);      /* cut-out disc */
      POINT (r1a, 343.0);
    }
  POINT (r4,  343.0);
  POINT (r4,  356.0);

  POINT (0.872, 356.05);   /* top indentation, left half */
  POINT (0.862, 356.19);
  POINT (0.851, 356.70);
  POINT (0.841, 357.35);
  POINT (0.835, 358.19);
  POINT (0.831, 359.15);
  POINT (0.829, 360);
# undef POINT

  points_size = res + (nctrls * 2);
  pointsx0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
  pointsy0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
  pointsx1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
  pointsy1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
  normals  = (GLfloat *) malloc (points_size * sizeof(GLfloat) * 2);

  npoints = 0;
  for (i = 1; i < nctrls; i++)
    {
      GLfloat from_r  = ctrl_r [i-1];
      GLfloat from_th = ctrl_th[i-1];
      GLfloat to_r    = ctrl_r [i];
      GLfloat to_th   = ctrl_th[i];

      GLfloat step = 2*M_PI / res;
      int nsteps = 1 + ((to_th - from_th) / step);
      int j;

      for (j = 0; j < nsteps + (i == nctrls-1); j++)
        {
          GLfloat r  = from_r  + (j * (to_r  - from_r)  / nsteps);
          GLfloat th = from_th + (j * (to_th - from_th) / nsteps);

          GLfloat cth = cos(th) * dc->gasket_size;
          GLfloat sth = sin(th) * dc->gasket_size;

          pointsx0[npoints] = r0 * cth;  /* inner ring */
          pointsy0[npoints] = r0 * sth;
          pointsx1[npoints] = r  * cth;  /* outer ring */
          pointsy1[npoints] = r  * sth;
          npoints++;

          if (npoints >= points_size) abort();
        }
    }

  /* normals for the outer ring */
  for (i = 1; i < npoints; i++)
    {
      XYZ a, b, c, n;
      a.x = pointsx1[i-1];
      a.y = pointsy1[i-1];
      a.z = 0;
      b.x = pointsx1[i];
      b.y = pointsy1[i];
      b.z = 0;
      c = b;
      c.z = 1;
      n = calc_normal (a, b, c);
      normals[(i-1)*2  ] = n.x;
      normals[(i-1)*2+1] = n.y;
    }

  glRotatef(-90, 0, 1, 0);
  glRotatef(180, 0, 0, 1);

  if (wire)
    {
      GLfloat z;
      for (z = -thick2; z <= thick2; z += thick2*2)
        {
# if 1
          /* inside edge */
          glBegin (GL_LINE_LOOP);
          for (i = 0; i < npoints; i++)
            glVertex3f (pointsx0[i], pointsy0[i], z);
          glEnd();

          /* outside edge */
          glBegin (GL_LINE_LOOP);
          for (i = 0; i < npoints; i++)
            glVertex3f (pointsx1[i], pointsy1[i], z);
          glEnd();
# else
          for (i = 1; i < npoints; i++)
            {
              glBegin (GL_LINE_STRIP);
              glVertex3f (pointsx0[i-1], pointsy0[i-1], z);
              glVertex3f (pointsx0[i  ], pointsy0[i  ], z);
              glVertex3f (pointsx1[i  ], pointsy1[i  ], z);
              glVertex3f (pointsx1[i-1], pointsy1[i-1], z);
              glEnd();
            }
# endif
        }
#if 1
      glBegin (GL_LINES);
      for (i = 0; i < npoints; i++)
        {
          /* inside rim */
          glVertex3f (pointsx0[i], pointsy0[i], -thick2);
          glVertex3f (pointsx0[i], pointsy0[i],  thick2);
          /* outside rim */
          glVertex3f (pointsx1[i], pointsy1[i], -thick2);
          glVertex3f (pointsx1[i], pointsy1[i],  thick2);
        }
      glEnd();
#endif
    }
  else
    {
      /* top */
      glFrontFace(GL_CW);
      glNormal3f(0, 0, -1);
      glBegin (GL_QUAD_STRIP);
      for (i = 0; i < npoints; i++)
        {
          glVertex3f (pointsx0[i], pointsy0[i], -thick2);
          glVertex3f (pointsx1[i], pointsy1[i], -thick2);
        }
      glEnd();

      /* bottom */
      glFrontFace(GL_CCW);
      glNormal3f(0, 0, 1);
      glBegin (GL_QUAD_STRIP);
      for (i = 0; i < npoints; i++)
        {
          glVertex3f (pointsx0[i], pointsy0[i], thick2);
          glVertex3f (pointsx1[i], pointsy1[i], thick2);
        }
      glEnd();

      /* inside edge */
      glFrontFace(GL_CW);
      glBegin (GL_QUAD_STRIP);
      for (i = 0; i < npoints; i++)
        {
          glNormal3f (-pointsx0[i], -pointsy0[i],  0);
          glVertex3f ( pointsx0[i],  pointsy0[i],  thick2);
          glVertex3f ( pointsx0[i],  pointsy0[i], -thick2);
        }
      glEnd();

      /* outside edge */
      glFrontFace(GL_CCW);
      glBegin (GL_QUADS);
      {
        for (i = 0; i < npoints-1; i++)
          {
            int ia = (i == 0 ? npoints-2 : i-1);
            int iz = (i == npoints-2 ? 0 : i+1);
            GLfloat  x = pointsx1[i];
            GLfloat  y = pointsy1[i];
            GLfloat xz = pointsx1[iz];
            GLfloat yz = pointsy1[iz];

            GLfloat nxa = normals[ia*2];   /* normal of [i-1 - i] face */
            GLfloat nya = normals[ia*2+1];
            GLfloat nx  = normals[i*2];    /* normal of [i - i+1] face */
            GLfloat ny  = normals[i*2+1];
            GLfloat nxz = normals[iz*2];    /* normal of [i+1 - i+2] face */
            GLfloat nyz = normals[iz*2+1];

            GLfloat anglea = vector_angle (nx, ny, 0, nxa, nya, 0);
            GLfloat anglez = vector_angle (nx, ny, 0, nxz, nyz, 0);
            GLfloat pointy = 0.005;

            if (anglea > pointy)
              {
                glNormal3f (nx, ny, 0);
                glVertex3f (x,  y,   thick2);
                glVertex3f (x,  y,  -thick2);
              }
            else
              {
                glNormal3f ((nxa + nx) / 2, (nya + ny) / 2, 0);
                glVertex3f (x,  y,   thick2);
                glVertex3f (x,  y,  -thick2);
              }

            if (anglez > pointy)
              {
                glNormal3f (nx, ny, 0);
                glVertex3f (xz, yz, -thick2);
                glVertex3f (xz, yz,  thick2);
              }
            else
              {
                glNormal3f ((nx + nxz) / 2, (ny + nyz) / 2, 0);
                glVertex3f (xz, yz, -thick2);
                glVertex3f (xz, yz,  thick2);
              }
          }
      }
      glEnd();
    }

  /* Fill in the upper left hole...
   */
  {
    GLfloat th;
    npoints = 0;

    th = 339.0 * d2r;
    pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
    pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
    npoints++;
    pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
    pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
    npoints++;

    th = 343.0 * d2r;
    pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
    pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
    npoints++;
    pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
    pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
    npoints++;

    if (! wire)
      {
        /* front wall */
        glNormal3f (0, 0, -1);
        glFrontFace(GL_CW);
        glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
        glVertex3f (pointsx0[0], pointsy0[0], -thick2);
        glVertex3f (pointsx0[1], pointsy0[1], -thick2);
        glVertex3f (pointsx0[3], pointsy0[3], -thick2);
        glVertex3f (pointsx0[2], pointsy0[2], -thick2);
        glEnd();

        /* back wall */
        glNormal3f (0, 0, 1);
        glFrontFace(GL_CCW);
        glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
        glVertex3f (pointsx0[0], pointsy0[0],  thick2);
        glVertex3f (pointsx0[1], pointsy0[1],  thick2);
        glVertex3f (pointsx0[3], pointsy0[3],  thick2);
        glVertex3f (pointsx0[2], pointsy0[2],  thick2);
        glEnd();
      }

    /* top wall */
    glFrontFace(GL_CW);
    glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
    glNormal3f (pointsx0[1], pointsy0[1], 0);
    glVertex3f (pointsx0[1], pointsy0[1],  thick2);
    glNormal3f (pointsx0[3], pointsy0[3], 0);
    glVertex3f (pointsx0[3], pointsy0[3],  thick2);
    glVertex3f (pointsx0[3], pointsy0[3], -thick2);
    glNormal3f (pointsx0[1], pointsy0[1], 0);
    glVertex3f (pointsx0[1], pointsy0[1], -thick2);
    glEnd();


    /* Now make a donut.
     */
    {
      int nsteps = 12;
      GLfloat r0 = 0.026;
      GLfloat r1 = 0.060;
      GLfloat th, cth, sth;

      glPushMatrix ();

      th = ((339.0 + 343.0) / 2) * d2r;
      
      glTranslatef (r1b * cos(th) * dc->gasket_size,
                    r1b * sin(th) * dc->gasket_size,
                    0);

      npoints = 0;
      for (i = 0; i < nsteps; i++)
        {
          th = 2 * M_PI * i / nsteps;
          cth = cos (th) * dc->gasket_size;
          sth = sin (th) * dc->gasket_size;
          pointsx0[npoints] = r0 * cth;
          pointsy0[npoints] = r0 * sth;
          pointsx1[npoints] = r1 * cth;
          pointsy1[npoints] = r1 * sth;
          npoints++;
        }

      pointsx0[npoints] = pointsx0[0];
      pointsy0[npoints] = pointsy0[0];
      pointsx1[npoints] = pointsx1[0];
      pointsy1[npoints] = pointsy1[0];
      npoints++;

      if (wire)
        {
          glBegin (GL_LINE_LOOP);
          for (i = 0; i < npoints; i++)
            glVertex3f (pointsx0[i], pointsy0[i], -thick2);
          glEnd();
          glBegin (GL_LINE_LOOP);
          for (i = 0; i < npoints; i++)
            glVertex3f (pointsx0[i], pointsy0[i],  thick2);
          glEnd();
# if 0
          glBegin (GL_LINE_LOOP);
          for (i = 0; i < npoints; i++)
            glVertex3f (pointsx1[i], pointsy1[i], -thick2);
          glEnd();
          glBegin (GL_LINE_LOOP);
          for (i = 0; i < npoints; i++)
            glVertex3f (pointsx1[i], pointsy1[i],  thick2);
          glEnd();
# endif
        }
      else
        {
          /* top */
          glFrontFace(GL_CW);
          glNormal3f(0, 0, -1);
          glBegin (GL_QUAD_STRIP);
          for (i = 0; i < npoints; i++)
            {
              glVertex3f (pointsx0[i], pointsy0[i], -thick2);
              glVertex3f (pointsx1[i], pointsy1[i], -thick2);
            }
          glEnd();

          /* bottom */
          glFrontFace(GL_CCW);
          glNormal3f(0, 0, 1);
          glBegin (GL_QUAD_STRIP);
          for (i = 0; i < npoints; i++)
            {
              glVertex3f (pointsx0[i], pointsy0[i],  thick2);
              glVertex3f (pointsx1[i], pointsy1[i],  thick2);
            }
          glEnd();
        }

      /* inside edge */
      glFrontFace(GL_CW);
      glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
      for (i = 0; i < npoints; i++)
        {
          glNormal3f (-pointsx0[i], -pointsy0[i],  0);
          glVertex3f ( pointsx0[i],  pointsy0[i],  thick2);
          glVertex3f ( pointsx0[i],  pointsy0[i], -thick2);
        }
      glEnd();

      glPopMatrix();
    }
  }


  /* Attach the bottom-right dingus...
   */
  {
    GLfloat w = 0.04;
    GLfloat h = 0.17;
    GLfloat th;

    glRotatef (50, 0, 0, 1);
    glScalef (dc->gasket_size, dc->gasket_size, 1);
    glTranslatef (0, (r0+r1)/2, 0);

    /* buried box */
    if (! wire)
      {
        glFrontFace(GL_CCW);
        glBegin (wire ? GL_LINE_STRIP : GL_QUADS);
        glNormal3f (0, 0, -1);
        glVertex3f (-w/2, -h/2, -thick2); glVertex3f (-w/2,  h/2, -thick2);
        glVertex3f ( w/2,  h/2, -thick2); glVertex3f ( w/2, -h/2, -thick2);
        glNormal3f (1, 0, 0);
        glVertex3f ( w/2, -h/2, -thick2); glVertex3f ( w/2,  h/2, -thick2);
        glVertex3f ( w/2,  h/2,  thick2); glVertex3f ( w/2, -h/2,  thick2);
        glNormal3f (0, 0, 1);
        glVertex3f ( w/2, -h/2,  thick2); glVertex3f ( w/2,  h/2,  thick2);
        glVertex3f (-w/2,  h/2,  thick2); glVertex3f (-w/2, -h/2,  thick2);
        glNormal3f (-1, 0, 0);
        glVertex3f (-w/2, -h/2,  thick2); glVertex3f (-w/2,  h/2,  thick2);
        glVertex3f (-w/2,  h/2, -thick2); glVertex3f (-w/2, -h/2, -thick2);
        glEnd();
      }

    npoints = 0;
    for (th = 0; th < M_PI; th += (M_PI / 6))
      {
        pointsx0[npoints] = w/2 * cos(th);
        pointsy0[npoints] = w/2 * sin(th);
        npoints++;
      }

    /* front inside curve */
    glNormal3f (0, 0, -1);
    glFrontFace(GL_CW);
    glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
    if (! wire) glVertex3f (0, h/2, -thick2);
    for (i = 0; i < npoints; i++)
      glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
    glEnd();

    /* front outside curve */
    glFrontFace(GL_CCW);
    glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
    if (! wire) glVertex3f (0, -h/2, -thick2);
    for (i = 0; i < npoints; i++)
      glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
    glEnd();

    /* back inside curve */
    glNormal3f (0, 0, 1);
    glFrontFace(GL_CCW);
    glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
    if (! wire) glVertex3f (0, h/2, thick2);
    for (i = 0; i < npoints; i++)
      glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
    glEnd();

    /* back outside curve */
    glFrontFace(GL_CW);
    glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
    if (! wire) glVertex3f (0, -h/2, thick2);
    for (i = 0; i < npoints; i++)
      glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
    glEnd();

    /* inside curve */
    glFrontFace(GL_CCW);
    glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
    for (i = 0; i < npoints; i++)
      {
        glNormal3f (pointsx0[i], pointsy0[i], 0);
        glVertex3f (pointsx0[i], h/2 + pointsy0[i],  thick2);
        glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
      }
    glEnd();

    /* outside curve */
    glFrontFace(GL_CW);
    glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
    for (i = 0; i < npoints; i++)
      {
        glNormal3f (pointsx0[i], -pointsy0[i], 0);
        glVertex3f (pointsx0[i], -h/2 - pointsy0[i],  thick2);
        glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
      }
    glEnd();
  }

  free (pointsx0);
  free (pointsy0);
  free (pointsx1);
  free (pointsy1);
  free (normals);

  glPopMatrix();
}