Exemple #1
0
void SlideNavmesh::update(const float dt)
{
	if (!m_update && !m_step)
		return;
	m_step = false;

	const float maxSpeed = 1.0f;
	NavmeshAgent* agent = &m_scene.agents[0];
	
	// Find next corner to steer to.
	// Smooth corner finding does a little bit of magic to calculate spline
	// like curve (or first tangent) based on current position and movement direction
	// next couple of corners.
	float corner[2],dir[2];
	int last = 1;
	vsub(dir, agent->pos, agent->oldpos); // This delta handles wall-hugging better than using current velocity.
	vnorm(dir);
	vcpy(corner, agent->pos);
	if (m_moveMode == AGENTMOVE_SMOOTH || m_moveMode == AGENTMOVE_DRUNK)
		last = agentFindNextCornerSmooth(agent, dir, m_scene.nav, corner);
	else
		last = agentFindNextCorner(agent, m_scene.nav, corner);
		
	if (last && vdist(agent->pos, corner) < 0.02f)
	{
		// Reached goal
		vcpy(agent->oldpos, agent->pos);
		vset(agent->dvel, 0,0);
		vcpy(agent->vel, agent->dvel);
		return;
	}

	vsub(agent->dvel, corner, agent->pos);

	// Apply style
	if (m_moveMode == AGENTMOVE_DRUNK)
	{
		agent->t += dt*4;
		float amp = cosf(agent->t)*0.25f;
		float nx = -agent->dvel[1];
		float ny = agent->dvel[0];
		agent->dvel[0] += nx * amp;
		agent->dvel[1] += ny * amp;
	}
	
	// Limit desired velocity to max speed.
	const float distToTarget = vdist(agent->pos,agent->target);
	const float clampedSpeed = maxSpeed * min(1.0f, distToTarget/agent->rad);
	vsetlen(agent->dvel, clampedSpeed);

	vcpy(agent->vel, agent->dvel);

	// Move agent
	vscale(agent->delta, agent->vel, dt);
	float npos[2];
	vadd(npos, agent->pos, agent->delta);
	agentMoveAndAdjustCorridor(&m_scene.agents[0], npos, m_scene.nav);

}
Exemple #2
0
bool SlideNavmesh::mouseDown(const float x, const float y)
{
	if (!m_expanded)
	{
		if (hitCorner(x,y))
		{
			startDrag(1, x,y, m_pos);
			return true;
		}
	}
	else
	{
		int bidx = hitButtons(x-m_pos[0],y-m_pos[1]);
		if (bidx != -1)
		{
			return true;
		}
		else if (hitCorner(x,y))
		{
			startDrag(1, x,y, m_pos);
			return true;
		}
		else if (hitArea(x,y))
		{
			const float lx = x - (m_pos[0]+PADDING_SIZE);
			const float ly = y - (m_pos[1]+PADDING_SIZE);

			float pos[2] = {lx,ly};
			float nearest[2] = {lx,ly};
			if (m_scene.nav)
				navmeshFindNearestTri(m_scene.nav, pos, nearest);
			
			if (SDL_GetModState() & KMOD_SHIFT)
			{
				agentMoveAndAdjustCorridor(&m_scene.agents[0], nearest, m_scene.nav);
				vcpy(m_scene.agents[0].oldpos, m_scene.agents[0].pos);
				vset(m_scene.agents[0].corner, FLT_MAX,FLT_MAX);
			}
			else
			{
				vcpy(m_scene.agents[0].target, nearest);
				vcpy(m_scene.agents[0].oldpos, m_scene.agents[0].pos);
				agentFindPath(&m_scene.agents[0], m_scene.nav);
				vset(m_scene.agents[0].corner, FLT_MAX,FLT_MAX);
			}

			return true;
		}
	}
	return false;
}
Exemple #3
0
/*
 * Find a intersection point for each beam's corner ray onto the triangle
 * plane.
 * Points found may not lie within the triangle.
 */
