parent
77b93bc480
commit
1bc7fc4e9e
@ -0,0 +1,172 @@ |
|||||||
|
#include "material.h" |
||||||
|
#include "array.h" |
||||||
|
#include "shader.h" |
||||||
|
#include "string_utils.h" |
||||||
|
#include "log.h" |
||||||
|
#include "model.h" |
||||||
|
|
||||||
|
#include <string.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
static struct Material* material_list; |
||||||
|
static int* empty_indices; |
||||||
|
|
||||||
|
void material_init(void) |
||||||
|
{ |
||||||
|
material_list = array_new(struct Material); |
||||||
|
empty_indices = array_new(int); |
||||||
|
|
||||||
|
/* TODO: implement reading material definitions from files */ |
||||||
|
/* Simple unshaded material */ |
||||||
|
struct Material* unshaded_mat = array_grow(material_list, struct Material); |
||||||
|
unshaded_mat->name = str_new("Unshaded"); |
||||||
|
unshaded_mat->shader = shader_create("unshaded.vert", "unshaded.frag"); |
||||||
|
unshaded_mat->registered_models = array_new(int); |
||||||
|
unshaded_mat->model_params = array_new(struct Uniform); |
||||||
|
unshaded_mat->pipeline_params = array_new(struct Uniform); |
||||||
|
unshaded_mat->active = 1; |
||||||
|
|
||||||
|
struct Uniform* uniform = array_grow(unshaded_mat->pipeline_params, struct Uniform); |
||||||
|
uniform->name = str_new("mvp"); |
||||||
|
uniform->type = UT_MAT4; |
||||||
|
uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name); |
||||||
|
|
||||||
|
uniform = array_grow(unshaded_mat->model_params, struct Uniform); |
||||||
|
uniform->name = str_new("diffuse_color"); |
||||||
|
uniform->type = UT_VEC4; |
||||||
|
uniform->location = shader_get_uniform_location(unshaded_mat->shader, "diffuse_color"); |
||||||
|
} |
||||||
|
|
||||||
|
struct Material* material_get_all_materials(void) |
||||||
|
{ |
||||||
|
return material_list; |
||||||
|
} |
||||||
|
|
||||||
|
void material_cleanup(void) |
||||||
|
{ |
||||||
|
for(int i = 0; i < array_len(material_list); i++) |
||||||
|
material_remove(i); |
||||||
|
array_free(empty_indices); |
||||||
|
} |
||||||
|
|
||||||
|
int material_register_model(struct Model* model, int model_index, const char* material_name) |
||||||
|
{ |
||||||
|
assert(material_name && model); |
||||||
|
int success = 0; |
||||||
|
int index = material_get_index(material_name); |
||||||
|
if(index < -1) |
||||||
|
{ |
||||||
|
log_error("material:register_model", "Material '%s' not found", material_name); |
||||||
|
return success; |
||||||
|
} |
||||||
|
|
||||||
|
struct Material* material = &material_list[index]; |
||||||
|
model->material = index; |
||||||
|
model->material_params = array_new(struct Material_Param); |
||||||
|
for(int i = 0; i < array_len(material->model_params); i++) |
||||||
|
{ |
||||||
|
/* set up parameters */ |
||||||
|
struct Uniform* uniform = &material->model_params[i]; |
||||||
|
struct Material_Param* param = array_grow(model->material_params, struct Material_Param); |
||||||
|
param->uniform_index = i; |
||||||
|
switch(uniform->type) |
||||||
|
{ |
||||||
|
case UT_INT: |
||||||
|
param->value = malloc(sizeof(int)); |
||||||
|
*((int*)param->value) = -1; |
||||||
|
break; |
||||||
|
case UT_FLOAT: |
||||||
|
param->value = malloc(sizeof(float)); |
||||||
|
*((float*)param->value) = -1.f; |
||||||
|
break; |
||||||
|
case UT_VEC2: |
||||||
|
param->value = malloc(sizeof(vec2)); |
||||||
|
vec2_fill((vec2*)param->value, 0.f, 0.f); |
||||||
|
break; |
||||||
|
case UT_VEC3: |
||||||
|
param->value = malloc(sizeof(vec3)); |
||||||
|
vec3_fill((vec3*)param->value, 0.f, 0.f, 0.f); |
||||||
|
break; |
||||||
|
case UT_VEC4: |
||||||
|
param->value = malloc(sizeof(vec4)); |
||||||
|
vec4_fill((vec4*)param->value, 0.f, 0.f, 0.f, 0.f); |
||||||
|
break; |
||||||
|
case UT_MAT4: |
||||||
|
param->value = malloc(sizeof(mat4)); |
||||||
|
mat4_identity((mat4*)param->value); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
array_push(material->registered_models, model_index, int); |
||||||
|
success = 1;
|
||||||
|
return success; |
||||||
|
} |
||||||
|
|
||||||
|
void material_unregister_model(struct Model* model, int model_index) |
||||||
|
{ |
||||||
|
assert(model); |
||||||
|
struct Material* material = &material_list[model->material]; |
||||||
|
/* Remove model index from material registry*/ |
||||||
|
for(int i = 0; i < array_len(material->registered_models); i++) |
||||||
|
{ |
||||||
|
if(material->registered_models[i] == model_index) |
||||||
|
{ |
||||||
|
array_remove_at(material->registered_models, i); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
struct Material* material_find(const char* material_name) |
||||||
|
{ |
||||||
|
struct Material* material = NULL; |
||||||
|
int index = material_get_index(material_name); |
||||||
|
if(index > -1) material = &material_list[index]; |
||||||
|
return material; |
||||||
|
} |
||||||
|
|
||||||
|
int material_get_index(const char* material_name) |
||||||
|
{ |
||||||
|
int index = -1; |
||||||
|
for(int i = 0; i < array_len(material_list); i++) |
||||||
|
{ |
||||||
|
if(!material_list[i].name) continue; |
||||||
|
|
||||||
|
if(strcmp(material_name, material_list[i].name) == 0) |
||||||
|
{ |
||||||
|
index = i; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
return index; |
||||||
|
} |
||||||
|
|
||||||
|
struct Material* material_get(int index) |
||||||
|
{ |
||||||
|
struct Material* material = NULL; |
||||||
|
if(index > -1 && index < array_len(material_list)) |
||||||
|
material = &material_list[index]; |
||||||
|
return material; |
||||||
|
} |
||||||
|
|
||||||
|
void material_remove(int index) |
||||||
|
{ |
||||||
|
assert(index > -1 && index < array_len(material_list)); |
||||||
|
struct Material* material = &material_list[index]; |
||||||
|
if(!material->active) |
||||||
|
return; |
||||||
|
material->active = 0; |
||||||
|
array_free(material->registered_models); |
||||||
|
for(int i = 0; i < array_len(material->model_params); i++) |
||||||
|
free(material->model_params[i].name); |
||||||
|
array_free(material->model_params); |
||||||
|
|
||||||
|
for(int i = 0; i < array_len(material->pipeline_params); i++) |
||||||
|
free(material->pipeline_params[i].name); |
||||||
|
array_free(material->pipeline_params); |
||||||
|
|
||||||
|
log_message("Removed material '%s'", material->name); |
||||||
|
free(material->name); |
||||||
|
array_push(empty_indices, index, int); |
||||||
|
} |
||||||
|
|
@ -0,0 +1,39 @@ |
|||||||
|
#ifndef material_H |
||||||
|
#define material_H |
||||||
|
|
||||||
|
struct Model; |
||||||
|
|
||||||
|
struct Uniform |
||||||
|
{ |
||||||
|
int location; |
||||||
|
int type; |
||||||
|
char* name; |
||||||
|
}; |
||||||
|
|
||||||
|
struct Material_Param |
||||||
|
{ |
||||||
|
int uniform_index; /* Index of the corresponding uniform in the material's model_params */ |
||||||
|
void* value; /* Actual value of the uniform */ |
||||||
|
}; |
||||||
|
|
||||||
|
struct Material |
||||||
|
{ |
||||||
|
char* name; |
||||||
|
int shader; |
||||||
|
int* registered_models; |
||||||
|
int active; |
||||||
|
struct Uniform* model_params; /* uniforms related to models */ |
||||||
|
struct Uniform* pipeline_params; /* general uniforms like matrices etc */ |
||||||
|
}; |
||||||
|
|
||||||
|
struct Material* material_get_all_materials(void); |
||||||
|
struct Material* material_find(const char* material_name); |
||||||
|
struct Material* material_get(int index); |
||||||
|
int material_get_index(const char* material_name); |
||||||
|
void material_init(void); |
||||||
|
void material_cleanup(void); |
||||||
|
int material_register_model(struct Model* model, int model_index, const char* material_name); |
||||||
|
void material_unregister_model(struct Model* model, int model_index); |
||||||
|
void material_remove(int index); |
||||||
|
|
||||||
|
#endif |
Loading…
Reference in new issue