1 /************************************************************************
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 ************************************************************************/
26 static mesh_t
*object_find_mat(object_t
*o
, material_t
*mat
)
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
))
36 m
= mesh_create_material(mat
);
38 array_push_ptr(o
->meshes
,m
);
43 static mesh_t
*object_find_colour(object_t
*o
, colour_t
*c
)
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
)
53 m
= mesh_create_colour(c
);
55 array_push_ptr(o
->meshes
,m
);
60 /* create a new 3d object */
61 object_t
*object_create(v3_t
*pos
)
65 /* TODO: uncomment this render3d_object_create(); */
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;
88 /* set the rotation for a 3d object */
89 void object_rotate(object_t
*o
, GLfloat x
, GLfloat y
, GLfloat z
)
96 /* set the scale for a 3d object */
97 void object_scale(object_t
*o
, GLfloat x
, GLfloat y
, GLfloat 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
;
143 /* calculate the object vertices for a given frame */
144 static void object_calc_frame(object_t
*o
, int frame
)
150 array_t
*fpre_current
;
154 sk
= array_get_ptr(o
->m
->skeletons
,o
->anim
.skeleton
);
156 sk
= array_get_ptr(o
->m
->skeletons
,0);
157 fr
= array_get_ptr(sk
->frames
,frame
);
159 fr
= array_get_ptr(sk
->frames
,0);
161 /* vertexes may be pre-calculated, if not do it now */
162 if (!fr
->pre_vertex
) {
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) {
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
;
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
);
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
)
237 o
->anim
.frame
= (int)o
->anim
.value
;
238 if (o
->anim
.frame
>= sk
->frames
->length
) {
239 o
->anim
.value
-= o
->anim
.frame
;
243 object_calc_frame(o
,o
->anim
.frame
);
248 /* calculate normals for an object */
249 void object_calc_normals(object_t
*o
)
253 for (i
=0; i
<o
->meshes
->length
; i
++) {
254 m
= ((mesh_t
**)o
->meshes
->data
)[i
];
255 mesh_calc_normals(m
);