BRL-CAD
mater.c
Go to the documentation of this file.
1 /* M A T E R . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1985-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @addtogroup librt */
21 /** @{ */
22 /** @file librt/mater.c
23  *
24  * Code to deal with establishing and maintaining the tables which map
25  * region ID codes into worthwhile material information (colors and
26  * outboard database "handles").
27  *
28  * These really are "db_" routines, more fundamental than "rt_".
29  *
30  */
31 /** @} */
32 
33 #include "common.h"
34 
35 #include "bio.h"
36 
37 #include "vmath.h"
38 #include "raytrace.h"
39 #include "mater.h"
40 
41 
42 /*
43  * It is expected that entries on this mater list will be sorted in
44  * strictly ascending order, with no overlaps (i.e., monotonically
45  * increasing).
46  */
47 static struct mater *material_head = MATER_NULL;
48 
49 
50 void
51 rt_pr_mater(register const struct mater *mp)
52 {
53  bu_log("%5d..%d\t", mp->mt_low, mp->mt_high);
54  bu_log("%d, %d, %d\t", mp->mt_r, mp->mt_g, mp->mt_b);
55 }
56 
57 
58 HIDDEN void
59 _rt_check_overlap(struct mater *newp)
60 {
61  struct mater *zot;
62 
63  /* Check for overlap, i.e., redefinition of following colors */
64  while (newp->mt_forw != MATER_NULL &&
65  newp->mt_high >= newp->mt_forw->mt_low)
66  {
67  if (newp->mt_high >= newp->mt_forw->mt_high) {
68  /* Drop this mater struct */
69  zot = newp->mt_forw;
70  newp->mt_forw = zot->mt_forw;
71  bu_log("dropping overlapping region-id based material property entry:\n");
72  rt_pr_mater(zot);
73  bu_free((char *)zot, "getstruct mater");
74  continue;
75  }
76  if (newp->mt_high >= newp->mt_forw->mt_low) {
77  /* Shorten this mater struct, then done */
78  bu_log("Shortening region-id based material property entry rhs range, from:\n");
79  rt_pr_mater(newp->mt_forw);
80  bu_log("to:\n");
81  newp->mt_forw->mt_low = newp->mt_high+1;
82  rt_pr_mater(newp->mt_forw);
83  continue; /* more conservative than returning */
84  }
85  }
86 }
87 
88 
89 /**
90  * While any additional database records are created and written here,
91  * it is the responsibility of the caller to color_putrec(newp) if
92  * needed.
93  */
94 void
95 rt_insert_color(struct mater *newp)
96 {
97  struct mater *mp;
98  struct mater *zot;
99 
100  if (material_head == MATER_NULL || newp->mt_high < material_head->mt_low) {
101  /* Insert at head of list */
102  newp->mt_forw = material_head;
103  material_head = newp;
104  return;
105  }
106  if (newp->mt_low < material_head->mt_low) {
107  /* Insert at head of list, check for redefinition */
108  newp->mt_forw = material_head;
109  material_head = newp;
110  _rt_check_overlap(newp);
111  return;
112  }
113  for (mp = material_head; mp != MATER_NULL; mp = mp->mt_forw) {
114  if (mp->mt_low == newp->mt_low && mp->mt_high <= newp->mt_high) {
115  bu_log("dropping overwritten region-id based material property entry:\n");
116  newp->mt_forw = mp->mt_forw;
117  rt_pr_mater(mp);
118  *mp = *newp; /* struct copy */
119  bu_free((char *)newp, "getstruct mater");
120  newp = mp;
121  _rt_check_overlap(newp);
122  return;
123  }
124  if (mp->mt_low < newp->mt_low && mp->mt_high > newp->mt_high) {
125  /* New range entirely contained in old range; split */
126  bu_log("Splitting region-id based material property entry into 3 ranges\n");
127  BU_ALLOC(zot, struct mater);
128  *zot = *mp; /* struct copy */
129  zot->mt_daddr = MATER_NO_ADDR;
130  /* zot->mt_high = mp->mt_high; */
131  zot->mt_low = newp->mt_high+1;
132  mp->mt_high = newp->mt_low-1;
133  /* mp, newp, zot */
134  /* zot->mt_forw = mp->mt_forw; */
135  newp->mt_forw = zot;
136  mp->mt_forw = newp;
137  rt_pr_mater(mp);
138  rt_pr_mater(newp);
139  rt_pr_mater(zot);
140  return;
141  }
142  if (mp->mt_high > newp->mt_low) {
143  /* Overlap to the left: Shorten preceding entry */
144  bu_log("Shortening region-id based material property entry lhs range, from:\n");
145  rt_pr_mater(mp);
146  bu_log("to:\n");
147  mp->mt_high = newp->mt_low-1;
148  rt_pr_mater(mp);
149  /* Now append */
150  newp->mt_forw = mp->mt_forw;
151  mp->mt_forw = newp;
152  _rt_check_overlap(newp);
153  return;
154  }
155  if (mp->mt_forw == MATER_NULL ||
156  newp->mt_low < mp->mt_forw->mt_low) {
157  /* Append */
158  newp->mt_forw = mp->mt_forw;
159  mp->mt_forw = newp;
160  _rt_check_overlap(newp);
161  return;
162  }
163  }
164  bu_log("fell out of rt_insert_color loop, append region-id based material property entry to end of list\n");
165  /* Append at end */
166  newp->mt_forw = MATER_NULL;
167  mp->mt_forw = newp;
168  return;
169 }
170 
171 
172 /**
173  * Called from db_scan() when initially scanning database.
174  */
175 void
176 rt_color_addrec(int low, int hi, int r, int g, int b, off_t addr)
177 {
178  register struct mater *mp;
179 
180  BU_ALLOC(mp, struct mater);
181  mp->mt_low = low;
182  mp->mt_high = hi;
183  mp->mt_r = r;
184  mp->mt_g = g;
185  mp->mt_b = b;
186  mp->mt_daddr = addr;
187  rt_insert_color(mp);
188 }
189 
190 
191 /**
192  * If the GIFT regionid of this region falls into a mapped area of
193  * regionid-driven color override.
194  */
195 void
196 rt_region_color_map(register struct region *regp)
197 {
198  register struct mater *mp;
199 
200  if (regp == REGION_NULL) {
201  bu_log("color_map(NULL)\n");
202  return;
203  }
204  for (mp = material_head; mp != MATER_NULL; mp = mp->mt_forw) {
205  if (regp->reg_regionid <= mp->mt_high &&
206  regp->reg_regionid >= mp->mt_low) {
207  regp->reg_mater.ma_color_valid = 1;
208  regp->reg_mater.ma_color[0] =
209  (((double)mp->mt_r)+0.5) / 255.0;
210  regp->reg_mater.ma_color[1] =
211  (((double)mp->mt_g)+0.5) / 255.0;
212  regp->reg_mater.ma_color[2] =
213  (((double)mp->mt_b)+0.5) / 255.0;
214  return;
215  }
216  }
217 }
218 
219 
220 void
222 {
223  struct mater *mp;
224 
225  BU_CK_VLS(str);
226 
227  for (mp = material_head; mp != MATER_NULL; mp = mp->mt_forw) {
228  bu_vls_printf(str,
229  "{%d %d %d %d %d} ",
230  mp->mt_low,
231  mp->mt_high,
232  mp->mt_r,
233  mp->mt_g,
234  mp->mt_b);
235  }
236 }
237 
238 
239 /**
240  * returns the material linked list head node
241  */
242 struct mater *
244 {
245  return material_head;
246 }
247 
248 
249 /**
250  * set the material linked list head node
251  */
252 void
253 rt_new_material_head(struct mater *newmat)
254 {
255  material_head = newmat;
256 }
257 
258 
259 /**
260  * returns a copy of the material linked list head node
261  */
262 struct mater *
264 {
265  register struct mater *mp = NULL;
266  register struct mater *newmp = NULL;
267  struct mater *newmater = NULL;
268  struct mater *dupmater = NULL;
269 
270  mp = material_head;
271  while (mp != MATER_NULL) {
272  BU_ALLOC(newmater, struct mater);
273  *newmater = *mp; /* struct copy */
274  newmater->mt_forw = MATER_NULL;
275 
276  if (dupmater == NULL) {
277  dupmater = newmater;
278  } else {
279  newmp->mt_forw = newmater;
280  }
281 
282  newmp = newmater;
283  mp = mp->mt_forw;
284  }
285 
286  return dupmater;
287 }
288 
289 
290 /**
291  * Really should be db_color_free(). Called from db_close().
292  */
293 void
295 {
296  register struct mater *mp;
297 
298  while ((mp = material_head) != MATER_NULL) {
299  material_head = mp->mt_forw; /* Dequeue 'mp' */
300  /* mt_handle? */
301  bu_free((char *)mp, "getstruct mater");
302  mp = MATER_NULL;
303  }
304 }
305 
306 
307 /*
308  * Local Variables:
309  * mode: C
310  * tab-width: 8
311  * indent-tabs-mode: t
312  * c-file-style: "stroustrup"
313  * End:
314  * ex: shiftwidth=4 tabstop=8
315  */
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
void rt_pr_mater(register const struct mater *mp)
Definition: mater.c:51
void rt_region_color_map(register struct region *regp)
Definition: mater.c:196
HIDDEN void _rt_check_overlap(struct mater *newp)
Definition: mater.c:59
Header file for the BRL-CAD common definitions.
char ma_color_valid
non-0 ==> ma_color is non-default
Definition: raytrace.h:524
#define HIDDEN
Definition: common.h:86
void rt_color_addrec(int low, int hi, int r, int g, int b, off_t addr)
Definition: mater.c:176
void rt_insert_color(struct mater *newp)
Definition: mater.c:95
#define BU_CK_VLS(_vp)
Definition: vls.h:69
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
int reg_regionid
Region ID code. If <=0, use reg_aircode.
Definition: raytrace.h:542
void rt_vls_color_map(struct bu_vls *str)
Definition: mater.c:221
void rt_new_material_head(struct mater *newmat)
Definition: mater.c:253
struct mater * rt_material_head(void)
Definition: mater.c:243
float ma_color[3]
explicit color: 0..1
Definition: raytrace.h:522
struct mater_info reg_mater
Real material information.
Definition: raytrace.h:546
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
#define REGION_NULL
Definition: raytrace.h:558
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
struct mater * rt_dup_material_head(void)
Definition: mater.c:263
Definition: vls.h:56
void rt_color_free(void)
Definition: mater.c:294