glstuff

experiments with opengl2/ogles2/sdl
git clone http://frotz.net/git/glstuff.git
Log | Files | Refs

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