int
find_isect_pos_onto_the_triangle_plane(
    ri_vector_t   *points,      /* [out]    */
    ri_beam_t     *beam,
    ri_triangle_t *triangle)
{
    int         i;
    ri_vector_t v0, v1, v2; 
    ri_vector_t e1, e2; 
    ri_vector_t p, s, q;
    ri_float_t  a, inva;
    ri_float_t  t;
    double      eps = 1.0e-14;

    vcpy( v0, triangle->v[0] );
    vcpy( v1, triangle->v[1] );
    vcpy( v2, triangle->v[2] );

    vsub( e1, v1, v0 );
    vsub( e2, v2, v0 );

    vsub( s, beam->org, v0 );

    for (i = 0; i < 4; i++) {

        vcross( p, beam->dir[i], e2 );

        a = vdot( e1, p );

        if (fabs(a) > eps) {
            inva = 1.0 / a;
        } else {
            inva = 1.0;
        }

        vcross( q, s, e1 );

        t = vdot( e2, q ) * inva;    
        
        points[i][0] = beam->org[0] + t * beam->dir[i][0];
        points[i][1] = beam->org[1] + t * beam->dir[i][1];
        points[i][2] = beam->org[2] + t * beam->dir[i][2];

    }

    return 0;

}
Exemple #4
0
/*
 * Rasterize beam into 2D raster plane.
 */
void
ri_rasterize_beam(
    ri_raster_plane_t *plane,
    ri_beam_t         *beam,
    ri_triangle_t     *triangle)
{
    int           i;
    int           n;

    ri_vector_t   points[4];            /* Points onto the plane defined by
                                           the triangle.  */

    ri_triangle_t triangles[2];         /* up to 2 triangles.   */

    //
    // Find hit points onto triangle plane.
    // 
    find_isect_pos_onto_the_triangle_plane(
        points,
        beam,
        triangle);

    if (beam->is_tetrahedron) {
        // Raster single triangle.
        
        vcpy(triangles[0].v[0], points[0]);
        vcpy(triangles[0].v[1], points[1]);
        vcpy(triangles[0].v[2], points[2]);
        n = 1;

    } else {
        // Raster 2 triangles.
        
        vcpy(triangles[0].v[0], points[0]);
        vcpy(triangles[0].v[1], points[1]);
        vcpy(triangles[0].v[2], points[2]);
        vcpy(triangles[1].v[0], points[0]);
        vcpy(triangles[1].v[1], points[2]);
        vcpy(triangles[1].v[2], points[3]);
        n = 2;

    }
        
    for (i = 0; i < n; i++) {

        ri_rasterize_triangle(plane, &triangles[i]);

    }

}
Exemple #5
0
static void trace_whitted(
    ri_render_t             *render,
    ri_intersection_state_t *isect,
    ri_transport_info_t     *result,
    int                      depth)
{
    double                      eps = 1.0e-7; 

    int                         hit;
    ri_intersection_state_t     state;
    ri_ray_t                    Rr;
    vec                         Rd;
    ri_ray_t                    Tr;
    vec                         Td;
    ri_float_t                  eta = 1.33;

    if (depth > MAX_TRACE_DEPTH) {
        return;
    }

    //ri_reflect(Rd, isect->I, isect->Ns);
    ri_refract(Rd, isect->I, isect->Ns, 1.33);
    vcpy(Rr.dir, Rd);

    Rr.org[0] = isect->P[0] + eps * Rd[0];
    Rr.org[1] = isect->P[1] + eps * Rd[1];
    Rr.org[2] = isect->P[2] + eps * Rd[2];

    hit = ri_raytrace(render, &Rr, &state);

    if (hit) {

        //vzero(result->radiance);
        trace_whitted(render, &state, result, depth + 1);

    } else {

        /*
         * If the scene has envmap, add contribution from the envmap.
         */
        if (render->scene->envmap_light) {

            ri_texture_ibl_fetch(result->radiance,
                                 render->scene->envmap_light->texture,
                                 Rd); 

        } else {

            vzero(result->radiance);
        
        }

    }

}
Exemple #6
0
void
sample_distant_light(
    ri_vector_t                      Lo,                /* [out]            */
    ri_bvh_t                        *bvh,
    const ri_intersection_state_t   *isect,
    ri_vector_t                      Ldir,              /* normalized       */
    ri_vector_t                      Lcol,
    int                              debug)
{
    (void)debug;

    int                         hit;
    ri_ray_t                    ray;
    ri_intersection_state_t     state;
    ri_float_t                  dot;

    vcpy(ray.org, isect->P);
    ray.org[0] += isect->Ns[0] * 0.00001;
    ray.org[1] += isect->Ns[1] * 0.00001;
    ray.org[2] += isect->Ns[2] * 0.00001;

    vcpy(ray.dir, Ldir);

    hit = ri_bvh_intersect( (void *)bvh, &ray, &state, NULL );

    if (hit) {
        /* There's obscrances between the shading point and the light */
        vzero(Lo);
    } else {
        /* Lo = L cosTheta */
        dot = vdot(Ldir, isect->Ns);
        if (dot < 0.0) dot = 0.0;

        Lo[0] = Lcol[0] * dot;
        Lo[1] = Lcol[1] * dot;
        Lo[2] = Lcol[2] * dot;
    }

}
Exemple #7
0
/*
 * Add the vertex to output.
 */
