예제 #1
0
/*
 * Function: ri_transport_sample
 *
 *     Triggers light transporter and computes radiance along the ray.
 *
 * Parameters:
 *
 *     *render - The global renderer data.
 *     *ray    - The ray originating camera which throughs pixel plane.
 *     *resut  - Light transport result(including radiance).
 *
 * Returns:
 *
 *     Always 1.
 */
int
ri_transport_sample(
    ri_render_t         *render,
    const ri_ray_t      *ray,
    ri_transport_info_t *result)
{
    ri_ray_t newray;

    memcpy(&newray, ray, sizeof(ri_ray_t));     /* copy */

    /*
     * Initialize
     */
    {
        ri_vector_setzero(result->radiance);
        result->nbound_diffuse  = 0;
        result->nbound_specular = 0;
        ri_intersection_state_clear( &result->state );
    }    



    trace_path(render, &newray, result);

    return 1;
}
예제 #2
0
파일: region.c 프로젝트: baskanov/wine
static GpStatus get_path_hrgn(GpPath *path, GpGraphics *graphics, HRGN *hrgn)
{
    HDC new_hdc=NULL;
    GpGraphics *new_graphics=NULL;
    GpStatus stat;
    INT save_state;

    if (!path->pathdata.Count)  /* PathToRegion doesn't support empty paths */
    {
        *hrgn = CreateRectRgn( 0, 0, 0, 0 );
        return *hrgn ? Ok : OutOfMemory;
    }

    if (!graphics)
    {
        new_hdc = CreateCompatibleDC(0);
        if (!new_hdc)
            return OutOfMemory;

        stat = GdipCreateFromHDC(new_hdc, &new_graphics);
        graphics = new_graphics;
        if (stat != Ok)
        {
            DeleteDC(new_hdc);
            return stat;
        }
    }
    else if (!graphics->hdc)
    {
        graphics->hdc = new_hdc = CreateCompatibleDC(0);
        if (!new_hdc)
            return OutOfMemory;
    }

    save_state = SaveDC(graphics->hdc);
    EndPath(graphics->hdc);

    SetPolyFillMode(graphics->hdc, (path->fill == FillModeAlternate ? ALTERNATE
                                                                    : WINDING));

    stat = trace_path(graphics, path);
    if (stat == Ok)
    {
        *hrgn = PathToRegion(graphics->hdc);
        stat = *hrgn ? Ok : OutOfMemory;
    }

    RestoreDC(graphics->hdc, save_state);
    if (new_hdc)
    {
        DeleteDC(new_hdc);
        if (new_graphics)
            GdipDeleteGraphics(new_graphics);
        else
            graphics->hdc = NULL;
    }

    return stat;
}
예제 #3
0
static void
trace_pixel(ri_vector_t *radiance, int x, int y)
{
	unsigned char     type;
	double            bsdf[3];
	ri_ray_t          ray;
	ri_intersection_state_t state;
	pathnode_t        node;
	ri_vector_t       Le;
 
	/* first check a ray hits scene object through pixel (x, y) */
	ri_vector_copy(&ray.org, cam_pos);
	sample_pixel(&ray.dir, x, y);

	ray.thread_num = 0;

	if (!ri_raytrace(ri_render_get(), &ray, &state)) {
		/* hits background */
		ri_texture_ibl_fetch(radiance, light->texture, ray.dir);
		return;
	}

	node.depth = 2;
	node.G[0] = 1.0; node.G[1] = 1.0; node.G[2] = 1.0;
	ri_mem_copy(&node.state, &state, sizeof(ri_intersection_state_t));
	ri_vector_copy(&node.indir, ray.dir);
	// assume that the camera is not located in the transparent object
	node.interior = 0;

	trace_path(&node);

	/* connect the path to the IBL light source */
	type = sample_reflection_type(node.state.geom->material);

	//if (node.interior) printf("???\n");

	sample_outdir(&ray.dir, &type,
		      node.interior,
		      node.state.geom->material,
		      node.indir, node.state.Ng);

	brdf(bsdf,
	     type, &node.state,
	     node.indir, ray.dir, node.state.Ng);
	node.G[0] *= bsdf[0];
	node.G[1] *= bsdf[1];
	node.G[2] *= bsdf[2];

	ri_vector_copy(&ray.org, node.state.P);

	light_sample(&Le, ray.org, ray.dir);

	radiance->f[0] = Le.f[0] * node.G[0];
	radiance->f[1] = Le.f[1] * node.G[1];
	radiance->f[2] = Le.f[2] * node.G[2];
}
예제 #4
0
파일: region.c 프로젝트: AmesianX/RosWine
static GpStatus get_path_hrgn(GpPath *path, GpGraphics *graphics, HRGN *hrgn)
{
    HDC new_hdc=NULL;
    GpGraphics *new_graphics=NULL;
    GpStatus stat;
    INT save_state;

    if (!graphics)
    {
        new_hdc = GetDC(0);
        if (!new_hdc)
            return OutOfMemory;

        stat = GdipCreateFromHDC(new_hdc, &new_graphics);
        graphics = new_graphics;
        if (stat != Ok)
        {
            ReleaseDC(0, new_hdc);
            return stat;
        }
    }
    else if (!graphics->hdc)
    {
        graphics->hdc = new_hdc = GetDC(0);
        if (!new_hdc)
            return OutOfMemory;
    }

    save_state = SaveDC(graphics->hdc);
    EndPath(graphics->hdc);

    SetPolyFillMode(graphics->hdc, (path->fill == FillModeAlternate ? ALTERNATE
                                                                    : WINDING));

    stat = trace_path(graphics, path);
    if (stat == Ok)
    {
        *hrgn = PathToRegion(graphics->hdc);
        stat = *hrgn ? Ok : OutOfMemory;
    }

    RestoreDC(graphics->hdc, save_state);
    if (new_hdc)
    {
        ReleaseDC(0, new_hdc);
        if (new_graphics)
            GdipDeleteGraphics(new_graphics);
        else
            graphics->hdc = NULL;
    }

    return stat;
}
예제 #5
0
파일: btree.c 프로젝트: poelzi/mspdebug
int btree_select(btree_t bt, const void *key, btree_selmode_t mode,
		 void *key_ret, void *data_ret)
{
	const struct btree_def *def = bt->def;

	check_btree(bt);

	switch (mode) {
	case BTREE_CLEAR:
		bt->slot[0] = -1;
		break;

	case BTREE_READ:
		break;

	case BTREE_EXACT:
	case BTREE_LE:
		if (!trace_path(bt, key, bt->path, bt->slot) &&
		    mode == BTREE_EXACT)
			bt->slot[0] = -1;
		break;

	case BTREE_FIRST:
		cursor_first(bt);
		break;

	case BTREE_NEXT:
		cursor_next(bt);
		break;
	}

	/* Return the data at the cursor */
	if (bt->slot[0] >= 0) {
		if (key_ret)
			memcpy(key_ret,
			       PAGE_KEY(bt->path[0], bt->slot[0]),
			       def->key_size);
		if (data_ret)
			memcpy(data_ret,
			       PAGE_DATA(bt->path[0], bt->slot[0]),
			       def->data_size);
		return 0;
	}

	return 1;
}
예제 #6
0
파일: btree.c 프로젝트: poelzi/mspdebug
int btree_delete(btree_t bt, const void *key)
{
	const struct btree_def *def = bt->def;
	const int halfsize = def->branches / 2;
	struct btree_page *path[MAX_HEIGHT] = {0};
	int slot[MAX_HEIGHT] = {0};
	int h;

	check_btree(bt);

	/* Trace a path to the item to be deleted */
	if (!key) {
		if (bt->slot[0] < 0)
			return 1;

		memcpy(path, bt->path, sizeof(path));
		memcpy(slot, bt->slot, sizeof(slot));
	} else if (!trace_path(bt, key, path, slot)) {
		return 1;
	}

	/* Select the next item if we're deleting at the cursor */
	if (bt->slot[0] == slot[0] && bt->path[0] == path[0])
		cursor_next(bt);

	/* Delete from the leaf node. If it's still full enough, then we don't
	 * need to do anything else.
	 */
	delete_item(path[0], slot[0]);
	if (path[0]->num_children >= halfsize)
		return 0;

	/* Trace back up the tree, fixing underfull nodes. If we can fix by
	 * borrowing, do it and we're done. Otherwise, we need to fix by
	 * merging, which may result in another underfull node, and we need
	 * to continue.
	 */
	for (h = 1; h <= bt->root->height; h++) {
		struct btree_page *p = path[h];
		struct btree_page *c = path[h - 1];
		int s = slot[h];

		if (s > 0) {
			/* Borrow/merge from lower page */
			struct btree_page *d = *PAGE_PTR(p, s - 1);

			if (d->num_children > halfsize) {
				move_item(d, d->num_children - 1, c, 0);
				memcpy(PAGE_KEY(p, s), PAGE_KEY(c, 0),
				       def->key_size);
				return 0;
			}

			merge_pages(d, c);
			delete_item(p, s);
			free(c);
		} else {
			/* Borrow/merge from higher page */
			struct btree_page *d = *PAGE_PTR(p, s + 1);

			if (d->num_children > halfsize) {
				move_item(d, 0, c, c->num_children);
				memcpy(PAGE_KEY(p, s + 1),
				       PAGE_KEY(d, 0),
				       def->key_size);
				return 0;
			}

			merge_pages(c, d);
			delete_item(p, s + 1);
			free(d);
		}

		if (p->num_children >= halfsize)
			return 0;
	}

	/* If the root contains only a single pointer to another page,
	 * shrink the tree. This does not affect the cursor.
	 */
	if (bt->root->height && bt->root->num_children == 1) {
		struct btree_page *old = bt->root;

		bt->root = *PAGE_PTR(old, 0);
		free(old);
	}

	return 0;
}
예제 #7
0
파일: btree.c 프로젝트: poelzi/mspdebug
int btree_put(btree_t bt, const void *key, const void *data)
{
	const struct btree_def *def = bt->def;
	struct btree_page *new_root = NULL;
	struct btree_page *path_new[MAX_HEIGHT] = {0};
	struct btree_page *path_old[MAX_HEIGHT] = {0};
	int slot_old[MAX_HEIGHT] = {0};
	int h;

	check_btree(bt);

	/* Special case: cursor overwrite */
	if (!key) {
		if (bt->slot[0] < 0) {
			fprintf(stderr, "btree: put at invalid cursor\n");
			return -1;
		}

		memcpy(PAGE_DATA(bt->path[0], bt->slot[0]), data,
		       def->data_size);
		return 1;
	}

	/* Find a path down the tree that leads to the page which should
	 * contain this datum (though the page might be too big to hold it).
	 */
	if (trace_path(bt, key, path_old, slot_old)) {
		/* Special case: overwrite existing item */
		memcpy(PAGE_DATA(path_old[0], slot_old[0]), data,
		       def->data_size);
		return 1;
	}

	/* Trace from the leaf up. If the leaf is at its maximum size, it will
	 * need to split, and cause a pointer to be added in the parent page
	 * of the same node (which may in turn cause it to split).
	 */
	for (h = 0; h <= bt->root->height; h++) {
		if (path_old[h]->num_children < def->branches)
			break;

		path_new[h] = allocate_page(bt, h);
		if (!path_new[h])
			goto fail;
	}

	/* If the split reaches the top (i.e. the root splits), then we need
	 * to allocate a new root node.
	 */
	if (h > bt->root->height) {
		if (h >= MAX_HEIGHT) {
			fprintf(stderr, "btree: maximum height exceeded\n");
			goto fail;
		}

		new_root = allocate_page(bt, h);
		if (!new_root)
			goto fail;
	}

	/* Trace up to one page above the split. At each page that needs
	 * splitting, copy the top half of keys into the new page. Also,
	 * insert a key into one of the pages at all pages from the leaf
	 * to the page above the top of the split.
	 */
	for (h = 0; h <= bt->root->height; h++) {
		int s = slot_old[h] + 1;
		struct btree_page *p = path_old[h];

		/* If there's a split at this level, copy the top half of
		 * the keys from the old page to the new one. Check to see
		 * if the position we were going to insert into is in the
		 * old page or the new one.
		 */
		if (path_new[h]) {
			split_page(path_old[h], path_new[h]);

			if (s > p->num_children) {
				s -= p->num_children;
				p = path_new[h];
			}
		}

		/* Insert the key in the appropriate page */
		if (h)
			insert_ptr(p, s, PAGE_KEY(path_new[h - 1], 0),
				   path_new[h - 1]);
		else
			insert_data(p, s, key, data);

		/* If there was no split at this level, there's nothing to
		 * insert higher up, and we're all done.
		 */
		if (!path_new[h])
			return 0;
	}

	/* If we made it this far, the split reached the top of the tree, and
	 * we need to grow it using the extra page we allocated.
	 */
	assert (new_root);

	if (bt->slot[0] >= 0) {
		/* Fix up the cursor, if active */
		bt->slot[new_root->height] =
			bt->path[bt->root->height] == new_root ? 1 : 0;
		bt->path[new_root->height] = new_root;
	}

	memcpy(PAGE_KEY(new_root, 0), def->zero, def->key_size);
	*PAGE_PTR(new_root, 0) = path_old[h - 1];
	memcpy(PAGE_KEY(new_root, 1), PAGE_KEY(path_new[h - 1], 0),
	       def->key_size);
	*PAGE_PTR(new_root, 1) = path_new[h - 1];
	new_root->num_children = 2;
	bt->root = new_root;

	return 0;

 fail:
	for (h = 0; h <= bt->root->height; h++)
		if (path_new[h])
			free(path_new[h]);
	return -1;
}
예제 #8
0
/*
 * Function: trace_path
 *
 *     Samples light transport path in recursive manner. In curent
 *     implementation, <trace_path> acts as distribution ray tracing.
 *
 * Parameters:
 *
 *     *render - The global renderer data.
 *     *ray    - The ray to be traced.
 *     *resut  - Light transport result(including radiance).
 *
 * Returns:
 *
 *     None.
 */
