예제 #1
0
파일: ALu.c 프로젝트: johndpope/Medusa
/* Calculates the fade time from the changes in gain and listener to source
 * angle between updates. The result is a the time, in seconds, for the
 * transition to complete.
 */
static ALfloat CalcFadeTime(ALfloat oldGain, ALfloat newGain, const aluVector *olddir, const aluVector *newdir)
{
    ALfloat gainChange, angleChange, change;

    /* Calculate the normalized dB gain change. */
    newGain = maxf(newGain, 0.0001f);
    oldGain = maxf(oldGain, 0.0001f);
    gainChange = fabsf(log10f(newGain / oldGain) / log10f(0.0001f));

    /* Calculate the angle change only when there is enough gain to notice it. */
    angleChange = 0.0f;
    if(gainChange > 0.0001f || newGain > 0.0001f)
    {
        /* No angle change when the directions are equal or degenerate (when
         * both have zero length).
         */
        if(newdir->v[0] != olddir->v[0] || newdir->v[1] != olddir->v[1] || newdir->v[2] != olddir->v[2])
        {
            ALfloat dotp = aluDotproduct(olddir, newdir);
            angleChange = acosf(clampf(dotp, -1.0f, 1.0f)) / F_PI;
        }
    }

    /* Use the largest of the two changes, and apply a significance shaping
     * function to it. The result is then scaled to cover a 15ms transition
     * range.
     */
    change = maxf(angleChange * 25.0f, gainChange) * 2.0f;
    return minf(change, 1.0f) * 0.015f;
}
예제 #2
0
std::pair<int, int> find_min_max(int a[], int length)
{
    int min(0), max(0), i(0); 
    if (length % 2)
    {
        min = a[0];
        max = a[0];
        i = 1;
    }
    else
    {
        min = minf(a[0], a[1]);
        max = maxf(a[0], a[1]);
        i = 2;
    }
    for (; i < length; i += 2)
    {
        int min2(0), max2(0);
        if (a[i] < a[i+1])
        {
            min2 = a[i];
            max2 = a[i+1];
        }
        else
        {
            max2 = a[i];
            min2 = a[i+1];
        }
        min = minf(min, min2);
        max = maxf(max, max2);
    }

    return std::make_pair(min, max);
}
static void morpho_dilate(CompBuf *cbuf)
{
	int x, y;
	float *p, *rectf = cbuf->rect;
	
	for (y = 0; y < cbuf->y; y++) {
		for (x = 0; x < cbuf->x - 1; x++) {
			p = rectf + cbuf->x * y + x;
			*p = maxf(*p, *(p + 1));
		}
	}

	for (y = 0; y < cbuf->y; y++) {
		for (x = cbuf->x - 1; x >= 1; x--) {
			p = rectf + cbuf->x * y + x;
			*p = maxf(*p, *(p - 1));
		}
	}

	for (x = 0; x < cbuf->x; x++) {
		for (y = 0; y < cbuf->y - 1; y++) {
			p = rectf + cbuf->x * y + x;
			*p = maxf(*p, *(p + cbuf->x));
		}
	}

	for (x = 0; x < cbuf->x; x++) {
		for (y = cbuf->y - 1; y >= 1; y--) {
			p = rectf + cbuf->x * y + x;
			*p = maxf(*p, *(p - cbuf->x));
		}
	}
}
예제 #4
0
파일: scene.cpp 프로젝트: tuxerr/City
Vec3<float> Scene::calculate_shadowing_optimal_point(Vec3<float> near_values[4],Vec3<float> far_values[4], float &radius) {
    float max_top=near_values[0].y,max_bot=near_values[0].y,max_right=near_values[0].x,max_left=near_values[0].x;

    float depth=0;

    for(int i=0;i<4;i++) {
        float cur_max_right = maxf(near_values[i].x,far_values[i].x);
        float cur_max_left = minf(near_values[i].x,far_values[i].x);
        float cur_max_top = maxf(near_values[i].y,far_values[i].y);
        float cur_max_bot = minf(near_values[i].y,far_values[i].y);

        max_top=maxf(max_top,cur_max_top);
        max_bot=minf(max_bot,cur_max_bot);
        max_right=maxf(max_right,cur_max_right);
        max_left=minf(max_left,cur_max_left);
        
        depth+=(near_values[0].z+far_values[0].z);
    }

    float max_height=max_top-max_bot;
    float max_width=max_right-max_left;

    radius=maxf(max_height,max_width);
    return Vec3<float>((max_right+max_left)/2,(max_top+max_bot)/2,depth/8);
}
예제 #5
0
파일: frustum.cpp 프로젝트: hglm/sre
void sreScissors::UpdateWithProjectedPoint(float x, float y, double z) {
    if (z >= - 1.001d) {
        // Beyond the near plane.
        z = maxd(- 1.0d, z);
        double depth = 0.5d * z + 0.5d;
        near = mind(depth, near);
        far = maxd(depth, far);
        left = minf(x, left);
        right = maxf(x, right);
        bottom = minf(y, bottom);
        top = maxf(y, top);
        return;
    }
    sreMessage(SRE_MESSAGE_WARNING,
        "Unexpected vertex in front of the near plane in UpdateWorldSpaceBoundingHull "
        "z = %lf", z);
    // In front of the near plane.
    near = 0;
    far = 1.0;
    // We know that the light volume intersects the frustum, so it must extend to
    // both sides of the near plane.
    // Assume it fills the whole viewport (not optimal).
    left = - 1.0f;
    right = 1.0f;
    bottom = - 1.0f;
    top = 1.0f;
}
예제 #6
0
/* Calculates the normalized HRTF transition factor (delta) from the changes
 * in gain and listener to source angle between updates.  The result is a
 * normalized delta factor that can be used to calculate moving HRIR stepping
 * values.
 */
ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], const ALfloat newdir[3])
{
    ALfloat gainChange, angleChange, change;

    // Calculate the normalized dB gain change.
    newGain = maxf(newGain, 0.0001f);
    oldGain = maxf(oldGain, 0.0001f);
    gainChange = fabsf(log10f(newGain / oldGain) / log10f(0.0001f));

    // Calculate the normalized listener to source angle change when there is
    // enough gain to notice it.
    angleChange = 0.0f;
    if(gainChange > 0.0001f || newGain > 0.0001f)
    {
        // No angle change when the directions are equal or degenerate (when
        // both have zero length).
        if(newdir[0]-olddir[0] || newdir[1]-olddir[1] || newdir[2]-olddir[2])
            angleChange = acosf(olddir[0]*newdir[0] +
                                olddir[1]*newdir[1] +
                                olddir[2]*newdir[2]) / F_PI;

    }

    // Use the largest of the two changes for the delta factor, and apply a
    // significance shaping function to it.
    change = maxf(angleChange * 25.0f, gainChange) * 2.0f;
    return minf(change, 1.0f);
}
예제 #7
0
void cmp_model_debug(struct cmp_obj* obj, void* data, cmphandle_t cur_hdl, float dt,
		const struct gfx_view_params* params)
{
	struct cmp_model* m = (struct cmp_model*)data;

    if (m->model_hdl == INVALID_HANDLE)
        return;
    struct gfx_model* gmodel = rs_get_model(m->model_hdl);
    if (gmodel == NULL)
        return;

	gfx_canvas_setztest(TRUE);
	gfx_canvas_setwireframe(TRUE, TRUE);

	uint tri_cnt = 0;
	uint vert_cnt = 0;
	for (uint i = 0; i < gmodel->node_cnt; i++)	{
		struct cmp_xform* xf = (struct cmp_xform*)cmp_getinstancedata(m->xforms[i]);
		struct vec4f node_pos;
		mat3_get_trans(&node_pos, &xf->ws_mat);

		gfx_canvas_text3d(gmodel->nodes[i].name, &node_pos, &params->viewproj);
        gfx_canvas_setztest(FALSE);
        gfx_canvas_coords(&xf->ws_mat, &params->cam_pos, 0.2f);
		if (gmodel->nodes[i].mesh_id != INVALID_INDEX)	{
            struct gfx_model_mesh* gmesh = &gmodel->meshes[gmodel->nodes[i].mesh_id];
            struct gfx_model_geo* geo = &gmodel->geos[gmesh->geo_id];
            /* either draw skeleton or wireframe mesh */
            if (geo->skeleton != NULL) {
                struct gfx_model_instance* inst = m->model_inst;
                gfx_canvas_setztest(FALSE);
                float scale =  maxf(aabb_getwidth(&gmodel->bb),
                    maxf(aabb_getheight(&gmodel->bb), aabb_getdepth(&gmodel->bb)));
                scale *= 0.05f;
                cmp_model_drawpose(geo, inst->poses[gmesh->geo_id], params, &xf->ws_mat, scale);
                gfx_canvas_setztest(TRUE);
            }   else    {
                gfx_canvas_setfillcolor_solid(&g_color_yellow);
                gfx_canvas_geo(geo, &xf->ws_mat);
            }
            tri_cnt += geo->tri_cnt;
            vert_cnt += geo->vert_cnt;
		}
	}

	/* model info */
	char info[64];
	struct vec4f farpt;
    gfx_canvas_settextcolor(&g_color_grey);
	cmp_bounds_getfarcorner(&farpt, obj->bounds_cmp, &params->cam_pos);
	sprintf(info, "node_cnt: %d\ntri_cnt: %d\nvertex_cnt: %d", gmodel->node_cnt,
			tri_cnt, vert_cnt);
	gfx_canvas_text3dmultiline(info, &farpt, &params->viewproj);

    gfx_canvas_setfillcolor_solid(&g_color_white);
    gfx_canvas_settextcolor(&g_color_white);
    gfx_canvas_setwireframe(FALSE, TRUE);
}
예제 #8
0
파일: field.c 프로젝트: aki5/marchester
static float
cube(float *pos, float *size)
{
	float d[3];
	float dst;
	abs3f(d, pos);
	sub3f(d, d, size);
	dst = minf(maxf(d[0], maxf(d[1],d[2])),0.0);	
	max3f(d, d,(float[]){0,0,0});
예제 #9
0
파일: prims.c 프로젝트: ataceyhun/libdhcore
struct aabb* aabb_merge(struct aabb* rb, const struct aabb* b1, const struct aabb* b2)
{
    struct vec4f minpt;
    struct vec4f maxpt;

    vec3_setf(&minpt, minf(b1->minpt.x, b2->minpt.x), minf(b1->minpt.y, b2->minpt.y),
              minf(b1->minpt.z, b2->minpt.z));
    vec3_setf(&maxpt, maxf(b1->maxpt.x, b2->maxpt.x), maxf(b1->maxpt.y, b2->maxpt.y),
              maxf(b1->maxpt.z, b2->maxpt.z));
    return aabb_setv(rb, &minpt, &maxpt);
}
예제 #10
0
int main(void) {
	int a = 10, b = 20;
	std::cout << "MAXM1 = " << MAXM(a, b) << std::endl;
	std::cout << "MAXM2 = " << MAXM(a, b + 0.2) << std::endl;
	std::cout << "MAXM3 = " << MAXM(a, b++) << std::endl;
	std::cout << "maxf1 = " << maxf(a, b) << std::endl;
	// what's the problem with the following line?
	//std::cout << "maxf = " << maxf((double)a,b+0.2) << std::endl;
	std::cout << "maxf2 = " << maxf(a + 0.1, b + 0.2) << std::endl;
	std::cout << "maxf3 = " << maxf(a, b++) << std::endl;
	std::cout << "a = " << a << ", b = " << b << std::endl;
}
예제 #11
0
파일: prims.c 프로젝트: ataceyhun/libdhcore
struct sphere* sphere_xform(struct sphere* rs, const struct sphere* s, const struct mat3f* m)
{
    /* we have to transform radius by scale value of transform matrix
     * to determine scale value, we find the highest scale component of the matrix */
    float xlen = m->m11*m->m11 + m->m12*m->m12 + m->m13*m->m13;
    float ylen = m->m21*m->m21 + m->m22*m->m22 + m->m23*m->m23;
    float zlen = m->m31*m->m31 + m->m32*m->m32 + m->m33*m->m33;
    float isqr_scale = maxf(xlen, ylen);
    isqr_scale = maxf(isqr_scale, zlen);

    /* transform center */
    struct vec4f c;
    vec3_setf(&c, s->x, s->y, s->z);
    vec3_transformsrt(&c, &c, m);
    return sphere_setf(rs, c.x, c.y, c.z, s->r*sqrtf(isqr_scale));
}
예제 #12
0
double diff_seq(cpx **seq, cpx **ref, const int n)
{
    double diff = 0.0;
    for (int i = 0; i < n; ++i)
        diff = maxf(diff, diff_seq(seq[i], ref[i], 1.f, n));
    return diff;
}
예제 #13
0
// input : simultaneous masking threshold *frqthr,
//         previous masking threshold *tmpthr,
//         Integrations *a (short-time) and *b (long-time)
// output: tracked Integrations *a and *b, time constant *tau
static void
CalcTemporalThreshold ( float* a, float* b, float* tau, float* frqthr, float* tmpthr )
{
    int    n;
    float  tmp;


    for ( n = 0; n < PART_LONG; n++ ) {
        // following calculations relative to threshold in quiet
        frqthr[n] *= invLtq[n];
		tmpthr[n] *= invLtq[n];

        // new post-masking 'tmp' via time constant tau, if old post-masking  > Ltq (=1)
        tmp = tmpthr[n] > 1.f  ?  POW ( tmpthr[n], tau[n] )  :  1.f;

        // calculate time constant for post-masking in next frame,
        // if new time constant has to be calculated (new tmpMask < frqMask)
        a[n] += 0.5f  * (frqthr[n] - a[n]); // short time integrator
        b[n] += 0.15f * (frqthr[n] - b[n]); // long  time integrator
        if (tmp < frqthr[n])
            tau[n] = a[n] <= b[n]  ?  0.8f  :  0.2f + b[n] / a[n] * 0.6f;

        // use post-masking of (Re-Normalization)
		tmpthr[n] = maxf (frqthr[n], tmp) * partLtq[n];
    }

    return;
}
예제 #14
0
파일: quant.c 프로젝트: vlakoff/musepack
// NoiseShaper for a subband
void
QuantizeSubbandWithNoiseShaping ( unsigned int* qu_output, const float* input, const int res, float* errors, const float* FIR )
{
    float  signal;
    float  mult    = A [res];
    float  invmult = C [res];
    int    offset  = D [res];
    int    n, quant;

	memset(errors, 0, 6 * sizeof *errors);       // arghh, it produces pops on each frame boundary!

    for ( n = 0; n < 36; n++) {
        signal = input[n] * NoiseInjectionCompensation1D [res] - (FIR[5]*errors[n+0] + FIR[4]*errors[n+1] + FIR[3]*errors[n+2] + FIR[2]*errors[n+3] + FIR[1]*errors[n+4] + FIR[0]*errors[n+5]);
		quant = mpc_lrintf(signal * mult);

        // calculate the current error and save it for error refeeding
        errors [n + 6] = invmult * quant - signal * NoiseInjectionCompensation1D [res];

        // limitation to +/-D
        quant = minf ( quant, +offset );
        quant = maxf ( quant, -offset );

        qu_output[n] = (unsigned int)(quant + offset);
    }
}
예제 #15
0
static void heat_set_H(LaplacianSystem *sys, int vertex)
{
	float dist, mindist, h;
	int j, numclosest = 0;

	mindist= 1e10;

	/* compute minimum distance */
	for(j=0; j<sys->heat.numsource; j++) {
		dist= heat_source_distance(sys, vertex, j);

		if(dist < mindist)
			mindist= dist;
	}

	sys->heat.mindist[vertex]= mindist;

	/* count number of sources with approximately this minimum distance */
	for(j=0; j<sys->heat.numsource; j++)
		if(heat_source_closest(sys, vertex, j))
			numclosest++;

	sys->heat.p[vertex]= (numclosest > 0)? 1.0f/numclosest: 0.0f;

	/* compute H entry */
	if(numclosest > 0) {
		mindist= maxf(mindist, 1e-4f);
		h= numclosest*C_WEIGHT/(mindist*mindist);
	}
	else
		h= 0.0f;
	
	sys->heat.H[vertex]= h;
}
예제 #16
0
파일: quant.c 프로젝트: vlakoff/musepack
float
ISNR_Schaetzer_Trans ( const float* input, const float SNRcomp, const int res )
{
    int    k;
    float  fac    = A [res];
    float  invfac = C [res];
	float  signal, error, ret, err, sig;

    // Summation of the absolute power and the quadratic error
	k = 0;
	signal = error = 1.e-30f;
    for ( ; k < 12; k++ ) {
        sig = input[k] * NoiseInjectionCompensation1D [res];
		err = mpc_nearbyintf(sig * fac) * invfac - sig;

        error += err * err;
        signal += sig * sig;
    }
    err = signal > error  ?  error / (SNRcomp * signal)  :  error / signal;
    ret = err;
    signal = error = 1.e-30f;
    for ( ; k < 24; k++ ) {
        sig = input[k] * NoiseInjectionCompensation1D [res];
		err = mpc_nearbyintf(sig * fac) * invfac - sig;

        error += err * err;
        signal += sig * sig;
    }
    err = signal > error  ?  error / (SNRcomp * signal)  :  error / signal;
	ret = maxf(ret, err);

    signal = error = 1.e-30f;
    for ( ; k < 36; k++ ) {
        sig = input[k] * NoiseInjectionCompensation1D [res];
		err = mpc_nearbyintf(sig * fac) * invfac - sig;

        error += err * err;
        signal += sig * sig;
    }
    err = signal > error  ?  error / (SNRcomp * signal)  :  error / signal;
	ret = maxf(ret, err);

    return ret;
}
예제 #17
0
double diff_forward_sinus(cpx *seq, const int n)
{
    if (seq == NULL)
        return 1;
    if (n < 4) {
        return 1.0;
    }
    const int n2 = (n >> 1);
    cpx *neg = seq + 1;
    cpx *pos = seq + n - 1;
    double diff = cpx_abs(seq[0]);
    diff = maxf(diff, neg->x);
    diff = maxf(diff, pos->x);
    for (int i = 2; i < n - 3; ++i) {
        diff = maxf(diff, cpx_abs(seq[i]));
    }
    diff = maxf(diff, abs(abs(neg->y) - n2));
    diff = maxf(diff, abs(abs(pos->y) - n2));
    return diff / n2;
}
예제 #18
0
inline
FLOAT F_Get_Translate_Handle_Radius( const Vec3D& eyePos, const Vec3D& objPos )
{
	FLOAT	eyeDist = (eyePos - objPos).LengthSqr();
	eyeDist = maxf(eyeDist,0.01f);
	eyeDist = mxSqrt(eyeDist);

	static FLOAT PICK_DIST = 0.01f;
	HOT_FLOAT(PICK_DIST);
	return PICK_DIST * eyeDist;
}
예제 #19
0
파일: nx.c 프로젝트: biasmv/nx
void collect_statistics(CallStatP call_stats)
{
  int i=0;
  CallStat min=call_stats[0], max=call_stats[0], mean=call_stats[0];
  CallStat stddev;
  memset(&stddev, 0, sizeof(CallStat));
  for (i=1; i<g_num_repeats; ++i) {
    min.real_time=minf(min.real_time, call_stats[i].real_time);
    min.user_time=minf(min.user_time, call_stats[i].user_time);
    min.sys_time=minf(min.sys_time, call_stats[i].sys_time);
    
    max.real_time=maxf(max.real_time, call_stats[i].real_time);
    max.user_time=maxf(max.user_time, call_stats[i].user_time);
    max.sys_time=maxf(max.sys_time, call_stats[i].sys_time);
    
    mean.real_time+=call_stats[i].real_time;
    mean.user_time+=call_stats[i].user_time;
    mean.sys_time+=call_stats[i].sys_time;
  }
  
  mean.real_time/=g_num_repeats;
  mean.user_time/=g_num_repeats;
  mean.sys_time/=g_num_repeats;
  
  for (i=0; i<g_num_repeats; ++i) {
    float d1=call_stats[i].real_time-mean.real_time;
    stddev.real_time+=d1*d1;
    float d2=call_stats[i].user_time-mean.user_time;
    stddev.real_time+=d2*d2;
    float d3=call_stats[i].sys_time-mean.sys_time;
    stddev.sys_time+=d3*d3;
  }
  stddev.real_time=sqrt(stddev.real_time/g_num_repeats);
  stddev.user_time=sqrt(stddev.user_time/g_num_repeats);
  stddev.sys_time=sqrt(stddev.sys_time/g_num_repeats);
  callstat_print(g_output_stream, &mean, "mean", g_output_format);
  callstat_print(g_output_stream, &min, "min", g_output_format);
  callstat_print(g_output_stream, &max, "max", g_output_format);
  callstat_print(g_output_stream, &stddev, "stddev", g_output_format);
  callstat_print_sep(g_output_stream, g_output_format);
}
예제 #20
0
void drawEmancipator(emancipator_s* e)
{
	if(!e || !e->used)return;
	
	e->modelInstance.brightness=maxf(1.0f-(e->counter*1.0f)/BLACKENINGTIME,0.0f);
	e->modelInstance.alpha=(e->counter<BLACKENINGTIME)?(1.0f):(maxf(1.0f-((e->counter-BLACKENINGTIME)*1.0f)/FADINGTIME,0.0f));
	
	gsPushMatrix();
		gsSwitchRenderMode(md2GsMode);

		gsTranslate(e->position.x, e->position.y, e->position.z);

		// TODO : transpose ?
		gsMultMatrix3(e->transformationMatrix);
		
		gsRotateX(e->axis.x*e->angle);
		gsRotateY(e->axis.y*e->angle);
		gsRotateZ(e->axis.z*e->angle);

		md2InstanceDraw(&e->modelInstance);
	gsPopMatrix();
}
예제 #21
0
double diff_seq(cpx *seq, cpx *ref, float scalar, const int n)
{
    if (seq == NULL)
        return 1;
    double mDiff = 0.0;
    double mVal = -1;
    cpx rScale{scalar, 0};
    for (int i = 0; i < n; ++i) {
        cpx norm = cpx_mul(seq + i, &rScale);
        if (invalidCpx(norm))
            return 1.0;
#if defined(_NVIDIA)
        mVal = maxf(mVal, maxf(cuCabsf(norm), cuCabsf(ref[i])));
        double tmp = cuCabsf(cuCsubf(norm, ref[i]));
#else
        mVal = maxf(mVal, maxf(cpx_abs(norm), cpx_abs(ref[i])));
        double tmp = cpx_abs(cpx_sub(&norm, ref + i));
#endif
        mDiff = tmp > mDiff ? tmp : mDiff;
    }
    return (mDiff / mVal);
}
예제 #22
0
ALfloat lpCoeffCalc(ALfloat g, ALfloat cw)
{
    ALfloat a = 0.0f;

    if(g < 0.9999f) /* 1-epsilon */
    {
        /* Be careful with gains < 0.001, as that causes the coefficient head
         * towards 1, which will flatten the signal */
        g = maxf(g, 0.001f);
        a = (1 - g*cw - sqrtf(2*g*(1-cw) - g*g*(1 - cw*cw))) /
            (1 - g);
    }

    return a;
}
/**
 * @brief
 * Calculate the Norm Error of Numerical Solution at Spicific Time.
 */
void NormErr(structMesh *mesh, physics *phys,
             double time, double **c,
             double *L2, double *Linf) {

    double **temp = Matrix_create(mesh->ndim1, mesh->ndim2);
    ExactSol(mesh, phys, time, temp);

    double err    = 0;
    double maxerr = 0.0;
    int    dim1, dim2;
    for (dim1=0; dim1<mesh->ndim1; dim1++) {
        for (dim2=0; dim2<mesh->ndim2; dim2++) {

            double dc = c[dim1][dim2]-temp[dim1][dim2];
            maxerr = maxf(fabs(dc), maxerr);
            err += dc*dc;
        }
    }
    *L2   = sqrt(err/mesh->ndim1/mesh->ndim2);
    *Linf = maxerr;

    Matrix_free(temp);
    return;
}
예제 #24
0
/* Calculates the moving HRIR target coefficients, target delays, and
 * stepping values for the given polar elevation and azimuth in radians.
 * Linear interpolation is used to increase the apparent resolution of the
 * HRIR data set.  The coefficients are also normalized and attenuated by the
 * specified gain.  Stepping resolution and count is determined using the
 * given delta factor between 0.0 and 1.0.
 */
ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat delta, ALint counter, ALfloat (*coeffs)[2], ALuint *delays, ALfloat (*coeffStep)[2], ALint *delayStep)
{
    ALuint evidx[2], azidx[2];
    ALuint lidx[4], ridx[4];
    ALfloat mu[3], blend[4];
    ALfloat left, right;
    ALfloat step;
    ALuint i;

    // Claculate elevation indices and interpolation factor.
    CalcEvIndices(Hrtf, elevation, evidx, &mu[2]);

    // Calculate azimuth indices and interpolation factor for the first
    // elevation.
    CalcAzIndices(Hrtf, evidx[0], azimuth, azidx, &mu[0]);

    // Calculate the first set of linear HRIR indices for left and right
    // channels.
    lidx[0] = Hrtf->evOffset[evidx[0]] + azidx[0];
    lidx[1] = Hrtf->evOffset[evidx[0]] + azidx[1];
    ridx[0] = Hrtf->evOffset[evidx[0]] + ((Hrtf->azCount[evidx[0]]-azidx[0]) % Hrtf->azCount[evidx[0]]);
    ridx[1] = Hrtf->evOffset[evidx[0]] + ((Hrtf->azCount[evidx[0]]-azidx[1]) % Hrtf->azCount[evidx[0]]);

    // Calculate azimuth indices and interpolation factor for the second
    // elevation.
    CalcAzIndices(Hrtf, evidx[1], azimuth, azidx, &mu[1]);

    // Calculate the second set of linear HRIR indices for left and right
    // channels.
    lidx[2] = Hrtf->evOffset[evidx[1]] + azidx[0];
    lidx[3] = Hrtf->evOffset[evidx[1]] + azidx[1];
    ridx[2] = Hrtf->evOffset[evidx[1]] + ((Hrtf->azCount[evidx[1]]-azidx[0]) % Hrtf->azCount[evidx[1]]);
    ridx[3] = Hrtf->evOffset[evidx[1]] + ((Hrtf->azCount[evidx[1]]-azidx[1]) % Hrtf->azCount[evidx[1]]);

    // Calculate the stepping parameters.
    delta = maxf(floorf(delta*(Hrtf->sampleRate*0.015f) + 0.5f), 1.0f);
    step = 1.0f / delta;

    /* Calculate 4 blending weights for 2D bilinear interpolation. */
    blend[0] = (1.0f-mu[0]) * (1.0f-mu[2]);
    blend[1] = (     mu[0]) * (1.0f-mu[2]);
    blend[2] = (1.0f-mu[1]) * (     mu[2]);
    blend[3] = (     mu[1]) * (     mu[2]);

    /* Calculate the HRIR delays using linear interpolation.  Then calculate
     * the delay stepping values using the target and previous running
     * delays.
     */
    left = (ALfloat)(delays[0] - (delayStep[0] * counter));
    right = (ALfloat)(delays[1] - (delayStep[1] * counter));

    delays[0] = fastf2u(Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] +
                        Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3] +
                        0.5f) << HRTFDELAY_BITS;
    delays[1] = fastf2u(Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] +
                        Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3] +
                        0.5f) << HRTFDELAY_BITS;

    delayStep[0] = fastf2i(step * (delays[0] - left));
    delayStep[1] = fastf2i(step * (delays[1] - right));

    /* Calculate the sample offsets for the HRIR indices. */
    lidx[0] *= Hrtf->irSize;
    lidx[1] *= Hrtf->irSize;
    lidx[2] *= Hrtf->irSize;
    lidx[3] *= Hrtf->irSize;
    ridx[0] *= Hrtf->irSize;
    ridx[1] *= Hrtf->irSize;
    ridx[2] *= Hrtf->irSize;
    ridx[3] *= Hrtf->irSize;

    /* Calculate the normalized and attenuated target HRIR coefficients using
     * linear interpolation when there is enough gain to warrant it.  Zero
     * the target coefficients if gain is too low.  Then calculate the
     * coefficient stepping values using the target and previous running
     * coefficients.
     */
    if(gain > 0.0001f)
    {
        gain *= 1.0f/32767.0f;
        for(i = 0;i < HRIR_LENGTH;i++)
        {
            left = coeffs[i][0] - (coeffStep[i][0] * counter);
            right = coeffs[i][1] - (coeffStep[i][1] * counter);

            coeffs[i][0] = (Hrtf->coeffs[lidx[0]+i]*blend[0] +
                            Hrtf->coeffs[lidx[1]+i]*blend[1] +
                            Hrtf->coeffs[lidx[2]+i]*blend[2] +
                            Hrtf->coeffs[lidx[3]+i]*blend[3]) * gain;
            coeffs[i][1] = (Hrtf->coeffs[ridx[0]+i]*blend[0] +
                            Hrtf->coeffs[ridx[1]+i]*blend[1] +
                            Hrtf->coeffs[ridx[2]+i]*blend[2] +
                            Hrtf->coeffs[ridx[3]+i]*blend[3]) * gain;

            coeffStep[i][0] = step * (coeffs[i][0] - left);
            coeffStep[i][1] = step * (coeffs[i][1] - right);
        }
    }
    else
    {
        for(i = 0;i < HRIR_LENGTH;i++)
        {
            left = coeffs[i][0] - (coeffStep[i][0] * counter);
            right = coeffs[i][1] - (coeffStep[i][1] * counter);

            coeffs[i][0] = 0.0f;
            coeffs[i][1] = 0.0f;

            coeffStep[i][0] = step * -left;
            coeffStep[i][1] = step * -right;
        }
    }

    /* The stepping count is the number of samples necessary for the HRIR to
     * complete its transition.  The mixer will only apply stepping for this
     * many samples.
     */
    return fastf2u(delta);
}
예제 #25
0
파일: autowah.c 프로젝트: NeoAxis/SDK
static ALvoid ALautowahState_process(ALautowahState *state, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[BUFFERSIZE], ALuint NumChannels)
{
    ALuint it, kt;
    ALuint base;

    for(base = 0;base < SamplesToDo;)
    {
        ALfloat temps[256];
        ALuint td = minu(256, SamplesToDo-base);
        ALfloat gain = state->GainCtrl;

        for(it = 0;it < td;it++)
        {
            ALfloat smp = SamplesIn[it+base];
            ALfloat a[3], b[3];
            ALfloat alpha, w0;
            ALfloat amplitude;
            ALfloat cutoff;

            /* Similar to compressor, we get the current amplitude of the
             * incoming signal, and attack or release to reach it. */
            amplitude = fabsf(smp);
            if(amplitude > gain)
                gain = minf(gain*state->AttackRate, amplitude);
            else if(amplitude < gain)
                gain = maxf(gain*state->ReleaseRate, amplitude);
            gain = maxf(gain, GAIN_SILENCE_THRESHOLD);

            /* FIXME: What range does the filter cover? */
            cutoff = lerp(20.0f, 20000.0f, minf(gain/state->PeakGain, 1.0f));

            /* The code below is like calling ALfilterState_setParams with
             * ALfilterType_LowPass. However, instead of passing a bandwidth,
             * we use the resonance property for Q. This also inlines the call.
             */
            w0 = F_TAU * cutoff / state->Frequency;

            /* FIXME: Resonance controls the resonant peak, or Q. How? Not sure
             * that Q = resonance*0.1. */
            alpha = sinf(w0) / (2.0f * state->Resonance*0.1f);
            b[0] = (1.0f - cosf(w0)) / 2.0f;
            b[1] =  1.0f - cosf(w0);
            b[2] = (1.0f - cosf(w0)) / 2.0f;
            a[0] =  1.0f + alpha;
            a[1] = -2.0f * cosf(w0);
            a[2] =  1.0f - alpha;

            state->LowPass.a1 = a[1] / a[0];
            state->LowPass.a2 = a[2] / a[0];
            state->LowPass.b1 = b[1] / a[0];
            state->LowPass.b2 = b[2] / a[0];
            state->LowPass.input_gain = b[0] / a[0];

            temps[it] = ALfilterState_processSingle(&state->LowPass, smp);
        }
        state->GainCtrl = gain;

        for(kt = 0;kt < NumChannels;kt++)
        {
            ALfloat gain = state->Gain[kt];
            if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
                continue;

            for(it = 0;it < td;it++)
                SamplesOut[kt][base+it] += gain * temps[it];
        }

        base += td;
    }
}
예제 #26
0
static ALvoid ALcompressorState_process(ALcompressorState *state, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[BUFFERSIZE])
{
    ALuint it, kt;
    ALuint base;

    for(base = 0;base < SamplesToDo;)
    {
        ALfloat temps[64];
        ALuint td = minu(SamplesToDo-base, 64);

        if(state->Enabled)
        {
            ALfloat output, smp, amplitude;
            ALfloat gain = state->GainCtrl;

            for(it = 0;it < td;it++)
            {
                smp = SamplesIn[it+base];

                amplitude = fabsf(smp);
                if(amplitude > gain)
                    gain = minf(gain+state->AttackRate, amplitude);
                else if(amplitude < gain)
                    gain = maxf(gain-state->ReleaseRate, amplitude);
                output = 1.0f / clampf(gain, 0.5f, 2.0f);

                temps[it] = smp * output;
            }

            state->GainCtrl = gain;
        }
        else
        {
            ALfloat output, smp, amplitude;
            ALfloat gain = state->GainCtrl;

            for(it = 0;it < td;it++)
            {
                smp = SamplesIn[it+base];

                amplitude = 1.0f;
                if(amplitude > gain)
                    gain = minf(gain+state->AttackRate, amplitude);
                else if(amplitude < gain)
                    gain = maxf(gain-state->ReleaseRate, amplitude);
                output = 1.0f / clampf(gain, 0.5f, 2.0f);

                temps[it] = smp * output;
            }

            state->GainCtrl = gain;
        }


        for(kt = 0;kt < MAX_OUTPUT_CHANNELS;kt++)
        {
            ALfloat gain = state->Gain[kt];
            if(!(gain > GAIN_SILENCE_THRESHOLD))
                continue;

            for(it = 0;it < td;it++)
                SamplesOut[kt][base+it] += gain * temps[it];
        }

        base += td;
    }
}
예제 #27
0
파일: gfx-csm.c 프로젝트: septag/darkhammer
void gfx_csm_render(gfx_cmdqueue cmdqueue, gfx_rendertarget rt,
        const struct gfx_view_params* params, struct gfx_batch_item* batch_items, uint batch_cnt,
        void* userdata, OUT struct gfx_rpath_result* result)
{
    ASSERT(batch_cnt != 0);

    PRF_OPENSAMPLE("rpath-csm");

    int supports_shared_cbuff = gfx_check_feature(GFX_FEATURE_RANGED_CBUFFERS);
    if (supports_shared_cbuff)
        csm_submit_batchdata(cmdqueue, batch_items, batch_cnt, g_csm->sharedbuff);

    gfx_cmdqueue_resetsrvs(cmdqueue);
    gfx_output_setrendertarget(cmdqueue, g_csm->shadow_rt);
    gfx_output_setviewport(cmdqueue, 0, 0, CSM_SHADOW_SIZE, CSM_SHADOW_SIZE);
    gfx_output_setrasterstate(cmdqueue, g_csm->rs_bias);
    gfx_output_setdepthstencilstate(cmdqueue, g_csm->ds_depth, 0);
    gfx_output_clearrendertarget(cmdqueue, g_csm->shadow_rt, NULL, 1.0f, 0, GFX_CLEAR_DEPTH);

    struct gfx_cblock* cb_frame = g_csm->cb_frame;
    struct gfx_cblock* cb_frame_gs = g_csm->cb_frame_gs;
    struct mat3f* views[CSM_CASCADE_CNT];
    float fovfactors[4];
    float texelsz[4] = {1.0f / (float)CSM_SHADOW_SIZE, 0, 0, 0};
    for (uint i = 0; i < CSM_CASCADE_CNT && i < 4; i++)    {
        views[i] = &g_csm->cascades[i].view;
        fovfactors[i] = maxf(g_csm->cascades[i].proj.m11, g_csm->cascades[i].proj.m22);
    }

    gfx_cb_set4f(cb_frame, SHADER_NAME(c_texelsz), texelsz);
    gfx_cb_set4f(cb_frame, SHADER_NAME(c_fovfactors), fovfactors);
    gfx_cb_set4f(cb_frame, SHADER_NAME(c_lightdir), g_csm->light_dir.f);
    gfx_cb_set3mvp(cb_frame, SHADER_NAME(c_views), (const struct mat3f**)views, CSM_CASCADE_CNT);
    gfx_cb_set4mv(cb_frame, SHADER_NAME(c_cascade_mats), g_csm->cascade_vps, CSM_CASCADE_CNT);
    gfx_shader_updatecblock(cmdqueue, cb_frame);

    gfx_cb_set4fv(cb_frame_gs, SHADER_NAME(c_cascade_planes), g_csm->cascade_planes,
        4*CSM_CASCADE_CNT);
    gfx_shader_updatecblock(cmdqueue, cb_frame_gs);

    for (uint i = 0; i < batch_cnt; i++)  {
        struct gfx_batch_item* bitem = &batch_items[i];
        struct gfx_shader* shader = gfx_shader_get(bitem->shader_id);
        ASSERT(shader);
        gfx_shader_bind(cmdqueue, shader);

        /* do not send cb_xforms to shader if we are using shared buffer (bind later before draw) */
        struct gfx_cblock* cbs[3];
        uint xforms_shared_idx;
        if (supports_shared_cbuff)  {
            cbs[0] = cb_frame;
            cbs[1] = cb_frame_gs;
            xforms_shared_idx = 2;
        }   else    {
            cbs[0] = cb_frame;
            cbs[1] = cb_frame_gs;
            cbs[2] = g_csm->cb_xforms;
            xforms_shared_idx = 3;
        }
        gfx_shader_bindcblocks(cmdqueue, shader, (const struct gfx_cblock**)cbs, xforms_shared_idx);

        /* batch draw */
        for (int k = 0; k < bitem->nodes.item_cnt; k++)  {
            struct gfx_batch_node* bnode_first = &((struct gfx_batch_node*)bitem->nodes.buffer)[k];

            csm_preparebatchnode(cmdqueue, bnode_first, shader);
            if (bnode_first->poses[0] != NULL)  {
                gfx_shader_bindcblock_tbuffer(cmdqueue, shader, SHADER_NAME(tb_skins),
                    g_csm->tb_skins);
            }

            struct linked_list* node = bnode_first->bll;
            while (node != NULL)    {
                struct gfx_batch_node* bnode = (struct gfx_batch_node*)node->data;
                csm_drawbatchnode(cmdqueue, bnode, shader, xforms_shared_idx);
                node = node->next;
            }
        }
    }

    /* switch back */
    gfx_output_setrasterstate(cmdqueue, NULL);
    gfx_output_setdepthstencilstate(cmdqueue, NULL, 0);

    if (g_csm->debug_csm)
        csm_renderpreview(cmdqueue, params);

    PRF_CLOSESAMPLE();  /* csm */
}
예제 #28
0
/* read command line, initialize, and create threads */
int main(int argc, char *argv[]) {
	int i, j;
	long l; /* use long in case of a 64-bit system */

	point glob_min, glob_max;
	int glob_sum;
	worker_input work_params[MAXWORKERS];

	pthread_attr_t attr;
	pthread_t workerid[MAXWORKERS];

	/* set global thread attributes */
	pthread_attr_init(&attr);
	pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);

	// Set the threads to be joinable
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

	/* initialize mutex and condition variable */
	pthread_mutex_init(&barrier, NULL);
	pthread_cond_init(&go, NULL);

	/* read command line args if any */
	size = (argc > 1)? atoi(argv[1]) : MAXSIZE;
	numWorkers = (argc > 2)? atoi(argv[2]) : MAXWORKERS;
	if (size > MAXSIZE) size = MAXSIZE;
	if (numWorkers > MAXWORKERS) numWorkers = MAXWORKERS;
	stripSize = size/numWorkers;
	/* initialize the matrix */
	for (i = 0; i < size; i++) {
		for (j = 0; j < size; j++) {
					matrix[i][j] = 1;//rand()%999;
		}
	}

	/* print the matrix */
