goat3d

changeset 17:1d85d7dd0038

goatprim done
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 27 Sep 2013 02:29:52 +0300
parents cb6c1a945a11
children bdfc8dd14965
files generators/goatprim/main.c src/goat3d.cc src/goat3d_scene.cc src/goat3d_writexml.cc src/log.cc src/scene.cc
diffstat 6 files changed, 569 insertions(+), 321 deletions(-) [+]
line diff
     1.1 --- a/generators/goatprim/main.c	Thu Sep 26 14:16:09 2013 +0300
     1.2 +++ b/generators/goatprim/main.c	Fri Sep 27 02:29:52 2013 +0300
     1.3 @@ -1,78 +1,306 @@
     1.4  #include <stdio.h>
     1.5 +#include <stdlib.h>
     1.6 +#include <string.h>
     1.7 +#include <math.h>
     1.8  #include "goat3d.h"
     1.9  
    1.10 -static struct goat3d_mesh *create_box(void);
    1.11 +#define DEF_USUB	16
    1.12 +#define DEF_VSUB	8
    1.13 +#define DEF_SIZE	1.0
    1.14 +#define DEF_OUTER	0.25
    1.15  
    1.16 -int main(void)
    1.17 +enum { BOX, SPHERE, TORUS };
    1.18 +
    1.19 +void gen_box(struct goat3d_mesh *mesh, float size);
    1.20 +void gen_sphere(struct goat3d_mesh *mesh, float rad, int usub, int vsub);
    1.21 +void gen_sphere_part(struct goat3d_mesh *mesh, float rad, int usub, int vsub, float umax, float vmax);
    1.22 +void gen_torus(struct goat3d_mesh *mesh, float inner, float outer, int usub, int vsub);
    1.23 +void gen_torus_part(struct goat3d_mesh *mesh, float inner, float outer,
    1.24 +		int usub, int vsub, float umax, float vmin, float vmax);
    1.25 +
    1.26 +
    1.27 +int main(int argc, char **argv)
    1.28  {
    1.29 +	int i, prim = BOX;
    1.30 +	int usub = DEF_USUB;
    1.31 +	int vsub = DEF_VSUB;
    1.32 +	float size = DEF_SIZE;
    1.33 +	float outer = DEF_OUTER;
    1.34  	struct goat3d *goat;
    1.35  	struct goat3d_material *mtl;
    1.36  	struct goat3d_mesh *mesh;
    1.37 +	const char *fname = 0;
    1.38 +
    1.39 +	for(i=1; i<argc; i++) {
    1.40 +		if(strcmp(argv[i], "-box") == 0) {
    1.41 +			prim = BOX;
    1.42 +
    1.43 +		} else if(strcmp(argv[i], "-sphere") == 0) {
    1.44 +			prim = SPHERE;
    1.45 +
    1.46 +		} else if(strcmp(argv[i], "-torus") == 0) {
    1.47 +			prim = TORUS;
    1.48 +
    1.49 +		} else if(strcmp(argv[i], "-rad") == 0 || strcmp(argv[i], "-size") == 0
    1.50 +				|| strcmp(argv[i], "-inner") == 0) {
    1.51 +			if((size = atof(argv[++i])) == 0.0) {
    1.52 +				fprintf(stderr, "invalid size\n");
    1.53 +				return 1;
    1.54 +			}
    1.55 +
    1.56 +		} else if(strcmp(argv[i], "-outer") == 0) {
    1.57 +			if((outer = atof(argv[++i])) == 0.0) {
    1.58 +				fprintf(stderr, "invalid outer radius\n");
    1.59 +				return 1;
    1.60 +			}
    1.61 +
    1.62 +		} else if(strcmp(argv[i], "-usub") == 0) {
    1.63 +			if(!(usub = atoi(argv[++i]))) {
    1.64 +				fprintf(stderr, "invalid usub\n");
    1.65 +				return 1;
    1.66 +			}
    1.67 +
    1.68 +		} else if(strcmp(argv[i], "-vsub") == 0) {
    1.69 +			if(!(vsub = atoi(argv[++i]))) {
    1.70 +				fprintf(stderr, "invalid vsub\n");
    1.71 +				return 1;
    1.72 +			}
    1.73 +
    1.74 +		} else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0) {
    1.75 +			printf("Usage: %s [filename] [options]\n", argv[0]);
    1.76 +			printf("Options:\n");
    1.77 +			printf(" -box          create box (default)\n");
    1.78 +			printf(" -sphere       create sphere\n");
    1.79 +			printf(" -torus        create torus\n");
    1.80 +			printf(" -size <n>, -rad <n>, -inner <n> (default: %g)\n", DEF_SIZE);
    1.81 +			printf(" -outer <n>    torus outer radius (default: %g)\n", DEF_OUTER);
    1.82 +			printf(" -usub <n>     subdivisions along the horizontal direction (default: %d)\n", DEF_USUB);
    1.83 +			printf(" -vsub <n>     subdivisions along the vertical direction (default: %d)\n", DEF_VSUB);
    1.84 +			printf(" -h, -help     print usage information and exit\n");
    1.85 +			return 0;
    1.86 +
    1.87 +		} else {
    1.88 +			if(fname) {
    1.89 +				fprintf(stderr, "unexpected argument: %s\n", argv[i]);
    1.90 +				return 1;
    1.91 +			}
    1.92 +			fname = argv[i];
    1.93 +		}
    1.94 +	}
    1.95 +
    1.96 +	if(!fname) {
    1.97 +		fname = "out.xml";
    1.98 +	}
    1.99  
   1.100  	goat = goat3d_create();
   1.101 +	goat3d_set_name(goat, fname);
   1.102  
   1.103  	mtl = goat3d_create_mtl();
   1.104  	goat3d_set_mtl_name(mtl, "mat");
   1.105  	goat3d_set_mtl_attrib4f(mtl, GOAT3D_MAT_ATTR_DIFFUSE, 1, 0, 0, 1);
   1.106  	goat3d_add_mtl(goat, mtl);
   1.107  
   1.108 -	mesh = create_box();
   1.109 +	mesh = goat3d_create_mesh();
   1.110 +
   1.111 +	switch(prim) {
   1.112 +	case BOX:
   1.113 +		gen_box(mesh, size);
   1.114 +		break;
   1.115 +
   1.116 +	case SPHERE:
   1.117 +		gen_sphere(mesh, size, usub, vsub);
   1.118 +		break;
   1.119 +
   1.120 +	case TORUS:
   1.121 +		gen_torus(mesh, size, outer, usub, vsub);
   1.122 +		break;
   1.123 +
   1.124 +	default:
   1.125 +		return 1;
   1.126 +	}
   1.127 +	goat3d_set_mesh_mtl(mesh, mtl);
   1.128  	goat3d_add_mesh(goat, mesh);
   1.129  
   1.130  	goat3d_setopt(goat, GOAT3D_OPT_SAVEXML, 1);
   1.131 -	goat3d_save(goat, "foo.xml");
   1.132 +	goat3d_save(goat, fname);
   1.133  
   1.134  	goat3d_free(goat);
   1.135  	return 0;
   1.136  }
   1.137  
   1.138 -static struct goat3d_mesh *create_box(void)
   1.139 +void gen_box(struct goat3d_mesh *mesh, float size)
   1.140  {
   1.141 -	struct goat3d_mesh *mesh = goat3d_create_mesh();
   1.142 +	float hsz = size / 2.0;
   1.143  
   1.144  	goat3d_begin(mesh, GOAT3D_QUADS);
   1.145  	// +X
   1.146  	goat3d_normal3f(1, 0, 0);
   1.147 -	goat3d_vertex3f(-1, -1, 1);
   1.148 -	goat3d_vertex3f(-1, -1, -1);
   1.149 -	goat3d_vertex3f(-1, 1, -1);
   1.150 -	goat3d_vertex3f(-1, 1, 1);
   1.151 +	goat3d_texcoord2f(0, 0);
   1.152 +	goat3d_vertex3f(hsz, -hsz, hsz);
   1.153 +	goat3d_texcoord2f(1, 0);
   1.154 +	goat3d_vertex3f(hsz, -hsz, -hsz);
   1.155 +	goat3d_texcoord2f(1, 1);
   1.156 +	goat3d_vertex3f(hsz, hsz, -hsz);
   1.157 +	goat3d_texcoord2f(0, 1);
   1.158 +	goat3d_vertex3f(hsz, hsz, hsz);
   1.159  
   1.160  	// -X
   1.161  	goat3d_normal3f(-1, 0, 0);
   1.162 -	goat3d_vertex3f(-1, -1, -1);
   1.163 -	goat3d_vertex3f(-1, -1, 1);
   1.164 -	goat3d_vertex3f(-1, 1, 1);
   1.165 -	goat3d_vertex3f(-1, 1, -1);
   1.166 +	goat3d_texcoord2f(0, 0);
   1.167 +	goat3d_vertex3f(-hsz, -hsz, -hsz);
   1.168 +	goat3d_texcoord2f(1, 0);
   1.169 +	goat3d_vertex3f(-hsz, -hsz, hsz);
   1.170 +	goat3d_texcoord2f(1, 1);
   1.171 +	goat3d_vertex3f(-hsz, hsz, hsz);
   1.172 +	goat3d_texcoord2f(0, 1);
   1.173 +	goat3d_vertex3f(-hsz, hsz, -hsz);
   1.174  
   1.175  	// +Y
   1.176  	goat3d_normal3f(0, 1, 0);
   1.177 -	goat3d_vertex3f(-1, 1, 1);
   1.178 -	goat3d_vertex3f(1, 1, 1);
   1.179 -	goat3d_vertex3f(1, 1, -1);
   1.180 -	goat3d_vertex3f(-1, 1, -1);
   1.181 +	goat3d_texcoord2f(0, 0);
   1.182 +	goat3d_vertex3f(-hsz, hsz, hsz);
   1.183 +	goat3d_texcoord2f(1, 0);
   1.184 +	goat3d_vertex3f(hsz, hsz, hsz);
   1.185 +	goat3d_texcoord2f(1, 1);
   1.186 +	goat3d_vertex3f(hsz, hsz, -hsz);
   1.187 +	goat3d_texcoord2f(0, 1);
   1.188 +	goat3d_vertex3f(-hsz, hsz, -hsz);
   1.189  
   1.190  	// -Y
   1.191  	goat3d_normal3f(0, -1, 0);
   1.192 -	goat3d_vertex3f(-1, -1, -1);
   1.193 -	goat3d_vertex3f(1, -1, -1);
   1.194 -	goat3d_vertex3f(1, -1, 1);
   1.195 -	goat3d_vertex3f(-1, -1, 1);
   1.196 +	goat3d_texcoord2f(0, 0);
   1.197 +	goat3d_vertex3f(-hsz, -hsz, -hsz);
   1.198 +	goat3d_texcoord2f(1, 0);
   1.199 +	goat3d_vertex3f(hsz, -hsz, -hsz);
   1.200 +	goat3d_texcoord2f(1, 1);
   1.201 +	goat3d_vertex3f(hsz, -hsz, hsz);
   1.202 +	goat3d_texcoord2f(0, 1);
   1.203 +	goat3d_vertex3f(-hsz, -hsz, hsz);
   1.204  
   1.205  	// +Z
   1.206  	goat3d_normal3f(0, 0, 1);
   1.207 -	goat3d_vertex3f(-1, -1, 1);
   1.208 -	goat3d_vertex3f(1, -1, 1);
   1.209 -	goat3d_vertex3f(1, -1, 1);
   1.210 -	goat3d_vertex3f(-1, -1, 1);
   1.211 +	goat3d_texcoord2f(0, 0);
   1.212 +	goat3d_vertex3f(-hsz, -hsz, hsz);
   1.213 +	goat3d_texcoord2f(1, 0);
   1.214 +	goat3d_vertex3f(hsz, -hsz, hsz);
   1.215 +	goat3d_texcoord2f(1, 1);
   1.216 +	goat3d_vertex3f(hsz, hsz, hsz);
   1.217 +	goat3d_texcoord2f(0, 1);
   1.218 +	goat3d_vertex3f(-hsz, hsz, hsz);
   1.219  
   1.220  	// -Z
   1.221  	goat3d_normal3f(0, 0, -1);
   1.222 -	goat3d_vertex3f(-1, -1, 1);
   1.223 -	goat3d_vertex3f(1, -1, 1);
   1.224 -	goat3d_vertex3f(1, -1, -1);
   1.225 -	goat3d_vertex3f(-1, -1, -1);
   1.226 +	goat3d_texcoord2f(0, 0);
   1.227 +	goat3d_vertex3f(hsz, -hsz, -hsz);
   1.228 +	goat3d_texcoord2f(1, 0);
   1.229 +	goat3d_vertex3f(-hsz, -hsz, -hsz);
   1.230 +	goat3d_texcoord2f(1, 1);
   1.231 +	goat3d_vertex3f(-hsz, hsz, -hsz);
   1.232 +	goat3d_texcoord2f(0, 1);
   1.233 +	goat3d_vertex3f(hsz, hsz, -hsz);
   1.234  	goat3d_end();
   1.235 +}
   1.236  
   1.237 -	return mesh;
   1.238 +void gen_sphere(struct goat3d_mesh *mesh, float rad, int usub, int vsub)
   1.239 +{
   1.240 +	gen_sphere_part(mesh, rad, usub, vsub, 1.0, 1.0);
   1.241  }
   1.242 +
   1.243 +#define sphere_vertex(u, v) \
   1.244 +	do { \
   1.245 +		float x, y, z, theta, phi; \
   1.246 +		float costheta, sinphi; \
   1.247 +		theta = (u) * 2.0 * M_PI; \
   1.248 +		phi = (v) * M_PI; \
   1.249 +		costheta = cos(theta); \
   1.250 +		sinphi = sin(phi); \
   1.251 +		x = costheta * sinphi; \
   1.252 +		y = cos(phi); \
   1.253 +		z = sin(theta) * sinphi; \
   1.254 +		goat3d_normal3f(x, y, z); \
   1.255 +		goat3d_texcoord2f(u, v); \
   1.256 +		goat3d_vertex3f(rad * x, rad * y, rad * z); \
   1.257 +	} while(0)
   1.258 +
   1.259 +void gen_sphere_part(struct goat3d_mesh *mesh, float rad, int usub, int vsub, float umax, float vmax)
   1.260 +{
   1.261 +	int i, j;
   1.262 +	float u, v, du, dv;
   1.263 +
   1.264 +	if(usub < 3) usub = 3;
   1.265 +	if(vsub < 3) vsub = 3;
   1.266 +
   1.267 +	du = umax / (float)usub;
   1.268 +	dv = vmax / (float)vsub;
   1.269 +
   1.270 +	goat3d_begin(mesh, GOAT3D_QUADS);
   1.271 +
   1.272 +	u = 0.0;
   1.273 +	for(i=0; i<usub; i++) {
   1.274 +		v = 0.0;
   1.275 +		for(j=0; j<vsub; j++) {
   1.276 +			sphere_vertex(u, v);
   1.277 +			sphere_vertex(u + du, v);
   1.278 +			sphere_vertex(u + du, v + dv);
   1.279 +			sphere_vertex(u, v + dv);
   1.280 +			v += dv;
   1.281 +		}
   1.282 +		u += du;
   1.283 +	}
   1.284 +	goat3d_end();
   1.285 +}
   1.286 +
   1.287 +
   1.288 +void gen_torus(struct goat3d_mesh *mesh, float inner, float outer, int usub, int vsub)
   1.289 +{
   1.290 +	gen_torus_part(mesh, inner, outer, usub, vsub, 1.0, 0.0, 1.0);
   1.291 +}
   1.292 +
   1.293 +#define torus_vertex(u, v) \
   1.294 +	do { \
   1.295 +		float rx, ry, rz, cx, cy, cz, theta, phi; \
   1.296 +		float costheta, sintheta, sinphi; \
   1.297 +		theta = (u) * 2.0 * M_PI; \
   1.298 +		phi = (v) * 2.0 * M_PI; \
   1.299 +		costheta = cos(theta); \
   1.300 +		sintheta = sin(theta); \
   1.301 +		sinphi = sin(phi); \
   1.302 +		cx = costheta * inner; \
   1.303 +		cy = 0.0f; \
   1.304 +		cz = sintheta * inner; \
   1.305 +		rx = costheta * sinphi; \
   1.306 +		ry = cos(phi); \
   1.307 +		rz = sintheta * sinphi; \
   1.308 +		goat3d_normal3f(rx, ry, rz); \
   1.309 +		goat3d_texcoord2f(u, v); \
   1.310 +		goat3d_vertex3f(outer * rx + cx, outer * ry + cy, outer * rz + cz); \
   1.311 +	} while(0)
   1.312 +
   1.313 +void gen_torus_part(struct goat3d_mesh *mesh, float inner, float outer,
   1.314 +		int usub, int vsub, float umax, float vmin, float vmax)
   1.315 +{
   1.316 +	int i, j;
   1.317 +	float u, v, du, dv;
   1.318 +
   1.319 +	if(usub < 3) usub = 3;
   1.320 +	if(vsub < 3) vsub = 3;
   1.321 +
   1.322 +	du = umax / (float)usub;
   1.323 +	dv = (vmax - vmin) / (float)vsub;
   1.324 +
   1.325 +	goat3d_begin(mesh, GOAT3D_QUADS);
   1.326 +
   1.327 +	u = 0.0;
   1.328 +	for(i=0; i<usub; i++) {
   1.329 +		v = vmin;
   1.330 +		for(j=0; j<vsub; j++) {
   1.331 +			torus_vertex(u, v);
   1.332 +			torus_vertex(u + du, v);
   1.333 +			torus_vertex(u + du, v + dv);
   1.334 +			torus_vertex(u, v + dv);
   1.335 +			v += dv;
   1.336 +		}
   1.337 +		u += du;
   1.338 +	}
   1.339 +	goat3d_end();
   1.340 +}
     2.1 --- a/src/goat3d.cc	Thu Sep 26 14:16:09 2013 +0300
     2.2 +++ b/src/goat3d.cc	Fri Sep 27 02:29:52 2013 +0300
     2.3 @@ -360,42 +360,44 @@
     2.4  
     2.5  void goat3d_end(void)
     2.6  {
     2.7 -	static int tri_offs[] = {0, 1, 2};
     2.8 -	static int quad_offs[] = {0, 1, 2, 0, 2, 3};
     2.9 -	int *index_offs;
    2.10 -
    2.11 -	int num_faces, in_face_verts, out_face_verts;
    2.12  	switch(im_prim) {
    2.13  	case GOAT3D_TRIANGLES:
    2.14 -		in_face_verts = 3;
    2.15 -		out_face_verts = 3;
    2.16 -		index_offs = tri_offs;
    2.17 +		{
    2.18 +			int num_faces = (int)im_mesh->vertices.size() / 3;
    2.19 +			im_mesh->faces.resize(num_faces);
    2.20 +
    2.21 +			int vidx = 0;
    2.22 +			for(int i=0; i<num_faces; i++) {
    2.23 +				im_mesh->faces[i].v[0] = vidx++;
    2.24 +				im_mesh->faces[i].v[1] = vidx++;
    2.25 +				im_mesh->faces[i].v[2] = vidx++;
    2.26 +			}
    2.27 +		}
    2.28  		break;
    2.29  
    2.30  	case GOAT3D_QUADS:
    2.31 -		in_face_verts = 4;
    2.32 -		out_face_verts = 6;
    2.33 -		index_offs = quad_offs;
    2.34 +		{
    2.35 +			int num_quads = (int)im_mesh->vertices.size() / 4;
    2.36 +			im_mesh->faces.resize(num_quads * 2);
    2.37 +
    2.38 +			int vidx = 0;
    2.39 +			for(int i=0; i<num_quads; i++) {
    2.40 +				im_mesh->faces[i * 2].v[0] = vidx;
    2.41 +				im_mesh->faces[i * 2].v[1] = vidx + 1;
    2.42 +				im_mesh->faces[i * 2].v[2] = vidx + 2;
    2.43 +
    2.44 +				im_mesh->faces[i * 2 + 1].v[0] = vidx;
    2.45 +				im_mesh->faces[i * 2 + 1].v[1] = vidx + 2;
    2.46 +				im_mesh->faces[i * 2 + 1].v[2] = vidx + 3;
    2.47 +
    2.48 +				vidx += 4;
    2.49 +			}
    2.50 +		}
    2.51  		break;
    2.52  
    2.53  	default:
    2.54  		return;
    2.55  	};
    2.56 -
    2.57 -	num_faces = (int)im_mesh->vertices.size() / in_face_verts;
    2.58 -	if(!num_faces) {
    2.59 -		return;
    2.60 -	}
    2.61 -
    2.62 -	im_mesh->faces.resize(num_faces);
    2.63 -
    2.64 -	int vidx = 0;
    2.65 -	for(int i=0; i<num_faces; i++) {
    2.66 -		for(int j=0; j<out_face_verts; j++) {
    2.67 -			im_mesh->faces[i].v[j] = vidx + index_offs[j];
    2.68 -		}
    2.69 -		vidx += 4;
    2.70 -	}
    2.71  }
    2.72  
    2.73  void goat3d_vertex3f(float x, float y, float z)
    2.74 @@ -424,21 +426,25 @@
    2.75  void goat3d_normal3f(float x, float y, float z)
    2.76  {
    2.77  	im_norm = Vector3(x, y, z);
    2.78 +	im_use[GOAT3D_MESH_ATTR_NORMAL] = true;
    2.79  }
    2.80  
    2.81  void goat3d_tangent3f(float x, float y, float z)
    2.82  {
    2.83  	im_tang = Vector3(x, y, z);
    2.84 +	im_use[GOAT3D_MESH_ATTR_TANGENT] = true;
    2.85  }
    2.86  
    2.87  void goat3d_texcoord2f(float x, float y)
    2.88  {
    2.89  	im_texcoord = Vector2(x, y);
    2.90 +	im_use[GOAT3D_MESH_ATTR_TEXCOORD] = true;
    2.91  }
    2.92  
    2.93  void goat3d_skin_weight4f(float x, float y, float z, float w)
    2.94  {
    2.95  	im_skinw = Vector4(x, y, z, w);
    2.96 +	im_use[GOAT3D_MESH_ATTR_SKIN_WEIGHT] = true;
    2.97  }
    2.98  
    2.99  void goat3d_skin_matrix4i(int x, int y, int z, int w)
   2.100 @@ -447,16 +453,18 @@
   2.101  	im_skinmat.y = y;
   2.102  	im_skinmat.z = z;
   2.103  	im_skinmat.w = w;
   2.104 +	im_use[GOAT3D_MESH_ATTR_SKIN_MATRIX] = true;
   2.105  }
   2.106  
   2.107  void goat3d_color3f(float x, float y, float z)
   2.108  {
   2.109 -	im_color = Vector4(x, y, z, 1.0f);
   2.110 +	goat3d_color4f(x, y, z, 1.0f);
   2.111  }
   2.112  
   2.113  void goat3d_color4f(float x, float y, float z, float w)
   2.114  {
   2.115  	im_color = Vector4(x, y, z, w);
   2.116 +	im_use[GOAT3D_MESH_ATTR_COLOR] = true;
   2.117  }
   2.118  
   2.119  void goat3d_add_mesh(struct goat3d *g, struct goat3d_mesh *mesh)
     3.1 --- a/src/goat3d_scene.cc	Thu Sep 26 14:16:09 2013 +0300
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,258 +0,0 @@
     3.4 -#include <stdarg.h>
     3.5 -#include "goat3d.h"
     3.6 -#include "goat3d_impl.h"
     3.7 -#include "chunk.h"
     3.8 -
     3.9 -Scene::Scene()
    3.10 -	: name("unnamed"), ambient(0.05, 0.05, 0.05)
    3.11 -{
    3.12 -}
    3.13 -
    3.14 -Scene::~Scene()
    3.15 -{
    3.16 -	clear();
    3.17 -}
    3.18 -
    3.19 -void Scene::clear()
    3.20 -{
    3.21 -	for(size_t i=0; i<materials.size(); i++) {
    3.22 -		delete materials[i];
    3.23 -	}
    3.24 -	materials.clear();
    3.25 -
    3.26 -	for(size_t i=0; i<meshes.size(); i++) {
    3.27 -		delete meshes[i];
    3.28 -	}
    3.29 -	meshes.clear();
    3.30 -
    3.31 -	for(size_t i=0; i<lights.size(); i++) {
    3.32 -		delete lights[i];
    3.33 -	}
    3.34 -	lights.clear();
    3.35 -
    3.36 -	for(size_t i=0; i<cameras.size(); i++) {
    3.37 -		delete cameras[i];
    3.38 -	}
    3.39 -	cameras.clear();
    3.40 -
    3.41 -	for(size_t i=0; i<nodes.size(); i++) {
    3.42 -		delete_node_tree(nodes[i]);
    3.43 -	}
    3.44 -	nodes.clear();
    3.45 -
    3.46 -	name = "unnamed";
    3.47 -}
    3.48 -
    3.49 -void Scene::set_name(const char *name)
    3.50 -{
    3.51 -	this->name = name;
    3.52 -}
    3.53 -
    3.54 -const char *Scene::get_name() const
    3.55 -{
    3.56 -	return name.c_str();
    3.57 -}
    3.58 -
    3.59 -void Scene::set_ambient(const Vector3 &amb)
    3.60 -{
    3.61 -	ambient = amb;
    3.62 -}
    3.63 -
    3.64 -const Vector3 &Scene::get_ambient() const
    3.65 -{
    3.66 -	return ambient;
    3.67 -}
    3.68 -
    3.69 -void Scene::add_material(Material *mat)
    3.70 -{
    3.71 -	materials.push_back(mat);
    3.72 -}
    3.73 -
    3.74 -Material *Scene::get_material(int idx) const
    3.75 -{
    3.76 -	return idx >=0 && idx < (int)materials.size() ? materials[idx] : 0;
    3.77 -}
    3.78 -
    3.79 -Material *Scene::get_material(const char *name) const
    3.80 -{
    3.81 -	for(size_t i=0; i<materials.size(); i++) {
    3.82 -		if(materials[i]->name == std::string(name)) {
    3.83 -			return materials[i];
    3.84 -		}
    3.85 -	}
    3.86 -	return 0;
    3.87 -}
    3.88 -
    3.89 -int Scene::get_material_count() const
    3.90 -{
    3.91 -	return (int)materials.size();
    3.92 -}
    3.93 -
    3.94 -
    3.95 -void Scene::add_mesh(Mesh *mesh)
    3.96 -{
    3.97 -	meshes.push_back(mesh);
    3.98 -}
    3.99 -
   3.100 -Mesh *Scene::get_mesh(int idx) const
   3.101 -{
   3.102 -	return idx >= 0 && idx < (int)meshes.size() ? meshes[idx] : 0;
   3.103 -}
   3.104 -
   3.105 -Mesh *Scene::get_mesh(const char *name) const
   3.106 -{
   3.107 -	for(size_t i=0; i<meshes.size(); i++) {
   3.108 -		if(meshes[i]->name == std::string(name)) {
   3.109 -			return meshes[i];
   3.110 -		}
   3.111 -	}
   3.112 -	return 0;
   3.113 -}
   3.114 -
   3.115 -int Scene::get_mesh_count() const
   3.116 -{
   3.117 -	return (int)meshes.size();
   3.118 -}
   3.119 -
   3.120 -
   3.121 -void Scene::add_light(Light *light)
   3.122 -{
   3.123 -	lights.push_back(light);
   3.124 -}
   3.125 -
   3.126 -Light *Scene::get_light(int idx) const
   3.127 -{
   3.128 -	return idx >= 0 && idx < (int)lights.size() ? lights[idx] : 0;
   3.129 -}
   3.130 -
   3.131 -Light *Scene::get_light(const char *name) const
   3.132 -{
   3.133 -	for(size_t i=0; i<lights.size(); i++) {
   3.134 -		if(lights[i]->name == std::string(name)) {
   3.135 -			return lights[i];
   3.136 -		}
   3.137 -	}
   3.138 -	return 0;
   3.139 -}
   3.140 -
   3.141 -int Scene::get_light_count() const
   3.142 -{
   3.143 -	return (int)lights.size();
   3.144 -}
   3.145 -
   3.146 -
   3.147 -void Scene::add_camera(Camera *cam)
   3.148 -{
   3.149 -	cameras.push_back(cam);
   3.150 -}
   3.151 -
   3.152 -Camera *Scene::get_camera(int idx) const
   3.153 -{
   3.154 -	return idx >= 0 && idx < (int)cameras.size() ? cameras[idx] : 0;
   3.155 -}
   3.156 -
   3.157 -Camera *Scene::get_camera(const char *name) const
   3.158 -{
   3.159 -	for(size_t i=0; i<cameras.size(); i++) {
   3.160 -		if(cameras[i]->name == std::string(name)) {
   3.161 -			return cameras[i];
   3.162 -		}
   3.163 -	}
   3.164 -	return 0;
   3.165 -}
   3.166 -
   3.167 -int Scene::get_camera_count() const
   3.168 -{
   3.169 -	return (int)cameras.size();
   3.170 -}
   3.171 -
   3.172 -
   3.173 -void Scene::add_node(Node *node)
   3.174 -{
   3.175 -	nodes.push_back(node);
   3.176 -}
   3.177 -
   3.178 -Node *Scene::get_node(int idx) const
   3.179 -{
   3.180 -	return idx >= 0 && idx < (int)nodes.size() ? nodes[idx] : 0;
   3.181 -}
   3.182 -
   3.183 -Node *Scene::get_node(const char *name) const
   3.184 -{
   3.185 -	for(size_t i=0; i<nodes.size(); i++) {
   3.186 -		if(strcmp(nodes[i]->get_name(), name) == 0) {
   3.187 -			return nodes[i];
   3.188 -		}
   3.189 -	}
   3.190 -	return 0;
   3.191 -}
   3.192 -
   3.193 -int Scene::get_node_count() const
   3.194 -{
   3.195 -	return (int)nodes.size();
   3.196 -}
   3.197 -
   3.198 -
   3.199 -bool Scene::load(goat3d_io *io)
   3.200 -{
   3.201 -	return false;
   3.202 -}
   3.203 -
   3.204 -bool Scene::loadxml(goat3d_io *io)
   3.205 -{
   3.206 -	return false;
   3.207 -}
   3.208 -
   3.209 -// Scene::save is defined in goat3d_write.cc
   3.210 -
   3.211 -
   3.212 -void io_fprintf(goat3d_io *io, const char *fmt, ...)
   3.213 -{
   3.214 -	va_list ap;
   3.215 -
   3.216 -	va_start(ap, fmt);
   3.217 -	io_vfprintf(io, fmt, ap);
   3.218 -	va_end(ap);
   3.219 -}
   3.220 -
   3.221 -
   3.222 -void io_vfprintf(goat3d_io *io, const char *fmt, va_list ap)
   3.223 -{
   3.224 -	char smallbuf[256];
   3.225 -	char *buf = smallbuf;
   3.226 -	int sz = sizeof smallbuf;
   3.227 -
   3.228 -	int retsz = vsnprintf(buf, sz - 1, fmt, ap);
   3.229 -
   3.230 -	if(retsz >= sz) {
   3.231 -		/* C99 mandates that snprintf with a short count should return the
   3.232 -		 * number of characters that *would* be printed.
   3.233 -		 */
   3.234 -		buf = new char[retsz + 1];
   3.235 -
   3.236 -		vsnprintf(buf, retsz, fmt, ap);
   3.237 -
   3.238 -	} else if(retsz <= 0) {
   3.239 -		/* SUSv2 and microsoft specify that snprintf with a short count
   3.240 -		 * returns an arbitrary value <= 0. So let's try allocating
   3.241 -		 * bigger and bigger arrays until we find the correct size.
   3.242 -		 */
   3.243 -		sz = sizeof smallbuf;
   3.244 -		do {
   3.245 -			sz *= 2;
   3.246 -			if(buf != smallbuf) {
   3.247 -				delete [] buf;
   3.248 -			}
   3.249 -			buf = new char[sz + 1];
   3.250 -
   3.251 -			retsz = vsnprintf(buf, sz, fmt, ap);
   3.252 -		} while(retsz <= 0);
   3.253 -	}
   3.254 -
   3.255 -	io->write(buf, retsz, io->cls);
   3.256 -
   3.257 -	if(buf != smallbuf) {
   3.258 -		delete [] buf;
   3.259 -	}
   3.260 -
   3.261 -}
     4.1 --- a/src/goat3d_writexml.cc	Thu Sep 26 14:16:09 2013 +0300
     4.2 +++ b/src/goat3d_writexml.cc	Fri Sep 27 02:29:52 2013 +0300
     4.3 @@ -1,6 +1,6 @@
     4.4  #include <stdarg.h>
     4.5  #include "goat3d_impl.h"
     4.6 -#include "chunk.h"
     4.7 +#include "log.h"
     4.8  #include "openctm.h"
     4.9  
    4.10  static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level);
    4.11 @@ -76,7 +76,9 @@
    4.12  	// then refer to that filename in the XML tags
    4.13  	xmlout(io, level, "<mesh>\n");
    4.14  	xmlout(io, level + 1, "<name string=\"%s\"/>\n", mesh->name.c_str());
    4.15 -	xmlout(io, level + 1, "<material string=\"%s\"/>\n", mesh->material->name.c_str());
    4.16 +	if(mesh->material) {
    4.17 +		xmlout(io, level + 1, "<material string=\"%s\"/>\n", mesh->material->name.c_str());
    4.18 +	}
    4.19  	xmlout(io, level + 1, "<file string=\"%s\"/>\n", mesh_filename);
    4.20  	xmlout(io, level, "</mesh>\n");
    4.21  	return true;
    4.22 @@ -145,6 +147,7 @@
    4.23  	 * probably in the comment field?
    4.24  	 */
    4.25  
    4.26 +	logmsg(LOG_INFO, "saving CTM mesh file: %s\n", fname);
    4.27  	ctmSave(ctm, fname);
    4.28  
    4.29  	ctmFreeContext(ctm);
     5.1 --- a/src/log.cc	Thu Sep 26 14:16:09 2013 +0300
     5.2 +++ b/src/log.cc	Fri Sep 27 02:29:52 2013 +0300
     5.3 @@ -6,14 +6,13 @@
     5.4  
     5.5  void logmsg(int prio, const char *fmt, ...)
     5.6  {
     5.7 -	fprintf(stderr, "goat3d error: ");
     5.8 -
     5.9  	va_list ap;
    5.10  
    5.11 -	if(prio < goat_log_level) {
    5.12 +	if(goat_log_level < prio) {
    5.13  		return;
    5.14  	}
    5.15  
    5.16 +	fprintf(stderr, "goat3d: ");
    5.17  	va_start(ap, fmt);
    5.18  	vfprintf(stderr, fmt, ap);
    5.19  	va_end(ap);
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/scene.cc	Fri Sep 27 02:29:52 2013 +0300
     6.3 @@ -0,0 +1,268 @@
     6.4 +#include <stdarg.h>
     6.5 +#include "goat3d.h"
     6.6 +#include "goat3d_impl.h"
     6.7 +#include "chunk.h"
     6.8 +
     6.9 +Scene::Scene()
    6.10 +	: name("unnamed"), ambient(0.05, 0.05, 0.05)
    6.11 +{
    6.12 +}
    6.13 +
    6.14 +Scene::~Scene()
    6.15 +{
    6.16 +	clear();
    6.17 +}
    6.18 +
    6.19 +void Scene::clear()
    6.20 +{
    6.21 +	for(size_t i=0; i<materials.size(); i++) {
    6.22 +		delete materials[i];
    6.23 +	}
    6.24 +	materials.clear();
    6.25 +
    6.26 +	for(size_t i=0; i<meshes.size(); i++) {
    6.27 +		delete meshes[i];
    6.28 +	}
    6.29 +	meshes.clear();
    6.30 +
    6.31 +	for(size_t i=0; i<lights.size(); i++) {
    6.32 +		delete lights[i];
    6.33 +	}
    6.34 +	lights.clear();
    6.35 +
    6.36 +	for(size_t i=0; i<cameras.size(); i++) {
    6.37 +		delete cameras[i];
    6.38 +	}
    6.39 +	cameras.clear();
    6.40 +
    6.41 +	for(size_t i=0; i<nodes.size(); i++) {
    6.42 +		delete_node_tree(nodes[i]);
    6.43 +	}
    6.44 +	nodes.clear();
    6.45 +
    6.46 +	name = "unnamed";
    6.47 +}
    6.48 +
    6.49 +void Scene::set_name(const char *name)
    6.50 +{
    6.51 +	this->name = name;
    6.52 +}
    6.53 +
    6.54 +const char *Scene::get_name() const
    6.55 +{
    6.56 +	return name.c_str();
    6.57 +}
    6.58 +
    6.59 +void Scene::set_ambient(const Vector3 &amb)
    6.60 +{
    6.61 +	ambient = amb;
    6.62 +}
    6.63 +
    6.64 +const Vector3 &Scene::get_ambient() const
    6.65 +{
    6.66 +	return ambient;
    6.67 +}
    6.68 +
    6.69 +void Scene::add_material(Material *mat)
    6.70 +{
    6.71 +	if(mat->name.empty()) {
    6.72 +		char buf[64];
    6.73 +		sprintf(buf, "material%04d", (int)materials.size());
    6.74 +		mat->name = std::string(buf);
    6.75 +	}
    6.76 +	materials.push_back(mat);
    6.77 +}
    6.78 +
    6.79 +Material *Scene::get_material(int idx) const
    6.80 +{
    6.81 +	return idx >=0 && idx < (int)materials.size() ? materials[idx] : 0;
    6.82 +}
    6.83 +
    6.84 +Material *Scene::get_material(const char *name) const
    6.85 +{
    6.86 +	for(size_t i=0; i<materials.size(); i++) {
    6.87 +		if(materials[i]->name == std::string(name)) {
    6.88 +			return materials[i];
    6.89 +		}
    6.90 +	}
    6.91 +	return 0;
    6.92 +}
    6.93 +
    6.94 +int Scene::get_material_count() const
    6.95 +{
    6.96 +	return (int)materials.size();
    6.97 +}
    6.98 +
    6.99 +
   6.100 +void Scene::add_mesh(Mesh *mesh)
   6.101 +{
   6.102 +	if(mesh->name.empty()) {
   6.103 +		char buf[64];
   6.104 +		sprintf(buf, "mesh%04d", (int)meshes.size());
   6.105 +		mesh->name = std::string(buf);
   6.106 +	}
   6.107 +	meshes.push_back(mesh);
   6.108 +}
   6.109 +
   6.110 +Mesh *Scene::get_mesh(int idx) const
   6.111 +{
   6.112 +	return idx >= 0 && idx < (int)meshes.size() ? meshes[idx] : 0;
   6.113 +}
   6.114 +
   6.115 +Mesh *Scene::get_mesh(const char *name) const
   6.116 +{
   6.117 +	for(size_t i=0; i<meshes.size(); i++) {
   6.118 +		if(meshes[i]->name == std::string(name)) {
   6.119 +			return meshes[i];
   6.120 +		}
   6.121 +	}
   6.122 +	return 0;
   6.123 +}
   6.124 +
   6.125 +int Scene::get_mesh_count() const
   6.126 +{
   6.127 +	return (int)meshes.size();
   6.128 +}
   6.129 +
   6.130 +
   6.131 +void Scene::add_light(Light *light)
   6.132 +{
   6.133 +	lights.push_back(light);
   6.134 +}
   6.135 +
   6.136 +Light *Scene::get_light(int idx) const
   6.137 +{
   6.138 +	return idx >= 0 && idx < (int)lights.size() ? lights[idx] : 0;
   6.139 +}
   6.140 +
   6.141 +Light *Scene::get_light(const char *name) const
   6.142 +{
   6.143 +	for(size_t i=0; i<lights.size(); i++) {
   6.144 +		if(lights[i]->name == std::string(name)) {
   6.145 +			return lights[i];
   6.146 +		}
   6.147 +	}
   6.148 +	return 0;
   6.149 +}
   6.150 +
   6.151 +int Scene::get_light_count() const
   6.152 +{
   6.153 +	return (int)lights.size();
   6.154 +}
   6.155 +
   6.156 +
   6.157 +void Scene::add_camera(Camera *cam)
   6.158 +{
   6.159 +	cameras.push_back(cam);
   6.160 +}
   6.161 +
   6.162 +Camera *Scene::get_camera(int idx) const
   6.163 +{
   6.164 +	return idx >= 0 && idx < (int)cameras.size() ? cameras[idx] : 0;
   6.165 +}
   6.166 +
   6.167 +Camera *Scene::get_camera(const char *name) const
   6.168 +{
   6.169 +	for(size_t i=0; i<cameras.size(); i++) {
   6.170 +		if(cameras[i]->name == std::string(name)) {
   6.171 +			return cameras[i];
   6.172 +		}
   6.173 +	}
   6.174 +	return 0;
   6.175 +}
   6.176 +
   6.177 +int Scene::get_camera_count() const
   6.178 +{
   6.179 +	return (int)cameras.size();
   6.180 +}
   6.181 +
   6.182 +
   6.183 +void Scene::add_node(Node *node)
   6.184 +{
   6.185 +	nodes.push_back(node);
   6.186 +}
   6.187 +
   6.188 +Node *Scene::get_node(int idx) const
   6.189 +{
   6.190 +	return idx >= 0 && idx < (int)nodes.size() ? nodes[idx] : 0;
   6.191 +}
   6.192 +
   6.193 +Node *Scene::get_node(const char *name) const
   6.194 +{
   6.195 +	for(size_t i=0; i<nodes.size(); i++) {
   6.196 +		if(strcmp(nodes[i]->get_name(), name) == 0) {
   6.197 +			return nodes[i];
   6.198 +		}
   6.199 +	}
   6.200 +	return 0;
   6.201 +}
   6.202 +
   6.203 +int Scene::get_node_count() const
   6.204 +{
   6.205 +	return (int)nodes.size();
   6.206 +}
   6.207 +
   6.208 +
   6.209 +bool Scene::load(goat3d_io *io)
   6.210 +{
   6.211 +	return false;
   6.212 +}
   6.213 +
   6.214 +bool Scene::loadxml(goat3d_io *io)
   6.215 +{
   6.216 +	return false;
   6.217 +}
   6.218 +
   6.219 +// Scene::save is defined in goat3d_write.cc
   6.220 +
   6.221 +
   6.222 +void io_fprintf(goat3d_io *io, const char *fmt, ...)
   6.223 +{
   6.224 +	va_list ap;
   6.225 +
   6.226 +	va_start(ap, fmt);
   6.227 +	io_vfprintf(io, fmt, ap);
   6.228 +	va_end(ap);
   6.229 +}
   6.230 +
   6.231 +
   6.232 +void io_vfprintf(goat3d_io *io, const char *fmt, va_list ap)
   6.233 +{
   6.234 +	char smallbuf[256];
   6.235 +	char *buf = smallbuf;
   6.236 +	int sz = sizeof smallbuf;
   6.237 +
   6.238 +	int retsz = vsnprintf(buf, sz - 1, fmt, ap);
   6.239 +
   6.240 +	if(retsz >= sz) {
   6.241 +		/* C99 mandates that snprintf with a short count should return the
   6.242 +		 * number of characters that *would* be printed.
   6.243 +		 */
   6.244 +		buf = new char[retsz + 1];
   6.245 +
   6.246 +		vsnprintf(buf, retsz, fmt, ap);
   6.247 +
   6.248 +	} else if(retsz <= 0) {
   6.249 +		/* SUSv2 and microsoft specify that snprintf with a short count
   6.250 +		 * returns an arbitrary value <= 0. So let's try allocating
   6.251 +		 * bigger and bigger arrays until we find the correct size.
   6.252 +		 */
   6.253 +		sz = sizeof smallbuf;
   6.254 +		do {
   6.255 +			sz *= 2;
   6.256 +			if(buf != smallbuf) {
   6.257 +				delete [] buf;
   6.258 +			}
   6.259 +			buf = new char[sz + 1];
   6.260 +
   6.261 +			retsz = vsnprintf(buf, sz, fmt, ap);
   6.262 +		} while(retsz <= 0);
   6.263 +	}
   6.264 +
   6.265 +	io->write(buf, retsz, io->cls);
   6.266 +
   6.267 +	if(buf != smallbuf) {
   6.268 +		delete [] buf;
   6.269 +	}
   6.270 +
   6.271 +}