BRL-CAD
loadview.c
Go to the documentation of this file.
1 /* L O A D 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/loadview.c
21  *
22  * The loadview command.
23  *
24  */
25 
26 #include "common.h"
27 
28 #include <stdlib.h>
29 #include <ctype.h>
30 #include <string.h>
31 
32 #include "./ged_private.h"
33 
34 
38 
39 /**
40  * here we define a minimal table of commands that are supported by the
41  * loadview command. unsupported commands are those that have no bearing on
42  * view restoration.
43  */
45  {"viewsize", "size in mm", "set view size",
46  _ged_cm_vsize, 2, 2},
47  {"eye_pt", "xyz of eye", "set eye point",
48  _ged_cm_eyept, 4, 4},
49  {"lookat_pt", "x y z [yflip]", "set eye look direction, in X-Y plane",
50  _ged_cm_lookat_pt, 4, 5},
51  {"viewrot", "4x4 matrix", "set view direction from matrix",
52  _ged_cm_vrot, 17, 17},
53  {"orientation", "quaternion", "set view direction from quaternion",
54  _ged_cm_orientation, 5, 5},
55  {"set", "", "show or set parameters",
56  _ged_cm_set, 1, 999},
57 
58  /* begin unsupported commands (for view loading) */
59 
60  {"start", "frame number", "start a new frame",
61  _ged_cm_null, 2, 2},
62  {"clean", "", "clean articulation from previous frame",
63  _ged_cm_null, 1, 1},
64  {"end", "", "end of frame setup, begin raytrace",
65  _ged_cm_null, 1, 1},
66 
67  /* not output, by default in saveview */
68 
69  {"multiview", "", "produce stock set of views",
70  _ged_cm_null, 1, 1},
71  {"anim", "path type args", "specify articulation animation",
72  _ged_cm_null, 4, 999},
73  {"tree", "treetop(s)", "specify alternate list of tree tops",
74  _ged_cm_null, 1, 999},
75  {"ae", "azim elev", "specify view as azim and elev, in degrees",
76  _ged_cm_null, 3, 3},
77  {"opt", "-flags", "set flags, like on command line",
78  _ged_cm_null, 2, 999},
79 
80  /* this is a quick hack used for quietly parsing the EOF delimiter in the
81  * script files.
82  */
83  {"EOF", "", "End of file delimiter",
84  _ged_cm_null, 1, 1},
85 
86  /* XXX support for the ae command is not included, though it probably should */
87  {(char *)0, (char *)0, (char *)0,
88  0, 0, 0 /* END */}
89 };
90 
91 
92 int
93 ged_loadview(struct ged *gedp, int argc, const char *argv[])
94 {
95  int ret;
96  FILE *fp;
97  char buffer[512] = {0};
98 
99  /* data pulled from script file */
100  int perspective=-1;
101 #define MAX_DBNAME 2048
102  char dbName[MAX_DBNAME] = {0};
103  char objects[10000] = {0};
104  char *editArgv[3];
105  int prevPerspective;
106  static const char *usage = "filename";
107 
109  GED_CHECK_VIEW(gedp, GED_ERROR);
110  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
111 
112  /* initialize result */
113  bu_vls_trunc(gedp->ged_result_str, 0);
114 
115  /* must be wanting help */
116  if (argc == 1) {
117  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
118  return GED_HELP;
119  }
120 
121  /* make sure the file exists */
122  if (!bu_file_exists(argv[1], NULL)) {
123  bu_log("Error: File %s does not exist\n", argv[1]);
124  return GED_ERROR;
125  }
126 
127  /* open the file for reading */
128  if ((fp = fopen(argv[1], "r")) == NULL) {
129  perror(argv[1]);
130  return GED_ERROR;
131  }
132 
133  prevPerspective = gedp->ged_gvp->gv_perspective;
134  _ged_current_gedp = gedp;
135 
136  /* turn perspective mode off, by default. A "-p" option in the
137  * view script will turn it back on.
138  */
139  gedp->ged_gvp->gv_perspective = 0;
140 
141  /* iterate over the contents of the raytrace script */
142  /* TODO: change to bu_fgets or bu_vls_fgets */
143  while (!feof(fp)) {
144  memset(buffer, 0, 512);
145  ret = fscanf(fp, "%512s", buffer);
146  if (ret != 1)
147  bu_log("Failed to read buffer\n");
148 
149  if (bu_strncmp(buffer, "-p", 2) == 0) {
150  /* we found perspective */
151 
152  buffer[0] = ' ';
153  buffer[1] = ' ';
154  sscanf(buffer, "%d", &perspective);
155  /* bu_log("perspective=%d\n", perspective);*/
156  gedp->ged_gvp->gv_perspective = perspective;
157 
158  } else if (bu_strncmp(buffer, "$*", 2) == 0) {
159  /* the next read is the file name, the objects come
160  * after that
161  */
162 
163  memset(dbName, 0, MAX_DBNAME);
164  ret = fscanf(fp, "%2048s", dbName); /* MAX_DBNAME */
165  if (ret != 1)
166  bu_log("Failed to read database name\n");
167 
168  /* if the last character is a line termination,
169  * remove it (it should always be unless the user
170  * modifies the file)
171  */
172  if (*(dbName + strlen(dbName) - 1)=='\\') {
173  memset(dbName+strlen(dbName)-1, 0, 1);
174  }
175  /* bu_log("dbName=%s\n", dbName); */
176 
177  if (!bu_same_file(gedp->ged_wdbp->dbip->dbi_filename, dbName)) {
178  /* stop here if they are not the same file,
179  * otherwise, we may proceed as expected, and load
180  * the objects.
181  */
182  bu_vls_printf(gedp->ged_result_str, "View script references a different database\nCannot load the view without closing the current database\n(i.e. run \"opendb %s\")\n", dbName);
183 
184  /* restore state before leaving */
185  gedp->ged_gvp->gv_perspective = prevPerspective;
186  fclose(fp);
187  return GED_ERROR;
188  }
189 
190  /* get rid of anything that may be displayed, since we
191  * will load objects that are listed in the script next.
192  */
193  (void)ged_zap(gedp, 1, NULL);
194 
195  /* now get the objects listed */
196  ret = fscanf(fp, "%10000s", objects);
197  if (ret != 1)
198  bu_log("Failed to read object names\n");
199 
200  /* bu_log("OBJECTS=%s\n", objects);*/
201  while ((!feof(fp)) && (bu_strncmp(objects, "\\", 1) != 0)) {
202 
203  /* clean off the single quotes... */
204  if (bu_strncmp(objects, "'", 1) == 0) {
205  objects[0]=' ';
206  memset(objects+strlen(objects)-1, ' ', 1);
207  sscanf(objects, "%10000s", objects);
208  }
209 
210  editArgv[0] = "draw";
211  editArgv[1] = objects;
212  editArgv[2] = (char *)NULL;
213  if (ged_draw(gedp, 2, (const char **)editArgv) != GED_OK) {
214  bu_vls_printf(gedp->ged_result_str, "Unable to load object: %s\n", objects);
215  }
216 
217  /* bu_log("objects=%s\n", objects);*/
218  ret = fscanf(fp, "%10000s", objects);
219  if (ret != 1)
220  bu_log("Failed to read object names\n");
221  }
222 
223  /* end iteration over reading in listed objects */
224  } else if (bu_strncmp(buffer, "<<EOF", 5) == 0) {
225  char *cmdBuffer = NULL;
226  /* we are almost done .. read in the view commands */
227 
228  while ((cmdBuffer = rt_read_cmd(fp)) != NULL) {
229  /* even unsupported commands should return successfully as
230  * they should be calling ged_cm_null()
231  */
232  if (rt_do_cmd((struct rt_i *)0, cmdBuffer, ged_loadview_cmdtab) < 0) {
233  bu_vls_printf(gedp->ged_result_str, "command failed: %s\n", cmdBuffer);
234  }
235  bu_free((void *)cmdBuffer, "loadview cmdBuffer");
236  }
237  /* end iteration over rt commands */
238 
239  }
240  /* end check for non-view values (dbname, etc.) */
241 
242  }
243  /* end iteration over file until eof */
244  fclose(fp);
245 
246  /* now we have to finish the eye point calculations that usually get
247  * postponed until the end command runs. Since we are at the "end"
248  * of a commands section, we may finish the computations.
249  */
250  /* First step: put eye at view center (view 0, 0, 0) */
251  MAT_COPY(gedp->ged_gvp->gv_rotation, _ged_viewrot);
252  MAT_DELTAS_VEC_NEG(gedp->ged_gvp->gv_center, _ged_eye_model);
253  ged_view_update(gedp->ged_gvp);
254 
255  return GED_OK;
256 }
257 
258 
259 int
260 _ged_cm_vsize(const int argc, const char **argv)
261 {
262  if (argc < 2)
263  return -1;
264  /* for some reason, scale is supposed to be half of size... */
265  _ged_current_gedp->ged_gvp->gv_size = atof(argv[1]);
266  _ged_current_gedp->ged_gvp->gv_scale = _ged_current_gedp->ged_gvp->gv_size * 0.5;
267  _ged_current_gedp->ged_gvp->gv_isize = 1.0 / _ged_current_gedp->ged_gvp->gv_size;
268  return 0;
269 }
270 
271 
272 int
273 _ged_cm_eyept(const int argc, const char **argv)
274 {
275  if (argc < 4)
276  return -1;
277  _ged_eye_model[X] = atof(argv[1]);
278  _ged_eye_model[Y] = atof(argv[2]);
279  _ged_eye_model[Z] = atof(argv[3]);
280  /* Processing is deferred until ged_cm_end() */
281  return 0;
282 }
283 
284 
285 int
286 _ged_cm_lookat_pt(const int argc, const char **argv)
287 {
288  point_t pt;
289  vect_t dir;
290 
291  if (argc < 4)
292  return -1;
293  pt[X] = atof(argv[1]);
294  pt[Y] = atof(argv[2]);
295  pt[Z] = atof(argv[3]);
296 
297  VSUB2(dir, pt, _ged_eye_model);
298  VUNITIZE(dir);
299 
300  /*
301  * At the moment bn_mat_lookat() will return NAN's if the
302  * direction vector is aligned with the Z axis. The following is a
303  * workaround.
304  */
305  {
306  vect_t neg_Z_axis = VINIT_ZERO;
307  neg_Z_axis[Z] = -1.0;
308  bn_mat_fromto(_ged_viewrot, dir, neg_Z_axis, &_ged_current_gedp->ged_wdbp->wdb_tol);
309  }
310 
311  /* Final processing is deferred until ged_cm_end(), but eye_pt
312  * must have been specified before here (for now)
313  */
314  return 0;
315 }
316 
317 
318 int
319 _ged_cm_vrot(const int argc, const char **argv)
320 {
321  int i;
322 
323  if (argc < 17)
324  return -1;
325  for (i = 0; i < 16; i++)
326  _ged_viewrot[i] = atof(argv[i+1]);
327  /* Processing is deferred until ged_cm_end() */
328  return 0;
329 }
330 
331 
332 int
333 _ged_cm_orientation(const int argc, const char **argv)
334 {
335  int i;
336  quat_t quat;
337 
338  if (argc < 4)
339  return -1;
340 
341  for (i = 0; i < 4; i++)
342  quat[i] = atof(argv[i+1]);
344 
345  return 0;
346 }
347 
348 
349 int
350 _ged_cm_set(const int UNUSED(argc), const char **UNUSED(argv))
351 {
352  return -1;
353 }
354 
355 
356 /**
357  * any commands that are not supported or implemented may call this null
358  * routine to avoid rt_do_cmd() "command not found" error reporting
359  */
360 int
361 _ged_cm_null(const int argc, const char **argv)
362 {
363  if (argc < 0 || argv == NULL)
364  return 1;
365 
366  return 0;
367 }
368 
369 
370 /*
371  * Local Variables:
372  * tab-width: 8
373  * mode: C
374  * indent-tabs-mode: t
375  * c-file-style: "stroustrup"
376  * End:
377  * ex: shiftwidth=4 tabstop=8
378  */
void usage(struct ged *gedp)
Definition: coil.c:315
#define GED_OK
Definition: ged.h:55
int rt_do_cmd(struct rt_i *rtip, const char *ilp, const struct command_tab *tp)
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
mat_t gv_center
Definition: bview.h:221
struct ged * _ged_current_gedp
Definition: loadview.c:37
Definition: ged.h:338
struct db_i * dbip
Definition: raytrace.h:1266
void bu_vls_trunc(struct bu_vls *vp, int len)
Definition: vls.c:198
mat_t _ged_viewrot
Definition: loadview.c:36
#define GED_CHECK_ARGC_GT_0(_gedp, _argc, _flags)
Definition: ged.h:202
int ged_draw(struct ged *gedp, int argc, const char *argv[])
Definition: draw.c:1212
struct rt_wdb * ged_wdbp
Definition: ged.h:340
int _ged_cm_set(const int argc, const char **argv)
Definition: loadview.c:350
int _ged_cm_orientation(const int argc, const char **argv)
Definition: loadview.c:333
Header file for the BRL-CAD common definitions.
fastf_t gv_perspective
perspective angle
Definition: bview.h:214
void ged_view_update(struct bview *gvp)
Definition: vutil.c:33
#define GED_ERROR
Definition: ged.h:61
struct bview * ged_gvp
Definition: ged.h:361
vect_t _ged_eye_model
Definition: loadview.c:35
int bu_strncmp(const char *string1, const char *string2, size_t n)
Definition: str.c:191
Definition: color.c:49
void * memset(void *s, int c, size_t n)
#define MAX_DBNAME
#define GED_CHECK_VIEW(_gedp, _flags)
Definition: ged.h:140
#define GED_CHECK_DATABASE_OPEN(_gedp, _flags)
Definition: ged.h:114
int _ged_cm_null(const int argc, const char **argv)
Definition: loadview.c:361
fastf_t gv_isize
1.0 / size
Definition: bview.h:213
fastf_t gv_scale
Definition: bview.h:211
char * rt_read_cmd(FILE *fp)
fastf_t gv_size
2.0 * scale
Definition: bview.h:212
void bn_mat_fromto(mat_t m, const fastf_t *from, const fastf_t *to, const struct bn_tol *tol)
Definition: mat.c:639
int bu_same_file(const char *fn1, const char *fn2)
Definition: file.c:101
int _ged_cm_eyept(const int argc, const char **argv)
Definition: loadview.c:273
#define UNUSED(parameter)
Definition: common.h:239
int ged_zap(struct ged *gedp, int argc, const char *argv[])
Definition: zap.c:42
struct bu_vls * ged_result_str
Definition: ged.h:357
int _ged_cm_vrot(const int argc, const char **argv)
Definition: loadview.c:319
mat_t gv_rotation
Definition: bview.h:220
int _ged_cm_vsize(const int argc, const char **argv)
Definition: loadview.c:260
struct bn_tol wdb_tol
Definition: raytrace.h:1269
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
int _ged_cm_lookat_pt(const int argc, const char **argv)
Definition: loadview.c:286
#define GED_HELP
Definition: ged.h:62
void quat_quat2mat(mat_t mat, const quat_t quat)
Convert Quaternion to Matrix.
Definition: color.c:51
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
char * dbi_filename
file name
Definition: raytrace.h:805
int bu_file_exists(const char *path, int *fd)
Definition: file.c:57
struct command_tab ged_loadview_cmdtab[]
Definition: loadview.c:44
Definition: color.c:50
int ged_loadview(struct ged *gedp, int argc, const char *argv[])
Definition: loadview.c:93