/* 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; }
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)); } } }
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); }
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; }
/* 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); }
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, ¶ms->viewproj); gfx_canvas_setztest(FALSE); gfx_canvas_coords(&xf->ws_mat, ¶ms->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, ¶ms->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, ¶ms->viewproj); gfx_canvas_setfillcolor_solid(&g_color_white); gfx_canvas_settextcolor(&g_color_white); gfx_canvas_setwireframe(FALSE, TRUE); }
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});
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); }
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; }
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)); }
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; }
// 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; }
// 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); } }
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; }
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; }
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; }
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; }
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); }
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(); }
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); }
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; }
/* 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); }
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; } }
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; } }
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 */ }
/* 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), ¤t )); (*wi).max = *(maxf( &((*wi).max), ¤t )); } } pthread_exit(wi); }
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); }
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 }