51 v[i] =
n[i] =
t[i] = 0;
67 for (i = 0; i <
nverts; i++) tmp[i] =
v[i];
68 for (i = 0; i <
nverts; i++)
v[i] = tmp[nverts-1-i];
70 for (i = 0; i <
nverts; i++) tmp[i] =
n[i];
71 for (i = 0; i <
nverts; i++)
n[i] = tmp[nverts-1-i];
73 for (i = 0; i <
nverts; i++) tmp[i] =
t[i];
74 for (i = 0; i <
nverts; i++)
t[i] = tmp[nverts-1-i];
78 static void ParsePoly(
const char* line,
ObjFace* face)
85 v[i] = n[i] = t[i] = 0;
88 const char* p = line + 1;
94 while (*p && i < MAX_OBJ_FACE_VERTS) {
102 while (isdigit(*p)) {
103 v[i] = v[i]*10 + *p -
'0';
108 if (*p ==
'/') { p++;
117 while (isdigit(*p)) {
118 t[i] = t[i]*10 + *p -
'0';
123 if (*p ==
'/') { p++;
132 while (isdigit(*p)) {
133 n[i] = n[i]*10 + *p -
'0';
139 while (isspace(*p)) p++;
152 static int LoadMatls(
const char* lpszPathName,
Model* m)
156 FILE* fp = fopen(lpszPathName,
"r");
158 ::MessageBox(0,
"Open Failed: could not open file",
"ERROR", MB_OK);
167 fgets(raw_line, 512, fp);
169 strcpy(line,
Text(raw_line).trim().data());
171 if (strstr(line,
"newmtl")) {
178 else if (line[0] ==
'K' && line[1] ==
'a') {
180 sscanf(line,
"Ka %f %f %f", &r, &g, &b);
187 else if (line[0] ==
'K' && line[1] ==
'd') {
189 sscanf(line,
"Kd %f %f %f", &r, &g, &b);
196 else if (line[0] ==
'K' && line[1] ==
's') {
198 sscanf(line,
"Ks %f %f %f", &r, &g, &b);
205 else if (line[0] ==
'N' && line[1] ==
's') {
207 sscanf(line,
"Ns %f", &ns);
211 else if (strstr(line,
"map_Kd")) {
212 const char* src = strstr(line,
"map_Kd") + 7;
213 while (!isalnum(*src)) src++;
223 static Material* FindMatl(
const char* mtl_name,
Model* model)
228 if (!strcmp(m->
name, mtl_name))
237 static int mcomp(
const void* a,
const void* b)
254 if (m && scale > 0 && strlen(
filename) > 0) {
260 ::MessageBox(0,
"Wavefront/OBJ Import Failed: Unable to open file",
"ERROR", MB_OK);
274 ZeroMemory(root_path, 256);
278 char* p = strrchr(root_path,
'\\');
285 char* p = strrchr(root_path,
'/');
293 fgets(line, 255, fp);
295 if (line[0] ==
'v') {
297 case ' ': vi++;
break;
298 case 'n': vn++;
break;
299 case 't': vt++;
break;
303 else if (line[0] ==
'f' && line[1] ==
' ') {
313 else if (strstr(line,
"mtllib")) {
314 const char* libname = strstr(line,
"mtllib");
316 while (isspace(*libname))
320 strcpy(libpath, root_path);
321 strcat(libpath, libname);
322 int n = strlen(libpath);
323 char* p = &libpath[n-1];
324 while (isspace(*p)) *p-- = 0;
326 int nmatls = LoadMatls(libpath, model);
331 if (vi > nverts) nverts = vi;
332 if (vn > nverts) nverts = vn;
333 if (vt > nverts) nverts = vt;
336 ::MessageBox(0,
"Wavefront/OBJ Import Failed: that model is just too darn complicated!",
"ERROR", MB_OK);
344 fseek(fp, 0, SEEK_SET);
358 float* vtu =
new float[nverts];
359 float* vtv =
new float[nverts];
365 fgets(line, 255, fp);
367 if (line[0] ==
'v') {
368 if (line[1] ==
' ') {
369 const char* p = line + 2;
371 while (isspace(*p)) p++;
372 sscanf(p,
"%f", &vloc[vi].x);
374 while (!isspace(*p)) p++;
375 while (isspace(*p)) p++;
376 sscanf(p,
"%f", &vloc[vi].y);
378 while (!isspace(*p)) p++;
379 while (isspace(*p)) p++;
380 sscanf(p,
"%f", &vloc[vi].z);
382 float d = vloc[vi].
length();
389 else if (line[1] ==
'n') {
390 const char* p = line + 2;
392 while (isspace(*p)) p++;
393 sscanf(p,
"%f", &vnrm[vn].x);
395 while (!isspace(*p)) p++;
396 while (isspace(*p)) p++;
397 sscanf(p,
"%f", &vnrm[vn].y);
399 while (!isspace(*p)) p++;
400 while (isspace(*p)) p++;
401 sscanf(p,
"%f", &vnrm[vn].z);
406 else if (line[1] ==
't') {
407 const char* p = line + 2;
409 while (isspace(*p)) p++;
410 sscanf(p,
"%f", &vtu[vt]);
412 while (!isspace(*p)) p++;
413 while (isspace(*p)) p++;
414 sscanf(p,
"%f", &vtv[vt]);
416 vtv[vt] = 1.0f - vtv[vt];
423 fseek(fp, 0, SEEK_SET);
442 fgets(raw_line, 256, fp);
444 strcpy(line,
Text(raw_line).trim().data());
446 if (strstr(line,
"usemtl")) {
447 material = FindMatl(line + 7, model);
450 if (material == iter.
value())
451 mtl_index = iter.
index();
454 else if (line[0] ==
'v') {
455 if (line[1] ==
' ') current_v++;
456 else if (line[1] ==
'n') current_vn++;
457 else if (line[1] ==
't') current_vt++;
460 else if (line[0] ==
'f') {
461 ParsePoly(line, &face);
464 for (
int n = 0; n < face.
nverts; n++) {
466 face.
v[n] += current_v;
469 face.
n[n] += current_vn;
472 face.
t[n] += current_vt;
476 npolys += face.
nverts - 3;
478 for (
int tri = 2; tri < face.
nverts; tri++) {
479 Poly* p = polys + poly;
484 vset->
loc[v+0] = vloc[face.
v[ tri ] -1];
485 vset->
loc[v+1] = vloc[face.
v[ tri-1 ] -1];
486 vset->
loc[v+2] = vloc[face.
v[ 0] -1];
489 vset->
nrm[v+0] = vnrm[face.
n[ tri ] -1];
490 vset->
nrm[v+1] = vnrm[face.
n[ tri-1 ] -1];
491 vset->
nrm[v+2] = vnrm[face.
n[ 0] -1];
500 vset->
tu[v+0] = vtu[face.
t[ tri ] -1];
501 vset->
tv[v+0] = vtv[face.
t[ tri ] -1];
502 vset->
tu[v+1] = vtu[face.
t[ tri-1 ] -1];
503 vset->
tv[v+1] = vtv[face.
t[ tri-1 ] -1];
504 vset->
tu[v+2] = vtu[face.
t[ 0 ] -1];
505 vset->
tv[v+2] = vtv[face.
t[ 0 ] -1];
525 Poly* p = polys + poly;
533 for (
int i = 0; i < p->
nverts; i++) {
536 vset->
loc[v] = vloc[face.
v[face_index]-1];
538 if (face.
n[face_index] > 0)
539 vset->
nrm[v] = vnrm[face.
n[face_index]-1];
541 vset->
nrm[v] = vset->
loc[v];
545 if (vset->
nrm[v] != vset->
nrm[first])
548 if (face.
t[face_index] > 0) {
549 vset->
tu[v] = vtu [face.
t[face_index]-1];
550 vset->
tv[v] = vtv [face.
t[face_index]-1];
578 qsort((
void*) polys, npolys,
sizeof(
Poly), mcomp);
583 for (
int n = 0; n < npolys; n++) {
595 segment->
polys = &polys[n];
623 SaveWaveFrontMatLib(
const char* path,
const char* root,
Model* model)
626 sprintf(filename,
"%s%s.mtl", path, root);
628 FILE* f = fopen(filename,
"w");
630 fprintf(f,
"#\n# %s Material Library exported by Magic 2.0\n#\n\n", root);
636 fprintf(f,
"newmtl %s\n", mtl->
name);
640 fprintf(f,
"Ns %.5f\n", mtl->
power);
641 fprintf(f,
"illum 2\n");
662 ZeroMemory(pathname,
sizeof(pathname));
663 ZeroMemory(rootname,
sizeof(rootname));
665 const char* ext = strstr(filename,
".obj");
667 ext = strstr(filename,
".OBJ");
669 const char* sep = strrchr(filename,
'/');
671 sep = strrchr(filename,
'\\');
674 char* dst = pathname;
688 strcpy(rootname, src);
691 strcpy(filename, pathname);
692 strcat(filename, rootname);
693 strcat(filename,
".obj");
695 FILE* f = fopen(filename,
"w");
697 ::MessageBox(0,
"Export Failed: Magic could not open the file for writing",
"ERROR", MB_OK);
701 fprintf(f,
"# Wavefront OBJ exported by Magic 2.0\n\n");
702 fprintf(f,
"mtllib %s.mtl\n", rootname);
707 fprintf(f,
"\n# VERTEX LOCATIONS: %d\n", m->
NumVerts());
712 for (
int n = 0; n < vset->
nverts; n++) {
713 fprintf(f,
"v %12.5f %12.5f %12.5f\n",
723 fprintf(f,
"\n# VERTEX NORMALS: %d\n", m->
NumVerts());
728 for (
int n = 0; n < vset->
nverts; n++) {
729 fprintf(f,
"vn %8.3f %8.3f %8.3f\n",
739 fprintf(f,
"\n# TEXTURE COORDINATES: %d\n", m->
NumVerts());
744 for (
int n = 0; n < vset->
nverts; n++) {
745 fprintf(f,
"vt %8.3f %8.3f\n",
746 vset->
tu[n], 1 - vset->
tv[n]);
755 fprintf(f,
"\n# FACES: %d\n", m->
NumPolys());
759 for (
int n = 0; n < s->
NumPolys(); n++) {
764 if (current_material != mtl) {
765 fprintf(f,
"\n\nusemtl %s\n", mtl->
name);
766 current_material = mtl;
770 for (
int v = nv-1; v >= 0; v--) {
771 fprintf(f,
"%d/%d/%d ",
779 fprintf(f,
"\n\n\n# END OF FILE.\n");
782 return SaveWaveFrontMatLib(pathname, rootname, m);