void triangle_update(triangle_t* triangle) { v3_sub(&triangle->edge1, &triangle->v1, &triangle->v0); v3_sub(&triangle->edge2, &triangle->v2, &triangle->v0); v3_cross(&triangle->normal, &triangle->edge1, &triangle->edge2); v3_normalize(&triangle->normal); }
void scotland_update() { camera* cam = entity_get("camera"); light* sun = entity_get("sun"); static_object* skydome = entity_get("skydome"); landscape* world = entity_get("world"); sun_orbit += frame_time() * 0.01; sun->position.x = 512 + sin(sun_orbit) * 512; sun->position.y = cos(sun_orbit) * 512; sun->position.z = 512; sun->target = v3(512, 0, 512); if (w_held || s_held) { vector3 cam_dir = v3_normalize(v3_sub(cam->target, cam->position)); float speed = 0.5; if (!freecam) speed = 0.05; if (w_held) { cam->position = v3_add(cam->position, v3_mul(cam_dir, speed)); } if (s_held) { cam->position = v3_sub(cam->position, v3_mul(cam_dir, speed)); } if (!freecam) { float height = terrain_height(world->terrain, v2(cam->position.x, cam->position.z)); cam->position.y = height + 1; } cam->target = v3_add(cam->position, cam_dir); } Uint8 keystate = SDL_GetMouseState(NULL, NULL); if(keystate & SDL_BUTTON(1)){ float a1 = -(float)mouse_x * 0.005; float a2 = (float)mouse_y * 0.005; vector3 cam_dir = v3_normalize(v3_sub(cam->target, cam->position)); cam_dir.y += -a2; vector3 side_dir = v3_normalize(v3_cross(cam_dir, v3(0,1,0))); cam_dir = v3_add(cam_dir, v3_mul(side_dir, -a1)); cam_dir = v3_normalize(cam_dir); cam->target = v3_add(cam->position, cam_dir); } mouse_x = 0; mouse_y = 0; ui_button* framerate = ui_elem_get("framerate"); ui_button_set_label(framerate, frame_rate_string()); }
hit_test intersect(ray r, object obj) { v3 ro = r.origin; v3 rd = r.direction; double t; hit_test ht_out; switch (obj.tag) { case SPHERE: { v3 sc = obj.o.s.center; double sr = obj.o.s.radius; v3 A = v3_sub(ro, sc); double B = v3_dot(A, rd); double C = v3_dot(A, A) - sr*sr; double D = B*B - C; t = -B - sqrt(D); if (D > 0 && t > 0) { v3 ray_pos = ray_position(r, t); ht_out.miss = HIT; ht_out.t = t; ht_out.hit_point = ray_pos; ht_out.surf = \ (*(obj.o.s.surface_color))(obj.o.s.center, ray_pos); ht_out.shine = obj.o.s.shine; ht_out.surf_norm = v3_norm(v3_sub(ray_pos, obj.o.s.center)); } else { ht_out.miss = MISS; } break; } case POSTER: { v3 n = v3_expr(0, 0, -1); double d = obj.o.p.upper_left.z; t = -(v3_dot(ro, n) + d) / v3_dot(rd, n); v3 ray_pos = ray_position(r, t); if (t > 0 && is_on_poster(ray_pos, obj.o.p)) { ht_out.miss = HIT; ht_out.t = t; ht_out.hit_point = ray_pos; ht_out.surf = \ (*(obj.o.p.surface_color))(obj.o.p.upper_left, ray_pos); ht_out.shine = obj.o.p.shine; ht_out.surf_norm = n; } else { ht_out.miss = MISS; } break; } default: fprintf(stderr, "error in intersect: unrecognized tag\n"); exit(1); } return ht_out; }
void sea_update() { camera* cam = entity_get("camera"); light* sun = entity_get("sun"); wave_time += frame_time(); static_object* corvette = entity_get("corvette"); corvette->position.y = (sin(wave_time) + 1) / 2; corvette->rotation = v4_quaternion_pitch(sin(wave_time * 1.123) / 50); corvette->rotation = v4_quaternion_mul(corvette->rotation, v4_quaternion_yaw(sin(wave_time * 1.254) / 25)); corvette->rotation = v4_quaternion_mul(corvette->rotation, v4_quaternion_roll(sin(wave_time * 1.355) / 100)); static_object* center_sphere = entity_get("center_sphere"); physics_object* balls[100]; int num_balls; entities_get(balls, &num_balls, physics_object); for(int i = 0; i < num_balls; i++) { physics_object_collide_static(balls[i], center_sphere, frame_time()); physics_object_collide_static(balls[i], corvette, frame_time()); physics_object_update(balls[i], frame_time()); } Uint8 keystate = SDL_GetMouseState(NULL, NULL); if(keystate & SDL_BUTTON(1)) { float a1 = -(float)mouse_x * 0.01; float a2 = (float)mouse_y * 0.01; cam->position = v3_sub(cam->position, cam->target); cam->position = m33_mul_v3(m33_rotation_y( a1 ), cam->position ); cam->position = v3_add(cam->position, cam->target); cam->position = v3_sub(cam->position, cam->target); vector3 rotation_axis = v3_normalize(v3_cross( v3_sub(cam->position, v3_zero()) , v3(0,1,0) )); cam->position = m33_mul_v3(m33_rotation_axis_angle(rotation_axis, a2 ), cam->position ); cam->position = v3_add(cam->position, cam->target); } if(keystate & SDL_BUTTON(3)) { sun->position.x += (float)mouse_y / 2; sun->position.z -= (float)mouse_x / 2; } mouse_x = 0; mouse_y = 0; ui_button* framerate = ui_elem_get("framerate"); ui_button_set_label(framerate, frame_rate_string()); }
static void toggle_freecam(ui_button* b, SDL_Event event) { if (event.type == SDL_MOUSEBUTTONDOWN) { if (ui_button_contains_position(b, v2(event.motion.x, event.motion.y))) { b->pressed = true; } } else if (event.type == SDL_MOUSEBUTTONUP) { if (b->pressed) { b->pressed = false; freecam = !freecam; camera* cam = entity_get("camera"); landscape* world = entity_get("world"); vector3 cam_dir = v3_normalize(v3_sub(cam->target, cam->position)); float height = terrain_height(world->terrain, v2(cam->position.x, cam->position.z)); cam->position.y = height + 1; cam->target = v3_add(cam->position, cam_dir); } } }
vec3_t get_mouse_hit(float x, float y) { double mv[16], proj[16]; int vp[4]; double res_x, res_y, res_z; float t; vec3_t res, pnear, pfar; glGetDoublev(GL_MODELVIEW_MATRIX, mv); glGetDoublev(GL_PROJECTION_MATRIX, proj); glGetIntegerv(GL_VIEWPORT, vp); y = vp[3] - y; gluUnProject(x, y, 0, mv, proj, vp, &res_x, &res_y, &res_z); pnear.x = res_x; pnear.y = res_y; pnear.z = res_z; gluUnProject(x, y, 1, mv, proj, vp, &res_x, &res_y, &res_z); pfar.x = res_x; pfar.y = res_y; pfar.z = res_z; t = fabs(pnear.z) / fabs(pfar.z - pnear.z); res = v3_add(pnear, v3_scale(v3_sub(pfar, pnear), t)); return res; }
v3_t FindRobustMean(const std::vector<v3_t> &points) { int num_points = (int) points.size(); double best_sum = DBL_MAX; int best_idx = -1; for (int i = 0; i < num_points; i++) { double sum = 0.0; for (int j = 0; j < num_points; j++) { v3_t diff = v3_sub(points[i], points[j]); sum += fabs(Vx(diff)) + fabs(Vy(diff)) + fabs(Vz(diff)); } if (sum < best_sum) { best_sum = sum; best_idx = i; } } if (best_idx == -1) return v3_new(0.0, 0.0, 0.0); return points[best_idx]; }
matrix_4x4 m44_view_look_at(vector3 position, vector3 target, vector3 up) { /* Taken From: http://www.opengl.org/wiki/GluLookAt_code */ vector3 zaxis = v3_normalize( v3_sub(target, position) ); vector3 xaxis = v3_normalize( v3_cross(up, zaxis) ); vector3 yaxis = v3_cross(zaxis, xaxis); matrix_4x4 view_matrix = m44_id(); view_matrix.xx = xaxis.x; view_matrix.xy = xaxis.y; view_matrix.xz = xaxis.z; view_matrix.yx = yaxis.x; view_matrix.yy = yaxis.y; view_matrix.yz = yaxis.z; view_matrix.zx = -zaxis.x; view_matrix.zy = -zaxis.y; view_matrix.zz = -zaxis.z; // Also unsure of this. view_matrix = m44_mul_m44(view_matrix, m44_translation(v3_neg(position)) ); return view_matrix; }
void gouraud_shade(Hpoly *c, Hpoly *p, Hpoly *n, Vector3 v, RContext *rc, Material *m) { int i; for (i = 0; i < p->n; i++) c->v[i] = v4_v3conv((*m->luminance)(rc_set(rc, v3_unit(v3_sub(v, v3_v4conv(p->v[i]))), v3_v4conv(p->v[i]), v3_v4conv(n->v[i]), m))); }
int triangle_intersects(const triangle_t *triangle, const ray_t *ray, intersection_t *result) { const v3_t* edge1; const v3_t* edge2; v3_t tvec; v3_t pvec; v3_t qvec; float det; float inv_det; float t; float u; float v; result->hit = 0; //v3_sub(&edge1, &triangle->pt2, &triangle->pt1); //v3_sub(&edge2, &triangle->pt3, &triangle->pt1); edge1 = &triangle->edge1; edge2 = &triangle->edge2; v3_cross(&pvec, &ray->direction, edge2); det = v3_dot(edge1, &pvec); //No culling version if(det > -EPSILON && det < EPSILON) return 0; inv_det = 1.0f / det; v3_sub(&tvec, &ray->origin, &triangle->v0); u = v3_dot(&tvec, &pvec) * inv_det; if(u < 0.0f || u > 1.0f) return 0; v3_cross(&qvec, &tvec, edge1); v = v3_dot(&ray->direction, &qvec) * inv_det; if(v < 0.0f || u + v > 1.0f + EPSILON) //add EPSILON to offset small precision errors return 0; t = v3_dot(edge2, &qvec) * inv_det; if(t > EPSILON) { result->hit = 1; result->distance = t; return 1; } /* v3_copy(&result->normal, &triangle->normal); v3_copy(&result->hit_point, &r->direction); v3_mul_scalar(&result->hit_point, t); v3_add(&result->hit_point, &result->hit_point, &r->origin); */ return 0; }
void metaballs_update() { camera* cam = entity_get("camera"); light* sun = entity_get("sun"); Uint8 keystate = SDL_GetMouseState(NULL, NULL); if(keystate & SDL_BUTTON(1)){ float a1 = -(float)mouse_x * frame_time() * 0.25; float a2 = (float)mouse_y * frame_time() * 0.25; cam->position = v3_sub(cam->position, cam->target); cam->position = m33_mul_v3(m33_rotation_y( a1 ), cam->position ); cam->position = v3_add(cam->position, cam->target); cam->position = v3_sub(cam->position, cam->target); vector3 rotation_axis = v3_normalize(v3_cross( v3_sub(cam->position, v3_zero()) , v3(0,1,0) )); cam->position = m33_mul_v3(m33_rotation_axis_angle(rotation_axis, a2 ), cam->position ); cam->position = v3_add(cam->position, cam->target); } if(keystate & SDL_BUTTON(3)){ sun->position.x += (float)mouse_y / 2; sun->position.z -= (float)mouse_x / 2; } mouse_x = 0; mouse_y = 0; particles_update(frame_time()); ui_button* framerate = ui_elem_get("framerate"); ui_button_set_label(framerate, frame_rate_string()); #ifdef MARCHING_CUBES marching_cubes_metaball_data( particle_positions_memory(), particles_count() ); marching_cubes_clear(); marching_cubes_update(); #endif #ifdef VOLUME_RENDERER volume_renderer_metaball_data( particle_positions_memory(), particles_count() ); volume_renderer_update(); #endif }
void metaballs_event(SDL_Event event) { camera* cam = entity_get("camera"); light* sun = entity_get("sun"); switch(event.type){ case SDL_KEYDOWN: break; case SDL_KEYUP: if (event.key.keysym.sym == SDLK_SPACE) { particles_reset(); } if (event.key.keysym.sym == SDLK_w) { wireframe = !wireframe; } break; case SDL_MOUSEBUTTONUP: break; case SDL_MOUSEBUTTONDOWN: if (event.button.button == SDL_BUTTON_WHEELUP) { cam->position = v3_sub(cam->position, v3_normalize(v3_sub(cam->position, cam->target))); } if (event.button.button == SDL_BUTTON_WHEELDOWN) { cam->position = v3_add(cam->position, v3_normalize(v3_sub(cam->position, cam->target))); } break; case SDL_MOUSEMOTION: mouse_x = event.motion.xrel; mouse_y = event.motion.yrel; break; } }
static void tri_refine(Vector3 v0, Vector3 v1, Vector3 v2, Real s, int maxrec) { Real l1 = v3_norm(v3_sub(v0, v1)); Real l2 = v3_norm(v3_sub(v1, v2)); Real l3 = v3_norm(v3_sub(v2, v0)); if ((MAX(l1, MAX(l2, l3))) <= s || --maxrec < 0) { plist = poly_insert(plist, poly3_make(v0, v1, v2)); } else { Vector3 m1 = v3_scale(0.5, v3_add(v0, v1)); Vector3 m2 = v3_scale(0.5, v3_add(v1, v2)); Vector3 m3 = v3_scale(0.5, v3_add(v2, v0)); tri_refine(m1, v1, m2, s, maxrec); tri_refine(m2, v2, m3, s, maxrec); tri_refine(m3, v0, m1, s, maxrec); tri_refine(m1, m2, m3, s, maxrec); } }
hit_test intersect_cylinder (ray r, cylinder c) { hit_test result; v3 rp = v3_expr(r.direction.x,0,r.direction.z); double mp = v3_mag(rp); v3 np = v3_norm(rp); double xbar = r.origin.x - c.center.x; double zbar = r.origin.z - c.center.z; double a = pow(np.x,2) + pow(np.z,2); double b = 2 * ( (xbar*np.x) + (zbar*np.z) ); double c1 = pow(xbar,2) + pow(zbar,2) - pow(c.radius,2); double d = pow(b,2) - (4*a*c1); result.miss = MISS; if(d >= 0) { double t_front = (-b - sqrt(d)) / (2*a); double t_back = (-b + sqrt(d)) / (2*a); v3 p_front = ray_position(r, t_front/mp); v3 p_back = ray_position(r, t_back/mp); if( (t_front < t_back) && (t_front > 0) && (p_front.y >= c.center.y) && (on_cylinder(p_front, c))) { result.miss = HIT; result.t = (t_front/mp); result.hit_point = p_front; result.surf = c.surface_color(c.center, p_front); result.shine = c.shine; v3 c2 = v3_expr(c.center.x, p_front.y, c.center.z); result.surf_norm = v3_norm(v3_sub(p_front,c2)); } else if( (t_back > 0) && (p_back.y >= c.center.y) && (on_cylinder(p_back, c)) ) { result.miss = HIT; result.t = (t_back/mp); result.hit_point = p_back; result.surf = c.surface_color(c.center, p_back); result.shine = c.shine; v3 c3 = v3_expr(c.center.x, p_back.y, c.center.z); result.surf_norm = v3_norm(v3_sub(c3,p_back)); } } return result; }
void sea_event(SDL_Event event) { camera* cam = entity_get("camera"); light* sun = entity_get("sun"); switch(event.type) { case SDL_KEYUP: if (event.key.keysym.sym == SDLK_SPACE) { char ball_name[20]; sprintf(ball_name, "ball_%i", ball_count); ball_count++; physics_object* ball = entity_new(ball_name, physics_object); ball->renderable = asset_get("./resources/ball.obj"); ball->collision_body = collision_body_new_sphere(sphere_new(v3_zero(), 1)); ball->position = cam->position; ball->scale = v3(0.5, 0.5, 0.5); ball->velocity = v3_mul(v3_normalize(v3_sub(cam->target, cam->position)), 75); } case SDL_MOUSEBUTTONDOWN: if (event.button.button == SDL_BUTTON_WHEELUP) { cam->position = v3_sub(cam->position, v3_normalize(cam->position)); } if (event.button.button == SDL_BUTTON_WHEELDOWN) { cam->position = v3_add(cam->position, v3_normalize(cam->position)); } break; case SDL_MOUSEMOTION: mouse_x = event.motion.xrel; mouse_y = event.motion.yrel; break; } }
hit_test intersect_sphere (ray r, sphere s) { hit_test result = {0}; v3 sc = s.center; double sr = s.radius; v3 a = v3_sub(r.origin, sc); double b = v3_dot(a, r.direction); double c = v3_dot(a, a) - (sr * sr); double d = (b * b) - c; double t = -b - sqrt(d); result.miss = MISS; if (d > 0 && t > 0) { v3 intersection = ray_position(r, t); result.miss = HIT; result.t = t; result.hit_point = intersection; result.surf = s.surface_color(sc, intersection); result.shine = s.shine; result.surf_norm = v3_norm(v3_sub(intersection, sc)); } return result; }
v3_t v3_extremum2(int n, const v3_t *a, const v3_t u, v3_t v) { int i; int max_idx = -1; double max_dist = 0.0; for (i = 0; i < n; i++) { v3_t diff1 = v3_sub(a[i], u); v3_t diff2 = v3_sub(a[i], v); double distsq1 = v3_magsq(diff1); double distsq2 = v3_magsq(diff2); if (MIN(distsq1, distsq2) > max_dist) { max_idx = i; max_dist = MIN(distsq1, distsq2); } } if (max_idx == -1) { printf("[v3_extremum2] Couldn't find extremum!\n"); return v3_new(0.0, 0.0, 0.0); } return a[max_idx]; }
t_mat4 m4_look_at(t_vec3 from, t_vec3 to, t_vec3 up) { t_vec3 x; t_vec3 y; t_vec3 z; z = v3_muls(v3_norm(v3_sub(to, from)), -1); x = v3_norm(v3_cross(up, z)); y = v3_cross(z, x); return (mat4( x.x, x.y, x.z, -v3_dot(from, x), y.x, y.y, y.z, -v3_dot(from, y), z.x, z.y, z.z, -v3_dot(from, z), 0, 0, 0, 1 )); }
void setcameraview(camera c, float aspectratio) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(c.fov,aspectratio,0.1,500.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //glRotatef(1,1,1,(float)c.roll*360.0f/255.0f); vector3 dir=v3_normalize(v3_sub(c.target,c.eye)); matrix m; m_rotate(dir.x,dir.y,dir.z,(float)c.roll*360.0f/255.0f*(float)radtheta,m); vector3 u; m_xformd(m,c.up,u); gluLookAt(c.eye.x,c.eye.y,c.eye.z, c.target.x,c.target.y,c.target.z, u.x,u.y,u.z); glGetFloatv(GL_MODELVIEW_MATRIX,cam); }
double FindRobustVariance(v3_t mean, const std::vector<v3_t> &points) { std::vector<double> dists; int num_points = (int) points.size(); for (int i = 0; i < num_points; i++) { v3_t disp = v3_sub(points[i], mean); double dist = v3_magsq(disp); dists.push_back(dist); } nth_element(dists.begin(), dists.begin() + num_points / 2, dists.end()); return dists[num_points / 2]; }
void display_generate_line(int subDiv, t_v3* min, t_v3* max, float sphere_radius, uint8* vb, t_mesh_definition* def, uint16* ib, uint16 start) { t_v3 direction; t_v3 normal; v3_set(&normal, 0, 0, 1); v3_sub(max, min, &direction); v3_norm(&direction, &direction); v3_cross(&direction, &normal, &normal); normal.x *= sphere_radius; normal.y *= sphere_radius; normal.z *= sphere_radius; float vs[] = { min->x - normal.x, min->y - normal.y, min->z, min->x + normal.x, min->y + normal.y, min->z, max->x - normal.x, max->y - normal.y, max->z, max->x + normal.x, max->y + normal.y, max->z, }; float* vsp = vs; int32 i; for (i = 0; i < 4; ++i) { t_v3* v = (t_v3*)(vb + def->vertex_offset); t_v3* n = (t_v3*)(vb + def->normal_offset); v3_set(v, *vsp, *(vsp + 1), *(vsp + 2)); vsp += 3; if (def->normal_offset != -1) v3_set(n, 0.0f, 0.0f, 1.0f); vb += def->stride; } *ib++ = start + 0; *ib++ = start + 1; *ib++ = start + 3; *ib++ = start + 0; *ib++ = start + 3; *ib++ = start + 2; }
Real shadow(Light *l, Vector3 p, Object *ol) { Real t, kt; Inode *i; Vector3 d; if (l->type == LIGHT_AMBIENT) return 1.0; d = (l->type == LIGHT_DISTANT)? l->dir : v3_sub(l->loc, p); if ((i = ray_intersect(ol, ray_make(p, d))) == NULL) return 1.0; t = i->t; kt = i->m->kt; inode_free(i); if (l->type == LIGHT_DISTANT && t > RAY_EPS) return kt; else if (l->type != LIGHT_DISTANT && t > RAY_EPS && t < 1) return kt; else return 1.0; }
static Real formfactor(int i, int j, int n, Poly **p, Real *a) { Vector3 vi, vj, vji, d; Real r2, ci, cj; vi = poly_centr(p[i]); vj = poly_centr(p[j]); vji = v3_sub(vi, vj); if ((r2 = v3_sqrnorm(vji)) < REL_EPS) return 0; d = v3_scale(1.0/sqrt(r2), vji); if ((cj = v3_dot(poly_normal(p[j]), d)) < REL_EPS) return 0; if ((ci = -v3_dot(poly_normal(p[i]), d)) < REL_EPS) return 0; if (vis_flag && visible(n, p, vj, vji) < REL_EPS) return 0; return a[i] * ((cj * ci) / (PI * r2 + a[i])); }
void makeviewVi(void) { Vector3 n,u,v,t; view->Vinv = m4_ident(); n = view->normal; v = v3_sub(view->up, v3_scale(v3_dot(view->up, n), n)); if (v3_norm(v) < ROUNDOFF) error("view up parallel to view normal"); v = v3_unit(v); u = v3_cross(n, v); t = view->center; view->Vinv = m4_ident(); view->Vinv.r1.x = u.x; view->Vinv.r2.x = u.y; view->Vinv.r3.x = u.z; view->Vinv.r1.y = v.x; view->Vinv.r2.y = v.y; view->Vinv.r3.y = v.z; view->Vinv.r1.z = n.x; view->Vinv.r2.z = n.y; view->Vinv.r3.z = n.z; view->Vinv.r1.w = t.x; view->Vinv.r2.w = t.y; view->Vinv.r3.w = t.z; }
/* Compute the "median" of a set of vectors */ v3_t v3_median(int n, const v3_t *v) { int i; v3_t median = v3_new(0.0, 0.0, 0.0); double min_dist = DBL_MAX; for (i = 0; i < n; i++) { double dist = 0.0; int j; for (j = 0; j < n; j++) { dist += v3_mag(v3_sub(v[j], v[i])); } if (dist < min_dist) { min_dist = dist; median = v[i]; } } return median; }
int v3_extremum_idx(int n, const v3_t *v, const v3_t u) { int i; int max_idx = -1; double max_dist = 0.0; for (i = 0; i < n; i++) { v3_t diff = v3_sub(v[i], u); double distsq = v3_magsq(diff); if (distsq > max_dist) { max_idx = i; max_dist = distsq; } } if (max_idx == -1) { printf("[v3_extremum] Couldn't find extremum!\n"); return 0; } return max_idx; }
void makeviewV(void) { Vector3 n,u,v,t; n = view->normal; v = v3_sub(view->up, v3_scale(v3_dot(view->up, n), n)); if (v3_norm(v) < ROUNDOFF) error("view up parallel to view normal"); v = v3_unit(v); u = v3_cross(n, v); v = v3_cross(u, n); n = v3_scale(-1.0, n); t.x = v3_dot(view->center, u); t.y = v3_dot(view->center, v); t.z = v3_dot(view->center, n); view->V = m4_ident(); view->V.r1.x = u.x; view->V.r2.x = v.x; view->V.r3.x = n.x; view->V.r1.y = u.y; view->V.r2.y = v.y; view->V.r3.y = n.y; view->V.r1.z = u.z; view->V.r2.z = v.z; view->V.r3.z = n.z; view->V.r1.w = -t.x; view->V.r2.w = -t.y; view->V.r3.w = -t.z; makeviewVi(); }
vector3 light_direction(light* l) { return v3_normalize( v3_sub( l->target, l->position ) ); }
/* M A I N */ int main(int argc, char *argv[]) { FILE *starfile; FILE *posnfile; double lat, lon; struct star_rec_str star_rec; /* time, UTC */ struct ymdhms tstar = {PLOTYEAR, PLOTMONTH, PLOTDAY, PLOTHOUR, PLOTMINUTE, PLOTSECOND}; struct starData stardat; double east, north; struct v3_str p0x, p0y; /* vector normal to ceiling */ struct v3_str n; /* compute normal to ceiling */ p0x = px; v3_sub(&p0x, &p0); p0y = py; v3_sub(&p0y, &p0); n = p0x; v3_cross(&n, &p0y); /* read in latitude, longitude */ posnfile = fopen(POSNFILE, "r"); if (posnfile != NULL) { if (read_latlon(posnfile, &lat, &lon) != 0) { lat = DFLT_LAT; lon = DFLT_LON; } fclose(posnfile); } else { lat = DFLT_LAT; lon = DFLT_LON; } #if 1 printf("lat: %f, lon: %f\n", lat, lon); #endif starfile = fopen(STARFILE, "r"); while (read_star(starfile, &star_rec) != -1) { /* dn is anchored in ne corner, ds in se corner */ /* * dn is wall measurement using NE anchor point * ds is wall measurement using SE anchor point * N, S walls measured from east side * W wall measured from S side _from_both_anchors_ */ double dn, ds; char wn, ws; /* wall on which line terminates */ double bri; /* brightness of dot (relative to mag 0) */ double dia; /* diameter of dot */ double dist; /* observer to dot distance */ /* unit vector in direction of star, spherical coords */ struct crd_sph_str u_sph; struct v3_str u_crt; /* same in cartesian coords */ /* calculate altitude, azimuth */ /* * note: these calculations don't quite agree with stellarium's. * I suspect it's due to "RA/DE (of date)" calculation * (proper motion) */ ephStarPos(&tstar, lat, lon, star_rec.ra, star_rec.dec, &stardat); #if 0 //printf("\nStar %d:\n", star_rec.hip); //ephStarDump(&stardat); printf("%d,%10.6f,%10.6f\n", star_rec.hip, stardat.az, stardat.alt); #endif /* create unit vector in direction of star */ u_sph.r = 1.0; u_sph.phi = ephDegToRad(ephAltToPhi(stardat.alt)); u_sph.theta = ephDegToRad(ephAzToTheta(stardat.az)); crd_sph2cart(&u_sph, &u_crt); /* distance from origin to dot */ dist = v3_dist_line_plane(&origin, &u_crt, &p0, &n); /* CLEANED UP TO HERE */ /* skip stars too low (or below horizon) */ if (stardat.alt < ALT_MIN) continue; /* * convert to cartesian coords: * observer is OBS_TO_CEIL below ceiling * OBS_TO_WALL from middle of east wall */ east = OBS_TO_CEIL * ephSin(stardat.az) / ephTan(stardat.alt); north = OBS_TO_CEIL * ephCos(stardat.az) / ephTan(stardat.alt); east -= OBS_TO_WALL; /* skip those not on ceiling */ if ((north > ROOM_NS / 2.0) || (north < -ROOM_NS / 2.0) || (east > 0) || (east < -ROOM_EW)) continue; #if 0 printf("%d %6.1f %6.1f %5.2f\n", star_rec.hip, east, north, star_rec.vmag); #endif if (-east / (ROOM_NS / 2.0 - north) <= ROOM_EW / ROOM_NS) { dn = -east * ROOM_NS / (ROOM_NS / 2.0 - north); wn = 's'; } else { dn = ROOM_NS - ROOM_EW * (ROOM_NS / 2.0 - north) / -east; wn = 'W'; } if (-east / (ROOM_NS / 2.0 + north) <= ROOM_EW / ROOM_NS) { ds = -east * ROOM_NS / (ROOM_NS / 2.0 + north); ws = 'n'; } else { ds = ROOM_EW * (ROOM_NS / 2.0 + north) / -east; ws = 'W'; } /* brightness ratio, relative to mag 0: m = -2.5log_10(F/F0) */ /* this could be more accurate: 5th root of 100 */ /* see Wikipedia: apparent magnitude */ bri = pow(10.0, star_rec.vmag / -2.5); /* compensate for distance from observer to dot */ bri *= dist * dist / (OBS_TO_CEIL * OBS_TO_CEIL); /* compensate for view angle */ bri /= ephSin(stardat.alt); /* brightness proportional to square of diameter */ dia = DIA_0 * sqrt(bri); #if 1 printf("%6d %5.2f %010.6f %09.6f %6.1f %6.1f %05.1f %c %05.1f %c %4.1f 0\n", star_rec.hip, star_rec.vmag, stardat.az, stardat.alt, east, north, dn, wn, ds, ws, dia); #endif } fclose(starfile); exit(0); }
/* Assumes unit_normal is normalized */ v3_t v3_project(const v3_t v, const v3_t unit_normal) { double dot = v3_dotp(v, unit_normal); v3_t par = v3_scale(dot, unit_normal); v3_t perp = v3_sub(v, par); return perp; }