/* model/material.cc This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2 */ #include #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::Registry Material::material_registry; Material::Material(const std::string &name) : material_name(name), material_color(1.0f) , material_size(64.0f, 64.0f) { aux::to_lowercase(material_name); material_flags = 0; material_texture_id = 0; } Material::~Material() { } void Material::set_color(const math::Color &color) { material_color.assign(color); material_color.a = 1.0f; } void Material::set_texture(const std::string &texture) { material_texture.assign(texture); if (material_loaderfunc) { material_loaderfunc(this); //con_debug << " material " << name() << " " << size().width() << "x" << size().height() << 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::init() { con_print << "^BInitializing materials..." << std::endl; filesystem::IFileStream shaderlist("materials/shaderlist.txt"); if (!shaderlist.is_open()) { con_warn << "Could not open " << shaderlist.name() << std::endl; return; } con_debug << " " << shaderlist.name() << std::endl; char line[1024]; while (shaderlist.getline(line, 1023)) { if ((line[0] == 0) || (line[0] == '#') || (line[0] == ';')) { continue; if ((line[0] == '/') && (line[1] == '/')) continue; } else { std::string s(line); aux::trim(s); load_shader(s); } } shaderlist.close(); } void Material::add(Material *material) { if (!find(material->name())) { material_registry[material->name()] = material; } } void Material::load_shader(const std::string &shadername) { std::string shaderfilename("materials/"); shaderfilename.append(shadername); shaderfilename.append(".shader"); filesystem::IFileStream shaderfile(shaderfilename); if (!shaderfile.is_open()) { con_warn << "Could not open " << shaderfile.name() << std::endl; return; } int parselevel = 0; unsigned int linenumber = 0; char line[1024]; unsigned int count = 0; float r,g,b; Material *material = 0; while (shaderfile.getline(line, 1023)) { linenumber++; // read materials std::string s(line); aux::trim(s); // skip empty lines if (!s.size()) continue; // skip comments if ((s[0] == '#') || (s[0] == ';') || ((s[0] == '/') && (s[1] == '/'))) continue; std::istringstream linestream(s); std::string firstword; if (linestream >> firstword) { if (firstword.compare("//") == 0) { continue; } else if (firstword.compare("}") == 0) { parselevel--; } else if (firstword.compare("{") == 0) { parselevel++; } else if ((firstword.size()) && (parselevel == 0) ) { material = find(firstword); if (material) { con_warn << "Duplicate material '" << firstword << "'" << std::endl; } else { material = new Material(firstword); add(material); count++; //con_debug << " " << firstword << std::endl; } } else if ((parselevel == 1) && (material)) { aux::to_lowercase(firstword); if (firstword.compare("color") == 0) { if (linestream >> r >> g >> b) { if (math::max(r, math::max(g, b)) > 1.0f) { r /= 255.0f; g /= 255.0f; b /= 255.0f; } material->set_color(math::Color(r, g, b, 1.0f)); } } else if (firstword.compare("engine") == 0) { material->set_flags(Engine); } else if (firstword.compare("bright") == 0) { material->set_flags(Bright); } else if (firstword.compare("environment") == 0) { material->set_flags(Environment); } else if (firstword.compare("entity") == 0) { material->set_flags(Primary); } else if (firstword.compare("entitysecond") == 0) { material->set_flags(Secondary); } else if (firstword.compare("entitythird") == 0) { material->set_flags(Tertiary); } else if (firstword.compare("ignore") == 0) { material->set_flags(Ignore); } else if (firstword.compare("qer_editorimage") == 0) { continue; } else if (firstword.compare("qer_trans") == 0) { continue; } else if (firstword.compare("texture") == 0) { // texture name should not contain spaces if (linestream >> firstword) { // remove extension if (firstword[firstword.size()-4] == '.') { firstword.erase(firstword.size()-4); } material->set_texture(firstword); material->set_flags(Material::Texture); } 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_debug << " " << shaderfile.name() << " " << count << " materials " << std::endl; shaderfile.close(); } void Material::shutdown() { clear(); } void Material::clear() { con_print << "^BClearing materials..." << std::endl; for (Registry::iterator i = material_registry.begin(); i != material_registry.end(); ++i) { delete (*i).second; } material_registry.clear(); } void Material::list() { for (Registry::iterator i = material_registry.begin(); i != material_registry.end(); ++i) { con_print << " " << (*i).second->name() << std::endl; } con_print << material_registry.size() << " registered materials" << std::endl; } Material *Material::find(const std::string &name) { for (Registry::iterator i = material_registry.begin(); i != material_registry.end(); ++i) { if ((*i).first.compare(name) == 0) return (*i).second; } return 0; } void Material::set_loader_func(LoaderFuncPtr func) { material_loaderfunc = func; } }