mtool_args.c (4833B)
1 /* Copyright (C) 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 General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 16 #define _POSIX_C_SOURCE 200112L /* getopt support */ 17 18 #include "mtool_args.h" 19 #include "mtool_version.h" 20 21 #include <rsys/cstr.h> 22 #include <rsys/double3.h> 23 24 #include <unistd.h> /* getopt */ 25 26 /******************************************************************************* 27 * Helper functions 28 ******************************************************************************/ 29 static INLINE void 30 usage(FILE* stream) 31 { 32 fprintf(stream, 33 "usage: mesh-tool [-abdhrv] [-i input] [-o output] [-S sx,sy,sz] [-T tx,ty,tz]\n" 34 " [-V verbosity]\n"); 35 } 36 37 static INLINE void 38 version(FILE* stream) 39 { 40 fprintf(stream, 41 "mesh-tool version %i.%i.%i\n", 42 MTOOL_VERSION_MAJOR, 43 MTOOL_VERSION_MINOR, 44 MTOOL_VERSION_PATCH); 45 } 46 47 static res_T 48 apply_scale(struct mtool_args* args, const char* str) 49 { 50 double scale[3] = {0,0,0}; 51 size_t len = 0; 52 res_T res = RES_OK; 53 54 ASSERT(args && str); 55 56 res = cstr_to_list_double(str, ',', scale, &len, 3); 57 if(res == RES_OK && len != 3) res = RES_BAD_ARG; 58 if(res != RES_OK) goto error; 59 60 /* | Sx 0 0 0 | | A, D G J | | A*Sx D*Sx G*Sx J*Sx | 61 * M = | 0 Sy 0 0 | * | B, E H K | = | B*Sy E*Sy H*Sy K*Sy | 62 * | 0 0 Sz 0 | | C, F I L | | C*Sz F*Sz I*Sz L*Sz | 63 * | 0 0 0 1 | | 0, 0 0 1 | | 0 0 0 1 | */ 64 d3_mul(args->transform+0, args->transform+0, scale); 65 d3_mul(args->transform+3, args->transform+3, scale); 66 d3_mul(args->transform+6, args->transform+6, scale); 67 d3_mul(args->transform+9, args->transform+9, scale); 68 69 exit: 70 return res; 71 error: 72 goto exit; 73 } 74 75 static res_T 76 apply_translation(struct mtool_args* args, const char* str) 77 { 78 double translation[3] = {0,0,0}; 79 size_t len = 0; 80 res_T res = RES_OK; 81 82 ASSERT(args && str); 83 84 res = cstr_to_list_double(str, ',', translation, &len, 3); 85 if(res == RES_OK && len != 3) res = RES_BAD_ARG; 86 if(res != RES_OK) goto error; 87 88 /* | 1 0 0 Tx | | A D G J | | A D G (Tx + J) | 89 * M = | 0 1 0 Ty | * | B E H K | = | B E H (Ty + K) | 90 * | 0 0 1 Tz | | C F I L | | C F I (Tz + L) | 91 * | 0 0 0 1 | | 0 0 0 1 | | 0 0 0 1 | */ 92 d3_add(args->transform+9, args->transform+9, translation); 93 94 exit: 95 return res; 96 error: 97 goto exit; 98 } 99 100 static res_T 101 parse_verbosity(struct mtool_args* args, const char* str) 102 { 103 unsigned verbosity = 0; 104 res_T res = RES_OK; 105 106 ASSERT(args && str); 107 108 res = cstr_to_uint(str, &verbosity); 109 if(res == RES_OK && verbosity > 3) res = RES_BAD_ARG; 110 if(res != RES_OK) goto error; 111 112 args->verbose = (int)verbosity; 113 114 exit: 115 return res; 116 error: 117 goto exit; 118 } 119 120 /******************************************************************************* 121 * Local functions 122 ******************************************************************************/ 123 res_T 124 mtool_args_init 125 (struct mtool_args* args, 126 int argc, 127 char** argv) 128 { 129 const char option_list[] = "abdhi:o:rS:T:vV:"; 130 int opt = 0; 131 res_T res = RES_OK; 132 133 ASSERT(args && argc && argv); 134 135 *args = MTOOL_ARGS_DEFAULT; 136 137 while((opt = getopt(argc, argv, option_list)) != -1) { 138 switch (opt) { 139 case 'a': args->type = SSTL_ASCII; break; 140 case 'b': args->type = SSTL_BINARY; break; 141 case 'd': args->print_desc = 1; break; 142 case 'h': 143 usage(stdout); 144 args->quit = 1; 145 goto exit; 146 case 'i': args->input = optarg; break; 147 case 'o': args->output = optarg; break; 148 case 'r': args->reverse_normals = 1; break; 149 case 'S': res = apply_scale(args, optarg); break; 150 case 'T': res = apply_translation(args, optarg); break; 151 case 'v': 152 version(stdout); 153 args->quit = 1; 154 goto exit; 155 case 'V': res = parse_verbosity(args, optarg); break; 156 default: res = RES_BAD_ARG; break; 157 } 158 if(res != RES_OK) { 159 if(optarg) { 160 fprintf(stderr, "mesh-tool: invalid option argument '%s' -- '%c'\n", 161 optarg, opt); 162 } 163 goto error; 164 } 165 } 166 167 exit: 168 return res; 169 error: 170 mtool_args_release(args); 171 usage(stderr); 172 goto exit; 173 } 174 175 void 176 mtool_args_release(struct mtool_args* args) 177 { 178 ASSERT(args); 179 *args = MTOOL_ARGS_DEFAULT; 180 }