X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=libs%2Fgoat3d%2Fsrc%2Fg3dscn.c;fp=libs%2Fgoat3d%2Fsrc%2Fg3dscn.c;h=f58bc19e09026bc438bc35bd0a8c7ff99c147f93;hb=d5f45e3128c537f272615cf76242e1dfebccdee7;hp=0000000000000000000000000000000000000000;hpb=dd7ce87b0ad2b8a1b4758bcc9354e993b71c8599;p=raydungeon diff --git a/libs/goat3d/src/g3dscn.c b/libs/goat3d/src/g3dscn.c new file mode 100644 index 0000000..f58bc19 --- /dev/null +++ b/libs/goat3d/src/g3dscn.c @@ -0,0 +1,212 @@ +/* +goat3d - 3D scene, and animation file format library. +Copyright (C) 2013-2023 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see . +*/ +#include +#include "g3dscn.h" +#include "dynarr.h" + +int g3dimpl_obj_init(struct object *o, int type) +{ + static int last_mesh, last_light, last_camera; + struct goat3d_mesh *m; + struct goat3d_light *lt; + struct goat3d_camera *cam; + char *name; + + if(!(name = malloc(64))) { + return -1; + } + + switch(type) { + case OBJTYPE_MESH: + m = (struct goat3d_mesh*)o; + memset(m, 0, sizeof *m); + if(!(m->vertices = dynarr_alloc(0, sizeof *m->vertices))) goto err; + if(!(m->normals = dynarr_alloc(0, sizeof *m->normals))) goto err; + if(!(m->tangents = dynarr_alloc(0, sizeof *m->tangents))) goto err; + if(!(m->texcoords = dynarr_alloc(0, sizeof *m->texcoords))) goto err; + if(!(m->skin_weights = dynarr_alloc(0, sizeof *m->skin_weights))) goto err; + if(!(m->skin_matrices = dynarr_alloc(0, sizeof *m->skin_matrices))) goto err; + if(!(m->colors = dynarr_alloc(0, sizeof *m->colors))) goto err; + if(!(m->faces = dynarr_alloc(0, sizeof *m->faces))) goto err; + if(!(m->bones = dynarr_alloc(0, sizeof *m->bones))) goto err; + sprintf(name, "mesh%d", last_mesh++); + break; + + case OBJTYPE_LIGHT: + lt = (struct goat3d_light*)o; + memset(lt, 0, sizeof *lt); + cgm_vcons(<->color, 1, 1, 1); + cgm_vcons(<->attenuation, 1, 0, 0); + cgm_vcons(<->dir, 0, 0, 1); + lt->inner_cone = cgm_deg_to_rad(30); + lt->outer_cone = cgm_deg_to_rad(45); + sprintf(name, "light%d", last_light++); + break; + + case OBJTYPE_CAMERA: + cam = (struct goat3d_camera*)o; + memset(cam, 0, sizeof *cam); + cam->near_clip = 0.5f; + cam->far_clip = 500.0f; + cgm_vcons(&cam->up, 0, 1, 0); + sprintf(name, "camera%d", last_camera++); + break; + + default: + return -1; + } + + o->name = name; + o->type = type; + cgm_qcons(&o->rot, 0, 0, 0, 1); + cgm_vcons(&o->scale, 1, 1, 1); + return 0; + +err: + free(name); + g3dimpl_obj_destroy(o); + return -1; +} + +void g3dimpl_obj_destroy(struct object *o) +{ + struct goat3d_mesh *m; + + switch(o->type) { + case OBJTYPE_MESH: + m = (struct goat3d_mesh*)o; + dynarr_free(m->vertices); + dynarr_free(m->normals); + dynarr_free(m->tangents); + dynarr_free(m->texcoords); + dynarr_free(m->skin_weights); + dynarr_free(m->skin_matrices); + dynarr_free(m->colors); + dynarr_free(m->faces); + dynarr_free(m->bones); + break; + + default: + break; + } +} + +void g3dimpl_mesh_bounds(struct aabox *bb, struct goat3d_mesh *m, float *xform) +{ + int i, nverts; + + g3dimpl_aabox_init(bb); + + nverts = dynarr_size(m->vertices); + for(i=0; ivertices[i]; + if(xform) cgm_vmul_m4v3(&v, xform); + + if(v.x < bb->bmin.x) bb->bmin.x = v.x; + if(v.y < bb->bmin.y) bb->bmin.y = v.y; + if(v.z < bb->bmin.z) bb->bmin.z = v.z; + + if(v.x > bb->bmax.x) bb->bmax.x = v.x; + if(v.y > bb->bmax.y) bb->bmax.y = v.y; + if(v.z > bb->bmax.z) bb->bmax.z = v.z; + } +} + +int g3dimpl_mtl_init(struct goat3d_material *mtl) +{ + memset(mtl, 0, sizeof *mtl); + if(!(mtl->attrib = dynarr_alloc(0, sizeof *mtl->attrib))) { + return -1; + } + return 0; +} + +void g3dimpl_mtl_destroy(struct goat3d_material *mtl) +{ + int i, num = dynarr_size(mtl->attrib); + for(i=0; iattrib[i].name); + free(mtl->attrib[i].map); + } + dynarr_free(mtl->attrib); +} + +struct material_attrib *g3dimpl_mtl_findattr(struct goat3d_material *mtl, const char *name) +{ + int i, num = dynarr_size(mtl->attrib); + + for(i=0; iattrib[i].name, name) == 0) { + return mtl->attrib + i; + } + } + return 0; +} + +struct material_attrib *g3dimpl_mtl_getattr(struct goat3d_material *mtl, const char *name) +{ + int idx, len; + char *tmpname; + struct material_attrib *tmpattr, *ma; + + if((ma = g3dimpl_mtl_findattr(mtl, name))) { + return ma; + } + + len = strlen(name); + if(!(tmpname = malloc(len + 1))) { + return 0; + } + memcpy(tmpname, name, len + 1); + + idx = dynarr_size(mtl->attrib); + if(!(tmpattr = dynarr_push(mtl->attrib, 0))) { + free(tmpname); + return 0; + } + mtl->attrib = tmpattr; + + ma = mtl->attrib + idx; + ma->name = tmpname; + ma->map = 0; + cgm_wcons(&ma->value, 1, 1, 1, 1); + + return ma; +} + +void g3dimpl_node_bounds(struct aabox *bb, struct goat3d_node *n) +{ + struct object *obj = n->obj; + struct goat3d_node *cn = n->child; + float xform[16]; + + goat3d_get_matrix(n, xform); + + if(obj && obj->type == OBJTYPE_MESH) { + g3dimpl_mesh_bounds(bb, (struct goat3d_mesh*)obj, xform); + } else { + g3dimpl_aabox_init(bb); + } + + while(cn) { + struct aabox cbox; + g3dimpl_node_bounds(&cbox, cn); + g3dimpl_aabox_union(bb, bb, &cbox); + cn = cn->next; + } +}