| 1 | – | /* Copyright (c) 1998 Silicon Graphics, Inc. */ | 
| 2 | – |  | 
| 1 |  | #ifndef lint | 
| 2 | < | static char SCCSid[] = "$SunId$ SGI"; | 
| 2 | > | static const char       RCSid[] = "$Id$"; | 
| 3 |  | #endif | 
| 6 | – |  | 
| 4 |  | /* | 
| 5 |  | * Routines for loading and displaying Radiance objects in rholo with GLX. | 
| 6 |  | */ | 
| 7 |  |  | 
| 8 | + | #include <string.h> | 
| 9 | + | #include <ctype.h> | 
| 10 | + |  | 
| 11 |  | #include "radogl.h" | 
| 12 |  | #include "tonemap.h" | 
| 13 |  | #include "rhdisp.h" | 
| 14 |  | #include "rhdriver.h" | 
| 15 |  | #include "rhdobj.h" | 
| 16 | + | #include "rtprocess.h" | 
| 17 |  |  | 
| 18 |  | extern FILE     *sstdout;               /* user standard output */ | 
| 19 |  |  | 
| 20 |  | char    rhdcmd[DO_NCMDS][8] = DO_INIT;  /* user command list */ | 
| 21 |  |  | 
| 22 | < | int     (*dobj_lightsamp)() = NULL;     /* pointer to function to get lights */ | 
| 22 | > | /* pointer to function to get lights */ | 
| 23 | > | void    (*dobj_lightsamp)(COLR clr, FVECT direc, FVECT pos) = NULL; | 
| 24 |  |  | 
| 25 |  | #define AVGREFL         0.5             /* assumed average reflectance */ | 
| 26 |  |  | 
| 34 |  | #define NALT            11              /* # sampling altitude angles */ | 
| 35 |  | #endif | 
| 36 |  | #ifndef NAZI | 
| 37 | < | #define NAZI            ((int)(PI/2.*NALT+.5)) | 
| 37 | > | #define NAZI            17 | 
| 38 |  | #endif | 
| 39 |  |  | 
| 40 |  | typedef struct dlights { | 
| 55 |  | struct dobject  *next;          /* next object in list */ | 
| 56 |  | char    name[64];               /* object name */ | 
| 57 |  | FVECT   center;                 /* orig. object center */ | 
| 58 | < | FLOAT   radius;                 /* orig. object radius */ | 
| 58 | > | RREAL   radius;                 /* orig. object radius */ | 
| 59 |  | int     listid;                 /* GL display list identifier */ | 
| 60 | < | int     rtp[3];                 /* associated rtrace process */ | 
| 60 | > | int     nlists;                 /* number of lists allocated */ | 
| 61 | > | SUBPROC rtp;                    /* associated rtrace process */ | 
| 62 |  | DLIGHTS *ol;                    /* object lights */ | 
| 63 |  | FULLXF  xfb;                    /* coordinate transform */ | 
| 64 |  | short   drawcode;               /* drawing code */ | 
| 86 |  |  | 
| 87 |  | #define curname         (curobj==NULL ? (char *)NULL : curobj->name) | 
| 88 |  |  | 
| 89 | + | static DOBJECT *getdobj(char *nm); | 
| 90 | + | static int freedobj(DOBJECT *op); | 
| 91 | + | static int savedxf(DOBJECT *op); | 
| 92 | + | static void ssph_sample(COLR clr, FVECT direc, FVECT pos); | 
| 93 | + | static void ssph_direc(FVECT direc, int alt, int azi); | 
| 94 | + | static int ssph_neigh(int sp[2], int next); | 
| 95 | + | static int ssph_compute(void); | 
| 96 | + | static int getdlights(DOBJECT *op, int force); | 
| 97 | + | static void cmderror(int cn, char *err); | 
| 98 |  |  | 
| 99 | + |  | 
| 100 |  | static DOBJECT * | 
| 101 | < | getdobj(nm)                     /* get object from list by name */ | 
| 102 | < | char    *nm; | 
| 101 | > | getdobj(                        /* get object from list by name */ | 
| 102 | > | char    *nm | 
| 103 | > | ) | 
| 104 |  | { | 
| 105 |  | register DOBJECT        *op; | 
| 106 |  |  | 
| 115 |  | } | 
| 116 |  |  | 
| 117 |  |  | 
| 118 | < | static | 
| 119 | < | freedobj(op)                    /* free resources and memory assoc. with op */ | 
| 120 | < | register DOBJECT        *op; | 
| 118 | > | static int | 
| 119 | > | freedobj(                       /* free resources and memory assoc. with op */ | 
| 120 | > | register DOBJECT        *op | 
| 121 | > | ) | 
| 122 |  | { | 
| 123 |  | int     foundlink = 0; | 
| 124 |  | DOBJECT ohead; | 
| 134 |  | } | 
| 135 |  | dobjects = ohead.next; | 
| 136 |  | if (!foundlink) { | 
| 137 | < | glDeleteLists(op->listid, 1); | 
| 138 | < | close_process(op->rtp); | 
| 137 | > | glDeleteLists(op->listid, op->nlists); | 
| 138 | > | close_process(&(op->rtp)); | 
| 139 |  | } | 
| 140 |  | while (op->xfac) | 
| 141 |  | freestr(op->xfav[--op->xfac]); | 
| 142 | < | free((char *)op); | 
| 142 | > | free((void *)op); | 
| 143 |  | return(1); | 
| 144 |  | } | 
| 145 |  |  | 
| 146 |  |  | 
| 147 | < | static | 
| 148 | < | savedxf(op)                     /* save transform for display object */ | 
| 149 | < | register DOBJECT        *op; | 
| 147 | > | static int | 
| 148 | > | savedxf(                        /* save transform for display object */ | 
| 149 | > | register DOBJECT        *op | 
| 150 | > | ) | 
| 151 |  | { | 
| 152 |  | /* free old */ | 
| 153 |  | while (lastxfac) | 
| 165 |  | } | 
| 166 |  |  | 
| 167 |  |  | 
| 168 | < | static | 
| 169 | < | ssph_sample(clr, direc, pos)    /* add sample to current source sphere */ | 
| 170 | < | COLR    clr; | 
| 171 | < | FVECT   direc, pos; | 
| 168 | > | static void | 
| 169 | > | ssph_sample(    /* add sample to current source sphere */ | 
| 170 | > | COLR    clr, | 
| 171 | > | FVECT   direc, | 
| 172 | > | FVECT   pos | 
| 173 | > | ) | 
| 174 |  | { | 
| 175 |  | COLOR   col; | 
| 176 |  | double  d; | 
| 194 |  | } | 
| 195 |  |  | 
| 196 |  |  | 
| 197 | < | static | 
| 198 | < | ssph_direc(direc, alt, azi)     /* compute sphere sampling direction */ | 
| 199 | < | FVECT   direc; | 
| 200 | < | int     alt, azi; | 
| 197 | > | static void | 
| 198 | > | ssph_direc(     /* compute sphere sampling direction */ | 
| 199 | > | FVECT   direc, | 
| 200 | > | int     alt, | 
| 201 | > | int     azi | 
| 202 | > | ) | 
| 203 |  | { | 
| 204 |  | double  phi, d; | 
| 205 |  |  | 
| 212 |  |  | 
| 213 |  |  | 
| 214 |  | static int | 
| 215 | < | ssph_neigh(sp, next)            /* neighbor counter on sphere */ | 
| 216 | < | register int    sp[2]; | 
| 217 | < | int     next; | 
| 215 | > | ssph_neigh(             /* neighbor counter on sphere */ | 
| 216 | > | register int    sp[2], | 
| 217 | > | int     next | 
| 218 | > | ) | 
| 219 |  | { | 
| 220 |  | static short    nneigh = 0;             /* neighbor count */ | 
| 221 |  | static short    neighlist[NAZI+6][2];   /* neighbor list (0 is home) */ | 
| 228 |  | sp[1] = neighlist[nneigh][1]; | 
| 229 |  | return(1); | 
| 230 |  | } | 
| 231 | < | if (sp[0] < 0 | sp[0] >= NALT | sp[1] < 0 | sp[1] >= NAZI) | 
| 231 | > | if ((sp[0] < 0) | (sp[0] >= NALT) | (sp[1] < 0) | (sp[1] >= NAZI)) | 
| 232 |  | return(nneigh=0); | 
| 233 |  | neighlist[0][0] = sp[0]; neighlist[0][1] = sp[1]; | 
| 234 |  | nneigh = 1; | 
| 278 |  | } | 
| 279 |  |  | 
| 280 |  |  | 
| 281 | < | static | 
| 282 | < | ssph_compute()                  /* compute source set from sphere samples */ | 
| 281 | > | static int | 
| 282 | > | ssph_compute(void)                      /* compute source set from sphere samples */ | 
| 283 |  | { | 
| 284 |  | int     ncells, nsamps; | 
| 285 |  | COLOR   csum; | 
| 302 |  | nsamps += ssamp[alt][azi].nsamp; | 
| 303 |  | ncells++; | 
| 304 |  | } | 
| 305 | < | if (dlightsets == NULL | ncells < NALT*NAZI/4) { | 
| 305 | > | if ((dlightsets == NULL) | (ncells < NALT*NAZI/4)) { | 
| 306 |  | ncells = 0; | 
| 307 |  | goto done; | 
| 308 |  | } | 
| 320 |  | /* avg. reflected brightness */ | 
| 321 |  | d = AVGREFL / (double)ncells; | 
| 322 |  | scalecolor(csum, d); | 
| 323 | < | if (tmCvColors(&dlightsets->larb, TM_NOCHROM, csum, 1) != TM_E_OK) | 
| 323 | > | if (tmCvColors(tmGlobal, &dlightsets->larb, | 
| 324 | > | TM_NOCHROM, &csum, 1) != TM_E_OK) | 
| 325 |  | error(CONSISTENCY, "tone mapping problem in ssph_compute"); | 
| 326 |  | /* greedy light source clustering */ | 
| 327 |  | while (dlightsets->nl < MAXLIGHTS) { | 
| 361 |  | d = 1.0/ncells; | 
| 362 |  | scalecolor(dlightsets->lamb, d); | 
| 363 |  | done:                                   /* clear sphere sample array */ | 
| 364 | < | bzero((char *)ssamp, sizeof(ssamp)); | 
| 364 | > | memset((void *)ssamp, '\0', sizeof(ssamp)); | 
| 365 |  | return(ncells); | 
| 366 |  | } | 
| 367 |  |  | 
| 368 |  |  | 
| 369 | < | static | 
| 370 | < | getdlights(op, force)           /* get lights for display object */ | 
| 371 | < | register DOBJECT        *op; | 
| 372 | < | int     force; | 
| 369 | > | static int | 
| 370 | > | getdlights(             /* get lights for display object */ | 
| 371 | > | register DOBJECT        *op, | 
| 372 | > | int     force | 
| 373 | > | ) | 
| 374 |  | { | 
| 375 |  | double  d2, mind2 = FHUGE*FHUGE; | 
| 376 |  | FVECT   ocent; | 
| 395 |  | if (!force) | 
| 396 |  | return(0); | 
| 397 |  | /* need to compute new light set */ | 
| 398 | < | copystruct(&cvw, &stdview); | 
| 398 | > | cvw = stdview; | 
| 399 |  | cvw.type = VT_PER; | 
| 400 |  | VCOPY(cvw.vp, ocent); | 
| 401 |  | cvw.vup[0] = 1.; cvw.vup[1] = cvw.vup[2] = 0.; | 
| 429 |  | quit(0); | 
| 430 |  | if (!ssph_compute()) {          /* compute light sources from sphere */ | 
| 431 |  | dlightsets = dl->next; | 
| 432 | < | free((char *)dl); | 
| 432 | > | free((void *)dl); | 
| 433 |  | return(0); | 
| 434 |  | } | 
| 435 |  | op->ol = dl; | 
| 436 |  | return(1); | 
| 437 |  | memerr: | 
| 438 |  | error(SYSTEM, "out of memory in getdlights"); | 
| 439 | + | return 0; /* pro forma return */ | 
| 440 |  | } | 
| 441 |  |  | 
| 442 |  |  | 
| 443 | < | static | 
| 444 | < | cmderror(cn, err)               /* report command error */ | 
| 445 | < | int     cn; | 
| 446 | < | char    *err; | 
| 443 | > | static void | 
| 444 | > | cmderror(               /* report command error */ | 
| 445 | > | int     cn, | 
| 446 | > | char    *err | 
| 447 | > | ) | 
| 448 |  | { | 
| 449 |  | sprintf(errmsg, "%s: %s", rhdcmd[cn], err); | 
| 450 |  | error(COMMAND, errmsg); | 
| 451 |  | } | 
| 452 |  |  | 
| 453 |  |  | 
| 454 | < | int | 
| 455 | < | dobj_command(cmd, args)         /* run object display command */ | 
| 456 | < | char    *cmd; | 
| 457 | < | register char   *args; | 
| 454 | > | extern int | 
| 455 | > | dobj_command(           /* run object display command */ | 
| 456 | > | char    *cmd, | 
| 457 | > | register char   *args | 
| 458 | > | ) | 
| 459 |  | { | 
| 460 |  | int     somechange = 0; | 
| 461 | < | int     cn, na, doxfm; | 
| 461 | > | int     cn, na; | 
| 462 |  | register int    nn; | 
| 463 |  | char    *alist[MAXAC+1], *nm; | 
| 464 |  | /* find command */ | 
| 556 |  | } | 
| 557 |  | return(somechange); | 
| 558 |  | toomany: | 
| 559 | < | return(cmderror(cn, "too many arguments")); | 
| 559 | > | cmderror(cn, "too many arguments"); | 
| 560 | > | return(-1); | 
| 561 |  | } | 
| 562 |  |  | 
| 563 |  |  | 
| 564 | < | dobj_load(oct, nam)             /* create/load an octree object */ | 
| 565 | < | char    *oct, *nam; | 
| 564 | > | extern int | 
| 565 | > | dobj_load(              /* create/load an octree object */ | 
| 566 | > | char    *oct, | 
| 567 | > | char    *nam | 
| 568 | > | ) | 
| 569 |  | { | 
| 540 | – | extern char     *getlibpath(), *getpath(); | 
| 570 |  | char    *fpp, fpath[128]; | 
| 571 |  | register DOBJECT        *op; | 
| 572 |  | /* check arguments */ | 
| 578 |  | error(COMMAND, "missing name"); | 
| 579 |  | return(0); | 
| 580 |  | } | 
| 581 | < | if (*nam == '*' | *nam == '-') { | 
| 581 | > | if ((*nam == '*') | (*nam == '-')) { | 
| 582 |  | error(COMMAND, "illegal name"); | 
| 583 |  | return(0); | 
| 584 |  | } | 
| 587 |  | return(0); | 
| 588 |  | } | 
| 589 |  | /* get octree path */ | 
| 590 | < | if ((fpp = getpath(oct, getlibpath(), R_OK)) == NULL) { | 
| 590 | > | if ((fpp = getpath(oct, getrlibpath(), R_OK)) == NULL) { | 
| 591 |  | sprintf(errmsg, "cannot find octree \"%s\"", oct); | 
| 592 |  | error(COMMAND, errmsg); | 
| 593 |  | return(0); | 
| 606 |  | /* load octree into display list */ | 
| 607 |  | dolights = 0; | 
| 608 |  | domats = 1; | 
| 609 | < | op->listid = rgl_octlist(fpath, op->center, &op->radius); | 
| 609 | > | op->listid = rgl_octlist(fpath, op->center, &op->radius, &op->nlists); | 
| 610 |  | /* start rtrace */ | 
| 611 |  | rtargv[RTARGC-1] = fpath; | 
| 612 |  | rtargv[RTARGC] = NULL; | 
| 613 | < | open_process(op->rtp, rtargv); | 
| 613 | > | open_process(&(op->rtp), rtargv); | 
| 614 |  | /* insert into main list */ | 
| 615 |  | op->next = dobjects; | 
| 616 |  | curobj = dobjects = op; | 
| 619 |  | } | 
| 620 |  |  | 
| 621 |  |  | 
| 622 | < | dobj_unload(nam)                        /* free the named object */ | 
| 623 | < | char    *nam; | 
| 622 | > | extern int | 
| 623 | > | dobj_unload(                    /* free the named object */ | 
| 624 | > | char    *nam | 
| 625 | > | ) | 
| 626 |  | { | 
| 627 |  | register DOBJECT        *op; | 
| 628 |  |  | 
| 636 |  | } | 
| 637 |  |  | 
| 638 |  |  | 
| 639 | < | dobj_cleanup()                          /* free all resources */ | 
| 639 | > | extern int | 
| 640 | > | dobj_cleanup(void)                              /* free all resources */ | 
| 641 |  | { | 
| 642 |  | register DLIGHTS        *lp; | 
| 643 |  |  | 
| 646 |  | savedxf(curobj = NULL); | 
| 647 |  | while ((lp = dlightsets) != NULL) { | 
| 648 |  | dlightsets = lp->next; | 
| 649 | < | free((char *)lp); | 
| 649 | > | free((void *)lp); | 
| 650 |  | } | 
| 651 |  | return(1); | 
| 652 |  | } | 
| 653 |  |  | 
| 654 |  |  | 
| 655 | < | dobj_xform(nam, rel, ac, av)            /* set/add transform for nam */ | 
| 656 | < | char    *nam; | 
| 657 | < | int     rel, ac; | 
| 658 | < | char    **av; | 
| 655 | > | extern int | 
| 656 | > | dobj_xform(             /* set/add transform for nam */ | 
| 657 | > | char    *nam, | 
| 658 | > | int     rel, | 
| 659 | > | int     ac, | 
| 660 | > | char    **av | 
| 661 | > | ) | 
| 662 |  | { | 
| 663 |  | register DOBJECT        *op; | 
| 664 |  | FVECT   cent; | 
| 717 |  | } | 
| 718 |  |  | 
| 719 |  |  | 
| 720 | < | dobj_putstats(nam, fp)                  /* put out statistics for nam */ | 
| 721 | < | char    *nam; | 
| 722 | < | FILE    *fp; | 
| 720 | > | extern int | 
| 721 | > | dobj_putstats(                  /* put out statistics for nam */ | 
| 722 | > | char    *nam, | 
| 723 | > | FILE    *fp | 
| 724 | > | ) | 
| 725 |  | { | 
| 726 |  | FVECT   ocent; | 
| 727 |  | register DOBJECT        *op; | 
| 760 |  | } | 
| 761 |  |  | 
| 762 |  |  | 
| 763 | < | dobj_unmove()                           /* undo last transform change */ | 
| 763 | > | extern int | 
| 764 | > | dobj_unmove(void)                               /* undo last transform change */ | 
| 765 |  | { | 
| 766 |  | int     txfac; | 
| 767 |  | char    *txfav[MAXAC+1]; | 
| 771 |  | return(0); | 
| 772 |  | } | 
| 773 |  | /* hold last transform */ | 
| 774 | < | bcopy((char *)lastxfav, (char *)txfav, | 
| 774 | > | memcpy((void *)txfav, (void *)lastxfav, | 
| 775 |  | (txfac=lastxfac)*sizeof(char *)); | 
| 776 |  | /* save this transform */ | 
| 777 | < | bcopy((char *)curobj->xfav, (char *)lastxfav, | 
| 777 | > | memcpy((void *)lastxfav, (void *)curobj->xfav, | 
| 778 |  | (lastxfac=curobj->xfac)*sizeof(char *)); | 
| 779 |  | /* copy back last transform */ | 
| 780 | < | bcopy((char *)txfav, (char *)curobj->xfav, | 
| 780 | > | memcpy((void *)curobj->xfav, (void *)txfav, | 
| 781 |  | (curobj->xfac=txfac)*sizeof(char *)); | 
| 782 |  | /* set matrices */ | 
| 783 |  | fullxf(&curobj->xfb, curobj->xfac, curobj->xfav); | 
| 787 |  | } | 
| 788 |  |  | 
| 789 |  |  | 
| 790 | < | dobj_dup(oldnm, nam)                    /* duplicate object oldnm as nam */ | 
| 791 | < | char    *oldnm, *nam; | 
| 790 | > | extern int | 
| 791 | > | dobj_dup(                       /* duplicate object oldnm as nam */ | 
| 792 | > | char    *oldnm, | 
| 793 | > | char    *nam | 
| 794 | > | ) | 
| 795 |  | { | 
| 796 |  | register DOBJECT        *op, *opdup; | 
| 797 |  | /* check arguments */ | 
| 803 |  | error(COMMAND, "missing name"); | 
| 804 |  | return(0); | 
| 805 |  | } | 
| 806 | < | if (*nam == '*' | *nam == '-') { | 
| 806 | > | if ((*nam == '*') | (*nam == '-')) { | 
| 807 |  | error(COMMAND, "illegal name"); | 
| 808 |  | return(0); | 
| 809 |  | } | 
| 815 |  | opdup = (DOBJECT *)malloc(sizeof(DOBJECT)); | 
| 816 |  | if (opdup == NULL) | 
| 817 |  | error(SYSTEM, "out of memory in dobj_dup"); | 
| 818 | < | copystruct(opdup, op); | 
| 818 | > | *opdup = *op; | 
| 819 |  | /* rename */ | 
| 820 |  | strcpy(opdup->name, nam); | 
| 821 |  | /* get our own copy of transform */ | 
| 829 |  | } | 
| 830 |  |  | 
| 831 |  |  | 
| 832 | < | dobj_lighting(nam, cn)          /* set up lighting for display object */ | 
| 833 | < | char    *nam; | 
| 834 | < | int     cn; | 
| 832 | > | extern int | 
| 833 | > | dobj_lighting(          /* set up lighting for display object */ | 
| 834 | > | char    *nam, | 
| 835 | > | int     cn | 
| 836 | > | ) | 
| 837 |  | { | 
| 838 |  | int     i, res[2]; | 
| 839 |  | VIEW    *dv; | 
| 865 |  | beam_view(dv, res[0], res[1]); | 
| 866 |  | beam_sync(1);                   /* update server */ | 
| 867 |  | } | 
| 868 | + | return 0; /* XXX not sure if this is the right value */ | 
| 869 |  | } | 
| 870 |  |  | 
| 871 |  |  | 
| 872 | < | double | 
| 873 | < | dobj_trace(nm, rorg, rdir)      /* check for ray intersection with object(s) */ | 
| 874 | < | char    nm[]; | 
| 875 | < | FVECT   rorg, rdir; | 
| 872 | > | extern double | 
| 873 | > | dobj_trace(     /* check for ray intersection with object(s) */ | 
| 874 | > | char    nm[], | 
| 875 | > | FVECT  rorg, | 
| 876 | > | FVECT  rdir | 
| 877 | > | ) | 
| 878 |  | { | 
| 879 |  | register DOBJECT        *op; | 
| 880 |  | FVECT   xorg, xdir; | 
| 908 |  | VCOPY(darr, rorg); VCOPY(darr+3, rdir); | 
| 909 |  | } | 
| 910 |  | /* trace it */ | 
| 911 | < | if (process(op->rtp, darr, darr, sizeof(double), | 
| 911 | > | if (process(&(op->rtp), (char *)darr, (char *)darr, sizeof(double), | 
| 912 |  | 6*sizeof(double)) != sizeof(double)) | 
| 913 |  | error(SYSTEM, "rtrace communication error"); | 
| 914 |  | /* return distance */ | 
| 918 |  | } | 
| 919 |  |  | 
| 920 |  |  | 
| 921 | < | int | 
| 922 | < | dobj_render()                   /* render our objects in OpenGL */ | 
| 921 | > | extern int | 
| 922 | > | dobj_render(void)                       /* render our objects in OpenGL */ | 
| 923 |  | { | 
| 924 |  | int     nrendered = 0; | 
| 925 |  | GLboolean       normalizing; | 
| 954 |  | continue; | 
| 955 |  | /* set up lighting */ | 
| 956 |  | if (op->drawcode == DO_LIGHT && op->ol != NULL) { | 
| 957 | < | BYTE    pval; | 
| 957 | > | uby8    pval; | 
| 958 |  | double  expval, d; | 
| 959 |  | /* use computed sources */ | 
| 960 | < | if (tmMapPixels(&pval, &op->ol->larb, TM_NOCHROM, 1) | 
| 961 | < | != TM_E_OK) | 
| 960 | > | if (tmMapPixels(tmGlobal, &pval, &op->ol->larb, | 
| 961 | > | TM_NOCHROM, 1) != TM_E_OK) | 
| 962 |  | error(CONSISTENCY, "dobj_render w/o tone map"); | 
| 963 |  | expval = pval * (WHTEFFICACY/256.) / | 
| 964 |  | tmLuminance(op->ol->larb); | 
| 1004 |  | } | 
| 1005 |  | /* set up object transform */ | 
| 1006 |  | if (op->xfac) { | 
| 1007 | < | if (!normalizing && op->xfb.f.sca < 1.-FTINY | | 
| 1008 | < | op->xfb.f.sca > 1.+FTINY) | 
| 1007 | > | if (!normalizing && (op->xfb.f.sca < 1.-FTINY) | | 
| 1008 | > | (op->xfb.f.sca > 1.+FTINY)) | 
| 1009 |  | glEnable(GL_NORMALIZE); | 
| 1010 |  | glMatrixMode(GL_MODELVIEW); | 
| 1011 |  | glPushMatrix(); |