added scr_lvled, a bunch of libraries, and improved framework code
[raydungeon] / libs / goat3d / src / g3dscn.c
1 /*
2 goat3d - 3D scene, and animation file format library.
3 Copyright (C) 2013-2023  John Tsiombikas <nuclear@member.fsf.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include <string.h>
19 #include "g3dscn.h"
20 #include "dynarr.h"
21
22 int g3dimpl_obj_init(struct object *o, int type)
23 {
24         static int last_mesh, last_light, last_camera;
25         struct goat3d_mesh *m;
26         struct goat3d_light *lt;
27         struct goat3d_camera *cam;
28         char *name;
29
30         if(!(name = malloc(64))) {
31                 return -1;
32         }
33
34         switch(type) {
35         case OBJTYPE_MESH:
36                 m = (struct goat3d_mesh*)o;
37                 memset(m, 0, sizeof *m);
38                 if(!(m->vertices = dynarr_alloc(0, sizeof *m->vertices))) goto err;
39                 if(!(m->normals = dynarr_alloc(0, sizeof *m->normals))) goto err;
40                 if(!(m->tangents = dynarr_alloc(0, sizeof *m->tangents))) goto err;
41                 if(!(m->texcoords = dynarr_alloc(0, sizeof *m->texcoords))) goto err;
42                 if(!(m->skin_weights = dynarr_alloc(0, sizeof *m->skin_weights))) goto err;
43                 if(!(m->skin_matrices = dynarr_alloc(0, sizeof *m->skin_matrices))) goto err;
44                 if(!(m->colors = dynarr_alloc(0, sizeof *m->colors))) goto err;
45                 if(!(m->faces = dynarr_alloc(0, sizeof *m->faces))) goto err;
46                 if(!(m->bones = dynarr_alloc(0, sizeof *m->bones))) goto err;
47                 sprintf(name, "mesh%d", last_mesh++);
48                 break;
49
50         case OBJTYPE_LIGHT:
51                 lt = (struct goat3d_light*)o;
52                 memset(lt, 0, sizeof *lt);
53                 cgm_vcons(&lt->color, 1, 1, 1);
54                 cgm_vcons(&lt->attenuation, 1, 0, 0);
55                 cgm_vcons(&lt->dir, 0, 0, 1);
56                 lt->inner_cone = cgm_deg_to_rad(30);
57                 lt->outer_cone = cgm_deg_to_rad(45);
58                 sprintf(name, "light%d", last_light++);
59                 break;
60
61         case OBJTYPE_CAMERA:
62                 cam = (struct goat3d_camera*)o;
63                 memset(cam, 0, sizeof *cam);
64                 cam->near_clip = 0.5f;
65                 cam->far_clip = 500.0f;
66                 cgm_vcons(&cam->up, 0, 1, 0);
67                 sprintf(name, "camera%d", last_camera++);
68                 break;
69
70         default:
71                 return -1;
72         }
73
74         o->name = name;
75         o->type = type;
76         cgm_qcons(&o->rot, 0, 0, 0, 1);
77         cgm_vcons(&o->scale, 1, 1, 1);
78         return 0;
79
80 err:
81         free(name);
82         g3dimpl_obj_destroy(o);
83         return -1;
84 }
85
86 void g3dimpl_obj_destroy(struct object *o)
87 {
88         struct goat3d_mesh *m;
89
90         switch(o->type) {
91         case OBJTYPE_MESH:
92                 m = (struct goat3d_mesh*)o;
93                 dynarr_free(m->vertices);
94                 dynarr_free(m->normals);
95                 dynarr_free(m->tangents);
96                 dynarr_free(m->texcoords);
97                 dynarr_free(m->skin_weights);
98                 dynarr_free(m->skin_matrices);
99                 dynarr_free(m->colors);
100                 dynarr_free(m->faces);
101                 dynarr_free(m->bones);
102                 break;
103
104         default:
105                 break;
106         }
107 }
108
109 void g3dimpl_mesh_bounds(struct aabox *bb, struct goat3d_mesh *m, float *xform)
110 {
111         int i, nverts;
112
113         g3dimpl_aabox_init(bb);
114
115         nverts = dynarr_size(m->vertices);
116         for(i=0; i<nverts; i++) {
117                 cgm_vec3 v = m->vertices[i];
118                 if(xform) cgm_vmul_m4v3(&v, xform);
119
120                 if(v.x < bb->bmin.x) bb->bmin.x = v.x;
121                 if(v.y < bb->bmin.y) bb->bmin.y = v.y;
122                 if(v.z < bb->bmin.z) bb->bmin.z = v.z;
123
124                 if(v.x > bb->bmax.x) bb->bmax.x = v.x;
125                 if(v.y > bb->bmax.y) bb->bmax.y = v.y;
126                 if(v.z > bb->bmax.z) bb->bmax.z = v.z;
127         }
128 }
129
130 int g3dimpl_mtl_init(struct goat3d_material *mtl)
131 {
132         memset(mtl, 0, sizeof *mtl);
133         if(!(mtl->attrib = dynarr_alloc(0, sizeof *mtl->attrib))) {
134                 return -1;
135         }
136         return 0;
137 }
138
139 void g3dimpl_mtl_destroy(struct goat3d_material *mtl)
140 {
141         int i, num = dynarr_size(mtl->attrib);
142         for(i=0; i<num; i++) {
143                 free(mtl->attrib[i].name);
144                 free(mtl->attrib[i].map);
145         }
146         dynarr_free(mtl->attrib);
147 }
148
149 struct material_attrib *g3dimpl_mtl_findattr(struct goat3d_material *mtl, const char *name)
150 {
151         int i, num = dynarr_size(mtl->attrib);
152
153         for(i=0; i<num; i++) {
154                 if(strcmp(mtl->attrib[i].name, name) == 0) {
155                         return mtl->attrib + i;
156                 }
157         }
158         return 0;
159 }
160
161 struct material_attrib *g3dimpl_mtl_getattr(struct goat3d_material *mtl, const char *name)
162 {
163         int idx, len;
164         char *tmpname;
165         struct material_attrib *tmpattr, *ma;
166
167         if((ma = g3dimpl_mtl_findattr(mtl, name))) {
168                 return ma;
169         }
170
171         len = strlen(name);
172         if(!(tmpname = malloc(len + 1))) {
173                 return 0;
174         }
175         memcpy(tmpname, name, len + 1);
176
177         idx = dynarr_size(mtl->attrib);
178         if(!(tmpattr = dynarr_push(mtl->attrib, 0))) {
179                 free(tmpname);
180                 return 0;
181         }
182         mtl->attrib = tmpattr;
183
184         ma = mtl->attrib + idx;
185         ma->name = tmpname;
186         ma->map = 0;
187         cgm_wcons(&ma->value, 1, 1, 1, 1);
188
189         return ma;
190 }
191
192 void g3dimpl_node_bounds(struct aabox *bb, struct goat3d_node *n)
193 {
194         struct object *obj = n->obj;
195         struct goat3d_node *cn = n->child;
196         float xform[16];
197
198         goat3d_get_matrix(n, xform);
199
200         if(obj && obj->type == OBJTYPE_MESH) {
201                 g3dimpl_mesh_bounds(bb, (struct goat3d_mesh*)obj, xform);
202         } else {
203                 g3dimpl_aabox_init(bb);
204         }
205
206         while(cn) {
207                 struct aabox cbox;
208                 g3dimpl_node_bounds(&cbox, cn);
209                 g3dimpl_aabox_union(bb, bb, &cbox);
210                 cn = cn->next;
211         }
212 }