void
output(
    point2d_t   *list_out,          /* [out]    */
    int         *len_inout,         /* [inout]  */
    point2d_t    p)
{
    int idx;

    idx = (*len_inout);

    vcpy( list_out[idx], p );

    (*len_inout)++;
}
static int
contribution_from_sunlight(
    vec                            Lo,
    const ri_ray_t                *inray,
    const ri_intersection_state_t *isect)
{
    ri_list_t               *light_list;
    ri_light_t              *light;

    int                      hit;
    ri_ray_t                 ray;
    ri_intersection_state_t  state;

    double                   eps = 1.0e-5;

    for (light_list = ri_list_first(ri_render_get()->scene->light_list);
         light_list != NULL;
         light_list = ri_list_next(light_list)) {

        light = (ri_light_t *)light_list->data;

        if (light->type != LIGHTTYPE_SUNLIGHT) continue;

        vcpy(ray.org, isect->P);
        ray.org[0] += isect->Ns[0] * eps;
        ray.org[1] += isect->Ns[1] * eps;
        ray.org[2] += isect->Ns[2] * eps;

        ray.dir[0] = light->direction[0];
        ray.dir[1] = light->direction[1];
        ray.dir[2] = light->direction[2];

        ray.thread_num = inray->thread_num;

        hit = ri_raytrace(ri_render_get(), &ray, &state);

        if (!hit) {

            Lo[0] += light->col[0];
            Lo[1] += light->col[1];
            Lo[2] += light->col[2];

        }

    }
            
}
void sph_model::zoom(double *w, const double *v)
{
    double d = vdot(v, zoomv);
    
    if (-1 < d && d < 1)
    {
        double b = scale(zoomk, acos(d) / M_PI) * M_PI;
                
        double y[3];
        double x[3];
        
        vcrs(y, v, zoomv);
        vnormalize(y, y);
        vcrs(x, zoomv, y);
        vnormalize(x, x);
        
        vmul(w, zoomv, cos(b));
        vmad(w, w,  x, sin(b));
    }
    else vcpy(w, v);
}
Exemple #10
0
void KX_ObstacleSimulation::UpdateObstacles()
{
	for (size_t i=0; i<m_obstacles.size(); i++)
	{
		if (m_obstacles[i]->m_type==KX_OBSTACLE_NAV_MESH || m_obstacles[i]->m_shape==KX_OBSTACLE_SEGMENT)
			continue;

		KX_Obstacle* obs = m_obstacles[i];
		obs->m_pos = obs->m_gameObj->NodeGetWorldPosition();
		obs->vel[0] = obs->m_gameObj->GetLinearVelocity().x();
		obs->vel[1] = obs->m_gameObj->GetLinearVelocity().y();

		// Update velocity history and calculate perceived (average) velocity.
		vcpy(&obs->hvel[obs->hhead*2], obs->vel);
		obs->hhead = (obs->hhead+1) % VEL_HIST_SIZE;
		vset(obs->pvel,0,0);
		for (int j = 0; j < VEL_HIST_SIZE; ++j)
			vadd(obs->pvel, obs->pvel, &obs->hvel[j*2]);
		vscale(obs->pvel, obs->pvel, 1.0f/VEL_HIST_SIZE);
	}
}
Exemple #11
0
void view_move(view *V, const double *v)
{
    assert(V);
    vcpy(V->v, v);
}
Exemple #12
0
int
ri_raster_plane_setup(
    ri_raster_plane_t *plane_inout,     /* [inout]  */
    int                width,
    int                height,
    ri_vector_t        frame[3],
    ri_vector_t        corner,
    ri_vector_t        org,
    ri_float_t         fov)
{
    
    size_t sz;

    sz = width * height;

    plane_inout->width  = width;
    plane_inout->height = height;

    if (plane_inout->t    ) ri_mem_free(plane_inout->t);
    if (plane_inout->u    ) ri_mem_free(plane_inout->u);
    if (plane_inout->v    ) ri_mem_free(plane_inout->v);
    if (plane_inout->geom ) ri_mem_free(plane_inout->geom);
    if (plane_inout->index) ri_mem_free(plane_inout->index);

    plane_inout->t      = (ri_float_t  *)ri_mem_alloc(sizeof(ri_float_t ) * sz);
    plane_inout->u      = (ri_float_t  *)ri_mem_alloc(sizeof(ri_float_t ) * sz);
    plane_inout->v      = (ri_float_t  *)ri_mem_alloc(sizeof(ri_float_t ) * sz);
    plane_inout->geom   = (ri_geom_t  **)ri_mem_alloc(sizeof(ri_geom_t *) * sz);
    plane_inout->index  = (uint32_t    *)ri_mem_alloc(sizeof(uint32_t   ) * sz);

    memset(plane_inout->t    , 0, sizeof(ri_float_t ) * sz);
    memset(plane_inout->u    , 0, sizeof(ri_float_t ) * sz);
    memset(plane_inout->v    , 0, sizeof(ri_float_t ) * sz);
    memset(plane_inout->geom , 0, sizeof(ri_geom_t *) * sz);
    memset(plane_inout->index, 0, sizeof(uint32_t   ) * sz);

    memcpy(plane_inout->frame, frame, sizeof(ri_vector_t) * 3);
    vcpy( plane_inout->corner, corner );
    vcpy( plane_inout->org   , org    );
    plane_inout->fov = fov;

    /*
     * Project lower-left point onto NDC coord. 
     */

    /*
     * p  = M F v
     * p' = p / p.z        - [0, 1)^2 
     *
     *      |     1                                |
     * M  = | ----------         0          0   0  |
     *      | tan(fov/2)                           |
     *      |                                      |
     *      |                    1                 |
     *      |      0         ----------     0   0  |
     *      |                tan(fov/2)            |
     *      |                                      |
     *      |      0             0          1   0  |
     *      |                                      |
     *      |      0             0         -1   0  |
     *
     *  F = |  du_x  du_y  du_z     0 |
     *      |  dv_x  dv_y  dv_z     0 |
     *      | -dw_x -dw_y -dw_z     0 |
     *      |     0     0     0     0 |
     *
     *  v = | x |
     *      | y |
     *      | z |
     *      | w |
     */

    {
        vec        vo;
        vec        w;
        vec        p;
        ri_float_t fov_rad  = plane_inout->fov * M_PI / 180.0;

        /* vo = v */
        vcpy( vo, plane_inout->corner );
            
        /* w = F v */
        w[0] =  plane_inout->frame[0][0] * vo[0]
             +  plane_inout->frame[0][1] * vo[1] 
             +  plane_inout->frame[0][2] * vo[2];
        w[1] =  plane_inout->frame[1][0] * vo[0] 
             +  plane_inout->frame[1][1] * vo[1] 
             +  plane_inout->frame[1][2] * vo[2];
        w[2] = -plane_inout->frame[2][0] * vo[0] 
             -  plane_inout->frame[2][1] * vo[1] 
             -  plane_inout->frame[2][2] * vo[2];

        /* p = M F v */
        p[0] = (1.0 / tan(0.5 * fov_rad)) * w[0];
        p[1] = (1.0 / tan(0.5 * fov_rad)) * w[1];
        p[2] = w[2];

        p[0] /= -w[2];       /* w = -z   */
        p[1] /= -w[2];

        printf("[raster] lowerleft = %f, %f\n", p[0], p[1]);

        plane_inout->offset[0] = p[0];
        plane_inout->offset[1] = p[1];
    }


    return 0;
}
Exemple #13
0
/*
 * Function: ri_bem_set
 *
 *   Setups a beam structure.
 *
 *
 * Parameters:
 *
 *   beam   - Pointer to the beam to be set up. 
 *   org    - Origin of beam.
 *   dir[4] - Corner rays of beam. 
 *
 *
 * Returns:
 *
 *   0 if OK, otherwise if err
 */
