BRL-CAD
stl_read.c
Go to the documentation of this file.
1 /* S T L _ R E A D . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2002-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This program 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 program 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  */
21 /** @file stl_read.c
22  *
23  * Convert Stereolithography format files to BRL-CAD .g binary format
24  *
25  * Note that binary STL format use a little-endian byte ordering where
26  * bytes at lower addresses have lower significance.
27  *
28  */
29 
30 #include "common.h"
31 
32 #include <stdlib.h>
33 #include <math.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include "bnetwork.h"
38 #include "bio.h"
39 
40 #include "bu/cv.h"
41 #include "bu/getopt.h"
42 #include "bu/units.h"
43 #include "vmath.h"
44 #include "nmg.h"
45 #include "rtgeom.h"
46 #include "raytrace.h"
47 #include "wdb.h"
48 #include "../../plugin.h"
49 
50 static struct vert_root *tree_root;
51 static struct wmember all_head;
52 static const char *input_file; /* name of the input file */
53 static char *forced_name = NULL; /* name specified on command line */
54 static int solid_count = 0; /* count of solids converted */
55 static struct bn_tol tol; /* Tolerance structure */
56 static int id_no = 1000; /* Ident numbers */
57 static int const_id =
58  -1; /* Constant ident number (assigned to all regions if non-negative) */
59 static int mat_code = 1; /* default material code */
60 static int debug = 0; /* Debug flag */
61 static int binary = 0; /* flag indicating input is binary format */
62 static FILE *fd_in; /* input file */
63 static struct rt_wdb *fd_out; /* Resulting BRL-CAD file */
64 static float conv_factor = 1.0; /* conversion factor from model units to mm */
65 static unsigned int obj_count =
66  0; /* Count of parts converted for "stl-g" conversions */
67 static int *bot_faces =
68  NULL; /* array of ints (indices into tree_root->the_array array) three per face */
69 static int bot_fsize = 0; /* current size of the bot_faces array */
70 static int bot_fcurr = 0; /* current bot face */
71 
72 /* Size of blocks of faces to malloc */
73 #define BOT_FBLOCK 128
74 
75 #define MAX_LINE_SIZE 512
76 
77 
78 void
79 Add_face(int face[3])
80 {
81  if (!bot_faces) {
82  bot_faces = (int *)bu_malloc(3 * BOT_FBLOCK * sizeof(int), "bot_faces");
83  bot_fsize = BOT_FBLOCK;
84  bot_fcurr = 0;
85  } else if (bot_fcurr >= bot_fsize) {
86  bot_fsize += BOT_FBLOCK;
87  bot_faces = (int *)bu_realloc((void *)bot_faces, 3 * bot_fsize * sizeof(int),
88  "bot_faces increase");
89  }
90 
91  VMOVE(&bot_faces[3 * bot_fcurr], face);
92  bot_fcurr++;
93 }
94 
95 void
97 {
98  char *c;
99  int count = 0;
100  int len;
101 
102  c = bu_vls_addr(name);
103 
104  while (*c != '\0') {
105  if (*c == '/' || !isprint((int)*c)) {
106  *c = '_';
107  }
108 
109  c++;
110  }
111 
112  len = bu_vls_strlen(name);
113 
114  while (db_lookup(fd_out->dbip, bu_vls_addr(name),
116  char suff[10];
117 
118  bu_vls_trunc(name, len);
119  count++;
120  sprintf(suff, "_%d", count);
121  bu_vls_strcat(name, suff);
122  }
123 }
124 
125 static void
126 Convert_part_ascii(char line[MAX_LINE_SIZE])
127 {
128  char line1[MAX_LINE_SIZE];
129  struct bu_vls solid_name = BU_VLS_INIT_ZERO;
130  struct bu_vls region_name = BU_VLS_INIT_ZERO;
131 
132  int start;
133  int i;
134  int face_count = 0;
135  int degenerate_count = 0;
136  float colr[3] = {0.5, 0.5, 0.5};
137  unsigned char color[3] = { 128, 128, 128 };
138  struct wmember head;
139  vect_t normal = {0, 0, 0};
140  int solid_in_region = 0;
141 
143  bu_prmem("At start of Convert_part_ascii():\n");
144 
145  if (RT_G_DEBUG & DEBUG_MEM_FULL) {
146  bu_log("Barrier check at start of Convert_part_ascii:\n");
147 
148  if (bu_mem_barriercheck())
149  bu_exit(EXIT_FAILURE, "Barrier check failed!\n");
150  }
151 
152 
153  bot_fcurr = 0;
154  BU_LIST_INIT(&head.l);
155 
156  start = (-1);
157 
158  /* skip leading blanks */
159  while (isspace((int)line[++start]) && line[start] != '\0');
160 
161  if (bu_strncmp(&line[start], "solid", 5)
162  && bu_strncmp(&line[start], "SOLID", 5)) {
163  bu_log("Convert_part_ascii: Called for non-part\n%s\n", line);
164  return;
165  }
166 
167  /* skip blanks before name */
168  start += 4;
169 
170  while (isspace((int)line[++start]) && line[start] != '\0');
171 
172  if (forced_name) {
173  bu_vls_strcpy(&region_name, forced_name);
174  } else if (line[start] != '\0') {
175  char *ptr;
176 
177  /* get name */
178  bu_vls_strcpy(&region_name, &line[start]);
179  bu_vls_trimspace(&region_name);
180  ptr = bu_vls_addr(&region_name);
181 
182  while (*ptr != '\0') {
183  if (isspace((int)*ptr)) {
184  bu_vls_trunc(&region_name, ptr - bu_vls_addr(&region_name));
185  break;
186  }
187 
188  ptr++;
189  }
190  } else {
191  /* build a name from the file name */
192 
193  char *ptr;
194  int base_len;
195 
196  obj_count++;
197 
198  /* copy the file name into our work space (skip over path) */
199  ptr = strrchr(input_file, '/');
200 
201  if (ptr) {
202  ptr++;
203  bu_vls_strcpy(&region_name, ptr);
204  } else {
205  bu_vls_strcpy(&region_name, input_file);
206  }
207 
208  /* eliminate a trailing ".stl" */
209  ptr = strstr(bu_vls_addr(&region_name), ".stl");
210 
211  if ((base_len = (ptr - bu_vls_addr(&region_name))) > 0) {
212  bu_vls_trunc(&region_name, base_len);
213  }
214  }
215 
216  mk_unique_brlcad_name(&region_name);
217  bu_log("Converting Part: %s\n", bu_vls_addr(&region_name));
218 
219  solid_count++;
220  bu_vls_strcpy(&solid_name, "s.");
221  bu_vls_vlscat(&solid_name, &region_name);
222  mk_unique_brlcad_name(&solid_name);
223 
224  bu_log("\tUsing solid name: %s\n", bu_vls_addr(&solid_name));
225 
226  if (RT_G_DEBUG & DEBUG_MEM || RT_G_DEBUG & DEBUG_MEM_FULL)
227  bu_prmem("At start of Convert_part_ascii()");
228 
229  while (bu_fgets(line1, MAX_LINE_SIZE, fd_in) != NULL) {
230  start = (-1);
231 
232  while (isspace((int)line1[++start]));
233 
234  if (!bu_strncmp(&line1[start], "endsolid", 8)
235  || !bu_strncmp(&line1[start], "ENDSOLID", 8)) {
236  break;
237  } else if (!bu_strncmp(&line1[start], "color", 5)
238  || !bu_strncmp(&line1[start], "COLOR", 5)) {
239  sscanf(&line1[start + 5], "%f%f%f", &colr[0], &colr[1], &colr[2]);
240 
241  for (i = 0; i < 3; i++)
242  color[i] = (int)(colr[i] * 255.0);
243  } else if (!bu_strncmp(&line1[start], "normal", 6)
244  || !bu_strncmp(&line1[start], "NORMAL", 6)) {
245  float x, y, z;
246 
247  start += 6;
248  sscanf(&line1[start], "%f%f%f", &x, &y, &z);
249  VSET(normal, x, y, z);
250  } else if (!bu_strncmp(&line1[start], "facet", 5)
251  || !bu_strncmp(&line1[start], "FACET", 5)) {
252  VSET(normal, 0.0, 0.0, 0.0);
253 
254  start += 4;
255 
256  while (line1[++start] && isspace((int)line1[start]));
257 
258  if (line1[start]) {
259  if (!bu_strncmp(&line1[start], "normal", 6)
260  || !bu_strncmp(&line1[start], "NORMAL", 6)) {
261  float x, y, z;
262 
263  start += 6;
264  sscanf(&line1[start], "%f%f%f", &x, &y, &z);
265  VSET(normal, x, y, z);
266  }
267  }
268  } else if (!bu_strncmp(&line1[start], "outer loop", 10)
269  || !bu_strncmp(&line1[start], "OUTER LOOP", 10)) {
270  int endloop = 0;
271  int vert_no = 0;
272  int tmp_face[3] = {0, 0, 0};
273 
274  while (!endloop) {
275  if (bu_fgets(line1, MAX_LINE_SIZE, fd_in) == NULL)
276  bu_exit(EXIT_FAILURE, "Unexpected EOF while reading a loop in a part!\n");
277 
278  start = (-1);
279 
280  while (isspace((int)line1[++start]));
281 
282  if (!bu_strncmp(&line1[start], "endloop", 7)
283  || !bu_strncmp(&line1[start], "ENDLOOP", 7))
284  endloop = 1;
285  else if (!bu_strncmp(&line1[start], "vertex", 6)
286  || !bu_strncmp(&line1[start], "VERTEX", 6)) {
287  double x, y, z;
288 
289  sscanf(&line1[start + 6], "%lf%lf%lf", &x, &y, &z);
290 
291  if (vert_no > 2) {
292  int n;
293 
294  bu_log("Non-triangular loop:\n");
295 
296  for (n = 0; n < 3; n++)
297  bu_log("\t(%g %g %g)\n", V3ARGS(&tree_root->the_array[tmp_face[n]]));
298 
299  bu_log("\t(%g %g %g)\n", x, y, z);
300  }
301 
302  x *= conv_factor;
303  y *= conv_factor;
304  z *= conv_factor;
305  tmp_face[vert_no++] = Add_vert(x, y, z, tree_root, tol.dist_sq);
306  } else {
307  bu_log("Unrecognized line: %s\n", line1);
308  }
309  }
310 
311  /* check for degenerate faces */
312  if (tmp_face[0] == tmp_face[1]) {
313  degenerate_count++;
314  continue;
315  }
316 
317  if (tmp_face[0] == tmp_face[2]) {
318  degenerate_count++;
319  continue;
320  }
321 
322  if (tmp_face[1] == tmp_face[2]) {
323  degenerate_count++;
324  continue;
325  }
326 
327  if (debug) {
328  int n;
329 
330  bu_log("Making Face:\n");
331 
332  for (n = 0; n < 3; n++)
333  bu_log("\tvertex #%d: (%g %g %g)\n", tmp_face[n],
334  V3ARGS(&tree_root->the_array[3 * tmp_face[n]]));
335 
336  VPRINT(" normal", normal);
337  }
338 
339  Add_face(tmp_face);
340  face_count++;
341  }
342  }
343 
344  /* Check if this part has any solid parts */
345  if (face_count == 0) {
346  bu_log("\t%s has no solid parts, ignoring\n", bu_vls_addr(&region_name));
347 
348  if (degenerate_count)
349  bu_log("\t%d faces were degenerate\n", degenerate_count);
350 
351  bu_vls_free(&region_name);
352  bu_vls_free(&solid_name);
353 
354  return;
355  } else {
356  if (degenerate_count)
357  bu_log("\t%d faces were degenerate\n", degenerate_count);
358  }
359 
360  mk_bot(fd_out, bu_vls_addr(&solid_name), RT_BOT_SOLID, RT_BOT_UNORIENTED, 0,
361  tree_root->curr_vert, bot_fcurr,
362  tree_root->the_array, bot_faces, NULL, NULL);
363  clean_vert_tree(tree_root);
364 
365  if (face_count && !solid_in_region) {
366  (void)mk_addmember(bu_vls_addr(&solid_name), &head.l, NULL, WMOP_UNION);
367  }
368 
369  bu_log("\tMaking region (%s)\n", bu_vls_addr(&region_name));
370 
371  if (const_id >= 0) {
372  mk_lrcomb(fd_out, bu_vls_addr(&region_name), &head, 1, (char *)NULL,
373  (char *)NULL, color, const_id, 0, mat_code, 100, 0);
374 
375  if (face_count) {
376  (void)mk_addmember(bu_vls_addr(&region_name), &all_head.l, NULL, WMOP_UNION);
377  }
378  } else {
379  mk_lrcomb(fd_out, bu_vls_addr(&region_name), &head, 1, (char *)NULL,
380  (char *)NULL, color, id_no, 0, mat_code, 100, 0);
381 
382  if (face_count)
383  (void)mk_addmember(bu_vls_addr(&region_name), &all_head.l, NULL, WMOP_UNION);
384 
385  id_no++;
386  }
387 
388  if (RT_G_DEBUG & DEBUG_MEM_FULL) {
389  bu_log("Barrier check at end of Convert_part_ascii:\n");
390 
391  if (bu_mem_barriercheck())
392  bu_exit(EXIT_FAILURE, "Barrier check failed!\n");
393  }
394 
395  bu_vls_free(&region_name);
396  bu_vls_free(&solid_name);
397 
398  return;
399 }
400 
401 /* Byte swaps a 4-byte val */
402 void lswap(unsigned int *v)
403 {
404  unsigned int r;
405 
406  r = *v;
407  *v = ((r & 0xff) << 24) | ((r & 0xff00) << 8) | ((r & 0xff0000) >> 8)
408  | ((r & 0xff000000) >> 24);
409 }
410 
411 static void
412 Convert_part_binary()
413 {
414  unsigned char buf[51];
415  unsigned long num_facets = 0;
416  float flts[12];
417  vect_t normal;
418  int tmp_face[3];
419  struct wmember head;
420  struct bu_vls solid_name = BU_VLS_INIT_ZERO;
421  struct bu_vls region_name = BU_VLS_INIT_ZERO;
422  int face_count = 0;
423  int degenerate_count = 0;
424  size_t ret;
425 
426  solid_count++;
427 
428  if (forced_name) {
429  bu_vls_strcpy(&solid_name, "s.");
430  bu_vls_strcat(&solid_name, forced_name);
431  bu_vls_strcpy(&region_name, forced_name);
432  } else {
433  bu_vls_strcat(&solid_name, "s.stl");
434  bu_vls_strcat(&region_name, "r.stl");
435  }
436 
437  bu_log("\tUsing solid name: %s\n", bu_vls_addr(&solid_name));
438 
439 
440  ret = fread(buf, 4, 1, fd_in);
441 
442  if (ret != 1)
443  perror("fread");
444 
445  /* swap bytes to convert from Little-endian to network order (big-endian) */
446  lswap((unsigned int *)buf);
447 
448  /* now use our network to native host format conversion tools */
449  num_facets = ntohl(*(uint32_t *)buf);
450 
451  bu_log("\t%ld facets\n", num_facets);
452 
453  while (fread(buf, 48, 1, fd_in)) {
454  int i;
455  double pt[3];
456 
457  /* swap bytes to convert from Little-endian to network order (big-endian) */
458  for (i = 0; i < 12; i++) {
459  lswap((unsigned int *)&buf[i * 4]);
460  }
461 
462  /* now use our network to native host format conversion tools */
463  bu_cv_ntohf((unsigned char *)flts, buf, 12);
464 
465  /* unused attribute byte count */
466  ret = fread(buf, 2, 1, fd_in);
467 
468  if (ret != 1)
469  perror("fread");
470 
471  VMOVE(normal, flts);
472  VSCALE(pt, &flts[3], conv_factor);
473  tmp_face[0] = Add_vert(V3ARGS(pt), tree_root, tol.dist_sq);
474  VSCALE(pt, &flts[6], conv_factor);
475  tmp_face[1] = Add_vert(V3ARGS(pt), tree_root, tol.dist_sq);
476  VSCALE(pt, &flts[9], conv_factor);
477  tmp_face[2] = Add_vert(V3ARGS(pt), tree_root, tol.dist_sq);
478 
479  /* check for degenerate faces */
480  if (tmp_face[0] == tmp_face[1]) {
481  degenerate_count++;
482  continue;
483  }
484 
485  if (tmp_face[0] == tmp_face[2]) {
486  degenerate_count++;
487  continue;
488  }
489 
490  if (tmp_face[1] == tmp_face[2]) {
491  degenerate_count++;
492  continue;
493  }
494 
495  if (debug) {
496  int n;
497 
498  bu_log("Making Face:\n");
499 
500  for (n = 0; n < 3; n++)
501  bu_log("\tvertex #%d: (%g %g %g)\n", tmp_face[n],
502  V3ARGS(&tree_root->the_array[3 * tmp_face[n]]));
503 
504  VPRINT(" normal", normal);
505  }
506 
507  Add_face(tmp_face);
508  face_count++;
509  }
510 
511  /* Check if this part has any solid parts */
512  if (face_count == 0) {
513  bu_log("\tpart has no solid parts, ignoring\n");
514 
515  if (degenerate_count)
516  bu_log("\t%d faces were degenerate\n", degenerate_count);
517 
518  return;
519  } else {
520  if (degenerate_count)
521  bu_log("\t%d faces were degenerate\n", degenerate_count);
522  }
523 
524  mk_bot(fd_out, bu_vls_addr(&solid_name), RT_BOT_SOLID, RT_BOT_UNORIENTED, 0,
525  tree_root->curr_vert, bot_fcurr, tree_root->the_array, bot_faces, NULL, NULL);
526  clean_vert_tree(tree_root);
527 
528  BU_LIST_INIT(&head.l);
529 
530  if (face_count) {
531  (void)mk_addmember(bu_vls_addr(&solid_name), &head.l, NULL, WMOP_UNION);
532  }
533 
534  bu_log("\tMaking region (%s)\n", bu_vls_addr(&region_name));
535 
536  if (const_id >= 0) {
537  mk_lrcomb(fd_out, bu_vls_addr(&region_name), &head, 1, (char *)NULL,
538  (char *)NULL, NULL, const_id, 0, mat_code, 100, 0);
539 
540  if (face_count) {
541  (void)mk_addmember(bu_vls_addr(&region_name), &all_head.l, NULL, WMOP_UNION);
542  }
543  } else {
544  mk_lrcomb(fd_out, bu_vls_addr(&region_name), &head, 1, (char *)NULL,
545  (char *)NULL, NULL, id_no, 0, mat_code, 100, 0);
546 
547  if (face_count)
548  (void)mk_addmember(bu_vls_addr(&region_name), &all_head.l, NULL, WMOP_UNION);
549 
550  id_no++;
551  }
552 
553  if (RT_G_DEBUG & DEBUG_MEM_FULL) {
554  bu_log("Barrier check at end of Convert_part_ascii:\n");
555 
556  if (bu_mem_barriercheck())
557  bu_exit(EXIT_FAILURE, "Barrier check failed!\n");
558  }
559 
560  return;
561 }
562 
563 
564 static void
565 Convert_input()
566 {
567  char line[ MAX_LINE_SIZE ];
568 
569  if (binary) {
570  if (fread(line, 80, 1, fd_in) < 1) {
571  if (feof(fd_in)) {
572  bu_exit(EXIT_FAILURE, "Unexpected EOF in input file!\n");
573  } else {
574  bu_log("Error reading input file\n");
575  perror("stl-g");
576  bu_exit(EXIT_FAILURE, "Error reading input file\n");
577  }
578  }
579 
580  line[80] = '\0';
581  bu_log("header data:\n%s\n\n", line);
582  Convert_part_binary();
583  } else {
584  while (bu_fgets(line, MAX_LINE_SIZE, fd_in) != NULL) {
585  int start = 0;
586 
587  while (line[start] != '\0' && isspace((int)line[start])) {
588  start++;
589  }
590 
591  if (!bu_strncmp(&line[start], "solid", 5)
592  || !bu_strncmp(&line[start], "SOLID", 5))
593  Convert_part_ascii(line);
594  else
595  bu_log("Unrecognized line:\n%s\n", line);
596  }
597  }
598 }
599 
600 
601 HIDDEN int
602 gcv_stl_read(const char *path, struct rt_wdb *wdbp,
603  const struct gcv_opts *UNUSED(options))
604 {
605  tol.magic = BN_TOL_MAGIC;
606 
607  /* this value selected as a reasonable compromise between eliminating
608  * needed faces and keeping degenerate faces
609  */
610  tol.dist = 0.0005; /* default, same as MGED, RT, ... */
611  tol.dist_sq = tol.dist * tol.dist;
612  tol.perp = 1e-6;
613  tol.para = 1 - tol.perp;
614 
615  forced_name = NULL;
616 
617  conv_factor = 1.0; /* default */
618 
619  input_file = path;
620 
621  if ((fd_in = fopen(input_file, "rb")) == NULL) {
622  bu_log("Cannot open input file (%s)\n", input_file);
623  perror("stl-g");
624  bu_exit(1, NULL);
625  }
626 
627  fd_out = wdbp;
628 
629  /* FIXME: update for libgcv
630  * mk_id_units(fd_out, "Conversion from Stereolithography format", "mm");
631  */
632 
633  BU_LIST_INIT(&all_head.l);
634 
635  /* create a tree structure to hold the input vertices */
636  tree_root = create_vert_tree();
637 
638  Convert_input();
639 
640  /* make a top level group */
641  mk_lcomb(fd_out, "all", &all_head, 0, (char *)NULL, (char *)NULL,
642  (unsigned char *)NULL, 0);
643 
644  fclose(fd_in);
645 
646 
647  return 1;
648 }
649 
650 
651 static const struct gcv_converter converters[] = {
652  {"stl", gcv_stl_read, NULL},
653  {NULL, NULL, NULL}
654 };
655 
656 const struct gcv_plugin_info gcv_plugin_conv_stl_read = {converters};
657 
658 
659 /*
660  * Local Variables:
661  * mode: C
662  * tab-width: 8
663  * indent-tabs-mode: t
664  * c-file-style: "stroustrup"
665  * End:
666  * ex: shiftwidth=4 tabstop=8
667  */
int mk_bot(struct rt_wdb *fp, const char *name, unsigned char mode, unsigned char orientation, unsigned char error_mode, size_t num_vertices, size_t num_faces, fastf_t *vertices, int *faces, fastf_t *thickness, struct bu_bitv *face_mode)
Definition: bot.c:121
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
void bu_prmem(const char *str)
Definition: malloc.c:516
double dist
>= 0
Definition: tol.h:73
struct db_i * dbip
Definition: raytrace.h:1266
Definition: clone.c:90
void bu_vls_strcat(struct bu_vls *vp, const char *s)
Definition: vls.c:368
#define VSET(a, b, c, d)
Definition: color.c:53
void bu_vls_trunc(struct bu_vls *vp, int len)
Definition: vls.c:198
double dist_sq
dist * dist
Definition: tol.h:74
struct directory * db_lookup(const struct db_i *, const char *name, int noisy)
Definition: db_lookup.c:153
#define BN_TOL_MAGIC
Definition: magic.h:74
Definition: wdb.h:64
Header file for the BRL-CAD common definitions.
Definition: gcv.c:8
struct vert_root * create_vert_tree(void)
routine to create a vertex tree.
Definition: vert_tree.c:80
#define WMOP_UNION
Definition: wdb.h:887
struct bu_list l
Definition: wdb.h:65
#define HIDDEN
Definition: common.h:86
#define DEBUG_MEM
17 –>> BU_DEBUG_MEM_LOG
Definition: raytrace.h:102
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
#define mk_lcomb(_fp, _name, _headp, _rf, _shadername, _shaderargs, _rgb, _inh)
Definition: wdb.h:820
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
#define RT_G_DEBUG
Definition: raytrace.h:1718
void bu_exit(int status, const char *fmt,...) _BU_ATTR_NORETURN _BU_ATTR_PRINTF23
Definition: bomb.c:195
#define mk_lrcomb(fp, name, _headp, region_flag, shadername, shaderargs, rgb, id, air, material, los, inherit_flag)
Definition: wdb.h:826
int Add_vert(double x, double y, double z, struct vert_root *tree_root, fastf_t local_tol_sq)
Routine to add a vertex to the current list of part vertices. The array is re-alloc'd if needed...
Definition: vert_tree.c:181
#define LOOKUP_QUIET
Definition: raytrace.h:893
#define V3ARGS(a)
Definition: color.c:56
void lswap(unsigned int *v)
Definition: stl_read.c:402
char * options
Definition: gqa.c:56
#define DEBUG_MEM_FULL
18 –>> BU_DEBUG_MEM_CHECK
Definition: raytrace.h:103
#define MAX_LINE_SIZE
Definition: stl_read.c:75
size_t bu_vls_strlen(const struct bu_vls *vp)
Definition: vls.c:189
void * bu_realloc(void *ptr, size_t siz, const char *str)
#define UNUSED(parameter)
Definition: common.h:239
struct wmember * mk_addmember(const char *name, struct bu_list *headp, mat_t mat, int op)
Definition: reg.c:181
Vertex tree support Routines to manage a binary search tree of vertices.
Definition: vert_tree.h:50
Support for uniform tolerances.
Definition: tol.h:71
size_t curr_vert
the number of vertices currently in the array
Definition: vert_tree.h:55
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
void clean_vert_tree(struct vert_root *tree_root)
Routine to free the binary search tree and reset the current number of vertices. The vertex array is ...
Definition: vert_tree.c:128
int bu_mem_barriercheck(void)
Definition: malloc.c:660
void mk_unique_brlcad_name(struct bu_vls *name)
Definition: stl_read.c:96
void bu_cv_ntohf(unsigned char *out, const unsigned char *in, size_t count)
double perp
nearly 0
Definition: tol.h:75
#define BU_LIST_INIT(_hp)
Definition: list.h:148
const struct gcv_plugin_info gcv_plugin_conv_stl_read
Definition: stl_read.c:656
uint32_t magic
Definition: tol.h:72
fastf_t * the_array
the array of vertices
Definition: vert_tree.h:54
#define RT_DIR_NULL
Definition: raytrace.h:875
HIDDEN int gcv_stl_read(const char *path, struct rt_wdb *wdbp, const struct gcv_opts *options)
Definition: stl_read.c:602
void bu_vls_trimspace(struct bu_vls *vp)
Definition: vls.c:678
#define BOT_FBLOCK
Definition: stl_read.c:73
void bu_vls_strcpy(struct bu_vls *vp, const char *s)
Definition: vls.c:310
char * bu_fgets(char *s, int size, FILE *stream)
Definition: fgets.c:31
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
void bu_vls_vlscat(struct bu_vls *dest, const struct bu_vls *src)
Definition: vls.c:415
Definition: vls.h:56
#define VPRINT(a, b)
Definition: raytrace.h:1881
void Add_face(int face[3])
Definition: stl_read.c:79
double para
nearly 1
Definition: tol.h:76