Beispiel #1
0
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);
}
Beispiel #2
0
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));
}
Beispiel #3
0
Datei: crt.c Projekt: arader/crt
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;
}
Beispiel #4
0
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;
}
Beispiel #5
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);
}