BRL-CAD
sh_tcl.c
Go to the documentation of this file.
1 /* S H _ T C L . 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_tcl.c
21  *
22  * To add a new shader to the "rt" program's LIBOPTICAL library:
23  *
24  * 6) Edit shaders.tcl and comb.tcl in the ../tclscripts/mged directory to
25  * add a new gui for this shader.
26  */
27 
28 #include "common.h"
29 
30 #include <stddef.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <math.h>
34 
35 #include <tcl.h>
36 
37 #include "bu/parallel.h"
38 #include "vmath.h"
39 #include "raytrace.h"
40 #include "optical.h"
41 
42 
43 #define tcl_MAGIC 0x54434C00 /* "TCL" */
44 #define CK_tcl_SP(_p) BU_CKMAG(_p, tcl_MAGIC, "tcl_specific")
45 
46 /*
47  * the shader specific structure contains all variables which are unique
48  * to any particular use of the shader.
49  */
50 struct tcl_specific {
51  uint32_t magic; /* magic # for memory validity check, must come 1st */
52  mat_t tcl_m_to_r; /* model to shader space matrix */
53  Tcl_Interp *tcl_interp[MAX_PSW];
54  Tcl_Obj *tcl_objPtr;
55  struct bu_vls tcl_file; /* name of script to run */
56  struct bu_mapped_file *tcl_mp; /* actual script */
57 };
58 
59 
60 /* The default values for the variables in the shader specific structure */
61 static const
62 struct tcl_specific tcl_defaults = {
63  tcl_MAGIC, /* magic */
64  MAT_INIT_ZERO, /* tcl_m_to_r */
65  {0}, /* tcl_interps */
66  NULL, /* tcl_objPtr */
67  BU_VLS_INIT_ZERO, /* tcl_file */
68  NULL /* tcl_mp */
69 };
70 
71 
72 #define SHDR_NULL ((struct tcl_specific *)0)
73 #define SHDR_O(m) bu_offsetof(struct tcl_specific, m)
74 
75 /* description of how to parse/print the arguments to the shader
76  * There is at least one line here for each variable in the shader specific
77  * structure above
78  */
80  {"%V", 1, "file", SHDR_O(tcl_file), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
81  {"", 0, (char *)0, 0, BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }
82 
83 };
85  {"%p", 1, "tcl_print_tab", bu_byteoffset(tcl_print_tab[0]), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
86  {"%V", 1, "f", SHDR_O(tcl_file), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
87  {"", 0, (char *)0, 0, BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }
88 };
89 
90 
91 HIDDEN int tcl_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *mfp, struct rt_i *rtip);
92 HIDDEN int tcl_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp);
93 HIDDEN void tcl_print(register struct region *rp, void *dp);
94 HIDDEN void tcl_free(void *cp);
95 
96 /* The "mfuncs" structure defines the external interface to the shader.
97  * Note that more than one shader "name" can be associated with a given
98  * shader by defining more than one mfuncs struct in this array.
99  * See sh_phong.c for an example of building more than one shader "name"
100  * from a set of source functions. There you will find that "glass" "mirror"
101  * and "plastic" are all names for the same shader with different default
102  * values for the parameters.
103  */
104 struct mfuncs tcl_mfuncs[] = {
105  {MF_MAGIC, "tcl", 0, MFI_NORMAL|MFI_HIT|MFI_UV, 0,
106  tcl_setup, tcl_render, tcl_print, tcl_free },
107 
108  {0, (char *)0, 0, 0, 0,
109  0, 0, 0, 0 }
110 };
111 
112 
113 /*
114  * This routine is called (at prep time)
115  * once for each region which uses this shader.
116  * Any shader-specific initialization should be done here.
117  */
118 HIDDEN int
119 tcl_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *UNUSED(mfp), struct rt_i *rtip)
120 
121 
122 /* pointer to reg_udata in *rp */
123 
124 /* New since 4.4 release */
125 {
126  register struct tcl_specific *tcl_sp;
127  int cpu;
128 
129  /* check the arguments */
130  RT_CHECK_RTI(rtip);
131  BU_CK_VLS(matparm);
132  RT_CK_REGION(rp);
133 
134 
135  if (rdebug&RDEBUG_SHADE)
136  bu_log("tcl_setup(%s)\n", rp->reg_name);
137 
138  /* Get memory for the shader parameters and shader-specific data */
139  BU_GET(tcl_sp, struct tcl_specific);
140  *dpp = tcl_sp;
141 
142  /* initialize the default values for the shader */
143  memcpy(tcl_sp, &tcl_defaults, sizeof(struct tcl_specific));
144 
145  /* parse the user's arguments for this use of the shader. */
146  if (bu_struct_parse(matparm, tcl_parse_tab, (char *)tcl_sp, NULL) < 0)
147  return -1;
148 
149  for (cpu=0; cpu < MAX_PSW; cpu++) {
150  tcl_sp->tcl_interp[cpu] = Tcl_CreateInterp();
151  if (Tcl_Init(tcl_sp->tcl_interp[cpu]) == TCL_ERROR)
152  return -1;
153  }
154 
155  /* the shader needs to operate in a coordinate system which stays
156  * fixed on the region when the region is moved (as in animation)
157  * we need to get a matrix to perform the appropriate transform(s).
158  *
159  * Shading is be done in "region coordinates":
160  */
162 
163 
164  if (rdebug&RDEBUG_SHADE) {
165  bu_struct_print(" Parameters:", tcl_print_tab,
166  (char *)tcl_sp);
167  bn_mat_print("m_to_sh", tcl_sp->tcl_m_to_r);
168  }
169 
170  return 1;
171 }
172 
173 
174 HIDDEN void
175 tcl_print(register struct region *rp, void *dp)
176 {
177  bu_struct_print(rp->reg_name, tcl_print_tab, (char *)dp);
178 }
179 
180 
181 HIDDEN void
182 tcl_free(void *cp)
183 {
184  BU_PUT(cp, struct tcl_specific);
185 }
186 
187 
188 /*
189  * This is called (from viewshade() in shade.c) once for each hit point
190  * to be shaded. The purpose here is to fill in values in the shadework
191  * structure.
192  */
193 int
194 tcl_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
195 
196 
197 /* defined in material.h */
198 /* ptr to the shader-specific struct */
199 {
200  register struct tcl_specific *tcl_sp =
201  (struct tcl_specific *)dp;
202  point_t pt;
203  int tcl_status;
204  register int cpu = ap->a_resource->re_cpu;
205 
206  /* check the validity of the arguments we got */
207  RT_AP_CHECK(ap);
208  RT_CHECK_PT(pp);
209  CK_tcl_SP(tcl_sp);
210 
211  if (rdebug&RDEBUG_SHADE)
212  bu_struct_print("tcl_render Parameters:",
213  tcl_print_tab, (char *)tcl_sp);
214 
215  /* we are performing the shading in "region" space, so we must
216  * transform the hit point from "model" space to "region" space.
217  */
218  MAT4X3PNT(pt, tcl_sp->tcl_m_to_r, swp->sw_hit.hit_point);
219 
220  if (rdebug&RDEBUG_SHADE) {
221  bu_log("tcl_render() model:(%g %g %g) shader:(%g %g %g)\n",
222  V3ARGS(swp->sw_hit.hit_point),
223  V3ARGS(pt));
224  }
225 
226  /* set some Tcl variables to the shadework structure values */
227 
228 #define rt_Tcl_LV(_s, _v) Tcl_LinkVar(tcl_sp->tcl_interp[cpu], _s, (char *)_v, \
229  TCL_LINK_DOUBLE)
230 
231  rt_Tcl_LV("sw_transmit", &swp->sw_transmit);
232  rt_Tcl_LV("sw_reflect", &swp->sw_reflect);
233  rt_Tcl_LV("sw_refrac_index", &swp->sw_refrac_index);
234  rt_Tcl_LV("sw_temperature", &swp->sw_temperature);
235  rt_Tcl_LV("reflect", &swp->sw_reflect);
236  rt_Tcl_LV("sw_red", &swp->sw_color[0]);
237  rt_Tcl_LV("sw_grn", &swp->sw_color[1]);
238  rt_Tcl_LV("sw_blu", &swp->sw_color[2]);
239  rt_Tcl_LV("sw_base_red", &swp->sw_basecolor[0]);
240  rt_Tcl_LV("sw_base_grn", &swp->sw_basecolor[1]);
241  rt_Tcl_LV("sw_base_blu", &swp->sw_basecolor[2]);
242  rt_Tcl_LV("sw_dist", &swp->sw_hit.hit_dist);
243  rt_Tcl_LV("sw_hitpt_x", &swp->sw_hit.hit_point[X]);
244  rt_Tcl_LV("sw_hitpt_y", &swp->sw_hit.hit_point[Y]);
245  rt_Tcl_LV("sw_hitpt_z", &swp->sw_hit.hit_point[Z]);
246  rt_Tcl_LV("sw_normal_x", &swp->sw_hit.hit_normal[X]);
247  rt_Tcl_LV("sw_normal_y", &swp->sw_hit.hit_normal[Y]);
248  rt_Tcl_LV("sw_normal_z", &swp->sw_hit.hit_normal[Z]);
249  rt_Tcl_LV("sw_uv_u", &swp->sw_uv.uv_u);
250  rt_Tcl_LV("sw_uv_v", &swp->sw_uv.uv_v);
251  rt_Tcl_LV("sw_x", &pt[X]);
252  rt_Tcl_LV("sw_y", &pt[Y]);
253  rt_Tcl_LV("sw_z", &pt[Z]);
254  Tcl_LinkVar(tcl_sp->tcl_interp[cpu], "ap_x", (char *)&ap->a_x,
255  TCL_LINK_INT);
256  Tcl_LinkVar(tcl_sp->tcl_interp[cpu], "ap_y", (char *)&ap->a_y,
257  TCL_LINK_INT);
258 
259  /* XXX run the script (should be Tcl_EvalObj) */
260  tcl_status = Tcl_EvalFile(tcl_sp->tcl_interp[cpu],
261  bu_vls_addr(&tcl_sp->tcl_file));
262 
263  if (tcl_status != TCL_OK) {
264  bu_log("%s\n", Tcl_GetStringResult(tcl_sp->tcl_interp[cpu]));
265  }
266 
267  /* break the links to these stack variables */
268  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_transmit");
269  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_reflect");
270  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_refrac_index");
271  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_temperature");
272  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "reflect");
273  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_red");
274  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_grn");
275  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_blu");
276  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_base_red");
277  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_base_grn");
278  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_base_blu");
279  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_dist");
280  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_hitpt_x");
281  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_hitpt_y");
282  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_hitpt_z");
283  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_normal_x");
284  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_normal_y");
285  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_normal_z");
286  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_uv_u");
287  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_uv_v");
288  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_x");
289  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_y");
290  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "sw_z");
291  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "ap_x");
292  Tcl_UnlinkVar(tcl_sp->tcl_interp[cpu], "ap_y");
293 
294 
295  /* shader must perform transmission/reflection calculations
296  *
297  * 0 < swp->sw_transmit <= 1 causes transmission computations
298  * 0 < swp->sw_reflect <= 1 causes reflection computations
299  */
300  if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
301  (void)rr_render(ap, pp, swp);
302 
303  return 1;
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
struct bu_structparse tcl_print_tab[]
Definition: sh_tcl.c:79
#define bu_byteoffset(_i)
Definition: parse.h:81
#define MF_MAGIC
Definition: magic.h:205
Tcl_Obj * tcl_objPtr
Definition: sh_tcl.c:54
#define rt_Tcl_LV(_s, _v)
Tcl_Interp * tcl_interp[MAX_PSW]
Definition: sh_tcl.c:53
HIDDEN void tcl_free(void *cp)
Definition: sh_tcl.c:182
Header file for the BRL-CAD common definitions.
const char * reg_name
Identifying string.
Definition: raytrace.h:539
struct resource * a_resource
dynamic memory resources
Definition: raytrace.h:1591
#define RT_CK_REGION(_p)
Definition: raytrace.h:559
#define HIDDEN
Definition: common.h:86
void bu_struct_print(const char *title, const struct bu_structparse *parsetab, const char *base)
Definition: parse.c:1221
#define RT_AP_CHECK(_ap)
Definition: raytrace.h:1685
struct bu_mapped_file * tcl_mp
Definition: sh_tcl.c:56
Definition: color.c:49
#define BU_CK_VLS(_vp)
Definition: vls.h:69
struct resource rt_uniresource
default. Defined in librt/globals.c
Definition: globals.c:41
HIDDEN int tcl_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *mfp, struct rt_i *rtip)
Definition: sh_tcl.c:119
void bn_mat_print(const char *title, const mat_t m)
Definition: mat.c:81
#define RT_CHECK_RTI(_p)
Definition: raytrace.h:1832
#define V3ARGS(a)
Definition: color.c:56
int a_x
Screen X of ray, if applicable.
Definition: raytrace.h:1596
#define BU_GET(_ptr, _type)
Definition: malloc.h:201
struct bu_vls tcl_file
Definition: sh_tcl.c:55
#define UNUSED(parameter)
Definition: common.h:239
HIDDEN int tcl_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
Definition: sh_tcl.c:194
#define BU_PUT(_ptr, _type)
Definition: malloc.h:215
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
#define BU_STRUCTPARSE_FUNC_NULL
Definition: parse.h:153
struct bu_structparse tcl_parse_tab[]
Definition: sh_tcl.c:84
#define tcl_MAGIC
Definition: sh_tcl.c:43
#define MAX_PSW
Definition: parallel.h:48
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_tcl.c:51
struct mfuncs tcl_mfuncs[]
Definition: sh_tcl.c:104
#define RDEBUG_SHADE
Definition: optical.h:130
HIDDEN void tcl_print(register struct region *rp, void *dp)
Definition: sh_tcl.c:175
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
int a_y
Screen Y of ray, if applicable.
Definition: raytrace.h:1597
Definition: color.c:51
#define CK_tcl_SP(_p)
Definition: sh_tcl.c:44
int re_cpu
processor number, for ID
Definition: raytrace.h:1442
int rr_render(struct application *app, const struct partition *pp, struct shadework *swp)
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
#define SHDR_O(m)
Definition: sh_tcl.c:73
#define RT_CHECK_PT(_p)
compat
Definition: raytrace.h:588
mat_t tcl_m_to_r
Definition: sh_tcl.c:52
Definition: vls.h:56
Header file for the BRL-CAD Optical Library, LIBOPTICAL.
int rdebug
Definition: init.c:39
Definition: color.c:50