/* intersect_sphere : intersect func for spheres */ hit_test intersect_sphere(ray r, object obj) { sphere s = obj.o.s; hit_test result; xyz A = xyz_sub(r.origin, s.center); double B = xyz_dot(A, xyz_norm(r.dir)); double C = xyz_dot(A, A) - s.radius*s.radius; double D = B*B - C; double t = -B - sqrt(D); ray newr = {r.origin, xyz_norm(r.dir)}; xyz loc = ray_position(newr,t); xyz v = xyz_sub(loc, s.center); xyz norm = xyz_norm(v); if(D<=0 || t<=0) result.miss = MISS; else { result.miss = HIT; result.t = t; result.hit_point = loc; result.surf = s.surface_color(&obj, loc); result.shine = s.shine; result.surf_norm = norm; } return result; }
/* intersect_poster : intersect func for posters */ hit_test intersect_poster(ray r, object obj) { poster p = obj.o.p; hit_test result; xyz n = xyz_expr(0, 0, -1); double d = p.upper_left.z; xyz rd = xyz_norm(r.dir); double t = -(xyz_dot(r.origin, n) + d)/xyz_dot(rd, n); ray newr = {r.origin, rd}; xyz loc = ray_position(newr,t); xyz ul = p.upper_left; if (t>0 && loc.x>=ul.x && loc.x<=(ul.x+p.w) && loc.y<=ul.y && loc.y>=(ul.y-p.h)) { result.miss = HIT; result.t = t; result.hit_point = loc; result.surf = p.surface_color(&obj, loc); result.shine = p.shine; result.surf_norm = n; } else { result.miss = MISS; } return result; }
// return vec (dot) vec double xyz_norm_squared( const xyz_t * const vec) { return xyz_dot( vec, vec); }
int main() { /* xyz */ printf(" *** testing xyz *** \n"); xyz v = xyz_expr(1,2,3); xyz add = xyz_add(v,v); xyz vv = xyz_expr(5,5,5); xyz sub = xyz_sub(v,vv); xyz n = xyz_neg(sub); xyz sc = xyz_scale(1.5,v); xyz sc2 = xyz_scale(-3.33,n); double dt = xyz_dot(v,sc); double mag = xyz_mag(v); xyz z = xyz_expr(0,0,0); xyz zn = xyz_norm(z); xyz vn = xyz_norm(v); printf("xyz_expr(1,2,3) =>\t%s\n",xyz_tos(v)); printf("(1,2,3)+(1,2,3) =>\t%s\n",xyz_tos(add)); printf("(1,2,3)-(5,5,5) =>\t%s\n",xyz_tos(sub)); printf("-(-4,-3,-2) =>\t%s\n",xyz_tos(n)); printf("scale (1,2,3) by 1.5 =>\t%s\n",xyz_tos(sc)); printf("scale (4,3,2) by -3.33 =>\t%s\n",xyz_tos(sc2)); printf("(1,2,3)*(1.5,3,4.5) =>\t%.2lf\n",dt); printf("magnitude of (1,2,3) =>\t%.2lf\n",mag); printf("norm (0,0,0) =>\t%s\n",xyz_tos(zn)); printf("norm (1,2,3) =>\t%s\n",xyz_tos(vn)); printf(" *****\n"); /* color */ printf(" *** testing color *** \n"); color c = color_expr(1,0.5,0); color cc = color_expr(0.75,0,0.25); color mod = color_modulate(c,cc); color scc = color_scale(1.5, cc); color addc = color_add(c,cc); printf("color_expr(1,0.5,0) =>\t%s\n",color_tos(c)); printf("(1,0.5,0)*(0.75,0,0.25) =>\t%s\n",color_tos(mod)); printf("scale (0.75,0,0.25) by 1.5 =>\t%s\n",color_tos(scc)); printf("(1,0.5,0)+(0.75,0,0.25) =>\t%s\n",color_tos(addc)); printf("(0.75,0,0.25) on [0,255] =>"); color_show_bytes(stdout,cc); printf(" *****\n"); /* ray */ printf(" *** testing ray *** \n"); ray testray = {v,vv}; printf("ray from (1,2,3) to (5,5,5) =>\t%s\n",ray_tos(testray)); printf(" *****\n"); /* sphere */ printf(" *** testing sphere *** \n"); sphere testsph = sphere_expr(v, 3.2, get_sc, c); printf("sphere at (1,2,3) with radius 3.2:\n"); sphere_show(stdout,testsph); printf("\n *****\n"); /* poster */ printf(" *** testing poster *** \n"); poster testpst = poster_expr(v, 4, 5.25, get_sc, c); printf("poster at (1,2,3) with width 4 and height 5.25:\n"); poster_show(stdout,testpst); printf("\n *****\n"); /* object */ printf(" *** testing object *** \n"); object objs = {SPHERE,{.s = testsph},NULL};
int project_o_tron(aero_table_output_t * out, aero_model_t * model, quat_t ref_to_body, int w, int h, int *pix_buf_panel) { int n = model->n_panels; // *** Input parameters xyz_t UU e_v_ref = { 1, 0, 0 }; // velocity unit vector in ref frame // todo: check that is normalized double res = 0.001 / MEGARES; // Resolution double sig_n = 0.8; // normal momentum exchange coeff double sig_t = 0.8; // tangential momentum exchange coeff // *** Let's choose a new "freestream" frame so that the velocity vector is just +X quat_t body_to_fs; xyz_t e_v_fs = { 1, 0, 0 }; // Don't need to rotate at all, the frames are already aligned // Now form the quaternion rotating the body frame to the freestream frame quat_inv(&body_to_fs, &ref_to_body); // *** Rotate "everything" into the new frame // // Rotate the center of mass xyz_t cg_fs; rot_vec_by_quat_a2b(&cg_fs, &body_to_fs, &model->cg); // Rotate the panels' coordinates panel_t panels_fs[model->n_panels]; for (int i = 0; i < n; i++) { rot_vec_by_quat_a2b(&panels_fs[i].origin, &body_to_fs, &model->panels[i].origin); rot_vec_by_quat_a2b(&panels_fs[i].side_a, &body_to_fs, &model->panels[i].side_a); rot_vec_by_quat_a2b(&panels_fs[i].side_b, &body_to_fs, &model->panels[i].side_b); } // Find the centroids xyz_t centroid_fs[n]; for (int i = 0; i < n; i++) { centroid_fs[i] = panels_fs[i].origin; // This handy function does (a <= a*A + b*B + c*C) xyz_sum_scale(¢roid_fs[i], 1, &panels_fs[i].side_a, 0.5, &panels_fs[i].side_b, 0.5); } // Sort by the X coordinate of the centroids struct indirect_element sort_list[n]; for (int i = 0; i < n; i++) { sort_list[i].index = i; sort_list[i].val = centroid_fs[i].x; } qsort(sort_list, n, sizeof(sort_list[0]), compare_indirect_elements); double *pix_buf_x = malloc(w * h * sizeof(double)); // Holds the fs frame X coordinate // of the panel element at each pixel if (!pix_buf_x) { fprintf(stderr, "Unable to allocate %zu bytes for pix_buf_x\n", w * h * sizeof(double)); return 1; } // Iterate over the panels, rearmost centroid first for (int i = 0; i < n; i++) { // if(sort_list[i].index==0){ panel_t *p = &panels_fs[sort_list[i].index]; //printf("Panel %d:::\n",sort_list[i].index); double res_a = res / xyz_norm(&p->side_a) / sqrt(2); double res_b = res / xyz_norm(&p->side_b) / sqrt(2); // Iterate over side a for (double a = 0; a <= 1; a += res_a) { // Iterate over side b for (double b = 0; b <= 1; b += res_b) { xyz_t panel_cell = p->origin; xyz_sum_scale(&panel_cell, 1, &p->side_a, a, &p->side_b, b); int pix_y = (int)round(panel_cell.y / res + w / 2); int pix_z = (int)round(panel_cell.z / res + h / 2); pix_buf_panel[pix_z + pix_y * w] = sort_list[i].index + 1; pix_buf_x[pix_z + pix_y * w] = panel_cell.x; // printf("\t%+7.4f\t%+7.4f\t%d\t%d\n",panel_cell.y,panel_cell.z,pix_y,pix_z); } } } // Find the unit normal vector in fs frame, and e_v.e_n for all panels xyz_t e_n_fs[n]; double e_v_dot_e_n[n]; for (int p = 0; p < n; p++) { xyz_cross(&e_n_fs[p], &panels_fs[p].side_a, &panels_fs[p].side_b); xyz_normalize_self(&e_n_fs[p]); e_v_dot_e_n[p] = xyz_dot(&e_n_fs[p], &e_v_fs); // if (e_v_dot_e_n[p] < 0) // printf("e_v dot e_n negative for panel %d\n",p); } // double A = 0; int n_pix[n]; memset(n_pix, 0, sizeof(n_pix)); xyz_t panel_sum_pos[n]; memset(panel_sum_pos, 0, sizeof(panel_sum_pos)); //printf("sizeof(n_pix)=%zu\n",sizeof(n_pix)); xyz_t F_fs = {0, 0, 0}; xyz_t T_fs = {0, 0, 0}; // Now iterate over the pixels for (int pix_y = 0; pix_y < w; pix_y++) for (int pix_z = 0; pix_z < h; pix_z++) { int p = pix_buf_panel[pix_z + pix_y * w]; if (p) { // There is a panel at this pixel. p--; // Actual panel index number is one less if (e_v_dot_e_n[p] < 0) { // Skip panels facing the wrong way continue; } n_pix[p]++; // Find the coordinates in the fs frame xyz_t fs_p; fs_p.x = pix_buf_x[pix_z * w + pix_y]; fs_p.y = (pix_y - w / 2) * res; fs_p.z = (pix_z - h / 2) * res; // Where is it wrt the center of mass? xyz_t r_from_cg_fs; xyz_diff(&r_from_cg_fs, &fs_p, &cg_fs); // Let's compute the forces on this element // ref: NASA SP-8058 eq 2-2 (page 5). // Dynamic pressure (1/2 rho v^2) factored out, hence leading 2 * xyz_t dF = { 0, 0, 0 }; xyz_sum_scale(&dF, 0, &e_n_fs[p], 2 * -1 * res * res * (2 - sig_n - sig_t) * xyz_dot(&e_v_fs, &e_n_fs[p]), &e_v_fs, 2 * -1 * res * res * sig_t); // Torque contribution from this element xyz_t dT; xyz_cross(&dT, &r_from_cg_fs, &dF); xyz_sum(&F_fs, &F_fs, &dF); xyz_sum(&T_fs, &T_fs, &dT); } } rot_vec_by_quat_b2a(&out->force, &body_to_fs, &F_fs); rot_vec_by_quat_b2a(&out->torque, &body_to_fs, &T_fs); printf("F = %f %f %f (norm=%f)\n",out->force.x, out->force.y, out->force.z, xyz_norm(&out->force)); printf("T = %f %f %f (norm=%f)\n",out->torque.x, out->torque.y, out->torque.z, xyz_norm(&out->torque)); // printf("%d pixels dropped due to e_v dot e_n negative\n",n_pix); free(pix_buf_x); return 0; }