1 // lpanel.cpp   lightpanel class
2 
3 #define DEBUG 0
4 
5 /* Copyright (c) 2007-2008, John Kichury
6 
7    This software is freely distributable free of charge and without license fees with the
8    following conditions:
9 
10    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
13    JOHN KICHURY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
14    IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
15    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16 
17    The above copyright notice must be included in any copies of this software.
18 
19 */
20 
21 #ifdef __CYGWIN__
22 #include <windef.h>
23 #endif
24 
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <pthread.h>
30 #include <GL/gl.h>
31 #include <GL/glu.h>
32 #include "lp_utils.h"
33 #include "lp_materials.h"
34 #include "lpanel.h"
35 
36 #include "lpanel_data.h"
37 
38 extern pthread_mutex_t data_sample_lock;
39 
40 static parser_rules_t light_parse_rules[] =
41 {
42   { "color",   3, 3, PARSER_FLOAT },
43   { "group",   1, 1, PARSER_INT },
44   { "object",  1, 1, PARSER_STRING },
45   { "pos",     2, 3, PARSER_FLOAT },
46   { "size",    2, 3, PARSER_FLOAT },
47   { NULL,0,0,0 }
48 };
49 
50 extern Parser parser;
51 
52 
drawLightObject(lpLight * lp)53 void drawLightObject(lpLight *lp)
54 {
55    lp->obj_ref->draw(2);
56 }
57 
drawLightGraphics(lpLight * lp)58 void drawLightGraphics(lpLight *lp)
59 {
60  int i;
61  int lod=1;
62 
63 for(i=0;i<3;i++)
64  {
65    if( lp->color[i] < 0. ||
66     lp->color[i] > 1. )
67     printf("drawLight: color out of range color[%d] = %f\n", i, lp->color[i]);
68  }
69 
70   //glColor3f(0.,0.,0.);
71   glBegin(GL_POLYGON);
72 
73    for(i=0;i<cir2d_nverts-1;i+=lod)
74     glVertex2fv(&cir2d_data2[i][0]);
75 
76   glEnd();
77 
78   glBegin(GL_TRIANGLE_STRIP);
79 
80   for(i=0;i<cir2d_nverts-1;i+=lod)
81    {
82      glColor3fv(&lp->color[0]);
83      glVertex2fv(&cir2d_data2[i][0]);
84      glColor3f(0.,0.,0.);
85      glVertex2fv(&cir2d_data[i][0]);
86    }
87 
88   glColor3fv(&lp->color[0]);
89   glVertex2fv(&cir2d_data2[0][0]);
90   glColor3f(0.,0.,0.);
91   glVertex2fv(&cir2d_data[0][0]);
92   glEnd();
93 
94 }
95 
96 void
sampleData8_error(lpLight * p)97 sampleData8_error(lpLight *p)
98 {
99 #if 0
100 static int flag = 0;
101  if(!flag)
102   {
103     printf("sampleData8: light %s has no data bound to it.  \n", p->name);
104     flag = 1;
105   }
106 #endif
107 }
108 
109 void
sampleData8(lpLight * p)110 sampleData8(lpLight *p)
111 {
112   unsigned char bit;
113   uint8 *ptr = (uint8 *) p->dataptr;
114 
115   bit = (int) (*ptr >> p->bitnum) & 0x01;
116 
117   if(bit)
118   {
119     p->on_time += ( *p->simclock - p->old_clock );
120   }
121   p->old_clock = *p->simclock;
122   p->dirty = 1;
123   p->state = bit;
124 
125 }
126 
127 
128 void
sampleData8invert(lpLight * p)129 sampleData8invert(lpLight *p)
130 {
131   unsigned char bit;
132   uint8 *ptr = (uint8 *) p->dataptr;
133 
134   bit = (int) ~(*ptr >> p->bitnum) & 0x01;
135 
136   if(bit)
137   {
138     p->on_time += ( *p->simclock - p->old_clock );
139   }
140   p->old_clock = *p->simclock;
141   p->dirty = 1;
142   p->state = bit;
143 
144 }
145 
146 void
sampleData16(lpLight * p)147 sampleData16(lpLight *p)
148 {
149   unsigned char bit;
150   uint16 *ptr = (uint16 *) p->dataptr;
151   uint64 on_time_inc = 0;
152   int logit = 0;
153 
154   bit = (int) (*ptr >> p->bitnum) & 0x01;
155 
156 #if 0
157   if(bit)
158   {
159 #if 0
160     p->on_time += ( *p->simclock - p->old_clock );
161 #endif
162    on_time_inc = ( *p->simclock - p->old_clock );
163   }
164 
165   if( bit != p->state)
166    {
167 	on_time_inc = on_time_inc >> 1;
168    }
169   p->on_time += on_time_inc;
170 #endif
171 
172  //if(p->old_clock > *p->simclock) printf("sampleData16: clock stepped backward\n");
173 
174   if(bit)
175   {
176     p->on_time += ( *p->simclock - p->old_clock );
177   }
178 
179   p->old_clock = *p->simclock;
180   p->dirty = 1;
181   p->state = bit;
182 
183 }
184 
185 void
sampleDatafv(lpLight * p)186 sampleDatafv(lpLight *p)
187 {
188   float *ptr = (float *) p->dataptr;
189   int logit = 0;
190 
191   if(p->smoothing > 0)
192   {
193     p->intense_curr = p->intensity;
194     p->intense_samples[p->intense_curr_idx]  = ptr[p->bitnum];
195 
196     if(p->intense_samples[p->intense_curr_idx] > 1.0) p->intense_samples[p->intense_curr_idx] = 1.0;
197     else if(p->intense_samples[p->intense_curr_idx] < 0.0) p->intense_samples[p->intense_curr_idx] = 0.0;
198 
199     p->intense_incr = ( p->intense_samples[p->intense_curr_idx] -
200 			p->intense_samples[!p->intense_curr_idx]) / (float) p->smoothing;
201 
202   }
203   else
204    p->intensity = ptr[p->bitnum];
205 
206 }
207 
208 
209 
210 void
sampleData16invert(lpLight * p)211 sampleData16invert(lpLight *p)
212 {
213   unsigned char bit;
214   uint16 *ptr = (uint16 *) p->dataptr;
215 
216   bit = (int) ~(*ptr >> p->bitnum) & 0x01;
217 
218   if(bit)
219   {
220     p->on_time += ( *p->simclock - p->old_clock );
221   }
222   p->old_clock = *p->simclock;
223   p->dirty = 1;
224   p->state = bit;
225 
226 }
227 
228 void
sampleData32(lpLight * p)229 sampleData32(lpLight *p)
230 {
231   unsigned char bit;
232   uint32 *ptr = (uint32 *) p->dataptr;
233 
234   bit = (int) (*ptr >> p->bitnum) & 0x01;
235 
236   if(bit)
237   {
238     p->on_time += ( *p->simclock - p->old_clock );
239   }
240   p->old_clock = *p->simclock;
241   p->dirty = 1;
242   p->state = bit;
243 
244 }
245 
246 
247 void
sampleData32invert(lpLight * p)248 sampleData32invert(lpLight *p)
249 {
250   unsigned char bit;
251   uint32 *ptr = (uint32 *) p->dataptr;
252 
253   bit = (int) ~(*ptr >> p->bitnum) & 0x01;
254 
255   if(bit)
256   {
257     p->on_time += ( *p->simclock - p->old_clock );
258   }
259   p->old_clock = *p->simclock;
260   p->dirty = 1;
261   p->state = bit;
262 
263 }
264 
265 void
sampleData64(lpLight * p)266 sampleData64(lpLight *p)
267 {
268   unsigned char bit;
269   uint64 *ptr = (uint64 *) p->dataptr;
270 
271   bit = (int) (*ptr >> p->bitnum) & 0x01;
272 
273   if(bit)
274   {
275     p->on_time += ( *p->simclock - p->old_clock );
276   }
277   p->old_clock = *p->simclock;
278   p->dirty = 1;
279   p->state = bit;
280 
281 }
282 
283 void
sampleData64invert(lpLight * p)284 sampleData64invert(lpLight *p)
285 {
286   unsigned char bit;
287   uint64 *ptr = (uint64 *) p->dataptr;
288 
289   bit = (int) ~(*ptr >> p->bitnum) & 0x01;
290 
291   if(bit)
292   {
293     p->on_time += ( *p->simclock - p->old_clock );
294   }
295   p->old_clock = *p->simclock;
296   p->dirty = 1;
297   p->state = bit;
298 
299 }
300 
301 
Lpanel(void)302 Lpanel::Lpanel(void)		 // constructor
303 {
304  int i;
305 
306 #if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__)
307 #else
308  window = 0;
309  cx = 0;
310  dpy = 0;
311 #endif
312 
313  num_lights = 0;
314  max_lights = 0;
315  lights = NULL;
316 
317  num_switches = max_switches = 0;
318  switches = NULL;
319  mom_switch_pressed = NULL;
320 
321  default_clock = 0;
322  old_clock = 0;
323  simclock =  &default_clock;
324  clock_warp = 0;
325 
326  default_runflag = 0;
327  runflag = &default_runflag;
328 
329  // init light groups
330 
331  for(i=0;i<LP_MAX_LIGHT_GROUPS;i++)
332  {
333    light_groups[i].num_items = 0;
334    light_groups[i].max_items = 0;
335    light_groups[i].list = NULL;
336  }
337 
338  // init light graphics
339 
340  lightcolor[0] = 1.;
341  lightcolor[1] = 0.;
342  lightcolor[2] = 0.;
343  lightsize[0] = 0.1875;
344  lightsize[1] = 0.1875;
345  lightsize[2] = 0.1875;
346 
347   for(i=0;i<cir2d_nverts;i++)
348    {
349     cir2d_data2[i][0] = cir2d_data[i][0] * .4;
350     cir2d_data2[i][1] = cir2d_data[i][1] * .4;
351    }
352 
353  // init config root path
354 
355  setConfigRootPath(".");
356 
357  // init graphics objects
358 
359  envmap_detected = 0;
360  num_objects = 0;
361  max_objects = 0;
362  objects = NULL;
363 
364  num_alpha_objects = 0;
365  max_alpha_objects = 0;
366  alpha_objects = NULL;
367 
368  curr_object = NULL;
369  curr_element = NULL;
370  curr_vertex = NULL;
371 
372  // use this for small displays like notebooks etc.
373  window_xsize = 800;
374  window_ysize = 325;
375 
376  // use this for Desktops/Workstations with good graphics
377  //window_xsize = 1600;
378  //window_ysize = 650;
379 
380  cursor[0] = 0.;
381  cursor[1] = 0.;
382  cursor[2] = 0.0;
383  cursor_inc = .01;
384  do_cursor = 0;
385  do_stats = 0;
386  shift_key_pressed = 0;
387 
388 
389  // graphics view parms
390 
391  view.rot[0] = 0.;
392  view.rot[1] = 0.;
393  view.rot[2] = 0.;
394 
395  view.pan[0] = 0.;
396  view.pan[1] = -0.0;
397  view.pan[2] = -16.0;
398 
399  view.znear = 0.01;
400  view.zfar  = 1000.0;
401  view.fovy  = 25.0;
402  view.projection = LP_ORTHO;
403  view.redo_projections = 1;
404  view.do_depthtest = 0;		// default to no zbuffer
405 
406  quit_callbackfunc = NULL;
407 
408 } // end constructor
409 
410 
~Lpanel(void)411 Lpanel::~Lpanel(void)		// destructor
412 {
413    Quit();
414 
415 }
416 
417 int
test(int n)418 Lpanel::test(int n)
419 {
420 
421  printf("panel test %d\n",n);
422 
423  switch(n)
424  {
425    case 0:
426 	break;
427    case 1:
428 	break;
429    default:
430 	break;
431  }
432 
433  return 1;
434 }
435 
436 void
addQuitCallback(void (* cbfunc)(void))437 Lpanel::addQuitCallback( void (*cbfunc)(void))
438 {
439   quit_callbackfunc = cbfunc;
440 }
441 
442 void
Quit(void)443 Lpanel::Quit(void)
444 {
445  int i;
446 
447 
448  for(i=0;i<num_lights;i++)
449   if(lights[i]) delete lights[i];
450  num_lights = max_lights = 0;
451 
452 
453  for(i=0;i<num_objects;i++)
454   if(objects[i]) delete objects[i];
455  num_objects = max_objects = 0;
456 
457  for(i=0;i<num_switches;i++)
458   if(switches[i]) delete switches[i];
459  num_switches = max_switches = 0;
460 
461  for(i=0;i<LP_MAX_LIGHT_GROUPS;i++)
462  {
463    if(light_groups[i].list)
464     { delete light_groups[i].list;
465       light_groups[i].list = NULL;
466     }
467    light_groups[i].num_items = 0;
468    light_groups[i].max_items = 0;
469  }
470 
471  //destroyWindow();
472 
473 } // end destructor
474 
475 
476 int
addLight(const char * name,lp_obj_parm_t * obj,const char * buff)477 Lpanel::addLight(const char *name, lp_obj_parm_t *obj, const char *buff)
478 {
479   int i,n;
480   parser_result_t *result;
481   lpLight *light;
482 
483 
484   if(num_lights + 1 > max_lights) growLights();
485 
486   lights[num_lights] = new lpLight;
487   light = lights[num_lights];
488   lights[num_lights]->parms = obj;
489   lights[num_lights]->setName(name);
490   lights[num_lights]->bindSimclock(simclock, &clock_warp);
491   lights[num_lights]->panel = this;
492 
493   parser.setRules(light_parse_rules);
494   parser.setParseString(buff);
495 
496   // parse config file line values such has position, color etc.
497   // if n >= 0 it contains the char position in the line where an error
498   // ocurred
499 
500  while( (n = parser.parse(&result)) < 0 )
501  {
502    if(n != PARSER_DONE)
503    {
504 
505       if(!strcmp(light_parse_rules[result->cmd_idx].cmd, "color"))
506        {
507 	for(i=0;i<result->num_args;i++)
508         light->parms->color[i] =  result->floats[i];
509        }
510       else if(!strcmp(light_parse_rules[result->cmd_idx].cmd, "group"))
511        {
512         light->parms->group =  result->ints[0];
513        }
514       else if(!strcmp(light_parse_rules[result->cmd_idx].cmd, "object"))
515        {
516 	light->obj_refname = new char[strlen(result->strings[0])+1];
517         strcpy(light->obj_refname, result->strings[0]);
518        }
519       else if(!strcmp(light_parse_rules[result->cmd_idx].cmd, "pos"))
520        {
521 	for(i=0;i<result->num_args;i++)
522         light->parms->pos[i] =  result->floats[i];
523        }
524       else if(!strcmp(light_parse_rules[result->cmd_idx].cmd, "size"))
525        {
526 	for(i=0;i<result->num_args;i++)
527         light->parms->scale[i] =  result->floats[i];
528        }
529    } // end if(n != PARSER_DONE)
530 
531   if( n == PARSER_DONE) break;
532  }
533 
534   if( n >= 0)
535    { printf("n=%d\n",n);
536      parser.printError();
537      return n;
538    }
539 
540 
541   if(obj->group >=0)
542    {
543      addLightToGroup(num_lights, obj->group);
544    }
545 
546   num_lights++;
547 
548   return(-1);
549 
550 }
551 
552 int
addLightToGroup(int lightnum,int groupnum)553 Lpanel::addLightToGroup( int lightnum, int groupnum)
554 {
555 
556  if(groupnum >= LP_MAX_LIGHT_GROUPS)
557   {
558      fprintf(stderr, "error: light %s invalid group number (%d)\n", lights[lightnum]->name, groupnum);
559      return 0;
560   }
561 
562  if( light_groups[groupnum].num_items + 1 > light_groups[groupnum].max_items)
563   {
564     int *new_list,
565 	i;
566 
567     new_list = new int[light_groups[groupnum].max_items + 1];
568 
569     if(light_groups[groupnum].list)
570      { for(i=0; i < light_groups[groupnum].max_items;i++)
571 		new_list[i] = light_groups[groupnum].list[i];
572        delete light_groups[groupnum].list;
573      }
574     light_groups[groupnum].list = new_list;
575   }
576  light_groups[groupnum].max_items += 1;
577  light_groups[groupnum].list[light_groups[groupnum].num_items] = lightnum;
578  light_groups[groupnum].num_items++;
579  return 1;
580 }
581 
582 int
bindLight8(char * name,void * loc,int start_bit_number)583 Lpanel::bindLight8(char *name, void *loc, int start_bit_number)
584 {
585   char **namelist;
586   int num_names;
587   int i, status = 1;
588   int bitnum, bit_inc;
589   lpLight *light;
590 
591   num_names = xpand(name, &namelist);
592 
593   bitnum = abs(start_bit_number);
594   if(start_bit_number > 0) bit_inc = 1;
595   else bit_inc = -1;
596 
597   for(i=0;i<num_names;i++)
598    {
599      if(bitnum <=0)
600       {
601 	fprintf(stderr, "bindLight8: light %s bad bitnum %d\n", namelist[i], bitnum);
602         bitnum = 1;
603       }
604 
605      light = findLightByName(namelist[i]);
606 
607      if(light)
608       {
609         light->bindData8( (uint8 *) loc);
610         light->setBitNumber(bitnum-1);
611       }
612      else
613       {
614 	if(!ignore_bind_errors) fprintf(stderr, "bindLight8: light %s not found\n", namelist[i]);
615 	status = 0;
616       }
617     if(namelist[i]) delete namelist[i];
618     bitnum += bit_inc;
619    }
620 
621   return status;
622 }
623 
624 // bind light and invert logic according to mask
625 
626 int
bindLight8invert(char * name,void * loc,int start_bit_number,uint8 mask)627 Lpanel::bindLight8invert(char *name, void *loc, int start_bit_number, uint8 mask)
628 {
629   char **namelist;
630   int num_names;
631   int i, status = 1;
632   int bitnum, bit_inc, bit_inv;
633   lpLight *light;
634 
635   num_names = xpand(name, &namelist);
636 
637   bitnum = abs(start_bit_number);
638   if(start_bit_number > 0) bit_inc = 1;
639   else bit_inc = -1;
640 
641   for(i=0;i<num_names;i++)
642    {
643      if(bitnum <=0)
644       {
645 	fprintf(stderr, "bindLight8invert: light %s bad bitnum %d\n", namelist[i], bitnum);
646         bitnum = 1;
647       }
648 
649      light = findLightByName(namelist[i]);
650 
651      if(light)
652       {
653 	if( mask & (0x1 << (bitnum-1)))
654          light->bindData8invert( (uint8 *) loc);
655         else
656          light->bindData8( (uint8 *) loc);
657         light->setBitNumber(bitnum-1);
658       }
659      else
660       {
661 	if(!ignore_bind_errors) fprintf(stderr, "bindLight8invert: light %s not found\n", namelist[i]);
662 	status = 0;
663       }
664     if(namelist[i]) delete namelist[i];
665     bitnum += bit_inc;
666    }
667 
668   return status;
669 }
670 
671 int
bindLight16(char * name,void * loc,int start_bit_number)672 Lpanel::bindLight16(char *name, void *loc, int start_bit_number)
673 {
674   char **namelist;
675   int num_names;
676   int i, status = 1;
677   int bitnum, bit_inc;
678   lpLight *light;
679 
680   num_names = xpand(name, &namelist);
681 
682   bitnum = abs(start_bit_number);
683   if(start_bit_number > 0) bit_inc = 1;
684   else bit_inc = -1;
685 
686   for(i=0;i<num_names;i++)
687    {
688      if(bitnum <=0)
689       {
690         fprintf(stderr, "bindLight16: light %s bad bitnum %d\n", namelist[i], bitnum);
691         bitnum = 1;
692       }
693 
694      light = findLightByName(namelist[i]);
695 
696      if(light)
697       {
698         light->bindData16( (uint16 *) loc);
699         light->setBitNumber(bitnum-1);
700       }
701      else
702       {
703         if(!ignore_bind_errors) fprintf(stderr, "bindLight16: light %s not found\n", namelist[i]);
704         status = 0;
705       }
706     if(namelist[i]) delete namelist[i];
707     bitnum += bit_inc;
708    }
709 
710   return status;
711 }
712 
713 
714 // bindLightfv
715 // bind to an array of float values
716 // subsequent sampling will use the bit number as an index into the array of float values
717 // instead of a single bit
718 
719 int
bindLightfv(char * name,void * loc)720 Lpanel::bindLightfv(char *name, void *loc)
721 {
722   char **namelist;
723   int num_names;
724   int i, status = 1;
725   int bitnum, bit_inc;
726   lpLight *light;
727 
728   num_names = xpand(name, &namelist);
729 
730   for(i=0;i<num_names;i++)
731    {
732 
733      light = findLightByName(namelist[i]);
734 
735      if(light)
736       {
737         light->bindDatafv( (float *) loc);
738         light->setBitNumber(i);
739       }
740      else
741       {
742         if(!ignore_bind_errors) fprintf(stderr, "bindLightfv: light %s not found\n", namelist[i]);
743         status = 0;
744       }
745     if(namelist[i]) delete namelist[i];
746     bitnum += bit_inc;
747    }
748 
749   return status;
750 }
751 
752 int
bindLight16invert(char * name,void * loc,int start_bit_number,uint16 mask)753 Lpanel::bindLight16invert(char *name, void *loc, int start_bit_number, uint16 mask)
754 {
755   char **namelist;
756   int num_names;
757   int i, status = 1;
758   int bitnum, bit_inc, bit_inv;
759   lpLight *light;
760 
761   num_names = xpand(name, &namelist);
762 
763   bitnum = abs(start_bit_number);
764   if(start_bit_number > 0) bit_inc = 1;
765   else bit_inc = -1;
766 
767   for(i=0;i<num_names;i++)
768    {
769      if(bitnum <=0)
770       {
771 	fprintf(stderr, "bindLight16invert: light %s bad bitnum %d\n", namelist[i], bitnum);
772         bitnum = 1;
773       }
774 
775      light = findLightByName(namelist[i]);
776 
777      if(light)
778       {
779 	if( mask & (0x1 << (bitnum-1)))
780          light->bindData16invert( (uint16 *) loc);
781         else
782          light->bindData16( (uint16 *) loc);
783         light->setBitNumber(bitnum-1);
784       }
785      else
786       {
787 	if(!ignore_bind_errors) fprintf(stderr, "bindLight16invert: light %s not found\n", namelist[i]);
788 	status = 0;
789       }
790     if(namelist[i]) delete namelist[i];
791     bitnum += bit_inc;
792    }
793 
794   return status;
795 }
796 
797 
798 
799 int
bindLight32(char * name,void * loc,int start_bit_number)800 Lpanel::bindLight32(char *name, void *loc, int start_bit_number)
801 {
802   char **namelist;
803   int num_names;
804   int i, status = 1;
805   int bitnum, bit_inc;
806   lpLight *light;
807 
808   num_names = xpand(name, &namelist);
809 
810   bitnum = abs(start_bit_number);
811   if(start_bit_number > 0) bit_inc = 1;
812   else bit_inc = -1;
813 
814   for(i=0;i<num_names;i++)
815    {
816      if(bitnum <=0)
817       {
818         fprintf(stderr, "bindLight16: light %s bad bitnum %d\n", namelist[i], bitnum);
819         bitnum = 1;
820       }
821 
822      light = findLightByName(namelist[i]);
823 
824      if(light)
825       {
826         light->bindData32( (uint32 *) loc);
827         light->setBitNumber(bitnum-1);
828       }
829      else
830       {
831         if(!ignore_bind_errors) fprintf(stderr, "bindLight32: light %s not found\n", namelist[i]);
832         status = 0;
833       }
834     if(namelist[i]) delete namelist[i];
835     bitnum += bit_inc;
836    }
837 
838   return status;
839 }
840 
841 int
bindLight32invert(char * name,void * loc,int start_bit_number,uint32 mask)842 Lpanel::bindLight32invert(char *name, void *loc, int start_bit_number, uint32 mask)
843 {
844   char **namelist;
845   int num_names;
846   int i, status = 1;
847   int bitnum, bit_inc, bit_inv;
848   lpLight *light;
849 
850   num_names = xpand(name, &namelist);
851 
852   bitnum = abs(start_bit_number);
853   if(start_bit_number > 0) bit_inc = 1;
854   else bit_inc = -1;
855 
856   for(i=0;i<num_names;i++)
857    {
858      if(bitnum <=0)
859       {
860 	fprintf(stderr, "bindLight32invert: light %s bad bitnum %d\n", namelist[i], bitnum);
861         bitnum = 1;
862       }
863 
864      light = findLightByName(namelist[i]);
865 
866      if(light)
867       {
868 	if( mask & (0x1 << (bitnum-1)))
869          light->bindData32invert( (uint32 *) loc);
870         else
871          light->bindData32( (uint32 *) loc);
872         light->setBitNumber(bitnum-1);
873       }
874      else
875       {
876 	if(!ignore_bind_errors) fprintf(stderr, "bindLight32invert: light %s not found\n", namelist[i]);
877 	status = 0;
878       }
879     if(namelist[i]) delete namelist[i];
880     bitnum += bit_inc;
881    }
882 
883   return status;
884 }
885 
886 
887 int
bindLight64(char * name,void * loc,int start_bit_number)888 Lpanel::bindLight64(char *name, void *loc, int start_bit_number)
889 {
890   char **namelist;
891   int num_names;
892   int i, status = 1;
893   int bitnum, bit_inc;
894   lpLight *light;
895 
896   num_names = xpand(name, &namelist);
897 
898   bitnum = abs(start_bit_number);
899   if(start_bit_number > 0) bit_inc = 1;
900   else bit_inc = -1;
901 
902   for(i=0;i<num_names;i++)
903    {
904      if(bitnum <=0)
905       {
906         fprintf(stderr, "bindLight64: light %s bad bitnum %d\n", namelist[i], bitnum);
907         bitnum = 1;
908       }
909 
910      light = findLightByName(namelist[i]);
911 
912      if(light)
913       {
914         light->bindData64( (uint64 *) loc);
915         light->setBitNumber(bitnum-1);
916       }
917      else
918       {
919         if(!ignore_bind_errors) fprintf(stderr, "bindLight64: light %s not found\n", namelist[i]);
920         status = 0;
921       }
922     if(namelist[i]) delete namelist[i];
923     bitnum += bit_inc;
924    }
925 
926   return status;
927 }
928 
929 int
bindLight64invert(char * name,void * loc,int start_bit_number,uint64 mask)930 Lpanel::bindLight64invert(char *name, void *loc, int start_bit_number, uint64 mask)
931 {
932   char **namelist;
933   int num_names;
934   int i, status = 1;
935   int bitnum, bit_inc, bit_inv;
936   lpLight *light;
937 
938   num_names = xpand(name, &namelist);
939 
940   bitnum = abs(start_bit_number);
941   if(start_bit_number > 0) bit_inc = 1;
942   else bit_inc = -1;
943 
944   for(i=0;i<num_names;i++)
945    {
946      if(bitnum <=0)
947       {
948 	fprintf(stderr, "bindLight64invert: light %s bad bitnum %d\n", namelist[i], bitnum);
949         bitnum = 1;
950       }
951 
952      light = findLightByName(namelist[i]);
953 
954      if(light)
955       {
956 	if( mask & (0x1 << (bitnum-1)))
957          light->bindData64invert( (uint64 *) loc);
958         else
959          light->bindData64( (uint64 *) loc);
960         light->setBitNumber(bitnum-1);
961       }
962      else
963       {
964 	if(!ignore_bind_errors) fprintf(stderr, "bindLight64invert: light %s not found\n", namelist[i]);
965 	status = 0;
966       }
967     if(namelist[i]) delete namelist[i];
968     bitnum += bit_inc;
969    }
970 
971   return status;
972 }
973 
974 void
bindRunFlag(uint8 * addr)975 Lpanel::bindRunFlag(uint8 *addr)
976 {
977  int i;
978 
979  runflag = (uint8 *) addr;
980 
981   for(i=0;i<num_lights;i++)
982    lights[i]->bindRunFlag((uint8 *)addr);
983 }
984 
985 void
bindSimclock(uint64 * addr)986 Lpanel::bindSimclock(uint64 *addr)
987 {
988  int i;
989  simclock = (uint64 *) addr;
990 
991  for(i=0;i<num_lights;i++)
992    lights[i]->bindSimclock((uint64 *) addr, &clock_warp);
993 
994 }
995 
996 
997 void
draw(void)998 Lpanel::draw(void)
999 { int i;
1000 
1001  if(view.redo_projections)
1002   {
1003    setProjection(0);
1004    setModelview(0);
1005    view.redo_projections = 0;
1006   }
1007  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
1008 
1009  // draw graphics objects
1010 
1011  //glEnable(GL_LIGHTING);
1012 
1013  for(i=0;i<num_objects;i++)
1014   {
1015     if(objects[i]->is_alpha) continue;
1016 
1017     if(objects[i]->texture_num)
1018      {
1019 	textures.bindTexture(objects[i]->texture_num);
1020      }
1021     if(objects[i]->have_normals) glEnable(GL_LIGHTING);
1022     objects[i]->draw();
1023   }
1024 
1025  // draw lights
1026 
1027  glDisable(GL_TEXTURE_2D);
1028  glDisable(GL_LIGHTING);
1029  glEnable(GL_POLYGON_OFFSET_FILL);
1030  glPolygonOffset(0.,-10.);
1031 
1032  for(i=0;i<num_lights;i++)
1033    lights[i]->draw();
1034 
1035  // draw switches
1036 
1037  for(i=0;i<num_switches;i++)
1038     switches[i]->drawFunc(this, switches[i]);
1039 
1040  if(alpha_objects)
1041  {
1042 //  glDisable(GL_DEPTH_TEST);
1043    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
1044  glEnable(GL_BLEND);
1045 
1046   for(i=0;i<num_alpha_objects;i++)
1047   {
1048     if(alpha_objects[i]->texture_num)
1049      {
1050 	textures.bindTexture(alpha_objects[i]->texture_num);
1051      }
1052     if(alpha_objects[i]->have_normals) glEnable(GL_LIGHTING);
1053     alpha_objects[i]->draw();
1054   }
1055  // glEnable(GL_DEPTH_TEST);
1056  }
1057 
1058  glDisable(GL_TEXTURE_2D);
1059  glDisable(GL_POLYGON_OFFSET_FILL);
1060  glEnable(GL_POLYGON_OFFSET_LINE);
1061  if(do_cursor)
1062   {
1063    glEnable(GL_POLYGON_OFFSET_LINE);
1064    draw_cursor();
1065    glDisable(GL_POLYGON_OFFSET_LINE);
1066   }
1067  if(do_stats) draw_stats();
1068 #if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__)
1069  SwapBuffers(hDC);
1070  //UpdateWindow(hWnd);
1071 #else
1072  glXSwapBuffers(dpy, window);
1073 #endif
1074 }
1075 
1076 
1077 void
growLights(void)1078 Lpanel::growLights(void)
1079 {
1080   int i;
1081   lpLight **new_lights;
1082 
1083   new_lights = new lpLight * [num_lights + 8];
1084   for(i=0;i<num_lights;i++)
1085     new_lights[i] = lights[i];
1086 
1087   max_lights += 8;
1088   delete lights;
1089   lights = new_lights;
1090 }
1091 
1092 void
growSwitches(void)1093 Lpanel::growSwitches(void)
1094 {
1095   int i;
1096   lpSwitch **new_switches;
1097 
1098   new_switches = new lpSwitch* [num_switches + 1];
1099   for(i=0;i<num_switches;i++)
1100     new_switches[i] = switches[i];
1101 
1102   max_switches += 1;
1103   delete switches;
1104   switches = new_switches;
1105 }
1106 
1107 int
pick(int button,int state,int x,int y)1108 Lpanel::pick(int button, int state, int x, int y)
1109 {
1110  GLuint namebuf[500], *ptr;
1111  int i,
1112      num_picked = 0,
1113      switch_dir;
1114  uint32 switch_num;
1115 
1116  if(state == 0)
1117   {
1118     if( mom_switch_pressed )
1119        mom_switch_pressed->action(2);
1120     return(num_picked);
1121   }
1122 
1123 
1124  namebuf[0]=0;
1125  glSelectBuffer(500,&namebuf[0]);
1126  glRenderMode(GL_SELECT);
1127  glInitNames();
1128  glPushName(0);
1129  glGetIntegerv (GL_VIEWPORT, viewport);
1130  glMatrixMode (GL_PROJECTION);
1131  glPushMatrix ();
1132  glLoadIdentity ();
1133 
1134  gluPickMatrix ((GLdouble) x, (GLdouble) (window_ysize - y), 1.0, 1.0, viewport);
1135  doPickProjection();
1136  glMatrixMode (GL_MODELVIEW);
1137  glPushMatrix();
1138  doPickModelview();
1139 
1140  // draw switches
1141 
1142  for(i=0;i<num_switches;i++)
1143     switches[i]->drawForPick();
1144 
1145  num_picked = glRenderMode(GL_RENDER);
1146 
1147  if( num_picked)
1148   {
1149    uint32 n;
1150    ptr = (GLuint *) namebuf;
1151    n = ptr[3];
1152 
1153    switch_num = n & LP_SW_PICK_IDMASK;		// decode the switch number
1154    switch_dir = ((n & LP_SW_PICK_UP_BIT) != 0);
1155 //printf("pick: switch_num=%d dir=%d\n", switch_num, switch_dir);
1156 
1157    switches[switch_num]->action(switch_dir);
1158   }
1159 
1160  glPopMatrix();
1161  glMatrixMode (GL_PROJECTION);
1162  glPopMatrix();
1163  glMatrixMode (GL_MODELVIEW);
1164  glPopMatrix();
1165  glRenderMode(GL_RENDER);
1166 
1167  return(num_picked);
1168 
1169 }
1170 
1171 
1172 int
readConfig(const char * _fname)1173 Lpanel::readConfig(const char *_fname)
1174 {
1175  FILE *fd;
1176  int i,n;
1177 
1178 #define BUFSIZE 256
1179 #define TOKENSIZE 80
1180 
1181  char buffer[BUFSIZE], token[TOKENSIZE];
1182  int pos, lineno=0, bailout=0;
1183  lp_obj_parm_t *obj;
1184 
1185  char *fname;
1186 
1187  fname = new char[strlen(config_root_path) + strlen(_fname) + 1];
1188  strcpy(fname, config_root_path);
1189  strcat(fname, "/");
1190  strcat(fname, _fname);
1191 
1192  if( (fd=fopen(fname,"r")) == 0)
1193   {
1194     fprintf(stderr,"readFile: could not open file %s\n",fname);
1195     return 0;
1196   }
1197 
1198  lp_init_materials();
1199 
1200  while(!feof(fd) && !bailout)
1201  {
1202   lineno++;
1203   if(!freadlin(fd,buffer,BUFSIZE)) continue;
1204   pos = 0;
1205   if(!gtoken(buffer,token,TOKENSIZE,&pos)) continue;   // blank line
1206   if(token[0] == '#') continue;                        // comment
1207 
1208   if(!strcmp(token, "color"))		// color
1209    {  int n;
1210 
1211       if(!curr_object)
1212        { printf("Error on line %d of config file %s\n",lineno, fname);
1213          printf("color defined outside of an object\n");
1214 	 bailout = 1;
1215        }
1216       else
1217        {
1218 	 n = sscanf(&buffer[pos],"%f %f %f",
1219 	    &curr_object->color[0],
1220 	    &curr_object->color[1],
1221 	    &curr_object->color[2]);
1222 
1223 	if(n < 3)
1224          { printf("Error on line %d of config file %s\n",lineno, fname);
1225            printf("color must have 3 (r g b) values in the range of 0.0 - 1.0.\n");
1226 	   bailout = 1;
1227 	 }
1228 
1229        }
1230    }
1231   else if(!strcmp(token, "zbuffer"))
1232    {
1233      view.do_depthtest = 1;
1234    }
1235   else
1236   if(!strcmp(token, "envmap"))		// environment mapped reflection
1237    {
1238       if(!curr_object)
1239 	{ printf("Error on line %d of config file %s\n",lineno, fname);
1240           printf("envmap defined outside of an object\n");
1241 	  bailout = 1;
1242 	}
1243 	else
1244 	{
1245 	 envmap_detected = 1;
1246 	 curr_object->envmapped = 1;
1247 	}
1248    }
1249   else if(!strcmp(token, "instance"))
1250    {
1251      char s[100];
1252 
1253       if(!curr_object)
1254 	{ printf("Error on line %d of config file %s\n",lineno, fname);
1255           printf("instance defined outside of an object\n");
1256 	  bailout = 1;
1257 	}
1258       else
1259 	{
1260   	  if(!gtoken(buffer,s,100,&pos))
1261 	   { printf("Error on line %d of config file %s\n",lineno, fname);
1262              printf("instance with no object name.\n");
1263 	     bailout = 1;
1264 	   }
1265 	  else
1266 	    curr_object->setInstanceName(s);
1267 	}
1268    }
1269   else if(!strcmp(token, "light"))
1270    {
1271       obj = new lp_obj_parm_t;
1272       obj->type = LP_LED;
1273       obj->subtype = LP_LED_3D;
1274       obj->group = -1;		// does not belong to group
1275       obj->pos[0] = 0.;
1276       obj->pos[1] = 0.;
1277       obj->pos[2] = 0.;
1278       obj->color[0] = lightcolor[0];
1279       obj->color[1] = lightcolor[1];
1280       obj->color[2] = lightcolor[2];
1281       obj->scale[0] = lightsize[0];
1282       obj->scale[1] = lightsize[1];
1283       obj->scale[2] = lightsize[2];
1284 
1285       gtoken(buffer,token,TOKENSIZE,&pos);		// get name
1286 
1287       n = addLight(token, obj, &buffer[pos]);
1288       if(n >= 0)
1289        { bailout = 1;
1290 	 n += pos;
1291   	 printf("Error on line %d of config file %s\n",lineno, fname);
1292 
1293   	 printf("%s\n",buffer);
1294 	 for(i=0;i<n;i++)
1295 	   putchar(' ');
1296 	 printf("^\n");
1297        }
1298 
1299    }
1300   else if(!strcmp(token, "lightcolor"))           // default light size
1301    {  int n;
1302 
1303          n = sscanf(&buffer[pos],"%f %f %f",
1304             &lightcolor[0],
1305             &lightcolor[1],
1306             &lightcolor[2]);
1307 
1308 	if(n < 3)
1309          { printf("Error on line %d of config file %s\n",lineno, fname);
1310            printf("lightcolor must have 3 (r g b) values in the range of 0.0 - 1.0.\n");
1311 	   bailout = 1;
1312 	 }
1313 
1314    }
1315   else if(!strcmp(token, "lightsize"))           // default light size
1316    {  int n;
1317 
1318          n = sscanf(&buffer[pos],"%f %f %f",
1319             &lightsize[0],
1320             &lightsize[1],
1321             &lightsize[2]);
1322 
1323         if(n < 1)
1324          { printf("Error on line %d of config file %s\n",lineno, fname);
1325            printf("lightsize must have 1, 2, or 3 values (x y z).\n");
1326            bailout = 1;
1327          }
1328 
1329 	if(n == 1)  lightsize[1] = lightsize[2] = lightsize[0];
1330 	else if(n == 2)  lightsize[2] = lightsize[0];
1331 
1332    }
1333   else if(!strcmp(token, "line"))
1334    {
1335       if(!curr_object)
1336        { printf("Error on line %d of config file %s\n",lineno, fname);
1337          printf("line defined outside of an object\n");
1338 	 bailout = 1;
1339        }
1340       else
1341        {
1342 	if(!(curr_element = curr_object->addElement(curr_object)))
1343          { printf("could not allocate memory for line.\n");
1344 	   bailout = 1;
1345 	 }
1346         else
1347 	 { curr_element->type = LP_LINE;
1348            curr_element->setTextureManager(&textures);
1349   	 }
1350        }
1351    }
1352   else if(!strcmp(token, "material"))           // material reference or definition
1353    {  int n, matnum;
1354       float Ar, Ag, Ab, Aa,   // Ambient rgba
1355 	    Dr,  Dg, Db, Da,  // Diffuse rgba
1356 	    Sr, Sg, Sb, Sa,   // Specular rgba
1357 	    shine,            // shinyness
1358 	    Er, Eg, Eb, Ea;   // emission rgba
1359 
1360 	if(curr_object)		// material reference
1361 	{
1362          n = sscanf(&buffer[pos],"%d",&curr_object->material);
1363 
1364          if(n != 1)
1365          { printf("Error on line %d of config file %s\n",lineno, fname);
1366            printf("material within an object definition must have one integer value.\n");
1367            bailout = 1;
1368          }
1369 	 curr_object->is_alpha = lp_is_material_alpha(curr_object->material);
1370 	}
1371 	else		// material definition
1372 	{
1373 
1374          n = sscanf(&buffer[pos],"%d %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f",
1375 	    &matnum, &Ar,&Ag,&Ab,&Aa, &Dr,&Dg,&Db,&Da, &Sr,&Sg,&Sb,&Sa, &shine, &Er,&Eg,&Eb,&Ea);
1376 
1377         if(n < 18)
1378          { printf("Error on line %d of config file %s\n",lineno, fname);
1379            printf("material definition must have 18 values.\n");
1380            bailout = 1;
1381          }
1382 	else
1383           lp_set_material_params(matnum, Ar,Ag,Ab,Aa, Dr,Dg,Db,Da, Sr,Sg,Sb,Sa, shine, Er,Eg,Eb,Ea);
1384 
1385 	}
1386    }
1387   else if(!strcmp(token, "message"))		// message
1388    {
1389 	printf("%s\n", &buffer[pos]);
1390    }
1391   else if(!strcmp(token, "n"))		// vertex normal vector
1392    {  int n;
1393 
1394       if(!curr_element || !curr_object)
1395        { printf("Error on line %d of config file %s\n",lineno, fname);
1396          printf("normal defined outside of a polygon or line\n");
1397 	 bailout = 1;
1398        }
1399       else
1400        {
1401 	if(!curr_vertex)
1402          { printf("Error on line %d of config file %s\n",lineno, fname);
1403            printf("normal defined before a vertex definition\n");
1404 	   bailout = 1;
1405 	 }
1406 
1407 	 n = sscanf(&buffer[pos],"%f %f %f",
1408 	    &curr_vertex->norm[0],
1409 	    &curr_vertex->norm[1],
1410 	    &curr_vertex->norm[2]);
1411 
1412 	if(n < 3)
1413          { printf("Error on line %d of config file %s\n",lineno, fname);
1414            printf("normal must have 3 values.\n");
1415 	   bailout = 1;
1416 	 }
1417 	else
1418 	 curr_object->have_normals = 1;
1419        }
1420    }
1421   else if(!strcmp(token, "object"))
1422    {
1423      curr_object = addObject();
1424      curr_object->setTextureManager(&textures);
1425      if( gtoken(buffer,token,TOKENSIZE,&pos))
1426 	curr_object->setName(token);
1427      curr_element = NULL;
1428      curr_vertex = NULL;
1429    }
1430   else if(!strcmp(token, "perspective"))
1431    {
1432      view.projection = LP_PERSPECTIVE;
1433    }
1434   else if(!strcmp(token, "polygon"))
1435    {
1436       if(!curr_object)
1437        { printf("Error on line %d of config file %s\n",lineno, fname);
1438          printf("polygon defined outside of an object\n");
1439 	 bailout = 1;
1440        }
1441       else
1442        {
1443 	if(!(curr_element = curr_object->addElement(curr_object)))
1444          { printf("could not allocate memory for polygon.\n");
1445 	   bailout = 1;
1446 	 }
1447         else
1448 	 { curr_element->type = LP_POLYGON;
1449            curr_element->setTextureManager(&textures);
1450   	 }
1451        }
1452    }
1453   else if(!strcmp(token, "referenced"))		// referenced
1454    {
1455       if(!curr_object)
1456        { printf("Error on line %d of config file %s\n",lineno, fname);
1457          printf("color defined outside of an object\n");
1458 	 bailout = 1;
1459        }
1460       else
1461 	curr_object->referenced = 1;
1462    }
1463   else if(!strcmp(token, "rotate"))		// rotate hpr
1464    {  int n;
1465 
1466       if(!curr_object)
1467        {
1468 	 n = sscanf(&buffer[pos],"%f %f",
1469 	    &view.rot[0],
1470 	    &view.rot[1]);
1471 
1472 	if(n < 2)
1473          { printf("Error on line %d of config file %s\n",lineno, fname);
1474            printf("scene rotate must have 2 values.\n");
1475 	   bailout = 1;
1476 	 }
1477 
1478        }
1479       else
1480        {
1481 	 n = sscanf(&buffer[pos],"%f %f %f",
1482 	    &curr_object->rotate[0],
1483 	    &curr_object->rotate[1],
1484 	    &curr_object->rotate[2]);
1485 
1486 	if(n < 3)
1487          { printf("Error on line %d of config file %s\n",lineno, fname);
1488            printf("object rotate must have 3 values.\n");
1489 	   bailout = 1;
1490 	 }
1491        }
1492    }
1493   else if(!strcmp(token, "switch"))
1494    {
1495       obj = new lp_obj_parm_t;
1496       obj->group = -1;		// does not belong to group
1497       obj->pos[0] = 0.;
1498       obj->pos[1] = 0.;
1499       obj->pos[2] = 0.;
1500       obj->color[0] = 1.;
1501       obj->color[1] = 0.;
1502       obj->color[2] = 0.;
1503       obj->scale[0] = 0.1875;
1504       obj->scale[1] = 0.1875;
1505       obj->scale[2] = 0.1875;
1506 
1507       gtoken(buffer,token,TOKENSIZE,&pos);		// get name
1508 
1509       n = addSwitch(token, obj, &buffer[pos], this);
1510       if(n >= 0)
1511        { bailout = 1;
1512 	 n += pos;
1513   	 printf("Error on line %d of config file %s\n",lineno, fname);
1514 
1515   	 printf("%s\n",buffer);
1516 	 for(i=0;i<n;i++)
1517 	   putchar(' ');
1518 	 printf("^\n");
1519        }
1520 
1521    }
1522   else if(!strcmp(token, "t"))		// texture coordinate
1523    {  int n;
1524 
1525       if(!curr_element || !curr_object)
1526        { printf("Error on line %d of config file %s\n",lineno, fname);
1527          printf("texture coord defined outside of a polygon or line\n");
1528 	 bailout = 1;
1529 	 break;
1530        }
1531       else
1532        {
1533 	if(!curr_vertex)
1534          { printf("Error on line %d of config file %s\n",lineno, fname);
1535            printf("texture coord defined before a vertex coordinate was defined.\n");
1536 	   bailout = 1;
1537 	   break;
1538          }
1539 
1540 	 n = sscanf(&buffer[pos],"%f %f",
1541 	    &curr_vertex->st[0],
1542 	    &curr_vertex->st[1]);
1543 
1544 	if(n < 2)
1545          { printf("Error on line %d of config file %s\n",lineno, fname);
1546            printf("texture coordinate must have 2 coordinates (e.g. t <s> <t>).\n");
1547 	   bailout = 1;
1548 	   break;
1549 	 }
1550 	 curr_element->have_tcoords = 1;
1551        }
1552    }
1553   else if(!strcmp(token, "texture"))		// texture
1554    {
1555       char *texture_path = NULL;
1556       int len;
1557 
1558       if(!curr_object)
1559        { printf("Error on line %d of config file %s\n",lineno, fname);
1560          printf("texture defined outside of an object.\n");
1561 	 bailout = 1;
1562 	 break;
1563        }
1564 
1565      if(!gtoken(buffer,token,TOKENSIZE,&pos))
1566        { printf("Error on line %d of config file %s\n",lineno, fname);
1567          printf("texture with no path to jpeg file defined.\n");
1568 	 bailout = 1;
1569 	 break;
1570        }
1571 
1572      len = strlen(config_root_path) + strlen(token) + 1;
1573 
1574      texture_path = new char[len+1];
1575      strcpy(texture_path, config_root_path);
1576      strcat(texture_path, "/");
1577      strcat(texture_path, token);
1578      texture_path[len] = 0;
1579 
1580 
1581      if( !(curr_object->texture_num = textures.addTexture(texture_path)))
1582        { printf("Error on line %d of config file %s\n",lineno, texture_path);
1583          printf("could not load texture '%s'.\n", texture_path);
1584 	 bailout = 1;
1585 	 break;
1586        }
1587 
1588      delete texture_path;
1589 
1590    }
1591   else if(!strcmp(token, "texture_scale"))
1592    {  int n;
1593 
1594       if(!curr_object)
1595        { printf("Error on line %d of config file %s\n",lineno, fname);
1596          printf("texture_scale defined outside of an object\n");
1597 	 bailout = 1;
1598        }
1599       else
1600        {
1601 	 n = sscanf(&buffer[pos],"%f %f",
1602 	    &curr_object->texture_scale[0],
1603 	    &curr_object->texture_scale[1]);
1604 
1605 	if(n < 2)
1606          { printf("Error on line %d of config file %s\n",lineno, fname);
1607            printf("texture_scale must have 2 (x y) values.\n");
1608 	   bailout = 1;
1609 	 }
1610 
1611        }
1612    }
1613   else if(!strcmp(token, "texture_translate"))
1614    {  int n;
1615 
1616       if(!curr_object)
1617        { printf("Error on line %d of config file %s\n",lineno, fname);
1618          printf("texture_translate defined outside of an object\n");
1619 	 bailout = 1;
1620        }
1621       else
1622        {
1623 	 n = sscanf(&buffer[pos],"%f %f",
1624 	    &curr_object->texture_translate[0],
1625 	    &curr_object->texture_translate[1]);
1626 
1627 	if(n < 2)
1628          { printf("Error on line %d of config file %s\n",lineno, fname);
1629            printf("texture_translate must have 2 (x y) values.\n");
1630 	   bailout = 1;
1631 	 }
1632 
1633        }
1634    }
1635   else if(!strcmp(token, "translate"))
1636    {  int n;
1637 
1638       if(!curr_object)
1639        {
1640 	 n = sscanf(&buffer[pos],"%f %f %f",
1641 	    &view.pan[0],
1642 	    &view.pan[1],
1643 	    &view.pan[2]);
1644 
1645 	if(n < 3)
1646          { printf("Error on line %d of config file %s\n",lineno, fname);
1647            printf("scene translate must have 3 values.\n");
1648 	   bailout = 1;
1649 	 }
1650 
1651        }
1652    }
1653   else if(!strcmp(token, "tristrip"))
1654    {
1655       if(!curr_object)
1656        { printf("Error on line %d of config file %s\n",lineno, fname);
1657          printf("tristrip defined outside of an object\n");
1658 	 bailout = 1;
1659        }
1660       else
1661        {
1662 	if(!(curr_element = curr_object->addElement(curr_object)))
1663          { printf("could not allocate memory for tristrip.\n");
1664 	   bailout = 1;
1665 	 }
1666         else
1667 	 { curr_element->type = LP_TRISTRIP;
1668            curr_element->setTextureManager(&textures);
1669   	 }
1670        }
1671    }
1672   else if(!strcmp(token, "v"))		// vertex
1673    {  int n;
1674 
1675       if(!curr_element || !curr_object)
1676        { printf("Error on line %d of config file %s\n",lineno, fname);
1677          printf("vertex defined outside of a polygon or line\n");
1678 	 bailout = 1;
1679        }
1680       else
1681        {
1682 	if(!(curr_vertex = curr_element->addVertex()))
1683          { printf("could not allocate memory for vertex.\n");
1684 	   bailout = 1;
1685 	 }
1686 
1687 	 n = sscanf(&buffer[pos],"%f %f %f",
1688 	    &curr_vertex->xyz[0],
1689 	    &curr_vertex->xyz[1],
1690 	    &curr_vertex->xyz[2]);
1691 
1692 	if(n < 2)
1693          { printf("Error on line %d of config file %s\n",lineno, fname);
1694            printf("vertex must have 2 or 3 coordinates.\n");
1695 	   bailout = 1;
1696 	 }
1697 
1698        }
1699    }
1700   else
1701    {
1702      printf("Error: unknown statement on line %d of config file %s\n",lineno, fname);
1703      bailout = 1;
1704 
1705    }
1706  } // end while(!feof)
1707 
1708  delete fname;
1709  fclose(fd);
1710 
1711  if(!bailout)
1712   {
1713     genGraphicsData();
1714     resolveObjectInstances();
1715 
1716     for(i=0;i<num_lights;i++)
1717       lights[i]->setupData();
1718 
1719     for(i=0;i<num_switches;i++)
1720       switches[i]->setupData(i);
1721   }
1722  return(!bailout);
1723 } // end readConfig()
1724 
1725 lpLight *
findLightByName(char * name)1726 Lpanel::findLightByName(char *name)
1727 { int i;
1728 
1729  for(i=0;i<num_lights;i++)
1730   { if( !strcmp(lights[i]->name, name))
1731       return lights[i];
1732   }
1733 
1734 return 0;
1735 }
1736 
1737 // parse var=v,v,v
1738 
1739  enum parse_states { GET_VAR, GET_VAL };
1740 
1741 
1742 
1743 void
printLights(void)1744 Lpanel::printLights(void)
1745 { int i;
1746 
1747  printf("lights:\n");
1748  for(i=0;i<num_lights;i++)
1749    lights[i]->print();
1750 
1751 }
1752 
1753 void
resolveObjectInstances(void)1754 Lpanel::resolveObjectInstances(void)
1755 {
1756  int i,j;
1757  lpObject *p;
1758 
1759  for(i=0;i<num_objects;i++)
1760   {
1761    if(objects[i]->instance_name)
1762     { if( (p = findObjectByName(objects[i]->instance_name)))
1763 	objects[i]->instance_object = p;
1764       else
1765 	fprintf(stderr,"Error: object %s instances object %s which cannot be found.\n",
1766 		objects[i]->name, objects[i]->instance_name);
1767     }
1768   }
1769 
1770  for(i=0;i<num_objects;i++)
1771   {
1772     p = objects[i]->instance_object;
1773     while(p)
1774     {
1775       for(j=0;j<3;j++)
1776 	{
1777  	   objects[i]->bbox.xyz_min[j] = min(objects[i]->bbox.xyz_min[j], p->bbox.xyz_min[j]);
1778            objects[i]->bbox.xyz_max[j] = max(objects[i]->bbox.xyz_max[j], p->bbox.xyz_max[j]);
1779 	}
1780       p = p->instance_object;
1781     }
1782 
1783   }
1784 }
1785 
1786 void
sampleData(void)1787 Lpanel::sampleData(void)
1788 { int i;
1789 
1790  // mutex lock
1791  pthread_mutex_lock(&data_sample_lock);
1792 
1793 if( *simclock < old_clock )
1794 {
1795   fprintf(stderr,"libfrontpanel: Warning clock went backwards (current=%lld  previous=%lld.\n", *simclock, old_clock);
1796 
1797 }
1798  old_clock = *simclock;
1799 
1800  for(i=0;i<num_lights;i++)
1801    lights[i]->sampleData();
1802  // mutex unlock
1803 pthread_mutex_unlock(&data_sample_lock);
1804 
1805 }
1806 
1807 void
sampleDataWarp(int clockwarp)1808 Lpanel::sampleDataWarp(int clockwarp)
1809 { int i;
1810 
1811  clock_warp = clockwarp;
1812 
1813  for(i=0;i<num_lights;i++)
1814    lights[i]->sampleData();
1815 
1816  clock_warp = 0;
1817 }
1818 
1819 void
sampleLightGroup(int groupnum,int clockval)1820 Lpanel::sampleLightGroup(int groupnum, int clockval)
1821 { int i;
1822 
1823  if(groupnum < 0 || groupnum >= LP_MAX_LIGHT_GROUPS)
1824   {
1825     fprintf(stderr, "sampleLightGroup: groupnum (%d) must be in the range of (0-%d). \n",
1826       groupnum, LP_MAX_LIGHT_GROUPS-1);
1827   }
1828 
1829  clock_warp = clockval;
1830 
1831  for(i=0;i<light_groups[groupnum].num_items;i++)
1832      lights[ light_groups[groupnum].list[i] ]->sampleData();
1833 
1834  clock_warp = 0;
1835 }
1836 
1837 void
setConfigRootPath(const char * path)1838 Lpanel::setConfigRootPath(const char *path)
1839 {
1840  if(config_root_path) delete config_root_path;
1841  config_root_path = new char [strlen(path) + 1];
1842  strcpy(config_root_path,path);
1843 
1844 }
1845 
1846 // -------------
1847 // lpLight class
1848 // -------------
1849 
lpLight(void)1850 lpLight::lpLight(void)
1851 {
1852   bindtype = LBINDTYPE_BIT;	// default to bind to bit
1853   parms = NULL;
1854   name  = NULL;
1855   obj_refname  = NULL;
1856   obj_ref = NULL;
1857   sampleDataFunc = sampleData8_error;
1858   drawFunc = drawLightGraphics;
1859   t1 = t2 = on_time = 1;
1860   old_clock = 0;
1861   dirty = 0;
1862   state = 0;
1863   old_state = 0;
1864   intensity = 1.;
1865 
1866   smoothing = 0;		// no intensity smoothing for bindtype of FLOATV
1867   intense_curr_idx = 0;
1868   intense_samples[0] = 0.;
1869   intense_samples[1] = 0.;
1870   color[0] = 0.2;
1871   color[1] = 0.;
1872   color[2] = 0.;
1873   default_runflag = 0;
1874   runflag = &default_runflag;
1875 }
1876 
~lpLight(void)1877 lpLight::~lpLight(void)
1878 {
1879  if(name) delete name;
1880  if(obj_refname) delete obj_refname;
1881  if(parms) delete parms;
1882 }
1883 
1884 void
bindRunFlag(uint8 * addr)1885 lpLight::bindRunFlag(uint8 *addr)
1886 {
1887  runflag = (uint8 *) addr;
1888 }
1889 
1890 void
bindSimclock(uint64 * addr,int * clockwarp)1891 lpLight::bindSimclock(uint64 *addr, int *clockwarp)
1892 {
1893 
1894  simclock = addr;
1895  clock_warp = clockwarp;
1896 }
1897 
1898 
1899 void
draw(void)1900 lpLight::draw(void)
1901 {
1902   int i;
1903   float *fp;
1904 
1905  switch(bindtype)
1906  {
1907 
1908   case LBINDTYPE_BIT:
1909 
1910 	if(*runflag)
1911 	 { if(dirty) calcIntensity();
1912          }
1913 	else
1914 	 {
1915     	   for(i=0;i<3;i++)
1916       	   { color[i] = parms->color[i] * (float) state + (parms->color[i] * .2);
1917              color[i] =  min(color[i],1.0);
1918            }
1919          }
1920 	break;
1921 
1922   case LBINDTYPE_FLOATV:
1923 
1924 	fp = (float *) dataptr;
1925 
1926 	//intensity = fp[bitnum];
1927 
1928 	//if(intensity > 1.0) intensity = 1.0;
1929 
1930 	if(smoothing)
1931 	{ intense_curr += intense_incr;
1932 	  if(intense_curr > 1.0) intense_curr = 1.0;
1933 	  else if(intense_curr < 0.0) intense_curr = 0.0;
1934 	  intensity = intense_curr;
1935 	}
1936 
1937 	for(i=0;i<3;i++)
1938       	   { color[i] = parms->color[i] * intensity + (parms->color[i] * .2);
1939              color[i] =  min(color[i],1.0);
1940            }
1941 //printf("xyzzy: intense=%f bitnum=%d\n",intensity, bitnum);
1942 	break;
1943 
1944  }
1945 
1946 #if DEBUG
1947 #if 0
1948  if(!strcmp(name,"LED_ADDR_00") ||
1949     !strcmp(name,"LED_ADDR_01") ||
1950     !strcmp(name,"LED_ADDR_10") )
1951 #endif
1952 
1953 
1954  if(!strcmp(name,"LED_ADDR_15"))
1955   {
1956     fprintf(stderr, "draw: %s %f\n",name, intensity);
1957   }
1958 #endif
1959 
1960   glPushMatrix();
1961   glTranslatef(parms->pos[0], parms->pos[1], parms->pos[2]);
1962   glScalef(parms->scale[0], parms->scale[1], parms->scale[2]);
1963 
1964 
1965  glColor3fv(&color[0]);
1966 
1967  (*drawFunc)(this);
1968 
1969  glPopMatrix();
1970 }
1971 
1972 void
print(void)1973 lpLight::print(void)
1974 {
1975   printf("light: name=%s\n", name);
1976 
1977  printf("obj: pos=%f %f %f  size=%f %f %f  color=%f %f %f\n",
1978    parms->pos[0],
1979    parms->pos[1],
1980    parms->pos[2],
1981    parms->scale[0],
1982    parms->scale[1],
1983    parms->scale[2],
1984    parms->color[0],
1985    parms->color[1],
1986    parms->color[2]);
1987 }
1988 
1989 void
bindData8(uint8 * ptr)1990 lpLight::bindData8(uint8 *ptr)
1991 {
1992   sampleDataFunc = sampleData8;
1993   dataptr = (uint8*) ptr;
1994 }
1995 void
bindData8invert(uint8 * ptr)1996 lpLight::bindData8invert(uint8 *ptr)
1997 {
1998   sampleDataFunc = sampleData8invert;
1999   dataptr = (uint8*) ptr;
2000 }
2001 
2002 void
bindData16(uint16 * ptr)2003 lpLight::bindData16(uint16 *ptr)
2004 {
2005 // xyzzy
2006   sampleDataFunc = sampleData16;
2007   dataptr = (uint16*) ptr;
2008 }
2009 
2010 void
bindDatafv(float * ptr)2011 lpLight::bindDatafv(float *ptr)
2012 {
2013   sampleDataFunc = sampleDatafv;
2014   dataptr = (float *) ptr;
2015   bindtype = LBINDTYPE_FLOATV;
2016 }
2017 
2018 void
bindData16invert(uint16 * ptr)2019 lpLight::bindData16invert(uint16 *ptr)
2020 {
2021   sampleDataFunc = sampleData16invert;
2022   dataptr = (uint16*) ptr;
2023 }
2024 
2025 void
bindData32(uint32 * ptr)2026 lpLight::bindData32(uint32 *ptr)
2027 {
2028   sampleDataFunc = sampleData32;
2029   dataptr = (uint32*) ptr;
2030 }
2031 
2032 void
bindData32invert(uint32 * ptr)2033 lpLight::bindData32invert(uint32 *ptr)
2034 {
2035   sampleDataFunc = sampleData32invert;
2036   dataptr = (uint32*) ptr;
2037 }
2038 
2039 void
bindData64(uint64 * ptr)2040 lpLight::bindData64(uint64 *ptr)
2041 {
2042   sampleDataFunc = sampleData64;
2043   dataptr = (uint64*) ptr;
2044 }
2045 
2046 void
bindData64invert(uint64 * ptr)2047 lpLight::bindData64invert(uint64 *ptr)
2048 {
2049   sampleDataFunc = sampleData64invert;
2050   dataptr = (uint64*) ptr;
2051 }
2052 
2053 
2054 void
calcIntensity(void)2055 lpLight::calcIntensity(void)
2056 {
2057   int i;
2058   unsigned int dt;
2059   uint64 clock_delta;
2060 
2061   int logit = 0;
2062 
2063   clock_delta = old_clock - start_clock;
2064   if(clock_delta == 0)
2065   {// intensity = 0.;
2066    return;
2067   }
2068   else
2069    intensity = (float) ((double) on_time / (double) (clock_delta) * 2.0);
2070   if(intensity > 1.0) intensity = 1.0;
2071 
2072 #if 0
2073 //printf("calcIntensity runflag = %d\n",*runflag);
2074  if(*runflag)
2075   //if(!strcmp(name,"LED_ADDR_15") && intensity > .2)
2076   if(!strcmp(name,"LED_ADDR_15") )
2077   {
2078 
2079     fprintf(stderr, "dbg: draw: %s intense=%f on_time=%d  old_clock=%d  start_clock=%d  old-start=%d\n",name, intensity, on_time, old_clock, start_clock,old_clock-start_clock);
2080   }
2081 #endif
2082 
2083   start_clock = *simclock;
2084   on_time = 0;
2085   dirty = 0;
2086 
2087 
2088 
2089   for(i=0;i<3;i++)
2090    {  color[i] = parms->color[i] * intensity + parms->color[i] * .2;
2091      // color[i] =  min(color[i],1.0);
2092       if(color[i] > 1.0) color[i] = 1.0;
2093    }
2094 
2095 
2096 }
2097 
2098 
2099 void
sampleData(void)2100 lpLight::sampleData(void)
2101 {
2102  (*sampleDataFunc)(this);
2103 }
2104 
2105 void
setupData(void)2106 lpLight::setupData(void)
2107 {
2108 
2109 
2110  if(obj_refname)
2111   { if( !( obj_ref = panel->findObjectByName(obj_refname)))
2112    {
2113      fprintf(stderr, "error: light %s references object %s which cannot be found.\n",
2114         name, obj_refname);
2115      return;
2116    }
2117 
2118    drawFunc = drawLightObject;
2119   }
2120 
2121 }
2122 
2123 void
setName(const char * _name)2124 lpLight::setName(const char *_name)
2125 { int n;
2126 
2127   n = strlen(_name);
2128   name = new char[n+1];
2129   strcpy(name,_name);
2130 }
2131 
2132 
2133 int
smoothLight(char * name,int nframes)2134 Lpanel::smoothLight(char *name, int nframes)
2135 {
2136   char **namelist;
2137   int num_names;
2138   int i, status = 1;
2139   lpLight *light;
2140 
2141   if( nframes <0)
2142    {
2143     fprintf(stderr, "smoothLight: light %s error. nframes = %d  must be >=0 \n", namelist[i], nframes);
2144     return 0;
2145    }
2146 
2147   num_names = xpand(name, &namelist);
2148 
2149   for(i=0;i<num_names;i++)
2150    {
2151 
2152      light = findLightByName(namelist[i]);
2153 
2154      if(light)
2155       {
2156         light->smoothing = nframes;
2157       }
2158      else
2159       {
2160 	if(!ignore_bind_errors) fprintf(stderr, "smoothLight: light %s not found\n", namelist[i]);
2161 	status = 0;
2162       }
2163     if(namelist[i]) delete namelist[i];
2164    }
2165 
2166   return status;
2167 }
2168 
2169