| 1 | 
– | 
/* Copyright (c) 1987 Regents of the University of California */ | 
| 2 | 
– | 
 | 
| 1 | 
  | 
#ifndef lint | 
| 2 | 
< | 
static char SCCSid[] = "$SunId$ LBL"; | 
| 2 | 
> | 
static const char       RCSid[] = "$Id$"; | 
| 3 | 
  | 
#endif | 
| 6 | 
– | 
 | 
| 4 | 
  | 
/* | 
| 5 | 
  | 
 *  rview.c - routines and variables for interactive view generation. | 
| 6 | 
  | 
 * | 
| 7 | 
< | 
 *     3/24/87 | 
| 7 | 
> | 
 *  External symbols declared in rpaint.h | 
| 8 | 
  | 
 */ | 
| 9 | 
  | 
 | 
| 10 | 
< | 
#include  "ray.h" | 
| 10 | 
> | 
#include "copyright.h" | 
| 11 | 
  | 
 | 
| 15 | 
– | 
#include  "rpaint.h" | 
| 16 | 
– | 
 | 
| 12 | 
  | 
#include  <signal.h> | 
| 18 | 
– | 
 | 
| 13 | 
  | 
#include  <ctype.h> | 
| 14 | 
  | 
 | 
| 15 | 
< | 
VIEW  ourview = STDVIEW;                /* viewing parameters */ | 
| 16 | 
< | 
int  hresolu, vresolu;                  /* image resolution */ | 
| 15 | 
> | 
#include  "ray.h" | 
| 16 | 
> | 
#include  "rpaint.h" | 
| 17 | 
  | 
 | 
| 18 | 
< | 
int  dimlist[MAXDIM];                   /* sampling dimensions */ | 
| 25 | 
< | 
int  ndims = 0;                         /* number of sampling dimensions */ | 
| 26 | 
< | 
int  samplendx = 0;                     /* index for this sample */ | 
| 18 | 
> | 
#define  CTRL(c)        ((c)-'@') | 
| 19 | 
  | 
 | 
| 28 | 
– | 
int  psample = 8;                       /* pixel sample size */ | 
| 29 | 
– | 
double  maxdiff = .15;                  /* max. sample difference */ | 
| 20 | 
  | 
 | 
| 21 | 
< | 
double  exposure = 1.0;                 /* exposure for scene */ | 
| 32 | 
< | 
 | 
| 33 | 
< | 
double  dstrsrc = 0.0;                  /* square source distribution */ | 
| 34 | 
< | 
double  shadthresh = .1;                /* shadow threshold */ | 
| 35 | 
< | 
double  shadcert = .25;                 /* shadow certainty */ | 
| 36 | 
< | 
int  directrelay = 0;                   /* number of source relays */ | 
| 37 | 
< | 
int  vspretest = 32;                    /* virtual source pretest density */ | 
| 38 | 
< | 
 | 
| 39 | 
< | 
int  maxdepth = 4;                      /* maximum recursion depth */ | 
| 40 | 
< | 
double  minweight = 1e-2;               /* minimum ray weight */ | 
| 41 | 
< | 
 | 
| 42 | 
< | 
COLOR  ambval = BLKCOLOR;               /* ambient value */ | 
| 43 | 
< | 
double  ambacc = 0.2;                   /* ambient accuracy */ | 
| 44 | 
< | 
int  ambres = 8;                        /* ambient resolution */ | 
| 45 | 
< | 
int  ambdiv = 32;                       /* ambient divisions */ | 
| 46 | 
< | 
int  ambssamp = 0;                      /* ambient super-samples */ | 
| 47 | 
< | 
int  ambounce = 0;                      /* ambient bounces */ | 
| 48 | 
< | 
char  *amblist[128];                    /* ambient include/exclude list */ | 
| 49 | 
< | 
int  ambincl = -1;                      /* include == 1, exclude == 0 */ | 
| 50 | 
< | 
 | 
| 51 | 
< | 
int  greyscale = 0;                     /* map colors to brightness? */ | 
| 52 | 
< | 
char  *devname = dev_default;           /* output device name */ | 
| 53 | 
< | 
 | 
| 54 | 
< | 
struct driver  *dev = NULL;             /* driver functions */ | 
| 55 | 
< | 
 | 
