Beispiel #1
0
static void RE_rayobject_blibvh_add(RayObject *o, RayObject *ob)
{
	BVHObject *obj = (BVHObject*)o;
	float min_max[6];
	INIT_MINMAX(min_max, min_max+3);
	RE_rayobject_merge_bb(ob, min_max, min_max+3);

	DO_MIN(min_max,     obj->bb[0]);
	DO_MAX(min_max + 3, obj->bb[1]);
	
	BLI_bvhtree_insert(obj->bvh, obj->next_leaf - obj->leafs, min_max, 2);	
	*(obj->next_leaf++) = ob;
}
Beispiel #2
0
/*
====================
CL_FinishTimeDemo

====================
*/
static void CL_FinishTimeDemo (void)
{
	int frames;
	int i;
	double time, totalfpsavg;
	double fpsmin, fpsavg, fpsmax; // report min/avg/max fps
	static int benchmark_runs = 0;
	char vabuf[1024];

	cls.timedemo = false;

	frames = cls.td_frames;
	time = realtime - cls.td_starttime;
	totalfpsavg = time > 0 ? frames / time : 0;
	fpsmin = cls.td_onesecondminfps;
	fpsavg = cls.td_onesecondavgcount ? cls.td_onesecondavgfps / cls.td_onesecondavgcount : 0;
	fpsmax = cls.td_onesecondmaxfps;
	// LordHavoc: timedemo now prints out 7 digits of fraction, and min/avg/max
	Con_Printf("%i frames %5.7f seconds %5.7f fps, one-second fps min/avg/max: %.0f %.0f %.0f (%i seconds)\n", frames, time, totalfpsavg, fpsmin, fpsavg, fpsmax, cls.td_onesecondavgcount);
	Log_Printf("benchmark.log", "date %s | enginedate %s | demo %s | commandline %s | run %d | result %i frames %5.7f seconds %5.7f fps, one-second fps min/avg/max: %.0f %.0f %.0f (%i seconds)\n", Sys_TimeString("%Y-%m-%d %H:%M:%S"), buildstring, cls.demoname, cmdline.string, benchmark_runs + 1, frames, time, totalfpsavg, fpsmin, fpsavg, fpsmax, cls.td_onesecondavgcount);
	if (COM_CheckParm("-benchmark"))
	{
		++benchmark_runs;
		i = COM_CheckParm("-benchmarkruns");
		if(i && i + 1 < com_argc)
		{
			static benchmarkhistory_t *history = NULL;
			if(!history)
				history = (benchmarkhistory_t *)Z_Malloc(sizeof(*history) * atoi(com_argv[i + 1]));

			history[benchmark_runs - 1].frames = frames;
			history[benchmark_runs - 1].time = time;
			history[benchmark_runs - 1].totalfpsavg = totalfpsavg;
			history[benchmark_runs - 1].fpsmin = fpsmin;
			history[benchmark_runs - 1].fpsavg = fpsavg;
			history[benchmark_runs - 1].fpsmax = fpsmax;

			if(atoi(com_argv[i + 1]) > benchmark_runs)
			{
				// restart the benchmark
				Cbuf_AddText(va(vabuf, sizeof(vabuf), "timedemo %s\n", cls.demoname));
				// cannot execute here
			}
			else
			{
				// print statistics
				int first = COM_CheckParm("-benchmarkruns_skipfirst") ? 1 : 0;
				if(benchmark_runs > first)
				{
#define DO_MIN(f) \
					for(i = first; i < benchmark_runs; ++i) if((i == first) || (history[i].f < f)) f = history[i].f

#define DO_MAX(f) \
					for(i = first; i < benchmark_runs; ++i) if((i == first) || (history[i].f > f)) f = history[i].f

#define DO_MED(f) \
					doublecmp_offset = (char *)&history->f - (char *)history; \
					qsort(history + first, benchmark_runs - first, sizeof(*history), doublecmp_withoffset); \
					if((first + benchmark_runs) & 1) \
						f = history[(first + benchmark_runs - 1) / 2].f; \
					else \
						f = (history[(first + benchmark_runs - 2) / 2].f + history[(first + benchmark_runs) / 2].f) / 2

					DO_MIN(frames);
					DO_MAX(time);
					DO_MIN(totalfpsavg);
					DO_MIN(fpsmin);
					DO_MIN(fpsavg);
					DO_MIN(fpsmax);
					Con_Printf("MIN: %i frames %5.7f seconds %5.7f fps, one-second fps min/avg/max: %.0f %.0f %.0f (%i seconds)\n", frames, time, totalfpsavg, fpsmin, fpsavg, fpsmax, cls.td_onesecondavgcount);

					DO_MED(frames);
					DO_MED(time);
					DO_MED(totalfpsavg);
					DO_MED(fpsmin);
					DO_MED(fpsavg);
					DO_MED(fpsmax);
					Con_Printf("MED: %i frames %5.7f seconds %5.7f fps, one-second fps min/avg/max: %.0f %.0f %.0f (%i seconds)\n", frames, time, totalfpsavg, fpsmin, fpsavg, fpsmax, cls.td_onesecondavgcount);

					DO_MAX(frames);
					DO_MIN(time);
					DO_MAX(totalfpsavg);
					DO_MAX(fpsmin);
					DO_MAX(fpsavg);
					DO_MAX(fpsmax);
					Con_Printf("MAX: %i frames %5.7f seconds %5.7f fps, one-second fps min/avg/max: %.0f %.0f %.0f (%i seconds)\n", frames, time, totalfpsavg, fpsmin, fpsavg, fpsmax, cls.td_onesecondavgcount);
				}
				Z_Free(history);
				history = NULL;
				Host_Quit_f();
			}
		}
		else
			Host_Quit_f();
	}
}
Beispiel #3
0
static void RE_rayobject_blibvh_bb(RayObject *o, float *min, float *max)
{
	BVHObject *obj = (BVHObject*)o;
	DO_MIN(obj->bb[0], min);
	DO_MAX(obj->bb[1], max);
}
Beispiel #4
0
/* Object Surface Area Heuristic splitter */
int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds)
{
	int size = rtbuild_size(b);
	assert(nchilds == 2);
	assert(size > 1);
	int baxis = -1, boffset = 0;

	if (size > nchilds) {
		float bcost = FLT_MAX;
		baxis = -1, boffset = size / 2;

		SweepCost *sweep = (SweepCost *)MEM_mallocN(sizeof(SweepCost) * size, "RTBuilder.HeuristicSweep");
		
		for (int axis = 0; axis < 3; axis++) {
			SweepCost sweep_left;

			RTBuilder::Object **obj = b->sorted_begin[axis];
			
//			float right_cost = 0;
			for (int i = size - 1; i >= 0; i--) {
				if (i == size - 1) {
					copy_v3_v3(sweep[i].bb, obj[i]->bb);
					copy_v3_v3(sweep[i].bb + 3, obj[i]->bb + 3);
					sweep[i].cost = obj[i]->cost;
				}
				else {
					sweep[i].bb[0] = min_ff(obj[i]->bb[0], sweep[i + 1].bb[0]);
					sweep[i].bb[1] = min_ff(obj[i]->bb[1], sweep[i + 1].bb[1]);
					sweep[i].bb[2] = min_ff(obj[i]->bb[2], sweep[i + 1].bb[2]);
					sweep[i].bb[3] = max_ff(obj[i]->bb[3], sweep[i + 1].bb[3]);
					sweep[i].bb[4] = max_ff(obj[i]->bb[4], sweep[i + 1].bb[4]);
					sweep[i].bb[5] = max_ff(obj[i]->bb[5], sweep[i + 1].bb[5]);
					sweep[i].cost  = obj[i]->cost + sweep[i + 1].cost;
				}
//				right_cost += obj[i]->cost;
			}
			
			sweep_left.bb[0] = obj[0]->bb[0];
			sweep_left.bb[1] = obj[0]->bb[1];
			sweep_left.bb[2] = obj[0]->bb[2];
			sweep_left.bb[3] = obj[0]->bb[3];
			sweep_left.bb[4] = obj[0]->bb[4];
			sweep_left.bb[5] = obj[0]->bb[5];
			sweep_left.cost  = obj[0]->cost;
			
//			right_cost -= obj[0]->cost;	if (right_cost < 0) right_cost = 0;

			for (int i = 1; i < size; i++) {
				//Worst case heuristic (cost of each child is linear)
				float hcost, left_side, right_side;
				
				// not using log seems to have no impact on raytracing perf, but
				// makes tree construction quicker, left out for now to test (brecht)
				// left_side  = bb_area(sweep_left.bb, sweep_left.bb + 3) * (sweep_left.cost + logf((float)i));
				// right_side = bb_area(sweep[i].bb,   sweep[i].bb   + 3) * (sweep[i].cost   + logf((float)size - i));
				left_side = bb_area(sweep_left.bb, sweep_left.bb + 3) * (sweep_left.cost);
				right_side = bb_area(sweep[i].bb, sweep[i].bb + 3) * (sweep[i].cost);
				hcost = left_side + right_side;

				assert(left_side >= 0);
				assert(right_side >= 0);
				
				if (left_side > bcost) break;   //No way we can find a better heuristic in this axis

				assert(hcost >= 0);
				// this makes sure the tree built is the same whatever is the order of the sorting axis
				if (hcost < bcost || (hcost == bcost && axis < baxis)) {
					bcost = hcost;
					baxis = axis;
					boffset = i;
				}
				DO_MIN(obj[i]->bb,   sweep_left.bb);
				DO_MAX(obj[i]->bb + 3, sweep_left.bb + 3);

				sweep_left.cost += obj[i]->cost;
//				right_cost -= obj[i]->cost; if (right_cost < 0) right_cost = 0;
			}
			
			//assert(baxis >= 0 && baxis < 3);
			if (!(baxis >= 0 && baxis < 3))
				baxis = 0;
		}
			
		
		MEM_freeN(sweep);
	}
	else if (size == 2) {
		baxis = 0;
		boffset = 1;
	}
	else if (size == 1) {
		b->child_offset[0] = 0;
		b->child_offset[1] = 1;
		return 1;
	}
		
	b->child_offset[0] = 0;
	b->child_offset[1] = boffset;
	b->child_offset[2] = size;
	

	/* Adjust sorted arrays for childs */
	for (int i = 0; i < boffset; i++) b->sorted_begin[baxis][i]->selected = true;
	for (int i = boffset; i < size; i++) b->sorted_begin[baxis][i]->selected = false;
	for (int i = 0; i < 3; i++)
		std::stable_partition(b->sorted_begin[i], b->sorted_end[i], selected_node);

	return nchilds;
}
Beispiel #5
0
void rtbuild_merge_bb(RTBuilder *b, float min[3], float max[3])
{
	rtbuild_calc_bb(b);
	DO_MIN(b->bb, min);
	DO_MAX(b->bb + 3, max);
}