BRL-CAD
preview.c
Go to the documentation of this file.
1 /* P R E V I E W . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2008-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 libged/preview.c
21  *
22  * The preview command.
23  *
24  */
25 
26 #include "common.h"
27 
28 #include <stdlib.h>
29 #include <ctype.h>
30 #include <string.h>
31 #include <time.h>
32 #include "bsocket.h"
33 
34 #include "bu/cmd.h"
35 #include "bu/getopt.h"
36 
37 #include "./ged_private.h"
38 
39 
40 static struct bn_vlblock *preview_vbp;
41 static double preview_delay;
42 static int preview_mode;
43 static int preview_desiredframe;
44 static int preview_finalframe;
45 static int preview_currentframe;
46 static int preview_tree_walk_needed;
47 static int draw_eye_path;
48 static char *image_name = NULL;
49 
50 
51 /* FIXME: this shouldn't exist as a static array and doesn't even seem
52  * to be necessary. gd_rt_cmd points into it as an argv, but the
53  * elements can probably be dup'd strings and released by the caller.
54  */
55 #define MAXARGS 9000
56 static char rt_cmd_storage[MAXARGS*9];
57 
58 
59 int
60 ged_cm_anim(const int argc, const char **argv)
61 {
62 
64  return 0;
65 
66  if (db_parse_anim(_ged_current_gedp->ged_wdbp->dbip, argc, (const char **)argv) < 0) {
67  bu_vls_printf(_ged_current_gedp->ged_result_str, "cm_anim: %s %s failed\n", argv[1], argv[2]);
68  return -1; /* BAD */
69  }
70 
71  preview_tree_walk_needed = 1;
72 
73  return 0;
74 }
75 
76 
77 int
78 ged_cm_clean(const int UNUSED(argc), const char **UNUSED(argv))
79 {
81  return 0;
82 
83  /*f_zap((ClientData)NULL, interp, 0, (char **)0);*/
84 
85  /* Free animation structures */
87 
88  preview_tree_walk_needed = 0;
89  return 0;
90 }
91 
92 
93 int
94 ged_cm_end(const int UNUSED(argc), const char **UNUSED(argv))
95 {
96  vect_t xlate;
97  vect_t new_cent;
98  vect_t xv, yv; /* view x, y */
99  vect_t xm, ym; /* model x, y */
100  struct bu_list *vhead = &preview_vbp->head[0];
101 
102  /* Only display the frames the user is interested in */
103  if (preview_currentframe < preview_desiredframe) return 0;
104  if (preview_finalframe && preview_currentframe > preview_finalframe) return 0;
105 
106  /* Record eye path as a polyline. Move, then draws */
107  if (BU_LIST_IS_EMPTY(vhead)) {
109  } else {
111  }
112 
113  /* First step: put eye at view center (view 0, 0, 0) */
115  MAT_DELTAS_VEC_NEG(_ged_current_gedp->ged_gvp->gv_center, _ged_eye_model);
117 
118  /*
119  * Compute camera orientation notch to right (+X) and up (+Y)
120  * Done here, with eye in center of view.
121  */
122  VSET(xv, 0.05, 0.0, 0.0);
123  VSET(yv, 0.0, 0.05, 0.0);
124  MAT4X3PNT(xm, _ged_current_gedp->ged_gvp->gv_view2model, xv);
125  MAT4X3PNT(ym, _ged_current_gedp->ged_gvp->gv_view2model, yv);
126  RT_ADD_VLIST(vhead, xm, BN_VLIST_LINE_DRAW);
128  RT_ADD_VLIST(vhead, ym, BN_VLIST_LINE_DRAW);
130 
131  /* Second step: put eye at view 0, 0, 1.
132  * For eye to be at 0, 0, 1, the old 0, 0, -1 needs to become 0, 0, 0.
133  */
134  VSET(xlate, 0.0, 0.0, -1.0); /* correction factor */
135  MAT4X3PNT(new_cent, _ged_current_gedp->ged_gvp->gv_view2model, xlate);
136  MAT_DELTAS_VEC_NEG(_ged_current_gedp->ged_gvp->gv_center, new_cent);
138 
139  /* If new treewalk is needed, get new objects into view. */
140  if (preview_tree_walk_needed) {
141  const char *av[2];
142 
143  av[0] = "zap";
144  av[1] = NULL;
145 
146  (void)ged_zap(_ged_current_gedp, 1, av);
148  }
149 
152 
153  if (preview_delay > 0) {
154  struct timeval tv;
155  fd_set readfds;
156 
157  FD_ZERO(&readfds);
158  FD_SET(fileno(stdin), &readfds);
159  tv.tv_sec = (long)preview_delay;
160  tv.tv_usec = (long)((preview_delay - tv.tv_sec) * 1000000);
161  select(fileno(stdin)+1, &readfds, (fd_set *)0, (fd_set *)0, &tv);
162  }
163 
164  return 0;
165 }
166 
167 
168 int
169 ged_cm_multiview(const int UNUSED(argc), const char **UNUSED(argv))
170 {
171  return -1;
172 }
173 
174 
175 int
176 ged_cm_start(const int argc, const char **argv)
177 {
178  if (argc < 2)
179  return -1;
180  preview_currentframe = atoi(argv[1]);
181  preview_tree_walk_needed = 0;
182 
183  return 0;
184 }
185 
186 
187 int
188 ged_cm_tree(const int argc, const char **argv)
189 {
190  int i = 1;
191  char *cp = rt_cmd_storage;
192 
193  for (i = 1; i < argc && i < MAXARGS; i++) {
194  bu_strlcpy(cp, argv[i], MAXARGS*9);
196  cp += strlen(cp) + 1;
197  }
198  _ged_current_gedp->ged_gdp->gd_rt_cmd[i] = (char *)0;
200 
201  preview_tree_walk_needed = 1;
202 
203  return 0;
204 }
205 
206 
208  {"start", "frame number", "start a new frame",
209  ged_cm_start, 2, 2},
210  {"viewsize", "size in mm", "set view size",
211  _ged_cm_vsize, 2, 2},
212  {"eye_pt", "xyz of eye", "set eye point",
213  _ged_cm_eyept, 4, 4},
214  {"lookat_pt", "x y z [yflip]", "set eye look direction, in X-Y plane",
215  _ged_cm_lookat_pt, 4, 5},
216  {"orientation", "quaternion", "set view direction from quaternion",
217  _ged_cm_orientation, 5, 5},
218  {"viewrot", "4x4 matrix", "set view direction from matrix",
219  _ged_cm_vrot, 17, 17},
220  {"end", "", "end of frame setup, begin raytrace",
221  ged_cm_end, 1, 1},
222  {"multiview", "", "produce stock set of views",
223  ged_cm_multiview, 1, 1},
224  {"anim", "path type args", "specify articulation animation",
225  ged_cm_anim, 4, 999},
226  {"tree", "treetop(s)", "specify alternate list of tree tops",
227  ged_cm_tree, 1, 999},
228  {"clean", "", "clean articulation from previous frame",
229  ged_cm_clean, 1, 1},
230  {"set", "", "show or set parameters",
231  _ged_cm_set, 1, 999},
232  {"ae", "azim elev", "specify view as azim and elev, in degrees",
233  _ged_cm_null, 3, 3},
234  {"opt", "-flags", "set flags, like on command line",
235  _ged_cm_null, 2, 999},
236  {(char *)0, (char *)0, (char *)0,
237  0, 0, 0} /* END */
238 };
239 
240 
241 int
242 ged_loadframe(struct ged *gedp, FILE *fp)
243 {
244  char *cmd;
245 
246  int end = 0;
247  while (!end && ((cmd = rt_read_cmd(fp)) != NULL)) {
248  /* Hack to prevent running framedone scripts prematurely */
249  if (cmd[0] == '!') {
250  if (preview_currentframe < preview_desiredframe ||
251  (preview_finalframe && preview_currentframe > preview_finalframe)) {
252  bu_free((void *)cmd, "preview ! cmd");
253  continue;
254  }
255  }
256 
257  if (cmd[0] == 'e' && bu_strncmp(cmd, "end", 3) == 0) {
258  end = 1;
259  }
260 
261  if (rt_do_cmd((struct rt_i *)0, cmd, ged_preview_cmdtab) < 0)
262  bu_vls_printf(gedp->ged_result_str, "command failed: %s\n", cmd);
263  bu_free((void *)cmd, "preview cmd");
264  }
265 
266  if (end) {
267  return GED_OK; /* possible more frames */
268  }
269  return GED_ERROR; /* end of frames */
270 }
271 
272 
273 /**
274  * Preview a new style RT animation script.
275  * Note that the RT command parser code is used, rather than the
276  * MGED command parser, because of the differences in format.
277  * The RT parser expects command handlers of the form "ged_cm_xxx()",
278  * and all communications are done via global variables.
279  *
280  * For the moment, the only preview mode is the normal one,
281  * moving the eyepoint as directed.
282  * However, as a bonus, the eye path is left behind as a vector plot.
283  */
284 int
285 ged_preview(struct ged *gedp, int argc, const char *argv[])
286 {
287  static const char *usage = "[-v] [-e] [-o image_name.ext] [-d sec_delay] [-D start frame] [-K last frame] rt_script_file";
288 
289  FILE *fp;
290  int c;
291  vect_t temp;
292  char **vp;
293  size_t args = 0;
294  struct bu_vls extension = BU_VLS_INIT_ZERO;
295  struct bu_vls name = BU_VLS_INIT_ZERO;
296  char *dot;
297 
300  GED_CHECK_VIEW(gedp, GED_ERROR);
301 
302  /* initialize result */
303  bu_vls_trunc(gedp->ged_result_str, 0);
304 
305  /* must be wanting help */
306  if (argc == 1) {
307  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
308  return GED_HELP;
309  }
310 
311  if (argc < 2) {
312  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
313  return GED_ERROR;
314  }
315 
316  preview_delay = 0; /* Full speed, by default */
317  preview_mode = 1; /* wireframe drawing */
318  preview_desiredframe = 0;
319  preview_finalframe = 0;
320  draw_eye_path = 0;
321  _ged_current_gedp = gedp;
322  image_name = NULL;
323 
324  /* Parse options */
325  bu_optind = 1; /* re-init bu_getopt() */
326  while ((c=bu_getopt(argc, (char * const *)argv, "d:evD:K:o:")) != -1) {
327  switch (c) {
328  case 'd':
329  preview_delay = atof(bu_optarg);
330  break;
331  case 'D':
332  preview_desiredframe = atof(bu_optarg);
333  break;
334  case 'e':
335  draw_eye_path = 1;
336  break;
337  case 'K':
338  preview_finalframe = atof(bu_optarg);
339  break;
340  case 'o':
341  image_name = bu_optarg;
342  break;
343  case 'v':
344  preview_mode = 3; /* Like "ev" */
345  break;
346  default: {
347  bu_vls_printf(gedp->ged_result_str, "option '%c' unknown\n", c);
348  bu_vls_printf(gedp->ged_result_str, " -d# inter-frame delay\n");
349  bu_vls_printf(gedp->ged_result_str, " -e overlay plot of eye path\n");
350  bu_vls_printf(gedp->ged_result_str, " -v polygon rendering (visual)\n");
351  bu_vls_printf(gedp->ged_result_str, " -D# desired starting frame\n");
352  bu_vls_printf(gedp->ged_result_str, " -K# final frame\n");
353  bu_vls_printf(gedp->ged_result_str, " -o image_name.ext output frame to file typed by extension(defaults to PIX)\n");
354  return GED_ERROR;
355  }
356 
357  break;
358  }
359  }
360  argc -= bu_optind-1;
361  argv += bu_optind-1;
362 
363  if ((fp = fopen(argv[1], "r")) == NULL) {
364  perror(argv[1]);
365  return GED_ERROR;
366  }
367 
368  args = argc + 2 + ged_count_tops(gedp);
369  gedp->ged_gdp->gd_rt_cmd = (char **)bu_calloc(args, sizeof(char *), "alloc gd_rt_cmd");
370  vp = &gedp->ged_gdp->gd_rt_cmd[0];
371  *vp++ = bu_strdup("tree");
372 
373  /* Build list of top-level objects in view, in _ged_current_gedp->ged_gdp->gd_rt_cmd[] */
375  /* Print out the command we are about to run */
377  while ((vp != NULL) && (*vp))
378  bu_vls_printf(gedp->ged_result_str, "%s ", *vp++);
379 
380  bu_vls_printf(gedp->ged_result_str, "\n");
381 
382  preview_vbp = rt_vlblock_init();
383 
384  bu_vls_printf(gedp->ged_result_str, "eyepoint at (0, 0, 1) viewspace\n");
385 
386 
387  /*
388  * Initialize the view to the current one provided by the ged
389  * structure in case a view specification is never given.
390  */
391  MAT_COPY(_ged_viewrot, gedp->ged_gvp->gv_rotation);
392  VSET(temp, 0.0, 0.0, 1.0);
393  MAT4X3PNT(_ged_eye_model, gedp->ged_gvp->gv_view2model, temp);
394 
395  if (image_name) {
396  /* parse file name and possible extension */
397  if ((dot = strrchr(image_name, '.')) != (char *) NULL) {
398  bu_vls_strncpy(&name, image_name, dot - image_name);
399  bu_vls_strcpy(&extension, dot);
400  } else {
401  bu_vls_strcpy(&extension, "");
402  bu_vls_strcpy(&name, image_name);
403  }
404  }
405  while (ged_loadframe(gedp, fp) == GED_OK) {
406  if (image_name) {
407  struct bu_vls fullname = BU_VLS_INIT_ZERO;
408  const char *screengrab_args[3];
409  int screengrab_argc = 0;
410 
411  screengrab_args[screengrab_argc++] = "screengrab";
412 
413  bu_vls_sprintf(&fullname, "%s%05d%s", bu_vls_addr(&name),
414  preview_currentframe, bu_vls_addr(&extension));
415  screengrab_args[screengrab_argc++] = bu_vls_addr(&fullname);
416 
417  /* ged_png(gedp, screengrab_argc, screengrab_args); */
418  ged_screen_grab(gedp, screengrab_argc, screengrab_args);
419 
420  bu_vls_free(&fullname);
421  }
422  }
423 
424  if (image_name) {
425  bu_vls_free(&name);
426  bu_vls_free(&extension);
427  }
428 
429  fclose(fp);
430  fp = NULL;
431 
432  if (draw_eye_path)
433  _ged_cvt_vlblock_to_solids(gedp, preview_vbp, "EYE_PATH", 0);
434 
435  if (preview_vbp) {
436  rt_vlblock_free(preview_vbp);
437  preview_vbp = (struct bn_vlblock *)NULL;
438  }
439  db_free_anim(gedp->ged_wdbp->dbip); /* Forget any anim commands */
440 
441  return GED_OK;
442 }
443 
444 
445 /*
446  * Local Variables:
447  * tab-width: 8
448  * mode: C
449  * indent-tabs-mode: t
450  * c-file-style: "stroustrup"
451  * End:
452  * ex: shiftwidth=4 tabstop=8
453  */
void db_free_anim(struct db_i *dbip)
Definition: db_anim.c:223
int _ged_cm_orientation(const int argc, const char **argv)
Definition: loadview.c:333
void usage(struct ged *gedp)
Definition: coil.c:315
#define GED_OK
Definition: ged.h:55
int _ged_cm_vrot(const int argc, const char **argv)
Definition: loadview.c:319
int ged_cm_multiview(const int argc, const char **argv)
Definition: preview.c:169
int ged_cm_end(const int argc, const char **argv)
Definition: preview.c:94
int rt_do_cmd(struct rt_i *rtip, const char *ilp, const struct command_tab *tp)
mat_t gv_center
Definition: bview.h:221
void rt_vlblock_free(struct bn_vlblock *vbp)
Definition: vlist.c:78
Definition: list.h:118
Definition: ged.h:338
struct db_i * dbip
Definition: raytrace.h:1266
size_t ged_count_tops(struct ged *gedp)
Definition: rt.c:409
#define VSET(a, b, c, d)
Definition: color.c:53
void bu_vls_trunc(struct bu_vls *vp, int len)
Definition: vls.c:198
#define BU_LIST_IS_EMPTY(hp)
Definition: list.h:295
void * ged_refresh_clientdata
client data passed to refresh handler
Definition: ged.h:366
int _ged_cm_null(const int argc, const char **argv)
Definition: loadview.c:361
void bu_vls_strncpy(struct bu_vls *vp, const char *s, size_t n)
Definition: vls.c:339
struct rt_wdb * ged_wdbp
Definition: ged.h:340
char * bu_optarg
Definition: globals.c:91
Header file for the BRL-CAD common definitions.
int bu_optind
Definition: globals.c:89
struct bn_vlblock * rt_vlblock_init(void)
Definition: vlist.c:71
int bu_getopt(int nargc, char *const nargv[], const char *ostr)
Definition: getopt.c:43
void ged_view_update(struct bview *gvp)
Definition: vutil.c:33
#define GED_ERROR
Definition: ged.h:61
struct bu_list * head
head[max] variable size array
Definition: vlist.h:174
int ged_cm_start(const int argc, const char **argv)
Definition: preview.c:176
struct bview * ged_gvp
Definition: ged.h:361
mat_t gv_view2model
Definition: bview.h:224
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
int bu_strncmp(const char *string1, const char *string2, size_t n)
Definition: str.c:191
int _ged_cm_lookat_pt(const int argc, const char **argv)
Definition: loadview.c:286
#define GED_CHECK_VIEW(_gedp, _flags)
Definition: ged.h:140
#define GED_CHECK_DATABASE_OPEN(_gedp, _flags)
Definition: ged.h:114
#define RT_ADD_VLIST(hd, pnt, draw)
Definition: raytrace.h:1865
int gd_rt_cmd_len
Definition: ged.h:313
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
vect_t _ged_eye_model
Definition: loadview.c:35
int ged_loadframe(struct ged *gedp, FILE *fp)
Definition: preview.c:242
void bu_vls_sprintf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:707
int _ged_cm_vsize(const int argc, const char **argv)
Definition: loadview.c:260
#define BN_VLIST_LINE_MOVE
Definition: vlist.h:82
#define bu_strlcpy(dst, src, size)
Definition: str.h:60
char * rt_read_cmd(FILE *fp)
#define BN_VLIST_LINE_DRAW
Definition: vlist.h:83
char ** gd_rt_cmd
Definition: ged.h:312
int _ged_cm_set(const int argc, const char **argv)
Definition: loadview.c:350
int ged_preview(struct ged *gedp, int argc, const char *argv[])
Definition: preview.c:285
#define GED_CHECK_DRAWABLE(_gedp, _flags)
Definition: ged.h:129
#define UNUSED(parameter)
Definition: common.h:239
struct command_tab ged_preview_cmdtab[]
Definition: preview.c:207
int ged_zap(struct ged *gedp, int argc, const char *argv[])
Definition: zap.c:42
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
struct bu_vls * ged_result_str
Definition: ged.h:357
struct ged * _ged_current_gedp
Definition: loadview.c:37
struct ged_drawable * ged_gdp
Definition: ged.h:360
int _ged_cm_eyept(const int argc, const char **argv)
Definition: loadview.c:273
void(* ged_refresh_handler)(void *)
function for handling refresh requests
Definition: ged.h:367
mat_t _ged_viewrot
Definition: loadview.c:36
void _ged_cvt_vlblock_to_solids(struct ged *gedp, struct bn_vlblock *vbp, const char *name, int copy)
Definition: draw.c:554
int ged_cm_anim(const int argc, const char **argv)
Definition: preview.c:60
mat_t gv_rotation
Definition: bview.h:220
int db_parse_anim(struct db_i *dbip, int argc, const char **argv)
Definition: db_anim.c:424
#define DBI_NULL
Definition: raytrace.h:827
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
int ged_cm_tree(const int argc, const char **argv)
Definition: preview.c:188
#define GED_HELP
Definition: ged.h:62
void bu_vls_strcpy(struct bu_vls *vp, const char *s)
Definition: vls.c:310
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
int ged_cm_clean(const int argc, const char **argv)
Definition: preview.c:78
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
Definition: vls.h:56
#define MAXARGS
Definition: preview.c:55
int ged_build_tops(struct ged *gedp, char **start, char **end)
Definition: rt.c:424
#define GED_REFRESH_CALLBACK_PTR_NULL
Definition: ged.h:81
int _ged_drawtrees(struct ged *gedp, int argc, const char *argv[], int kind, struct _ged_client_data *_dgcdp)
Definition: draw.c:581
int ged_screen_grab(struct ged *gedp, int argc, const char *argv[])
Definition: screengrab.c:44
#define bu_strdup(s)
Definition: str.h:71