double find_cylinder_intersection(t_cylinder *cy, t_ray *r) { t_vect *abc; double d; double rslt; t_vect *point; abc = coeff_cylinder(cy, r); d = pow(abc->y, 2) - abc->x * abc->z; if (d > 0) { rslt = ((-abc->y - sqrt(d)) / abc->x) - 0.000001 > 0 ? (-abc->y - sqrt(d)) / abc->x - 0.000001 : (-abc->y + sqrt(d)) / abc->x - 0.000001; point = vect_add(r->origin, vect_mult(r->direction, rslt)); if (!check_finite_cyl(cy, point)) rslt = -1; } else rslt = -1; delete_vect(abc); return (rslt); }
t_inter *find_cylinders_intersection(t_ray *ray) { double mininter; double inter; t_vect *normal; t_color *color; t_cylinder *c; mininter = -1; c = get_scene()->cylinders; while (c != NULL) { inter = find_cylinder_intersection(c, ray); if (inter > ACCURACY && (inter < mininter || mininter == -1)) { mininter = inter; normal = get_normal_at_cylinder(c, vect_add(ray->origin, vect_mult(ray->direction, inter))); color = c->color; } c = c->next; } return (new_inter(normal, mininter, color)); }
color* trace( ray *aray, primitive *scene, int depth, float refr, float *dist, int shadows ){ intersection *isect; primitive *prim, *iter; vector isect_pt, pn, lv, ln, tmpv1, tmpv2; ray tmpr; float tmpf1, tmpf2, tmpf3, shade; color *tmpc; color *c = (color*)malloc( sizeof( color ) ); if( c == NULL ) { fprintf( stderr, "*** error: could not allocate color memory\n" ); exit( 1 ); } c->x = 0.0f; c->y = 0.0f; c->z = 0.0f; isect = intersect( aray, scene ); if( isect == NULL ) { return c; } *dist = isect->dist; prim = isect->prim; if( prim->is_light ) { vect_copy( c, &(isect->prim->mat.col) ); free( isect ); return c; } vect_copy( &isect_pt, aray->dir ); vect_multf( &isect_pt, isect->dist ); vect_add( &isect_pt, aray->origin ); prim->normal( prim, &isect_pt, &pn ); iter = scene; while( iter != NULL ) { if( iter->is_light ) { vect_copy( &lv, &iter->center ); vect_sub( &lv, &isect_pt ); vect_copy( &ln, &lv ); vect_normalize( &ln ); shade = calc_shade( iter, &isect_pt, &lv, &ln, scene, shadows ); if( shade > 0.0f ) { /* determine the diffuse component */ tmpf1 = prim->mat.diffuse; if( tmpf1 > 0.0f ) { tmpf2 = vect_dot( &pn, &ln ); if( tmpf2 > 0.0f ) { tmpf1 *= tmpf2 * shade; vect_copy( &tmpv1, &prim->mat.col ); vect_mult( &tmpv1, &iter->mat.col ); vect_multf( &tmpv1, tmpf1 ); vect_add( c, &tmpv1 ); } } /* determine the specular component */ tmpf1 = prim->mat.specular; if( tmpf1 > 0.0f ) { vect_copy( &tmpv1, &pn ); vect_copy( &tmpv2, &ln ); tmpf2 = 2.0f * vect_dot( &ln, &pn ); vect_multf( &tmpv1, tmpf2 ); vect_sub( &tmpv2, &tmpv1 ); tmpf2 = vect_dot( aray->dir, &tmpv2 ); if( tmpf2 > 0.0f ) { tmpf1 = powf( tmpf2, 20.0f ) * tmpf1 * shade; vect_copy( &tmpv1, &iter->mat.col ); vect_multf( &tmpv1, tmpf1 ); vect_add( c, &tmpv1 ); } } } } iter = iter->next; } /* calculate reflection */ if( prim->mat.refl > 0.0f && depth < TRACE_DEPTH ) { vect_copy( &tmpv1, &pn ); vect_multf( &tmpv1, 2.0f * vect_dot( &pn, aray->dir ) ); vect_copy( &tmpv2, aray->dir ); vect_sub( &tmpv2, &tmpv1 ); vect_copy( &tmpv1, &tmpv2 ); vect_multf( &tmpv1, EPSILON ); vect_add( &tmpv1, &isect_pt ); tmpr.origin = &tmpv1; tmpr.dir = &tmpv2; tmpc = trace( &tmpr, scene, depth + 1, refr, &tmpf1, shadows ); vect_multf( tmpc, prim->mat.refl ); vect_copy( &tmpv1, &prim->mat.col ); vect_mult( &tmpv1, tmpc ); vect_add( c, &tmpv1 ); free( tmpc ); } /* calculate refraction */ if( prim->mat.is_refr && depth < TRACE_DEPTH ) { vect_copy( &tmpv1, &pn ); if( isect->inside ) { vect_multf( &tmpv1, -1.0f ); } tmpf1 = refr / prim->mat.refr; tmpf2 = -( vect_dot( &tmpv1, aray->dir ) ); tmpf3 = 1.0f - tmpf1 * tmpf1 * (1.0f - tmpf2 * tmpf2); if( tmpf3 > 0.0f ) { vect_copy( &tmpv2, aray->dir ); vect_multf( &tmpv2, tmpf1 ); vect_multf( &tmpv1, tmpf1 * tmpf2 - sqrtf( tmpf3 ) ); vect_add( &tmpv1, &tmpv2 ); vect_copy( &tmpv2, &tmpv1 ); vect_multf( &tmpv2, EPSILON ); vect_add( &tmpv2, &isect_pt ); tmpr.origin = &tmpv2; tmpr.dir = &tmpv1; tmpc = trace( &tmpr, scene, depth + 1, refr, &tmpf1, shadows ); vect_copy( &tmpv1, &prim->mat.col ); vect_multf( &tmpv1, prim->mat.absorb * tmpf1 ); tmpv2.x = expf( -tmpv1.x ); tmpv2.y = expf( -tmpv1.y ); tmpv2.z = expf( -tmpv1.z ); vect_mult( tmpc, &tmpv2 ); vect_add( c, tmpc ); free( tmpc ); } } free( isect ); if( c->x > 1.0f ) { c->x = 1.0f; } else if( c->x < 0.0f ) { c->x = 0.0f; } if( c->y > 1.0f ) { c->y = 1.0f; } else if( c->y < 0.0f ) { c->y = 0.0f; } if( c->z > 1.0f ) { c->z = 1.0f; } else if( c->z < 0.0f ) { c->z = 0.0f; } return c; }
Graph::Graph(const int *cartan, const std::vector<Word>& gens, //namesake const std::vector<Word>& v_cogens, const std::vector<Word>& e_gens, const std::vector<Word>& f_gens, const Vect& weights) { //define symmetry group relations std::vector<Word> words = words_from_cartan(cartan); { const Logging::fake_ostream& os = logger.debug(); os << "relations ="; for (int w=0; w<6; ++w) { Word& word = words[w]; os << "\n "; for (unsigned i=0; i<word.size(); ++i) { os << word[i]; } } os |0; } //check vertex stabilizer generators { const Logging::fake_ostream& os = logger.debug(); os << "v_cogens ="; for (unsigned w=0; w<v_cogens.size(); ++w) { const Word& jenn = v_cogens[w]; //namesake os << "\n "; for (unsigned t=0; t<jenn.size(); ++t) { int j = jenn[t]; os << j; Assert (0<=j and j<4, "generator out of range: letter w[" << w << "][" << t << "] = " << j ); } } os |0; } //check edge generators { const Logging::fake_ostream& os = logger.debug(); os << "e_gens ="; for (unsigned w=0; w<e_gens.size(); ++w) { const Word& edge = e_gens[w]; os << "\n "; for (unsigned t=0; t<edge.size(); ++t) { int j = edge[t]; os << j; Assert (0<=j and j<4, "generator out of range: letter w[" << w << "][" << t << "] = " << j ); } } os |0; } //check face generators { const Logging::fake_ostream& os = logger.debug(); os << "f_gens ="; for (unsigned w=0; w<f_gens.size(); ++w) { const Word& face = f_gens[w]; os << "\n "; for (unsigned t=0; t<face.size(); ++t) { int j = face[t]; os << j; Assert (0<=j and j<4, "generator out of range: letter w[" << w << "][" << t << "] = " << j ); } } os |0; } //build symmetry group Group group(words); logger.debug() << "group.ord = " << group.ord |0; //build subgroup std::vector<int> subgroup; subgroup.push_back(0); std::set<int> in_subgroup; in_subgroup.insert(0); for (unsigned g=0; g<subgroup.size(); ++g) { int g0 = subgroup[g]; for (unsigned j=0; j<gens.size(); ++j) { int g1 = group.left(g0,gens[j]); if (in_subgroup.find(g1) != in_subgroup.end()) continue; subgroup.push_back(g1); in_subgroup.insert(g1); } } logger.debug() << "subgroup.ord = " << subgroup.size() |0; //build cosets and count ord std::map<int,int> coset; //maps group elements to cosets ord = 0; //used as coset number for (unsigned g=0; g<subgroup.size(); ++g) { int g0 = subgroup[g]; if (coset.find(g0) != coset.end()) continue; int c0 = ord++; coset[g0] = c0; std::vector<int> members(1, g0); std::vector<int> others(0); for (unsigned i=0; i<members.size(); ++i) { int g1 = members[i]; for (unsigned w=0; w<v_cogens.size(); ++w) { int g2 = group.left(g1, v_cogens[w]); if (coset.find(g2) != coset.end()) continue; coset[g2] = c0; members.push_back(g2); } } } logger.info() << "cosets table built: " << " ord = " << ord |0; //build edge lists std::vector<std::set<int> > neigh(ord); for (unsigned g=0; g<subgroup.size(); ++g) { int g0 = subgroup[g]; int c0 = coset[g0]; for (unsigned w=0; w<e_gens.size(); ++w) { int g1 = group.left(g0, e_gens[w]); Assert (in_subgroup.find(g1) != in_subgroup.end(), "edge leaves subgroup"); int c1 = coset[g1]; if (c0 != c1) neigh[c0].insert(c1); } } // make symmetric for (int c0=0; c0<ord; ++c0) { const std::set<int>& n = neigh[c0]; for (std::set<int>::iterator c1=n.begin(); c1!=n.end(); ++c1) { neigh[*c1].insert(c0); } } // build edge table adj.resize(ord); for (int c=0; c<ord; ++c) { adj[c].insert(adj[c].begin(), neigh[c].begin(), neigh[c].end()); } neigh.clear(); deg = adj[0].size(); logger.info() << "edge table built: deg = " << deg |0; //define faces for (unsigned g=0; g<f_gens.size(); ++g) { const Word& face = f_gens[g]; logger.debug() << "defining faces on " << face |0; Logging::IndentBlock block; //define basic face in group Ring basic(1,0); // g = 0; int g0 = 0; for (unsigned c=0; true; ++c) { g0 = group.left(g0, face[c%face.size()]); if (c >= face.size() and g0 == 0) break; if (in_subgroup.find(g0) != in_subgroup.end() and g0 != basic.back()) { basic.push_back(g0); } } for (unsigned c=0; c<basic.size(); ++c) { logger.debug() << " corner: " << basic[c] |0; } logger.debug() << "sides/face (free) = " << basic.size() |0; //build orbit of basic face std::vector<Ring> faces_g; faces_g.push_back(basic); FaceRecognizer recognized; recognized(basic); for (unsigned i=0; i<faces_g.size(); ++i) { const Ring f = faces_g[i]; for (unsigned j=0; j<gens.size(); ++j) { //right action of group on faces Ring f_j(f.size()); for (unsigned c=0; c<f.size(); ++c) { f_j[c] = group.right(f[c],gens[j]); } //add face if (not recognized(f_j)) { faces_g.push_back(f_j); //logger.debug() << "new face: " << f_j |0; } else { //logger.debug() << "old face: " << f_j|0; } } } //hom face down to quotient graph recognized.clear(); for (unsigned f=0; f<faces_g.size(); ++f) { const Ring face_g = faces_g[f]; Ring face; face.push_back(coset[face_g[0]]); for (unsigned i=1; i<face_g.size(); ++i) { int c = coset[face_g[i]]; if (c != face.back() and c != face[0]) { face.push_back(c); } } if (face.size() < 3) continue; if (not recognized(face)) { faces.push_back(face); } } } ord_f = faces.size(); logger.info() << "faces defined: order = " << ord_f |0; //define vertex coset std::vector<Word> vertex_coset; for (unsigned g=0; g<subgroup.size(); ++g) { int g0 = subgroup[g]; if (coset[g0]==0) vertex_coset.push_back(group.parse(g0)); } //build geometry std::vector<Mat> gen_reps(gens.size()); points.resize(ord); build_geom(cartan, vertex_coset, gens, v_cogens, weights, gen_reps, points[0]); std::vector<int> pointed(ord,0); pointed[0] = true; logger.debug() << "geometry built" |0; //build point sets std::vector<int> reached(1,0); std::set<int> is_reached; is_reached.insert(0); for (unsigned g=0; g<subgroup.size(); ++g) { int g0 = reached[g]; for (unsigned j=0; j<gens.size(); ++j) { int g1 = group.right(g0,gens[j]); if (is_reached.find(g1) == is_reached.end()) { if (not pointed[coset[g1]]) { vect_mult(gen_reps[j], points[coset[g0]], points[coset[g1]]); pointed[coset[g1]] = true; } reached.push_back(g1); is_reached.insert(g1); } } } logger.debug() << "point set built." |0; //build face normals normals.resize(ord_f); for (int f=0; f<ord_f; ++f) { Ring& face = faces[f]; Vect &a = points[face[0]]; Vect &b = points[face[1]]; Vect &c = points[face[2]]; Vect &n = normals[f]; cross4(a,b,c, n); normalize(n); /* Assert1(fabs(inner(a,n)) < 1e-6, "bad normal: <n,a> = " << fabs(inner(a,n))); Assert1(fabs(inner(b,n)) < 1e-6, "bad normal: <n,b> = " << fabs(inner(b,n))); Assert1(fabs(inner(c,n)) < 1e-6, "bad normal: <n,b> = " << fabs(inner(c,n))); */ } logger.debug() << "face normals built." |0; }
VECT surface_height::height_normal_get(int x, int y, MASK_INTERFACE *p_mask, int mask_x, int mask_y) { VECT2DI list[] = { VECT2DI( 0, 1), VECT2DI( 1, 1), VECT2DI( 1, 0), VECT2DI( 1,-1), VECT2DI( 0,-1), VECT2DI(-1,-1), VECT2DI(-1, 0), VECT2DI(-1, 1), VECT2DI( 0, 1) }; VECT vects[] = { VECT3DF( 0, 0, 1), VECT3DF( 1, 0, 1), VECT3DF( 1, 0, 0), VECT3DF( 1, 0,-1), VECT3DF( 0, 0,-1), VECT3DF(-1, 0,-1), VECT3DF(-1, 0, 0), VECT3DF(-1, 0, 1), VECT3DF( 0, 0, 1) }; int points = (int)(sizeof(list)/sizeof(list[0])); float height_current = height_get(x, y); int i; for(i = 0; i < points; i++) { tpos ax = x+list[i].x; tpos ay = y+list[i].y; if(pixel_valid(ax, ay) && (!p_mask || p_mask->mask_get(mask_x+ax,mask_y+ay))) { float height = height_get(ax, ay); vects[i].y = (height - height_current)*pixel_height_range; vects[i].norm(); } else { vects[i].set(FLOAT_UNDEFINED); } } VECT last(0); for(i = 0; i < points; i++) { if(vects[i].x != FLOAT_UNDEFINED) { last = vects[i]; break; } } if(i == points) { // return some default normal return(VECT3DF(0,-1,0)); } VECT normal(0); for(i = i+1; i < points; i++) { if(vects[i].x != FLOAT_UNDEFINED) { VECT3DF tmp = vect_mult(last, vects[i]); tmp.norm(); normal += tmp; last = vects[i]; } } normal.norm(); return(normal); }