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 material_t
*mat_list
= NULL
;
27 static int mat_ids
= 0;
29 /* find or create a material called 'name' */
30 material_t
*mat_find_or_create(char* name
)
32 material_t
*mat
= mat_list
;
34 if (!strcmp(mat
->name
,name
))
41 strcpy(mat
->name
,name
);
46 /* create a new blank material */
47 material_t
*mat_create()
49 material_t
*mat
= malloc(sizeof(material_t
));
52 mat
->options
= 0;/* TODO: set to MATOPT_BFCULL;*/
55 mat
->ambient
[0] = 1.0;
56 mat
->ambient
[1] = 1.0;
57 mat
->ambient
[2] = 1.0;
58 mat
->ambient
[3] = 1.0;
59 mat
->specular
[0] = 1.0;
60 mat
->specular
[1] = 1.0;
61 mat
->specular
[2] = 1.0;
62 mat
->specular
[3] = 1.0;
63 mat
->diffuse
[0] = 1.0;
64 mat
->diffuse
[1] = 1.0;
65 mat
->diffuse
[2] = 1.0;
66 mat
->diffuse
[3] = 1.0;
68 mat_list
= list_push(&mat_list
,mat
);
74 void mat_free(material_t
*mat
)
79 mat_list
= list_remove(&mat_list
,mat
);
87 /* create a material from a texture */
88 material_t
*mat_from_tex(texture_t
*tex
)
90 material_t
*mat
= mat_find_or_create(tex
->name
);
94 strcpy(mat
->name
,tex
->name
);
99 /* create a material from pixel data */
100 material_t
*mat_from_pixels(image_t
*p
)
102 material_t
*mat
= mat_create();
103 mat
->tex
= tex_from_pixels(p
);
104 strcpy(mat
->name
,mat
->tex
->name
);
109 /* update a material from pixel data */
110 material_t
*mat_update_pixels(material_t
*mat
, image_t
*p
)
113 return mat_from_pixels(p
);
115 mat
->tex
= tex_update_pixels(mat
->tex
,p
);
120 /* create a material from an image */
121 material_t
*mat_from_image(char* type
, char* file
)
123 material_t
*mat
= mat_find_or_create(file
);
126 mat
->tex
= tex_from_image(type
,file
);
131 strcpy(mat
->name
,mat
->tex
->name
);
136 /* create a material from float diffuse values */
137 material_t
*mat_from_dif3f(GLfloat r
, GLfloat g
, GLfloat b
)
141 snprintf(buff
,100,"rgb-%f-%f-%f",r
,g
,b
);
143 mat
= mat_find_or_create(buff
);
144 if ((mat
->options
&MATOPT_DIFFUSE
) == MATOPT_DIFFUSE
)
151 mat
->options
|= MATOPT_DIFFUSE
;
153 strcpy(mat
->name
,buff
);
158 /* create a material from unsigned byte diffuse values */
159 material_t
*mat_from_dif3ub(uint8_t r
, uint8_t g
, uint8_t b
)
161 GLfloat rf
= (GLfloat
)r
/255.0;
162 GLfloat gf
= (GLfloat
)g
/255.0;
163 GLfloat bf
= (GLfloat
)b
/255.0;
165 return mat_from_dif3f(rf
,gf
,bf
);
168 /* create a material from a colour */
169 material_t
*mat_from_colour(colour_t
*c
)
173 GLfloat rf
= (GLfloat
)c
->r
/255.0;
174 GLfloat gf
= (GLfloat
)c
->g
/255.0;
175 GLfloat bf
= (GLfloat
)c
->b
/255.0;
176 GLfloat af
= (GLfloat
)c
->a
/255.0;
177 snprintf(buff
,100,"rgba-%.3f-%.3f-%.3f-%.3f",rf
,gf
,bf
,af
);
179 mat
= mat_find_or_create(buff
);
180 if ((mat
->options
&MATOPT_DIFFUSE
) == MATOPT_DIFFUSE
)
183 mat
->diffuse
[0] = rf
;
184 mat
->diffuse
[1] = gf
;
185 mat
->diffuse
[2] = bf
;
186 mat
->diffuse
[3] = af
;
188 mat
->options
|= MATOPT_DIFFUSE
;
190 strcpy(mat
->name
,buff
);
196 void mat_use(material_t
*mat
)
199 if (mat
->tex
->state
!= 1)
200 tex_generate(mat
->tex
);
202 glEnable(GL_TEXTURE_2D
);
203 glActiveTexture(GL_TEXTURE0
);
204 glBindTexture(GL_TEXTURE_2D
,mat
->tex
->tex
);
205 if (glGetError() != GL_NO_ERROR
)
208 glDisable(GL_TEXTURE_2D
);
211 if ((mat
->options
&MATOPT_DIFFUSE
) == MATOPT_DIFFUSE
) {
212 glColor4f(mat
->diffuse
[0],mat
->diffuse
[1],mat
->diffuse
[2],mat
->diffuse
[3]);
214 glColor4f(1.0,1.0,1.0,1.0);
218 opengl_backfacecull_setter((mat
->options
&MATOPT_BFCULL
));
221 /* specular and ambient doesn't work well (if at all) with
222 * glDrawElements() so ignore them
223 * TODO: a better solution *
225 if ((mat->options&MATOPT_SPECULAR) == MATOPT_SPECULAR) {
226 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat->specular);
228 GLfloat spc[4] = {1.0,1.0,1.0,1.0};
229 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spc);
232 if ((mat->options&MATOPT_AMBIENT) == MATOPT_AMBIENT) {
233 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat->ambient);
235 GLfloat amb[4] = {1.0,1.0,1.0,1.0};
236 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, amb);
239 if ((mat->options&MATOPT_SPECULAR) == MATOPT_SPECULAR) {
240 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat->specular);
242 GLfloat spc[4] = {1.0,1.0,1.0,1.0};
243 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spc);
246 if ((mat->options&MATOPT_SPECULAR) == MATOPT_SPECULAR) {
247 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat->specular);
249 GLfloat spc[4] = {1.0,1.0,1.0,1.0};
250 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spc);
254 /* GLfloat tmp[4] = {0.1,0.1,0.1,0.1}; */
255 /* glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,tmp); */
260 /* glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,tmp); */
263 /* set the name of a material */
264 void mat_name(material_t
*mat
, char* name
)
266 strncpy(mat
->name
,name
,100);
269 /* set the texture of a material */
270 void mat_tex(material_t
*mat
, texture_t
*tex
)
275 /* set the texture of a material from an image file */
276 void mat_tex_file(material_t
*mat
, char* type
, char* file
)
278 mat
->tex
= tex_from_image(type
,file
);
279 strcpy(mat
->name
,mat
->tex
->name
);
282 /* set the ambient values of a material from float values */
283 void mat_amb3f(material_t
*mat
, GLfloat r
, GLfloat g
, GLfloat b
)
289 mat
->options
|= MATOPT_AMBIENT
;
292 /* set the ambient values of a material from unsigned byte values */
293 void mat_amb3ub(material_t
*mat
, uint8_t r
, uint8_t g
, uint8_t b
)
295 mat
->ambient
[0] = (GLfloat
)r
/255.0;
296 mat
->ambient
[1] = (GLfloat
)g
/255.0;
297 mat
->ambient
[2] = (GLfloat
)b
/255.0;
299 mat
->options
|= MATOPT_AMBIENT
;
302 /* set the diffuse values of a material from float values */
303 void mat_dif3f(material_t
*mat
, GLfloat r
, GLfloat g
, GLfloat b
)
309 mat
->options
|= MATOPT_DIFFUSE
;
312 /* set the diffuse values of a material from unsigned byte values */
313 void mat_dif3ub(material_t
*mat
, uint8_t r
, uint8_t g
, uint8_t b
)
315 mat
->diffuse
[0] = (GLfloat
)r
/255.0;
316 mat
->diffuse
[1] = (GLfloat
)g
/255.0;
317 mat
->diffuse
[2] = (GLfloat
)b
/255.0;
319 mat
->options
|= MATOPT_DIFFUSE
;
322 /* set the specular values of a material from float values */
323 void mat_spc3f(material_t
*mat
, GLfloat r
, GLfloat g
, GLfloat b
)
325 mat
->specular
[0] = r
;
326 mat
->specular
[1] = g
;
327 mat
->specular
[2] = b
;
329 mat
->options
|= MATOPT_SPECULAR
;
332 /* set the specular values of a material from unsigned byte values */
333 void mat_spc3ub(material_t
*mat
, uint8_t r
, uint8_t g
, uint8_t b
)
335 mat
->specular
[0] = (GLfloat
)r
/255.0;
336 mat
->specular
[1] = (GLfloat
)g
/255.0;
337 mat
->specular
[2] = (GLfloat
)b
/255.0;
339 mat
->options
|= MATOPT_SPECULAR
;
342 /* set the alpha value of a material from float data */
343 void mat_alf(material_t
*mat
, GLfloat d
)
346 mat
->options
|= MATOPT_DIFFUSE
;
349 /* set the alpha values of a material from unsigned byte data */
350 void mat_alub(material_t
*mat
, uint8_t d
)
352 mat
->diffuse
[3] = (GLfloat
)d
/255.0;
354 mat
->options
|= MATOPT_DIFFUSE
;
357 /* set the options for a material, return the previous options */
358 uint32_t mat_options(material_t
*mat
, uint32_t opt
)
360 uint32_t o
= mat
->options
;
361 if (opt
!= MATOPT_GET
)