…aaand add PREFIX to the freebsd makefile too
[voxelands-alt.git] / src / graphics / object.c
blob7a4e1e08176c20db597a1c5620bbcd7f4db7d1da
1 /************************************************************************
2 * object.c
3 * voxelands - 3d voxel world sandbox game
4 * Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
18 ************************************************************************/
20 #include "common.h"
21 #include "graphics.h"
22 #include "array.h"
24 #include <string.h>
26 static mesh_t *object_find_mat(object_t *o, material_t *mat)
28 int i;
29 mesh_t *m;
30 for (i=0; i<o->meshes->length; i++) {
31 m = ((mesh_t**)o->meshes->data)[i];
32 if (m->mat && !strcmp(m->mat->name,mat->name))
33 return m;
36 m = mesh_create_material(mat);
38 array_push_ptr(o->meshes,m);
40 return m;
43 static mesh_t *object_find_colour(object_t *o, colour_t *c)
45 int i;
46 mesh_t *m;
47 for (i=0; i<o->meshes->length; i++) {
48 m = ((mesh_t**)o->meshes->data)[i];
49 if (m->col && m->col->r == c->r && m->col->g == c->g && m->col->b == c->b && m->col->a == c->a)
50 return m;
53 m = mesh_create_colour(c);
55 array_push_ptr(o->meshes,m);
57 return m;
60 /* create a new 3d object */
61 object_t *object_create(v3_t *pos)
63 object_t *o = NULL;
64 return o;
65 /* TODO: uncomment this render3d_object_create(); */
66 o->pos.x = pos->x;
67 o->pos.y = pos->y;
68 o->pos.z = pos->z;
70 o->anim.skeleton = 0;
71 o->anim.frame = 0;
72 o->anim.value = 0.0;
74 o->ignore = 0;
75 o->drop = 0;
77 o->abounds = NULL;
78 o->bounds.max.x = 0.0;
79 o->bounds.max.y = 0.0;
80 o->bounds.max.z = 0.0;
81 o->bounds.min.x = 0.0;
82 o->bounds.min.y = 0.0;
83 o->bounds.min.z = 0.0;
85 return o;
88 /* set the rotation for a 3d object */
89 void object_rotate(object_t *o, GLfloat x, GLfloat y, GLfloat z)
91 o->rot.x = x;
92 o->rot.y = y;
93 o->rot.z = z;
96 /* set the scale for a 3d object */
97 void object_scale(object_t *o, GLfloat x, GLfloat y, GLfloat z)
99 o->scale.x = x;
100 o->scale.y = y;
101 o->scale.z = z;
104 /* add a material to a 3d object */
105 void object_add_material(object_t *o, material_t *mat)
107 object_find_mat(o,mat);
110 /* add a colour to a 3d object */
111 void object_add_colour(object_t *o, colour_t *c)
113 object_find_colour(o,c);
116 /* add a new poly to an object */
117 void object_add_mat_poly(object_t *o, material_t *mat, v3_t *v1, v3_t *v2, v3_t *v3)
119 mesh_t *m = object_find_mat(o,mat);
121 mesh_push_poly(m,v1,v2,v3);
124 /* add a new quad to an object */
125 void object_add_mat_quad(object_t *o, material_t *mat, v3_t *v1, v3_t *v2, v3_t *v3, v3_t *v4)
127 mesh_t *m = object_find_mat(o,mat);
129 mesh_push_quad(m,v1,v2,v3,v4);
132 /* set the skeleton for animation */
133 void object_set_skeleton(object_t *o, int skel)
135 if (!o->m->skeletons || o->m->skeletons->length >= skel)
136 o->anim.skeleton = 0;
138 o->anim.skeleton = skel;
139 o->anim.frame = 0;
140 o->anim.value = 0.0;
143 /* calculate the object vertices for a given frame */
144 static void object_calc_frame(object_t *o, int frame)
146 int i;
147 skeleton_t *sk;
148 frame_t* fr;
150 array_t *fpre_current;
152 mesh_t *m;
154 sk = array_get_ptr(o->m->skeletons,o->anim.skeleton);
155 if (!sk)
156 sk = array_get_ptr(o->m->skeletons,0);
157 fr = array_get_ptr(sk->frames,frame);
158 if (!fr)
159 fr = array_get_ptr(sk->frames,0);
161 /* vertexes may be pre-calculated, if not do it now */
162 if (!fr->pre_vertex) {
163 int j;
164 int k;
165 int l;
166 int wb;
167 int we;
169 weight_t *wt;
170 joint_t *jt;
171 mesh_t *bm;
172 v3_t vt;
173 v3_t v;
175 fr->pre_vertex = array_create(ARRAY_TYPE_PTR);
176 for (k=0; k<o->meshes->length; k++) {
177 bm = array_get_ptr(o->m->meshes,k);
178 fpre_current = array_create(ARRAY_TYPE_FLOAT);
179 array_push_ptr(fr->pre_vertex,fpre_current);
180 for (i=0; i<bm->m->length; i += 2) {
181 v.x = 0.0;
182 v.y = 0.0;
183 v.z = 0.0;
185 wb = array_get_int(bm->m,i);
186 we = array_get_int(bm->m,i+1)+wb;
188 /* Calculate final vertex to draw with weights */
189 for (j=wb; j<we; j++) {
190 wt = array_get_ptr(bm->w,j);
191 jt = array_get_ptr(fr->joints,wt->joint);
193 /* Calculate transformed vertex for this weight */
194 quat_rotate(&jt->rot, &wt->pos, &vt);
196 v.x += (jt->pos.x + vt.x) * wt->bias;
197 v.y += (jt->pos.y + vt.y) * wt->bias;
198 v.z += (jt->pos.z + vt.z) * wt->bias;
201 l = (i/2)*3;
202 array_set_float(fpre_current,v.x,l);
203 array_set_float(fpre_current,v.y,l+1);
204 array_set_float(fpre_current,v.z,l+2);
209 /* now just get the frame data, and copy it to the object data */
210 for (i=0; i<o->meshes->length; i++) {
211 m = array_get_ptr(o->meshes,i);
212 fpre_current = array_get_ptr(fr->pre_vertex,i);
213 array_set_float(m->v,0.0,fpre_current->length);
214 memcpy(m->v->data,fpre_current->data,sizeof(float)*fpre_current->length);
218 /* set the frame for animation */
219 void object_set_frame(object_t *o, int frame)
221 o->anim.frame = frame;
222 o->anim.value = frame;
223 object_calc_frame(o,frame);
226 /* advance an animated objects frame */
227 int object_advance_frame(object_t *o, float dtime)
229 skeleton_t *sk = array_get_ptr(o->m->skeletons,o->anim.skeleton);
230 if (!sk)
231 sk = array_get_ptr(o->m->skeletons,0);
233 o->anim.value += sk->fps*dtime;
234 if (o->anim.frame == (int)o->anim.value)
235 return 0;
237 o->anim.frame = (int)o->anim.value;
238 if (o->anim.frame >= sk->frames->length) {
239 o->anim.value -= o->anim.frame;
240 o->anim.frame = 0;
243 object_calc_frame(o,o->anim.frame);
245 return 1;
248 /* calculate normals for an object */
249 void object_calc_normals(object_t *o)
251 int i;
252 mesh_t *m;
253 for (i=0; i<o->meshes->length; i++) {
254 m = ((mesh_t**)o->meshes->data)[i];
255 mesh_calc_normals(m);