| 1 | #ifndef lint | 
| 2 | static const char       RCSid[] = "$Id: ambio.c,v 2.16 2023/12/11 23:57:32 greg Exp $"; | 
| 3 | #endif | 
| 4 | /* | 
| 5 | * Read and write portable ambient values | 
| 6 | * | 
| 7 | *  Declarations of external symbols in ambient.h | 
| 8 | */ | 
| 9 |  | 
| 10 | #include "copyright.h" | 
| 11 |  | 
| 12 | #include "ray.h" | 
| 13 | #include "ambient.h" | 
| 14 |  | 
| 15 |  | 
| 16 | int     *AMB_CNDX = CNDX;       /* open ambient file RGBE indices */ | 
| 17 | float   *AMB_WLPART = WLPART;   /* open ambient file limits+partitions (nm) */ | 
| 18 |  | 
| 19 |  | 
| 20 | #define  badflt(x)      (((x) < -FHUGE) | ((x) > FHUGE)) | 
| 21 |  | 
| 22 | #define  badvec(v)      (badflt((v)[0]) | badflt((v)[1]) | badflt((v)[2])) | 
| 23 |  | 
| 24 |  | 
| 25 | int | 
| 26 | amb_headline(           /* check ambient headline (copy to file if *p) */ | 
| 27 | char *hl, | 
| 28 | void *p | 
| 29 | ) | 
| 30 | { | 
| 31 | static int      ambcndx[4]; | 
| 32 | static float    ambwlpart[4]; | 
| 33 | FILE            *fout = (FILE *)p; | 
| 34 | char            fmt[MAXFMTLEN]; | 
| 35 |  | 
| 36 | if (formatval(fmt, hl)) { | 
| 37 | if (strcmp(fmt, AMBFMT)) | 
| 38 | return(-1); | 
| 39 | return(0); | 
| 40 | } | 
| 41 | if (isncomp(hl)) { | 
| 42 | ambcndx[3] = ncompval(hl); | 
| 43 | if ((ambcndx[3] < 3) | (ambcndx[3] > MAXCSAMP)) | 
| 44 | return(-1); | 
| 45 | AMB_CNDX = ambcndx; | 
| 46 | return(1); | 
| 47 | } | 
| 48 | if (iswlsplit(hl)) { | 
| 49 | if (!wlsplitval(ambwlpart, hl)) | 
| 50 | return(-1); | 
| 51 | AMB_WLPART = ambwlpart; | 
| 52 | return(1); | 
| 53 | } | 
| 54 | if (fout) | 
| 55 | fputs(hl, fout); | 
| 56 | return(0); | 
| 57 | } | 
| 58 |  | 
| 59 |  | 
| 60 | void | 
| 61 | putambmagic(fp)                 /* write out ambient value magic number */ | 
| 62 | FILE  *fp; | 
| 63 | { | 
| 64 | putint(AMBMAGIC, 2, fp); | 
| 65 | } | 
| 66 |  | 
| 67 |  | 
| 68 | int | 
| 69 | hasambmagic(fp)                 /* read in and check validity of magic # */ | 
| 70 | FILE  *fp; | 
| 71 | { | 
| 72 | int  magic; | 
| 73 |  | 
| 74 | magic = getint(2, fp); | 
| 75 | if (feof(fp)) | 
| 76 | return(0); | 
| 77 | return(magic == AMBMAGIC); | 
| 78 | } | 
| 79 |  | 
| 80 |  | 
| 81 | #define  putpos(v,fp)   putflt((v)[0],fp);putflt((v)[1],fp);putflt((v)[2],fp) | 
| 82 |  | 
| 83 | #define  getpos(v,fp)   (v)[0]=getflt(fp);(v)[1]=getflt(fp);(v)[2]=getflt(fp) | 
| 84 |  | 
| 85 | #define  putv2(v2,fp)   putflt((v2)[0],fp);putflt((v2)[1],fp) | 
| 86 |  | 
| 87 | #define  getv2(v2,fp)   (v2)[0]=getflt(fp);(v2)[1]=getflt(fp) | 
| 88 |  | 
| 89 | int | 
| 90 | writambval(                     /* write ambient value to stream */ | 
| 91 | AMBVAL  *av, | 
| 92 | FILE  *fp | 
| 93 | ) | 
| 94 | { | 
| 95 | SCOLR  sclr; | 
| 96 |  | 
| 97 | putint(av->lvl, 1, fp); | 
| 98 | putflt(av->weight, fp); | 
| 99 | putpos(av->pos, fp); | 
| 100 | putint(av->ndir, sizeof(av->ndir), fp); | 
| 101 | putint(av->udir, sizeof(av->udir), fp); | 
| 102 | putv2(av->rad, fp); | 
| 103 | putv2(av->gpos, fp); | 
| 104 | putv2(av->gdir, fp); | 
| 105 | putint(av->corral, sizeof(av->corral), fp); | 
| 106 | if ((AMB_CNDX == CNDX) & (AMB_WLPART == WLPART)) { | 
| 107 | scolor_scolr(sclr, av->val); | 
| 108 | } else { | 
| 109 | SCOLOR  scol; | 
| 110 | convertscolor(scol, AMB_CNDX[3], AMB_WLPART[0], AMB_WLPART[3], | 
| 111 | av->val, NCSAMP, WLPART[0], WLPART[3]); | 
| 112 | scolor2scolr(sclr, scol, AMB_CNDX[3]); | 
| 113 | } | 
| 114 | putbinary(sclr, AMB_CNDX[3]+1, 1, fp); | 
| 115 |  | 
| 116 | return(ferror(fp) ? -1 : 0); | 
| 117 | } | 
| 118 |  | 
| 119 |  | 
| 120 | int | 
| 121 | ambvalOK(                       /* check consistency of ambient value */ | 
| 122 | AMBVAL  *av | 
| 123 | ) | 
| 124 | { | 
| 125 | int     i; | 
| 126 |  | 
| 127 | if (badvec(av->pos)) return(0); | 
| 128 | if (!av->ndir | !av->udir) return(0); | 
| 129 | if ((av->weight <= 0.) | (av->weight > 1.)) return(0); | 
| 130 | if ((av->rad[0] <= 0.) | (av->rad[0] >= FHUGE)) return(0); | 
| 131 | if ((av->rad[1] <= 0.) | (av->rad[1] >= FHUGE)) return(0); | 
| 132 | if (av->rad[0] > av->rad[1]+FTINY) return(0); | 
| 133 | if (badflt(av->gpos[0]) | badflt(av->gpos[1])) return(0); | 
| 134 | if (badflt(av->gdir[0]) | badflt(av->gdir[1])) return(0); | 
| 135 | for (i = NCSAMP; i-- > 0; ) | 
| 136 | if ((av->val[i] < 0.) | (av->val[i] >= FHUGE)) | 
| 137 | return(0); | 
| 138 | return(1); | 
| 139 | } | 
| 140 |  | 
| 141 |  | 
| 142 | int | 
| 143 | readambval(                     /* read ambient value from stream */ | 
| 144 | AMBVAL  *av, | 
| 145 | FILE  *fp | 
| 146 | ) | 
| 147 | { | 
| 148 | SCOLR  sclr; | 
| 149 |  | 
| 150 | av->lvl = getint(1, fp) & 0xff; | 
| 151 | if (feof(fp)) | 
| 152 | return(0); | 
| 153 | av->weight = getflt(fp); | 
| 154 | getpos(av->pos, fp); | 
| 155 | av->ndir = getint(sizeof(av->ndir), fp); | 
| 156 | av->udir = getint(sizeof(av->udir), fp); | 
| 157 | getv2(av->rad, fp); | 
| 158 | getv2(av->gpos, fp); | 
| 159 | getv2(av->gdir, fp); | 
| 160 | av->corral = (uint32)getint(sizeof(av->corral), fp); | 
| 161 | if (getbinary(sclr, AMB_CNDX[3]+1, 1, fp) != 1) | 
| 162 | return(0); | 
| 163 | if ((AMB_CNDX == CNDX) & (AMB_WLPART == WLPART)) { | 
| 164 | scolr_scolor(av->val, sclr); | 
| 165 | } else { | 
| 166 | SCOLOR  scol; | 
| 167 | scolr2scolor(scol, sclr, AMB_CNDX[3]); | 
| 168 | convertscolorcol(av->val, scol, AMB_CNDX[3], | 
| 169 | AMB_WLPART[0], AMB_WLPART[3]); | 
| 170 | } | 
| 171 | return(feof(fp) ? 0 : ambvalOK(av)); | 
| 172 | } |