int
ri_beam_set(
    ri_beam_t   *beam,      /* [inout]  */
    ri_vector_t  org,
    ri_vector_t  dir[4])
{
    int        i, j;
    int        mask;
    int        dominant_axis;
    int        zeros;
    ri_float_t maxval;  

    beam->d     = 1024.0;
    beam->t_max = RI_INFINITY;

    /*
     * Check if beam's directions lie in same quadrant.
     */
    for (i = 0; i < 3; i++) {

        zeros = 0;
        mask  = 0;

        for (j = 0; j < 4; j++) {
            if (fabs(dir[j][i]) < RI_EPS) {
                zeros++;
            } else {
                mask  += (dir[j][i] <  0.0) ? 1 : -1;
            }
        }

        if ( (mask != -(4 - zeros)) && (mask != (4 - zeros)) ) {

            /* FIXME:
             * split beam so that subdivided beam has same sign.
             */
            fprintf(stderr, "TODO: Beam's dir does not have same sign.\n");

            for (j = 0; j < 4; j++) {
                fprintf(stderr, "      dir[%d] = %f, %f, %f\n", j,
                    dir[j][0], dir[j][1], dir[j][2]);
            }

            return -1;

        }

    }

    vcpy( beam->org,    org    );

    /*
     * Find dominant plane. Use dir[0]
     */
    maxval        = fabs(dir[0][0]);
    dominant_axis = 0;
    if ( (maxval < fabs(dir[0][1])) ) {
        maxval        = fabs(dir[0][0]);
        dominant_axis = 1;
    }
    if ( (maxval < fabs(dir[0][2])) ) {
        maxval        = fabs(dir[0][2]);
        dominant_axis = 2;
    }
         
    beam->dominant_axis = dominant_axis;

    /*
     * Precompute sign of direction.
     * We know all 4 directions has same sign, thus dir[0] is used to
     * get sign of direction for each axis.
     */
    beam->dirsign[0] = (dir[0][0] < 0.0) ? 1 : 0;
    beam->dirsign[1] = (dir[0][1] < 0.0) ? 1 : 0;
    beam->dirsign[2] = (dir[0][2] < 0.0) ? 1 : 0;


    /*
     * Project beam dir onto axis-alied plane.
     */
    {

        ri_vector_t normals[3] = {
            { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 } };
        ri_vector_t normal;
        ri_float_t  t;
        ri_float_t  k;

        vcpy( normal, normals[beam->dominant_axis] );
        
        if (beam->dirsign[beam->dominant_axis]) {
            vneg( normal );
        }


        for (i = 0; i < 4; i++) {

            t = vdot( dir[i], normal );
            
            if (fabs(t) > RI_EPS) {
                k = beam->d / t;
            } else {
                k = 1.0;
            }

            beam->dir[i][0] = k * dir[i][0];
            beam->dir[i][1] = k * dir[i][1];
            beam->dir[i][2] = k * dir[i][2];
            
        }

    }


    /*
     * Precompute inverse of direction
     */
    for (i = 0; i < 4; i++) {
        beam->invdir[i][0] = safeinv( beam->dir[i][0], RI_EPS, RI_FLT_MAX );
        beam->invdir[i][1] = safeinv( beam->dir[i][1], RI_EPS, RI_FLT_MAX );
        beam->invdir[i][2] = safeinv( beam->dir[i][2], RI_EPS, RI_FLT_MAX );
    }

    /*
     * Precompute normal plane of beam frustum
     */
    vcross( beam->normal[0], beam->dir[1], beam->dir[0] );
    vcross( beam->normal[1], beam->dir[2], beam->dir[1] );
    vcross( beam->normal[2], beam->dir[3], beam->dir[2] );
    vcross( beam->normal[3], beam->dir[0], beam->dir[3] );

    beam->is_tetrahedron = 0;

    return 0;   /* OK   */
}
/*
 * Derived version of ambient occlusion: gather sunsky color instead of
 * just computing occlusion. 
 */