| 56 | 
< | 
VIEW  oldview;                          /* previous view parameters */ | 
| 57 | 
< | 
 | 
| 58 | 
< | 
PNODE  ptrunk;                          /* the base of our image */ | 
| 59 | 
< | 
RECT  pframe;                           /* current frame boundaries */ | 
| 60 | 
< | 
int  pdepth;                            /* image depth in current frame */ | 
| 61 | 
< | 
 | 
| 62 | 
< | 
static char  *reserve_mem = NULL;       /* pre-allocated reserve memory */ | 
| 63 | 
< | 
 | 
| 64 | 
< | 
#define RESERVE_AMT     8192            /* amount of memory to reserve */ | 
| 65 | 
< | 
 | 
| 66 | 
< | 
#define  CTRL(c)        ('c'-'@') | 
| 67 | 
< | 
 | 
| 68 | 
< | 
 | 
| 21 | 
> | 
void | 
| 22 | 
  | 
quit(code)                      /* quit program */ | 
| 23 | 
  | 
int  code; | 
| 24 | 
  | 
{ | 
| 25 | 
< | 
        devclose(); | 
| 25 | 
> | 
        if (ray_pnprocs > 0)    /* close children if any */ | 
| 26 | 
> | 
                ray_pclose(0); | 
| 27 | 
> | 
        else if (!ray_pnprocs)  /* in parent */ | 
| 28 | 
> | 
                devclose(); | 
| 29 | 
  | 
        exit(code); | 
| 30 | 
  | 
} | 
| 31 | 
  | 
 | 
| 32 | 
  | 
 | 