#ifdef DEBUG
	for (i = 0; i < size; i++) {
		printf("[ ");
		for (j = 0; j < size; j++) {
			printf(" %d", matrix[i][j]);
		}
		printf(" ]\n");
	}
#endif

	/* do the parallel work: create the workers */
	// here we send in a an argument which we will get back loaded with min, max and sum values for that thread
	start_time = read_timer();
	for (l = 0; l < numWorkers; ++l){
		worker_input wi = {.id = l, .sum = 0};
		work_params[l] = wi; // saved in an array for perfomance issues (removing this meant a slowdown of a factor 4)
		pthread_create(&workerid[l], &attr, Worker, (void *) &work_params[l]);
	}

	worker_input wi;

	//initialize end variables to first value of the matrix
	glob_min.x = glob_max.x = 0;
	glob_min.y = glob_max.y = 0;
    glob_sum = 0;

    // A variable for the pointer so we can handle the return value
    void* status;
	for(l = 0; l < numWorkers; ++l){
		// we join the the different threads into the main thread and sums up the total results
		pthread_join(workerid[l],  &status);
		wi = *((worker_input *) status);
		
		glob_sum += wi.sum;
		glob_min = *(minf(&glob_min, &wi.min));
    	glob_max = *(maxf(&glob_max, &wi.max));
    }

    // get end time 
	end_time = read_timer();
	// print results 
	printf("The total is %d\n", glob_sum);
	printf("The smallest value is %d at x:%d, y:%d\n", matrix[glob_min.x][glob_min.y], glob_min.x, glob_min.y );
	printf("The largest value is %d at x:%d, y:%d\n", matrix[glob_max.x][glob_max.y], glob_max.x, glob_max.y );
	printf("The execution time is %g sec\n", end_time - start_time);


    // printf("Total values are: Sum %d, min %d, max %d\n", glob_sum, glob_min, glob_max);
	pthread_exit(NULL);
}

