goat3d

diff src/goat3d.cc @ 16:cb6c1a945a11

goat3d is starting to become functional inch by inch
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 26 Sep 2013 14:16:09 +0300
parents
children 1d85d7dd0038
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/goat3d.cc	Thu Sep 26 14:16:09 2013 +0300
     1.3 @@ -0,0 +1,487 @@
     1.4 +#include <string.h>
     1.5 +#include <errno.h>
     1.6 +#include "goat3d.h"
     1.7 +#include "goat3d_impl.h"
     1.8 +#include "log.h"
     1.9 +
    1.10 +struct goat3d {
    1.11 +	Scene *scn;
    1.12 +	unsigned int flags;
    1.13 +};
    1.14 +
    1.15 +struct goat3d_material : public Material {};
    1.16 +struct goat3d_mesh : public Mesh {};
    1.17 +struct goat3d_light : public Light {};
    1.18 +struct goat3d_camera : public Camera {};
    1.19 +struct goat3d_node : public Node {};
    1.20 +
    1.21 +
    1.22 +static long read_file(void *buf, size_t bytes, void *uptr);
    1.23 +static long write_file(const void *buf, size_t bytes, void *uptr);
    1.24 +static long seek_file(long offs, int whence, void *uptr);
    1.25 +
    1.26 +extern "C" {
    1.27 +
    1.28 +struct goat3d *goat3d_create(void)
    1.29 +{
    1.30 +	goat3d *goat = new goat3d;
    1.31 +	goat->scn = new Scene;
    1.32 +	return goat;
    1.33 +}
    1.34 +
    1.35 +void goat3d_free(struct goat3d *g)
    1.36 +{
    1.37 +	delete g->scn;
    1.38 +	delete g;
    1.39 +}
    1.40 +
    1.41 +void goat3d_setopt(struct goat3d *g, enum goat3d_option opt, int val)
    1.42 +{
    1.43 +	if(val) {
    1.44 +		g->flags |= (1 << (int)opt);
    1.45 +	} else {
    1.46 +		g->flags &= ~(1 << (int)opt);
    1.47 +	}
    1.48 +}
    1.49 +
    1.50 +int goat3d_getopt(const struct goat3d *g, enum goat3d_option opt)
    1.51 +{
    1.52 +	return (g->flags >> (int)opt) & 1;
    1.53 +}
    1.54 +
    1.55 +int goat3d_load(struct goat3d *g, const char *fname)
    1.56 +{
    1.57 +	FILE *fp = fopen(fname, "rb");
    1.58 +	if(!fp) {
    1.59 +		logmsg(LOG_ERROR, "failed to open file \"%s\" for reading: %s\n", fname, strerror(errno));
    1.60 +		return -1;
    1.61 +	}
    1.62 +
    1.63 +	int res = goat3d_load_file(g, fp);
    1.64 +	fclose(fp);
    1.65 +	return res;
    1.66 +}
    1.67 +
    1.68 +int goat3d_save(const struct goat3d *g, const char *fname)
    1.69 +{
    1.70 +	FILE *fp = fopen(fname, "wb");
    1.71 +	if(!fp) {
    1.72 +		logmsg(LOG_ERROR, "failed to open file \"%s\" for writing: %s\n", fname, strerror(errno));
    1.73 +		return -1;
    1.74 +	}
    1.75 +
    1.76 +	int res = goat3d_save_file(g, fp);
    1.77 +	fclose(fp);
    1.78 +	return res;
    1.79 +}
    1.80 +
    1.81 +int goat3d_load_file(struct goat3d *g, FILE *fp)
    1.82 +{
    1.83 +	goat3d_io io;
    1.84 +	io.cls = fp;
    1.85 +	io.read = read_file;
    1.86 +	io.write = write_file;
    1.87 +	io.seek = seek_file;
    1.88 +
    1.89 +	return goat3d_load_io(g, &io);
    1.90 +}
    1.91 +
    1.92 +int goat3d_save_file(const struct goat3d *g, FILE *fp)
    1.93 +{
    1.94 +	goat3d_io io;
    1.95 +	io.cls = fp;
    1.96 +	io.read = read_file;
    1.97 +	io.write = write_file;
    1.98 +	io.seek = seek_file;
    1.99 +
   1.100 +	return goat3d_save_io(g, &io);
   1.101 +}
   1.102 +
   1.103 +int goat3d_load_io(struct goat3d *g, struct goat3d_io *io)
   1.104 +{
   1.105 +	if(!g->scn->load(io)) {
   1.106 +		if(g->scn->loadxml(io)) {
   1.107 +			return -1;
   1.108 +		}
   1.109 +	}
   1.110 +	return 0;
   1.111 +}
   1.112 +
   1.113 +int goat3d_save_io(const struct goat3d *g, struct goat3d_io *io)
   1.114 +{
   1.115 +	if(goat3d_getopt(g, GOAT3D_OPT_SAVEXML)) {
   1.116 +		return g->scn->savexml(io) ? 0 : -1;
   1.117 +	}
   1.118 +	return g->scn->save(io) ? 0 : -1;
   1.119 +}
   1.120 +
   1.121 +int goat3d_set_name(struct goat3d *g, const char *name)
   1.122 +{
   1.123 +	g->scn->set_name(name);
   1.124 +	return 0;
   1.125 +}
   1.126 +
   1.127 +const char *goat3d_get_name(const struct goat3d *g)
   1.128 +{
   1.129 +	return g->scn->get_name();
   1.130 +}
   1.131 +
   1.132 +void goat3d_set_ambient(struct goat3d *g, const float *amb)
   1.133 +{
   1.134 +	g->scn->set_ambient(Vector3(amb[0], amb[1], amb[2]));
   1.135 +}
   1.136 +
   1.137 +void goat3d_set_ambient3f(struct goat3d *g, float ar, float ag, float ab)
   1.138 +{
   1.139 +	g->scn->set_ambient(Vector3(ar, ag, ab));
   1.140 +}
   1.141 +
   1.142 +const float *goat3d_get_ambient(const struct goat3d *g)
   1.143 +{
   1.144 +	return &g->scn->get_ambient().x;
   1.145 +}
   1.146 +
   1.147 +// ---- materials ----
   1.148 +struct goat3d_material *goat3d_create_mtl(void)
   1.149 +{
   1.150 +	return new goat3d_material;
   1.151 +}
   1.152 +
   1.153 +void goat3d_destroy_mtl(struct goat3d_material *mtl)
   1.154 +{
   1.155 +	delete mtl;
   1.156 +}
   1.157 +
   1.158 +void goat3d_set_mtl_name(struct goat3d_material *mtl, const char *name)
   1.159 +{
   1.160 +	mtl->name = std::string(name);
   1.161 +}
   1.162 +
   1.163 +const char *goat3d_get_mtl_name(const struct goat3d_material *mtl)
   1.164 +{
   1.165 +	return mtl->name.c_str();
   1.166 +}
   1.167 +
   1.168 +void goat3d_set_mtl_attrib(struct goat3d_material *mtl, const char *attrib, const float *val)
   1.169 +{
   1.170 +	(*mtl)[attrib].value = Vector4(val[0], val[1], val[2], val[3]);
   1.171 +}
   1.172 +
   1.173 +void goat3d_set_mtl_attrib1f(struct goat3d_material *mtl, const char *attrib, float val)
   1.174 +{
   1.175 +	goat3d_set_mtl_attrib4f(mtl, attrib, val, 0, 0, 1);
   1.176 +}
   1.177 +
   1.178 +void goat3d_set_mtl_attrib3f(struct goat3d_material *mtl, const char *attrib, float r, float g, float b)
   1.179 +{
   1.180 +	goat3d_set_mtl_attrib4f(mtl, attrib, r, g, b, 1);
   1.181 +}
   1.182 +
   1.183 +void goat3d_set_mtl_attrib4f(struct goat3d_material *mtl, const char *attrib, float r, float g, float b, float a)
   1.184 +{
   1.185 +	(*mtl)[attrib].value = Vector4(r, g, b, a);
   1.186 +}
   1.187 +
   1.188 +const float *goat3d_get_mtl_attrib(struct goat3d_material *mtl, const char *attrib)
   1.189 +{
   1.190 +	return &(*mtl)[attrib].value.x;
   1.191 +}
   1.192 +
   1.193 +void goat3d_set_mtl_attrib_map(struct goat3d_material *mtl, const char *attrib, const char *mapname)
   1.194 +{
   1.195 +	(*mtl)[attrib].map = std::string(mapname);
   1.196 +}
   1.197 +
   1.198 +const char *goat3d_get_mtl_attrib_map(struct goat3d_material *mtl, const char *attrib)
   1.199 +{
   1.200 +	return (*mtl)[attrib].map.c_str();
   1.201 +}
   1.202 +
   1.203 +void goat3d_add_mtl(struct goat3d *g, struct goat3d_material *mtl)
   1.204 +{
   1.205 +	g->scn->add_material(mtl);
   1.206 +}
   1.207 +
   1.208 +// ---- meshes ----
   1.209 +struct goat3d_mesh *goat3d_create_mesh(void)
   1.210 +{
   1.211 +	return new goat3d_mesh;
   1.212 +}
   1.213 +
   1.214 +void goat3d_destroy_mesh(struct goat3d_mesh *mesh)
   1.215 +{
   1.216 +	delete mesh;
   1.217 +}
   1.218 +
   1.219 +void goat3d_set_mesh_name(struct goat3d_mesh *mesh, const char *name)
   1.220 +{
   1.221 +	mesh->name = std::string(name);
   1.222 +}
   1.223 +
   1.224 +const char *goat3d_get_mesh_name(const struct goat3d_mesh *mesh)
   1.225 +{
   1.226 +	return mesh->name.c_str();
   1.227 +}
   1.228 +
   1.229 +void goat3d_set_mesh_mtl(struct goat3d_mesh *mesh, struct goat3d_material *mtl)
   1.230 +{
   1.231 +	mesh->material = mtl;
   1.232 +}
   1.233 +
   1.234 +struct goat3d_material *goat3d_get_mesh_mtl(struct goat3d_mesh *mesh)
   1.235 +{
   1.236 +	return (goat3d_material*)mesh->material;
   1.237 +}
   1.238 +
   1.239 +int goat3d_get_mesh_attrib_count(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib)
   1.240 +{
   1.241 +	return (int)mesh->vertices.size();
   1.242 +}
   1.243 +
   1.244 +int goat3d_get_mesh_face_count(struct goat3d_mesh *mesh)
   1.245 +{
   1.246 +	return (int)mesh->faces.size();
   1.247 +}
   1.248 +
   1.249 +#if __cplusplus >= 201103L
   1.250 +#define MOVE(x)	std::move(x)
   1.251 +#else
   1.252 +#define MOVE(x) x
   1.253 +#endif
   1.254 +
   1.255 +#define VECDATA(type, data, num) \
   1.256 +	MOVE(std::vector<type>((type*)(data), (type*)(data) + (num)))
   1.257 +
   1.258 +void goat3d_set_mesh_attribs(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, const void *data, int vnum)
   1.259 +{
   1.260 +	if(attrib == GOAT3D_MESH_ATTR_VERTEX) {
   1.261 +		mesh->vertices = VECDATA(Vector3, data, vnum);
   1.262 +		return;
   1.263 +	}
   1.264 +
   1.265 +	if(vnum != (int)mesh->vertices.size()) {
   1.266 +		logmsg(LOG_ERROR, "trying to set mesh attrib data with number of elements different than the vertex array\n");
   1.267 +		return;
   1.268 +	}
   1.269 +
   1.270 +	switch(attrib) {
   1.271 +	case GOAT3D_MESH_ATTR_NORMAL:
   1.272 +		mesh->normals = VECDATA(Vector3, data, vnum);
   1.273 +		break;
   1.274 +	case GOAT3D_MESH_ATTR_TANGENT:
   1.275 +		mesh->tangents = VECDATA(Vector3, data, vnum);
   1.276 +		break;
   1.277 +	case GOAT3D_MESH_ATTR_TEXCOORD:
   1.278 +		mesh->texcoords = VECDATA(Vector2, data, vnum);
   1.279 +		break;
   1.280 +	case GOAT3D_MESH_ATTR_SKIN_WEIGHT:
   1.281 +		mesh->skin_weights = VECDATA(Vector4, data, vnum);
   1.282 +		break;
   1.283 +	case GOAT3D_MESH_ATTR_SKIN_MATRIX:
   1.284 +		mesh->skin_matrices = VECDATA(Int4, data, vnum);
   1.285 +		break;
   1.286 +	case GOAT3D_MESH_ATTR_COLOR:
   1.287 +		mesh->colors = VECDATA(Vector4, data, vnum);
   1.288 +	default:
   1.289 +		break;
   1.290 +	}
   1.291 +}
   1.292 +
   1.293 +void *goat3d_get_mesh_attribs(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib)
   1.294 +{
   1.295 +	return goat3d_get_mesh_attrib(mesh, attrib, 0);
   1.296 +}
   1.297 +
   1.298 +void *goat3d_get_mesh_attrib(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, int idx)
   1.299 +{
   1.300 +	switch(attrib) {
   1.301 +	case GOAT3D_MESH_ATTR_VERTEX:
   1.302 +		return mesh->vertices.empty() ? 0 : (void*)&mesh->vertices[idx];
   1.303 +	case GOAT3D_MESH_ATTR_NORMAL:
   1.304 +		return mesh->normals.empty() ? 0 : (void*)&mesh->normals[idx];
   1.305 +	case GOAT3D_MESH_ATTR_TANGENT:
   1.306 +		return mesh->tangents.empty() ? 0 : (void*)&mesh->tangents[idx];
   1.307 +	case GOAT3D_MESH_ATTR_TEXCOORD:
   1.308 +		return mesh->texcoords.empty() ? 0 : (void*)&mesh->texcoords[idx];
   1.309 +	case GOAT3D_MESH_ATTR_SKIN_WEIGHT:
   1.310 +		return mesh->skin_weights.empty() ? 0 : (void*)&mesh->skin_weights[idx];
   1.311 +	case GOAT3D_MESH_ATTR_SKIN_MATRIX:
   1.312 +		return mesh->skin_matrices.empty() ? 0 : (void*)&mesh->skin_matrices[idx];
   1.313 +	case GOAT3D_MESH_ATTR_COLOR:
   1.314 +		return mesh->colors.empty() ? 0 : (void*)&mesh->colors[idx];
   1.315 +	default:
   1.316 +		break;
   1.317 +	}
   1.318 +	return 0;
   1.319 +}
   1.320 +
   1.321 +
   1.322 +void goat3d_set_mesh_faces(struct goat3d_mesh *mesh, const int *data, int num)
   1.323 +{
   1.324 +	mesh->faces = VECDATA(Face, data, num);
   1.325 +}
   1.326 +
   1.327 +int *goat3d_get_mesh_faces(struct goat3d_mesh *mesh)
   1.328 +{
   1.329 +	return goat3d_get_mesh_face(mesh, 0);
   1.330 +}
   1.331 +
   1.332 +int *goat3d_get_mesh_face(struct goat3d_mesh *mesh, int idx)
   1.333 +{
   1.334 +	return mesh->faces.empty() ? 0 : mesh->faces[idx].v;
   1.335 +}
   1.336 +
   1.337 +// immedate mode state
   1.338 +static enum goat3d_im_primitive im_prim;
   1.339 +static struct goat3d_mesh *im_mesh;
   1.340 +static Vector3 im_norm, im_tang;
   1.341 +static Vector2 im_texcoord;
   1.342 +static Vector4 im_skinw, im_color = Vector4(1, 1, 1, 1);
   1.343 +static Int4 im_skinmat;
   1.344 +static bool im_use[NUM_GOAT3D_MESH_ATTRIBS];
   1.345 +
   1.346 +
   1.347 +void goat3d_begin(struct goat3d_mesh *mesh, enum goat3d_im_primitive prim)
   1.348 +{
   1.349 +	mesh->vertices.clear();
   1.350 +	mesh->normals.clear();
   1.351 +	mesh->tangents.clear();
   1.352 +	mesh->texcoords.clear();
   1.353 +	mesh->skin_weights.clear();
   1.354 +	mesh->skin_matrices.clear();
   1.355 +	mesh->colors.clear();
   1.356 +	mesh->faces.clear();
   1.357 +
   1.358 +	im_mesh = mesh;
   1.359 +	memset(im_use, 0, sizeof im_use);
   1.360 +
   1.361 +	im_prim = prim;
   1.362 +}
   1.363 +
   1.364 +void goat3d_end(void)
   1.365 +{
   1.366 +	static int tri_offs[] = {0, 1, 2};
   1.367 +	static int quad_offs[] = {0, 1, 2, 0, 2, 3};
   1.368 +	int *index_offs;
   1.369 +
   1.370 +	int num_faces, in_face_verts, out_face_verts;
   1.371 +	switch(im_prim) {
   1.372 +	case GOAT3D_TRIANGLES:
   1.373 +		in_face_verts = 3;
   1.374 +		out_face_verts = 3;
   1.375 +		index_offs = tri_offs;
   1.376 +		break;
   1.377 +
   1.378 +	case GOAT3D_QUADS:
   1.379 +		in_face_verts = 4;
   1.380 +		out_face_verts = 6;
   1.381 +		index_offs = quad_offs;
   1.382 +		break;
   1.383 +
   1.384 +	default:
   1.385 +		return;
   1.386 +	};
   1.387 +
   1.388 +	num_faces = (int)im_mesh->vertices.size() / in_face_verts;
   1.389 +	if(!num_faces) {
   1.390 +		return;
   1.391 +	}
   1.392 +
   1.393 +	im_mesh->faces.resize(num_faces);
   1.394 +
   1.395 +	int vidx = 0;
   1.396 +	for(int i=0; i<num_faces; i++) {
   1.397 +		for(int j=0; j<out_face_verts; j++) {
   1.398 +			im_mesh->faces[i].v[j] = vidx + index_offs[j];
   1.399 +		}
   1.400 +		vidx += 4;
   1.401 +	}
   1.402 +}
   1.403 +
   1.404 +void goat3d_vertex3f(float x, float y, float z)
   1.405 +{
   1.406 +	im_mesh->vertices.push_back(Vector3(x, y, z));
   1.407 +	if(im_use[GOAT3D_MESH_ATTR_NORMAL]) {
   1.408 +		im_mesh->normals.push_back(im_norm);
   1.409 +	}
   1.410 +	if(im_use[GOAT3D_MESH_ATTR_TANGENT]) {
   1.411 +		im_mesh->tangents.push_back(im_tang);
   1.412 +	}
   1.413 +	if(im_use[GOAT3D_MESH_ATTR_TEXCOORD]) {
   1.414 +		im_mesh->texcoords.push_back(im_texcoord);
   1.415 +	}
   1.416 +	if(im_use[GOAT3D_MESH_ATTR_SKIN_WEIGHT]) {
   1.417 +		im_mesh->skin_weights.push_back(im_skinw);
   1.418 +	}
   1.419 +	if(im_use[GOAT3D_MESH_ATTR_SKIN_MATRIX]) {
   1.420 +		im_mesh->skin_matrices.push_back(im_skinmat);
   1.421 +	}
   1.422 +	if(im_use[GOAT3D_MESH_ATTR_COLOR]) {
   1.423 +		im_mesh->colors.push_back(im_color);
   1.424 +	}
   1.425 +}
   1.426 +
   1.427 +void goat3d_normal3f(float x, float y, float z)
   1.428 +{
   1.429 +	im_norm = Vector3(x, y, z);
   1.430 +}
   1.431 +
   1.432 +void goat3d_tangent3f(float x, float y, float z)
   1.433 +{
   1.434 +	im_tang = Vector3(x, y, z);
   1.435 +}
   1.436 +
   1.437 +void goat3d_texcoord2f(float x, float y)
   1.438 +{
   1.439 +	im_texcoord = Vector2(x, y);
   1.440 +}
   1.441 +
   1.442 +void goat3d_skin_weight4f(float x, float y, float z, float w)
   1.443 +{
   1.444 +	im_skinw = Vector4(x, y, z, w);
   1.445 +}
   1.446 +
   1.447 +void goat3d_skin_matrix4i(int x, int y, int z, int w)
   1.448 +{
   1.449 +	im_skinmat.x = x;
   1.450 +	im_skinmat.y = y;
   1.451 +	im_skinmat.z = z;
   1.452 +	im_skinmat.w = w;
   1.453 +}
   1.454 +
   1.455 +void goat3d_color3f(float x, float y, float z)
   1.456 +{
   1.457 +	im_color = Vector4(x, y, z, 1.0f);
   1.458 +}
   1.459 +
   1.460 +void goat3d_color4f(float x, float y, float z, float w)
   1.461 +{
   1.462 +	im_color = Vector4(x, y, z, w);
   1.463 +}
   1.464 +
   1.465 +void goat3d_add_mesh(struct goat3d *g, struct goat3d_mesh *mesh)
   1.466 +{
   1.467 +	g->scn->add_mesh(mesh);
   1.468 +}
   1.469 +
   1.470 +
   1.471 +}	// extern "C"
   1.472 +
   1.473 +
   1.474 +static long read_file(void *buf, size_t bytes, void *uptr)
   1.475 +{
   1.476 +	return (long)fread(buf, 1, bytes, (FILE*)uptr);
   1.477 +}
   1.478 +
   1.479 +static long write_file(const void *buf, size_t bytes, void *uptr)
   1.480 +{
   1.481 +	return (long)fwrite(buf, 1, bytes, (FILE*)uptr);
   1.482 +}
   1.483 +
   1.484 +static long seek_file(long offs, int whence, void *uptr)
   1.485 +{
   1.486 +	if(fseek((FILE*)uptr, offs, whence) == -1) {
   1.487 +		return -1;
   1.488 +	}
   1.489 +	return ftell((FILE*)uptr);
   1.490 +}