| 33 | 
< | 
devopen(dname)                          /* open device driver */ | 
| 34 | 
< | 
char  *dname; | 
| 33 | 
> | 
void | 
| 34 | 
> | 
devopen(                                /* open device driver */ | 
| 35 | 
> | 
        char  *dname | 
| 36 | 
> | 
) | 
| 37 | 
  | 
{ | 
| 38 | 
  | 
        extern char  *progname, *octname; | 
| 39 | 
  | 
        char  *id; | 
| 40 | 
< | 
        register int  i; | 
| 40 | 
> | 
        int  i; | 
| 41 | 
  | 
 | 
| 42 | 
  | 
        id = octname!=NULL ? octname : progname; | 
| 43 | 
  | 
                                                /* check device table */ | 
| 44 | 
  | 
        for (i = 0; devtable[i].name; i++) | 
| 45 | 
< | 
                if (!strcmp(dname, devtable[i].name)) | 
| 45 | 
> | 
                if (!strcmp(dname, devtable[i].name)) { | 
| 46 | 
  | 
                        if ((dev = (*devtable[i].init)(dname, id)) == NULL) { | 
| 47 | 
  | 
                                sprintf(errmsg, "cannot initialize %s", dname); | 
| 48 | 
  | 
                                error(USER, errmsg); | 
| 49 | 
  | 
                        } else | 
| 50 | 
  | 
                                return; | 
| 51 | 
+ | 
                } | 
| 52 | 
  | 
                                                /* not there, try exec */ | 
| 53 | 
  | 
        if ((dev = comm_init(dname, id)) == NULL) { | 
| 54 | 
  | 
                sprintf(errmsg, "cannot start device \"%s\"", dname); | 
| 57 | 
  | 
} | 
| 58 | 
  | 
 | 
| 59 | 
  | 
 | 
| 60 | 
< | 
devclose()                              /* close our device */ | 
| 60 | 
> | 
void | 
| 61 | 
> | 
devclose(void)                          /* close our device */ | 
| 62 | 
  | 
{ | 
| 63 | 
  | 
        if (dev != NULL) | 
| 64 | 
  | 
                (*dev->close)(); | 
| 66 | 
  | 
} | 
| 67 | 
  | 
 | 
| 68 | 
  | 
 | 
| 69 | 
< | 
printdevices()                          /* print list of output devices */ | 
| 69 | 
> | 
void | 
| 70 | 
> | 
printdevices(void)                      /* print list of output devices */ | 
| 71 | 
  | 
{ | 
| 72 | 
< | 
        register int  i; | 
| 72 | 
> | 
        int  i; | 
| 73 | 
  | 
 | 
| 74 | 
  | 
        for (i = 0; devtable[i].name; i++) | 
| 75 | 
  | 
                printf("%-16s # %s\n", devtable[i].name, devtable[i].descrip); | 
| 76 | 
  | 
} | 
| 77 | 
  | 
 | 
| 78 | 
  | 
 | 
| 79 | 
< | 
rview()                         /* do a view */ | 
| 79 | 
> | 
void | 
| 80 | 
> | 
rview(void)                             /* do a view */ | 
| 81 | 
  | 
{ | 
| 82 | 
  | 
        char  buf[32]; | 
| 83 | 
  | 
 | 
| 84 | 
< | 
        devopen(devname);               /* open device */ | 
| 85 | 
< | 
        newimage();                     /* start image (calls fillreserves) */ | 
| 84 | 
> | 
        devopen(dvcname);               /* open device */ | 
| 85 | 
> | 
        newimage(NULL);                 /* start image */ | 
| 86 | 
  | 
 | 
| 87 | 
  | 
        for ( ; ; ) {                   /* quit in command() */ | 
| 88 | 
  | 
                while (hresolu <= 1<<pdepth && vresolu <= 1<<pdepth) | 
| 89 | 
  | 
                        command("done: "); | 
| 128 | 
– | 
                while (reserve_mem == NULL) | 
| 129 | 
– | 
                        command("out of memory: "); | 
| 90 | 
  | 
                errno = 0; | 
| 91 | 
  | 
                if (hresolu <= psample<<pdepth && vresolu <= psample<<pdepth) { | 
| 92 | 
  | 
                        sprintf(buf, "%d sampling...\n", 1<<pdepth); | 
| 95 | 
  | 
                } else { | 
| 96 | 
  | 
                        sprintf(buf, "%d refining...\n", 1<<pdepth); | 
| 97 | 
  | 
                        (*dev->comout)(buf); | 
| 98 | 
< | 
                        refine(&ptrunk, 0, 0, hresolu, vresolu, pdepth+1); | 
| 98 | 
> | 
                        refine(&ptrunk, pdepth+1); | 
| 99 | 
  | 
                } | 
| 100 | 
< | 
                if (errno == ENOMEM)            /* ran out of memory */ | 
| 141 | 
< | 
                        freereserves(); | 
| 142 | 
< | 
                else if (dev->inpready)         /* noticed some input */ | 
| 100 | 
> | 
                if (dev->inpready)              /* noticed some input */ | 
| 101 | 
  | 
                        command(": "); | 
| 102 | 
  | 
                else                            /* finished this depth */ | 
| 103 | 
  | 
                        pdepth++; | 
| 105 | 
  | 
} | 
| 106 | 
  | 
 | 
| 107 | 
  | 
 | 
| 108 | 
< | 
fillreserves()                  /* fill memory reserves */ | 
| 108 | 
> | 
void | 
| 109 | 
> | 
command(                        /* get/execute command */ | 
| 110 | 
> | 
        char  *prompt | 
| 111 | 
> | 
) | 
| 112 | 
  | 
{ | 
| 113 | 
< | 
        if (reserve_mem != NULL) | 
| 153 | 
< | 
                return; | 
| 154 | 
< | 
        reserve_mem = malloc(RESERVE_AMT); | 
| 155 | 
< | 
} | 
| 156 | 
< | 
 | 
| 157 | 
< | 
 | 
| 158 | 
< | 
freereserves()                  /* free memory reserves */ | 
| 159 | 
< | 
{ | 
| 160 | 
< | 
        if (reserve_mem == NULL) | 
| 161 | 
< | 
                return; | 
| 162 | 
< | 
        free(reserve_mem); | 
| 163 | 
< | 
        reserve_mem = NULL; | 
| 164 | 
< | 
} | 
| 165 | 
< | 
 | 
| 166 | 
< | 
 | 
| 167 | 
< | 
command(prompt)                 /* get/execute command */ | 
| 168 | 
< | 
char  *prompt; | 
| 169 | 
< | 
{ | 
| 170 | 
< | 
#define  badcom(s)      strncmp(s, inpbuf, args-inpbuf-1) | 
| 171 | 
< | 
        double  atof(); | 
| 113 | 
> | 
#define  badcom(s)      strncmp(s, inpbuf, args-inpbuf-1) | 
| 114 | 
  | 
        char  inpbuf[256]; | 
| 115 | 
  | 
        char  *args; | 
| 116 | 
  | 
again: | 
| 119 | 
  | 
                ; | 
| 120 | 
  | 
        if (*args) *args++ = '\0'; | 
| 121 | 
  | 
        else *++args = '\0'; | 
| 122 | 
+ | 
 | 
| 123 | 
+ | 
        if (waitrays() < 0)                     /* clear ray queue */ | 
| 124 | 
+ | 
                quit(1); | 
| 125 | 
  | 
         | 
| 126 | 
  | 
        switch (inpbuf[0]) { | 
| 127 | 
< | 
        case 'f':                               /* new frame */ | 
| 128 | 
< | 
                if (badcom("frame")) | 
| 129 | 
< | 
                        goto commerr; | 
| 127 | 
> | 
        case 'f':                               /* new frame (|focus|free) */ | 
| 128 | 
> | 
                if (badcom("frame")) { | 
| 129 | 
> | 
                        if (badcom("focus")) { | 
| 130 | 
> | 
                                if (badcom("free")) | 
| 131 | 
> | 
                                        goto commerr; | 
| 132 | 
> | 
                                free_objmem(); | 
| 133 | 
> | 
                                break; | 
| 134 | 
> | 
                        } | 
| 135 | 
> | 
                        getfocus(args); | 
| 136 | 
> | 
                        break; | 
| 137 | 
> | 
                } | 
| 138 | 
  | 
                getframe(args); | 
| 139 | 
  | 
                break; | 
| 140 | 
  | 
        case 'v':                               /* view */ | 
| 147 | 
  | 
                        goto commerr; | 
| 148 | 
  | 
                lastview(args); | 
| 149 | 
  | 
                break; | 
| 150 | 
+ | 
        case 'V':                               /* save view */ | 
| 151 | 
+ | 
                if (badcom("V")) | 
| 152 | 
+ | 
                        goto commerr; | 
| 153 | 
+ | 
                saveview(args); | 
| 154 | 
+ | 
                break; | 
| 155 | 
+ | 
        case 'L':                               /* load view */ | 
| 156 | 
+ | 
                if (badcom("L")) | 
| 157 | 
+ | 
                        goto commerr; | 
| 158 | 
+ | 
                loadview(args); | 
| 159 | 
+ | 
                break; | 
| 160 | 
  | 
        case 'e':                               /* exposure */ | 
| 161 | 
  | 
                if (badcom("exposure")) | 
| 162 | 
  | 
                        goto commerr; | 
| 163 | 
  | 
                getexposure(args); | 
| 164 | 
  | 
                break; | 
| 165 | 
  | 
        case 's':                               /* set a parameter */ | 
| 166 | 
< | 
                if (badcom("set")) | 
| 166 | 
> | 
                if (badcom("set")) { | 
| 167 | 
> | 
#ifdef  SIGTSTP | 
| 168 | 
> | 
                        if (!badcom("stop")) | 
| 169 | 
> | 
                                goto dostop; | 
| 170 | 
> | 
#endif | 
| 171 | 
  | 
                        goto commerr; | 
| 172 | 
+ | 
                } | 
| 173 | 
  | 
                setparam(args); | 
| 174 | 
  | 
                break; | 
| 175 | 
  | 
        case 'n':                               /* new picture */ | 
| 176 | 
  | 
                if (badcom("new")) | 
| 177 | 
  | 
                        goto commerr; | 
| 178 | 
< | 
                newimage(); | 
| 178 | 
> | 
                newimage(args); | 
| 179 | 
  | 
                break; | 
| 180 | 
  | 
        case 't':                               /* trace a ray */ | 
| 181 | 
  | 
                if (badcom("trace")) | 
| 187 | 
  | 
                        goto commerr; | 
| 188 | 
  | 
                getaim(args); | 
| 189 | 
  | 
                break; | 
| 190 | 
< | 
        case 'm':                               /* move camera */ | 
| 190 | 
> | 
        case 'm':                               /* move camera (or memstats) */ | 
| 191 | 
  | 
                if (badcom("move")) | 
| 192 | 
  | 
                        goto commerr; | 
| 193 | 
  | 
                getmove(args); | 
| 194 | 
  | 
                break; | 
| 195 | 
  | 
        case 'r':                               /* rotate/repaint */ | 
| 196 | 
  | 
                if (badcom("rotate")) { | 
| 197 | 
< | 
                        if (badcom("repaint")) | 
| 198 | 
< | 
                                goto commerr; | 
| 197 | 
> | 
                        if (badcom("repaint")) { | 
| 198 | 
> | 
                                if (badcom("redraw")) | 
| 199 | 
> | 
                                        goto commerr; | 
| 200 | 
> | 
                                redraw(); | 
| 201 | 
> | 
                                break; | 
| 202 | 
> | 
                        } | 
| 203 | 
  | 
                        getrepaint(args); | 
| 204 | 
  | 
                        break; | 
| 205 | 
  | 
                } | 
| 206 | 
  | 
                getrotate(args); | 
| 207 | 
  | 
                break; | 
| 208 | 
  | 
        case 'p':                               /* pivot view */ | 
| 209 | 
< | 
                if (badcom("pivot")) | 
| 210 | 
< | 
                        goto commerr; | 
| 209 | 
> | 
                if (badcom("pivot")) { | 
| 210 | 
> | 
                        if (badcom("pause")) | 
| 211 | 
> | 
                                goto commerr; | 
| 212 | 
> | 
                        goto again; | 
| 213 | 
> | 
                } | 
| 214 | 
  | 
                getpivot(args); | 
| 215 | 
  | 
                break; | 
| 216 | 
< | 
        case CTRL(R):                           /* redraw */ | 
| 216 | 
> | 
        case CTRL('R'):                         /* redraw */ | 
| 217 | 
  | 
                redraw(); | 
| 218 | 
  | 
                break; | 
| 219 | 
  | 
        case 'w':                               /* write */ | 
| 225 | 
  | 
                if (badcom("quit")) | 
| 226 | 
  | 
                        goto commerr; | 
| 227 | 
  | 
                quit(0); | 
| 228 | 
< | 
        case CTRL(C):                           /* interrupt */ | 
| 228 | 
> | 
        case CTRL('C'):                         /* interrupt */ | 
| 229 | 
  | 
                goto again; | 
| 230 | 
< | 
#ifdef  SIGTSTP | 
| 231 | 
< | 
        case CTRL(Z):                           /* stop */ | 
| 230 | 
> | 
#ifdef  SIGTSTP | 
| 231 | 
> | 
        case CTRL('Z'):;                        /* stop */ | 
| 232 | 
> | 
dostop: | 
| 233 | 
  | 
                devclose(); | 
| 234 | 
  | 
                kill(0, SIGTSTP); | 
| 235 | 
  | 
                /* pc stops here */ | 
| 236 | 
< | 
                devopen(devname); | 
| 236 | 
> | 
                devopen(dvcname); | 
| 237 | 
  | 
                redraw(); | 
| 238 | 
  | 
                break; | 
| 239 | 
  | 
#endif | 
| 249 | 
  | 
                error(COMMAND, errmsg); | 
| 250 | 
  | 
                break; | 
| 251 | 
  | 
        } | 
| 252 | 
< | 
#undef  badcom | 
| 252 | 
> | 
#undef  badcom | 
| 253 | 
  | 
} | 
| 254 | 
  | 
 | 
| 255 | 
  | 
 | 
| 256 | 
< | 
rsample()                       /* sample the image */ | 
| 256 | 
> | 
void | 
| 257 | 
> | 
rsample(void)                   /* sample the image */ | 
| 258 | 
  | 
{ | 
| 259 | 
  | 
        int  xsiz, ysiz, y; | 
| 283 | 
– | 
        RECT  r; | 
| 260 | 
  | 
        PNODE  *p; | 
| 261 | 
< | 
        register RECT  *rl; | 
| 262 | 
< | 
        register PNODE  **pl; | 
| 287 | 
< | 
        register int  x; | 
| 261 | 
> | 
        PNODE   **pl; | 
| 262 | 
> | 
        int  x; | 
| 263 | 
  | 
        /* | 
| 264 | 
  | 
         *     We initialize the bottom row in the image at our current | 
| 265 | 
< | 
         * resolution.  During sampling, we check super-pixels to the | 
| 265 | 
> | 
         * resolution.  During sampling, we check super-pixels to the | 
| 266 | 
  | 
         * right and above by calling bigdiff().  If there is a significant | 
| 267 | 
  | 
         * difference, we subsample the super-pixels.  The testing process | 
| 268 | 
  | 
         * includes initialization of the next row. | 
| 269 | 
  | 
         */ | 
| 270 | 
< | 
        xsiz = (((pframe.r-pframe.l)<<pdepth)+hresolu-1) / hresolu; | 
| 271 | 
< | 
        ysiz = (((pframe.u-pframe.d)<<pdepth)+vresolu-1) / vresolu; | 
| 297 | 
< | 
        rl = (RECT *)malloc(xsiz*sizeof(RECT)); | 
| 298 | 
< | 
        if (rl == NULL) | 
| 299 | 
< | 
                return; | 
| 270 | 
> | 
        xsiz = (((long)(pframe.r-pframe.l)<<pdepth)+hresolu-1) / hresolu; | 
| 271 | 
> | 
        ysiz = (((long)(pframe.u-pframe.d)<<pdepth)+vresolu-1) / vresolu; | 
| 272 | 
  | 
        pl = (PNODE **)malloc(xsiz*sizeof(PNODE *)); | 
| 273 | 
  | 
        if (pl == NULL) | 
| 274 | 
  | 
                return; | 
| 275 | 
  | 
        /* | 
| 276 | 
  | 
         * Initialize the bottom row. | 
| 277 | 
  | 
         */ | 
| 278 | 
< | 
        rl[0].l = rl[0].d = 0; | 
| 307 | 
< | 
        rl[0].r = hresolu; rl[0].u = vresolu; | 
| 308 | 
< | 
        pl[0] = findrect(pframe.l, pframe.d, &ptrunk, rl, pdepth); | 
| 278 | 
> | 
        pl[0] = findrect(pframe.l, pframe.d, &ptrunk, pdepth); | 
| 279 | 
  | 
        for (x = 1; x < xsiz; x++) { | 
| 310 | 
– | 
                rl[x].l = rl[x].d = 0; | 
| 311 | 
– | 
                rl[x].r = hresolu; rl[x].u = vresolu; | 
| 280 | 
  | 
                pl[x] = findrect(pframe.l+((x*hresolu)>>pdepth), | 
| 281 | 
< | 
                                pframe.d, &ptrunk, rl+x, pdepth); | 
| 281 | 
> | 
                                pframe.d, &ptrunk, pdepth); | 
| 282 | 
  | 
        } | 
| 283 | 
  | 
                                                /* sample the image */ | 
| 284 | 
  | 
        for (y = 0; /* y < ysiz */ ; y++) { | 
| 290 | 
  | 
                         */ | 
| 291 | 
  | 
                        if (pl[x] != pl[x+1] && bigdiff(pl[x]->v, | 
| 292 | 
  | 
                                        pl[x+1]->v, maxdiff)) { | 
| 293 | 
< | 
                                refine(pl[x], rl[x].l, rl[x].d, | 
| 294 | 
< | 
                                                rl[x].r, rl[x].u, 1); | 
| 327 | 
< | 
                                refine(pl[x+1], rl[x+1].l, rl[x+1].d, | 
| 328 | 
< | 
                                                rl[x+1].r, rl[x+1].u, 1); | 
| 293 | 
> | 
                                refine(pl[x], 1); | 
| 294 | 
> | 
                                refine(pl[x+1], 1); | 
| 295 | 
  | 
                        } | 
| 296 | 
  | 
                } | 
| 297 | 
  | 
                if (y >= ysiz-1) | 
| 302 | 
  | 
                        /* | 
| 303 | 
  | 
                         * Find super-pixel at this position in next row. | 
| 304 | 
  | 
                         */ | 
| 339 | 
– | 
                        r.l = r.d = 0; | 
| 340 | 
– | 
                        r.r = hresolu; r.u = vresolu; | 
| 305 | 
  | 
                        p = findrect(pframe.l+((x*hresolu)>>pdepth), | 
| 306 | 
  | 
                                pframe.d+(((y+1)*vresolu)>>pdepth), | 
| 307 | 
< | 
                                        &ptrunk, &r, pdepth); | 
| 307 | 
> | 
                                        &ptrunk, pdepth); | 
| 308 | 
  | 
                        /* | 
| 309 | 
  | 
                         * Test super-pixel in next row. | 
| 310 | 
  | 
                         */ | 
| 311 | 
  | 
                        if (pl[x] != p && bigdiff(pl[x]->v, p->v, maxdiff)) { | 
| 312 | 
< | 
                                refine(pl[x], rl[x].l, rl[x].d, | 
| 313 | 
< | 
                                                rl[x].r, rl[x].u, 1); | 
| 350 | 
< | 
                                refine(p, r.l, r.d, r.r, r.u, 1); | 
| 312 | 
> | 
                                refine(pl[x], 1); | 
| 313 | 
> | 
                                refine(p, 1); | 
| 314 | 
  | 
                        } | 
| 315 | 
  | 
                        /* | 
| 316 | 
  | 
                         * Copy into super-pixel array. | 
| 317 | 
  | 
                         */ | 
| 355 | 
– | 
                        rl[x].l = r.l; rl[x].d = r.d; | 
| 356 | 
– | 
                        rl[x].r = r.r; rl[x].u = r.u; | 
| 318 | 
  | 
                        pl[x] = p; | 
| 319 | 
  | 
                } | 
