1 /* Steven Andrews, started 10/22/2001.
2  This is a library of functions for the Smoldyn program.
3  See documentation called SmoldynManual.pdf and SmoldynCodeDoc.pdf, and the Smoldyn
4  website, which is at www.smoldyn.org.
5  Copyright 2003-2016 by Steven Andrews.  This work is distributed under the terms
6  of the Gnu Lesser General Public License (LGPL). */
7 
8 #include <float.h>
9 #include <math.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include "Geometry.h"
13 #include "math2.h"
14 #include "opengl2.h"
15 #include "Rn.h"
16 #include "string2.h"
17 #include "../libSteve/SimCommand.h"
18 
19 #ifdef OPTION_NSV
20   #include "nsvc.h"
21 #endif
22 
23 #include "smoldyn.h"
24 #include "smoldynfuncs.h"
25 #include "smoldynconfigure.h"
26 
27 /******************************************************************************/
28 /*********************************** Graphics *********************************/
29 /******************************************************************************/
30 
31 
32 /******************************************************************************/
33 /****************************** Local declarations ****************************/
34 /******************************************************************************/
35 
36 // enumerated types
37 char *graphicslp2string(enum LightParam lp,char *string);
38 
39 // low level utilities
40 
41 // memory management
42 graphicsssptr graphssalloc(void);
43 
44 // data structure output
45 
46 // structure setup
47 
48 // structure update functions
49 int graphicsupdateinit(simptr sim);
50 int graphicsupdatelists(simptr sim);
51 int graphicsupdateparams(simptr sim);
52 
53 // core simulation functions
54 void RenderSurfaces(simptr sim);
55 void RenderMolecs(simptr sim);
56 void RenderText(simptr sim);
57 void RenderSim(simptr sim);
58 
59 // top level OpenGL functions
60 
61 /******************************************************************************/
62 /******************************* enumerated types *****************************/
63 /******************************************************************************/
64 
65 /* graphicsstring2lp */
graphicsstring2lp(char * string)66 enum LightParam graphicsstring2lp(char *string) {
67 	enum LightParam ans;
68 
69 	if(strbegin(string,"ambient",0)) ans=LPambient;
70 	else if(strbegin(string,"diffuse",0)) ans=LPdiffuse;
71 	else if(strbegin(string,"specular",0)) ans=LPspecular;
72 	else if(strbegin(string,"position",0)) ans=LPposition;
73 	else if(strbegin(string,"on",0)) ans=LPon;
74 	else if(strbegin(string,"off",0)) ans=LPoff;
75 	else if(strbegin(string,"auto",0)) ans=LPauto;
76 	else ans=LPnone;
77 	return ans; }
78 
79 
80 /* graphicslp2string */
graphicslp2string(enum LightParam lp,char * string)81 char *graphicslp2string(enum LightParam lp,char *string) {
82 	if(lp==LPambient) strcpy(string,"ambient");
83 	else if(lp==LPdiffuse) strcpy(string,"diffuse");
84 	else if(lp==LPspecular) strcpy(string,"specular");
85 	else if(lp==LPposition) strcpy(string,"position");
86 	else if(lp==LPon) strcpy(string,"on");
87 	else if(lp==LPoff) strcpy(string,"off");
88 	else if(lp==LPauto) strcpy(string,"auto");
89 	else strcpy(string,"none");
90 	return string; }
91 
92 
93 /******************************************************************************/
94 /****************************** low level utilities ***************************/
95 /******************************************************************************/
96 
97 /* graphicsreadcolor */
graphicsreadcolor(char ** stringptr,double * rgba)98 int graphicsreadcolor(char **stringptr,double *rgba) {
99 	char *string,name[STRCHAR];
100 	double r,g,b,a;
101 	int itct,er;
102 
103 	if(!stringptr) return 1;
104 	string=*stringptr;
105 	if(!string) return 1;
106 	itct=sscanf(string,"%s",name);
107 	if(itct!=1) return 1;
108 
109 	er=0;
110 	r=g=b=0;
111 	a=1;
112 	if((name[0]>='0' && name[0]<='9') || name[0]=='.') {	// numbers
113 		itct=sscanf(string,"%lg %lg %lg",&r,&g,&b);
114 		if(itct!=3) er=2;
115 		else {
116 			if(r<0 || r>1 || g<0 ||g>1 || b<0 || b>1) er=3;
117 			string=strnword(string,4); }}
118 	else {																								// word
119 		if(!strcmp(name,"maroon"))			{r=0.5;g=0;b=0;}
120 		else if(!strcmp(name,"red"))		{r=1;g=0;b=0;}
121 		else if(!strcmp(name,"scarlet")) {r=1;g=0.14;b=0;}
122 		else if(!strcmp(name,"rose"))		{r=1;g=0;b=0.5;}
123 		else if(!strcmp(name,"brick"))	{r=0.7;g=0.13;b=0.13;}
124 		else if(!strcmp(name,"pink"))		{r=1;g=0.08;b=0.58;}
125 		else if(!strcmp(name,"brown"))	{r=0.54;g=0.27;b=0.07;}
126 		else if(!strcmp(name,"tan"))		{r=0.86;g=0.58;b=0.44;}
127 		else if(!strcmp(name,"sienna"))	{r=0.56;g=0.42;b=0.14;}
128 		else if(!strcmp(name,"orange")) {r=1;g=0.65;b=0;}
129 		else if(!strcmp(name,"salmon")) {r=0.91;g=0.59;b=0.48;}
130 		else if(!strcmp(name,"coral"))	{r=0.94;g=0.42;b=0.31;}
131 		else if(!strcmp(name,"yellow")) {r=1;g=1;b=0;}
132 		else if(!strcmp(name,"gold"))		{r=1;g=0.84;b=0;}
133 		else if(!strcmp(name,"olive"))	{r=0.5;g=0.5;b=0;}
134 		else if(!strcmp(name,"green"))	{r=0;g=0.5;b=0;}
135 		else if(!strcmp(name,"chartrouse")) {r=0.5;g=1;b=0;}
136 		else if(!strcmp(name,"khaki"))	{r=0.8;g=0.77;b=0.45;}
137 		else if(!strcmp(name,"purple")) {r=0.5;g=0;b=0.5;}
138 		else if(!strcmp(name,"magenta"))	{r=1;g=0;b=1;}
139 		else if(!strcmp(name,"fuchsia"))	{r=1;g=0;b=1;}
140 		else if(!strcmp(name,"lime"))		{r=0;g=1;b=0;}
141 		else if(!strcmp(name,"teal"))		{r=0;g=0.5;b=0.5;}
142 		else if(!strcmp(name,"aqua"))		{r=0;g=1;b=1;}
143 		else if(!strcmp(name,"cyan"))		{r=0;g=1;b=1;}
144 		else if(!strcmp(name,"blue"))		{r=0;g=0;b=1;}
145 		else if(!strcmp(name,"navy"))		{r=0;g=0;b=0.5;}
146 		else if(!strcmp(name,"turquoise")) {r=0.25;g=0.88;b=0.82;}
147 		else if(!strcmp(name,"royal"))	{r=0;g=0.14;b=0.4;}
148 		else if(!strcmp(name,"sky"))		{r=0.53;g=0.81;b=0.92;}
149 		else if(!strcmp(name,"aquamarine")) {r=0.5;g=1;b=0.83;}
150 		else if(!strcmp(name,"indigo"))	{r=0.29;g=0;b=0.51;}
151 		else if(!strcmp(name,"violet"))	{r=0.58;g=0;b=0.83;}
152 		else if(!strcmp(name,"mauve"))	{r=0.88;g=0.69;b=1;}
153 		else if(!strcmp(name,"orchid")) {r=0.73;g=0.33;b=0.83;}
154 		else if(!strcmp(name,"plum"))		{r=0.6;g=0.12;b=0.5;}
155 		else if(!strcmp(name,"azure"))	{r=0;g=0.5;b=1;}
156 		else if(!strcmp(name,"black"))	{r=0;g=0;b=0;}
157 		else if(!strcmp(name,"gray"))		{r=0.5;g=0.5;b=0.5;}
158 		else if(!strcmp(name,"grey"))		{r=0.5;g=0.5;b=0.5;}
159 		else if(!strcmp(name,"silver")) {r=0.75;g=0.75;b=0.75;}
160 		else if(!strcmp(name,"slate"))	{r=0.44;g=0.5;b=0.56;}
161 		else if(!strcmp(name,"white"))	{r=1;g=1;b=1;}
162 
163 		else if(!strcmp(name,"darkred"))	{r=0.55;g=0;b=0;}
164 		else if(!strcmp(name,"darkorange"))	{r=1;g=0.55;b=0;}
165 		else if(!strcmp(name,"darkyellow"))	{r=1;g=0.84;b=0;}
166 		else if(!strcmp(name,"darkgreen"))	{r=0;g=0.39;b=0;}
167 		else if(!strcmp(name,"darkblue"))	{r=0;g=0;b=0.55;}
168 		else if(!strcmp(name,"darkviolet"))	{r=0.29;g=0;b=0.51;}
169 		else if(!strcmp(name,"darkgrey"))	{r=0.25;g=0.25;b=0.25;}
170 		else if(!strcmp(name,"darkgray"))	{r=0.25;g=0.25;b=0.25;}
171 		else if(!strcmp(name,"lightred"))	{r=1;g=0.39;b=0.28;}
172 		else if(!strcmp(name,"lightorange"))	{r=1;g=0.75;b=0.2;}
173 		else if(!strcmp(name,"lightyellow"))	{r=1;g=1;b=0.5;}
174 		else if(!strcmp(name,"lightgreen"))	{r=0.56;g=1;b=0.5;}
175 		else if(!strcmp(name,"lightblue"))	{r=0.53;g=0.81;b=0.98;}
176 		else if(!strcmp(name,"lightviolet"))	{r=0.68;g=0.1;b=1;}
177 		else if(!strcmp(name,"lightgrey"))	{r=0.75;g=0.75;b=0.75;}
178 		else if(!strcmp(name,"lightgray"))	{r=0.75;g=0.75;b=0.75;}
179 
180 		else er=4;
181 		string=strnword(string,2); }
182 
183 	if(string) {
184 		itct=sscanf(string,"%lg",&a);
185 		if(itct!=1) er=5;
186 		if(a<0 || a>1) er=6;
187 		string=strnword(string,2); }
188 
189 	if(rgba) {
190 		rgba[0]=r;
191 		rgba[1]=g;
192 		rgba[2]=b;
193 		rgba[3]=a; }
194 	*stringptr=string;
195 	return er; }
196 
197 
198 /******************************************************************************/
199 /******************************* memory management ****************************/
200 /******************************************************************************/
201 
202 /* graphssalloc */
graphssalloc(void)203 graphicsssptr graphssalloc(void) {
204 	graphicsssptr graphss;
205 	int lt;
206 
207 	graphss=NULL;
208 	CHECKMEM(graphss=(graphicsssptr) malloc(sizeof(struct graphicssuperstruct)));
209 
210 	graphss->condition=SCinit;
211 	graphss->sim=NULL;
212 	graphss->graphics=0;
213 	graphss->currentit=0;
214 	graphss->graphicit=20;
215 	graphss->graphicdelay=0;
216 	graphss->tiffit=0;
217 	graphss->framepts=2;
218 	graphss->gridpts=0;
219 
220 	graphss->framecolor[0]=0;		// black frame
221 	graphss->framecolor[1]=0;
222 	graphss->framecolor[2]=0;
223 	graphss->framecolor[3]=1;
224 
225 	graphss->gridcolor[0]=0;		// black grid
226 	graphss->gridcolor[1]=0;
227 	graphss->gridcolor[2]=0;
228 	graphss->gridcolor[3]=1;
229 
230 	graphss->backcolor[0]=1;		// white background
231 	graphss->backcolor[1]=1;
232 	graphss->backcolor[2]=1;
233 	graphss->backcolor[3]=1;
234 
235 	graphss->textcolor[0]=0;		// black text
236 	graphss->textcolor[1]=0;
237 	graphss->textcolor[2]=0;
238 	graphss->textcolor[3]=0;
239 
240 	graphss->maxtextitems=0;
241 	graphss->ntextitems=0;
242 	graphss->textitems=NULL;
243 
244 	graphicssetlight(NULL,graphss,-1,LPauto,NULL);
245 	for(lt=0;lt<MAXLIGHTS;lt++) graphicssetlight(NULL,graphss,lt,LPauto,NULL);
246 
247 	return graphss;
248 
249 failure:
250 	graphssfree(graphss);
251 	simLog(NULL,10,"Failed to allocate memory in graphssalloc");
252 	return NULL; }
253 
254 
255 /* graphssfree */
graphssfree(graphicsssptr graphss)256 void graphssfree(graphicsssptr graphss) {
257 	int item;
258 
259 	if(!graphss) return;
260 	for(item=0;item<graphss->maxtextitems;item++) free(graphss->textitems[item]);
261 	free(graphss->textitems);
262 	free(graphss);
263 	return; }
264 
265 
266 /******************************************************************************/
267 /***************************** data structure output **************************/
268 /******************************************************************************/
269 
270 
271 /* graphssoutput */
graphssoutput(simptr sim)272 void graphssoutput(simptr sim) {
273 	graphicsssptr graphss;
274 	char string1[STRCHAR],string2[STRCHAR];
275 	int i1,i2,lt;
276 
277 	graphss=sim->graphss;
278 	simLog(sim,2,"GRAPHICS PARAMETERS\n");
279 	if(!graphss || graphss->graphics==0) {
280 		simLog(sim,2," No graphical output\n\n");
281 		return; }
282 
283 	simLog(sim,2," display: ");
284 	if(graphss->graphics==1) simLog(sim,2,"OpenGL");
285 	else if(graphss->graphics==2) simLog(sim,2,"OpenGL_good");
286 	else if(graphss->graphics==3) simLog(sim,2,"OpenGL_better");
287 	simLog(sim,2,", every %i iterations\n",graphss->graphicit);
288 	if(graphss->graphicdelay>0) simLog(sim,2," delay per frame: %ui ms\n",graphss->graphicdelay);
289 
290 	simLog(sim,2," frame thickness: %g",graphss->framepts);
291 	if(graphss->gridpts) simLog(sim,2,", grid thickness: %g",graphss->gridpts);
292 	simLog(sim,2,"\n");
293 	if(graphss->framepts) simLog(sim,2," frame color: %g,%g,%g,%g\n",graphss->framecolor[0],graphss->framecolor[1],graphss->framecolor[2],graphss->framecolor[3]);
294 	if(graphss->gridpts) simLog(sim,2," grid color: %g,%g,%g,%g\n",graphss->gridcolor[0],graphss->gridcolor[1],graphss->gridcolor[2],graphss->gridcolor[3]);
295 	simLog(sim,2," background color: %g,%g,%g,%g\n",graphss->backcolor[0],graphss->backcolor[1],graphss->backcolor[2],graphss->backcolor[3]);
296 
297 	if(graphss->ntextitems) {
298 		simLog(sim,2," text color: %g,%g,%g,%g\n",graphss->textcolor[0],graphss->textcolor[1],graphss->textcolor[2],graphss->textcolor[3]);
299 		simLog(sim,2," text items:");
300 		for(i1=0;i1<graphss->ntextitems;i1++)
301 			simLog(sim,2," %s",graphss->textitems[i1]);
302 		simLog(sim,2,"\n"); }
303 
304 	if(graphss->graphics>=3)
305 		simLog(sim,2," ambient light (%s): %g %g %g %g\n",graphicslp2string(graphss->roomstate,string1),graphss->ambiroom[0],graphss->ambiroom[1],graphss->ambiroom[2],graphss->ambiroom[3]);
306 	for(lt=0;lt<MAXLIGHTS;lt++)
307 		if(graphss->lightstate[lt]!=LPauto) {
308 			simLog(sim,2," light %i: %s\n",lt,graphicslp2string(graphss->lightstate[lt],string1));
309 			simLog(sim,2,"  position: %g %g %g %g\n",graphss->lightpos[lt][0],graphss->lightpos[lt][1],graphss->lightpos[lt][2],graphss->lightpos[lt][3]);
310 			simLog(sim,2,"  ambient: %g %g %g %g\n",graphss->ambilight[lt][0],graphss->ambilight[lt][1],graphss->ambilight[lt][2],graphss->ambilight[lt][3]);
311 			simLog(sim,2,"  diffuse: %g %g %g %g\n",graphss->difflight[lt][0],graphss->difflight[lt][1],graphss->difflight[lt][2],graphss->difflight[lt][3]);
312 			simLog(sim,2,"  specular: %g %g %g %g\n",graphss->speclight[lt][0],graphss->speclight[lt][1],graphss->speclight[lt][2],graphss->speclight[lt][3]); }
313 
314 	gl2GetString("TiffName",string1);
315 	gl2GetString("TiffNameDefault",string2);
316 	i1=(int)gl2GetNumber("TiffNumber");
317 	i2=(int)gl2GetNumber("TiffNumMax");
318 	if(strcmp(string1,string2)) simLog(sim,2," TIFF name: %s\n",string1);
319 	if(i1!=(int)gl2GetNumber("TiffNumberDefault") || i2!=(int)gl2GetNumber("TiffNumMaxDefault"))
320 		simLog(sim,2," TIFFs numbered from %i to %i\n",i1,i2);
321 	simLog(sim,2,"\n");
322 	return; }
323 
324 
325 /* writegraphss */
writegraphss(simptr sim,FILE * fptr)326 void writegraphss(simptr sim,FILE *fptr) {
327 	graphicsssptr graphss;
328 	char string[STRCHAR];
329 	int lt,item;
330 
331 	graphss=sim->graphss;
332 	if(!graphss) return;
333 
334 	fprintf(fptr,"# Graphics parameters\n");
335 	if(graphss->graphics==0) fprintf(fptr,"graphics none\n");
336 	else if(graphss->graphics==1) fprintf(fptr,"graphics opengl\n");
337 	else if(graphss->graphics==2) fprintf(fptr,"graphics opengl_good\n");
338 	else if(graphss->graphics==3) fprintf(fptr,"graphics opengl_better\n");
339 	if(graphss->graphicit>1) fprintf(fptr,"graphic_iter %i\n",graphss->graphicit);
340 	if(graphss->graphicdelay>0) fprintf(fptr,"graphic_delay %ui\n",graphss->graphicdelay);
341 
342 	if(graphss->tiffit>0) fprintf(fptr,"tiff_iter %i\n",graphss->tiffit);
343 	fprintf(fptr,"tiff_name %s\n",gl2GetString("TiffName",string));
344 	fprintf(fptr,"tiff_min %i\n",gl2SetOptionInt("TiffNumber",-1));
345 	fprintf(fptr,"tiff_max %i\n",gl2SetOptionInt("TiffNumMax",-1));
346 
347 	fprintf(fptr,"frame_thickness %g\n",graphss->framepts);
348 	fprintf(fptr,"frame_color %g %g %g %g\n",graphss->framecolor[0],graphss->framecolor[1],graphss->framecolor[2],graphss->framecolor[3]);
349 	fprintf(fptr,"grid_thickness %g\n",graphss->gridpts);
350 	fprintf(fptr,"grid_color %g %g %g %g\n",graphss->gridcolor[0],graphss->gridcolor[1],graphss->gridcolor[2],graphss->gridcolor[3]);
351 	fprintf(fptr,"background_color %g %g %g %g\n",graphss->backcolor[0],graphss->backcolor[1],graphss->backcolor[2],graphss->backcolor[3]);
352 	fprintf(fptr,"text_color %g %g %g %g\n",graphss->textcolor[0],graphss->textcolor[1],graphss->textcolor[2],graphss->textcolor[3]);
353 
354 	for(item=0;item<graphss->ntextitems;item++)
355 		fprintf(fptr,"text_display %s\n",graphss->textitems[item]);
356 
357 	if(graphss->roomstate!=LPauto) {
358 		fprintf(fptr,"light global ambient %g %g %g %g\n",graphss->ambiroom[0],graphss->ambiroom[1],graphss->ambiroom[2],graphss->ambiroom[3]);
359 		fprintf(fptr,"light global %s\n",graphicslp2string(graphss->roomstate,string)); }
360 	for(lt=0;lt<MAXLIGHTS;lt++)
361 		if(graphss->lightstate[lt]!=LPauto) {
362 			fprintf(fptr,"light %i position %g %g %g\n",lt,graphss->lightpos[lt][0],graphss->lightpos[lt][1],graphss->lightpos[lt][2]);
363 			fprintf(fptr,"light %i ambient %g %g %g %g\n",lt,graphss->ambilight[lt][0],graphss->ambilight[lt][1],graphss->ambilight[lt][2],graphss->ambilight[lt][3]);
364 			fprintf(fptr,"light %i diffuse %g %g %g %g\n",lt,graphss->difflight[lt][0],graphss->difflight[lt][1],graphss->difflight[lt][2],graphss->difflight[lt][3]);
365 			fprintf(fptr,"light %i specular %g %g %g %g\n",lt,graphss->speclight[lt][0],graphss->speclight[lt][1],graphss->speclight[lt][2],graphss->speclight[lt][3]);
366 			fprintf(fptr,"light %i %s\n",lt,graphicslp2string(graphss->lightstate[lt],string)); }
367 
368 	fprintf(fptr,"\n");
369 	return; }
370 
371 
372 /* checkgraphicsparams */
checkgraphicsparams(simptr sim,int * warnptr)373 int checkgraphicsparams(simptr sim,int *warnptr) {
374 	int error,warn;
375 	graphicsssptr graphss;
376 	char string[STRCHAR];
377 
378 	error=warn=0;
379 	graphss=sim->graphss;
380 	if(!graphss) {
381 		if(warnptr) *warnptr=warn;
382 		return 0; }
383 
384 	if(graphss->condition!=SCok) {
385 		warn++;
386 		simLog(sim,7," WARNING: graphics structure %s\n",simsc2string(graphss->condition,string)); }
387 
388 	if(warnptr) *warnptr=warn;
389 	return error; }
390 
391 /******************************************************************************/
392 /******************************* structure setup ******************************/
393 /******************************************************************************/
394 
395 
396 /* graphicssetcondition */
graphicssetcondition(graphicsssptr graphss,enum StructCond cond,int upgrade)397 void graphicssetcondition(graphicsssptr graphss,enum StructCond cond,int upgrade) {
398 	if(!graphss) return;
399 	if(upgrade==0 && graphss->condition>cond) graphss->condition=cond;
400 	else if(upgrade==1 && graphss->condition<cond) graphss->condition=cond;
401 	else if(upgrade==2) graphss->condition=cond;
402 	if(graphss->sim && graphss->condition<graphss->sim->condition) {
403 		cond=graphss->condition;
404 		simsetcondition(graphss->sim,cond==SCinit?SClists:cond,0); }
405 	return; }
406 
407 
408 /* graphicsenablegraphics */
graphicsenablegraphics(simptr sim,const char * type)409 int graphicsenablegraphics(simptr sim,const char *type) {
410 	graphicsssptr graphss;
411 	int code;
412 
413 	if(!sim) return 2;
414 
415 	if(type) {
416 		if(!strcmp(type,"none")) code=0;
417 		else if(!strcmp(type,"opengl")) code=1;
418 		else if(!strcmp(type,"opengl_good")) code=2;
419 		else if(!strcmp(type,"opengl_better")) code=3;
420 		else return 3; }
421 	else code=-1;
422 
423 	if(sim->graphss && (code==-1 || sim->graphss->graphics==code)) return 0;
424 	if(!sim->graphss && code==0) return 0;
425 
426 	if(!sim->graphss) {
427 		graphss=graphssalloc();
428 		if(!graphss) return 1;
429 		sim->graphss=graphss;
430 		graphss->sim=sim; }
431 	else graphss=sim->graphss;
432 	if(code>=0) graphss->graphics=code;
433 	graphicssetcondition(graphss,SClists,0);
434 	return 0; }
435 
436 
437 /* graphicssetiter */
graphicssetiter(simptr sim,int iter)438 int graphicssetiter(simptr sim,int iter) {
439 	int er;
440 
441 	er=graphicsenablegraphics(sim,NULL);
442 	if(er) return er;
443 	if(iter<1) return 3;
444 	sim->graphss->graphicit=iter;
445 	return 0; }
446 
447 
448 /* graphicssettiffiter */
graphicssettiffiter(simptr sim,int iter)449 int graphicssettiffiter(simptr sim,int iter) {
450 	int er;
451 
452 	er=graphicsenablegraphics(sim,NULL);
453 	if(er) return er;
454 	if(iter<1) return 3;
455 	sim->graphss->tiffit=iter;
456 	return 0; }
457 
458 
459 /* graphicssetdelay */
graphicssetdelay(simptr sim,int delay)460 int graphicssetdelay(simptr sim,int delay) {
461 	int er;
462 
463 	er=graphicsenablegraphics(sim,NULL);
464 	if(er) return er;
465 	if(delay<0) return 3;
466 	sim->graphss->graphicdelay=delay;
467 	return 0; }
468 
469 
470 /* graphicssetframethickness */
graphicssetframethickness(simptr sim,double thickness)471 int graphicssetframethickness(simptr sim,double thickness) {
472 	int er;
473 
474 	er=graphicsenablegraphics(sim,NULL);
475 	if(er) return er;
476 	if(thickness<0) return 3;
477 	sim->graphss->framepts=thickness;
478 	return 0; }
479 
480 
481 /* graphicssetframecolor */
graphicssetframecolor(simptr sim,double * color)482 int graphicssetframecolor(simptr sim,double *color) {
483 	int er;
484 
485 	er=graphicsenablegraphics(sim,NULL);
486 	if(er) return er;
487 	if(color[0]<0 || color[0]>1) return 3;
488 	if(color[1]<0 || color[1]>1) return 3;
489 	if(color[2]<0 || color[2]>1) return 3;
490 	if(color[3]<0 || color[3]>1) return 3;
491 	sim->graphss->framecolor[0]=color[0];
492 	sim->graphss->framecolor[1]=color[1];
493 	sim->graphss->framecolor[2]=color[2];
494 	sim->graphss->framecolor[3]=color[3];
495 	return 0; }
496 
497 
498 /* graphicssetgridthickness */
graphicssetgridthickness(simptr sim,double thickness)499 int graphicssetgridthickness(simptr sim,double thickness) {
500 	int er;
501 
502 	er=graphicsenablegraphics(sim,NULL);
503 	if(er) return er;
504 	if(thickness<0) return 3;
505 	sim->graphss->gridpts=thickness;
506 	return 0; }
507 
508 
509 /* graphicssetgridcolor */
graphicssetgridcolor(simptr sim,double * color)510 int graphicssetgridcolor(simptr sim,double *color) {
511 	int er;
512 
513 	er=graphicsenablegraphics(sim,NULL);
514 	if(er) return er;
515 	if(color[0]<0 || color[0]>1) return 3;
516 	if(color[1]<0 || color[1]>1) return 3;
517 	if(color[2]<0 || color[2]>1) return 3;
518 	if(color[3]<0 || color[3]>1) return 3;
519 	sim->graphss->gridcolor[0]=color[0];
520 	sim->graphss->gridcolor[1]=color[1];
521 	sim->graphss->gridcolor[2]=color[2];
522 	sim->graphss->gridcolor[3]=color[3];
523 	return 0; }
524 
525 
526 /* graphicssetbackcolor */
graphicssetbackcolor(simptr sim,double * color)527 int graphicssetbackcolor(simptr sim,double *color) {
528 	int er;
529 
530 	er=graphicsenablegraphics(sim,NULL);
531 	if(er) return er;
532 	if(color[0]<0 || color[0]>1) return 3;
533 	if(color[1]<0 || color[1]>1) return 3;
534 	if(color[2]<0 || color[2]>1) return 3;
535 	if(color[3]<0 || color[3]>1) return 3;
536 	sim->graphss->backcolor[0]=color[0];
537 	sim->graphss->backcolor[1]=color[1];
538 	sim->graphss->backcolor[2]=color[2];
539 	sim->graphss->backcolor[3]=color[3];
540 
541 	graphicssetcondition(sim->graphss,SCparams,0);
542 	return 0; }
543 
544 
545 /* graphicssettextcolor */
graphicssettextcolor(simptr sim,double * color)546 int graphicssettextcolor(simptr sim,double *color) {
547 	int er;
548 
549 	er=graphicsenablegraphics(sim,NULL);
550 	if(er) return er;
551 	if(color[0]<0 || color[0]>1) return 3;
552 	if(color[1]<0 || color[1]>1) return 3;
553 	if(color[2]<0 || color[2]>1) return 3;
554 	if(color[3]<0 || color[3]>1) return 3;
555 	sim->graphss->textcolor[0]=color[0];
556 	sim->graphss->textcolor[1]=color[1];
557 	sim->graphss->textcolor[2]=color[2];
558 	sim->graphss->textcolor[3]=color[3];
559 	return 0; }
560 
561 
562 /* graphicssettextitem */
graphicssettextitem(simptr sim,char * itemname)563 int graphicssettextitem(simptr sim,char *itemname) {
564 	graphicsssptr graphss;
565 	int er,i,newmaxtextitems,item;
566 	char **newtextitems;
567 	enum MolecState ms;
568 
569 	er=graphicsenablegraphics(sim,NULL);
570 	if(er) return er;
571 	graphss=sim->graphss;
572 
573 	if(graphss->ntextitems==graphss->maxtextitems) {
574 		newmaxtextitems=2*graphss->maxtextitems+1;
575 		newtextitems=(char **) calloc(newmaxtextitems,sizeof(char *));
576 		if(!newtextitems) return 1;
577 		for(item=0;item<graphss->maxtextitems;item++)
578 			newtextitems[item]=graphss->textitems[item];
579 		for(;item<newmaxtextitems;item++) {
580 			newtextitems[item]=EmptyString();
581 			if(!newtextitems[item]) return 1; }
582 
583 		free(graphss->textitems);
584 		graphss->maxtextitems=newmaxtextitems;
585 		graphss->textitems=newtextitems; }
586 
587 	if(!strcmp(itemname,"time"));		// supported items
588 	else if(((sim->mols && ((i=molstring2index1(sim,itemname,&ms,NULL))>=0 || i==-5)) || sim->ruless) && ms!=MSbsoln);
589 	else return 2;									// unrecognized item name
590 
591 	for(item=0;item<graphss->ntextitems;item++)
592 		if(!strcmp(itemname,graphss->textitems[item])) return 3;
593 	strncpy(graphss->textitems[graphss->ntextitems++],itemname,STRCHAR);
594 	return 0; }
595 
596 /* graphicssetlight */
graphicssetlight(simptr sim,graphicsssptr graphss,int lt,enum LightParam ltparam,double * value)597 int graphicssetlight(simptr sim,graphicsssptr graphss,int lt,enum LightParam ltparam,double *value) {
598 	int i,er;
599 
600 	if(!graphss) {
601 		er=graphicsenablegraphics(sim,NULL);
602 		if(er) return er;
603 		graphss=sim->graphss; }
604 
605 	if(lt==-1) {										// room lights
606 		if(ltparam==LPambient) {
607 			if(graphss->roomstate==LPauto) graphss->roomstate=LPon;
608 			for(i=0;i<4;i++) graphss->ambiroom[i]=value[i]; }
609 		else if(ltparam==LPon)
610 			graphss->roomstate=LPon;
611 		else if(ltparam==LPoff)
612 			graphss->roomstate=LPoff;
613 		else if(ltparam==LPauto) {
614 			graphss->roomstate=LPauto;
615 			graphss->ambiroom[0]=0.2;		// low white ambient light
616 			graphss->ambiroom[1]=0.2;
617 			graphss->ambiroom[2]=0.2;
618 			graphss->ambiroom[3]=1; }}
619 
620 	else if(ltparam==LPambient) {
621 		if(graphss->lightstate[lt]==LPauto) graphss->lightstate[lt]=LPon;
622 		for(i=0;i<4;i++) graphss->ambilight[lt][i]=value[i]; }
623 	else if(ltparam==LPdiffuse) {
624 		if(graphss->lightstate[lt]==LPauto) graphss->lightstate[lt]=LPon;
625 		for(i=0;i<4;i++) graphss->difflight[lt][i]=value[i]; }
626 	else if(ltparam==LPspecular) {
627 		if(graphss->lightstate[lt]==LPauto) graphss->lightstate[lt]=LPon;
628 		for(i=0;i<4;i++) graphss->speclight[lt][i]=value[i]; }
629 	else if(ltparam==LPposition) {
630 		if(graphss->lightstate[lt]==LPauto) graphss->lightstate[lt]=LPon;
631 		for(i=0;i<4;i++) graphss->lightpos[lt][i]=value[i]; }
632 	else if(ltparam==LPon)
633 		graphss->lightstate[lt]=LPon;
634 	else if(ltparam==LPoff)
635 		graphss->lightstate[lt]=LPoff;
636 	else if(ltparam==LPauto) {
637 		graphss->lightstate[lt]=LPauto;
638 		graphss->ambilight[lt][0]=0;	// no ambient lightsource light
639 		graphss->ambilight[lt][1]=0;
640 		graphss->ambilight[lt][2]=0;
641 		graphss->ambilight[lt][3]=1;
642 		graphss->difflight[lt][0]=1;	// white diffuse lightsource light
643 		graphss->difflight[lt][1]=1;
644 		graphss->difflight[lt][2]=1;
645 		graphss->difflight[lt][3]=1;
646 		graphss->speclight[lt][0]=1;	// white specular lightsource light
647 		graphss->speclight[lt][1]=1;
648 		graphss->speclight[lt][2]=1;
649 		graphss->speclight[lt][3]=1;
650 		graphss->lightpos[lt][0]=1;		// lightsource at (1,1,0)
651 		graphss->lightpos[lt][1]=1;
652 		graphss->lightpos[lt][2]=0;
653 		graphss->lightpos[lt][3]=0; }
654 
655 	graphicssetcondition(graphss,SCparams,0);
656 	return 0; }
657 
658 
659 /******************************************************************************/
660 /************************** structure update functions ************************/
661 /******************************************************************************/
662 
663 
664 /* graphicsupdateinit */
graphicsupdateinit(simptr sim)665 int graphicsupdateinit(simptr sim) {
666 #ifdef __gl_h_
667 	graphicsssptr graphss;
668 	int qflag,tflag,dim;
669 	wallptr *wlist;
670 
671 	graphss=sim->graphss;
672 	tflag=strchr(sim->flags,'t')?1:0;
673 	if(tflag || graphss->graphics==0) return 0;
674 
675 	qflag=strchr(sim->flags,'q')?1:0;
676 	gl2glutInit(NULL,NULL);
677 	gl2SetOptionInt("Fix2DAspect",1);
678 	gl2SetOptionVoid("FreeFunc",(void*) &simfree);
679 	gl2SetOptionVoid("FreePointer",(void*)sim);
680 	if(!qflag) simLog(sim,2,"Starting simulation\n");
681 	dim=sim->dim;
682 	wlist=sim->wlist;
683 	if(dim==1) gl2Initialize(sim->filename,(float)wlist[0]->pos,(float)wlist[1]->pos,0,0,0,0);
684 	else if(dim==2) gl2Initialize(sim->filename,(float)wlist[0]->pos,(float)wlist[1]->pos,(float)wlist[2]->pos,(float)wlist[3]->pos,0,0);
685 	else {
686 		gl2Initialize(sim->filename,(float)wlist[0]->pos,(float)wlist[1]->pos,(float)wlist[2]->pos,(float)wlist[3]->pos,(float)wlist[4]->pos,(float)wlist[5]->pos);
687 		if(sim->srfss) {
688 			glEnable(GL_BLEND);
689 			glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);}}
690 #endif
691 	return 0; }
692 
693 
694 /* graphicsupdatelists */
graphicsupdatelists(simptr sim)695 int graphicsupdatelists(simptr sim) {
696 #ifdef __gl_h_
697 	graphicsssptr graphss;
698 	int tflag;
699 	GLfloat f1[4];
700 
701 	graphss=sim->graphss;
702 	tflag=strchr(sim->flags,'t')?1:0;
703 	if(tflag || graphss->graphics==0) return 0;
704 
705 	if(graphss->graphics>=3) {
706 		glEnable(GL_LIGHTING);
707 		glLightModelfv(GL_LIGHT_MODEL_AMBIENT,gl2Double2GLfloat(graphss->ambiroom,f1,4));
708 		glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,1);
709 		glEnable(GL_COLOR_MATERIAL);
710 		glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); }
711 #endif
712 	return 0; }
713 
714 
715 /* graphicsupdateparams */
graphicsupdateparams(simptr sim)716 int graphicsupdateparams(simptr sim) {
717 #ifdef __gl_h_
718 	graphicsssptr graphss;
719 	int lt,tflag;
720 	GLenum gllightnum;
721 	GLfloat glf1[4];
722 
723 	graphss=sim->graphss;
724 	tflag=strchr(sim->flags,'t')?1:0;
725 	if(tflag || graphss->graphics==0) return 0;
726 
727 	glClearColor((GLclampf)graphss->backcolor[0],(GLclampf)graphss->backcolor[1],(GLclampf)graphss->backcolor[2],(GLclampf)graphss->backcolor[3]);
728 	if(graphss->graphics>=3) {
729 		for(lt=0;lt<MAXLIGHTS;lt++)
730 			if(graphss->lightstate[lt]==LPon) {
731 				if(lt==0) gllightnum=GL_LIGHT0;
732 				else if(lt==1) gllightnum=GL_LIGHT1;
733 				else if(lt==2) gllightnum=GL_LIGHT2;
734 				else if(lt==3) gllightnum=GL_LIGHT3;
735 				else if(lt==4) gllightnum=GL_LIGHT4;
736 				else if(lt==5) gllightnum=GL_LIGHT5;
737 				else if(lt==6) gllightnum=GL_LIGHT6;
738 				else gllightnum=GL_LIGHT7;
739 				glLightfv(gllightnum,GL_AMBIENT,gl2Double2GLfloat(graphss->ambilight[lt],glf1,4));
740 				glLightfv(gllightnum,GL_DIFFUSE,gl2Double2GLfloat(graphss->difflight[lt],glf1,4));
741 				glLightfv(gllightnum,GL_SPECULAR,gl2Double2GLfloat(graphss->speclight[lt],glf1,4));
742 				glLightfv(gllightnum,GL_POSITION,gl2Double2GLfloat(graphss->lightpos[lt],glf1,4));
743 				glEnable(gllightnum); }}
744 #endif
745 	return 0; }
746 
747 
748 /* graphicsupdate */
graphicsupdate(simptr sim)749 int graphicsupdate(simptr sim) {
750 	int er;
751 	graphicsssptr graphss;
752 
753 	graphss=sim->graphss;
754 	if(graphss) {
755 		if(graphss->condition==SCinit) {
756 			er=graphicsupdateinit(sim);
757 			if(er) return er;
758 			graphicssetcondition(graphss,SClists,1); }
759 		if(graphss->condition==SClists) {
760 			er=graphicsupdatelists(sim);
761 			if(er) return er;
762 			graphicssetcondition(graphss,SCparams,1); }
763 		if(graphss->condition==SCparams) {
764 			er=graphicsupdateparams(sim);
765 			if(er) return er;
766 			graphicssetcondition(graphss,SCok,1); }}
767 	return 0; }
768 
769 
770 /******************************************************************************/
771 /*************************** core simulation functions ************************/
772 /******************************************************************************/
773 
774 
775 /* RenderSurfaces */
RenderSurfaces(simptr sim)776 void RenderSurfaces(simptr sim) {
777 #ifdef __gl_h_
778 	surfacessptr srfss;
779 	surfaceptr srf;
780 	int s,p,graphics,fdone,bdone,c;
781 	double **point,*front;
782 	double xlo,xhi,ylo,yhi,xpix,ypix,ymid,zmid;
783 	double delta,deltax,deltay,theta,vect[3],vect2[3],axis[3],height;
784 	double flcolor[4],blcolor[4];
785 	enum DrawMode fdrawmode,bdrawmode,fdm,bdm;
786 	GLdouble gldvect[3];
787 	GLfloat glfvect[4];
788 
789 	srfss=sim->srfss;
790 	graphics=sim->graphss->graphics;
791 	if(!srfss) return;
792 	xlo=gl2GetNumber("ClipLeft");
793 	xhi=gl2GetNumber("ClipRight");
794 	ylo=gl2GetNumber("ClipBot");
795 	yhi=gl2GetNumber("ClipTop");
796 	xpix=gl2GetNumber("PixWide");
797 	ypix=gl2GetNumber("PixHigh");
798 	ymid=gl2GetNumber("ClipMidy");
799 	zmid=gl2GetNumber("ClipMidz");
800 
801 	if(sim->dim==1) {
802 		for(s=0;s<srfss->nsrf;s++) {
803 			srf=srfss->srflist[s];
804 			if(srf->fdrawmode!=DMno) {
805 				glLineWidth((GLfloat)srf->edgepts);
806 				delta=srf->edgepts*(xhi-xlo)/xpix/2;
807 				glColor4fv(gl2Double2GLfloat(srf->fcolor,glfvect,4));
808 				glBegin(GL_LINES);
809 				for(p=0;p<srf->npanel[0];p++) {		// 1-D rectangles front
810 					point=srf->panels[0][p]->point;
811 					front=srf->panels[0][p]->front;
812 					glVertex3d((GLdouble)(point[0][0]+front[0]*delta),(GLdouble)(ymid-(yhi-ylo)/20),(GLdouble)zmid);
813 					glVertex3d((GLdouble)(point[0][0]+front[0]*delta),(GLdouble)(ymid+(yhi-ylo)/20),(GLdouble)zmid); }
814 				for(p=0;p<srf->npanel[1];p++) {		// 1-D triangles front
815 					point=srf->panels[1][p]->point;
816 					front=srf->panels[1][p]->front;
817 					glVertex3d((GLdouble)(point[0][0]+front[0]*delta),(GLdouble)(ymid-(yhi-ylo)/20),(GLdouble)zmid);
818 					glVertex3d((GLdouble)(point[0][0]+front[0]*delta),(GLdouble)(ymid+(yhi-ylo)/20),(GLdouble)zmid); }
819 				for(p=0;p<srf->npanel[2];p++) {		// 1-D spheres front
820 					point=srf->panels[2][p]->point;
821 					front=srf->panels[2][p]->front;
822 					glVertex3d((GLdouble)(point[0][0]+point[1][0]+front[0]*delta),(GLdouble)(ymid-(yhi-ylo)/20),(GLdouble)zmid);
823 					glVertex3d((GLdouble)(point[0][0]+point[1][0]+front[0]*delta),(GLdouble)(ymid+(yhi-ylo)/20),(GLdouble)zmid);
824 					glVertex3d((GLdouble)(point[0][0]-point[1][0]-front[0]*delta),(GLdouble)(ymid-(yhi-ylo)/20),(GLdouble)zmid);
825 					glVertex3d((GLdouble)(point[0][0]-point[1][0]-front[0]*delta),(GLdouble)(ymid+(yhi-ylo)/20),(GLdouble)zmid); }
826 				glEnd();
827 
828 				delta*=-1;
829 				glColor4fv(gl2Double2GLfloat(srf->bcolor,glfvect,4));
830 				glBegin(GL_LINES);
831 				for(p=0;p<srf->npanel[0];p++) {		// 1-D rectangles back
832 					point=srf->panels[0][p]->point;
833 					front=srf->panels[0][p]->front;
834 					glVertex3d((GLdouble)(point[0][0]+front[0]*delta),(GLdouble)(ymid-(yhi-ylo)/20),(GLdouble)zmid);
835 					glVertex3d((GLdouble)(point[0][0]+front[0]*delta),(GLdouble)(ymid+(yhi-ylo)/20),(GLdouble)zmid); }
836 				for(p=0;p<srf->npanel[1];p++) {		// 1-D triangles back
837 					point=srf->panels[1][p]->point;
838 					front=srf->panels[1][p]->front;
839 					glVertex3d((GLdouble)(point[0][0]+front[0]*delta),(GLdouble)(ymid-(yhi-ylo)/20),(GLdouble)zmid);
840 					glVertex3d((GLdouble)(point[0][0]+front[0]*delta),(GLdouble)(ymid+(yhi-ylo)/20),(GLdouble)zmid); }
841 				for(p=0;p<srf->npanel[2];p++) {		// 1-D spheres back
842 					point=srf->panels[2][p]->point;
843 					front=srf->panels[2][p]->front;
844 					glVertex3d((GLdouble)(point[0][0]+point[1][0]+front[0]*delta),(GLdouble)(ymid-(yhi-ylo)/20),(GLdouble)zmid);
845 					glVertex3d((GLdouble)(point[0][0]+point[1][0]+front[0]*delta),(GLdouble)(ymid+(yhi-ylo)/20),(GLdouble)zmid);
846 					glVertex3d((GLdouble)(point[0][0]-point[1][0]-front[0]*delta),(GLdouble)(ymid-(yhi-ylo)/20),(GLdouble)zmid);
847 					glVertex3d((GLdouble)(point[0][0]-point[1][0]-front[0]*delta),(GLdouble)(ymid+(yhi-ylo)/20),(GLdouble)zmid); }
848 				glEnd(); }}}
849 
850 	else if(sim->dim==2) {
851 		for(s=0;s<srfss->nsrf;s++) {
852 			srf=srfss->srflist[s];
853 			fdrawmode=srf->fdrawmode;
854 			bdrawmode=srf->bdrawmode;
855 			if(fdrawmode!=DMno) {
856 				glColor4fv(gl2Double2GLfloat(srf->fcolor,glfvect,4));
857 				if(fdrawmode&DMedge || fdrawmode&DMface) {
858 					glLineWidth((GLfloat)srf->edgepts);
859 					deltax=srf->edgepts*(xhi-xlo)/xpix/2.5;
860 					deltay=srf->edgepts*(yhi-ylo)/ypix/2.5;
861 					glBegin(GL_LINES); }
862 				else {
863 					glPointSize((GLfloat)srf->edgepts);
864 					deltax=deltay=0;
865 					glBegin(GL_POINTS); }
866 
867 				for(p=0;p<srf->npanel[0];p++) {		// 2-D rectangles front
868 					point=srf->panels[0][p]->point;
869 					front=srf->panels[0][p]->front;
870 					if(front[1]==0) {
871 						glVertex3d((GLdouble)(point[0][0]+front[0]*deltax),(GLdouble)(point[0][1]),(GLdouble)zmid);
872 						glVertex3d((GLdouble)(point[1][0]+front[0]*deltax),(GLdouble)(point[1][1]),(GLdouble)zmid); }
873 					else {
874 						glVertex3d((GLdouble)(point[0][0]),(GLdouble)(point[0][1]+front[0]*deltay),(GLdouble)zmid);
875 						glVertex3d((GLdouble)(point[1][0]),(GLdouble)(point[1][1]+front[0]*deltay),(GLdouble)zmid); }}
876 				for(p=0;p<srf->npanel[1];p++) {		// 2-D triangles front
877 					point=srf->panels[1][p]->point;
878 					front=srf->panels[1][p]->front;
879 					glVertex3d((GLdouble)(point[0][0]+front[0]*deltax),(GLdouble)(point[0][1]+front[1]*deltay),(GLdouble)zmid);
880 					glVertex3d((GLdouble)(point[1][0]+front[0]*deltax),(GLdouble)(point[1][1]+front[1]*deltay),(GLdouble)zmid); }
881 				for(p=0;p<srf->npanel[3];p++) {		// 2-D cylinders front
882 					point=srf->panels[3][p]->point;
883 					front=srf->panels[3][p]->front;
884 					glVertex3d((GLdouble)(point[0][0]+front[0]*point[2][0]+front[2]*front[0]*deltax),(GLdouble)(point[0][1]+front[1]*point[2][0]+front[2]*front[1]*deltay),(GLdouble)zmid);
885 					glVertex3d((GLdouble)(point[1][0]+front[0]*point[2][0]+front[2]*front[0]*deltax),(GLdouble)(point[1][1]+front[1]*point[2][0]+front[2]*front[1]*deltay),(GLdouble)zmid);
886 					glVertex3d((GLdouble)(point[0][0]-front[0]*point[2][0]-front[2]*front[0]*deltax),(GLdouble)(point[0][1]-front[1]*point[2][0]-front[2]*front[1]*deltay),(GLdouble)zmid);
887 					glVertex3d((GLdouble)(point[1][0]-front[0]*point[2][0]-front[2]*front[0]*deltax),(GLdouble)(point[1][1]-front[1]*point[2][0]-front[2]*front[1]*deltay),(GLdouble)zmid); }
888 				for(p=0;p<srf->npanel[5];p++) {		// 2-D disks front
889 					point=srf->panels[5][p]->point;
890 					front=srf->panels[5][p]->front;
891 					glVertex3d((GLdouble)(point[0][0]+point[1][0]*front[1]+front[0]*deltax),(GLdouble)(point[0][1]-point[1][0]*front[0]+front[1]*deltay),(GLdouble)zmid);
892 					glVertex3d((GLdouble)(point[0][0]-point[1][0]*front[1]+front[0]*deltax),(GLdouble)(point[0][1]+point[1][0]*front[0]+front[1]*deltay),(GLdouble)zmid); }
893 				glEnd();
894 				for(p=0;p<srf->npanel[2];p++) {		// 2-D spheres front
895 					point=srf->panels[2][p]->point;
896 					front=srf->panels[2][p]->front;
897 					if(fdrawmode&DMvert) gl2DrawCircleD(point[0],point[1][0],(int)point[1][1],'v',2);
898 					if(fdrawmode&DMface) gl2DrawCircleD(point[0],point[1][0],(int)point[1][1],'f',2);
899 					if(fdrawmode&DMedge) gl2DrawCircleD(point[0],point[1][0]+front[0]*deltax,(int)point[1][1],'e',2); }
900 				for(p=0;p<srf->npanel[4];p++) {		// 2-D hemispheres front
901 					point=srf->panels[4][p]->point;
902 					front=srf->panels[4][p]->front;
903 					theta=atan2(point[2][1],point[2][0])+PI/2.0;
904 					if(fdrawmode&DMvert) gl2DrawArcD(point[0],point[1][0],theta,theta+PI,(int)point[1][1],'v',2);
905 					if(fdrawmode&DMface) gl2DrawArcD(point[0],point[1][0],theta,theta+PI,(int)point[1][1],'f',2);
906 					if(fdrawmode&DMedge) gl2DrawArcD(point[0],point[1][0]+front[0]*deltax,theta,theta+PI,(int)point[1][1],'e',2); }
907 
908 				if(fdrawmode&DMedge || fdrawmode&DMface) {
909 					deltax*=-1;
910 					deltay*=-1;
911 					glColor4fv(gl2Double2GLfloat(srf->bcolor,glfvect,4));
912 					glBegin(GL_LINES);
913 					for(p=0;p<srf->npanel[0];p++) {		// 2-D rectangles back
914 						point=srf->panels[0][p]->point;
915 						front=srf->panels[0][p]->front;
916 						if(front[1]==0) {
917 							glVertex3d((GLdouble)(point[0][0]+front[0]*deltax),(GLdouble)(point[0][1]),(GLdouble)zmid);
918 							glVertex3d((GLdouble)(point[1][0]+front[0]*deltax),(GLdouble)(point[1][1]),(GLdouble)zmid); }
919 						else {
920 							glVertex3d((GLdouble)(point[0][0]),(GLdouble)(point[0][1]+front[0]*deltay),(GLdouble)zmid);
921 							glVertex3d((GLdouble)(point[1][0]),(GLdouble)(point[1][1]+front[0]*deltay),(GLdouble)zmid); }}
922 					for(p=0;p<srf->npanel[1];p++) {		// 2-D triangles back
923 						point=srf->panels[1][p]->point;
924 						front=srf->panels[1][p]->front;
925 						glVertex3d((GLdouble)(point[0][0]+front[0]*deltax),(GLdouble)(point[0][1]+front[1]*deltay),(GLdouble)zmid);
926 						glVertex3d((GLdouble)(point[1][0]+front[0]*deltax),(GLdouble)(point[1][1]+front[1]*deltay),(GLdouble)zmid); }
927 					for(p=0;p<srf->npanel[3];p++) {		// 2-D cylinders back
928 						point=srf->panels[3][p]->point;
929 						front=srf->panels[3][p]->front;
930 						glVertex3d((GLdouble)(point[0][0]+front[0]*point[2][0]+front[2]*front[0]*deltax),(GLdouble)(point[0][1]+front[1]*point[2][0]+front[2]*front[1]*deltay),(GLdouble)zmid);
931 						glVertex3d((GLdouble)(point[1][0]+front[0]*point[2][0]+front[2]*front[0]*deltax),(GLdouble)(point[1][1]+front[1]*point[2][0]+front[2]*front[1]*deltay),(GLdouble)zmid);
932 						glVertex3d((GLdouble)(point[0][0]-front[0]*point[2][0]-front[2]*front[0]*deltax),(GLdouble)(point[0][1]-front[1]*point[2][0]-front[2]*front[1]*deltay),(GLdouble)zmid);
933 						glVertex3d((GLdouble)(point[1][0]-front[0]*point[2][0]-front[2]*front[0]*deltax),(GLdouble)(point[1][1]-front[1]*point[2][0]-front[2]*front[1]*deltay),(GLdouble)zmid); }
934 					for(p=0;p<srf->npanel[5];p++) {		// 2-D disks back
935 						point=srf->panels[5][p]->point;
936 						front=srf->panels[5][p]->front;
937 						glVertex3d((GLdouble)(point[0][0]+point[1][0]*front[1]+front[0]*deltax),(GLdouble)(point[0][1]-point[1][0]*front[0]+front[1]*deltay),(GLdouble)zmid);
938 						glVertex3d((GLdouble)(point[0][0]-point[1][0]*front[1]+front[0]*deltax),(GLdouble)(point[0][1]+point[1][0]*front[0]+front[1]*deltay),(GLdouble)zmid); }
939 					glEnd();
940 					for(p=0;p<srf->npanel[2];p++) {		// 2-D spheres back
941 						point=srf->panels[2][p]->point;
942 						front=srf->panels[2][p]->front;
943 						if(bdrawmode&DMedge) gl2DrawCircleD(point[0],point[1][0]+front[0]*deltax,(int)point[1][1],'e',2); }
944 					for(p=0;p<srf->npanel[4];p++) {		// 2-D hemispheres back
945 						point=srf->panels[4][p]->point;
946 						front=srf->panels[4][p]->front;
947 						theta=atan2(point[2][1],point[2][0])+PI/2.0;
948 						if(bdrawmode&DMedge) gl2DrawArcD(point[0],point[1][0]+front[0]*deltax,theta,theta+PI,(int)point[1][1],'e',2); }}}}}
949 
950 	else if(sim->dim==3) {
951 		for(s=0;s<srfss->nsrf;s++) {
952 			srf=srfss->srflist[s];
953 			fdrawmode=srf->fdrawmode;
954 			bdrawmode=srf->bdrawmode;
955 			for(c=0;c<4;c++) flcolor[c]=srf->fcolor[c];
956 			for(c=0;c<4;c++) blcolor[c]=srf->bcolor[c];
957 
958 			if(fdrawmode&DMface) fdm=DMface;
959 			else if(fdrawmode&DMedge) fdm=DMedge;
960 			else if(fdrawmode&DMvert) fdm=DMvert;
961 			else fdm=DMno;
962 
963 			if(bdrawmode&DMface) bdm=DMface;
964 			else if(bdrawmode&DMedge) bdm=DMedge;
965 			else if(bdrawmode&DMvert) bdm=DMvert;
966 			else bdm=DMno;
967 
968 			while(fdm || bdm) {
969 				if(fdm==DMface) glPolygonMode(GL_FRONT,GL_FILL);
970 				else if(fdm==DMedge) glPolygonMode(GL_FRONT,GL_LINE);
971 				else if(fdm==DMvert) glPolygonMode(GL_FRONT,GL_POINT);
972 				else glCullFace(GL_FRONT);
973 
974 				if(bdm==DMface) glPolygonMode(GL_BACK,GL_FILL);
975 				else if(bdm==DMedge) glPolygonMode(GL_BACK,GL_LINE);
976 				else if(bdm==DMvert) glPolygonMode(GL_BACK,GL_POINT);
977 				else glCullFace(GL_BACK);
978 
979 				glColor4fv(gl2Double2GLfloat(flcolor,glfvect,4));
980 				glLineWidth((GLfloat)srf->edgepts);
981 				if(graphics>=2 && srf->edgestipple[1]!=0xFFFF) {
982 					glEnable(GL_LINE_STIPPLE);
983 					glLineStipple((GLint)srf->edgestipple[0],(GLushort)srf->edgestipple[1]); }
984 
985 				if(graphics>=3) {
986 					glMaterialfv(GL_FRONT,GL_SPECULAR,gl2Double2GLfloat(flcolor,glfvect,4));
987 					glMaterialfv(GL_BACK,GL_SPECULAR,gl2Double2GLfloat(blcolor,glfvect,4));
988 					glMateriali(GL_FRONT,GL_SHININESS,(GLint)srf->fshiny);
989 					glMateriali(GL_BACK,GL_SHININESS,(GLint)srf->bshiny); }
990 
991 				if(srf->npanel[PSrect]) {
992 					glBegin(GL_QUADS);									// 3-D rectangles
993 					for(p=0;p<srf->npanel[PSrect];p++) {
994 						if(graphics>=3) {
995 							gldvect[0]=gldvect[1]=gldvect[2]=0;
996 							front=srf->panels[PSrect][p]->front;
997 							gldvect[(int)front[1]]=(GLdouble)front[0];
998 							glNormal3dv(gldvect); }
999 						point=srf->panels[PSrect][p]->point;
1000 						glVertex3d((GLdouble)(point[0][0]),(GLdouble)(point[0][1]),(GLdouble)(point[0][2]));
1001 						glVertex3d((GLdouble)(point[1][0]),(GLdouble)(point[1][1]),(GLdouble)(point[1][2]));
1002 						glVertex3d((GLdouble)(point[2][0]),(GLdouble)(point[2][1]),(GLdouble)(point[2][2]));
1003 						glVertex3d((GLdouble)(point[3][0]),(GLdouble)(point[3][1]),(GLdouble)(point[3][2])); }
1004 					glEnd(); }
1005 
1006 				if(srf->npanel[PStri]) {
1007 					glBegin(GL_TRIANGLES);							// 3-D triangles
1008 					for(p=0;p<srf->npanel[PStri];p++) {
1009 						if(graphics>=3) glNormal3fv(gl2Double2GLfloat(srf->panels[PStri][p]->front,glfvect,4));
1010 						point=srf->panels[PStri][p]->point;
1011 						glVertex3d((GLdouble)(point[0][0]),(GLdouble)(point[0][1]),(GLdouble)(point[0][2]));
1012 						glVertex3d((GLdouble)(point[1][0]),(GLdouble)(point[1][1]),(GLdouble)(point[1][2]));
1013 						glVertex3d((GLdouble)(point[2][0]),(GLdouble)(point[2][1]),(GLdouble)(point[2][2])); }
1014 					glEnd(); }
1015 
1016 				for(p=0;p<srf->npanel[PSsph];p++) {		// 3-D spheres
1017 					point=srf->panels[PSsph][p]->point;
1018 					front=srf->panels[PSsph][p]->front;
1019 					glMatrixMode(GL_MODELVIEW);
1020 					glPushMatrix();
1021 					glTranslated((GLdouble)(point[0][0]),(GLdouble)(point[0][1]),(GLdouble)(point[0][2]));
1022 					gl2DrawSphere(point[1][0],(int)point[1][1],(int)point[1][2],front[0]>0?0:1,graphics>=3?1:0);
1023 					glPopMatrix(); }
1024 
1025 				for(p=0;p<srf->npanel[PScyl];p++) {			// 3-D cylinders
1026 					point=srf->panels[PScyl][p]->point;
1027 					front=srf->panels[PScyl][p]->front;
1028 					glMatrixMode(GL_MODELVIEW);
1029 					glPushMatrix();
1030 					glTranslated((GLdouble)(point[0][0]),(GLdouble)(point[0][1]),(GLdouble)(point[0][2]));
1031 					vect[0]=vect[1]=0;
1032 					vect[2]=1;
1033 					vect2[0]=point[1][0]-point[0][0];
1034 					vect2[1]=point[1][1]-point[0][1];
1035 					vect2[2]=point[1][2]-point[0][2];
1036 					height=sqrt(vect2[0]*vect2[0]+vect2[1]*vect2[1]+vect2[2]*vect2[2]);
1037 					normalizeVD(vect2,3);
1038 					theta=gl2FindRotateD(vect,vect2,axis);
1039 					glRotated((GLdouble)theta,(GLdouble)(axis[0]),(GLdouble)(axis[1]),(GLdouble)(axis[2]));
1040 					gl2DrawCylinder(point[2][0],point[2][0],height,(int)point[2][1],(int)point[2][2],front[0]>0?0:1,graphics>=3?1:0);
1041 					glPopMatrix(); }
1042 
1043 				for(p=0;p<srf->npanel[PShemi];p++) {			// 3-D hemispheres
1044 					point=srf->panels[PShemi][p]->point;
1045 					front=srf->panels[PShemi][p]->front;
1046 					glMatrixMode(GL_MODELVIEW);
1047 					glPushMatrix();
1048 					glTranslated((GLdouble)(point[0][0]),(GLdouble)(point[0][1]),(GLdouble)(point[0][2]));
1049 					vect[0]=vect[1]=0;
1050 					vect[2]=-1;
1051 					theta=gl2FindRotateD(vect,point[2],axis);
1052 					glRotated((GLdouble)theta,(GLdouble)(axis[0]),(GLdouble)(axis[1]),(GLdouble)(axis[2]));
1053 					gl2DrawHemisphere(point[1][0],(int)point[1][1],(int)point[1][2],front[0]>0?0:1,graphics>=3?1:0);
1054 					glPopMatrix(); }
1055 
1056 				for(p=0;p<srf->npanel[PSdisk];p++) {			// 3-D disks
1057 					point=srf->panels[PSdisk][p]->point;
1058 					front=srf->panels[PSdisk][p]->front;
1059 					glMatrixMode(GL_MODELVIEW);
1060 					glPushMatrix();
1061 					glTranslated((GLdouble)(point[0][0]),(GLdouble)(point[0][1]),(GLdouble)(point[0][2]));
1062 					vect[0]=vect[1]=0;
1063 					vect[2]=-1;
1064 					theta=gl2FindRotateD(vect,front,axis);
1065 					glRotated((GLdouble)theta,(GLdouble)(axis[0]),(GLdouble)(axis[1]),(GLdouble)(axis[2]));
1066 					vect2[0]=vect2[1]=vect2[2]=0;
1067 					gl2DrawCircleD(vect2,point[1][0],(int)point[1][1],'f',3);		//?? 'f' isn't right
1068 					glPopMatrix(); }
1069 
1070 				fdone=0;
1071 				if(fdm==DMface && fdrawmode&DMedge) fdm=DMedge;
1072 				else if((fdm==DMface || fdm==DMedge) && fdrawmode&DMvert) fdm=DMvert;
1073 				else fdone=1;
1074 
1075 				bdone=0;
1076 				if(bdm==DMface && bdrawmode&DMedge) bdm=DMedge;
1077 				else if((bdm==DMface || bdm==DMedge) && bdrawmode&DMvert) bdm=DMvert;
1078 				else bdone=1;
1079 
1080 				if(fdone && bdone) fdm=bdm=DMno;
1081 				else {
1082 					for(c=0;c<3;c++) flcolor[c]=blcolor[c]=0;
1083 					flcolor[3]=blcolor[3]=1; }}
1084 
1085 			if((fdrawmode || bdrawmode) && glIsEnabled(GL_LINE_STIPPLE))
1086 				glDisable(GL_LINE_STIPPLE); }}
1087 #endif
1088 	return; }
1089 
1090 
1091 /* RenderFilaments */
RenderFilaments(simptr sim)1092 void RenderFilaments(simptr sim) {
1093 #ifdef __gl_h_
1094 	filamentssptr filss;
1095 	filamenttypeptr filtype;
1096 	filamentptr fil;
1097 	int f,vtx,graphics,ft;
1098 	double *point;
1099 	enum DrawMode drawmode;
1100 	GLfloat glfvect[4];
1101 
1102 	filss=sim->filss;
1103 	if(!filss) return;
1104 	graphics=sim->graphss->graphics;
1105 
1106 	for(ft=0;ft<filss->ntype;ft++) {
1107 		filtype=filss->filtypes[ft];
1108 		drawmode=filtype->drawmode;
1109 
1110 		for(f=0;f<filtype->nfil;f++) {
1111 			fil=filtype->fillist[f];
1112 			if(drawmode==DMno);
1113 
1114 			else if(drawmode&DMvert || drawmode&DMedge) {
1115 				glColor4fv(gl2Double2GLfloat(filtype->color,glfvect,4));
1116 				if(graphics>=2 && filtype->edgestipple[1]!=0xFFFF) {
1117 					glEnable(GL_LINE_STIPPLE);
1118 					glLineStipple((GLint)filtype->edgestipple[0],(GLushort)filtype->edgestipple[1]); }
1119 				if(drawmode&DMedge) {
1120 					glLineWidth((GLfloat)filtype->edgepts);
1121 					glBegin(GL_LINE_STRIP); }
1122 				else {
1123 					glPointSize((GLfloat)filtype->edgepts);
1124 					glBegin(GL_POINTS); }
1125 
1126 				for(vtx=fil->frontbs;vtx<fil->nbs+fil->frontbs;vtx++) {
1127 					if(filtype->isbead)
1128 						point=fil->beads[vtx]->xyz;
1129 					else
1130 						point=fil->segments[vtx]->xyzfront;
1131 					glVertex3d((GLdouble)(point[0]),(GLdouble)(point[1]),(GLdouble)(point[2])); }
1132 					if(!filtype->isbead) {
1133 						point=fil->segments[vtx-1]->xyzback;
1134 						glVertex3d((GLdouble)(point[0]),(GLdouble)(point[1]),(GLdouble)(point[2])); }
1135 				glEnd(); }
1136 
1137 			else if(drawmode&DMface) {
1138 				glPolygonMode(GL_FRONT,GL_FILL);
1139 				glCullFace(GL_BACK);
1140 				if(graphics>=3) {
1141 					//glMaterialfv(GL_FRONT,GL_SPECULAR,gl2Double2GLfloat(srf->fcolor,glfvect,4));
1142 					//glMaterialfv(GL_BACK,GL_SPECULAR,gl2Double2GLfloat(srf->bcolor,glfvect,4));
1143 					glMateriali(GL_FRONT,GL_SHININESS,(GLint)filtype->shiny); }
1144 				for(vtx=fil->frontbs;vtx<fil->nbs+fil->frontbs;vtx++)
1145 					/*gl2drawtwistprism(fil->px[vtx],fil->px[vtx+1],fil->nface,fil->po[vtx],twist,fil->radius,fil->facecolor)*/; }
1146 			if(glIsEnabled(GL_LINE_STIPPLE))
1147 				glDisable(GL_LINE_STIPPLE); }}
1148 
1149 #endif
1150 	return; }
1151 
1152 
1153 /* RenderMolecs */
RenderMolecs(simptr sim)1154 void RenderMolecs(simptr sim) {
1155 #ifdef __gl_h_
1156 	molssptr mols;
1157 	moleculeptr mptr;
1158 	int ll,m,i,dim;
1159 	double ymid,zmid;
1160 	enum MolecState ms;
1161 	GLfloat whitecolor[]={1,1,1,1};
1162 	GLfloat glf1[4];
1163 
1164 	dim=sim->dim;
1165 	mols=sim->mols;
1166 	if(!mols) return;
1167 	ymid=gl2GetNumber("ClipMidy");
1168 	zmid=gl2GetNumber("ClipMidz");
1169 
1170 	if(sim->graphss->graphics==1) {
1171 		for(ll=0;ll<sim->mols->nlist;ll++)
1172 			if(sim->mols->listtype[ll]==MLTsystem)
1173 				for(m=0;m<mols->nl[ll];m++) {
1174 					mptr=mols->live[ll][m];
1175 					i=mptr->ident;
1176 					ms=mptr->mstate;
1177 					if(mols->display[i][ms]>0) {
1178 						glPointSize((GLfloat)mols->display[i][ms]);
1179 						glColor3fv(gl2Double2GLfloat(mols->color[i][ms],glf1,3));
1180 						glBegin(GL_POINTS);
1181 						if(dim==1) glVertex3d((GLdouble)mptr->pos[0],(GLdouble)ymid,(GLdouble)zmid);
1182 						else if(dim==2) glVertex3d((GLdouble)(mptr->pos[0]),(GLdouble)(mptr->pos[1]),(GLdouble)zmid);
1183 						else glVertex3fv(gl2Double2GLfloat(mptr->pos,glf1,3));
1184 						glEnd(); }}}
1185 
1186 	else if(sim->graphss->graphics>=2) {
1187 		glMatrixMode(GL_MODELVIEW);
1188 		glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
1189 		if(sim->graphss->graphics>=3) {
1190 			glMaterialfv(GL_FRONT,GL_SPECULAR,whitecolor);
1191 			glMateriali(GL_FRONT,GL_SHININESS,30); }
1192 		for(ll=0;ll<sim->mols->nlist;ll++)
1193 			if(sim->mols->listtype[ll]==MLTsystem)
1194 				for(m=0;m<mols->nl[ll];m++) {
1195 					mptr=mols->live[ll][m];
1196 					i=mptr->ident;
1197 					ms=mptr->mstate;
1198 					if(mols->display[i][ms]>0) {
1199 						glColor3fv(gl2Double2GLfloat(mols->color[i][ms],glf1,3));
1200 						glPushMatrix();
1201 						if(dim==1) glTranslated((GLdouble)(mptr->pos[0]),(GLdouble)ymid,(GLdouble)zmid);
1202 						else if(dim==2) glTranslated((GLdouble)(mptr->pos[0]),(GLdouble)(mptr->pos[1]),(GLdouble)zmid);
1203 						else glTranslated((GLdouble)(mptr->pos[0]),(GLdouble)(mptr->pos[1]),(GLdouble)(mptr->pos[2]));
1204 						glutSolidSphere((GLdouble)(mols->display[i][ms]),15,15);
1205 						glPopMatrix(); }}}
1206 
1207 #endif
1208 	return; }
1209 
1210 
1211 /* RenderLattice */
RenderLattice(simptr sim)1212 void RenderLattice(simptr sim) {
1213 #ifdef __gl_h_
1214 	latticeptr lattice;
1215 	int lat,n,ilat,ismol,i,dim;
1216 	const int *copy_numbers;
1217 	const double* positions;
1218 	molssptr mols;
1219 	GLfloat glf1[4];
1220 	double poslo[3],poshi[3],deltay;
1221 
1222 	mols=sim->mols;
1223 	dim=sim->dim;
1224 	poslo[0]=poshi[0]=gl2GetNumber("ClipMidx");
1225 	poslo[1]=poshi[1]=gl2GetNumber("ClipMidy");
1226 	poslo[2]=poshi[2]=gl2GetNumber("ClipMidz");
1227 	for(lat=0;lat<sim->latticess->nlattice;lat++) {
1228 		lattice = sim->latticess->latticelist[lat];
1229 		positions=NULL;
1230 		copy_numbers=NULL;
1231 		n=0;
1232 		for(ilat=0;ilat<lattice->nspecies;ilat++) {		// ilat is the species identity
1233 			ismol=lattice->species_index[ilat];
1234 			NSV_CALL(n = nsv_get_species_copy_numbers(lattice->nsv, ismol,&copy_numbers,&positions));
1235 			for (i=0;i<n;++i) {						// n is the total number of molecules of this species, copy_numbers is how many in each site, and positions are the site positions
1236 				if((mols->display[ismol][MSsoln]>0)&&(copy_numbers[i]>0)) {
1237 					poslo[0]=positions[3*i+0]-0.5*lattice->dx[0];
1238 					poshi[0]=positions[3*i+0]+0.5*lattice->dx[0];
1239 					if(dim==1) {
1240 						deltay=0.025*(gl2GetNumber("ClipTop")-gl2GetNumber("ClipBot"));
1241 						poslo[1]-=deltay;
1242 						poshi[1]+=deltay; }
1243 					else if(dim>1) {
1244 						poslo[1]=positions[3*i+1]-0.5*lattice->dx[1];
1245 						poshi[1]=positions[3*i+1]+0.5*lattice->dx[1]; }
1246 					if(dim>2) {
1247 						poslo[2]=positions[3*i+2]-0.5*lattice->dx[2];
1248 						poshi[2]=positions[3*i+2]+0.5*lattice->dx[2]; }
1249 					glColor3fv(gl2Double2GLfloat(mols->color[ismol][MSsoln],glf1,3));
1250 					gl2DrawBoxFaceD(poslo,poshi,dim==3?3:2); }}}}
1251 #endif
1252 	return; }
1253 
1254 
1255 /* RenderText */
RenderText(simptr sim)1256 void RenderText(simptr sim) {
1257 #ifdef __gl_h_
1258 	graphicsssptr graphss;
1259 	int item,i,*index;
1260 	char *itemname,string[STRCHAR],string2[STRCHAR];
1261 	enum MolecState ms;
1262 
1263 	graphss=sim->graphss;
1264 	string2[0]='\0';
1265 	for(item=0;item<graphss->ntextitems;item++) {
1266 		itemname=graphss->textitems[item];
1267 		if(!strcmp(itemname,"time"))
1268 			 snprintf(string,STRCHAR,"time: %g",sim->time);
1269 		else if((i=molstring2index1(sim,itemname,&ms,&index))>=0 || i==-5)
1270 			snprintf(string,STRCHAR,"%s: %i",itemname,molcount(sim,i,index,ms,-1));
1271 		else if(sim->ruless)
1272 			snprintf(string,STRCHAR,"%s: 0",itemname);
1273 		else
1274 			snprintf(string,STRCHAR,"syntax error");
1275 
1276 		if(STRCHAR-strlen(string2)>strlen(string))
1277 			strcat(string2,string);
1278 		if(item+1<graphss->ntextitems)
1279 			strncat(string2,", ",STRCHAR-3); }
1280 	gl2DrawTextD(5,95,graphss->textcolor,GLUT_BITMAP_HELVETICA_12,string2,-1);
1281 #endif
1282 	return; }
1283 
1284 
1285 /* RenderSim */
RenderSim(simptr sim)1286 void RenderSim(simptr sim) {
1287 #ifdef __gl_h_
1288 	graphicsssptr graphss;
1289 	double pt1[DIMMAX],pt2[DIMMAX];
1290 	int dim;
1291 	wallptr *wlist;
1292 	GLfloat glf1[4];
1293 
1294 	graphss=sim->graphss;
1295 	if(!graphss || graphss->graphics==0) return;
1296 	dim=sim->dim;
1297 	wlist=sim->wlist;
1298 	if(dim<3) glClear(GL_COLOR_BUFFER_BIT);
1299 	else glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
1300 
1301 	if(dim==3) RenderMolecs(sim);
1302 
1303 	if(graphss->framepts) {														// draw bounding box
1304 		pt1[0]=wlist[0]->pos;
1305 		pt2[0]=wlist[1]->pos;
1306 		pt1[1]=dim>1?wlist[2]->pos:0;
1307 		pt2[1]=dim>1?wlist[3]->pos:0;
1308 		pt1[2]=dim>2?wlist[4]->pos:0;
1309 		pt2[2]=dim>2?wlist[5]->pos:0;
1310 		glColor4fv(gl2Double2GLfloat(graphss->framecolor,glf1,4));
1311 		glLineWidth((GLfloat)graphss->framepts);
1312 		gl2DrawBoxD(pt1,pt2,dim); }
1313 
1314 	if(graphss->gridpts) {
1315 		pt1[0]=sim->boxs->min[0];
1316 		pt2[0]=pt1[0]+sim->boxs->size[0]*sim->boxs->side[0];
1317 		pt1[1]=dim>1?sim->boxs->min[1]:0;
1318 		pt2[1]=dim>1?pt1[1]+sim->boxs->size[1]*sim->boxs->side[1]:0;
1319 		pt1[2]=dim>2?sim->boxs->min[2]:0;
1320 		pt2[2]=dim>2?pt1[2]+sim->boxs->size[2]*sim->boxs->side[2]:0;
1321 		glColor4fv(gl2Double2GLfloat(graphss->gridcolor,glf1,4));
1322 		if(dim==1) glPointSize((GLfloat)graphss->gridpts);
1323 		else glLineWidth((GLfloat)graphss->gridpts);
1324 		gl2DrawGridD(pt1,pt2,sim->boxs->side,dim); }
1325 
1326 	if(dim<3) RenderMolecs(sim);
1327 
1328 	if(sim->srfss) RenderSurfaces(sim);
1329 	if(sim->filss) RenderFilaments(sim);
1330 	if(sim->latticess) RenderLattice(sim);
1331 	if(graphss->ntextitems) RenderText(sim);
1332 
1333 	glutSwapBuffers();
1334 #endif
1335 	return; }
1336 
1337 
1338 /******************************************************************************/
1339 /************************** Top level OpenGL functions ************************/
1340 /******************************************************************************/
1341 
1342 
1343 void RenderScene(void);
1344 void TimerFunction(int state);
1345 
1346 simptr Sim;
1347 
1348 
1349 /* smolPostRedisplay */
smolPostRedisplay(void)1350 void smolPostRedisplay(void) {	//??
1351 #ifdef __gl_h_
1352 	glutPostRedisplay();
1353 #endif
1354 	return; }
1355 
1356 
1357 /* RenderScene */
RenderScene(void)1358 void RenderScene(void) {
1359 	RenderSim(Sim);
1360 	return; }
1361 
1362 
1363 /* TimerFunction */
TimerFunction(int state)1364 void TimerFunction(int state) {
1365 #ifdef __gl_h_
1366 	static int oldstate=0;
1367 	unsigned int delay;
1368 	int it;
1369 	simptr sim;
1370 	graphicsssptr graphss;
1371 
1372 	sim=Sim;
1373 	graphss=sim->graphss;
1374 	//qflag=strchr(sim->flags,'q')?1:0;
1375 	delay=graphss->graphicdelay;
1376 
1377 	if(oldstate==1 && gl2State(-1)==0) {							// leave pause state
1378 		oldstate=0;
1379 		sim->clockstt=time(NULL);
1380 		simLog(sim,2,"Simulation running\n"); }
1381 
1382 	if(state==0 && gl2State(-1)==0) {										// normal run mode
1383 		it=graphss->currentit;
1384 		if(!(it%graphss->graphicit)) glutPostRedisplay();
1385 		if(graphss->tiffit>0 && it>0 && !((it-1)%graphss->tiffit)) gl2SetKeyPush('T');
1386 		state=simulatetimestep(sim);
1387 		graphss->currentit++; }
1388 	else if(state>0 || (state==0 && gl2State(-1)==2)) {			// stop the simulation
1389 		if(oldstate==0) sim->elapsedtime+=difftime(time(NULL),sim->clockstt);
1390 		scmdpop(sim->cmds,sim->tmax);
1391 		scmdexecute(sim->cmds,sim->time,sim->dt,-1,1);
1392 		scmdsetcondition(sim->cmds,0,0);
1393 		endsimulate(sim,state);
1394 		if(sim->quitatend) gl2SetKeyPush('Q');	//??
1395 		state=-1; }
1396 	else if(oldstate==0 && gl2State(-1)==1) {					// enter pause state
1397 		sim->elapsedtime+=difftime(time(NULL),sim->clockstt);
1398 		oldstate=1;
1399 		delay=20;
1400 		simLog(sim,2,"Simulation paused at simulation time: %g\n",sim->time); }
1401 	else {																						// still in pause state or simulation is over
1402 		glutPostRedisplay();
1403 		delay=20; }
1404 
1405 	glutTimerFunc(delay,TimerFunction,state);
1406 #endif
1407 	return; }
1408 
1409 
1410 
1411 /* smolsimulategl */
smolsimulategl(simptr sim)1412 void smolsimulategl(simptr sim) {
1413 #ifdef __gl_h_
1414 	int er;
1415 
1416 	glutTimerFunc((unsigned int)0,TimerFunction,0);
1417 	Sim=sim;
1418 	sim->clockstt=time(NULL);
1419 	er=simdocommands(sim);
1420 	if(er) endsimulate(sim,er);
1421 	glutDisplayFunc(RenderScene);
1422 	glutMainLoop();
1423 #else
1424 	simLog(sim,5,"Graphics are unavailable, so performing non-graphics simulation.\n");
1425 	smolsimulate(sim);
1426 #endif
1427 	return; }
1428