/* Each worker sums the values in one strip of the matrix.
	 After a barrier, worker(0) computes and prints the total 
This is pretty much the same as in matrixSum_min_max.c except that 
the barrier function and calculation of final min and max values has 
moved to the main thread.
*/
void *Worker(void *arg) {
	worker_input* wi = (worker_input*) arg;
	point current;
	int i, j, first, last;

	

	#ifdef DEBUG
		printf("worker %ld (pthread id %d) has started\n", (*wi).id, pthread_self());
	#endif

	/* determine first and last rows of my strip */
	first = (*wi).id*stripSize;
	last = ((*wi).id == numWorkers - 1) ? (size - 1) : (first + stripSize - 1);

	(*wi).min.x = (*wi).max.x = first;
	(*wi).min.y = (*wi).max.y = 0;
	/* sum values in my strip */
	for (i = first; i <= last; i++){
		current.x =i;
		for (j = 0; j < size; j++){
			current.y = j;
			(*wi).sum += matrix[i][j];
			(*wi).min = *(minf( &((*wi).min), &current ));
			(*wi).max = *(maxf( &((*wi).max), &current ));
		}
	}
	pthread_exit(wi);

}
예제 #29
0
파일: frustum.cpp 프로젝트: hglm/sre
void sreFrustum::CalculateLightScissors(sreLight *light) {
    if (light->type & (SRE_LIGHT_SPOT | SRE_LIGHT_BEAM)) {
        // Approximate the bounding volume of the light by the bounding box of the bounding cylinder.
        Vector3D up;
        if (fabsf(light->cylinder.axis.x) < 0.01f && fabsf(light->cylinder.axis.z) < 0.01f) {
            if (light->cylinder.axis.y > 0)
                up = Vector3D(0, 0, - 1.0f);
            else
                up = Vector3D(0, 0, 1.0f);
        }
        else
            up = Vector3D(0, 1.0f, 0);
        // Calculate tangent planes.
        Vector3D N2 = Cross(up, light->cylinder.axis);
        N2.Normalize();
        Vector3D N3 = Cross(light->cylinder.axis, N2);
        Point3DPadded B[8];
        Point3D E1 = light->cylinder.center - 0.5f * light->cylinder.length * light->cylinder.axis;
        Point3D E2 = E1 + light->cylinder.length * light->cylinder.axis;
        B[0] = E2 + light->cylinder.radius * N2 + light->cylinder.radius * N3;
        B[1] = E1 + light->cylinder.radius * N2 + light->cylinder.radius * N3;
        B[2] = E1 - light->cylinder.radius * N2 + light->cylinder.radius * N3;
        B[3] = E2 - light->cylinder.radius * N2 + light->cylinder.radius * N3;
        B[4] = E2 + light->cylinder.radius * N2 - light->cylinder.radius * N3;
        B[5] = E1 + light->cylinder.radius * N2 - light->cylinder.radius * N3;
        B[6] = E1 - light->cylinder.radius * N2 - light->cylinder.radius * N3;
        B[7] = E2 - light->cylinder.radius * N2 - light->cylinder.radius * N3;
        scissors.SetEmptyRegion();
        scissors.UpdateWithWorldSpaceBoundingBox(B, 8, *this);
        scissors.ClampEmptyRegion();
        scissors.ClampRegionAndDepthBounds();
#if 0
        printf("Light %d (spot): ");
        sreMessage(SRE_MESSAGE_INFO,
            "Scissors = (%f, %f, %f, %f)", scissors.left, scissors.right, scissors.bottom, scissors.top);
#endif
        return;
    }
    // Point source light.
    scissors.SetFullRegionAndDepthBounds();
    // Transform the light position from world space to eye space.
    Point3D L = (sre_internal_view_matrix * light->vector).GetPoint3D();
    // Calculate the depth range.
    // The near and far tangent planes parallel to the z-axis can be represented by 4D vectors
    // T= <0, 0, 1.0, Lz + r> and T = <0, 0, 1.0, L.z - r> respectively.
    // Multiply the z coordinates by the projection matrix to arrive at projected depths.
    // Divide by w coordinate. Note that we assume an infinite view frustum.
    float Lz_near = L.z + light->sphere.radius;
    if (Lz_near <= - nearD) {
        Vector4D V = sre_internal_projection_matrix * Vector4D(0, 0, Lz_near, 1.0);
        scissors.near = 0.5 * (double)V.z / (double)V.w + 0.5;
    }
    float Lz_far = L.z - light->sphere.radius;
    if (Lz_far <= - nearD) {
        Vector4D V = sre_internal_projection_matrix * Vector4D(0, 0, Lz_far, 1.0);
        scissors.far = 0.5 * (double)V.z / (double)V.w + 0.5;
    }
    else
        scissors.far = 0;
    // Calculate the determinant D
    float D = 4 * (sqrf(light->sphere.radius) * sqrf(L.x) - (sqrf(L.x) + sqrf(L.z)) *
        (sqrf(light->sphere.radius) - sqrf(L.z)));
    if (D <= 0) {
        // The light source's bounding sphere fills the entire viewport.
        return;
    }
    // Calculate the tangent planes <Nx, 0, Nz, 0> of the light volume.
    float Nx1 = (light->sphere.radius * L.x + sqrtf(D / 4)) /
        (sqrf(L.x) + sqrf(L.z));
    float Nx2 = (light->sphere.radius * L.x - sqrtf(D / 4)) /
        (sqrf(L.x) + sqrf(L.z));
    float Nz1 = (light->sphere.radius - Nx1 * L.x) / L.z;
    float Nz2 = (light->sphere.radius - Nx2 * L.x) / L.z;
    // The point P at which the plane T is tangent to the bounding sphere is
    // given by <Lx - rNx, 0, Lz - rNz, 1>
    float Pz1 = L.z - light->sphere.radius * Nz1;
    float Pz2 = L.z - light->sphere.radius * Nz2;
    if (Pz1 < 0) {
        // Plane 1 may shrink the scissors rectangle.
        float x = Nz1 * e / Nx1;
        float Px1 = L.x - light->sphere.radius * Nx1;
#if 0
        int xvp = 0 + (x + 1) * sre_internal_window_width / 2;
        if (Px1 < L.x) {
            // Left-side boundary
            scissors.left = max(xvp, 0);
        }
        else {
            // Right-side boundary
            scissors.right = min(xvp, sre_internal_window_width);
        }
#else
        if (Px1 < L.x) {
            // Left-side boundary
            scissors.left = maxf(x, - 1.0);
        }
        else {
            // Right-side boundary
            scissors.right = minf(x, 1.0);
        }
#endif
    }
    if (Pz2 < 0) {
        // Plane 2 may shrink the scissors rectangle.
        float x = Nz2 * e / Nx2;
        float Px2 = L.x - light->sphere.radius * Nx2;
#if 0
        int xvp = 0 + (x + 1) * sre_internal_window_width / 2;
        if (Px2 < L.x) {
            // Left-side boundary
            scissors.left = max(xvp, 0);
        }
        else {
            // Right-side boundary
            scissors.right = min(xvp, sre_internal_window_width);
        }
#else
        if (Px2 < L.x) {
            // Left-side boundary
            scissors.left = maxf(x, - 1.0);
        }
        else {
            // Right-side boundary
            scissors.right = minf(x, 1.0);
        }
#endif
    }
    // Calculate the tangent planes <0, Ny, Nz, 0> of the light volume.
    float term1 = sqrf(light->sphere.radius) * sqrf(L.y) -
        (sqrf(L.y) + sqrf(L.z)) *
        (sqrf(light->sphere.radius) - sqrf(L.z));
    float Ny1 = (light->sphere.radius * L.y + sqrtf(term1)) /
        (sqrf(L.y) + sqrf(L.z));
    float Ny2 = (light->sphere.radius * L.y - sqrtf(term1)) /
        (sqrf(L.y) + sqrf(L.z));
    Nz1 = (light->sphere.radius - Ny1 * L.y) / L.z;
    Nz2 = (light->sphere.radius - Ny2 * L.y) / L.z;
    Pz1 = L.z - light->sphere.radius * Nz1;
    Pz2 = L.z - light->sphere.radius * Nz2;
    if (Pz1 < 0) {
        // Plane 3 may shrink the scissors rectangle.
        float y = Nz1 * e * ratio / Ny1;
        float Py1 = L.y - light->sphere.radius * Ny1;
#if 0
        int yvp = 0 + (y + 1) * sre_internal_window_height / 2;
        if (Py1 < L.y) {
            // Bottom boundary.
            scissors.bottom = max(yvp, 0);
        }
        else {
            // Top boundary.
            scissors.top = min(yvp, sre_internal_window_height);
        }
#else
        if (Py1 < L.y) {
            // Bottom boundary.
            scissors.bottom = maxf(y, - 1.0);
        }
        else {
            // Top boundary.
            scissors.top = minf(y, 1.0);
        }
#endif
    }
    if (Pz2 < 0) {
        // Plane 4 may shrink the scissors rectangle.
        float y = Nz2 * e * ratio / Ny2;
        float Py2 = L.y - light->sphere.radius * Ny2;
#if 0
        int yvp = 0 + (y + 1) * sre_internal_window_height / 2;
        if (Py2 < L.y) {
            // Bottom boundary.
            scissors.bottom = max(yvp, 0);
        }
        else {
            // Top boundary.
            scissors.top = min(yvp, sre_internal_window_height);
        }
#else
        if (Py2 < L.y) {
            // Bottom boundary.
            scissors.bottom = maxf(y, - 1.0);
        }
        else {
            // Top boundary.
            scissors.top = minf(y, 1.0);
        }
#endif
    }
//    scissors.ClampRegionToScreen();
//    printf("Scissors = (%f, %f, %f, %f)\n", scissors.left, scissors.right, scissors.bottom, scissors.top);
}
예제 #30
0
파일: frustum.cpp 프로젝트: hglm/sre
void sreFrustum::CalculateShadowCasterVolume(const Vector4D& lightpos, int nu_frustum_planes) {
    nu_frustum_planes = maxf(nu_frustum_planes, SRE_NU_FRUSTUM_PLANES);
    // Note: for beam lights, this might be inaccurate.
    if (lightpos.w == 1.0f && Intersects(lightpos.GetPoint3D(), frustum_world)) {
        // If the point light position is inside the view frustum, we only need to consider the
        // set of visible objects.
        shadow_caster_volume.nu_planes = nu_frustum_planes;
        for (int i = 0; i < nu_frustum_planes; i++)
            shadow_caster_volume.plane[i] = frustum_world.plane[i];
        goto end;
    }
    // Calculate the convex hull enclosing the view frustum and the light source.
    shadow_caster_volume.nu_planes = 0;
    // Calculate the dot products between the frustum planes and the light source.
    float dot[6] DST_ALIGNED(16);
    // The SIMD-accelerated version check for 16-bytes aligned arrays, which is hard to
    // guarantee in this case; otherwise, no SIMD will be used.
#if 1
    dstCalculateDotProductsNx1(nu_frustum_planes, &frustum_world.plane[0],
        lightpos, &dot[0]);
#else
    for (int i = 0; i < nu_frustum_planes; i++)
        dot[i] = Dot(frustum_world.plane[i], lightpos);
#endif
    // For each frustum plane, add it if it is part of the convex hull.
    for (int i = 0; i < nu_frustum_planes; i++)
        if (dot[i] > 0) {
             shadow_caster_volume.plane[shadow_caster_volume.nu_planes] = frustum_world.plane[i];
             shadow_caster_volume.nu_planes++;
        }
//    printf("Shadow caster volume planes: from frustum: %d\n", shadow_caster_volume.nu_planes);
    if (shadow_caster_volume.nu_planes == 0 && lightpos.w == 1.0f) {
        // Special case: the point light source is behind the camera and there is no far plane.
        // As a result, there is no plane from the frustum with a positive dot product. In
        // this case, construct a volume consisting of the lightsource and four planes parallel 
        // to the frustum side planes but starting at the lightsource.
        for (int i = 0; i < 4; i++) {
            // Copy the normal.
            shadow_caster_volume.plane[i] = frustum_world.plane[i];
            // Calculate the distance such that the lightsource is in the plane.
            shadow_caster_volume.plane[i].w = - Dot(frustum_world.plane[i].GetVector3D(),
                lightpos.GetPoint3D());
        }
        shadow_caster_volume.nu_planes = 4;
        goto end;
    }
    // For each pair of adjacent frustum planes, if one has a positive dot product and the other
    // does not, calculate a new plane defined by the edge between those two frustum planes and
    // the position of the light source, making sure the plane's normal direction faces inward.
    // For directional lights, the plane runs parallel to the direction of the light.
    nu_shadow_caster_edges = 0;
    int n;
    if (nu_frustum_planes == 5)
        n = 8;
    else
        n = 12;
    for (int i = 0; i < n; i++)
        if ((dot[adjacent_plane[i].plane0] > 0 && dot[adjacent_plane[i].plane1] <= 0) ||
        (dot[adjacent_plane[i].plane0] <= 0 && dot[adjacent_plane[i].plane1] > 0)) {
//            printf("Setting plane from adjacent planes %d and %d using frustum vertices %d and %d\n",
//                adjacent_plane[i].plane0, adjacent_plane[i].plane1, adjacent_plane[i].vertex0,
//                adjacent_plane[i].vertex1);
            if (lightpos.w == 1.0f)
                shadow_caster_volume.plane[shadow_caster_volume.nu_planes] = dstPlaneFromPoints(
                    frustum_world.hull.vertex[adjacent_plane[i].vertex0],
                    frustum_world.hull.vertex[adjacent_plane[i].vertex1],
                    lightpos.GetPoint3D()
                    );
            else {
                shadow_caster_volume.plane[shadow_caster_volume.nu_planes] = dstPlaneFromPoints(
                    frustum_world.hull.vertex[adjacent_plane[i].vertex0],
                    frustum_world.hull.vertex[adjacent_plane[i].vertex1],
                    frustum_world.hull.vertex[adjacent_plane[i].vertex0] + lightpos.GetVector3D()
                    );
                shadow_caster_edge[nu_shadow_caster_edges][0] = adjacent_plane[i].vertex0;
                shadow_caster_edge[nu_shadow_caster_edges][1] = adjacent_plane[i].vertex1;
                nu_shadow_caster_edges++;
            }
            // Make sure the normal is pointed inward, check by taking the dot product with the frustum
            // "centroid".
            shadow_caster_volume.plane[shadow_caster_volume.nu_planes].OrientPlaneTowardsPoint(
                frustum_world.sphere.center);
            shadow_caster_volume.nu_planes++;
        }
end: ;
#if 0
    printf("Light (%lf, %lf, %lf, %lf), %d planes in shadow caster volume.\n",
        lightpos.x, lightpos.y, lightpos.z, lightpos.w, shadow_caster_volume.nu_planes);
    for (int i = 0; i < shadow_caster_volume.nu_planes; i++)
        printf("Plane %d: (%lf, %lf, %lf, %lf) ", i,
            shadow_caster_volume.plane[i].x, shadow_caster_volume.plane[i].y,
            shadow_caster_volume.plane[i].y, shadow_caster_volume.plane[i].w);
    printf("\n");
#endif
}