123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913 |
- /*
- * m3dconv/objnurbs.h
- *
- * Copyright (C) 2019 bzt (bztsrc@gitlab)
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * @brief simple 3D model to M3D converter OBJ (with NURBS) importer
- * https://gitlab.com/bztsrc/model3d
- *
- */
- typedef struct {
- int type;
- unsigned int num;
- uint32_t *data;
- } csmod_t;
- /**
- * Parse material file
- */
- void mtl_load(char *fn, m3d_t *m3d)
- {
- unsigned int siz, i, j, k, l;
- char *s, *e, *data, *path, *bn;
- float r,g,b,a;
- m3dm_t *m;
- storeinline = 0;
- data = (char*)readfile(fn, &siz);
- storeinline = doinline;
- if(data) {
- if(verbose > 2) printf(" Material library '%s'\n", fn);
- while(*data) {
- while(*data && (*data == ' ' || *data == '\t' || *data == '\r' || *data == '\n')) data++;
- if(!*data) break;
- /* comments */
- if(*data == '#') { data = _m3d_findnl(data); continue; }
- /* material */
- if(!memcmp(data, "newmtl", 6)) {
- m = NULL;
- data = _m3d_findarg(data + 6);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- s = _m3d_safestr(data, 0);
- if(!s || !*s) goto skip;
- for(j = 0, i = -1U; j < m3d->nummaterial; j++)
- if(!strcmp(s, m3d->material[j].name)) { i = j; free(s); break; }
- if(i == -1U) {
- i = m3d->nummaterial++;
- m3d->material = (m3dm_t*)realloc(m3d->material, m3d->nummaterial * sizeof(m3dm_t));
- if(!m3d->material) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- m = &m3d->material[i];
- m->name = s;
- m->numprop = 0;
- m->prop = NULL;
- } else
- m = &m3d->material[i];
- }
- if(m) {
- k = i = 256;
- if(!memcmp(data, "map_", 4)) {
- k = m3dpf_map;
- data += 4;
- }
- for(j = 0; j < sizeof(m3d_propertytypes)/sizeof(m3d_propertytypes[0]); j++)
- if(!memcmp(data, m3d_propertytypes[j].key, strlen(m3d_propertytypes[j].key))) {
- i = m3d_propertytypes[j].id;
- if(k != m3dpf_map) k = m3d_propertytypes[j].format;
- break;
- }
- if(i != 256 && k != 256) {
- data = _m3d_findarg(data);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- i += (k == m3dpf_map && i < 128 ? 128 : 0);
- for(l = 0, j = -1U; l < m->numprop; l++)
- if(m->prop[l].type == i) { j = l; break; }
- if(j == -1U) {
- j = m->numprop++;
- m->prop = (m3dp_t*)realloc(m->prop, m->numprop * sizeof(m3dp_t));
- if(!m->prop) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- m->prop[j].type = i;
- }
- switch(k) {
- case m3dpf_color:
- r = g = b = a = 0.0f;
- data = _m3d_getfloat(data, &r);
- data = _m3d_getfloat(data, &g);
- data = _m3d_getfloat(data, &b);
- if(*data && *data != '\r' && *data != '\n')
- data = _m3d_getfloat(data, &a);
- else
- a = 1.0f;
- m->prop[j].value.color = ((uint8_t)(a*255) << 24L) |
- ((uint8_t)(b*255) << 16L) |
- ((uint8_t)(g*255) << 8L) |
- ((uint8_t)(r*255) << 0L);
- break;
- case m3dpf_uint8:
- case m3dpf_uint16:
- case m3dpf_uint32: data = _m3d_getint(data, &m->prop[j].value.num); break;
- case m3dpf_float: data = _m3d_getfloat(data, &m->prop[j].value.fnum); break;
- case m3dpf_map:
- s = e = _m3d_findnl(data);
- while(e > data && (e[-1] == ' ' || e[-1] == '\t' || e[-1] == '\r' || e[-1] == '\n')) e--;
- for(i = 0; s > data && s[-1] != ' ' && s[-1] != '/' && s[-1] != '\\'; s--)
- if(!i && *s == '.') { i = 1; *s = 0; }
- data = e;
- e = s;
- s = _m3d_safestr(s, 0);
- if(!s || !*s) goto skip;
- for(i = 0, l = -1U; i < m3d->numtexture; i++) {
- if(!strcmp(s, m3d->texture[i].name)) { l = i; free(s); break; }
- }
- if(l == -1U) {
- if(storeinline) {
- path = (char*)malloc(strlen(fn) + strlen(e) + 5);
- strcpy(path, fn);
- bn = strrchr(path, '/');
- if(!bn) bn = strrchr(path, '\\');
- if(!bn) bn = path; else bn++;
- strcpy(bn, e);
- bn += strlen(e);
- strcpy(bn, ".png");
- if(!readfile(path, &l)) {
- strcpy(bn, ".PNG");
- if(!readfile(path, &l)) {
- for(l = strlen(path)-1; l > 0 && path[l]!='/' && path[l]!='\\'; l--)
- if(path[l] >= 'A' && path[l] <= 'Z') path[l] += 'a'-'A';
- readfile(path, &l);
- }
- }
- if(l && verbose>1) printf(" Inlining '%s'\n", s);
- }
- l = m3d->numtexture++;
- m3d->texture = (m3dtx_t*)realloc(m3d->texture, m3d->numtexture * sizeof(m3dtx_t));
- if(!m3d->texture) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- m3d->texture[l].name = s;
- m3d->texture[l].w = m3d->texture[l].h = 0;
- m3d->texture[l].d = NULL;
- }
- m->prop[j].value.textureid = l;
- break;
- }
- }
- }
- skip: data = _m3d_findnl(data);
- }
- }
- }
- /**
- * Load a model and convert it's structures into a Model 3D in-memory format
- */
- m3d_t *obj_load(char *data, char *fn)
- {
- unsigned int i, j, sidx = 0, cidx = 0, numv = 0, numn = 0, nump = 0, numm = 0, numc, numpu, numpv, numsp, mi = -1U;
- unsigned int boneid = -1U, maxv = 0, maxn = 0, maxp = 0, maxuv = 0, maxl = 0;
- uint32_t cstype = 0, degu, degv, rangeu, rangev, csidx = 0, *sp = NULL, *ctrl = NULL, *cidxs = NULL, *sidxs = NULL;
- int idx;
- char *s, *an, *bn, *path, name[6];
- float r,g,b,a, ures, vres, maxlen, maxdist, maxangle, *paru = NULL, *parv = NULL;
- m3d_t *m3d;
- m3dv_t *v, *vertex = NULL, *normal = NULL, *param = NULL;
- m3dh_t *h;
- csmod_t *mod = NULL;
- m3d = (m3d_t*)malloc(sizeof(m3d_t));
- if(!m3d) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- memset(m3d, 0, sizeof(m3d_t));
- m3d->flags = M3D_FLG_FREESTR;
- /* add default position and orientation, may be needed by bones in group statements */
- m3d->numvertex = 2;
- m3d->vertex = (m3dv_t*)malloc(m3d->numvertex * sizeof(m3dv_t));
- if(!m3d->vertex) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- memset(m3d->vertex, 0, 2 * sizeof(m3dv_t));
- m3d->vertex[0].skinid = -1U;
- m3d->vertex[0].type = VT_WORLD;
- m3d->vertex[1].skinid = -2U;
- m3d->vertex[1].type = VT_QUATERN;
- while(*data) {
- while(*data && (*data == ' ' || *data == '\t' || *data == '\r' || *data == '\n')) data++;
- if(!*data) break;
- /* comments */
- if(*data == '#') { data = _m3d_findnl(data); continue; }
- /* annotation label, not in the spec, but I needed it. This is the only statement I've added
- * "a (vertexid) (utf-8 string without control characters)"
- */
- if(data[0] == 'a' && data[1] == ' ') {
- data = _m3d_findarg(data + 1);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- data = _m3d_getint(data, (unsigned int*)&idx);
- if(idx > 0) idx--; else idx = numv - idx;
- data = _m3d_findarg(data);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- s = _m3d_safestr(data, 2);
- if(!s || !*s) goto skip;
- i = m3d->numlabel++;
- if(m3d->numlabel >= maxl) {
- maxl += 256;
- m3d->label = (m3dl_t*)realloc(m3d->label, maxl * sizeof(m3dl_t));
- if(!m3d->label) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- }
- m3d->label[i].name = NULL;
- m3d->label[i].lang = NULL;
- m3d->label[i].color = 0;
- m3d->label[i].vertexid = idx + m3d->numvertex;
- m3d->label[i].text = s;
- } else
- /* object name and groups */
- if(data[1] == ' ' && (data[0] == 'o' || data[0] == 'g')) {
- s = data;
- data = _m3d_findarg(data + 1);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- /* there can be several "o " lines, but we only use the first as model name */
- if(s[0] == 'o' && !m3d->name) m3d->name = _m3d_safestr(data, 2);
- /* create a bone for each group */
- boneid = -1U;
- an = _m3d_safestr(data, 0);
- if(an) {
- for(i = 0; i < m3d->numbone; i++)
- if(!strcmp(an, m3d->bone[i].name)) { boneid = i; break; }
- if(boneid == -1U) {
- boneid = m3d->numbone++;
- m3d->bone = (m3db_t*)realloc(m3d->bone, m3d->numbone * sizeof(m3db_t));
- if(!m3d->bone) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- memset(&m3d->bone[boneid], 0, sizeof(m3db_t));
- m3d->bone[boneid].parent = (M3D_INDEX)-1U;
- m3d->bone[boneid].name = an;
- m3d->bone[boneid].pos = 0;
- m3d->bone[boneid].ori = 1;
- } else
- free(an);
- }
- csidx = 0;
- } else
- /* material library */
- if(!memcmp(data, "mtllib", 6)) {
- data = _m3d_findarg(data + 6);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- s = bn = _m3d_findnl(data);
- while(bn > data && (bn[-1] == ' ' || bn[-1] == '\t' || bn[-1] == '\r' || bn[-1] == '\n')) bn--;
- while(s > data && s[-1] != '/' && s[-1] != '\\') s--;
- *bn++ = 0;
- data = bn;
- path = (char*)malloc(strlen(fn) + strlen(s) + 5);
- if(!path) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- strcpy(path, fn);
- bn = strrchr(path, '/');
- if(!bn) bn = strrchr(path, '\\');
- if(!bn) bn = path; else bn++;
- strcpy(bn, s);
- mtl_load(path, m3d);
- free(path);
- continue;
- } else
- /* use material */
- if(!memcmp(data, "usemtl", 6)) {
- data = _m3d_findarg(data + 6);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- mi = (M3D_INDEX)-1U;
- if(*data && *data != '\r' && *data != '\n') {
- s = _m3d_safestr(data, 0);
- if(!s || !*s) goto skip;
- for(i = 0; i < m3d->nummaterial; i++)
- if(!strcmp(s, m3d->material[i].name)) {
- mi = (M3D_INDEX)i;
- break;
- }
- free(s);
- }
- } else
- /* vertex lists */
- if(data[0] == 'v' && (data[1] == ' ' || (data[2] == ' ' && (data[1] == 'n' || data[1] == 'p')))) {
- s = data + 1;
- data = _m3d_findarg(data);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- v = NULL;
- switch(*s) {
- case 'n':
- i = numn++;
- if(numn >= maxn) {
- maxn += 1024;
- normal = (m3dv_t*)realloc(normal, maxn * sizeof(m3dv_t));
- if(!normal) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- }
- v = &normal[i];
- break;
- case 'p':
- i = nump++;
- if(nump >= maxp) {
- maxp += 1024;
- param = (m3dv_t*)realloc(param, maxp * sizeof(m3dv_t));
- if(!param) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- }
- v = ¶m[i];
- break;
- default:
- i = numv++;
- if(numv >= maxv) {
- maxv += 1024;
- vertex = (m3dv_t*)realloc(vertex, maxv * sizeof(m3dv_t));
- if(!vertex) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- }
- v = &vertex[i];
- break;
- }
- if(!v) goto skip;
- memset(v, 0, sizeof(m3dv_t));
- if(*s == 'n') v->type = VT_NORMAL;
- v->skinid = (M3D_INDEX)-1U;
- v->w = (M3D_FLOAT)1.0;
- data = _m3d_getfloat(data, &v->x);
- if(*data && *data != '\r' && *data != '\n') {
- data = _m3d_getfloat(data, &v->y);
- if(*data && *data != '\r' && *data != '\n') {
- data = _m3d_getfloat(data, &v->z);
- if((*s == ' ' || *s == 'p') && *data && *data != '\r' && *data != '\n') {
- data = _m3d_getfloat(data, &v->w);
- if(*s == ' ' && *data && *data != '\r' && *data != '\n') {
- r = g = b = a = 0.0f;
- data = _m3d_getfloat(data, &r);
- data = _m3d_getfloat(data, &g);
- if(!*data || *data == '\r' || *data == '\n') {
- a = 1.0f; b = g; g = r; r = v->w;
- v->w = (M3D_FLOAT)1.0;
- } else {
- data = _m3d_getfloat(data, &b);
- if(*data && *data != '\r' && *data != '\n')
- data = _m3d_getfloat(data, &a);
- else
- a = 1.0f;
- }
- v->color = ((uint8_t)(a*255) << 24L) |
- ((uint8_t)(b*255) << 16L) |
- ((uint8_t)(g*255) << 8L) |
- ((uint8_t)(r*255) << 0L);
- }
- }
- }
- }
- } else
- /* texture map lists */
- if(data[0] == 'v' && data[1] == 't' && data[2] == ' ') {
- data = _m3d_findarg(data + 2);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- i = m3d->numtmap++;
- if(m3d->numtmap >= maxuv) {
- maxuv += 1024;
- m3d->tmap = (m3dti_t*)realloc(m3d->tmap, maxuv * sizeof(m3dti_t));
- if(!m3d->tmap) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- }
- m3d->tmap[i].u = m3d->tmap[i].v = (M3D_FLOAT)0.0;
- data = _m3d_getfloat(data, &m3d->tmap[i].u);
- if(*data && *data != '\r' && *data != '\n')
- data = _m3d_getfloat(data, &m3d->tmap[i].v);
- } else
- /* mesh face */
- if(data[0] == 'f' && data[1] == ' ') {
- data = _m3d_findarg(data + 1);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- bn = _m3d_findnl(data);
- i = 3 * ((int)(bn - data) / 2) * sizeof(uint32_t);
- ctrl = (uint32_t*)realloc(ctrl, i);
- if(!ctrl) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- memset(ctrl, 255, i);
- /* get the polygon */
- for(numc = 0; *data && *data != '\r' && *data != '\n'; numc += 3) {
- data = _m3d_getint(data, (unsigned int*)&idx);
- if(idx > 0) idx--; else idx = numv - idx;
- ctrl[numc] = idx + m3d->numvertex;
- if(*data == '/') {
- data++;
- if(*data != '/') {
- data = _m3d_getint(data, (unsigned int*)&idx);
- if(idx > 0) idx--; else idx = m3d->numtmap - idx;
- ctrl[numc + 1] = idx;
- }
- if(*data == '/') {
- data = _m3d_getint(data + 1, (unsigned int*)&idx);
- if(idx > 0) idx--; else idx = numn - idx;
- ctrl[numc + 2] = idx + numv + m3d->numvertex;
- }
- }
- data = _m3d_findarg(data);
- }
- if(numc < 9) goto skip;
- /* triangulate, assuming CCW */
- numm = (numc / 3) - 2;
- i = m3d->numface; m3d->numface += numm;
- m3d->face = (m3df_t*)realloc(m3d->face, m3d->numface * sizeof(m3df_t));
- if(!m3d->face) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- memset(&m3d->face[i], 255, sizeof(m3df_t)); /* set all index to -1 by default */
- for(j = 6; j < numc; j += 3, i++) {
- m3d->face[i].materialid = mi;
- m3d->face[i].vertex[0] = (M3D_INDEX)ctrl[0];
- m3d->face[i].texcoord[0] = (M3D_INDEX)ctrl[1];
- m3d->face[i].normal[0] = (M3D_INDEX)ctrl[2];
- m3d->face[i].vertex[1] = (M3D_INDEX)ctrl[j - 3];
- m3d->face[i].texcoord[1] = (M3D_INDEX)ctrl[j - 2];
- m3d->face[i].normal[1] = (M3D_INDEX)ctrl[j - 1];
- m3d->face[i].vertex[2] = (M3D_INDEX)ctrl[j + 0];
- m3d->face[i].texcoord[2] = (M3D_INDEX)ctrl[j + 1];
- m3d->face[i].normal[2] = (M3D_INDEX)ctrl[j + 2];
- }
- } else
- if(!domesh) {
- /* curves and surfaces */
- if(!memcmp(data, "cstype", 6)) {
- data = _m3d_findarg(data + 6);
- if(!memcmp(data, "rat", 3)) data = _m3d_findarg(data);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- cstype = 0;
- if(!memcmp(data, "bezier", 6)) cstype = 1; else
- if(!memcmp(data, "bspline", 7)) cstype = 4; else {
- if(verbose > 1) {
- for(s = data; *s && *s != '\r' && *s != '\n'; s++);
- *s = 0;
- printf(" Unknown curve / surface type '%s'\n", data);
- data = s + 1;
- }
- while(*data && memcmp(data, "end", 3)) data++;
- goto skip;
- }
- degu = degv = numc = numpv = numpu = numsp = numm = 0;
- rangeu = rangev = -1U;
- ures = vres = maxlen = maxdist = maxangle = 1.0f;
- } else
- if(cstype) {
- /* arguments for curves / surfaces */
- if(!memcmp(data, "deg", 3)) {
- data = _m3d_findarg(data + 3);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- data = _m3d_getint(data, °u);
- if(*data && *data != '\r' && *data != '\n')
- data = _m3d_getint(data, °v);
- else
- degv = degu;
- } else
- if((data[0] == 'c' && data[1] == 's') && !memcmp(data + 1, "tech", 4)) {
- data = _m3d_findarg(data + 5);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- if(!memcmp(data, "cparm", 5)) {
- s = data + 5;
- data = _m3d_findarg(data + 5);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- data = _m3d_getfloat(data, &ures);
- if(*s == 'b' && *data && *data != '\r' && *data != '\n')
- data = _m3d_getfloat(data, &vres);
- else
- vres = ures;
- } else
- if(!memcmp(data, "cspace", 6)) {
- data = _m3d_findarg(data + 6);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- data = _m3d_getfloat(data, &maxlen);
- } else
- if(!memcmp(data, "curv", 4)) {
- data = _m3d_findarg(data + 4);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- data = _m3d_getfloat(data, &maxdist);
- if(*data && *data != '\r' && *data != '\n')
- data = _m3d_getfloat(data, &maxangle);
- }
- } else
- if(!memcmp(data, "parm", 4)) {
- data = _m3d_findarg(data + 4);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- bn = _m3d_findnl(data);
- s = data;
- data = _m3d_findarg(data);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- if(*s != 'v') {
- paru = (float*)realloc(paru, ((int)(bn - data) / 2) * sizeof(float));
- if(!paru) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- for(numpu = 0; *data && *data != '\r' && *data != '\n'; numpu++)
- data = _m3d_getfloat(data, &paru[numpu]);
- } else {
- parv = (float*)realloc(parv, ((int)(bn - data) / 2) * sizeof(float));
- if(!parv) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- for(numpv = 0; *data && *data != '\r' && *data != '\n'; numpv++)
- data = _m3d_getfloat(data, &parv[numpv]);
- }
- } else
- if(!memcmp(data, "sp", 2)) {
- data = _m3d_findarg(data + 2);
- bn = _m3d_findnl(data);
- sp = (uint32_t*)realloc(sp, ((int)(bn - data) / 2) * sizeof(uint32_t));
- if(!sp) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- for(numsp = 0; *data && *data != '\r' && *data != '\n'; numsp++) {
- data = _m3d_getint(data, (unsigned int*)&idx);
- if(idx > 0) idx--; else idx = nump - idx;
- sp[numsp] = idx + numv + numn;
- data = _m3d_findarg(data);
- }
- } else
- if(!memcmp(data, "trim", 4) || !memcmp(data, "hole", 4) || !memcmp(data, "scrv", 4)) {
- i = numm++;
- mod = (csmod_t*)realloc(mod, numm * sizeof(uint32_t));
- if(!mod) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- switch(*data) {
- case 't': mod[i].type = m3dc_trim; break;
- case 'h': mod[i].type = m3dc_hole; break;
- case 's': mod[i].type = m3dc_scrv; break;
- }
- mod[i].num = 0;
- s = data;
- data = _m3d_findarg(data + 4);
- bn = _m3d_findnl(data);
- mod[i].data = (uint32_t*)malloc(((int)(bn - data) / 6) * 2 * sizeof(uint32_t));
- if(!mod[i].data) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- for(mod[i].num = 0; *data && *data != '\r' && *data != '\n';) {
- j = m3d->numtmap++;
- if(m3d->numtmap >= maxuv) {
- maxuv += 1024;
- m3d->tmap = (m3dti_t*)realloc(m3d->tmap, maxuv * sizeof(m3dti_t));
- if(!m3d->tmap) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- }
- m3d->tmap[j].u = m3d->tmap[j].v = (M3D_FLOAT)0.0;
- data = _m3d_getfloat(data, &m3d->tmap[j].u);
- if(*data && *data != '\r' && *data != '\n') {
- data = _m3d_getfloat(data, &m3d->tmap[j].v);
- mod[i].data[mod[i].num++] = j;
- if(*data && *data != '\r' && *data != '\n' && !cidxs) {
- data = _m3d_getint(data, (unsigned int*)&idx);
- if(idx > 0) idx--; else idx = cidx - idx;
- mod[i].data[mod[i].num++] = cidxs[idx];
- data = _m3d_findarg(data);
- }
- }
- }
- } else
- /* control points */
- if(!memcmp(data, "curv2", 5)) {
- cstype++;
- data = _m3d_findarg(data + 5);
- bn = _m3d_findnl(data);
- ctrl = (uint32_t*)realloc(ctrl, ((int)(bn - data) / 2) * sizeof(uint32_t));
- if(!ctrl) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- for(numc = 0; *data && *data != '\r' && *data != '\n'; numc++) {
- data = _m3d_getint(data, (unsigned int*)&idx);
- if(idx > 0) idx--; else idx = nump - idx;
- ctrl[numc] = idx + numv + numn + m3d->numvertex;
- data = _m3d_findarg(data);
- }
- } else
- if(!memcmp(data, "curv", 4)) {
- data = _m3d_findarg(data + 4);
- i = m3d->numtmap++;
- if(m3d->numtmap >= maxuv) {
- maxuv += 1024;
- m3d->tmap = (m3dti_t*)realloc(m3d->tmap, maxuv * sizeof(m3dti_t));
- if(!m3d->tmap) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- }
- m3d->tmap[i].u = m3d->tmap[i].v = (M3D_FLOAT)0.0;
- data = _m3d_getfloat(data, &m3d->tmap[i].u);
- if(*data && *data != '\r' && *data != '\n')
- data = _m3d_getfloat(data, &m3d->tmap[i].v);
- rangeu = i;
- bn = _m3d_findnl(data);
- ctrl = (uint32_t*)realloc(ctrl, ((int)(bn - data) / 2) * sizeof(uint32_t));
- if(!ctrl) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- for(numc = 0; *data && *data != '\r' && *data != '\n'; numc++) {
- data = _m3d_getint(data, (unsigned int*)&idx);
- if(idx > 0) idx--; else idx = numv - idx;
- ctrl[numc] = idx;
- data = _m3d_findarg(data);
- }
- } else
- if(!memcmp(data, "surf", 4)) {
- cstype += 2;
- data = _m3d_findarg(data + 4);
- i = m3d->numtmap++;
- if(m3d->numtmap >= maxuv) {
- maxuv += 1024;
- m3d->tmap = (m3dti_t*)realloc(m3d->tmap, maxuv * sizeof(m3dti_t));
- if(!m3d->tmap) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- }
- m3d->tmap[i].u = m3d->tmap[i].v = (M3D_FLOAT)0.0;
- data = _m3d_getfloat(data, &m3d->tmap[i].u);
- if(*data && *data != '\r' && *data != '\n')
- data = _m3d_getfloat(data, &m3d->tmap[i].v);
- rangeu = i;
- i = m3d->numtmap++;
- if(m3d->numtmap >= maxuv) {
- maxuv += 1024;
- m3d->tmap = (m3dti_t*)realloc(m3d->tmap, maxuv * sizeof(m3dti_t));
- if(!m3d->tmap) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- }
- m3d->tmap[i].u = m3d->tmap[i].v = (M3D_FLOAT)0.0;
- data = _m3d_getfloat(data, &m3d->tmap[i].u);
- if(*data && *data != '\r' && *data != '\n')
- data = _m3d_getfloat(data, &m3d->tmap[i].v);
- rangev = i;
- bn = _m3d_findnl(data);
- ctrl = (uint32_t*)realloc(ctrl, 3 * ((int)(bn - data) / 2) * sizeof(uint32_t));
- if(!ctrl) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- for(numc = 0; *data && *data != '\r' && *data != '\n';) {
- data = _m3d_getint(data, (unsigned int*)&idx);
- if(idx > 0) idx--; else idx = numv - idx;
- ctrl[numc++] = idx + m3d->numvertex;
- if(*data == '/') {
- data++;
- if(*data != '/') {
- data = _m3d_getint(data, (unsigned int*)&idx);
- if(idx > 0) idx--; else idx = m3d->numtmap - idx;
- ctrl[numc++] = idx;
- cstype |= 0x40;
- }
- if(*data == '/') {
- data = _m3d_getint(data + 1, (unsigned int*)&idx);
- if(idx > 0) idx--; else idx = numn - idx;
- ctrl[numc++] = idx + numv + m3d->numvertex;
- cstype |= 0x80;
- }
- }
- data = _m3d_findarg(data);
- }
- } else
- /* on block end, convert everything into M3D shape commands */
- if(!memcmp(data, "end", 3)) {
- if(numc && degu) {
- /* add a new shape if we must */
- if(!csidx) {
- i = m3d->numshape++;
- m3d->shape = (m3dh_t*)realloc(m3d->shape, m3d->numshape * sizeof(m3dh_t));
- if(!m3d->shape) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- h = &m3d->shape[i];
- h->numcmd = 0;
- h->cmd = NULL;
- h->group = boneid;
- sprintf(name, "s%04X", i);
- h->name = _m3d_safestr((char*)&name, 0);
- }
- /* count how many commands we need */
- j = 1 + numm;
- if(ures != 1.0f || vres != 1.0f) j++;
- if(maxlen != 1.0f) j++;
- if(maxdist != 1.0f || maxangle != 1.0f) j++;
- if(degu || degv) j++;
- if(rangeu != -1U || rangev != -1U) j++;
- if(numpu) j++;
- if(numpv) j++;
- i = h->numcmd; h->numcmd += j;
- /* allocate commands */
- h->cmd = (m3dc_t*)realloc(h->cmd, h->numcmd * sizeof(m3dc_t));
- if(!h->cmd) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- /* add commands */
- if(ures != 1.0f || vres != 1.0f) {
- if(ures == vres) {
- h->cmd[i].type = m3dc_div;
- h->cmd[i].arg = (uint32_t*)malloc(1 * sizeof(uint32_t));
- if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- memcpy(&h->cmd[i].arg[0], &ures, sizeof(uint32_t));
- } else {
- h->cmd[i].type = m3dc_sub;
- h->cmd[i].arg = (uint32_t*)malloc(2 * sizeof(uint32_t));
- if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- memcpy(&h->cmd[i].arg[0], &ures, sizeof(uint32_t));
- memcpy(&h->cmd[i].arg[1], &vres, sizeof(uint32_t));
- }
- i++;
- }
- if(maxlen != 1.0f) {
- h->cmd[i].type = m3dc_len;
- h->cmd[i].arg = (uint32_t*)malloc(1 * sizeof(uint32_t));
- if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- memcpy(&h->cmd[i].arg[0], &maxlen, sizeof(uint32_t));
- i++;
- }
- if(maxdist != 1.0f || maxangle != 1.0f) {
- h->cmd[i].type = m3dc_dist;
- h->cmd[i].arg = (uint32_t*)malloc(2 * sizeof(uint32_t));
- if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- memcpy(&h->cmd[i].arg[0], &maxdist, sizeof(uint32_t));
- memcpy(&h->cmd[i].arg[1], &maxangle, sizeof(uint32_t));
- i++;
- }
- if(degu || degv) {
- if(degu == degv) {
- h->cmd[i].type = m3dc_degu;
- h->cmd[i].arg = (uint32_t*)malloc(1 * sizeof(uint32_t));
- if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- h->cmd[i].arg[0] = degu;
- } else {
- h->cmd[i].type = m3dc_deg;
- h->cmd[i].arg = (uint32_t*)malloc(2 * sizeof(uint32_t));
- if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- h->cmd[i].arg[0] = degu;
- h->cmd[i].arg[1] = degv;
- }
- i++;
- }
- if(rangeu != -1U || rangev != -1U) {
- if(rangev == -1U) {
- h->cmd[i].type = m3dc_rangeu;
- h->cmd[i].arg = (uint32_t*)malloc(1 * sizeof(uint32_t));
- if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- h->cmd[i].arg[0] = rangeu;
- } else {
- h->cmd[i].type = m3dc_range;
- h->cmd[i].arg = (uint32_t*)malloc(2 * sizeof(uint32_t));
- if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- h->cmd[i].arg[0] = rangeu;
- h->cmd[i].arg[1] = rangev;
- }
- i++;
- }
- if(numpu) {
- h->cmd[i].type = m3dc_paru;
- h->cmd[i].arg = (uint32_t*)malloc((numpu + 1) * sizeof(uint32_t));
- if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- h->cmd[i].arg[0] = numpu;
- memcpy(&h->cmd[i].arg[1], &paru, numpu * sizeof(uint32_t));
- i++;
- }
- if(numpv) {
- h->cmd[i].type = m3dc_parv;
- h->cmd[i].arg = (uint32_t*)malloc((numpv + 1) * sizeof(uint32_t));
- if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- h->cmd[i].arg[0] = numpv;
- memcpy(&h->cmd[i].arg[1], &parv, numpv * sizeof(uint32_t));
- i++;
- }
- for(j = 0; j < numm; j++) {
- h->cmd[i].type = mod[j].type;
- h->cmd[i].arg = (uint32_t*)malloc((mod[j].num + 1) * sizeof(uint32_t));
- if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- h->cmd[i].arg[0] = mod[j].num;
- memcpy(&h->cmd[i].arg[1], &mod[j].data, mod[j].num * sizeof(uint32_t));
- free(mod[j].data);
- i++;
- }
- j = (cstype >> 6) & 3;
- if((cstype & 0x3F) == 3 || (cstype & 0x3F) == 6) {
- sidxs = (uint32_t*)realloc(sidxs, (sidx+1) * sizeof(uint32_t));
- sidxs[sidx] = csidx;
- } else {
- cidxs = (uint32_t*)realloc(cidxs, (cidx+1) * sizeof(uint32_t));
- cidxs[cidx] = csidx;
- }
- switch(cstype & 0x3F) {
- case 1: j = m3dc_bez1; cidx++; break;
- case 2: j = m3dc_bez2; cidx++; break;
- case 3: j += m3dc_bez; sidx++; break;
- case 4: j = m3dc_bsp1; cidx++; break;
- case 5: j = m3dc_bsp2; cidx++; break;
- case 6: j += m3dc_nurbs; sidx++; break;
- }
- h->cmd[i].type = j;
- h->cmd[i].arg = (uint32_t*)malloc((numc + 1) * sizeof(uint32_t));
- if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- h->cmd[i].arg[0] = (cstype & 0xC0) == 0xC0 ? numc / 3 : (cstype & 0xC0 ? numc / 2 : numc);
- memcpy(&h->cmd[i].arg[1], &ctrl, numc * sizeof(uint32_t));
- csidx++;
- }
- cstype = 0;
- }
- } else
- if(data[0] == 'l' && data[1] == ' ') {
- data = _m3d_findarg(data + 1);
- if(!*data || *data == '\r' || *data == '\n') goto skip;
- /* add a new shape if we must */
- if(!csidx) {
- i = m3d->numshape++;
- m3d->shape = (m3dh_t*)realloc(m3d->shape, m3d->numshape * sizeof(m3dh_t));
- if(!m3d->shape) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- h = &m3d->shape[i];
- h->numcmd = 0;
- h->cmd = NULL;
- h->group = boneid;
- sprintf(name, "s%04X", i);
- h->name = _m3d_safestr((char*)&name, 0);
- }
- i = h->numcmd++;
- h->cmd = (m3dc_t*)realloc(h->cmd, h->numcmd * sizeof(m3dc_t));
- if(!h->cmd) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- bn = _m3d_findnl(data);
- h->cmd[i].arg = (uint32_t*)malloc((((int)(bn - data) / 2) + 1) * sizeof(uint32_t));
- if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- h->cmd[i].type = m3dc_line;
- for(j = 0; *data && *data != '\r' && *data != '\n'; j++) {
- data = _m3d_getint(data, (unsigned int*)&idx);
- if(idx > 0) idx--; else idx = numv - idx;
- h->cmd[i].arg[j + 1] = idx;
- data = _m3d_findarg(data);
- }
- h->cmd[i].arg[0] = j;
- csidx++;
- } else
- if(!memcmp(data, "con", 3) && h) {
- data = _m3d_findarg(data + 3);
- if(!*data || *data == '\r' || *data == '\n' || !cidxs || !sidxs) goto skip;
- /* allocate command and its arguments */
- i = h->numcmd++;
- h->cmd = (m3dc_t*)realloc(h->cmd, h->numcmd * sizeof(m3dc_t));
- if(!h->cmd) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- h->cmd[i].arg = (uint32_t*)malloc(6 * sizeof(uint32_t));
- if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- h->cmd[i].type = m3dc_conn;
- /* get arguments */
- data = _m3d_getint(data, (unsigned int*)&idx);
- if(idx > 0) idx--; else idx = sidx - idx;
- h->cmd[i].arg[0] = sidxs[idx];
- data = _m3d_findarg(data);
- if(!*data || *data == '\r' || *data == '\n') { free(h->cmd[i].arg); h->numcmd--; goto skip; }
- j = m3d->numtmap++;
- if(m3d->numtmap >= maxuv) {
- maxuv += 1024;
- m3d->tmap = (m3dti_t*)realloc(m3d->tmap, maxuv * sizeof(m3dti_t));
- if(!m3d->tmap) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- }
- m3d->tmap[j].u = m3d->tmap[j].v = (M3D_FLOAT)0.0;
- data = _m3d_getfloat(data, &m3d->tmap[j].u);
- if(!*data || *data == '\r' || *data == '\n') { free(h->cmd[i].arg); h->numcmd--; goto skip; }
- data = _m3d_getfloat(data, &m3d->tmap[j].v);
- if(!*data || *data == '\r' || *data == '\n') { free(h->cmd[i].arg); h->numcmd--; goto skip; }
- h->cmd[i].arg[1] = j;
- data = _m3d_getint(data, (unsigned int*)&idx);
- if(idx > 0) idx--; else idx = cidx - idx;
- h->cmd[i].arg[2] = cidxs[idx];
- data = _m3d_findarg(data);
- if(!*data || *data == '\r' || *data == '\n') { free(h->cmd[i].arg); h->numcmd--; goto skip; }
- data = _m3d_getint(data, (unsigned int*)&idx);
- if(idx > 0) idx--; else idx = sidx - idx;
- h->cmd[i].arg[3] = sidxs[idx];
- data = _m3d_findarg(data);
- if(!*data || *data == '\r' || *data == '\n') { free(h->cmd[i].arg); h->numcmd--; goto skip; }
- j = m3d->numtmap++;
- if(m3d->numtmap >= maxuv) {
- maxuv += 1024;
- m3d->tmap = (m3dti_t*)realloc(m3d->tmap, maxuv * sizeof(m3dti_t));
- if(!m3d->tmap) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- }
- m3d->tmap[j].u = m3d->tmap[j].v = (M3D_FLOAT)0.0;
- data = _m3d_getfloat(data, &m3d->tmap[j].u);
- if(!*data || *data == '\r' || *data == '\n') { free(h->cmd[i].arg); h->numcmd--; goto skip; }
- data = _m3d_getfloat(data, &m3d->tmap[j].v);
- if(!*data || *data == '\r' || *data == '\n') { free(h->cmd[i].arg); h->numcmd--; goto skip; }
- h->cmd[i].arg[4] = j;
- data = _m3d_getint(data, (unsigned int*)&idx);
- if(idx > 0) idx--; else idx = cidx - idx;
- h->cmd[i].arg[5] = cidxs[idx];
- }
- }
- skip: data = _m3d_findnl(data);
- }
- i = numv + numn + nump;
- if(i) {
- m3d->vertex = (m3dv_t*)realloc(m3d->vertex, (m3d->numvertex + i) * sizeof(m3dv_t));
- if(!m3d->vertex) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- if(numv) memcpy(&m3d->vertex[m3d->numvertex], vertex, numv * sizeof(m3dv_t));
- if(numn) memcpy(&m3d->vertex[m3d->numvertex + numv], normal, numn * sizeof(m3dv_t));
- if(nump) memcpy(&m3d->vertex[m3d->numvertex + numv + numn], param, nump * sizeof(m3dv_t));
- m3d->numvertex += i;
- }
- if(m3d->numtmap) {
- m3d->tmap = (m3dti_t*)realloc(m3d->tmap, m3d->numtmap * sizeof(m3dti_t));
- if(!m3d->tmap) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- }
- if(m3d->numlabel) {
- m3d->label = (m3dl_t*)realloc(m3d->label, m3d->numlabel * sizeof(m3dl_t));
- if(!m3d->label) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
- }
- if(vertex) free(vertex);
- if(normal) free(normal);
- if(param) free(param);
- if(cidxs) free(cidxs);
- if(sidxs) free(sidxs);
- if(ctrl) free(ctrl);
- if(paru) free(paru);
- if(parv) free(parv);
- if(mod) free(mod);
- if(sp) free(sp);
- return m3d;
- }
|