loadobj.cc (3776B)
1 /* Copyright 2013 Brian Swetland <swetland@frotz.net> 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 20 #include <vector> 21 using std::vector; 22 23 #include "util.h" 24 25 struct v3 { 26 float x; 27 float y; 28 float z; 29 }; 30 31 struct v2 { 32 float u; 33 float v; 34 }; 35 36 struct i3 { 37 unsigned v; 38 unsigned vt; 39 unsigned vn; 40 }; 41 42 struct obj { 43 vector<v3> vertices; 44 vector<v3> normals; 45 vector<v2> texcoords; 46 vector<i3> triangles; 47 }; 48 49 struct obj *load_obj(const char *fn) { 50 char buf[128]; 51 FILE *fp; 52 struct obj *o = 0; 53 54 if (!(fp = fopen(fn, "r"))) 55 goto exit; 56 57 o = new(obj); 58 if (!o) 59 goto close_and_exit; 60 61 while (fgets(buf, sizeof(buf), fp) != 0) { 62 if (!strncmp(buf, "v ", 2)) { 63 v3 t; 64 sscanf(buf + 2, "%f %f %f", &t.x, &t.y, &t.z); 65 o->vertices.push_back(t); 66 } else if (!strncmp(buf, "vn ", 3)) { 67 v3 t; 68 sscanf(buf + 3, "%f %f %f", &t.x, &t.y, &t.z); 69 o->normals.push_back(t); 70 } else if (!strncmp(buf, "vt ", 3)) { 71 v2 t; 72 sscanf(buf + 3, "%f %f", &t.u, &t.v); 73 o->texcoords.push_back(t); 74 } else if (!strncmp(buf, "f ", 2)) { 75 i3 t; 76 char *tmp = buf + 2; 77 /* XXX: handle non-triangles */ 78 while (sscanf(tmp, "%d/%d/%d", &t.v, &t.vt, &t.vn) == 3) { 79 t.v--; 80 t.vt--; 81 t.vn--; 82 o->triangles.push_back(t); 83 tmp = strstr(tmp, " "); 84 if (!tmp) break; 85 tmp++; 86 } 87 } else { 88 // fprintf(stderr,"ignoring: %s", buf); 89 } 90 } 91 92 close_and_exit: 93 fclose(fp); 94 exit: 95 return o; 96 } 97 98 static struct model *obj_to_model(struct obj *o) { 99 int i, j, n; 100 struct model *m; 101 int count = o->triangles.size(); 102 103 if(!(m = (model*) malloc(sizeof(struct model)))) 104 return 0; 105 memset(m, 0, sizeof(struct model)); 106 107 if (!(m->vdata = (float*) malloc(sizeof(float) * 8 * count))) { 108 free(m); 109 return 0; 110 } 111 if (!(m->idx = (unsigned short *) malloc(sizeof(short) * count))) { 112 free(m->vdata); 113 free(m); 114 return 0; 115 } 116 117 for (n = 0, i = 0; i < count; i++) { 118 i3 &tri = o->triangles[i]; 119 float data[8]; 120 v3 &vrt = o->vertices[tri.v]; 121 v3 &nrm = o->normals[tri.vn]; 122 v2 &txc = o->texcoords[tri.vt]; 123 data[0] = vrt.x; 124 data[1] = vrt.y; 125 data[2] = vrt.z; 126 data[3] = nrm.x; 127 data[4] = nrm.y; 128 data[5] = nrm.z; 129 data[6] = txc.u; 130 data[7] = txc.v; 131 for (j = 0; j < n; j++) 132 if (!memcmp(data, &m->vdata[8 * j], sizeof(float) * 8)) 133 goto found_it; 134 memcpy(&m->vdata[8 * j], data, sizeof(float) * 8); 135 n++; 136 found_it: 137 m->idx[i] = j; 138 } 139 140 m->vcount = n; 141 m->icount = count; 142 143 return m; 144 } 145 146 #if 0 147 void model_dump(struct model *m, FILE *fp) { 148 int i; 149 fprintf(fp, "struct model M = {\n"); 150 fprintf(fp, " .vdata = {\n"); 151 for (i = 0; i < m->vcount; i++) 152 fprintf(fp, " %f, %f, %f,\n %f, %f, %f, %f, %f,\n", 153 m->vdata[i*8+0], m->vdata[i*8+1], 154 m->vdata[i*8+2], m->vdata[i*8+3], 155 m->vdata[i*8+4], m->vdata[i*8+5], 156 m->vdata[i*8+6], m->vdata[i*8+7]); 157 fprintf(fp, " },\n .idx[] = {\n"); 158 for (i = 0; i < m->icount; i += 3) 159 fprintf(fp, " %d, %d, %d,\n", 160 m->idx[i+0], m->idx[i+1], m->idx[i+2]); 161 fprintf(fp, " },\n .vcount = %d,\n .icount = %d,\n};\n", 162 m->vcount, m->icount); 163 } 164 #endif 165 166 struct model *load_wavefront_obj(const char *fn) { 167 struct obj *o; 168 struct model *m; 169 o = load_obj(fn); 170 if (!o) 171 return 0; 172 m = obj_to_model(o); 173 delete o; 174 return m; 175 } 176