BRL-CAD
sh_prj.c
Go to the documentation of this file.
1 /* S H _ P R J . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-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 /** @file liboptical/sh_prj.c
21  *
22  * Projection shader
23  *
24  * The one parameter to this shader is a filename. The named file
25  * contains the REAL parameters to the shader. The v4 database format
26  * is far too anemic to support this sort of shader.
27  *
28  */
29 
30 #include "common.h"
31 
32 #include <stddef.h>
33 #include <stdio.h>
34 #include <fcntl.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <math.h>
40 
41 #include "vmath.h"
42 #include "raytrace.h"
43 #include "optical.h"
44 #include "plot3.h"
45 
46 
47 #define prj_MAGIC 0x70726a00 /* "prj" */
48 #define CK_prj_SP(_p) BU_CKMAG(_p, prj_MAGIC, "prj_specific")
49 
50 struct img_specific {
51  struct bu_list l;
52  unsigned long junk;
53  struct bu_vls i_name; /* name of object or file (depending on i_datasrc flag) */
54 #define IMG_SRC_FILE 'f'
55 #define IMG_SRC_OBJECT 'o'
56 #define IMG_SRC_AUTO 0
57  char i_datasrc; /* is the datasource a file/object or automatic */
58  struct bu_mapped_file *i_data; /* mapped file when IMG_SRC_FILE */
59  struct rt_binunif_internal *i_binunifp; /* db internal object when IMG_SRC_OBJECT */
60  unsigned char *i_img;
61  int i_width;
62  int i_height;
64  point_t i_eye_pt;
65  quat_t i_orient;
66  mat_t i_mat; /* computed from i_orient */
67  mat_t i_bn_mat_inv; /* computed (for debug) */
68  plane_t i_plane; /* dir/plane of projection */
69  mat_t i_sh_to_img; /* transform used in prj_render() */
70  char i_through; /* ignore surface normal */
71  char i_antialias; /* anti-alias texture */
72  char i_behind; /* shade points behind img plane */
73  fastf_t i_perspective; /* perspective angle 0=ortho */
74 };
75 #define IMG_MAGIC 0x696d6700 /* "img" */
76 #define IMG_SPECIFIC_INIT_ZERO {BU_LIST_INIT_ZERO, 0, BU_VLS_INIT_ZERO, '\0', NULL, NULL, NULL, 0, 0, 0.0, VINIT_ZERO, HINIT_ZERO, MAT_INIT_IDN, MAT_INIT_IDN, HINIT_ZERO, MAT_INIT_IDN, '\0', '\0', '\0', 0.0}
77 
78 
79 /**
80  * the shader specific structure contains all variables which are unique
81  * to any particular use of the shader.
82  */
83 struct prj_specific {
84  uint32_t magic;
86  mat_t prj_m_to_sh;
87  FILE *prj_plfd;
88 };
89 
90 
91 /**
92  * img_source_hook() is used to record where the image datasource is coming from
93  * so that the image may be loaded automatically as needed from either a file or
94  * from a database-embedded binary object.
95  */
96 HIDDEN void
98  const char *sp_name,
99  void *base,
100  const char *UNUSED(value),
101  void *UNUSED(data))
102 {
103  struct img_specific *imageSpecific = (struct img_specific *)base;
104  if (bu_strncmp(sp_name, "file", 4) == 0) {
105  imageSpecific->i_datasrc=IMG_SRC_FILE;
106  } else if (bu_strncmp(sp_name, "obj", 3) == 0) {
107  imageSpecific->i_datasrc=IMG_SRC_OBJECT;
108  } else {
109  imageSpecific->i_datasrc=IMG_SRC_AUTO;
110  }
111 }
112 
113 
114 /**
115  * This is a helper routine used in prj_setup() to load a projection image
116  * either from a file or from a db object.
117  */
118 HIDDEN int
119 img_load_datasource(struct img_specific *image, struct db_i *dbInstance, const unsigned long int size)
120 {
121  struct directory *dirEntry;
122 
123  RT_CK_DBI(dbInstance);
124 
125  if (image == (struct img_specific *)NULL) {
126  bu_bomb("ERROR: img_load_datasource() received NULL arg (struct img_specific *)\n");
127  }
128 
129  bu_log("Loading image %s [%s]...", image->i_datasrc==IMG_SRC_AUTO?"from auto-determined datasource":image->i_datasrc==IMG_SRC_OBJECT?"from a database object":image->i_datasrc==IMG_SRC_FILE?"from a file":"from an unknown source (ERROR)", bu_vls_addr(&image->i_name));
130 
131  /* if the source is auto or object, we try to load the object */
132  if ((image->i_datasrc==IMG_SRC_AUTO) || (image->i_datasrc==IMG_SRC_OBJECT)) {
133 
134  /* see if the object exists */
135  if ((dirEntry=db_lookup(dbInstance, bu_vls_addr(&image->i_name), LOOKUP_QUIET)) == RT_DIR_NULL) {
136 
137  /* unable to find the image object */
138  if (image->i_datasrc!=IMG_SRC_AUTO) {
139  return -1;
140  }
141  } else {
142  struct rt_db_internal *dbip;
143 
144  BU_ALLOC(dbip, struct rt_db_internal);
145 
146  RT_DB_INTERNAL_INIT(dbip);
147  RT_CK_DB_INTERNAL(dbip);
148  RT_CK_DIR(dirEntry);
149 
150  /* the object was in the directory, so go get it */
151  if (rt_db_get_internal(dbip, dirEntry, dbInstance, NULL, NULL) <= 0) {
152  /* unable to load/create the image database record object */
153  return -1;
154  }
155 
156  RT_CK_DB_INTERNAL(dbip);
157  RT_CK_BINUNIF(dbip->idb_ptr);
158 
159  /* keep the binary object pointer */
160  image->i_binunifp=(struct rt_binunif_internal *)dbip->idb_ptr; /* make it so */
161 
162  /* release the database struct we created */
163  RT_DB_INTERNAL_INIT(dbip);
164  bu_free(dbip, "img_load_datasource");
165 
166  /* check size of object */
167  if (image->i_binunifp->count < size) {
168  bu_log("\nWARNING: %s needs %d bytes, binary object only has %zu\n", bu_vls_addr(&image->i_name), size, image->i_binunifp->count);
169  } else if (image->i_binunifp->count > size) {
170  bu_log("\nWARNING: Binary object is larger than specified image size\n\tBinary Object: %lu pixels\n"
171  "\tSpecified Image Size: %zu pixels\n...continuing to load using image subsection...",
172  (unsigned long)image->i_binunifp->count);
173  }
174  image->i_img = (unsigned char *) image->i_binunifp->u.uint8;
175 
176  }
177  }
178 
179  /* if we are auto and we couldn't find a database object match, or if source
180  * is explicitly a file then we load the file.
181  */
182  if (((image->i_datasrc==IMG_SRC_AUTO) && (image->i_binunifp==NULL)) || (image->i_datasrc==IMG_SRC_FILE)) {
183 
184 
185  image->i_data = bu_open_mapped_file_with_path(dbInstance->dbi_filepath, bu_vls_addr(&image->i_name), NULL);
186 
187  if (image->i_data==NULL)
188  return -1; /* FAIL */
189 
190  if (image->i_data->buflen < size) {
191  bu_log("\nWARNING: %s needs %lu bytes, file only has %lu\n", bu_vls_addr(&image->i_name), size, image->i_data->buflen);
192  } else if (image->i_data->buflen > size) {
193  bu_log("\nWARNING: Image file size is larger than specified image size\n\tInput File: %zu pixels\n\tSpecified Image Size: %lu pixels\n...continuing to load using image subsection...", image->i_data->buflen, size);
194  }
195 
196  image->i_img = (unsigned char *) image->i_data->buf;
197  }
198 
199  bu_log("done.\n");
200 
201  return 0;
202 }
203 
204 
205 /**
206  * Bounds checking on perspective angle
207  */
208 HIDDEN void
209 persp_hook(const struct bu_structparse *UNUSED(sdp),
210  const char *UNUSED(name),
211  void *base,
212  const char *value,
213  void *UNUSED(data))
214 /* structure description */
215 /* struct member name */
216 /* beginning of structure */
217 /* string containing value */
218 {
219  struct img_specific *img_sp = (struct img_specific *)base;
220 
221  if (img_sp->i_perspective < 0.0) {
222  bu_log("perspective %s < 0.0\n", value);
223  bu_bomb("");
224  }
225 
226  if (img_sp->i_perspective > 180.0) {
227  bu_log("perspective %s > 180.\n", value);
228  bu_bomb("");
229  }
230 
231  if (!ZERO(img_sp->i_perspective))
232  bu_bomb("non-ortho perspective not yet implemented!\n");
233 }
234 
235 
236 /**
237  * Check for value < 0.0
238  */
239 HIDDEN void
240 dimen_hook(const struct bu_structparse *sdp,
241  const char *UNUSED(name),
242  void *base,
243  const char *value,
244  void *UNUSED(data))
245 /* structure description */
246 /* struct member name */
247 /* beginning of structure */
248 /* string containing value */
249 {
250  if (BU_STR_EQUAL("%f", sdp->sp_fmt)) {
251  fastf_t *f;
252  f = (fastf_t *)((char *)base + sdp->sp_offset);
253  if (*f < 0.0) {
254  bu_log("%s value %g(%s) < 0.0\n",
255  sdp->sp_name, *f, value);
256  bu_bomb("");
257  }
258  } else if (BU_STR_EQUAL("%d", sdp->sp_fmt)) {
259  int *i;
260  i = (int *)((char *)base + sdp->sp_offset);
261  if (*i < 0) {
262  bu_log("%s value %d(%s) < 0.0\n",
263  sdp->sp_name, *i, value);
264  bu_bomb("");
265  }
266  }
267 }
268 
269 
270 /**
271  * This routine is responsible for duplicating the image list head to make
272  * a new list element. It used to read in pixel data for an image (this is
273  * now done in the prj_setup() routine), and computes the matrix from the view
274  * quaternion.
275  *
276  * XXX "orient" MUST ALWAYS BE THE LAST PARAMETER SPECIFIED FOR EACH IMAGE.
277  */
278 static void
279 orient_hook(const struct bu_structparse *UNUSED(sdp),
280  const char *UNUSED(name),
281  void *base,
282  const char *UNUSED(value),
283  void *UNUSED(data))
284 /* structure description */
285 /* struct member name */
286 /* beginning of structure */
287 /* string containing value */
288 {
289  struct prj_specific *prj_sp;
290  struct img_specific *img_sp = (struct img_specific *)base;
291  struct img_specific *img_new;
292  mat_t trans, scale, tmp, xform;
293  vect_t v_tmp;
294  point_t p_tmp;
295 
296  BU_CK_LIST_HEAD(&img_sp->l);
297 
298  /* create a new img_specific struct,
299  * copy the parameters from the "head" into the new
300  * img_specific struct
301  */
302  BU_GET(img_new, struct img_specific);
303  memcpy(img_new, img_sp, sizeof(struct img_specific));
304  BU_LIST_MAGIC_SET(&img_new->l, IMG_MAGIC);
305  BU_CK_VLS(&img_sp->i_name);
306 
307  /* zero the filename for the next iteration */
308  bu_vls_init(&img_sp->i_name);
309 
310  /* Generate matrix from the quaternion */
311  quat_quat2mat(img_new->i_mat, img_new->i_orient);
312 
313 
314  /* compute matrix to transform region coordinates into
315  * shader projection coordinates:
316  *
317  * prj_coord = scale * rot * translate * region_coord
318  */
319  MAT_IDN(trans);
320  MAT_DELTAS_VEC_NEG(trans, img_new->i_eye_pt);
321 
322  MAT_IDN(scale);
323  MAT_SCALE_ALL(scale, img_new->i_viewsize);
324 
325  bn_mat_mul(tmp, img_new->i_mat, trans);
326  bn_mat_mul(img_new->i_sh_to_img, scale, tmp);
327 
328 
329  VSET(v_tmp, 0.0, 0.0, 1.0);
330 
331  /* compute inverse */
332  bn_mat_inv(img_new->i_bn_mat_inv, img_new->i_mat);
333  bn_mat_inv(xform, img_new->i_sh_to_img);
334 
335  MAT4X3VEC(img_new->i_plane, xform, v_tmp);
336  VUNITIZE(img_new->i_plane);
337 
338  if (rdebug&RDEBUG_SHADE) {
339  point_t pt;
340 
341  prj_sp = (struct prj_specific *)
342  ((struct prj_specific *)base - (bu_offsetof(struct prj_specific, prj_images)));
343  CK_prj_SP(prj_sp);
344 
345  if (!prj_sp->prj_plfd)
346  bu_bomb("prj shader prj_plfd should be open\n");
347 
348  /* plot out the extent of the image frame */
349  pl_color(prj_sp->prj_plfd, 255, 0, 0);
350 
351  VSET(v_tmp, -0.5, -0.5, 0.0);
352  MAT4X3PNT(pt, xform, v_tmp);
353  pdv_3move(prj_sp->prj_plfd, pt);
354 
355  VSET(v_tmp, 0.5, -0.5, 0.0);
356  MAT4X3PNT(p_tmp, xform, v_tmp);
357  pdv_3cont(prj_sp->prj_plfd, p_tmp);
358 
359  VSET(v_tmp, 0.5, 0.5, 0.0);
360  MAT4X3PNT(p_tmp, xform, v_tmp);
361  pdv_3cont(prj_sp->prj_plfd, p_tmp);
362 
363  VSET(v_tmp, -0.5, 0.5, 0.0);
364  MAT4X3PNT(p_tmp, xform, v_tmp);
365  pdv_3cont(prj_sp->prj_plfd, p_tmp);
366 
367  pdv_3cont(prj_sp->prj_plfd, pt);
368 
369  VSET(v_tmp, 0.0, 0.0, 0.0);
370  MAT4X3PNT(p_tmp, xform, v_tmp);
371  pdv_3move(prj_sp->prj_plfd, p_tmp);
372  VREVERSE(pt, img_new->i_plane);
373  VADD2(p_tmp, p_tmp, pt);
374  pdv_3cont(prj_sp->prj_plfd, p_tmp);
375 
376  }
377 
378  /* read in the pixel data now happens in prj_setup() */
379  /* we add an image to the list of images regardless of whether the data is valid or not */
380  BU_LIST_APPEND(&img_sp->l, &img_new->l);
381 }
382 
383 
384 #define IMG_O(m) bu_offsetof(struct img_specific, m)
385 
386 
387 /** description of how to parse/print the arguments to the shader.
388  * There is at least one line here for each variable in the shader specific
389  * structure above
390  */
392  {"%V", 1, "image", IMG_O(i_name), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
393  {"%V", 1, "file", IMG_O(i_name), img_source_hook, NULL, NULL },
394  {"%V", 1, "obj", IMG_O(i_name), img_source_hook, NULL, NULL },
395  {"%V", 1, "object", IMG_O(i_name), img_source_hook, NULL, NULL },
396  {"%d", 1, "w", IMG_O(i_width), dimen_hook, NULL, NULL },
397  {"%d", 1, "n", IMG_O(i_height), dimen_hook, NULL, NULL },
398  {"%f", 1, "viewsize", IMG_O(i_viewsize), dimen_hook, NULL, NULL },
399  {"%f", 3, "eye_pt", IMG_O(i_eye_pt), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
400  {"%f", 4, "orientation", IMG_O(i_orient), orient_hook, NULL, NULL },
401  {"%c", 1, "through", IMG_O(i_through), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
402  {"%c", 1, "antialias", IMG_O(i_antialias), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
403  {"%c", 1, "behind", IMG_O(i_behind), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
404  {"%f", 1, "perspective", IMG_O(i_perspective), persp_hook, NULL, NULL },
405  {"", 0, (char *)0, 0, BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }
406 };
408  {"%p", 1, "img_parse_tab", bu_byteoffset(img_parse_tab[0]), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
409  {"%f", 4, "i_plane", IMG_O(i_plane), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
410  {"", 0, (char *)0, 0, BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }
411 };
412 
413 
414 HIDDEN int prj_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *mfp, struct rt_i *rtip);
415 HIDDEN int prj_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp);
416 HIDDEN void prj_print(register struct region *rp, void *dp);
417 HIDDEN void prj_free(void *cp);
418 
419 /**
420  * The "mfuncs" structure defines the external interface to the shader.
421  * Note that more than one shader "name" can be associated with a given
422  * shader by defining more than one mfuncs struct in this array.
423  * See sh_phong.c for an example of building more than one shader "name"
424  * from a set of source functions. There you will find that "glass" "mirror"
425  * and "plastic" are all names for the same shader with different default
426  * values for the parameters.
427  */
428 struct mfuncs prj_mfuncs[] = {
429  {MF_MAGIC, "prj", 0, MFI_NORMAL|MFI_HIT|MFI_UV, 0,
430  prj_setup, prj_render, prj_print, prj_free },
431 
432  {0, (char *)0, 0, 0, 0,
433  0, 0, 0, 0 }
434 };
435 
436 
437 /**
438  * This routine is called (at prep time)
439  * once for each region which uses this shader.
440  * Any shader-specific initialization should be done here.
441  */
442 HIDDEN int
443 prj_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *UNUSED(mfp), struct rt_i *rtip)
444 /* pointer to reg_udata in *rp */
445 /* New since 4.4 release */
446 {
447  /* we use this to initialize new img_specific objects */
448  static const struct img_specific IMG_INIT = IMG_SPECIFIC_INIT_ZERO;
449 
450  struct prj_specific *prj_sp;
451  struct img_specific *img_sp;
452 
453  struct bu_vls parameter_data = BU_VLS_INIT_ZERO;
454  struct bu_mapped_file *parameter_file;
455 
456  /* check the arguments */
457  RT_CHECK_RTI(rtip);
458  BU_CK_VLS(matparm);
459  RT_CK_REGION(rp);
460 
461  if (rdebug&RDEBUG_SHADE)
462  bu_log("prj_setup(%s) matparm:\"%s\"\n",
463  rp->reg_name, bu_vls_addr(matparm));
464 
465  /* Get memory for the shader parameters and shader-specific data */
466  BU_GET(prj_sp, struct prj_specific);
467  *dpp = prj_sp;
468 
469  prj_sp->magic = prj_MAGIC;
470  memcpy(&prj_sp->prj_images, &IMG_INIT, sizeof(struct img_specific));
471  BU_LIST_INIT(&prj_sp->prj_images.l);
472 
473  if (rdebug&RDEBUG_SHADE) {
474  if ((prj_sp->prj_plfd=fopen("prj.plot3", "wb")) == (FILE *)NULL) {
475  bu_log("ERROR creating plot3 file prj.plot3");
476  }
477  } else {
478  prj_sp->prj_plfd = (FILE *)NULL;
479  }
480 
481  if (! *(bu_vls_addr(matparm))) {
482  bu_log("ERROR: Null projection shader file or options?\n");
483  return -1;
484  }
485 
486  /* first we try to open the specified argument as a file, as previously implemented.
487  * if it succeeds, then the file contents become the parameter data. Otherwise, the
488  * argument string considered the parameter data.
489  */
490 
491  parameter_file = bu_open_mapped_file(bu_vls_addr(matparm), (char *)NULL);
492 
493  if (parameter_file) {
494  /* the file loaded, so the contents become the parameter string */
495  bu_log("Filename: %s\n", bu_vls_addr(matparm));
496 
497  bu_vls_strncpy(&parameter_data, (char *)parameter_file->buf,
498  parameter_file->buflen);
499 
500  if (rdebug&RDEBUG_SHADE) {
501  bu_log("parsing: %s\n", bu_vls_addr(&parameter_data));
502  }
503 
504  bu_close_mapped_file(parameter_file);
505  } else {
506  /* the file did not load, so the shader args become the param string */
507  bu_log("Parameters: %s\n", bu_vls_addr(matparm));
508 
509  bu_vls_strncpy (&parameter_data, bu_vls_addr(matparm), bu_vls_strlen(matparm));
510  }
511 
512  /* set defaults on img_specific struct */
513  prj_sp->prj_images.i_width = prj_sp->prj_images.i_height = 512;
514  prj_sp->prj_images.i_antialias = '1';
515  prj_sp->prj_images.i_through = '0';
516  prj_sp->prj_images.i_behind = '0';
518 
519  if (bu_struct_parse(&parameter_data, img_parse_tab,
520  (char *)&prj_sp->prj_images, NULL) < 0) {
521  bu_log("ERROR: Unable to properly parse projection shader parameters\n");
522  return -1;
523  }
524 
525  bu_vls_free(&parameter_data);
526 
527  /* load the image data for any specified images */
528  for (BU_LIST_FOR(img_sp, img_specific, &prj_sp->prj_images.l)) {
529  if (img_load_datasource(img_sp, rtip->rti_dbip, img_sp->i_width * img_sp->i_height * 3) < 0) {
530  bu_log("\nERROR: prj_setup() %s %s could not be loaded [source was %s]\n",
531  rp->reg_name, bu_vls_addr(&img_sp->i_name),
532  img_sp->i_datasrc==IMG_SRC_OBJECT?"object":img_sp->i_datasrc==IMG_SRC_FILE?"file":"auto");
533 
534  /* skip this one */
535  img_sp->i_through='0';
536  HREVERSE(img_sp->i_plane, img_sp->i_plane);
537 
538  return -1;
539  }
540  }
541 
542  /* if even one of the images is to be anti-aliased, then we need
543  * to set the rti_prismtrace flag so that we can compute the exact
544  * extent of the pixel.
545  */
546  for (BU_LIST_FOR(img_sp, img_specific, &prj_sp->prj_images.l)) {
547  if (img_sp->i_antialias != '0') {
548  if (rdebug&RDEBUG_SHADE)
549  bu_log("prj_setup(%s) setting prismtrace 1\n", rp->reg_name);
550  rtip->rti_prismtrace = 1;
551  break;
552  }
553  }
554 
555  /* The shader needs to operate in a coordinate system which stays
556  * fixed on the region when the region is moved (as in animation)
557  * we need to get a matrix to perform the appropriate transform(s).
558  *
559  * db_region_mat returns a matrix which maps points on/in the region
560  * as it exists where the region is defined (as opposed to the
561  * (possibly transformed) one we are rendering.
562  *
563  * Non-PARALLEL, which is OK, because shaders are prepped serially.
564  */
566 
567 
568  if (rdebug&RDEBUG_SHADE) {
569 
570  prj_print(rp, (char *)prj_sp);
571  }
572 
573  return 1;
574 }
575 
576 
577 HIDDEN void
578 prj_print(register struct region *rp, void *dp)
579 {
580  struct prj_specific *prj_sp = (struct prj_specific *)dp;
581  struct img_specific *img_sp;
582 
583  for (BU_LIST_FOR(img_sp, img_specific, &prj_sp->prj_images.l)) {
584  bu_struct_print(rp->reg_name, img_print_tab, (char *)img_sp);
585  }
586 }
587 
588 
589 HIDDEN void
590 prj_free(void *cp)
591 {
592  struct prj_specific *prj_sp = (struct prj_specific *)cp;
593 
594  struct img_specific *img_sp;
595 
596  while (BU_LIST_WHILE(img_sp, img_specific, &prj_sp->prj_images.l)) {
597 
598  img_sp->i_img = (unsigned char *)0;
599  if (img_sp->i_data) bu_close_mapped_file(img_sp->i_data);
600  img_sp->i_data = (struct bu_mapped_file *)NULL; /* sanity */
601  if (img_sp->i_binunifp) rt_binunif_free(img_sp->i_binunifp);
602  img_sp->i_binunifp = (struct rt_binunif_internal *)NULL; /* sanity */
603  bu_vls_vlsfree(&img_sp->i_name);
604 
605  BU_LIST_DEQUEUE(&img_sp->l);
606  BU_PUT(img_sp, struct img_specific);
607  }
608 
609  if (prj_sp->prj_plfd) {
611  fclose(prj_sp->prj_plfd);
613  }
614 
615  BU_PUT(cp, struct prj_specific);
616 }
617 HIDDEN const double cs = (1.0/255.0);
618 HIDDEN const point_t delta = {0.5, 0.5, 0.0};
619 
620 
621 HIDDEN int
622 project_point(point_t sh_color, struct img_specific *img_sp, struct prj_specific *prj_sp, point_t r_pt)
623 {
624  int x, y;
625  point_t sh_pt;
626  point_t tmp_pt;
627  unsigned char *pixel;
628 
629  MAT4X3PNT(sh_pt, img_sp->i_sh_to_img, r_pt);
630  VADD2(sh_pt, sh_pt, delta);
631 
632  if (rdebug&RDEBUG_SHADE) {
633  VPRINT("sh_pt", sh_pt);
634  }
635 
636  /* make sure we have an image to project into */
637  if (img_sp->i_width <= 0 || img_sp->i_height <= 0) {
638  return 1;
639  }
640 
641  x = sh_pt[X] * (img_sp->i_width-1);
642  y = sh_pt[Y] * (img_sp->i_height-1);
643 
644  if (x<0 || y<0
645  || (x*3 + y*img_sp->i_width*3) < 0
646  || (x*3 + y*img_sp->i_width*3) > (img_sp->i_width * img_sp->i_height * 3))
647  {
648  static int count = 0;
649  static int suppressed = 0;
650  if (count++ < 10) {
651  bu_log("INTERNAL ERROR: projection point is invalid\n");
652  } else {
653  if (!suppressed) {
654  suppressed++;
655  bu_log("INTERNAL ERROR: suppressing further project point error messages\n");
656  }
657  }
658  return 1;
659  }
660 
661  pixel = &img_sp->i_img[x*3 + y*img_sp->i_width*3];
662 
663  if (x >= img_sp->i_width || x < 0 ||
664  y >= img_sp->i_height || y < 0 ||
665  ((img_sp->i_behind == '0' && sh_pt[Z] > 0.0))) {
666  /* we're out of bounds,
667  * leave the color alone
668  */
669  return 1;
670  }
671 
672  if (rdebug&RDEBUG_SHADE && prj_sp->prj_plfd) {
673  /* plot projection direction */
674  pl_color(prj_sp->prj_plfd, V3ARGS(pixel));
675  pdv_3move(prj_sp->prj_plfd, r_pt);
676  VMOVE(tmp_pt, r_pt);
677 
678  VSCALE(tmp_pt, img_sp->i_plane, -sh_pt[Z]);
679  VADD2(tmp_pt, r_pt, tmp_pt);
680  pdv_3cont(prj_sp->prj_plfd, tmp_pt);
681  }
682  VMOVE(sh_color, pixel); /* int/float conversion */
683  return 0;
684 }
685 
686 
687 /**
688  * This is called (from viewshade() in shade.c) once for each hit point
689  * to be shaded. The purpose here is to fill in values in the shadework
690  * structure.
691  */
692 int
693 prj_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
694 /* defined in material.h */
695 /* ptr to the shader-specific struct */
696 {
697  register struct prj_specific *prj_sp =
698  (struct prj_specific *)dp;
699  point_t r_pt;
700  plane_t r_N;
701  int i, status;
702  struct img_specific *img_sp;
703  point_t sh_color;
704  point_t final_color;
705  point_t tmp_pt;
706  fastf_t divisor;
707  struct pixel_ext r_pe; /* region coord version of ap->a_pixelext */
708  fastf_t dist;
709  fastf_t weight;
710 
711 
712  /* check the validity of the arguments we got */
713  RT_AP_CHECK(ap);
714  RT_CHECK_PT(pp);
715  CK_prj_SP(prj_sp);
716 
717  if (rdebug&RDEBUG_SHADE) {
718  bu_log("shading with prj\n");
719  prj_print(pp->pt_regionp, dp);
720  }
721  /* If we are performing the shading in "region" space, we must
722  * transform the hit point from "model" space to "region" space.
723  * See the call to db_region_mat in prj_setup().
724  */
725  MAT4X3PNT(r_pt, prj_sp->prj_m_to_sh, swp->sw_hit.hit_point);
726  MAT4X3VEC(r_N, prj_sp->prj_m_to_sh, swp->sw_hit.hit_normal);
727 
728 
729  if (rdebug&RDEBUG_SHADE) {
730  bu_log("prj_render() model:(%g %g %g) shader:(%g %g %g)\n",
731  V3ARGS(swp->sw_hit.hit_point),
732  V3ARGS(r_pt));
733  }
734 
735 
736  VSET(final_color, 0.0, 0.0, 0.0);
737  divisor = 0.0;
738 
739  if (ap->a_pixelext) {
740 
742 
743  /* We need to compute the extent of the pixel on an
744  * imaginary plane through the hit point with the same
745  * normal as the surface normal at the hit point. Later
746  * this quadrilateral will be projected onto the image
747  * plane(s) to facilitate anti-aliasing.
748  */
749 
750  /* compute region coordinates for pixel extent */
751  for (i = 0; i < CORNER_PTS; i++) {
752  MAT4X3PNT(r_pe.corner[i].r_pt,
753  prj_sp->prj_m_to_sh,
754  ap->a_pixelext->corner[i].r_pt);
755  MAT4X3VEC(r_pe.corner[i].r_dir,
756  prj_sp->prj_m_to_sh,
757  ap->a_pixelext->corner[i].r_dir);
758  }
759 
760  /* compute plane of hit point */
761  VUNITIZE(r_N);
762  r_N[H] = VDOT(r_N, r_pt);
763 
764  /* project corner points into plane of hit point */
765  for (i = 0; i < CORNER_PTS; i++) {
766  dist = 0.0;
767  status = bn_isect_line3_plane(
768  &dist,
769  r_pe.corner[i].r_pt,
770  r_pe.corner[i].r_dir,
771  r_N,
772  &(ap->a_rt_i->rti_tol));
773 
774  if (rdebug&RDEBUG_SHADE) {
775  /* status will be <= 0 when the image was not loaded */
776  if (status <= 0) {
777  /* XXX What to do if we don't
778  * hit plane?
779  */
780  bu_log("%s:%d The unthinkable has happened\n",
781  __FILE__, __LINE__);
782  }
783  }
784 
785  VJOIN1(r_pe.corner[i].r_pt,
786  r_pe.corner[i].r_pt,
787  dist,
788  r_pe.corner[i].r_dir);
789  }
790  }
791 
792 
793  for (BU_LIST_FOR(img_sp, img_specific, &prj_sp->prj_images.l)) {
794  if (img_sp->i_through == '0' && VDOT(r_N, img_sp->i_plane) < 0.0) {
795  /* normal and projection dir don't match, skip on */
796 
797  if (rdebug&RDEBUG_SHADE && prj_sp->prj_plfd) {
798  /* plot hit normal */
799  pl_color(prj_sp->prj_plfd, 255, 255, 255);
800  pdv_3move(prj_sp->prj_plfd, r_pt);
801  VADD2(tmp_pt, r_pt, r_N);
802  pdv_3cont(prj_sp->prj_plfd, tmp_pt);
803 
804  /* plot projection direction */
805  pl_color(prj_sp->prj_plfd, 255, 255, 0);
806  pdv_3move(prj_sp->prj_plfd, r_pt);
807  VADD2(tmp_pt, r_pt, img_sp->i_plane);
808  pdv_3cont(prj_sp->prj_plfd, tmp_pt);
809  }
810  continue;
811  }
812 
813  if (project_point(sh_color, img_sp, prj_sp, r_pt))
814  continue;
815 
816  VSCALE(sh_color, sh_color, cs);
817  weight = VDOT(r_N, img_sp->i_plane);
818  if (img_sp->i_through != '0')
819  weight = (weight < 0.0 ? -weight : weight);
820  if (weight > 0.0) {
821  VJOIN1(final_color, final_color, weight, sh_color);
822  divisor += weight;
823  }
824  }
825 
826  if (divisor > 0.0) {
827  divisor = 1.0 / divisor;
828  VSCALE(swp->sw_color, final_color, divisor);
829  }
830  return 1;
831 }
832 
833 
834 /*
835  * Local Variables:
836  * mode: C
837  * tab-width: 8
838  * indent-tabs-mode: t
839  * c-file-style: "stroustrup"
840  * End:
841  * ex: shiftwidth=4 tabstop=8
842  */
#define IMG_SRC_AUTO
Definition: sh_prj.c:56
struct img_specific prj_images
Definition: sh_prj.c:85
void bu_vls_init(struct bu_vls *vp)
Definition: vls.c:56
HIDDEN int prj_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *mfp, struct rt_i *rtip)
Definition: sh_prj.c:443
int i_height
Definition: sh_prj.c:62
#define CK_prj_SP(_p)
Definition: sh_prj.c:48
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
Definition: raytrace.h:800
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
int rt_db_get_internal(struct rt_db_internal *ip, const struct directory *dp, const struct db_i *dbip, const mat_t mat, struct resource *resp)
Definition: dir.c:76
struct region * pt_regionp
ptr to containing region
Definition: raytrace.h:580
#define bu_byteoffset(_i)
Definition: parse.h:81
int bn_isect_line3_plane(fastf_t *dist, const point_t pt, const vect_t dir, const plane_t plane, const struct bn_tol *tol)
const char * sp_name
Definition: parse.h:140
HIDDEN void prj_free(void *cp)
Definition: sh_prj.c:590
char i_antialias
Definition: sh_prj.c:71
unsigned char * uint8
Definition: raytrace.h:1009
Definition: list.h:118
mat_t i_mat
Definition: sh_prj.c:66
struct pixel_ext * a_pixelext
locations of pixel corners
Definition: raytrace.h:1610
void bu_vls_vlsfree(struct bu_vls *vp)
Definition: vls.c:263
#define MF_MAGIC
Definition: magic.h:205
void pdv_3move(register FILE *plotfp, const fastf_t *pt)
Definition: plot3.c:618
fastf_t i_perspective
Definition: sh_prj.c:73
Definition: clone.c:90
int rti_prismtrace
add support for pixel prism trace
Definition: raytrace.h:1761
#define IMG_SRC_FILE
Definition: sh_prj.c:54
#define VSET(a, b, c, d)
Definition: color.c:53
#define prj_MAGIC
Definition: sh_prj.c:47
HIDDEN int project_point(point_t sh_color, struct img_specific *img_sp, struct prj_specific *prj_sp, point_t r_pt)
Definition: sh_prj.c:622
void bu_semaphore_acquire(unsigned int i)
Definition: semaphore.c:180
struct directory * db_lookup(const struct db_i *, const char *name, int noisy)
Definition: db_lookup.c:153
#define BU_LIST_MAGIC_SET(_l, _magic)
Definition: list.h:129
char i_datasrc
Definition: sh_prj.c:57
char ** dbi_filepath
search path for aux file opens (convenience var)
Definition: raytrace.h:810
void bu_vls_strncpy(struct bu_vls *vp, const char *s, size_t n)
Definition: vls.c:339
Header file for the BRL-CAD common definitions.
#define IMG_O(m)
Definition: sh_prj.c:384
const char * reg_name
Identifying string.
Definition: raytrace.h:539
#define BU_LIST_APPEND(old, new)
Definition: list.h:197
char i_through
Definition: sh_prj.c:70
#define RT_CK_REGION(_p)
Definition: raytrace.h:559
union rt_binunif_internal::@9 u
#define HIDDEN
Definition: common.h:86
#define RT_CK_BINUNIF(_p)
Definition: raytrace.h:1016
mat_t i_sh_to_img
Definition: sh_prj.c:69
void bu_struct_print(const char *title, const struct bu_structparse *parsetab, const char *base)
Definition: parse.c:1221
mat_t prj_m_to_sh
Definition: sh_prj.c:86
HIDDEN void img_source_hook(const struct bu_structparse *sdp, const char *sp_name, void *base, const char *value, void *data)
Definition: sh_prj.c:97
#define RT_AP_CHECK(_ap)
Definition: raytrace.h:1685
#define IMG_SRC_OBJECT
Definition: sh_prj.c:55
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
const char sp_fmt[4]
Definition: parse.h:138
int bu_strncmp(const char *string1, const char *string2, size_t n)
Definition: str.c:191
Definition: color.c:49
COMPLEX data[64]
Definition: fftest.c:34
struct rt_i * a_rt_i
this librt instance
Definition: raytrace.h:1588
#define BU_CK_VLS(_vp)
Definition: vls.h:69
struct rt_binunif_internal * i_binunifp
Definition: sh_prj.c:59
struct resource rt_uniresource
default. Defined in librt/globals.c
Definition: globals.c:41
#define RT_CK_DB_INTERNAL(_p)
Definition: raytrace.h:207
HIDDEN void dimen_hook(const struct bu_structparse *sdp, const char *name, void *base, const char *value, void *data)
Definition: sh_prj.c:240
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
HIDDEN int prj_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
Definition: sh_prj.c:693
#define RT_CK_DIR(_dp)
Definition: raytrace.h:876
struct bu_structparse img_print_tab[]
Definition: sh_prj.c:407
unsigned long junk
Definition: sh_prj.c:52
#define RT_CHECK_RTI(_p)
Definition: raytrace.h:1832
#define RT_DB_INTERNAL_INIT(_p)
Definition: raytrace.h:199
#define LOOKUP_QUIET
Definition: raytrace.h:893
HIDDEN void prj_print(register struct region *rp, void *dp)
Definition: sh_prj.c:578
void bn_mat_inv(mat_t output, const mat_t input)
#define V3ARGS(a)
Definition: color.c:56
mat_t i_bn_mat_inv
Definition: sh_prj.c:67
HIDDEN void persp_hook(const struct bu_structparse *sdp, const char *name, void *base, const char *value, void *data)
Definition: sh_prj.c:209
point_t i_eye_pt
Definition: sh_prj.c:64
#define BU_GET(_ptr, _type)
Definition: malloc.h:201
#define IMG_SPECIFIC_INIT_ZERO
Definition: sh_prj.c:76
size_t bu_vls_strlen(const struct bu_vls *vp)
Definition: vls.c:189
void pdv_3cont(register FILE *plotfp, const fastf_t *pt)
Definition: plot3.c:630
struct bu_vls i_name
Definition: sh_prj.c:53
#define UNUSED(parameter)
Definition: common.h:239
plane_t i_plane
Definition: sh_prj.c:68
#define BU_PUT(_ptr, _type)
Definition: malloc.h:215
struct bu_mapped_file * bu_open_mapped_file(const char *name, const char *appl)
Definition: mappedfile.c:56
void bn_mat_mul(mat_t o, const mat_t a, const mat_t b)
size_t sp_offset
Definition: parse.h:141
void rt_binunif_free(struct rt_binunif_internal *bip)
Definition: db5_bin.c:378
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
#define BU_LIST_WHILE(p, structure, hp)
Definition: list.h:410
#define BU_STRUCTPARSE_FUNC_NULL
Definition: parse.h:153
void bu_semaphore_release(unsigned int i)
Definition: semaphore.c:218
void pl_color(register FILE *plotfp, int r, int g, int b)
Definition: plot3.c:325
vect_t r_dir
Direction of ray (UNIT Length)
Definition: raytrace.h:219
int i_width
Definition: sh_prj.c:61
unsigned char * i_img
Definition: sh_prj.c:60
struct bn_tol rti_tol
Math tolerances for this model.
Definition: raytrace.h:1765
HIDDEN const double cs
Definition: sh_prj.c:617
#define bu_offsetof(_t, _m)
Definition: parse.h:64
#define RT_CK_DBI(_p)
Definition: raytrace.h:829
struct xray corner[CORNER_PTS]
Definition: raytrace.h:1528
int db_region_mat(mat_t m, struct db_i *dbip, const char *name, struct resource *resp)
Definition: db_tree.c:2269
uint32_t magic
Definition: sh_prj.c:84
#define ZERO(val)
Definition: units.c:38
#define BU_LIST_INIT(_hp)
Definition: list.h:148
void * idb_ptr
Definition: raytrace.h:195
point_t r_pt
Point at which ray starts.
Definition: raytrace.h:218
#define IMG_MAGIC
Definition: sh_prj.c:75
#define RDEBUG_SHADE
Definition: optical.h:130
#define BU_SEM_SYSCALL
Definition: parallel.h:178
struct bu_mapped_file * i_data
Definition: sh_prj.c:58
char i_behind
Definition: sh_prj.c:72
struct db_i * rti_dbip
prt to Database instance struct
Definition: raytrace.h:1774
int bu_struct_parse(const struct bu_vls *in_vls, const struct bu_structparse *desc, const char *base, void *data)
Definition: parse.c:878
struct bu_list l
Definition: sh_prj.c:51
#define RT_DIR_NULL
Definition: raytrace.h:875
void bu_close_mapped_file(struct bu_mapped_file *mp)
Definition: mappedfile.c:339
void quat_quat2mat(mat_t mat, const quat_t quat)
Convert Quaternion to Matrix.
Definition: color.c:51
#define CORNER_PTS
Definition: raytrace.h:1525
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
#define BU_CK_LIST_HEAD(_p)
Definition: list.h:142
FILE * prj_plfd
Definition: sh_prj.c:87
fastf_t i_viewsize
Definition: sh_prj.c:63
struct bu_structparse img_parse_tab[]
Definition: sh_prj.c:391
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
HIDDEN int img_load_datasource(struct img_specific *image, struct db_i *dbInstance, const unsigned long int size)
Definition: sh_prj.c:119
#define BU_LIST_DEQUEUE(cur)
Definition: list.h:209
#define RT_CHECK_PT(_p)
compat
Definition: raytrace.h:588
Definition: vls.h:56
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
HIDDEN const point_t delta
Definition: sh_prj.c:618
double fastf_t
Definition: defines.h:300
#define VPRINT(a, b)
Definition: raytrace.h:1881
Header file for the BRL-CAD Optical Library, LIBOPTICAL.
int rdebug
Definition: init.c:39
struct bu_mapped_file * bu_open_mapped_file_with_path(char *const *path, const char *name, const char *appl)
Definition: mappedfile.c:430
Definition: color.c:50
#define BU_CK_PIXEL_EXT(_p)
Definition: raytrace.h:1531
quat_t i_orient
Definition: sh_prj.c:65
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126
struct mfuncs prj_mfuncs[]
Definition: sh_prj.c:428