some meshgen and map rendering updates
[voxelands-alt.git] / src / graphics / model_obj.c
blobf74db930a0dc7a48a0061b8ab66326d625d9348f
1 /************************************************************************
2 * model_obj.c
3 * voxelands - 3d voxel world sandbox game
4 * Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
18 ************************************************************************/
20 #include "common.h"
21 #include "graphics.h"
23 #include <string.h>
25 struct obj_poly_s {
26 GLuint v1;
27 GLuint t1;
28 GLuint n1;
29 GLuint v2;
30 GLuint t2;
31 GLuint n2;
32 GLuint v3;
33 GLuint t3;
34 GLuint n3;
35 mesh_t *m;
38 /* load the materials */
39 void model_load_obj_mtl(char* file)
41 file_t* f;
42 material_t *m;
43 char* data;
44 char* p;
45 char* e;
46 char tmp1[255];
47 char name[255];
48 float rf;
49 float gf;
50 float bf;
51 float af;
52 colour_t c = {255,255,255,255};
53 int mkd = 1;
55 f = file_load("model",file);
56 if (!f)
57 return;
59 data = (char*)f->data;
61 p = data;
62 e = data + f->len;
64 while (p != e) {
65 if (!strncmp(p, "newmtl", 6)) {
66 if (!mkd) {
67 m = mat_from_colour(&c);
68 mat_options(m,MATOPT_ALPHA_BLEND);
69 strcpy(m->name,name);
71 mkd = 0;
72 sscanf(p,"newmtl %s",name);
73 }else if (strncmp(p, "map_Kd", 6) == 0) {
74 sscanf(p,"map_Kd %s",tmp1);
75 m = mat_from_image("texture",tmp1);
76 mat_options(m,MATOPT_ALPHA_BLEND);
77 mkd = 1;
78 strcpy(m->name,name);
79 }else if (strncmp(p,"Kd ",3) == 0) {
80 sscanf(p,"Kd %f %f %f",&rf,&gf,&bf);
81 c.r = (unsigned char)(rf*255.0);
82 c.g = (unsigned char)(gf*255.0);
83 c.b = (unsigned char)(bf*255.0);
84 }else if (strncmp(p,"d ",2) == 0) {
85 sscanf(p,"d %f",&af);
86 c.a = (unsigned char)(af*255.0);
89 p = strchr(p,'\n');
90 if (!p)
91 break;
92 p++;
95 if (!mkd) {
96 m = mat_from_colour(&c);
97 strcpy(m->name,name);
101 /* load an obj model */
102 model_t *model_load_obj(file_t *f)
104 char* d;
105 model_t* mdl;
106 mesh_t *m = NULL;
107 material_t *mat;
108 char* data;
109 char* p;
110 char* e;
111 v3_t *vert;
112 v2_t *tex;
113 v3_t *norm;
114 struct obj_poly_s *poly;
115 int i;
116 int nq = 0;
117 int tq = 0;
118 int vq = 0;
119 int pq = 0;
120 char tmp[255];
121 char file[255];
123 d = strrchr(f->name,'.');
124 if (!d)
125 return NULL;
126 *d = 0;
127 sprintf(file,"%s.mtl",f->name);
128 *d = '.';
130 mdl = model_create();
132 model_load_obj_mtl(file);
134 data = (char*)f->data;
135 p = data;
136 e = data+f->len;
138 while (p < e) {
139 if (!strncmp(p, "vn", 2)) {
140 nq++;
141 }else if (!strncmp(p, "vt", 2)) {
142 tq++;
143 }else if (!strncmp(p, "v", 1)) {
144 vq++;
145 }else if (!strncmp(p, "f", 1)) {
146 pq++;
149 p = strchr(p,'\n');
150 if (!p)
151 break;
152 p++;
154 p = data;
156 vert = malloc(sizeof(v3_t)*vq);
157 if (tq) {
158 tex = malloc(sizeof(v2_t)*tq);
159 }else{
160 tex = malloc(sizeof(v2_t)*2);
161 tex[0].x = 0;
162 tex[0].y = 0;
163 tex[1].x = 1;
164 tex[1].y = 1;
166 norm = malloc(sizeof(v3_t)*nq);
167 poly = malloc(sizeof(struct obj_poly_s)*pq);
169 vq = 0;
170 nq = 0;
171 tq = 0;
172 pq = 0;
174 /* stage 1, read in the file data */
175 while (p < e) {
176 if (strncmp(p, "vn", 2) == 0) {
177 sscanf(p, "vn %f %f %f", &norm[nq].x, &norm[nq].y, &norm[nq].z);
178 nq++;
179 }else if (strncmp(p, "vt", 2) == 0) {
180 sscanf(p, "vt %f %f", &tex[tq].x, &tex[tq].y);
181 tq++;
182 }else if (strncmp(p, "v", 1) == 0) {
183 sscanf(p, "v %f %f %f", &vert[vq].x, &vert[vq].y, &vert[vq].z);
184 vq++;
185 }else if (strncmp(p, "f", 1) == 0) {
186 if (strstr(p,"//")) {
187 sscanf(
189 "f %u//%u %u//%u %u//%u",
190 &poly[pq].v1,
191 &poly[pq].n1,
192 &poly[pq].v2,
193 &poly[pq].n2,
194 &poly[pq].v3,
195 &poly[pq].n3
197 poly[pq].v1 -= 1;
198 poly[pq].t1 = 0;
199 poly[pq].n1 -= 1;
200 poly[pq].v2 -= 1;
201 poly[pq].t2 = 1;
202 poly[pq].n2 -= 1;
203 poly[pq].v3 -= 1;
204 poly[pq].t3 = 1;
205 poly[pq].n3 -= 1;
206 }else{
207 sscanf(
209 "f %u/%u/%u %u/%u/%u %u/%u/%u",
210 &poly[pq].v1,
211 &poly[pq].t1,
212 &poly[pq].n1,
213 &poly[pq].v2,
214 &poly[pq].t2,
215 &poly[pq].n2,
216 &poly[pq].v3,
217 &poly[pq].t3,
218 &poly[pq].n3
220 poly[pq].v1 -= 1;
221 poly[pq].t1 -= 1;
222 poly[pq].n1 -= 1;
223 poly[pq].v2 -= 1;
224 poly[pq].t2 -= 1;
225 poly[pq].n2 -= 1;
226 poly[pq].v3 -= 1;
227 poly[pq].t3 -= 1;
228 poly[pq].n3 -= 1;
230 poly[pq].m = m;
231 pq++;
232 }else if (strncmp(p, "usemtl", 6) == 0) {
233 sscanf(p,"usemtl %s",tmp);
234 mat = mat_find(tmp);
235 if (!mat)
236 mat = mat_create();
237 m = mesh_create_material(mat);
238 array_push_ptr(mdl->meshes,m);
241 p = strchr(p,'\n');
242 if (!p)
243 break;
244 p++;
247 /* stage 2, make a rosethorn model out of it */
248 if (!nq) {
249 for (i=0; i<pq; i++) {
250 mesh_push_polypoint(poly[i].m,&vert[poly[i].v1],&tex[poly[i].t1]);
251 mesh_push_polypoint(poly[i].m,&vert[poly[i].v2],&tex[poly[i].t2]);
252 mesh_push_polypoint(poly[i].m,&vert[poly[i].v3],&tex[poly[i].t3]);
254 for (i=0; i<mdl->meshes->length; i++) {
255 m = ((mesh_t**)(mdl->meshes->data))[i];
256 mesh_calc_normals(m);
258 }else{
259 for (i=0; i<pq; i++) {
260 mesh_push_polypoint_n(poly[i].m,&vert[poly[i].v1],&norm[poly[i].n1],&tex[poly[i].t1]);
261 mesh_push_polypoint_n(poly[i].m,&vert[poly[i].v2],&norm[poly[i].n2],&tex[poly[i].t2]);
262 mesh_push_polypoint_n(poly[i].m,&vert[poly[i].v3],&norm[poly[i].n3],&tex[poly[i].t3]);
266 return mdl;