Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/model/material.cc')
-rw-r--r--src/model/material.cc316
1 files changed, 177 insertions, 139 deletions
diff --git a/src/model/material.cc b/src/model/material.cc
index 29bd80e..0f3487c 100644
--- a/src/model/material.cc
+++ b/src/model/material.cc
@@ -6,69 +6,47 @@
#include <string>
+#include "model/material.h"
+
#include "auxiliary/functions.h"
#include "filesystem/filestream.h"
#include "math/functions.h"
-#include "model/material.h"
#include "sys/sys.h"
namespace model
{
-Material::LoaderFuncPtr Material::material_loaderfunc = 0;
+Material::ImageLoaderFuncPtr Material::material_imageloaderfunc = 0;
Material::Registry Material::material_registry;
Material::Material(const std::string &name) :
material_name(name),
- material_color(1.0f) ,
- material_specular(1.0f) ,
+ material_flags(0),
material_size(64.0f, 64.0f)
{
aux::to_lowercase(material_name);
- material_flags = 0;
- material_colortype = ColorMaterial;
- material_texture_id = 0;
-
}
Material::~Material()
{
+ for (Layers::iterator it = material_layers.begin(); it != material_layers.end(); ++it) {
+ delete (*it);
+ (*it) = 0;
+ }
+}
+
+void Material::set_size(const math::Vector2f & size)
+{
+ material_size.assign(size);
}
void Material::print()
{
con_print << name() << std::endl;
-
- con_print << " material color: " << material_color.r << " " << material_color.g << " " << material_color.b << " " << material_color.a << std::endl;
- switch (colortype()) {
- case ColorMaterial:
- break;
- case ColorPrimary:
- con_print << " color type " << "entity primary" << std::endl;
- break;
- case ColorSecondary:
- con_print << " color type " << "entity secondary" << std::endl;
- break;
- case ColorTertiary:
- con_print << " color type " << "entity tertiary" << std::endl;
- break;
- case ColorEngine:
- con_print << " color type " << "entity engine" << std::endl;
- break;
- }
con_print << " flags: " << flags() << " ";
if (flags() == FlagNone) {
con_print << "none";
} else {
- if (flags() & FlagBright) {
- con_print << "bright ";
- }
- if (flags() & FlagEnvironment) {
- con_print << "environment ";
- }
- if (flags() & FlagTexture) {
- con_print << "texture ";
- }
if (flags() & FlagIgnore) {
con_print << "ignore ";
}
@@ -84,61 +62,47 @@ void Material::print()
if (flags() & FlagBounds) {
con_print << "bounds ";
}
- }
- con_print << std::endl;
-
- if (material_texture.size()) {
- con_print << " texture: " << material_texture << std::endl;
}
+ con_print << " layers: " << layers().size() << std::endl;
-}
-
-void Material::set_color(const math::Color &color)
-{
- material_color.assign(color);
- //material_color.a = 1.0f;
-}
-
-void Material::set_specular(const math::Color &color)
-{
- material_specular.assign(color);
-}
-
-void Material::set_texture(const std::string &texture)
-{
- if (texture.size()) {
- set_flags(FlagTexture);
- material_texture.assign(texture);
- if (material_loaderfunc) {
- material_loaderfunc(this);
+ for (Layers::const_iterator lit = material_layers.begin(); lit != material_layers.end(); ++lit) {
+ const Layer *layer = (*lit);
+
+ con_print << " - texture: ";
+ if (layer->texmap() == Layer::TexMapNone) {
+ con_print << "none";
+ } else if (layer->texmap() == Layer::TexMapImage) {
+ con_print << layer->texture();
}
- } else {
- unset_flags(FlagTexture);
- material_texture.clear();
- material_texture_id = 0;
+ con_print << std::endl;
+
+ con_print << " color: " << layer->color() << std::endl;
+
+ con_print << " rgbgen: ";
+ switch (layer->rgbgen()) {
+ case Layer::RGBGenIdentity:
+ con_print << "identity";
+ break;
+ case Layer::RGBGenColor:
+ con_print << "color";
+ break;
+ case Layer::RGBGenEngine:
+ con_print << "engine";
+ break;
+ case Layer::RGBGenPrimary:
+ con_print << "entity primary";
+ break;
+ case Layer::RGBGenSecondary:
+ con_print << "entity secondary";
+ break;
+ case Layer::RGBGenTertiary:
+ con_print << "entity tertiary";
+ break;
+ }
+ con_print << std::endl;
}
}
-void Material::set_texture_id(const size_t texture_id)
-{
- material_texture_id = texture_id;
-}
-
-void Material::set_size(const float width, const float height)
-{
- material_size.assign(width, height);
-}
-
-void Material::set_size(const math::Vector2f &size)
-{
- material_size.assign(size);
-}
-
-void Material::set_colortype(ColorType colortype)
-{
- material_colortype = colortype;
-}
-
/* ---- static ----------------------------------------------------- */
void Material::init()
@@ -185,13 +149,6 @@ void Material::shutdown()
clear();
}
-void Material::add(Material *material)
-{
- if (!find(material->name())) {
- material_registry[material->name()] = material;
- }
-}
-
void Material::load_shaderfile(const std::string &shadername)
{
std::string shaderfilename("materials/");
@@ -209,7 +166,9 @@ void Material::load_shaderfile(const std::string &shadername)
char line[1024];
unsigned int count = 0;
float r, g, b, a;
+
Material *material = 0;
+ Layer *layer = 0;
while (shaderfile.getline(line, 1023)) {
linenumber++;
@@ -233,26 +192,77 @@ void Material::load_shaderfile(const std::string &shadername)
if (firstword.compare("//") == 0) {
continue;
- } else if (firstword.compare("}") == 0) {
+ } else if (firstword.compare("}") == 0){
+ if (parselevel == 2) {
+ // leaving layer definition
+ layer = 0;
+ } else if (parselevel == 1) {
+ // leaving material definition
+ material = 0;
+ }
parselevel--;
} else if (firstword.compare("{") == 0) {
parselevel++;
- } else if ((firstword.size()) && (parselevel == 0)) {
-
+ } else if (parselevel == 0) {
+
+ // add new material
material = find(firstword);
if (material) {
con_warn << "Duplicate material '" << firstword << "'" << std::endl;
+ material = 0;
+ layer = 0;
} else {
material = new Material(firstword);
- add(material);
+ material_registry[material->name()] = material;
count++;
- //con_debug << " " << firstword << std::endl;
+
+ layer = 0;
}
} else if ((parselevel == 1) && (material)) {
+
+ // inside material definition
+
+ aux::to_lowercase(firstword);
+
+ if (firstword.compare("qer_editorimage") == 0) {
+ // keyword qer_editorimage is ignored
+ continue;
+ } else if (firstword.compare("qer_trans") == 0) {
+ // keyword qer_trans is ignored
+ continue;
+ } else if (firstword.compare("surfaceparm") == 0) {
+ // keyword surfaceparm is ignored
+ continue;
+
+ } else if (firstword.compare("ignore") == 0) {
+ material->set_flags(FlagIgnore);
+ } else if (firstword.compare("clip") == 0) {
+ material->set_flags(FlagClip);
+ } else if (firstword.compare("origin") == 0) {
+ material->set_flags(FlagOrigin);
+ } else if (firstword.compare("decal") == 0) {
+ material->set_flags(FlagDecal);
+ } else if (firstword.compare("bounds") == 0) {
+ material->set_flags(FlagBounds);
+ } else {
+ con_warn << shaderfile.name() << " unknown material key '" << firstword << "' at line " << linenumber << std::endl;
+ }
+
+ } else if ((parselevel == 2) && (material)) {
+
+ // inside layer definition
+
+ // create new layer if required
+ if (!layer) {
+ layer = new Layer();
+ material->material_layers.push_back(layer);
+ }
+
aux::to_lowercase(firstword);
+
if (firstword.compare("color") == 0) {
if (linestream >> r >> g >> b) {
if (math::max(r, math::max(g, b)) > 1.0f) {
@@ -263,9 +273,10 @@ void Material::load_shaderfile(const std::string &shadername)
if (!(linestream >> a)) {
a = 1.0f;
}
- material->set_color(math::Color(r, g, b, a));
+ layer->set_color(math::Color(r, g, b, a));
+ layer->set_rgbgen(Layer::RGBGenColor);
// set specular too, preserving the old behavior
- material->set_specular(math::Color(r, g, b, a));
+ layer->set_specular(math::Color(r, g, b, a));
}
} else if (firstword.compare("specular") == 0) {
if (linestream >> r >> g >> b) {
@@ -277,56 +288,46 @@ void Material::load_shaderfile(const std::string &shadername)
if (!(linestream >> a)) {
a = 1.0f;
}
- material->set_specular(math::Color(r, g, b, a));
+ layer->set_specular(math::Color(r, g, b, a));
}
} else if (firstword.compare("engine") == 0) {
- material->set_colortype(ColorEngine);
+ layer->set_rgbgen(Layer::RGBGenEngine);
} else if (firstword.compare("entity") == 0) {
- material->set_colortype(ColorPrimary);
+ layer->set_rgbgen(Layer::RGBGenPrimary);
} else if (firstword.compare("entitysecond") == 0) {
- material->set_colortype(ColorSecondary);
+ layer->set_rgbgen(Layer::RGBGenSecondary);
} else if (firstword.compare("entitythird") == 0) {
- material->set_colortype(ColorTertiary);
-
+ layer->set_rgbgen(Layer::RGBGenTertiary);
} else if (firstword.compare("bright") == 0) {
- material->set_flags(FlagBright);
+ layer->set_bright(true);
} else if (firstword.compare("environment") == 0) {
- material->set_flags(FlagEnvironment);
- } else if (firstword.compare("ignore") == 0) {
- material->set_flags(FlagIgnore);
- } else if (firstword.compare("clip") == 0) {
- material->set_flags(FlagClip);
- } else if (firstword.compare("origin") == 0) {
- material->set_flags(FlagOrigin);
- } else if (firstword.compare("decal") == 0) {
- material->set_flags(FlagDecal);
- } else if (firstword.compare("bounds") == 0) {
- material->set_flags(FlagBounds);
- } else if (firstword.compare("qer_editorimage") == 0) {
- // keyword qer_editorimage is ignored
- continue;
- } else if (firstword.compare("qer_trans") == 0) {
- // keyword qer_trans is ignored
- continue;
- } else if (firstword.compare("surfaceparm") == 0) {
- // keyword surfaceparm is ignored
- continue;
- } else if (firstword.compare("texture") == 0) {
- // texture name should not contain spaces
+ layer->set_tcgen(Layer::TCGenEnvironment);
+ layer->set_texmap(Layer::TexMapEnvironment);
+ } else if (firstword.compare("map") == 0) {
+
if (linestream >> firstword) {
- // remove extension
- if (firstword[firstword.size()-4] == '.') {
- firstword.erase(firstword.size() - 4);
+ aux::to_lowercase(firstword);
+ if (firstword.compare("$environment") == 0) {
+ layer->set_texmap(Layer::TexMapEnvironment);
+ } else if (firstword.compare("$logo") == 0) {
+ layer->set_texmap(Layer::TexMapLogo);
+ } else {
+ // regular texture from image file
+ // FIXME strip extension from filename
+ layer->set_texture(firstword);
+
+ if (material_imageloaderfunc) {
+ material_imageloaderfunc(layer);
+ if ((layer->size().width() > 0) && (layer->size().height() > 0)) {
+ material->material_size.assign(layer->size());
+ }
+ }
}
- material->set_texture(firstword);
- } else {
- con_warn << shaderfile.name() << " texture key without filename at line " << linenumber << std::endl;
}
-
} else {
- con_warn << shaderfile.name() << " unknown key '" << firstword
- << "' at line " << linenumber << std::endl;
+ con_warn << shaderfile.name() << " unknown layer key '" << firstword << "' at line " << linenumber << std::endl;
}
+
}
}
}
@@ -346,16 +347,53 @@ void Material::list()
Material *Material::find(const std::string &name)
{
+ std::string searchstr(name);
+ aux::to_lowercase(searchstr);
+
for (Registry::iterator i = material_registry.begin(); i != material_registry.end(); ++i) {
- if ((*i).first.compare(name) == 0)
+ if ((*i).first.compare(searchstr) == 0)
return (*i).second;
}
return 0;
}
-void Material::set_loader_func(LoaderFuncPtr func)
+Material *Material::load(const std::string &name, const bool bright)
+{
+ // check if the requested material already exist
+ Material *material = find(name);
+ if (material)
+ {
+ return material;
+ }
+
+ // create a new material
+ material = new Material(name);
+
+ // create a single layer
+ Layer *layer = new Layer();
+
+ // add a texture
+ layer->set_texture(name);
+ layer->set_bright(bright);
+ if (material_imageloaderfunc) {
+ material_imageloaderfunc(layer);
+ if ((layer->size().width() > 0) && (layer->size().height() > 0)) {
+ material->material_size.assign(layer->size());
+ }
+ }
+
+ // add the new layer to the material
+ material->material_layers.push_back(layer);
+
+ // add the new material to the registry
+ material_registry[material->name()] = material;
+
+ return material;
+}
+
+void Material::set_imageloader_func(ImageLoaderFuncPtr func)
{
- material_loaderfunc = func;
+ material_imageloaderfunc = func;
}
}