static int
gather_sunsky(
    ri_vector_t                    Lo,              /* [out] */
    const ri_ray_t                *inray,
    const ri_intersection_state_t *isect,
    uint32_t                       ntheta_samples,
    uint32_t                       nphi_samples)
{
    int                     hit;
    uint32_t                i, j, k;
    int                     thread_id = 0;

    double                  z0, z1;
    double                  cos_theta, phi;
    double                  eps = 1.0e-5;

    vec                     dir;
    vec                     basis[3];
    vec                     col;

    float                   sunskycol[3];
    float                   v[3];

    ri_ray_t                ray;
    ri_intersection_state_t state;

    ri_ortho_basis(basis, isect->Ns);

    vcpy(ray.org, isect->P);
    vzero(col);

    /*
     * Slightly move the shading point towards the surface normal.
     * FIXME: Choose eps relative to scene scale, not as an absolute value.
     */
    ray.org[0] += isect->Ns[0] * eps;
    ray.org[1] += isect->Ns[1] * eps;
    ray.org[2] += isect->Ns[2] * eps;

    thread_id = inray->thread_num;
    assert(thread_id >=  0);
    assert(thread_id <  16);

    ray.thread_num = thread_id;

    for (j = 0; j < nphi_samples; j++) {
        for (i = 0; i < ntheta_samples; i++) {

            /*
             * 1. Choose random ray direction over the hemisphere.
             */

            /* Simple stratified sampling */
            z0 = (i + randomMT2(thread_id)) / (double)ntheta_samples;
            z1 = (j + randomMT2(thread_id)) / (double)nphi_samples;

            /* Do importance sampling. the probability function is,
             *
             * p(x) ~ cos(theta) / PI (against with differential solid angle)
             *
             * -> theta = acos(sqrt(z_0))
             *    phi   = 2 PI z_1
             *
             */
            cos_theta = sqrt(z0);
            phi       = 2.0 * M_PI * z1;

            dir[0]    = cos(phi) * cos_theta;
            dir[1]    = sin(phi) * cos_theta;
            dir[2]    = sqrt(1.0 - cos_theta * cos_theta);
    

            /* 'dir' is defined in local coord.
             * Convert it into global coord.
             */
            for (k = 0; k < 3; k++) {
                ray.dir[k] = dir[0]*basis[0][k]
                           + dir[1]*basis[1][k]
                           + dir[2]*basis[2][k];
            }

            /*
             * 2. Do raytracing to check visibility.
             */

            hit = ri_raytrace(ri_render_get(), &ray, &state);

            if (!hit) {

                v[0] = ray.dir[0];
                v[1] = ray.dir[1];
                v[2] = ray.dir[2];

                ri_sunsky_get_sky_rgb(
                    sunskycol,
                    ri_render_get()->scene->sunsky_light->sunsky,
                    v); 
                    
                col[0] += sunskycol[0];
                col[1] += sunskycol[1];
                col[2] += sunskycol[2];

            }
        }
    }

    /*
     * Add contribution from sun.
     */
    contribution_from_sunlight(col, inray, isect);

    double nsamples = ntheta_samples * nphi_samples;
    double m =(1.0 / M_PI);
    Lo[0] = m * col[0] / nsamples;
    Lo[1] = m * col[1] / nsamples;
    Lo[2] = m * col[2] / nsamples;

    return 0;   /* OK */
}
static int
calculate_occlusion(
    ri_vector_t                    Lo,              /* [out] */
    const ri_ray_t                *inray,
    const ri_intersection_state_t *isect,
    uint32_t                       ntheta_samples,
    uint32_t                       nphi_samples)
{
    int                     hit;
    uint32_t                i, j, k;
    int                     thread_id = 0;

    double                  z0, z1;
    double                  cos_theta, phi;
    double                  eps = 1.0e-6;
    double                  occlusion = 0.0;

    vec                     dir;
    vec                     basis[3];

    ri_ray_t                ray;
    ri_intersection_state_t state;

    ri_ortho_basis(basis, isect->Ns);

    vcpy(ray.org, isect->P);

    /*
     * Slightly move the shading point towards the surface normal.
     * FIXME: Choose eps relative to scene scale, not as an absolute value.
     */
    ray.org[0] += isect->Ns[0] * eps;
    ray.org[1] += isect->Ns[1] * eps;
    ray.org[2] += isect->Ns[2] * eps;

    thread_id = inray->thread_num;
    assert(thread_id >=  0);
    assert(thread_id <  16);

    ray.thread_num = thread_id;

    for (j = 0; j < nphi_samples; j++) {
        for (i = 0; i < ntheta_samples; i++) {

            /*
             * 1. Choose random ray direction over the hemisphere.
             */

            /* Simple stratified sampling */
            z0 = (i + randomMT2(thread_id)) / (double)ntheta_samples;
            z1 = (j + randomMT2(thread_id)) / (double)nphi_samples;

            /* Do importance sampling. the probability function is,
             *
             * p(x) ~ cos(theta) / PI (against with differential solid angle)
             *
             * -> theta = acos(sqrt(z_0))
             *    phi   = 2 PI z_1
             *
             */
            cos_theta = sqrt(z0);
            phi       = 2.0 * M_PI * z1;

            dir[0]    = cos(phi) * cos_theta;
            dir[1]    = sin(phi) * cos_theta;
            dir[2]    = sqrt(1.0 - cos_theta * cos_theta);
    

            /* 'dir' is defined in local coord.
             * Convert it into global coord.
             */
            for (k = 0; k < 3; k++) {
                ray.dir[k] = dir[0]*basis[0][k]
                           + dir[1]*basis[1][k]
                           + dir[2]*basis[2][k];
            }

            /*
             * 2. Do raytracing to check visibility.
             */

            hit = ri_raytrace(ri_render_get(), &ray, &state);

            if (hit) {

                /* There's an occluder. */
                occlusion += 1.0;
            }

        }
    }

    /*
     * Turn occlusion value into color(radiance)
     *
     *  Lo = m * (N - occlusion) / N
     *
     *    where N = ntheta * nphi
     *          m = pi              if phisically accurate value is required.
     *              1.0             otherwise
     */
    double nsamples = ntheta_samples * nphi_samples;
    double m = 1.0; // (1.0 / M_PI)
    Lo[0] = m * (nsamples - occlusion) / nsamples;
    Lo[1] = m * (nsamples - occlusion) / nsamples;
    Lo[2] = m * (nsamples - occlusion) / nsamples;


    return 0;   /* OK */
}
Exemple #16
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;

}
Exemple #17
0
void KX_ObstacleSimulationTOI_cells::sampleRVO(KX_Obstacle* activeObst, KX_NavMeshObject* activeNavMeshObj, 
					   const float maxDeltaAngle)
{
	vset(activeObst->nvel, 0.f, 0.f);
	float vmax = vlen(activeObst->dvel);

	float* spos = new float[2*m_maxSamples];
	int nspos = 0;

	if (!m_adaptive)
	{
		const float cvx = activeObst->dvel[0]*m_bias;
		const float cvy = activeObst->dvel[1]*m_bias;
		float vmax = vlen(activeObst->dvel);
		const float vrange = vmax*(1-m_bias);
		const float cs = 1.0f / (float)m_sampleRadius*vrange;

		for (int y = -m_sampleRadius; y <= m_sampleRadius; ++y)
		{
			for (int x = -m_sampleRadius; x <= m_sampleRadius; ++x)
			{
				if (nspos < m_maxSamples)
				{
					const float vx = cvx + (float)(x+0.5f)*cs;
					const float vy = cvy + (float)(y+0.5f)*cs;
					if (vx*vx+vy*vy > sqr(vmax+cs/2)) continue;
					spos[nspos*2+0] = vx;
					spos[nspos*2+1] = vy;
					nspos++;
				}
			}
		}
		processSamples(activeObst, activeNavMeshObj, m_obstacles, m_levelHeight, vmax, spos, cs/2, 
			nspos,  activeObst->nvel, m_maxToi, m_velWeight, m_curVelWeight, m_collisionWeight, m_toiWeight);
	}
	else
	{
		int rad;
		float res[2];
		float cs;
		// First sample location.
		rad = 4;
		res[0] = activeObst->dvel[0]*m_bias;
		res[1] = activeObst->dvel[1]*m_bias;
		cs = vmax*(2-m_bias*2) / (float)(rad-1);

		for (int k = 0; k < 5; ++k)
		{
			const float half = (rad-1)*cs*0.5f;

			nspos = 0;
			for (int y = 0; y < rad; ++y)
			{
				for (int x = 0; x < rad; ++x)
				{
					const float vx = res[0] + x*cs - half;
					const float vy = res[1] + y*cs - half;
					if (vx*vx+vy*vy > sqr(vmax+cs/2)) continue;
					spos[nspos*2+0] = vx;
					spos[nspos*2+1] = vy;
					nspos++;
				}
			}

			processSamples(activeObst, activeNavMeshObj, m_obstacles, m_levelHeight, vmax, spos, cs/2, 
				nspos,  res, m_maxToi, m_velWeight, m_curVelWeight, m_collisionWeight, m_toiWeight);

			cs *= 0.5f;
		}
		vcpy(activeObst->nvel, res);
	}
}
Exemple #18
0
static void processSamples(KX_Obstacle* activeObst, KX_NavMeshObject* activeNavMeshObj, 
						   KX_Obstacles& obstacles,  float levelHeight, const float vmax,
						   const float* spos, const float cs, const int nspos, float* res, 						   
						   float maxToi, float velWeight, float curVelWeight, float sideWeight,
						   float toiWeight)
{
	vset(res, 0,0);

	const float ivmax = 1.0f / vmax;

	float adir[2], adist;
	vcpy(adir, activeObst->pvel);
	if (vlen(adir) > 0.01f)
		vnorm(adir);
	else
		vset(adir,0,0);
	float activeObstPos[2];
	vset(activeObstPos, activeObst->m_pos.x(), activeObst->m_pos.y()); 
	adist = vdot(adir, activeObstPos);

	float minPenalty = FLT_MAX;

	for (int n = 0; n < nspos; ++n)
	{
		float vcand[2];
		vcpy(vcand, &spos[n*2]);		

		// Find min time of impact and exit amongst all obstacles.
		float tmin = maxToi;
		float side = 0;
		int nside = 0;

		for (int i = 0; i < obstacles.size(); ++i)
		{
			KX_Obstacle* ob = obstacles[i];
			bool res = filterObstacle(activeObst, activeNavMeshObj, ob, levelHeight);
			if (!res)
				continue;
			float htmin, htmax;

			if (ob->m_shape==KX_OBSTACLE_CIRCLE)
			{
				float vab[2];

				// Moving, use RVO
				vscale(vab, vcand, 2);
				vsub(vab, vab, activeObst->vel);
				vsub(vab, vab, ob->vel);

				// Side
				// NOTE: dp, and dv are constant over the whole calculation,
				// they can be precomputed per object. 
				const float* pa = activeObstPos;
				float pb[2];
				vset(pb, ob->m_pos.x(), ob->m_pos.y());

				const float orig[2] = {0,0};
				float dp[2],dv[2],np[2];
				vsub(dp,pb,pa);
				vnorm(dp);
				vsub(dv,ob->dvel, activeObst->dvel);

				const float a = triarea(orig, dp,dv);
				if (a < 0.01f)
				{
					np[0] = -dp[1];
					np[1] = dp[0];
				}
				else
				{
					np[0] = dp[1];
					np[1] = -dp[0];
				}

				side += clamp(min(vdot(dp,vab)*2,vdot(np,vab)*2), 0.0f, 1.0f);
				nside++;

				if (!sweepCircleCircle(activeObst->m_pos, activeObst->m_rad, vab, ob->m_pos, ob->m_rad, 
					htmin, htmax))
					continue;

				// Handle overlapping obstacles.
				if (htmin < 0.0f && htmax > 0.0f)
				{
					// Avoid more when overlapped.
					htmin = -htmin * 0.5f;
				}
			}
			else if (ob->m_shape == KX_OBSTACLE_SEGMENT)
			{
				MT_Point3 p1 = ob->m_pos;
				MT_Point3 p2 = ob->m_pos2;
				//apply world transform
				if (ob->m_type == KX_OBSTACLE_NAV_MESH)
				{
					KX_NavMeshObject* navmeshobj = static_cast<KX_NavMeshObject*>(ob->m_gameObj);
					p1 = navmeshobj->TransformToWorldCoords(p1);
					p2 = navmeshobj->TransformToWorldCoords(p2);
				}
				float p[2], q[2];
				vset(p, p1.x(), p1.y());
				vset(q, p2.x(), p2.y());

				// NOTE: the segments are assumed to come from a navmesh which is shrunken by
				// the agent radius, hence the use of really small radius.
				// This can be handle more efficiently by using seg-seg test instead.
				// If the whole segment is to be treated as obstacle, use agent->rad instead of 0.01f!
				const float r = 0.01f; // agent->rad
				if (distPtSegSqr(activeObstPos, p, q) < sqr(r+ob->m_rad))
				{
					float sdir[2], snorm[2];
					vsub(sdir, q, p);
					snorm[0] = sdir[1];
					snorm[1] = -sdir[0];
					// If the velocity is pointing towards the segment, no collision.
					if (vdot(snorm, vcand) < 0.0f)
						continue;
					// Else immediate collision.
					htmin = 0.0f;
					htmax = 10.0f;
				}
				else
				{
					if (!sweepCircleSegment(activeObstPos, r, vcand, p, q, ob->m_rad, htmin, htmax))
						continue;
				}

				// Avoid less when facing walls.
				htmin *= 2.0f;
			}

			if (htmin >= 0.0f)
			{
				// The closest obstacle is somewhere ahead of us, keep track of nearest obstacle.
				if (htmin < tmin)
					tmin = htmin;
			}
		}

		// Normalize side bias, to prevent it dominating too much.
		if (nside)
			side /= nside;

		const float vpen = velWeight * (vdist(vcand, activeObst->dvel) * ivmax);
		const float vcpen = curVelWeight * (vdist(vcand, activeObst->vel) * ivmax);
		const float spen = sideWeight * side;
		const float tpen = toiWeight * (1.0f/(0.1f+tmin/maxToi));

		const float penalty = vpen + vcpen + spen + tpen;

		if (penalty < minPenalty)
		{
			minPenalty = penalty;
			vcpy(res, vcand);
		}
	}
}