static void
trace_path(ri_render_t *render, ri_ray_t *ray, ri_transport_info_t *result)
{
    int max_nbound_specular = 10;

    if (result->nbound_specular > max_nbound_specular) {
        /* Too much reflection, terminate.  */
        return;
    }

    ri_light_t *light = NULL;

    int hit;

    /* hack */
    vec white;
    vec black;

    ri_vector_set1(white,  1.0);
    ri_vector_set1(black,  0.0);

    hit = ri_raytrace(render, ray, &(result->state));

    if (hit) {

        if (result->state.geom->light) {

            light = result->state.geom->light;

            /* Hit light geometry. */
            vcpy(result->radiance, light->col);
            return;

        }

        vcpy(result->radiance, white);

    } else {

        vcpy(result->radiance, black);

    }

    return;

#if 0 // TODO
    int hit, lighthit;
    int hasfresnel;
    ri_vector_t col;
    ri_vector_t transmit_ray;
    ri_vector_t reflect_ray;
    ri_vector_t offset;
    ri_vector_t raydir;
    ri_vector_t rayorg;
    ri_vector_t refrad, trasrad;
    ri_vector_t normal;
    ri_light_t *light;
    ri_vector_t rad;
    ri_material_t *material;
    ri_ray_t       lightray;
    ri_transport_info_t ref_result;        /* for reflection */
    double r, d, s, t;
    float  fresnel_factor = 1.0f;
    float  kr, kt;
    float  eta = 1.0f / 1.4f;
    float  etaval;

    if (result->nbound_specular > 8) {
        //printf("too reflection\n");
        return;
    }

    light = get_light(render);

    ri_vector_copy(&raydir, ray->dir);
    result->state.inside = 0;
    hit = ri_raytrace(render, ray, &(result->state));

    if (hit) {

        if (light->geom) {
            /* Check if a ray also hits light geometry and
             * that is closer than scene geometry or not.
             */
            ri_vector_copy(&lightray.org, ray->org);
            ri_vector_copy(&lightray.dir, ray->dir);

            lighthit = ri_raytrace_geom(
                    light->geom,
                    &lightray,
                    &(result->state));            

            if (lighthit && (lightray.isectt < ray->isectt) ) {

                // light is "seen"
                ri_vector_copy(&result->radiance,
                           light->col);
                result->hit = 1;
                return;
            }
        }

        r = randomMT();

        material = result->state.geom->material;
        if (!material) {
            d = 1.0;
            s = 0.0;
            t = 0.0;
        } else {
            d = ri_vector_ave(&material->kd);
            s = ri_vector_ave(&material->ks);
            t = ri_vector_ave(&material->kt);
        }

        if (s > 0.0) {
            /* specular reflection */

            if (result->state.geom->material &&
                result->state.geom->material->fresnel) {

                /* Fresnel reflection */
            
                ri_fresnel(&ray->dir, &transmit_ray,
                       &kr, &kt,
                       &ray->dir, &result->state.normal,
                       eta);

                fresnel_factor = kr;

            } else {
                ri_reflect(&(ray->dir),
                       &ray->dir,
                       &result->state.normal);

                fresnel_factor = 1.0f;
            }

    
            ri_vector_copy(&(ray->org), result->state.P);

            ri_vector_copy(&col, result->state.color);


            result->nbound_specular++;

            /* push radiance */
            ri_vector_copy(&rad, result->radiance);
            ri_vector_zero(&(result->radiance));

            trace_path(render, ray, result);

            /* pop radiance */
            ri_vector_mul(&(result->radiance),
                      &result->radiance, &material->ks);
            ri_vector_mul(&(result->radiance),
                      &result->radiance, &col);
            ri_vector_scale(&(result->radiance),
                        fresnel_factor);


            ri_vector_add(&(result->radiance),
                      &result->radiance,
                      &rad);
        }

        if (d > 0.0) {
            /* diffuse reflection */
            result->nbound_diffuse++;
            ri_shade(&rad, &ray->dir, ray, &(result->state));

            ri_vector_mul(&rad,
                      &rad, &material->kd);
            ri_vector_add(&(result->radiance), &result->radiance,
                                   &rad);    
        }


        if (t > 0.0) {
            /* specular refraction */

            if (result->state.geom->material &&
                result->state.geom->material->fresnel) {
                hasfresnel = 1;
            } else {
                hasfresnel = 0;
            }


            if (hasfresnel) {
                /* Fresnel effect */
            
                ri_vector_copy(&normal,
                           result->state.normal);

                if (result->state.inside) {
                    printf("inside val = %d\n", result->state.inside);
                    printf("inside\n");
                    /* ray hits inside surface */
                    //ri_vector_neg(&normal);
                    etaval = 1.0 / eta;
                } else {
                    etaval = eta;
                }

                ri_fresnel(&reflect_ray, &transmit_ray,
                       &kr, &kt,
                       &ray->dir, &normal,
                       etaval);

            } else {
                ri_refract(&(ray->dir),
                       &ray->dir,
                       &result->state.normal,
                       eta);

                kr = 0.0; kt = 1.0;
            }

            /* slightly moves the ray towards outgoing direction */

            ri_vector_copy(&rayorg, result->state.P);

            /* ray.org = ray.org + 0.001 * ray.dir */
            ri_vector_copy(&offset, &transmit_ray);
            ri_vector_scale(&offset, 0.001);
            ri_vector_add(&(ray->org), &rayorg, &offset);

            /* ray.dir = refract direction */
            ri_vector_copy(&(ray->dir), &transmit_ray);
 
            ri_vector_copy(&col, &result->state.color);

            result->nbound_specular++;
            ray->prev_hit = 'S';

            /* push radiance */
            ri_vector_copy(&rad, &result->radiance);
            ri_vector_zero(&(result->radiance));

            trace_path(render, ray, result);

            /* pop radiance */
            ri_vector_mul(&(result->radiance),
                      &result->radiance, &material->kt);
            ri_vector_mul(&(result->radiance),
                      &result->radiance, &col);
            ri_vector_scale(&(result->radiance), kt);

            if (hasfresnel) {
                /* add reflection color */

                /* ray.org = ray.org + 0.001 * ray.dir */
                ri_vector_copy(&offset, &reflect_ray);
                ri_vector_scale(&offset, 0.001);
                ri_vector_add(&(ray->org), &rayorg, &offset);

                ri_vector_copy(&(ray->dir), &reflect_ray);
                ri_vector_copy(&col, &result->state.color);

                ray->prev_hit = 'S';

                ri_vector_zero(&ref_result.radiance);
                ref_result.nbound_specular = result->nbound_specular;
                ref_result.nbound_diffuse = result->nbound_diffuse;
                ref_result.state.inside = 0;

                trace_path(render, ray, &ref_result);

                /* pop radiance */
                ri_vector_mul(&(ref_result.radiance),
                          &ref_result.radiance, &col);
                ri_vector_scale(&(ref_result.radiance), kr);
                ri_vector_add(&(result->radiance),
                          &result->radiance, &ref_result.radiance);

            }

            ri_vector_add(&(result->radiance),
                          &result->radiance,
                      &rad);
        }

    //} else if (result->nbound_specular + result->nbound_diffuse < 2) {
    } else {

        /* check if hit light geometry */
        ray->isectt = 0.0f;

        if (light->type == LIGHTTYPE_IBL ||
            light->type == LIGHTTYPE_SUNSKY) {

            ri_texture_ibl_fetch(&(result->radiance),
                         light->texture,
                         &ray->dir);
            result->hit = 1;
            return;    
        } else if (ri_render_get()->background_map) {

            ri_texture_ibl_fetch(&(result->radiance),
                         ri_render_get()->background_map,
                         &ray->dir);
            result->hit = 1;
            return;    

        
        } else {
            if (light->geom) {
                /* area light. */

                lighthit = ri_raytrace_geom(
                        light->geom,
                        ray,
                        &(result->state));            
                if (lighthit) {

                    // light is "seen"
                    result->radiance.e[0] = 1.0;
                    result->radiance.e[1] = 1.0;
                    result->radiance.e[2] = 1.0;
                    result->hit = 1;
                    return;
                }
            } else if (light->type == LIGHTTYPE_DOME) {
                //ri_vector_copy(&(result->radiance),
                //           &(light->col));
                //ri_vector_scale(&(result->radiance),
                //        (float)light->intensity);
            }
        }
    } 
#endif

    return;

}
예제 #9
0
static int
trace_path(pathnode_t *path)
{
	unsigned char     type;		/* type of reflection */
	int               hit;
	int               prev_interior;
	double            bsdf[3];
	ri_vector_t       outdir;
	ri_ray_t          ray;
	ri_intersection_state_t next_state;

	ri_material_t *material;

	if (path->depth >= MAX_PATH_VERTICES) {
		return 0;
	}

	material = path->state.geom->material;

	if (!russian_roulette(material)) {
		return 0;
	}

	type = sample_reflection_type(material);

	prev_interior = path->interior;

	if (path->interior && !floateq(material->ior, 1.0f)) {
		/* ray exits from a transparent object */
		path->interior = 0;
	}

	sample_outdir(&outdir, &type,
		      path->interior, material,
		      path->indir, path->state.Ng);

	if (type == 'T' && prev_interior) {
		/* ray enters into a transparent object */
		path->interior = 1;
	}


	/* find next surface point where ray hits */
	ri_vector_copy(&ray.org, path->state.P);
	ri_vector_copy(&ray.dir, outdir);

	ray.thread_num = 0;

	hit = ri_raytrace(ri_render_get(), &ray, &next_state);
	if (!hit) {
		return 0;	
	}

	brdf(bsdf,
	     type, &path->state,
	     path->indir, outdir, path->state.Ng);
	path->G[0] *= bsdf[0];
	path->G[1] *= bsdf[1];
	path->G[2] *= bsdf[2];

	path->depth++;

	ri_vector_copy(&path->indir, outdir);
	//ri_vector_neg(&path->indir);
	ri_mem_copy(&path->state, &next_state, sizeof(ri_intersection_state_t));
	
	return trace_path(path);

}