| 320 | 
  | 
        } | 
| 321 | 
  | 
escape: | 
| 322 | 
< | 
        free((char *)rl); | 
| 362 | 
< | 
        free((char *)pl); | 
| 322 | 
> | 
        free((void *)pl); | 
| 323 | 
  | 
} | 
| 324 | 
  | 
 | 
| 325 | 
  | 
 | 
| 326 | 
  | 
int | 
| 327 | 
< | 
refine(p, xmin, ymin, xmax, ymax, pd)           /* refine a node */ | 
| 328 | 
< | 
register PNODE  *p; | 
| 329 | 
< | 
int  xmin, ymin, xmax, ymax; | 
| 330 | 
< | 
int  pd; | 
| 327 | 
> | 
refine(                         /* refine a node */ | 
| 328 | 
> | 
        PNODE   *p, | 
| 329 | 
> | 
        int  pd | 
| 330 | 
> | 
) | 
| 331 | 
  | 
{ | 
| 332 | 
  | 
        int  growth; | 
| 333 | 
  | 
        int  mx, my; | 
| 339 | 
  | 
        if (pd <= 0)                            /* depth limit */ | 
| 340 | 
  | 
                return(0); | 
| 341 | 
  | 
 | 
| 342 | 
< | 
        mx = (xmin + xmax) >> 1; | 
| 343 | 
< | 
        my = (ymin + ymax) >> 1; | 
| 342 | 
> | 
        mx = (p->xmin + p->xmax) >> 1; | 
| 343 | 
> | 
        my = (p->ymin + p->ymax) >> 1; | 
| 344 | 
  | 
        growth = 0; | 
| 345 | 
  | 
 | 
| 346 | 
  | 
        if (p->kid == NULL) {                   /* subdivide */ | 
| 347 | 
  | 
 | 
| 348 | 
  | 
                if ((p->kid = newptree()) == NULL) | 
| 349 | 
< | 
                        return(growth); | 
| 349 | 
> | 
                        return(0); | 
| 350 | 
> | 
 | 
| 351 | 
> | 
                p->kid[UR].xmin = mx; | 
| 352 | 
> | 
                p->kid[UR].ymin = my; | 
| 353 | 
> | 
                p->kid[UR].xmax = p->xmax; | 
| 354 | 
> | 
                p->kid[UR].ymax = p->ymax; | 
| 355 | 
> | 
                p->kid[UL].xmin = p->xmin; | 
| 356 | 
> | 
                p->kid[UL].ymin = my; | 
| 357 | 
> | 
                p->kid[UL].xmax = mx; | 
| 358 | 
> | 
                p->kid[UL].ymax = p->ymax; | 
| 359 | 
> | 
                p->kid[DR].xmin = mx; | 
| 360 | 
> | 
                p->kid[DR].ymin = p->ymin; | 
| 361 | 
> | 
                p->kid[DR].xmax = p->xmax; | 
| 362 | 
> | 
                p->kid[DR].ymax = my; | 
| 363 | 
> | 
                p->kid[DL].xmin = p->xmin; | 
| 364 | 
> | 
                p->kid[DL].ymin = p->ymin; | 
| 365 | 
> | 
                p->kid[DL].xmax = mx; | 
| 366 | 
> | 
                p->kid[DL].ymax = my; | 
| 367 | 
  | 
                /* | 
| 368 | 
  | 
                 *  The following paint order can leave a black pixel | 
| 369 | 
< | 
                 *  when redraw() is called in (*dev->paintr)(). | 
| 369 | 
> | 
                 *  if redraw() is called in (*dev->paintr)(). | 
| 370 | 
  | 
                 */ | 
| 371 | 
  | 
                if (p->x >= mx && p->y >= my) | 
| 372 | 
  | 
                        pcopy(p, p->kid+UR); | 
| 373 | 
< | 
                else | 
| 374 | 
< | 
                        paint(p->kid+UR, mx, my, xmax, ymax); | 
| 373 | 
> | 
                else if (paint(p->kid+UR) < 0) | 
| 374 | 
> | 
                        quit(1); | 
| 375 | 
  | 
                if (p->x < mx && p->y >= my) | 
| 376 | 
  | 
                        pcopy(p, p->kid+UL); | 
| 377 | 
< | 
                else | 
| 378 | 
< | 
                        paint(p->kid+UL, xmin, my, mx, ymax); | 
| 377 | 
> | 
                else if (paint(p->kid+UL) < 0) | 
| 378 | 
> | 
                        quit(1); | 
| 379 | 
  | 
                if (p->x >= mx && p->y < my) | 
| 380 | 
  | 
                        pcopy(p, p->kid+DR); | 
| 381 | 
< | 
                else | 
| 382 | 
< | 
                        paint(p->kid+DR, mx, ymin, xmax, my); | 
| 381 | 
> | 
                else if (paint(p->kid+DR) < 0) | 
| 382 | 
> | 
                        quit(1); | 
| 383 | 
  | 
                if (p->x < mx && p->y < my) | 
| 384 | 
  | 
                        pcopy(p, p->kid+DL); | 
| 385 | 
< | 
                else | 
| 386 | 
< | 
                        paint(p->kid+DL, xmin, ymin, mx, my); | 
| 385 | 
> | 
                else if (paint(p->kid+DL) < 0) | 
| 386 | 
> | 
                        quit(1); | 
| 387 | 
  | 
 | 
| 388 | 
  | 
                growth++; | 
| 389 | 
  | 
        } | 
| 390 | 
  | 
                                                /* do children */ | 
| 391 | 
  | 
        if (mx > pframe.l) { | 
| 392 | 
  | 
                if (my > pframe.d) | 
| 393 | 
< | 
                        growth += refine(p->kid+DL, xmin, ymin, mx, my, pd-1); | 
| 393 | 
> | 
                        growth += refine(p->kid+DL, pd-1); | 
| 394 | 
  | 
                if (my < pframe.u) | 
| 395 | 
< | 
                        growth += refine(p->kid+UL, xmin, my, mx, ymax, pd-1); | 
| 395 | 
> | 
                        growth += refine(p->kid+UL, pd-1); | 
| 396 | 
  | 
        } | 
| 397 | 
  | 
        if (mx < pframe.r) { | 
| 398 | 
  | 
                if (my > pframe.d) | 
| 399 | 
< | 
                        growth += refine(p->kid+DR, mx, ymin, xmax, my, pd-1); | 
| 399 | 
> | 
                        growth += refine(p->kid+DR, pd-1); | 
| 400 | 
  | 
                if (my < pframe.u) | 
| 401 | 
< | 
                        growth += refine(p->kid+UR, mx, my, xmax, ymax, pd-1); | 
| 425 | 
< | 
        } | 
| 426 | 
< | 
                                                /* recompute sum */ | 
| 427 | 
< | 
        if (growth) { | 
| 428 | 
< | 
                setcolor(p->v, 0.0, 0.0, 0.0); | 
| 429 | 
< | 
                for (i = 0; i < 4; i++) | 
| 430 | 
< | 
                        addcolor(p->v, p->kid[i].v); | 
| 431 | 
< | 
                scalecolor(p->v, 0.25); | 
| 401 | 
> | 
                        growth += refine(p->kid+UR, pd-1); | 
| 402 | 
  | 
        } | 
| 403 | 
  | 
        return(growth); | 
| 404 | 
  | 
} |