goat3d

changeset 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 f1b4c27382ce
children 1d85d7dd0038 0e31f2c3f29d
files generators/goatprim/Makefile generators/goatprim/main.c src/goat3d.cc src/log.cc src/log.h
diffstat 5 files changed, 610 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/generators/goatprim/Makefile	Thu Sep 26 14:16:09 2013 +0300
     1.3 @@ -0,0 +1,17 @@
     1.4 +obj = main.o
     1.5 +bin = goatprim
     1.6 +
     1.7 +goat_root = ../..
     1.8 +libgoat = $(goat_root)/libgoat3d.so.0.1
     1.9 +
    1.10 +CC = clang
    1.11 +CXX = clang++
    1.12 +CFLAGS = -pedantic -Wall -g -I$(goat_root)/src
    1.13 +LDFLAGS = $(libgoat) -Wl,-rpath=$(goat_root)
    1.14 +
    1.15 +$(bin): $(obj) $(libgoat)
    1.16 +	$(CXX) -o $@ $(obj) $(LDFLAGS)
    1.17 +
    1.18 +.PHONY: clean
    1.19 +clean:
    1.20 +	rm -f $(obj) $(bin)
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/generators/goatprim/main.c	Thu Sep 26 14:16:09 2013 +0300
     2.3 @@ -0,0 +1,78 @@
     2.4 +#include <stdio.h>
     2.5 +#include "goat3d.h"
     2.6 +
     2.7 +static struct goat3d_mesh *create_box(void);
     2.8 +
     2.9 +int main(void)
    2.10 +{
    2.11 +	struct goat3d *goat;
    2.12 +	struct goat3d_material *mtl;
    2.13 +	struct goat3d_mesh *mesh;
    2.14 +
    2.15 +	goat = goat3d_create();
    2.16 +
    2.17 +	mtl = goat3d_create_mtl();
    2.18 +	goat3d_set_mtl_name(mtl, "mat");
    2.19 +	goat3d_set_mtl_attrib4f(mtl, GOAT3D_MAT_ATTR_DIFFUSE, 1, 0, 0, 1);
    2.20 +	goat3d_add_mtl(goat, mtl);
    2.21 +
    2.22 +	mesh = create_box();
    2.23 +	goat3d_add_mesh(goat, mesh);
    2.24 +
    2.25 +	goat3d_setopt(goat, GOAT3D_OPT_SAVEXML, 1);
    2.26 +	goat3d_save(goat, "foo.xml");
    2.27 +
    2.28 +	goat3d_free(goat);
    2.29 +	return 0;
    2.30 +}
    2.31 +
    2.32 +static struct goat3d_mesh *create_box(void)
    2.33 +{
    2.34 +	struct goat3d_mesh *mesh = goat3d_create_mesh();
    2.35 +
    2.36 +	goat3d_begin(mesh, GOAT3D_QUADS);
    2.37 +	// +X
    2.38 +	goat3d_normal3f(1, 0, 0);
    2.39 +	goat3d_vertex3f(-1, -1, 1);
    2.40 +	goat3d_vertex3f(-1, -1, -1);
    2.41 +	goat3d_vertex3f(-1, 1, -1);
    2.42 +	goat3d_vertex3f(-1, 1, 1);
    2.43 +
    2.44 +	// -X
    2.45 +	goat3d_normal3f(-1, 0, 0);
    2.46 +	goat3d_vertex3f(-1, -1, -1);
    2.47 +	goat3d_vertex3f(-1, -1, 1);
    2.48 +	goat3d_vertex3f(-1, 1, 1);
    2.49 +	goat3d_vertex3f(-1, 1, -1);
    2.50 +
    2.51 +	// +Y
    2.52 +	goat3d_normal3f(0, 1, 0);
    2.53 +	goat3d_vertex3f(-1, 1, 1);
    2.54 +	goat3d_vertex3f(1, 1, 1);
    2.55 +	goat3d_vertex3f(1, 1, -1);
    2.56 +	goat3d_vertex3f(-1, 1, -1);
    2.57 +
    2.58 +	// -Y
    2.59 +	goat3d_normal3f(0, -1, 0);
    2.60 +	goat3d_vertex3f(-1, -1, -1);
    2.61 +	goat3d_vertex3f(1, -1, -1);
    2.62 +	goat3d_vertex3f(1, -1, 1);
    2.63 +	goat3d_vertex3f(-1, -1, 1);
    2.64 +
    2.65 +	// +Z
    2.66 +	goat3d_normal3f(0, 0, 1);
    2.67 +	goat3d_vertex3f(-1, -1, 1);
    2.68 +	goat3d_vertex3f(1, -1, 1);
    2.69 +	goat3d_vertex3f(1, -1, 1);
    2.70 +	goat3d_vertex3f(-1, -1, 1);
    2.71 +
    2.72 +	// -Z
    2.73 +	goat3d_normal3f(0, 0, -1);
    2.74 +	goat3d_vertex3f(-1, -1, 1);
    2.75 +	goat3d_vertex3f(1, -1, 1);
    2.76 +	goat3d_vertex3f(1, -1, -1);
    2.77 +	goat3d_vertex3f(-1, -1, -1);
    2.78 +	goat3d_end();
    2.79 +
    2.80 +	return mesh;
    2.81 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/goat3d.cc	Thu Sep 26 14:16:09 2013 +0300
     3.3 @@ -0,0 +1,487 @@
     3.4 +#include <string.h>
     3.5 +#include <errno.h>
     3.6 +#include "goat3d.h"
     3.7 +#include "goat3d_impl.h"
     3.8 +#include "log.h"
     3.9 +
    3.10 +struct goat3d {
    3.11 +	Scene *scn;
    3.12 +	unsigned int flags;
    3.13 +};
    3.14 +
    3.15 +struct goat3d_material : public Material {};
    3.16 +struct goat3d_mesh : public Mesh {};
    3.17 +struct goat3d_light : public Light {};
    3.18 +struct goat3d_camera : public Camera {};
    3.19 +struct goat3d_node : public Node {};
    3.20 +
    3.21 +
    3.22 +static long read_file(void *buf, size_t bytes, void *uptr);
    3.23 +static long write_file(const void *buf, size_t bytes, void *uptr);
    3.24 +static long seek_file(long offs, int whence, void *uptr);
    3.25 +
    3.26 +extern "C" {
    3.27 +
    3.28 +struct goat3d *goat3d_create(void)
    3.29 +{
    3.30 +	goat3d *goat = new goat3d;
    3.31 +	goat->scn = new Scene;
    3.32 +	return goat;
    3.33 +}
    3.34 +
    3.35 +void goat3d_free(struct goat3d *g)
    3.36 +{
    3.37 +	delete g->scn;
    3.38 +	delete g;
    3.39 +}
    3.40 +
    3.41 +void goat3d_setopt(struct goat3d *g, enum goat3d_option opt, int val)
    3.42 +{
    3.43 +	if(val) {
    3.44 +		g->flags |= (1 << (int)opt);
    3.45 +	} else {
    3.46 +		g->flags &= ~(1 << (int)opt);
    3.47 +	}
    3.48 +}
    3.49 +
    3.50 +int goat3d_getopt(const struct goat3d *g, enum goat3d_option opt)
    3.51 +{
    3.52 +	return (g->flags >> (int)opt) & 1;
    3.53 +}
    3.54 +
    3.55 +int goat3d_load(struct goat3d *g, const char *fname)
    3.56 +{
    3.57 +	FILE *fp = fopen(fname, "rb");
    3.58 +	if(!fp) {
    3.59 +		logmsg(LOG_ERROR, "failed to open file \"%s\" for reading: %s\n", fname, strerror(errno));
    3.60 +		return -1;
    3.61 +	}
    3.62 +
    3.63 +	int res = goat3d_load_file(g, fp);
    3.64 +	fclose(fp);
    3.65 +	return res;
    3.66 +}
    3.67 +
    3.68 +int goat3d_save(const struct goat3d *g, const char *fname)
    3.69 +{
    3.70 +	FILE *fp = fopen(fname, "wb");
    3.71 +	if(!fp) {
    3.72 +		logmsg(LOG_ERROR, "failed to open file \"%s\" for writing: %s\n", fname, strerror(errno));
    3.73 +		return -1;
    3.74 +	}
    3.75 +
    3.76 +	int res = goat3d_save_file(g, fp);
    3.77 +	fclose(fp);
    3.78 +	return res;
    3.79 +}
    3.80 +
    3.81 +int goat3d_load_file(struct goat3d *g, FILE *fp)
    3.82 +{
    3.83 +	goat3d_io io;
    3.84 +	io.cls = fp;
    3.85 +	io.read = read_file;
    3.86 +	io.write = write_file;
    3.87 +	io.seek = seek_file;
    3.88 +
    3.89 +	return goat3d_load_io(g, &io);
    3.90 +}
    3.91 +
    3.92 +int goat3d_save_file(const struct goat3d *g, FILE *fp)
    3.93 +{
    3.94 +	goat3d_io io;
    3.95 +	io.cls = fp;
    3.96 +	io.read = read_file;
    3.97 +	io.write = write_file;
    3.98 +	io.seek = seek_file;
    3.99 +
   3.100 +	return goat3d_save_io(g, &io);
   3.101 +}
   3.102 +
   3.103 +int goat3d_load_io(struct goat3d *g, struct goat3d_io *io)
   3.104 +{
   3.105 +	if(!g->scn->load(io)) {
   3.106 +		if(g->scn->loadxml(io)) {
   3.107 +			return -1;
   3.108 +		}
   3.109 +	}
   3.110 +	return 0;
   3.111 +}
   3.112 +
   3.113 +int goat3d_save_io(const struct goat3d *g, struct goat3d_io *io)
   3.114 +{
   3.115 +	if(goat3d_getopt(g, GOAT3D_OPT_SAVEXML)) {
   3.116 +		return g->scn->savexml(io) ? 0 : -1;
   3.117 +	}
   3.118 +	return g->scn->save(io) ? 0 : -1;
   3.119 +}
   3.120 +
   3.121 +int goat3d_set_name(struct goat3d *g, const char *name)
   3.122 +{
   3.123 +	g->scn->set_name(name);
   3.124 +	return 0;
   3.125 +}
   3.126 +
   3.127 +const char *goat3d_get_name(const struct goat3d *g)
   3.128 +{
   3.129 +	return g->scn->get_name();
   3.130 +}
   3.131 +
   3.132 +void goat3d_set_ambient(struct goat3d *g, const float *amb)
   3.133 +{
   3.134 +	g->scn->set_ambient(Vector3(amb[0], amb[1], amb[2]));
   3.135 +}
   3.136 +
   3.137 +void goat3d_set_ambient3f(struct goat3d *g, float ar, float ag, float ab)
   3.138 +{
   3.139 +	g->scn->set_ambient(Vector3(ar, ag, ab));
   3.140 +}
   3.141 +
   3.142 +const float *goat3d_get_ambient(const struct goat3d *g)
   3.143 +{
   3.144 +	return &g->scn->get_ambient().x;
   3.145 +}
   3.146 +
   3.147 +// ---- materials ----
   3.148 +struct goat3d_material *goat3d_create_mtl(void)
   3.149 +{
   3.150 +	return new goat3d_material;
   3.151 +}
   3.152 +
   3.153 +void goat3d_destroy_mtl(struct goat3d_material *mtl)
   3.154 +{
   3.155 +	delete mtl;
   3.156 +}
   3.157 +
   3.158 +void goat3d_set_mtl_name(struct goat3d_material *mtl, const char *name)
   3.159 +{
   3.160 +	mtl->name = std::string(name);
   3.161 +}
   3.162 +
   3.163 +const char *goat3d_get_mtl_name(const struct goat3d_material *mtl)
   3.164 +{
   3.165 +	return mtl->name.c_str();
   3.166 +}
   3.167 +
   3.168 +void goat3d_set_mtl_attrib(struct goat3d_material *mtl, const char *attrib, const float *val)
   3.169 +{
   3.170 +	(*mtl)[attrib].value = Vector4(val[0], val[1], val[2], val[3]);
   3.171 +}
   3.172 +
   3.173 +void goat3d_set_mtl_attrib1f(struct goat3d_material *mtl, const char *attrib, float val)
   3.174 +{
   3.175 +	goat3d_set_mtl_attrib4f(mtl, attrib, val, 0, 0, 1);
   3.176 +}
   3.177 +
   3.178 +void goat3d_set_mtl_attrib3f(struct goat3d_material *mtl, const char *attrib, float r, float g, float b)
   3.179 +{
   3.180 +	goat3d_set_mtl_attrib4f(mtl, attrib, r, g, b, 1);
   3.181 +}
   3.182 +
   3.183 +void goat3d_set_mtl_attrib4f(struct goat3d_material *mtl, const char *attrib, float r, float g, float b, float a)
   3.184 +{
   3.185 +	(*mtl)[attrib].value = Vector4(r, g, b, a);
   3.186 +}
   3.187 +
   3.188 +const float *goat3d_get_mtl_attrib(struct goat3d_material *mtl, const char *attrib)
   3.189 +{
   3.190 +	return &(*mtl)[attrib].value.x;
   3.191 +}
   3.192 +
   3.193 +void goat3d_set_mtl_attrib_map(struct goat3d_material *mtl, const char *attrib, const char *mapname)
   3.194 +{
   3.195 +	(*mtl)[attrib].map = std::string(mapname);
   3.196 +}
   3.197 +
   3.198 +const char *goat3d_get_mtl_attrib_map(struct goat3d_material *mtl, const char *attrib)
   3.199 +{
   3.200 +	return (*mtl)[attrib].map.c_str();
   3.201 +}
   3.202 +
   3.203 +void goat3d_add_mtl(struct goat3d *g, struct goat3d_material *mtl)
   3.204 +{
   3.205 +	g->scn->add_material(mtl);
   3.206 +}
   3.207 +
   3.208 +// ---- meshes ----
   3.209 +struct goat3d_mesh *goat3d_create_mesh(void)
   3.210 +{
   3.211 +	return new goat3d_mesh;
   3.212 +}
   3.213 +
   3.214 +void goat3d_destroy_mesh(struct goat3d_mesh *mesh)
   3.215 +{
   3.216 +	delete mesh;
   3.217 +}
   3.218 +
   3.219 +void goat3d_set_mesh_name(struct goat3d_mesh *mesh, const char *name)
   3.220 +{
   3.221 +	mesh->name = std::string(name);
   3.222 +}
   3.223 +
   3.224 +const char *goat3d_get_mesh_name(const struct goat3d_mesh *mesh)
   3.225 +{
   3.226 +	return mesh->name.c_str();
   3.227 +}
   3.228 +
   3.229 +void goat3d_set_mesh_mtl(struct goat3d_mesh *mesh, struct goat3d_material *mtl)
   3.230 +{
   3.231 +	mesh->material = mtl;
   3.232 +}
   3.233 +
   3.234 +struct goat3d_material *goat3d_get_mesh_mtl(struct goat3d_mesh *mesh)
   3.235 +{
   3.236 +	return (goat3d_material*)mesh->material;
   3.237 +}
   3.238 +
   3.239 +int goat3d_get_mesh_attrib_count(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib)
   3.240 +{
   3.241 +	return (int)mesh->vertices.size();
   3.242 +}
   3.243 +
   3.244 +int goat3d_get_mesh_face_count(struct goat3d_mesh *mesh)
   3.245 +{
   3.246 +	return (int)mesh->faces.size();
   3.247 +}
   3.248 +
   3.249 +#if __cplusplus >= 201103L
   3.250 +#define MOVE(x)	std::move(x)
   3.251 +#else
   3.252 +#define MOVE(x) x
   3.253 +#endif
   3.254 +
   3.255 +#define VECDATA(type, data, num) \
   3.256 +	MOVE(std::vector<type>((type*)(data), (type*)(data) + (num)))
   3.257 +
   3.258 +void goat3d_set_mesh_attribs(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, const void *data, int vnum)
   3.259 +{
   3.260 +	if(attrib == GOAT3D_MESH_ATTR_VERTEX) {
   3.261 +		mesh->vertices = VECDATA(Vector3, data, vnum);
   3.262 +		return;
   3.263 +	}
   3.264 +
   3.265 +	if(vnum != (int)mesh->vertices.size()) {
   3.266 +		logmsg(LOG_ERROR, "trying to set mesh attrib data with number of elements different than the vertex array\n");
   3.267 +		return;
   3.268 +	}
   3.269 +
   3.270 +	switch(attrib) {
   3.271 +	case GOAT3D_MESH_ATTR_NORMAL:
   3.272 +		mesh->normals = VECDATA(Vector3, data, vnum);
   3.273 +		break;
   3.274 +	case GOAT3D_MESH_ATTR_TANGENT:
   3.275 +		mesh->tangents = VECDATA(Vector3, data, vnum);
   3.276 +		break;
   3.277 +	case GOAT3D_MESH_ATTR_TEXCOORD:
   3.278 +		mesh->texcoords = VECDATA(Vector2, data, vnum);
   3.279 +		break;
   3.280 +	case GOAT3D_MESH_ATTR_SKIN_WEIGHT:
   3.281 +		mesh->skin_weights = VECDATA(Vector4, data, vnum);
   3.282 +		break;
   3.283 +	case GOAT3D_MESH_ATTR_SKIN_MATRIX:
   3.284 +		mesh->skin_matrices = VECDATA(Int4, data, vnum);
   3.285 +		break;
   3.286 +	case GOAT3D_MESH_ATTR_COLOR:
   3.287 +		mesh->colors = VECDATA(Vector4, data, vnum);
   3.288 +	default:
   3.289 +		break;
   3.290 +	}
   3.291 +}
   3.292 +
   3.293 +void *goat3d_get_mesh_attribs(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib)
   3.294 +{
   3.295 +	return goat3d_get_mesh_attrib(mesh, attrib, 0);
   3.296 +}
   3.297 +
   3.298 +void *goat3d_get_mesh_attrib(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, int idx)
   3.299 +{
   3.300 +	switch(attrib) {
   3.301 +	case GOAT3D_MESH_ATTR_VERTEX:
   3.302 +		return mesh->vertices.empty() ? 0 : (void*)&mesh->vertices[idx];
   3.303 +	case GOAT3D_MESH_ATTR_NORMAL:
   3.304 +		return mesh->normals.empty() ? 0 : (void*)&mesh->normals[idx];
   3.305 +	case GOAT3D_MESH_ATTR_TANGENT:
   3.306 +		return mesh->tangents.empty() ? 0 : (void*)&mesh->tangents[idx];
   3.307 +	case GOAT3D_MESH_ATTR_TEXCOORD:
   3.308 +		return mesh->texcoords.empty() ? 0 : (void*)&mesh->texcoords[idx];
   3.309 +	case GOAT3D_MESH_ATTR_SKIN_WEIGHT:
   3.310 +		return mesh->skin_weights.empty() ? 0 : (void*)&mesh->skin_weights[idx];
   3.311 +	case GOAT3D_MESH_ATTR_SKIN_MATRIX:
   3.312 +		return mesh->skin_matrices.empty() ? 0 : (void*)&mesh->skin_matrices[idx];
   3.313 +	case GOAT3D_MESH_ATTR_COLOR:
   3.314 +		return mesh->colors.empty() ? 0 : (void*)&mesh->colors[idx];
   3.315 +	default:
   3.316 +		break;
   3.317 +	}
   3.318 +	return 0;
   3.319 +}
   3.320 +
   3.321 +
   3.322 +void goat3d_set_mesh_faces(struct goat3d_mesh *mesh, const int *data, int num)
   3.323 +{
   3.324 +	mesh->faces = VECDATA(Face, data, num);
   3.325 +}
   3.326 +
   3.327 +int *goat3d_get_mesh_faces(struct goat3d_mesh *mesh)
   3.328 +{
   3.329 +	return goat3d_get_mesh_face(mesh, 0);
   3.330 +}
   3.331 +
   3.332 +int *goat3d_get_mesh_face(struct goat3d_mesh *mesh, int idx)
   3.333 +{
   3.334 +	return mesh->faces.empty() ? 0 : mesh->faces[idx].v;
   3.335 +}
   3.336 +
   3.337 +// immedate mode state
   3.338 +static enum goat3d_im_primitive im_prim;
   3.339 +static struct goat3d_mesh *im_mesh;
   3.340 +static Vector3 im_norm, im_tang;
   3.341 +static Vector2 im_texcoord;
   3.342 +static Vector4 im_skinw, im_color = Vector4(1, 1, 1, 1);
   3.343 +static Int4 im_skinmat;
   3.344 +static bool im_use[NUM_GOAT3D_MESH_ATTRIBS];
   3.345 +
   3.346 +
   3.347 +void goat3d_begin(struct goat3d_mesh *mesh, enum goat3d_im_primitive prim)
   3.348 +{
   3.349 +	mesh->vertices.clear();
   3.350 +	mesh->normals.clear();
   3.351 +	mesh->tangents.clear();
   3.352 +	mesh->texcoords.clear();
   3.353 +	mesh->skin_weights.clear();
   3.354 +	mesh->skin_matrices.clear();
   3.355 +	mesh->colors.clear();
   3.356 +	mesh->faces.clear();
   3.357 +
   3.358 +	im_mesh = mesh;
   3.359 +	memset(im_use, 0, sizeof im_use);
   3.360 +
   3.361 +	im_prim = prim;
   3.362 +}
   3.363 +
   3.364 +void goat3d_end(void)
   3.365 +{
   3.366 +	static int tri_offs[] = {0, 1, 2};
   3.367 +	static int quad_offs[] = {0, 1, 2, 0, 2, 3};
   3.368 +	int *index_offs;
   3.369 +
   3.370 +	int num_faces, in_face_verts, out_face_verts;
   3.371 +	switch(im_prim) {
   3.372 +	case GOAT3D_TRIANGLES:
   3.373 +		in_face_verts = 3;
   3.374 +		out_face_verts = 3;
   3.375 +		index_offs = tri_offs;
   3.376 +		break;
   3.377 +
   3.378 +	case GOAT3D_QUADS:
   3.379 +		in_face_verts = 4;
   3.380 +		out_face_verts = 6;
   3.381 +		index_offs = quad_offs;
   3.382 +		break;
   3.383 +
   3.384 +	default:
   3.385 +		return;
   3.386 +	};
   3.387 +
   3.388 +	num_faces = (int)im_mesh->vertices.size() / in_face_verts;
   3.389 +	if(!num_faces) {
   3.390 +		return;
   3.391 +	}
   3.392 +
   3.393 +	im_mesh->faces.resize(num_faces);
   3.394 +
   3.395 +	int vidx = 0;
   3.396 +	for(int i=0; i<num_faces; i++) {
   3.397 +		for(int j=0; j<out_face_verts; j++) {
   3.398 +			im_mesh->faces[i].v[j] = vidx + index_offs[j];
   3.399 +		}
   3.400 +		vidx += 4;
   3.401 +	}
   3.402 +}
   3.403 +
   3.404 +void goat3d_vertex3f(float x, float y, float z)
   3.405 +{
   3.406 +	im_mesh->vertices.push_back(Vector3(x, y, z));
   3.407 +	if(im_use[GOAT3D_MESH_ATTR_NORMAL]) {
   3.408 +		im_mesh->normals.push_back(im_norm);
   3.409 +	}
   3.410 +	if(im_use[GOAT3D_MESH_ATTR_TANGENT]) {
   3.411 +		im_mesh->tangents.push_back(im_tang);
   3.412 +	}
   3.413 +	if(im_use[GOAT3D_MESH_ATTR_TEXCOORD]) {
   3.414 +		im_mesh->texcoords.push_back(im_texcoord);
   3.415 +	}
   3.416 +	if(im_use[GOAT3D_MESH_ATTR_SKIN_WEIGHT]) {
   3.417 +		im_mesh->skin_weights.push_back(im_skinw);
   3.418 +	}
   3.419 +	if(im_use[GOAT3D_MESH_ATTR_SKIN_MATRIX]) {
   3.420 +		im_mesh->skin_matrices.push_back(im_skinmat);
   3.421 +	}
   3.422 +	if(im_use[GOAT3D_MESH_ATTR_COLOR]) {
   3.423 +		im_mesh->colors.push_back(im_color);
   3.424 +	}
   3.425 +}
   3.426 +
   3.427 +void goat3d_normal3f(float x, float y, float z)
   3.428 +{
   3.429 +	im_norm = Vector3(x, y, z);
   3.430 +}
   3.431 +
   3.432 +void goat3d_tangent3f(float x, float y, float z)
   3.433 +{
   3.434 +	im_tang = Vector3(x, y, z);
   3.435 +}
   3.436 +
   3.437 +void goat3d_texcoord2f(float x, float y)
   3.438 +{
   3.439 +	im_texcoord = Vector2(x, y);
   3.440 +}
   3.441 +
   3.442 +void goat3d_skin_weight4f(float x, float y, float z, float w)
   3.443 +{
   3.444 +	im_skinw = Vector4(x, y, z, w);
   3.445 +}
   3.446 +
   3.447 +void goat3d_skin_matrix4i(int x, int y, int z, int w)
   3.448 +{
   3.449 +	im_skinmat.x = x;
   3.450 +	im_skinmat.y = y;
   3.451 +	im_skinmat.z = z;
   3.452 +	im_skinmat.w = w;
   3.453 +}
   3.454 +
   3.455 +void goat3d_color3f(float x, float y, float z)
   3.456 +{
   3.457 +	im_color = Vector4(x, y, z, 1.0f);
   3.458 +}
   3.459 +
   3.460 +void goat3d_color4f(float x, float y, float z, float w)
   3.461 +{
   3.462 +	im_color = Vector4(x, y, z, w);
   3.463 +}
   3.464 +
   3.465 +void goat3d_add_mesh(struct goat3d *g, struct goat3d_mesh *mesh)
   3.466 +{
   3.467 +	g->scn->add_mesh(mesh);
   3.468 +}
   3.469 +
   3.470 +
   3.471 +}	// extern "C"
   3.472 +
   3.473 +
   3.474 +static long read_file(void *buf, size_t bytes, void *uptr)
   3.475 +{
   3.476 +	return (long)fread(buf, 1, bytes, (FILE*)uptr);
   3.477 +}
   3.478 +
   3.479 +static long write_file(const void *buf, size_t bytes, void *uptr)
   3.480 +{
   3.481 +	return (long)fwrite(buf, 1, bytes, (FILE*)uptr);
   3.482 +}
   3.483 +
   3.484 +static long seek_file(long offs, int whence, void *uptr)
   3.485 +{
   3.486 +	if(fseek((FILE*)uptr, offs, whence) == -1) {
   3.487 +		return -1;
   3.488 +	}
   3.489 +	return ftell((FILE*)uptr);
   3.490 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/log.cc	Thu Sep 26 14:16:09 2013 +0300
     4.3 @@ -0,0 +1,20 @@
     4.4 +#include <stdio.h>
     4.5 +#include <stdarg.h>
     4.6 +#include "log.h"
     4.7 +
     4.8 +int goat_log_level = 256;
     4.9 +
    4.10 +void logmsg(int prio, const char *fmt, ...)
    4.11 +{
    4.12 +	fprintf(stderr, "goat3d error: ");
    4.13 +
    4.14 +	va_list ap;
    4.15 +
    4.16 +	if(prio < goat_log_level) {
    4.17 +		return;
    4.18 +	}
    4.19 +
    4.20 +	va_start(ap, fmt);
    4.21 +	vfprintf(stderr, fmt, ap);
    4.22 +	va_end(ap);
    4.23 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/log.h	Thu Sep 26 14:16:09 2013 +0300
     5.3 @@ -0,0 +1,8 @@
     5.4 +#ifndef LOG_H_
     5.5 +#define LOG_H_
     5.6 +
     5.7 +enum { LOG_ERROR, LOG_INFO };
     5.8 +
     5.9 +void logmsg(int prio, const char *fmt, ...);
    5.10 +
    5.11 +#endif	// LOG_H_