#if 0

#define MAX_SCENE_SIZE  200 /* WTF? */

typedef struct ms_output_s
{
	u32_t	   framenum;
	vboolean	noflush;
	vhandle_t   outfile;
}   ms_output_t, *ms_output_p;

V_LOCAL vboolean V_CALL
ms_save_frame(particle_system_p ps)
{
	ms_output_p ctx = (ms_output_p)ps->monitoring_context;
	conlPrintf(LOG_TRACE,
		"ms_save_frame(): last frame %u (realtime %g,rt_limit %g)\n",
		ctx->framenum,ps->cur_time,ps->solution_realtime_limit);
	ms_append_frame(ctx->outfile,ps);
	if(!ctx->noflush)
		fileControl(ctx->outfile,pctl_flush,NULL);
	return true;
}

V_LOCAL vboolean V_CALL
ms_end_monitoring(particle_system_p ps)
{
	ms_output_p ctx = (ms_output_p)ps->monitoring_context;
	fileClose(ctx->outfile);
	memFree(ctx);
	return true;
}

vboolean
init_ms_context(particle_system_p ps)
{
	CALLER_NAME(init_ms_context)
	char outfile_name[_MAX_PATH] = "";
	ms_output_p ctx;
	vboolean noflush = false;
	vec_t scale = -1;
	vhandle_t sc = lexParseString(ps->monitor_setup,"");
	while(lexNext(sc))
	{
		if(lexLastWas(sc,"filename"))
		{
			strCopy(outfile_name,lexNext(sc),_MAX_PATH);
			continue;
		}
		if(lexLastWas(sc,"noflush"))
		{
			noflush = true;
			continue;
		}
		if(lexLastWas(sc,"scale")) /* fixme: global scale */
		{
			if(!lexNextFloat(sc,&scale))
				SYN_EXPECTED(sc,"float scale");
			continue;
		}
		conlPrintf(LOG_WARNING,"init_ms_context(): unknown token '%s'.\n",
			lexLast(sc));
	}
	lexDestroy(sc);
	ctx = (ms_output_p)memAlloc(sizeof(ms_output_t));
	memZero(ctx,sizeof(ms_output_t));
	ctx->outfile = fileOpenWrite(outfile_name);
	if(ctx->outfile == LIBV_INVALID_HANDLE)
	{
		conlPrintf(LOG_ERROR,"init_ms_context(): unable to open '%s'.\n",
			outfile_name);
		memFree(ctx);
		return false;
	}
	ctx->framenum = 0;
	ctx->noflush = noflush;
	ps->monitor = ms_save_frame;
	ps->monitoring_context = ctx;
	ps->end_monitoring = ms_end_monitoring;
	ms_write_init(ctx->outfile);
	if(IsZero(scale+1))
	{
		/* no scale in setup; compute it */ /* WTF? */
		u32_t i;
		vec_p p;
		vec3_t mins, maxs, extents;
		bboxClear(mins,maxs);
		for(i=0;i<ps->num_particles;i++)
		{
			p = PS_POS(ps->phase,i);
			bboxAddPoint(mins,maxs,p);
		}
		vec3Sub(extents,maxs,mins);
		scale = extents[vec3MaxAbsInd(extents)];
		if(IsZero(scale))
			scale = 1;
		else
			scale = (vec_t)MAX_SCENE_SIZE / scale;
	}
	ms_create_spheres(ctx->outfile,ps);
	return true;
}

#endif

V_LOCAL void
ms_write_init(vhandle_t out)
{
	filePuts(out,"select $*\nmax delete\n\n");
	filePuts(out,"SceneSpheres = #()\nSpherePositions = #()\n\n");
	ms_write_helpers(out);
}

V_LOCAL void
ms_append_frame(vhandle_t out,particle_system_p ps)
{
	vec_p pos;
	u32_t i, npts = ps->num_particles;
	vec_p phase = ps->cur_phase;
	filePuts(out,"append SpherePositions #(\n");
	npts -= 1; /* min npts == 1 */
	for(i=0;i<npts;i++)
	{
		pos = PS_POS(phase,i);
		filePrintf(out,"\t[%g,%g,%g],\n",pos[0],pos[1],pos[2]);
	}
	pos = PS_POS(phase,i);
	filePrintf(out,"\t[%g,%g,%g]);\n",pos[0],pos[1],pos[2]);
}

V_LOCAL void
WriteCreateFalloffMap(vhandle_t out,char *fn_name,vec3_t c1,vec3_t c2)
{
	filePrintf(out,"fn %s =\n(\n",fn_name);
	filePrintf(out,"\tlocal m = Falloff();\n");
	filePrintf(out,"\tm.color1 = (color %g %g %g)\n",c1[0],c1[1],c1[2]);
	filePrintf(out,"\tm.color2 = (color %g %g %g)\n",c2[0],c2[1],c2[2]);
	filePrintf(out,"\tm.type = 0\n\tm.direction = 0\n\treturn m;\n)\n");
}

V_LOCAL void
ms_write_helpers(vhandle_t out)
{
	filePuts(out,AnimateSpheres_body);
}

V_LOCAL char *AnimateSpheres_body =
	"fn AnimateSpheres SceneSpheres SpherePositions FramesPerPos =\n"
	"(\n"
	"\tlocal i, j;\n"
	"\tlocal npos = SpherePositions.count;\n"
	"\tAnimationRange = (interval 0 FramesPerPos * npos)\n"
	"\tanimate on\n"
	"\t(\n"
	"\t\tfor i=1 to npos do\n"
	"\t\t(\n"
	"\t\t\tat time (i * FramesPerPos)\n"
	"\t\t\t(\n"
	"\t\t\t\tfor j=1 to SceneSpheres.count do\n"
	"\t\t\t\t\tSceneSpheres[j].position = SpherePositions[i][j];\n"
	"\t\t\t)\n"
	"\t\t)\n"
	"\t)\n"
	")\n\n";

V_LOCAL void V_CALL
meta_draw(void *param)
{
	/* Send large white rectangle to the feedback buffer */
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	glOrtho(0,1,0,1,-1,1);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();
	glColor4f(1,1,1,1);
	glRectf(-0.1f,-0.1f,1.1f,1.1f);
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();
	draw(param);
}

	/*
	logFormatString(ps->tmpname,"%s/shot%04u.wmf",ps->outdir,*counter);
	// BROKEN! segfaults
	vglDrawToMetafile(ps->tmpname,mmw,mmh,meta_draw,ps);
	*/
