graphics

experiments with opengl3.2/ogles3.3 on linux and win7
git clone http://frotz.net/git/graphics.git
Log | Files | Refs

loadobj.cc (4018B)


      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 #include "io.h"
     25 
     26 struct v3 {
     27 	float x;
     28 	float y;
     29 	float z;
     30 };
     31 
     32 struct v2 {
     33 	float u;
     34 	float v;
     35 };
     36 
     37 struct i3 {
     38 	unsigned v;
     39 	unsigned vt;
     40 	unsigned vn;
     41 };
     42 
     43 struct obj {
     44 	vector<v3> vertices;
     45 	vector<v3> normals;
     46 	vector<v2> texcoords;
     47 	vector<i3> triangles;
     48 };
     49 
     50 struct obj *load_obj(const char *fn) {
     51 	char buf[128];
     52 	FILE *fp;
     53 	struct obj *o = 0;
     54 
     55 	if (!(fp = io_fopen_asset(fn, "model")))
     56 		goto exit;
     57 
     58 	o = new(obj);
     59 	if (!o)
     60 		goto close_and_exit;
     61 
     62 	while (fgets(buf, sizeof(buf), fp) != 0) {
     63 		if (!strncmp(buf, "v ", 2)) {
     64 			v3 t;
     65 			sscanf(buf + 2, "%f %f %f", &t.x, &t.y, &t.z);
     66 			o->vertices.push_back(t);
     67 		} else if (!strncmp(buf, "vn ", 3)) {
     68 			v3 t;
     69 			sscanf(buf + 3, "%f %f %f", &t.x, &t.y, &t.z);
     70 			o->normals.push_back(t);
     71 		} else if (!strncmp(buf, "vt ", 3)) {
     72 			v2 t;
     73 			sscanf(buf + 3, "%f %f", &t.u, &t.v);
     74 
     75 			/* TODO: make parameter -- inverting V for DX... */
     76 			t.v = 1.0 - t.v;
     77 
     78 			o->texcoords.push_back(t);
     79 		} else if (!strncmp(buf, "f ", 2)) {
     80 			i3 t;
     81 			char *tmp = buf + 2;
     82 			/* XXX: handle non-triangles */
     83 			while (sscanf(tmp, "%d/%d/%d", &t.v, &t.vt, &t.vn) == 3) {
     84 				t.v--;
     85 				t.vt--;
     86 				t.vn--;
     87 				o->triangles.push_back(t);
     88 				tmp = strstr(tmp, " ");
     89 				if (!tmp) break;
     90 				tmp++;
     91 			}
     92 		} else {
     93 //			fprintf(stderr,"ignoring: %s", buf);
     94 		}
     95 	}
     96 
     97 close_and_exit:
     98 	fclose(fp);
     99 exit:
    100 	return o;	
    101 }
    102 
    103 static struct model *obj_to_model(struct obj *o) {
    104 	int i, j, n;
    105 	struct model *m;
    106 	int count = o->triangles.size();
    107 
    108 	if(!(m = (model*) malloc(sizeof(struct model))))
    109 		return 0;
    110 	memset(m, 0, sizeof(struct model));
    111 
    112 	if (!(m->vdata = (float*) malloc(sizeof(float) * 8 * count))) {
    113 		free(m);
    114 		return 0;
    115 	}
    116 	if (!(m->idx = (unsigned short *) malloc(sizeof(short) * count))) {
    117 		free(m->vdata);
    118 		free(m);
    119 		return 0;
    120 	}
    121 
    122 	for (n = 0, i = 0; i < count; i++) {
    123 		i3 &tri = o->triangles[i];
    124 		float data[8];
    125 		v3 &vrt = o->vertices[tri.v];
    126 		v3 &nrm = o->normals[tri.vn];
    127 		v2 &txc = o->texcoords[tri.vt];
    128 		data[0] = vrt.x;
    129 		data[1] = vrt.y;
    130 		data[2] = vrt.z;
    131 		data[3] = nrm.x;
    132 		data[4] = nrm.y;
    133 		data[5] = nrm.z;
    134 		data[6] = txc.u;
    135 		data[7] = txc.v;
    136 		for (j = 0; j < n; j++)
    137 			if (!memcmp(data, &m->vdata[8 * j], sizeof(float) * 8))
    138 				goto found_it;
    139 		memcpy(&m->vdata[8 * j], data, sizeof(float) * 8);
    140 		n++;
    141 found_it:
    142 		m->idx[i] = j;
    143 	}
    144 
    145 	m->vcount = n;
    146 	m->icount = count;
    147 
    148 	return m;
    149 }
    150 
    151 #if 0
    152 void model_dump(struct model *m, FILE *fp) {
    153 	int i;
    154 	fprintf(fp, "struct model M = {\n");
    155 	fprintf(fp, "  .vdata = {\n");
    156 	for (i = 0; i < m->vcount; i++)
    157 		fprintf(fp, "    %f, %f, %f,\n    %f, %f, %f, %f, %f,\n",
    158 			m->vdata[i*8+0], m->vdata[i*8+1],
    159 			m->vdata[i*8+2], m->vdata[i*8+3], 
    160 			m->vdata[i*8+4], m->vdata[i*8+5],
    161 			m->vdata[i*8+6], m->vdata[i*8+7]);
    162 	fprintf(fp, "  },\n  .idx[] = {\n");
    163 	for (i = 0; i < m->icount; i += 3) 
    164 		fprintf(fp, "    %d, %d, %d,\n",
    165 			m->idx[i+0], m->idx[i+1], m->idx[i+2]);
    166 	fprintf(fp, "  },\n  .vcount = %d,\n  .icount = %d,\n};\n",
    167 		m->vcount, m->icount);
    168 }
    169 #endif
    170 
    171 struct model *load_wavefront_obj(const char *fn) {
    172 	struct obj *o;
    173 	struct model *m;
    174 	o = load_obj(fn);
    175 	if (!o) {
    176 		error("Failed to load Model '%s'", fn);
    177 		return 0;
    178 	}
    179 	m = obj_to_model(o);
    180 	delete o;
    181 	return m;
    182 }
    183 
    184 void delete_wavefront_obj(struct model *m) {
    185 	free(m->vdata);
    186 	free(m->idx);
    187 	free(m);
    188 }