star-stl

Load STereo Lithography (StL) file format
git clone git://git.meso-star.fr/star-stl.git
Log | Files | Refs | README | LICENSE

sstl_binary.c (3953B)


      1 /* Copyright (C) 2015, 2016, 2019, 2021, 2023, 2025 |Méso|Star> (contact@meso-star.com)
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published by
      5  * the Free Software Foundation, either version 3 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     11  * GNU Lesser General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU Lesser General Public License
     14  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     15 
     16 #include "sstl_c.h"
     17 
     18 #include <rsys/cstr.h>
     19 #include <rsys/stretchy_array.h>
     20 
     21 /*******************************************************************************
     22  * Helper functions
     23  ******************************************************************************/
     24 static INLINE res_T
     25 parse_header(struct sstl* sstl, FILE* fp, const char* name)
     26 {
     27   char header[80];
     28   ASSERT(sstl && fp && fp);
     29 
     30   if(fread(header, sizeof(header), 1, fp) != 1) {
     31     ERROR(sstl, "%s: invalid header\n", name);
     32     return RES_BAD_ARG;
     33   }
     34   return RES_OK;
     35 }
     36 
     37 static INLINE res_T
     38 parse_triangle_count
     39   (struct sstl* sstl,
     40    FILE* fp,
     41    const char* name,
     42    uint32_t* ntri)
     43 {
     44   uint8_t bytes[4]; /* Little endian */
     45   ASSERT(sstl && fp && name && ntri);
     46 
     47   if(fread(bytes, sizeof(bytes), 1, fp) != 1) {
     48     ERROR(sstl, "%s: invalid triangle count\n", name);
     49     return RES_BAD_ARG;
     50   }
     51 
     52   /* Ensure encoding in host byte order */
     53   *ntri =
     54    (uint32_t)(bytes[0]<<0)
     55  | (uint32_t)(bytes[1]<<8)
     56  | (uint32_t)(bytes[2]<<16)
     57  | (uint32_t)(bytes[3]<<24);
     58   return RES_OK;
     59 }
     60 
     61 static INLINE res_T
     62 parse_triangle
     63   (struct sstl* sstl,
     64    FILE* fp,
     65    const char* name,
     66    const uint32_t itri) /* Triangle identifier */
     67 {
     68   uint8_t bytes[4/*#bytes*/*12/*#vectors*/+2/*attribute*/];
     69   union { uint32_t ui32; float f; } ucast;
     70   float* N = NULL; /* Normal */
     71   float v[3][3] = {0}; /* Vertices */
     72   int i = 0;
     73   res_T res = RES_OK;
     74   ASSERT(sstl && fp && name);
     75 
     76   if(fread(bytes, sizeof(bytes), 1, fp) != 1) {
     77     ERROR(sstl, "%s: invalid triangle %i\n", name, itri);
     78     res = RES_BAD_ARG;
     79     goto error;
     80   }
     81 
     82   #define CAST(Bytes) \
     83     ((ucast.ui32 = \
     84       (uint32_t)((Bytes)[0]<<0) \
     85     | (uint32_t)((Bytes)[1]<<8) \
     86     | (uint32_t)((Bytes)[2]<<16) \
     87     | (uint32_t)((Bytes)[3]<<24)), \
     88     ucast.f)
     89 
     90   N = sa_add(sstl->normals, 3);
     91   N[0] = CAST(bytes+0);
     92   N[1] = CAST(bytes+4);
     93   N[2] = CAST(bytes+8);
     94 
     95   FOR_EACH(i, 0, 3) {
     96     v[i][0] = CAST(bytes+(i+1)*12+0);
     97     v[i][1] = CAST(bytes+(i+1)*12+4);
     98     v[i][2] = CAST(bytes+(i+1)*12+8);
     99 
    100     res = register_vertex(sstl, v[i]);
    101     if(res != RES_OK) {
    102       ERROR(sstl, "%s: triangle %i: vertex registration error -- %s\n",
    103         name, itri, res_to_cstr(res));
    104       res = RES_BAD_ARG;
    105       goto error;
    106     }
    107   }
    108 
    109   /* If necessary, automatically calculate the surface normal. */
    110   if(!f3_is_normalized(N)) calculate_normal(N, v[0], v[1], v[2]);
    111 
    112 exit:
    113   return res;
    114 error:
    115   goto exit;
    116 }
    117 
    118 /*******************************************************************************
    119  * Local functions
    120  ******************************************************************************/
    121 res_T
    122 load_stream_binary(struct sstl* sstl, FILE* fp, const char* name)
    123 {
    124   uint32_t ntris = 0;
    125   uint32_t i = 0;
    126   res_T res = RES_OK;
    127   ASSERT(sstl && fp && name);
    128 
    129   clear(sstl);
    130 
    131   if((res = parse_header(sstl, fp, name)) != RES_OK) goto error;
    132   if((res = parse_triangle_count(sstl, fp, name, &ntris)) != RES_OK) goto error;
    133 
    134   FOR_EACH(i, 0, ntris) {
    135     if((res = parse_triangle(sstl, fp, name, i)) != RES_OK) goto error;
    136   }
    137 
    138   sstl->type = SSTL_BINARY;
    139 
    140 exit:
    141   htable_vertex_purge(&sstl->vertex2id); /* Purge the helper structure */
    142   return res;
    143 error:
    144   clear(sstl);
    145   goto exit;
    146 }