diff options
author | 53hornet <53hornet@gmail.com> | 2019-02-02 23:33:15 -0500 |
---|---|---|
committer | 53hornet <53hornet@gmail.com> | 2019-02-02 23:33:15 -0500 |
commit | db072ad4dc181eca5a1458656b130beb43f475bf (patch) | |
tree | a3c03c7f5497cb70503e2486662fa85cfb53415a /hw6/src/sceneIO_material.cpp | |
download | csci427-db072ad4dc181eca5a1458656b130beb43f475bf.tar.xz csci427-db072ad4dc181eca5a1458656b130beb43f475bf.zip |
Diffstat (limited to 'hw6/src/sceneIO_material.cpp')
-rw-r--r-- | hw6/src/sceneIO_material.cpp | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/hw6/src/sceneIO_material.cpp b/hw6/src/sceneIO_material.cpp new file mode 100644 index 0000000..7999eca --- /dev/null +++ b/hw6/src/sceneIO_material.cpp @@ -0,0 +1,243 @@ +/******************************************************************/ +/* This file is part of the homework assignments for CSCI-427/527 */ +/* at The College of William & Mary and authored by Pieter Peers. */ +/* No part of this file, whether altered or in original form, can */ +/* be distributed or used outside the context of CSCI-427/527 */ +/* without consent of either the College of William & Mary or */ +/* Pieter Peers. */ +/******************************************************************/ +#include <cassert> + +#include "sceneIO_xml.h" +#include "sceneIO_core.h" +#include "sceneIO_texture.h" +#include "sceneIO_material.h" + +#include "bumpMap.h" +#include "normalMap.h" +#include "compoundShader.h" +#include "reflectanceParameter.h" +#include "phongReflectanceShader.h" +#include "diffuseReflectanceShader.h" + +////////////////////////////////////////////////////////////// +static colorReflectanceParameter importColorReflectanceParameter(const XMLNode& node, nodeCache<texture_base>& texture_cache, const std::string& rootDir) +{ + // get parameter + color value = getColor(node, "value", color(0.0f, 0.0f, 0.0f)); + + // check for texture + std::shared_ptr<const texture_base> texture = importTexture(node.firstChild(), texture_cache, rootDir); + + // create & return parameter, give preference to textured parameters + if(texture) return colorReflectanceParameter(texture); + else return colorReflectanceParameter(value); + + // Done. +} + +////////////////////////////////////////////////////////////// +static scalarReflectanceParameter importScalarReflectanceParameter(const XMLNode& node, nodeCache<texture_base>& texture_cache, const std::string& rootDir) +{ + // get parameters + float value = getFloat(node, "value", 0.0f); + unsigned int channel = getInteger(node, "channel", 0); + + // check for texture + std::shared_ptr<const texture_base> texture = importTexture(node.firstChild(), texture_cache, rootDir); + + // create & return parameter, give preference to textured parameters + if(texture) return scalarReflectanceParameter(texture, channel); + else return scalarReflectanceParameter(value); + + // Done. +} + +////////////////////////////////////////////////////////////// +static std::shared_ptr<shader_base> importDiffuse(const XMLNode& node, nodeCache<shader_base>& shader_cache, nodeCache<texture_base>& texture_cache, const std::string& rootDir) +{ + // sanity check + assert(node.name() == "diffuse"); + + // parameter storage + colorReflectanceParameter albedo; + + // check child nodes + for(XMLNode child=node.firstChild(); child.isValid(); child++) + { + std::string name = child.name(); + if(name == "albedo") albedo = importColorReflectanceParameter(child, texture_cache, rootDir); + else errorMessage("Unknown parameter in diffuse-node (%s).", name.c_str()); + } + + // Done. + return std::shared_ptr<shader_base>(new diffuseReflectanceShader(albedo)); +} + +////////////////////////////////////////////////////////////// +static std::shared_ptr<shader_base> importPhong(const XMLNode& node, nodeCache<shader_base>& shader_cache, nodeCache<texture_base>& texture_cache, const std::string& rootDir) +{ + // sanity check + assert(node.name() == "phong"); + + // parameter storage + colorReflectanceParameter albedo; + scalarReflectanceParameter sharpness; + + // check child nodes + for(XMLNode child=node.firstChild(); child.isValid(); child++) + { + std::string name = child.name(); + if(name == "albedo") albedo = importColorReflectanceParameter(child, texture_cache, rootDir); + else if(name == "sharpness") sharpness = importScalarReflectanceParameter(child, texture_cache, rootDir); + else errorMessage("Unknown parameter in phong-node (%s).", name.c_str()); + } + + // Done. + return std::shared_ptr<shader_base>(new phongReflectanceShader(albedo, sharpness)); +} + +////////////////////////////////////////////////////////////// +static std::shared_ptr<shader_base> importCompoundMaterial(const XMLNode& node, nodeCache<shader_base>& shader_cache, nodeCache<texture_base>& texture_cache, const std::string& rootDir) +{ + // sanity check + assert(node.isValid() && node.name() == "material"); + + // storage for child material nodes + std::vector<std::shared_ptr<const shader_base>> shader_list; + + // for each child + for(XMLNode child = node.firstChild(); child.isValid(); child++) + { + // try to import material + std::shared_ptr<shader_base> shader = importMaterial(child, shader_cache, texture_cache, rootDir); + + // add to list if successful. + if(shader) shader_list.push_back(shader); + else errorMessage("Unknown material-node (%s).", child.name().c_str()); + } + + // Done. + return std::shared_ptr<shader_base>(new compoundShader(shader_list)); +} + +////////////////////////////////////////////////////////////// +std::shared_ptr<shader_base> importNormalMap(const XMLNode& node, nodeCache<shader_base>& shader_cache, nodeCache<texture_base>& texture_cache, const std::string& rootDir) +{ + // sanity check + assert(getString(node, "type") == "normalMap"); + + // parameter storage + std::shared_ptr<const shader_base> shader; + std::shared_ptr<const texture_base> map; + + // process child nodes + for(XMLNode child=node.firstChild(); child.isValid(); child++) + { + // process specific nodes + if(child.name() == "texture") map = importTexture(child, texture_cache, rootDir); + + // process general shader nodes + else if(!shader) shader = importMaterial(child, shader_cache, texture_cache, rootDir); + + else if(!shader) errorMessage("Unknown node in normalMap (%s).", child.name().c_str()); + } + + // check if shader & texture was specified + if(!shader) errorMessage("NormalMap requires a shader."); + if(!map) errorMessage("NormalMap requires a texture."); + + // Done. + return std::shared_ptr<shader_base>(new normalMap(map, shader)); +} + +////////////////////////////////////////////////////////////// +std::shared_ptr<shader_base> importBumpMap(const XMLNode& node, nodeCache<shader_base>& shader_cache, nodeCache<texture_base>& texture_cache, const std::string& rootDir) +{ + // sanity check + assert(getString(node, "type") == "bumpMap"); + + // obtain parameters + float scale = getFloat(node, "scale", 1.0f); + unsigned int channel = getInteger(node, "channel", 0); + + // parameter storage + std::shared_ptr<const shader_base> shader; + std::shared_ptr<const texture_base> map; + + // process child nodes + for(XMLNode child=node.firstChild(); child.isValid(); child++) + { + // process specific nodes + if(child.name() == "texture") map = importTexture(child, texture_cache, rootDir); + + // process general shader nodes + else if(!shader) shader = importMaterial(child, shader_cache, texture_cache, rootDir); + + else if(!shader) errorMessage("Unknown node in bumpMap (%s).", child.name().c_str()); + } + + // check if shader & texture was specified + if(!shader) errorMessage("BumpMap requires a shader."); + if(!map) errorMessage("BumpMap requires a texture."); + + // Done. + return std::shared_ptr<shader_base>(new bumpMap(map, scale, channel, shader)); +} + +////////////////////////////////////////////////////////////// +std::shared_ptr<shader_base> importShadingFrameTransformation(const XMLNode& node, nodeCache<shader_base>& shader_cache, nodeCache<texture_base>& texture_cache, const std::string& rootDir) +{ + // sanity check + assert(node.name() == "shadingFrameTransformation"); + + // get type + std::string type = getString(node, "type", "none specified"); + + // specialize based on type + std::shared_ptr<shader_base> sft; + + if(type == "normalMap") sft = importNormalMap(node, shader_cache, texture_cache, rootDir); + else if(type == "bumpMap") sft = importBumpMap(node, shader_cache, texture_cache, rootDir); + else errorMessage("Unknown shadingFrameTransformation type (%s).", type.c_str()); + + // Done. + return sft; +} + +////////////////////////////////////////////////////////////// +std::shared_ptr<shader_base> importMaterial(const XMLNode& node, nodeCache<shader_base>& shader_cache, nodeCache<texture_base>& texture_cache, const std::string& rootDir) +{ + std::string name = node.name(); + + // check material type + if(name != "material" && + name != "shadingFrameTransformation" && + name != "diffuse" && + name != "phong") return std::shared_ptr<shader_base>(nullptr); + + // check if reference + std::string ref = getString(node, "ref"); + std::shared_ptr<shader_base> shader = shader_cache.get(ref); + if(shader) return shader; + else if(ref != "") errorMessage("Unknown %s name (%s).", name.c_str(), ref.c_str()); + + // get id + std::string id = getString(node, "id"); + if(shader_cache.get(id)) + errorMessage("%s-id is not unique (%s).", name.c_str(), id.c_str()); + + // process primitives based on type + if(name == "material") shader = importCompoundMaterial(node, shader_cache, texture_cache, rootDir); + else if(name == "shadingFrameTransformation") shader = importShadingFrameTransformation(node, shader_cache, texture_cache, rootDir); + else if(name == "diffuse") shader = importDiffuse(node, shader_cache, texture_cache, rootDir); + else if(name == "phong") shader = importPhong(node, shader_cache, texture_cache, rootDir); + else errorMessage("Unknown material-node (%s).", name.c_str()); + + // update cache + if(id != "") shader_cache.add(id, shader); + + // Done. + return shader; +} + |