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 }