Browse Source

- Work on the new material

WONT COMPILE
Panagiotis Christopoulos Charitos 14 years ago
parent
commit
354ceeba92

+ 42 - 39
.cproject

@@ -24,16 +24,18 @@
 <tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.733325444" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug">
 <option id="gnu.cpp.compiler.exe.debug.option.optimization.level.678362421" name="Optimization Level" superClass="gnu.cpp.compiler.exe.debug.option.optimization.level" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
 <option id="gnu.cpp.compiler.exe.debug.option.debugging.level.527125870" name="Debug Level" superClass="gnu.cpp.compiler.exe.debug.option.debugging.level" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
-<option id="gnu.cpp.compiler.option.include.paths.2128411428" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
+<option id="gnu.cpp.compiler.option.include.paths.2128411428" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
 <listOptionValue builtIn="false" value="/usr/include"/>
+<listOptionValue builtIn="false" value="&quot;${workspace_loc:/anki/anki}&quot;"/>
 </option>
 <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1705857210" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
 </tool>
 <tool id="cdt.managedbuild.tool.gnu.c.compiler.exe.debug.509716139" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.debug">
 <option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.exe.debug.option.optimization.level.857210792" name="Optimization Level" superClass="gnu.c.compiler.exe.debug.option.optimization.level" valueType="enumerated"/>
 <option id="gnu.c.compiler.exe.debug.option.debugging.level.236164295" name="Debug Level" superClass="gnu.c.compiler.exe.debug.option.debugging.level" value="gnu.c.debugging.level.max" valueType="enumerated"/>
-<option id="gnu.c.compiler.option.include.paths.2141416219" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
+<option id="gnu.c.compiler.option.include.paths.2141416219" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
 <listOptionValue builtIn="false" value="/usr/include"/>
+<listOptionValue builtIn="false" value="&quot;${workspace_loc:/anki/anki}&quot;"/>
 </option>
 <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1888715461" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
 </tool>
@@ -45,8 +47,9 @@
 </inputType>
 </tool>
 <tool id="cdt.managedbuild.tool.gnu.assembler.exe.debug.1152709085" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.debug">
-<option id="gnu.both.asm.option.include.paths.1360594794" superClass="gnu.both.asm.option.include.paths" valueType="includePath">
+<option id="gnu.both.asm.option.include.paths.1360594794" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath">
 <listOptionValue builtIn="false" value="/usr/include"/>
+<listOptionValue builtIn="false" value="&quot;${workspace_loc:/anki/anki}&quot;"/>
 </option>
 <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1588784404" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
 </tool>
@@ -55,8 +58,9 @@
 </configuration>
 </storageModule>
 			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
-		<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
-<storageModule moduleId="scannerConfiguration">
+			<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
+			<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+		<storageModule moduleId="scannerConfiguration">
 <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>
 <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
 <buildOutputProvider>
@@ -305,7 +309,6 @@
 </profile>
 </scannerConfigBuildInfo>
 </storageModule>
-<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
 </cconfiguration>
 		<cconfiguration id="cdt.managedbuild.config.gnu.exe.release.571635259">
 			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.exe.release.571635259" moduleId="org.eclipse.cdt.core.settings" name="Release">
@@ -319,39 +322,40 @@
 </extensions>
 </storageModule>
 			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
-<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.release.571635259" name="Release" parent="cdt.managedbuild.config.gnu.exe.release">
-<folderInfo id="cdt.managedbuild.config.gnu.exe.release.571635259." name="/" resourcePath="">
-<toolChain id="cdt.managedbuild.toolchain.gnu.exe.release.1798558317" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.release">
-<targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.release.1852283584" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.release"/>
-<builder buildPath="${workspace_loc:/anki/Release}" id="cdt.managedbuild.target.gnu.builder.exe.release.154092247" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.exe.release"/>
-<tool id="cdt.managedbuild.tool.gnu.archiver.base.1469196148" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
-<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.1634217479" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release">
-<option id="gnu.cpp.compiler.exe.release.option.optimization.level.467488783" name="Optimization Level" superClass="gnu.cpp.compiler.exe.release.option.optimization.level" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/>
-<option id="gnu.cpp.compiler.exe.release.option.debugging.level.1206763877" name="Debug Level" superClass="gnu.cpp.compiler.exe.release.option.debugging.level" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/>
-<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1897753799" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
-</tool>
-<tool id="cdt.managedbuild.tool.gnu.c.compiler.exe.release.1453949923" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.release">
-<option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.exe.release.option.optimization.level.204107120" name="Optimization Level" superClass="gnu.c.compiler.exe.release.option.optimization.level" valueType="enumerated"/>
-<option id="gnu.c.compiler.exe.release.option.debugging.level.1402099681" name="Debug Level" superClass="gnu.c.compiler.exe.release.option.debugging.level" value="gnu.c.debugging.level.none" valueType="enumerated"/>
-<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.813305505" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
-</tool>
-<tool id="cdt.managedbuild.tool.gnu.c.linker.exe.release.1557937760" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.release"/>
-<tool id="cdt.managedbuild.tool.gnu.cpp.linker.exe.release.1899812877" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.release">
-<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.443040260" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
-<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
-<additionalInput kind="additionalinput" paths="$(LIBS)"/>
-</inputType>
-</tool>
-<tool id="cdt.managedbuild.tool.gnu.assembler.exe.release.1828291711" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.release">
-<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1528209394" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
-</tool>
-</toolChain>
-</folderInfo>
-</configuration>
-</storageModule>
+				<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.release.571635259" name="Release" parent="cdt.managedbuild.config.gnu.exe.release">
+					<folderInfo id="cdt.managedbuild.config.gnu.exe.release.571635259." name="/" resourcePath="">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.exe.release.1798558317" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.release">
+							<targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.release.1852283584" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.release"/>
+							<builder buildPath="${workspace_loc:/anki/Release}" id="cdt.managedbuild.target.gnu.builder.exe.release.154092247" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.exe.release"/>
+							<tool id="cdt.managedbuild.tool.gnu.archiver.base.1469196148" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.1634217479" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release">
+								<option id="gnu.cpp.compiler.exe.release.option.optimization.level.467488783" name="Optimization Level" superClass="gnu.cpp.compiler.exe.release.option.optimization.level" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/>
+								<option id="gnu.cpp.compiler.exe.release.option.debugging.level.1206763877" name="Debug Level" superClass="gnu.cpp.compiler.exe.release.option.debugging.level" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/>
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1897753799" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.exe.release.1453949923" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.release">
+								<option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.exe.release.option.optimization.level.204107120" name="Optimization Level" superClass="gnu.c.compiler.exe.release.option.optimization.level" valueType="enumerated"/>
+								<option id="gnu.c.compiler.exe.release.option.debugging.level.1402099681" name="Debug Level" superClass="gnu.c.compiler.exe.release.option.debugging.level" value="gnu.c.debugging.level.none" valueType="enumerated"/>
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.813305505" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.exe.release.1557937760" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.release"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.exe.release.1899812877" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.release">
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.443040260" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.exe.release.1828291711" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.release">
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1528209394" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+				</configuration>
+			</storageModule>
 			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
-		<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
-<storageModule moduleId="scannerConfiguration">
+			<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
+			<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+		<storageModule moduleId="scannerConfiguration">
 <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>
 <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
 <buildOutputProvider>
@@ -600,7 +604,6 @@
 </profile>
 </scannerConfigBuildInfo>
 </storageModule>
-<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
 </cconfiguration>
 	</storageModule>
 	<storageModule moduleId="cdtBuildSystem" version="4.0.0">

+ 1 - 1
CMakeLists.txt

@@ -45,7 +45,7 @@ ENDIF()
 #
 # Defines & flags
 #
-ADD_DEFINITIONS("-DANKI_MATH_INTEL_SIMD -DGLEW_MX -pedantic-errors -pedantic -ansi -Wall -Winline -W -Wwrite-strings -Wno-unused -Wno-long-long -msse4")
+ADD_DEFINITIONS("-DANKI_MATH_INTEL_SIMD -DGLEW_MX -pedantic-errors -pedantic -ansi -Wall -Winline -W -Wwrite-strings -Wno-unused -Wfatal-errors -Werror -Wno-long-long -msse4")
 
 # Add a few compiler specific stuff 
 IF(${CMAKE_CXX_COMPILER} MATCHES ".*clang\\+\\+$")	

+ 142 - 67
anki/resource/Material.cpp

@@ -10,6 +10,8 @@
 #include <boost/property_tree/xml_parser.hpp>
 #include <boost/assign/list_of.hpp>
 #include <boost/functional/hash.hpp>
+#include <boost/tokenizer.hpp>
+#include <boost/lexical_cast.hpp>
 #include <algorithm>
 
 
@@ -74,23 +76,47 @@ void Material::parseMaterialTag(const boost::property_tree::ptree& pt)
 	using namespace boost::property_tree;
 
 	//
-	// castsShadow
+	// renderingStage
 	//
-	boost::optional<bool> shadow =
-		PropertyTree::getBoolOptional(pt, "castsShadow");
-	if(shadow)
+	renderingStage = pt.get<int>("renderingStage");
+
+	//
+	// passes
+	//
+	boost::optional<std::string> pass =
+		pt.get_optional<std::string>("passes");
+
+	if(pass)
+	{
+		passes = splitString(pass.get().c_str());
+	}
+	else
+	{
+		passes.push_back("DUMMY");
+	}
+
+	//
+	// levelsOfDetail
+	//
+	boost::optional<int> lod = pt.get_optional<int>("levelsOfDetail");
+
+	if(lod)
+	{
+		levelsOfDetail = lod.get();
+	}
+	else
 	{
-		castsShadowFlag = shadow.get();
+		levelsOfDetail = 1;
 	}
 
 	//
-	// renderInBlendingStage
+	// shadow
 	//
-	boost::optional<bool> bs =
-		PropertyTree::getBoolOptional(pt, "renderInBlendingStage");
-	if(bs)
+	boost::optional<int> sw = pt.get_optional<int>("shadow");
+
+	if(sw)
 	{
-		renderInBlendingStageFlag = bs.get();
+		shadow = sw.get();
 	}
 
 	//
@@ -136,8 +162,8 @@ void Material::parseMaterialTag(const boost::property_tree::ptree& pt)
 	//
 	// depthTesting
 	//
-	boost::optional<bool> dp =
-		PropertyTree::getBoolOptional(pt, "depthTesting");
+	boost::optional<int> dp = pt.get_optional<int>("depthTesting");
+
 	if(dp)
 	{
 		depthTesting = dp.get();
@@ -146,8 +172,8 @@ void Material::parseMaterialTag(const boost::property_tree::ptree& pt)
 	//
 	// wireframe
 	//
-	boost::optional<bool> wf =
-		PropertyTree::getBoolOptional(pt, "wireframe");
+	boost::optional<int> wf = pt.get_optional<int>("wireframe");
+
 	if(wf)
 	{
 		wireframe = wf.get();
@@ -158,14 +184,30 @@ void Material::parseMaterialTag(const boost::property_tree::ptree& pt)
 	//
 	MaterialShaderProgramCreator mspc(pt.get_child("shaderProgram"));
 
-	for(uint i = 0; i < PASS_TYPES_NUM; i++)
+	for(uint level = 0; level < levelsOfDetail; ++level)
 	{
-		std::string src = std::string("#define ") + passNames[i] + "\n" +
-			mspc.getShaderProgramSource();
+		for(uint pid = 0; pid < passes.size(); ++pid)
+		{
+			std::stringstream src;
 
-		std::string filename = createShaderProgSourceToCache(src);
+			src << "#define LEVEL_" << level << std::endl;
+			src << "#define PASS_" << passes[pid] << std::endl;
+			src << mspc.getShaderProgramSource() << std::endl;
 
-		sProgs[i].load(filename.c_str());
+			std::string filename =
+				createShaderProgSourceToCache(src.str().c_str());
+
+			ShaderProgramResourcePointer* pptr =
+				new ShaderProgramResourcePointer;
+
+			pptr->load(filename.c_str());
+
+			ShaderProgram* sprog = pptr->get();
+
+			sProgs.push_back(pptr);
+
+			eSProgs[PassLevelKey(pid, level)] = sprog;
+		}
 	}
 
 	populateVariables(pt.get_child("shaderProgram.inputs"));
@@ -225,92 +267,125 @@ void Material::populateVariables(const boost::property_tree::ptree& pt)
 	//
 	// Iterate shader program variables
 	//
-	MaterialVariable::ShaderPrograms sProgs_;
-	for(uint i = 0; i < PASS_TYPES_NUM; i++)
-	{
-		sProgs_[i] = sProgs[i].get();
-	}
-
 	std::map<std::string, GLenum>::const_iterator it = allVarNames.begin();
 	for(; it != allVarNames.end(); it++)
 	{
 		const char* svName = it->first.c_str();
 		GLenum dataType = it->second;
 
-		// Buildin?
-		if(MaterialBuildinVariable::isBuildin(svName))
-		{
-			MaterialBuildinVariable* v =
-				new MaterialBuildinVariable(svName, sProgs_);
-
-			mtlVars.push_back(v);
-			buildinsArr[v->getMatchingVariable()] = v;
-		}
-		// User defined
-		else
+		// Find the ptree that contains the value
+		const ptree* valuePt = NULL;
+		BOOST_FOREACH(const ptree::value_type& v, pt)
 		{
-			// Find the ptree that contains the value
-			const ptree* valuePt = NULL;
-			BOOST_FOREACH(const ptree::value_type& v, pt)
+			if(v.first != "input")
 			{
-				if(v.first != "input")
-				{
-					throw ANKI_EXCEPTION("Expecting <input> and not: " +
-						v.first);
-				}
-
-				if(v.second.get<std::string>("name") == svName)
-				{
-					valuePt = &v.second.get_child("value");
-					break;
-				}
+				throw ANKI_EXCEPTION("Expecting <input> and not: " +
+					v.first);
 			}
 
-			if(valuePt == NULL)
+			if(v.second.get<std::string>("name") == svName)
 			{
-				throw ANKI_EXCEPTION("Variable not buildin and not found: " +
-					svName);
+				valuePt = &v.second.get_child("value");
+				break;
 			}
+		}
+
+		MaterialVariable* v = NULL;
+
+		// Buildin?
+		if(!valuePt)
+		{
+			v = new MaterialVariable(svName, eSProgs);
+		}
+		// User defined
+		else
+		{
+			const std::string& value = valuePt->get<std::string>("value");
 
-			MaterialUserVariable* v = NULL;
 			// Get the value
 			switch(dataType)
 			{
 				// sampler2D
 				case GL_SAMPLER_2D:
-					v = new MaterialUserVariable(svName, sProgs_,
-						valuePt->get<std::string>("sampler2D").c_str());
+					v = new MaterialVariable(svName, eSProgs,
+						value);
 					break;
 				// float
 				case GL_FLOAT:
-					v = new MaterialUserVariable(svName, sProgs_,
-						PropertyTree::getFloat(*valuePt));
+					v = new MaterialVariable(svName, eSProgs,
+						boost::lexical_cast<float>(value));
 					break;
 				// vec2
 				case GL_FLOAT_VEC2:
-					v = new MaterialUserVariable(svName, sProgs_,
-						PropertyTree::getVec2(*valuePt));
+					v = new MaterialVariable(svName, eSProgs,
+						setMathType<Vec2, 2>(value.c_str()));
 					break;
 				// vec3
 				case GL_FLOAT_VEC3:
-					v = new MaterialUserVariable(svName, sProgs_,
-						PropertyTree::getVec3(*valuePt));
+					v = new MaterialVariable(svName, eSProgs,
+						setMathType<Vec3, 3>(value.c_str()));
 					break;
 				// vec4
 				case GL_FLOAT_VEC4:
-					v = new MaterialUserVariable(svName, sProgs_,
-						PropertyTree::getVec4(*valuePt));
+					v = new MaterialVariable(svName, eSProgs,
+						setMathType<Vec4, 4>(value.c_str()));
 					break;
 				// default is error
 				default:
 					ANKI_ASSERT(0);
 			}
-
-			mtlVars.push_back(v);
-			userMtlVars.push_back(v);
 		}
+
+		vars.push_back(v);
+		nameToVar[v->getName().c_str()] = v;
 	} // end for all sprog vars
 }
 
 
+//==============================================================================
+StringList Material::splitString(const char* str)
+{
+	StringList out;
+	std::string s = str;
+	boost::tokenizer<> tok(s);
+
+	for(boost::tokenizer<>::iterator it = tok.begin(); it != tok.end(); ++it)
+	{
+		out.push_back(*it);
+	}
+
+	return out;
+}
+
+
+//==============================================================================
+template<typename Type, size_t n>
+Type Material::setMathType(const char* str)
+{
+	Type out;
+	StringList sl = splitString(str);
+	ANKI_ASSERT(sl.size() == n);
+
+	for(uint i = 0; i < n; ++i)
+	{
+		out[i] = boost::lexical_cast<float>(sl[i]);
+	}
+
+	return out;
+}
+
+
+//==============================================================================
+const MaterialVariable& Material::findVariableByName(const char* name) const
+{
+	NameToVariableHashMap::const_iterator it = nameToVar.find(name);
+	if(it == nameToVar.end())
+	{
+		throw ANKI_EXCEPTION("Cannot get material variable "
+			"with name \"" + name + '\"');
+	}
+	return *(it->second);
+}
+
+
 } // end namespace

+ 38 - 40
anki/resource/Material.h

@@ -1,10 +1,10 @@
 #ifndef ANKI_RESOURCE_MATERIAL_H
 #define ANKI_RESOURCE_MATERIAL_H
 
-#include "anki/resource/MaterialUserVariable.h"
-#include "anki/resource/MaterialBuildinVariable.h"
 #include "anki/resource/MaterialCommon.h"
 #include "anki/resource/MaterialProperties.h"
+#include "anki/resource/MaterialVariable.h"
+#include "anki/resource/Resource.h"
 #include "anki/util/ConstCharPtrHashMap.h"
 #include <GL/glew.h>
 #include <boost/ptr_container/ptr_vector.hpp>
@@ -40,16 +40,16 @@ class ShaderProgram;
 ///
 /// 	[<levelsOfDetail>0 to N</levelsOfDetail>]
 ///
-/// 	[<shadow>true | false</shadow>]
+/// 	[<shadow>0 | 1</shadow>]
 ///
 /// 	[<blendFunctions> (2)
 /// 		<sFactor>GL_SOMETHING</sFactor>
 /// 		<dFactor>GL_SOMETHING</dFactor>
 /// 	</blendFunctions>]
 ///
-/// 	[<depthTesting>true | false</depthTesting>] (2)
+/// 	[<depthTesting>0 | 1</depthTesting>] (2)
 ///
-/// 	[<wireframe>true | false</wireframe>] (2)
+/// 	[<wireframe>0 | 1</wireframe>] (2)
 ///
 /// 	<shaderProgram>
 /// 		<shader> (5)
@@ -122,47 +122,37 @@ class Material: public MaterialProperties
 			return *this;
 		}
 
-		const ShaderProgram& getShaderProgram(uint pass, uint level) const
+		const ShaderProgram& getShaderProgram(const PassLevelKey& key) const
 		{
-			return *eSProgs[pass][level];
+			return *eSProgs.at(key);
 		}
 
 		// Variable accessors
-		boost::iterator_range<VarsContainer::const_iterator> getVariables()
-			const
+		const VarsContainer& getVariables() const
 		{
-			return boost::iterator_range<VarsContainer::const_iterator>(
-				mtlVars.begin(), mtlVars.end());
+			return vars;
 		}
-
-		boost::iterator_range<std::vector<MaterialUserVariable*>::const_iterator>
-			getUserVariables() const
-		{
-			return boost::iterator_range<std::vector<MaterialUserVariable*>::
-				const_iterator>(userMtlVars.begin(), userMtlVars.end());
-		}
-
-		const MaterialBuildinVariable& getBuildinVariable(
-			MaterialBuildinVariable::MatchingVariable e) const;
 		/// @}
 
-		/// Load a material file
-		void load(const char* filename);
+		/// Get by name
+		const MaterialVariable& findVariableByName(const char* name) const;
 
-		/// Check if a buildin variable exists in a pass type
-		bool buildinVariableExits(MaterialBuildinVariable::MatchingVariable e,
-			PassType p) const
+		bool variableExists(const char* name) const
 		{
-			return buildinsArr[e] != NULL && buildinsArr[e]->inPass(p);
+			return nameToVar.find(name) != nameToVar.end();
 		}
 
-		/// Check if a buildin variable exists in a any pass type
-		bool buildinVariableExits(
-			MaterialBuildinVariable::MatchingVariable e) const
+		/// Check if a variable exists in the shader program of the @a key
+		bool variableExistsAndInKey(const char* name,
+			const PassLevelKey& key) const
 		{
-			return buildinsArr[e] != NULL;
+			NameToVariableHashMap::const_iterator it = nameToVar.find(name);
+			return it != nameToVar.end() && it->second->inPass(key);
 		}
 
+		/// Load a material file
+		void load(const char* filename);
+
 		/// For sorting
 		bool operator<(const Material& b) const
 		{
@@ -176,11 +166,9 @@ class Material: public MaterialProperties
 		
 		/// Type for garbage collection
 		typedef boost::ptr_vector<ShaderProgramResourcePointer> ShaderPrograms;
-		
-		/// Type for easy accessing the shader programs. Its a 2D array with 
-		/// the first dimention the pass ID and the second the level of detail
-		typedef std::vector<std::vector<ShaderProgram*> > EasyShaderPrograms;
-		
+
+		typedef ConstCharPtrHashMap<MaterialVariable*>::Type
+			NameToVariableHashMap;
 
 		//======================================================================
 		// Members                                                             =
@@ -191,16 +179,18 @@ class Material: public MaterialProperties
 
 		std::string fname; ///< filename
 
-		/// All the material variables. Both buildins and user
-		VarsContainer mtlVars;
+		/// All the material variables
+		VarsContainer vars;
+
+		NameToVariableHashMap nameToVar;
 
 		/// The most important aspect of materials. These are all the shader 
 		/// programs per level and per pass. Their number are NP * NL where
 		/// NP is the number of passes and NL the number of levels of detail
 		ShaderPrograms sProgs;
 		
-		/// Easy access the shader programs
-		EasyShaderPrograms eSProgs;
+		/// For searching
+		PassLevelToShaderProgramHashMap eSProgs;
 
 		//======================================================================
 		// Methods                                                             =
@@ -214,6 +204,14 @@ class Material: public MaterialProperties
 
 		/// XXX
 		void populateVariables(const boost::property_tree::ptree& pt);
+
+		/// Get a string and split it into words
+		static StringList splitString(const char* str);
+
+		/// Parses something like this: "0.0 0.01 -1.2" and returns a valid
+		/// math type
+		template<typename Type, size_t n>
+		static Type setMathType(const char* str);
 };
 
 

+ 0 - 127
anki/resource/MaterialBuildinVariable.cpp

@@ -1,127 +0,0 @@
-#include "anki/resource/MaterialBuildinVariable.h"
-#include "anki/util/Exception.h"
-#include "anki/util/Assert.h"
-#include <cstring>
-#include <boost/lexical_cast.hpp>
-#include <boost/assign/list_of.hpp>
-
-
-namespace anki {
-
-
-//==============================================================================
-// Statics                                                                     =
-//==============================================================================
-
-MaterialBuildinVariable::StrToMatchingVariable
-	MaterialBuildinVariable::strToMatchingVariable = boost::assign::map_list_of
-	("position", MV_POSITION)
-	("tangent", MV_TANGENT)
-	("normal", MV_NORMAL)
-	("texCoords", MV_TEX_COORDS)
-	("modelMat", MV_MODEL_MAT)
-	("viewMat", MV_VIEW_MAT)
-	("projectionMat", MV_PROJECTION_MAT)
-	("modelViewMat", MV_MODELVIEW_MAT)
-	("viewProjectionMat", MV_VIEWPROJECTION_MAT)
-	("normalMat", MV_NORMAL_MAT)
-	("modelViewProjectionMat", MV_MODELVIEWPROJECTION_MAT)
-	("msNormalFai", MV_MS_NORMAL_FAI)
-	("msDiffuseFai", MV_MS_DIFFUSE_FAI)
-	("msSpecularFai", MV_MS_SPECULAR_FAI)
-	("msDepthFai", MV_MS_DEPTH_FAI)
-	("isFai", MV_IS_FAI)
-	("ppsPrePassFai", MV_PPS_PRE_PASS_FAI)
-	("ppsPostPassFai", MV_PPS_POST_PASS_FAI)
-	("rendererSize", MV_RENDERER_SIZE)
-	("sceneAmbientColor", MV_SCENE_AMBIENT_COLOR)
-	("blurring", MV_BLURRING);
-
-
-MaterialBuildinVariable::MatchingVariableToGlType
-	MaterialBuildinVariable::matchingVariableToGlType =
-	boost::assign::map_list_of
-	(MV_POSITION, GL_FLOAT_VEC3)
-	(MV_TANGENT, GL_FLOAT_VEC4)
-	(MV_NORMAL, GL_FLOAT_VEC3)
-	(MV_TEX_COORDS, GL_FLOAT_VEC2)
-	(MV_MODEL_MAT, GL_FLOAT_MAT4)
-	(MV_VIEW_MAT, GL_FLOAT_MAT4)
-	(MV_PROJECTION_MAT, GL_FLOAT_MAT4)
-	(MV_MODELVIEW_MAT, GL_FLOAT_MAT4)
-	(MV_VIEWPROJECTION_MAT, GL_FLOAT_MAT4)
-	(MV_NORMAL_MAT, GL_FLOAT_MAT3)
-	(MV_MODELVIEWPROJECTION_MAT, GL_FLOAT_MAT4)
-	(MV_MS_NORMAL_FAI, GL_SAMPLER_2D)
-	(MV_MS_DIFFUSE_FAI, GL_SAMPLER_2D)
-	(MV_MS_SPECULAR_FAI, GL_SAMPLER_2D)
-	(MV_MS_DEPTH_FAI, GL_SAMPLER_2D)
-	(MV_IS_FAI, GL_SAMPLER_2D)
-	(MV_PPS_PRE_PASS_FAI, GL_SAMPLER_2D)
-	(MV_PPS_POST_PASS_FAI, GL_SAMPLER_2D)
-	(MV_RENDERER_SIZE, GL_FLOAT_VEC2)
-	(MV_SCENE_AMBIENT_COLOR, GL_FLOAT_VEC3)
-	(MV_BLURRING, GL_FLOAT);
-
-
-//==============================================================================
-// Constructor                                                                 =
-//==============================================================================
-MaterialBuildinVariable::MaterialBuildinVariable(
-	const char* shaderProgVarName,
-	const ShaderPrograms& shaderProgsArr)
-:	MaterialVariable(T_BUILDIN, shaderProgVarName, shaderProgsArr),
- 	bEnum(MV_NUM)
-{
-	GLenum dataType;
-	// Sanity checks
-	if(!isBuildin(shaderProgVarName, &bEnum, &dataType))
-	{
-		throw ANKI_EXCEPTION("The variable is not buildin: " +
-			shaderProgVarName);
-	}
-
-	if(dataType != getGlDataType())
-	{
-		throw ANKI_EXCEPTION("The buildin variable \"" + shaderProgVarName +
-			"\" should be of type: " +
-			boost::lexical_cast<std::string>(dataType));
-	}
-}
-
-
-//==============================================================================
-// isBuildin                                                                   =
-//==============================================================================
-bool MaterialBuildinVariable::isBuildin(const char* name,
-	MatchingVariable* var, GLenum* dataType)
-{
-	StrToMatchingVariable::const_iterator it = strToMatchingVariable.find(name);
-
-	if(it == strToMatchingVariable.end())
-	{
-		return false;
-	}
-
-	MatchingVariable mv = it->second;
-
-	if(var)
-	{
-		*var = mv;
-	}
-
-	if(dataType)
-	{
-		MatchingVariableToGlType::const_iterator it2 =
-			matchingVariableToGlType.find(mv);
-
-		ANKI_ASSERT(it2 != matchingVariableToGlType.end());
-
-		*dataType = it2->second;
-	}
-
-	return true;
-}
-
-
-} // end namespace

+ 0 - 100
anki/resource/MaterialBuildinVariable.h

@@ -1,100 +0,0 @@
-#ifndef ANKI_RESOURCE_MATERIAL_BUILDIN_VARIABLE_H
-#define ANKI_RESOURCE_MATERIAL_BUILDIN_VARIABLE_H
-
-#include "anki/resource/MaterialVariable.h"
-#include "anki/util/ConstCharPtrHashMap.h"
-#include "anki/resource/ShaderProgramUniformVariable.h"
-#include <boost/array.hpp>
-
-
-namespace anki {
-
-
-/// XXX
-class MaterialBuildinVariable: public MaterialVariable
-{
-	public:
-		/// Standard attribute variables that are acceptable inside the
-		/// ShaderProgram
-		enum MatchingVariable
-		{
-			// Attributes
-			MV_POSITION,
-			MV_TANGENT,
-			MV_NORMAL,
-			MV_TEX_COORDS,
-			// Uniforms
-			// Matrices
-			MV_MODEL_MAT,
-			MV_VIEW_MAT,
-			MV_PROJECTION_MAT,
-			MV_MODELVIEW_MAT,
-			MV_VIEWPROJECTION_MAT,
-			MV_NORMAL_MAT,
-			MV_MODELVIEWPROJECTION_MAT,
-			// FAIs (for materials in blending stage)
-			MV_MS_NORMAL_FAI,
-			MV_MS_DIFFUSE_FAI,
-			MV_MS_SPECULAR_FAI,
-			MV_MS_DEPTH_FAI,
-			MV_IS_FAI,
-			MV_PPS_PRE_PASS_FAI,
-			MV_PPS_POST_PASS_FAI,
-			// Other
-			MV_RENDERER_SIZE,
-			MV_SCENE_AMBIENT_COLOR,
-			MV_BLURRING,
-			// num
-			MV_NUM ///< The number of all buildin variables
-		};
-
-		MaterialBuildinVariable(
-			const char* shaderProgVarName,
-			const ShaderPrograms& shaderProgsArr);
-
-		MatchingVariable getMatchingVariable() const
-		{
-			return bEnum;
-		}
-
-		/// Uses static cast to get the uniform. It will fail if the variable
-		/// is attribute
-		const ShaderProgramUniformVariable&
-			getShaderProgramUniformVariable(PassType p) const;
-
-		static bool isBuildin(const char* name, MatchingVariable* var = NULL,
-			GLenum* dataType = NULL);
-
-	private:
-		/// From string to MatchingVariable
-		typedef ConstCharPtrHashMap<MatchingVariable>::Type
-			StrToMatchingVariable;
-
-		/// From MatchingVariable to GL type (GLenum)
-		typedef boost::unordered_map<MatchingVariable, GLenum>
-			MatchingVariableToGlType;
-
-		/// Given a name of a variable find its MaterialBuildinVariable enum
-		static StrToMatchingVariable strToMatchingVariable;
-
-		/// Given a MaterialBuildinVariable enum it gives the GL type
-		static MatchingVariableToGlType matchingVariableToGlType;
-
-		MatchingVariable bEnum;
-};
-
-
-inline const ShaderProgramUniformVariable&
-	MaterialBuildinVariable::getShaderProgramUniformVariable(PassType p) const
-{
-	ANKI_ASSERT(getShaderProgramVariable(p).getType() ==
-		ShaderProgramVariable::T_UNIFORM);
-	return static_cast<const ShaderProgramUniformVariable&>(
-		getShaderProgramVariable(p));
-}
-
-
-} // end namespace
-
-
-#endif

+ 0 - 13
anki/resource/MaterialCommon.cpp

@@ -1,13 +0,0 @@
-#include "anki/resource/MaterialCommon.h"
-
-
-namespace anki {
-
-
-boost::array<const char*, PASS_TYPES_NUM> passNames = {{
-	"COLOR_PASS",
-	"DEPTH_PASS"
-}};
-
-
-} // end namespace

+ 4 - 10
anki/resource/MaterialCommon.h

@@ -1,22 +1,16 @@
 #ifndef ANKI_RESOURCE_MATERIAL_COMMON_H
 #define ANKI_RESOURCE_MATERIAL_COMMON_H
 
+#include "anki/resource/PassLevelKey.h"
 #include <boost/array.hpp>
 
 
 namespace anki {
 
 
-/// The types of the rendering passes
-enum PassType
-{
-	COLOR_PASS,
-	DEPTH_PASS,
-	PASS_TYPES_NUM
-};
-
-
-extern boost::array<const char*, PASS_TYPES_NUM> passNames;
+/// Given a pair of pass and level it returns a pointer to a shader program
+typedef PassLevelHashMap<const class ShaderProgram*>::Type
+	PassLevelToShaderProgramHashMap;
 
 
 } // end namespace

+ 2 - 1
anki/resource/MaterialProperties.h

@@ -2,6 +2,7 @@
 #define ANKI_RESOURCE_MATERIAL_PROPERTIES_H
 
 #include "anki/util/StringList.h"
+#include "anki/util/StdTypes.h"
 #include <GL/glew.h>
 
 
@@ -57,7 +58,7 @@ struct MaterialProperties
 			return blendingDfactor;
 		}
 
-		bool getGetDepthTesting() const
+		bool getDepthTesting() const
 		{
 			return depthTesting;
 		}

+ 18 - 14
anki/resource/MaterialShaderProgramCreator.cpp

@@ -1,6 +1,9 @@
 #include "anki/resource/MaterialShaderProgramCreator.h"
+#include "anki/util/Assert.h"
+#include "anki/util/Exception.h"
 #include <boost/foreach.hpp>
 #include <boost/property_tree/ptree.hpp>
+#include <boost/lexical_cast.hpp>
 
 
 namespace anki {
@@ -36,7 +39,7 @@ void MaterialShaderProgramCreator::parseShaderProgramTag(
 		parseShaderTag(v.second);
 	}
 
-	srcLines.join("\n", source);
+	source = srcLines.join("\n");
 	//std::cout << source << std::endl;
 }
 
@@ -45,6 +48,8 @@ void MaterialShaderProgramCreator::parseShaderProgramTag(
 void MaterialShaderProgramCreator::parseShaderTag(
 	const boost::property_tree::ptree& pt)
 {
+	using namespace boost::property_tree;
+
 	//
 	// <type></type>
 	//
@@ -65,7 +70,9 @@ void MaterialShaderProgramCreator::parseShaderTag(
 				v.first);
 		}
 
-		includeLines.push_back("#pragma anki include \"" + fname + "\"");
+		const std::string& fname = v.second.data();
+		includeLines.push_back(std::string("#pragma anki include \"") +
+			fname + "\"");
 	}
 
 	//std::sort(includeLines.begin(), includeLines.end(), compareStrings);
@@ -132,12 +139,12 @@ void MaterialShaderProgramCreator::parseInputTag(
 	const std::string& name = pt.get<std::string>("name");
 	const std::string& type = pt.get<std::string>("type");
 
-	line = "uniform " + type " " + name + ";";
+	line = "uniform " + type + " " + name + ";";
 }
 
 
 //==============================================================================
-void MaterialShaderProgramCreator::parseOperatorTag(
+void MaterialShaderProgramCreator::parseOperationTag(
 	const boost::property_tree::ptree& pt)
 {
 	using namespace boost::property_tree;
@@ -148,8 +155,8 @@ void MaterialShaderProgramCreator::parseOperatorTag(
 	int id = pt.get<int>("id");
 	
 	// <returnType></returnType>
-	boost::optional<const string&> retTypeOpt = 
-		pt.get_optional<const string&>("returnType");
+	boost::optional<std::string> retTypeOpt =
+		pt.get_optional<std::string>("returnType");
 		
 	if(retTypeOpt)
 	{
@@ -163,11 +170,12 @@ void MaterialShaderProgramCreator::parseOperatorTag(
 	
 	// <arguments></arguments>
 	boost::optional<const ptree&> argsPt = pt.get_child_optional("arguments");
+	StringList argsList;
 	
 	if(argsPt)
 	{
 		// Write all arguments
-		ptree::const_iterator it = argsPt.get();
+		ptree::const_iterator it = argsPt.get().begin();
 		for(; it != argsPt.get().end(); ++it)
 		{
 			const ptree::value_type& v = *it;
@@ -180,14 +188,10 @@ void MaterialShaderProgramCreator::parseOperatorTag(
 			}
 
 			const std::string& argName = v.second.data();
-			line << argName;
-
-			// Add a comma
-			if(it != argsPt.get().end() - 1)
-			{
-				line << ", ";
-			}
+			argsList.push_back(argName);
 		}
+
+		line << argsList.join(", ");
 	}
 	
 	line << ");";

+ 0 - 82
anki/resource/MaterialUserVariable.cpp

@@ -1,82 +0,0 @@
-#include "anki/resource/MaterialUserVariable.h"
-#include "anki/resource/Texture.h"
-
-
-namespace anki {
-
-
-//==============================================================================
-// Constructors & destructor                                                   =
-//==============================================================================
-
-MaterialUserVariable::MaterialUserVariable(
-	const char* shaderProgVarName,
-	const ShaderPrograms& shaderProgsArr,
-	float val)
-:	MaterialVariable(T_USER, shaderProgVarName, shaderProgsArr)
-{
-	ANKI_ASSERT(getGlDataType() == GL_FLOAT);
-	ANKI_ASSERT(getShaderProgramVariableType() ==
-		ShaderProgramVariable::T_UNIFORM);
-	data = val;
-}
-
-
-MaterialUserVariable::MaterialUserVariable(
-	const char* shaderProgVarName,
-	const ShaderPrograms& shaderProgsArr,
-	const Vec2& val)
-:	MaterialVariable(T_USER, shaderProgVarName, shaderProgsArr)
-{
-	ANKI_ASSERT(getGlDataType() == GL_FLOAT_VEC2);
-	ANKI_ASSERT(getShaderProgramVariableType() ==
-		ShaderProgramVariable::T_UNIFORM);
-	data = val;
-}
-
-
-MaterialUserVariable::MaterialUserVariable(
-	const char* shaderProgVarName,
-	const ShaderPrograms& shaderProgsArr,
-	const Vec3& val)
-:	MaterialVariable(T_USER, shaderProgVarName, shaderProgsArr)
-{
-	ANKI_ASSERT(getGlDataType() == GL_FLOAT_VEC3);
-	ANKI_ASSERT(getShaderProgramVariableType() ==
-		ShaderProgramVariable::T_UNIFORM);
-	data = val;
-}
-
-
-MaterialUserVariable::MaterialUserVariable(
-	const char* shaderProgVarName,
-	const ShaderPrograms& shaderProgsArr,
-	const Vec4& val)
-:	MaterialVariable(T_USER, shaderProgVarName, shaderProgsArr)
-{
-	ANKI_ASSERT(getGlDataType() == GL_FLOAT_VEC4);
-	ANKI_ASSERT(getShaderProgramVariableType() ==
-		ShaderProgramVariable::T_UNIFORM);
-	data = val;
-}
-
-
-MaterialUserVariable::MaterialUserVariable(
-	const char* shaderProgVarName,
-	const ShaderPrograms& shaderProgsArr,
-	const char* texFilename)
-:	MaterialVariable(T_USER, shaderProgVarName, shaderProgsArr)
-{
-	ANKI_ASSERT(getGlDataType() == GL_SAMPLER_2D);
-	ANKI_ASSERT(getShaderProgramVariableType() ==
-		ShaderProgramVariable::T_UNIFORM);
-	data = TextureResourcePointer();
-	boost::get<TextureResourcePointer >(data).load(texFilename);
-}
-
-
-MaterialUserVariable::~MaterialUserVariable()
-{}
-
-
-} // end namespace

+ 0 - 86
anki/resource/MaterialUserVariable.h

@@ -1,86 +0,0 @@
-#ifndef ANKI_RESOURCE_MATERIAL_USER_VARIABLE_H
-#define ANKI_RESOURCE_MATERIAL_USER_VARIABLE_H
-
-#include "anki/resource/MaterialVariable.h"
-#include "anki/math/Math.h"
-#include "anki/resource/Resource.h"
-#include "anki/resource/ShaderProgramUniformVariable.h"
-#include <boost/variant.hpp>
-
-
-namespace anki {
-
-
-class Texture;
-
-
-/// XXX
-class MaterialUserVariable: public MaterialVariable
-{
-	public:
-		/// The data union
-		typedef boost::variant<float, Vec2, Vec3, Vec4, TextureResourcePointer>
-			DataVariant;
-
-		/// @name Constructors & destructor
-		/// @{
-		MaterialUserVariable(
-			const char* shaderProgVarName,
-			const ShaderPrograms& shaderProgsArr,
-			float val);
-
-		MaterialUserVariable(
-			const char* shaderProgVarName,
-			const ShaderPrograms& shaderProgsArr,
-			const Vec2& val);
-
-		MaterialUserVariable(
-			const char* shaderProgVarName,
-			const ShaderPrograms& shaderProgsArr,
-			const Vec3& val);
-
-		MaterialUserVariable(
-			const char* shaderProgVarName,
-			const ShaderPrograms& shaderProgsArr,
-			const Vec4& val);
-
-		MaterialUserVariable(
-			const char* shaderProgVarName,
-			const ShaderPrograms& shaderProgsArr,
-			const char* texFilename);
-
-		~MaterialUserVariable();
-		/// @}
-
-		/// @name Accessors
-		/// @{
-		const DataVariant& getDataVariant() const {return data;}
-
-		/// Get the value of the variant
-		/// @exception boost::exception when you try to get the incorrect data
-		/// type
-		template<typename Type>
-		const Type& getValue() const {return boost::get<Type>(data);}
-
-		/// Uses static cast to get the uniform
-		const ShaderProgramUniformVariable&
-			getShaderProgramUniformVariable(PassType p) const;
-		/// @}
-
-	private:
-		DataVariant data;
-};
-
-
-inline const ShaderProgramUniformVariable&
-	MaterialUserVariable::getShaderProgramUniformVariable(PassType p) const
-{
-	return static_cast<const ShaderProgramUniformVariable&>(
-		getShaderProgramVariable(p));
-}
-
-
-} // end namespace
-
-
-#endif

+ 41 - 14
anki/resource/MaterialVariable.cpp

@@ -9,31 +9,58 @@ namespace anki {
 
 
 //==============================================================================
-// Constructor                                                                 =
+MaterialVariable::MaterialVariable(
+	const char* shaderProgVarName,
+	const PassLevelToShaderProgramHashMap& sProgs)
+:	type(T_BUILDIN)
+{
+	init(shaderProgVarName, sProgs);
+}
+
+
 //==============================================================================
+template <>
 MaterialVariable::MaterialVariable(
-	Type type_,
 	const char* shaderProgVarName,
-	const ShaderPrograms& shaderProgsArr)
-:	type(type_),
- 	oneSProgVar(NULL)
+	const PassLevelToShaderProgramHashMap& sProgs,
+	const std::string& val)
+:	type(T_USER)
+{
+	init(shaderProgVarName, sProgs);
+	ANKI_ASSERT(getShaderProgramVariableType() ==
+		ShaderProgramVariable::T_UNIFORM);
+	data = TextureResourcePointer();
+	boost::get<TextureResourcePointer>(data).load(val.c_str());
+}
+
+
+//==============================================================================
+void MaterialVariable::init(const char* shaderProgVarName,
+	const PassLevelToShaderProgramHashMap& sProgs)
 {
-	// For all shader progs point to the variables
-	for(uint i = 0; i < shaderProgsArr.size(); i++)
+	oneSProgVar = NULL;
+
+	PassLevelToShaderProgramHashMap::const_iterator it = sProgs.begin();
+	for(; it != sProgs.end(); ++it)
 	{
-		if(shaderProgsArr[i]->variableExists(shaderProgVarName))
+		const ShaderProgram& sProg = *(it->second);
+		const PassLevelKey& key = it->first;
+
+		if(sProg.variableExists(shaderProgVarName))
 		{
-			sProgVars[i] = &shaderProgsArr[i]->getVariableByName(
-				shaderProgVarName);
+			const ShaderProgramVariable& sProgVar =
+				sProg.getVariableByName(shaderProgVarName);
+
+			sProgVars[key] = &sProgVar;
 
 			if(!oneSProgVar)
 			{
-				oneSProgVar = sProgVars[i];
+				oneSProgVar = &sProgVar;
 			}
 
 			// Sanity check: All the sprog vars need to have same GL data type
-			if(oneSProgVar->getGlDataType() != sProgVars[i]->getGlDataType() ||
-				oneSProgVar->getType() != sProgVars[i]->getType())
+			if(oneSProgVar->getGlDataType() != sProgVar.getGlDataType() ||
+				oneSProgVar->getType() != sProgVar.getType())
 			{
 				throw ANKI_EXCEPTION("Incompatible shader "
 					"program variables: " +
@@ -42,7 +69,7 @@ MaterialVariable::MaterialVariable(
 		}
 		else
 		{
-			sProgVars[i] = NULL;
+			sProgVars[key] = NULL;
 		}
 	}
 

+ 54 - 30
anki/resource/MaterialVariable.h

@@ -1,21 +1,22 @@
 #ifndef ANKI_RESOURCE_MATERIAL_VARIABLE_H
 #define ANKI_RESOURCE_MATERIAL_VARIABLE_H
 
-#include "anki/resource/MaterialCommon.h"
 #include "anki/resource/ShaderProgramVariable.h"
+#include "anki/resource/MaterialCommon.h"
+#include "anki/math/Math.h"
+#include "anki/resource/Resource.h"
+#include "anki/resource/Texture.h" // For one of the constructors
 #include "anki/util/Assert.h"
 #include <GL/glew.h>
 #include <string>
-#include <boost/array.hpp>
+#include <boost/variant.hpp>
 
 
 namespace anki {
 
 
-class ShaderProgram;
-
-
-/// XXX
+/// Holds the shader variables. Its a container for shader program variables
+/// that share the same name
 class MaterialVariable
 {
 	public:
@@ -26,28 +27,35 @@ class MaterialVariable
 			T_BUILDIN
 		};
 		
-		/// The data union
+		/// The data union (limited to a few types at the moment)
 		typedef boost::variant<float, Vec2, Vec3, Vec4, Mat3, 
 			Mat4, TextureResourcePointer> Variant;
 
-		/// Used for initialization in the constructor
-		typedef std::vector<std::vector<ShaderProgram*> >
-			ShaderPrograms;
+		/// Given a pair of pass and level it returns a pointer to a
+		/// shader program variable. The pointer may be null
+		typedef PassLevelHashMap<const ShaderProgramVariable*>::Type
+			PassLevelToShaderProgramVariableHashMap;
 
 		/// @name Constructors & destructor
 		/// @{
 		
-		/// Build-in
+		/// For build-ins
 		MaterialVariable(
 			const char* shaderProgVarName,
-			const ShaderPrograms& sProgs);
+			const PassLevelToShaderProgramHashMap& sProgs);
 			
-		/// User defined
-		<template Type>
+		/// For user defined
+		template<typename Type>
 		MaterialVariable(
 			const char* shaderProgVarName,
-			const ShaderPrograms& sProgs,
-			const Type& val);
+			const PassLevelToShaderProgramHashMap& sProgs,
+			const Type& val)
+		{
+			init(shaderProgVarName, sProgs);
+			ANKI_ASSERT(getShaderProgramVariableType() ==
+				ShaderProgramVariable::T_UNIFORM);
+			data = val;
+		}
 		/// @}
 			
 		/// @name Accessors
@@ -57,15 +65,26 @@ class MaterialVariable
 			return type;
 		}
 
+		const Variant& getVariant() const
+		{
+			return data;
+		}
+
 		/// XXX
 		const ShaderProgramVariable& getShaderProgramVariable(
-			PassType p) const;
+			const PassLevelKey& key) const
+		{
+			ANKI_ASSERT(inPass(key));
+			const ShaderProgramVariable* var =
+				sProgVars.at(key);
+			return *var;
+		}
 
-		/// Check if pass p needs this variable. Check if the shader program
-		/// of p contains this variable or not
-		bool inPass(uint p) const
+		/// Check if the shader program of the given pass and level needs
+		/// contains this variable or not
+		bool inPass(const PassLevelKey& key) const
 		{
-			return sProgVars[p] != NULL;
+			return sProgVars.find(key) != sProgVars.end();
 		}
 
 		/// Get the GL data type of all the shader program variables
@@ -75,9 +94,9 @@ class MaterialVariable
 		}
 
 		/// Get the name of all the shader program variables
-		const char* getName() const
+		const std::string& getName() const
 		{
-			return oneSProgVar->getName().c_str();
+			return oneSProgVar->getName();
 		}
 
 		/// Get the type of all the shader program variables
@@ -89,20 +108,25 @@ class MaterialVariable
 
 	private:
 		Type type;
-		ShaderProgramVariables sProgVars;
+		PassLevelToShaderProgramVariableHashMap sProgVars;
+		Variant data;
 
 		/// Keep one ShaderProgramVariable here for easy access of the common
 		/// variable stuff like name or GL data type etc
 		const ShaderProgramVariable* oneSProgVar;
+
+		/// Common constructor code
+		void init(const char* shaderProgVarName,
+			const PassLevelToShaderProgramHashMap& shaderProgsArr);
 };
 
 
-inline const ShaderProgramVariable& MaterialVariable::getShaderProgramVariable(
-	PassType p) const
-{
-	ANKI_ASSERT(inPass(p));
-	return *sProgVars[p];
-}
+/// Declaration for specialized (string)
+template<>
+MaterialVariable::MaterialVariable<std::string>(
+	const char* shaderProgVarName,
+	const PassLevelToShaderProgramHashMap& sProgs,
+	const std::string& val);
 
 
 } // end namespace

+ 9 - 10
anki/resource/Mesh.h

@@ -30,6 +30,8 @@ class Mesh
 			VBOS_NUM
 		};
 
+		typedef boost::array<Vbo, VBOS_NUM> VbosArray;
+
 		/// Default constructor
 		Mesh()
 		{}
@@ -61,7 +63,7 @@ class Mesh
 		}
 		/// @}
 
-		/// Implements @ref Resource::load
+		/// Load from a file
 		void load(const char* filename);
 
 		/// @name Ask for geometry properties
@@ -76,11 +78,15 @@ class Mesh
 			return vbos[VBO_VERT_WEIGHTS].isCreated();
 		}
 
-		bool hasNormalsAndTangents() const;
+		bool hasNormalsAndTangents() const
+		{
+			return vbos[VBO_VERT_NORMALS].isCreated() &&
+				vbos[VBO_VERT_TANGENTS].isCreated();
+		}
 		/// @}
 
 	private:
-		boost::array<Vbo, VBOS_NUM> vbos; ///< The vertex buffer objects
+		VbosArray vbos; ///< The vertex buffer objects
 		uint vertIdsNum; ///< The number of vertex IDs
 		Obb visibilityShape;
 		uint vertsNum;
@@ -90,13 +96,6 @@ class Mesh
 };
 
 
-inline bool Mesh::hasNormalsAndTangents() const
-{
-	return vbos[VBO_VERT_NORMALS].isCreated() &&
-		vbos[VBO_VERT_TANGENTS].isCreated();
-}
-
-
 } // end namespace
 
 

+ 75 - 13
anki/resource/ModelPatch.cpp

@@ -7,36 +7,98 @@ namespace anki {
 
 
 //==============================================================================
-// Constructors & Destructor                                                   =
-//==============================================================================
-
 ModelPatch::ModelPatch(const char* meshFName, const char* mtlFName)
 {
-	load(meshFName, mtlFName);
+	// Load
+	mesh.load(meshFName);
+	mtl.load(mtlFName);
+
+	// Create VAOs
+	VboArray vboArr;
+	for(uint i = 0; i < Mesh::VBOS_NUM; i++)
+	{
+		vboArr[i] = &mesh->getVbo((Mesh::Vbos)i);
+	}
+
+	createVaos(*mtl, vboArr, vaos, vaosHashMap);
 }
 
 
+//==============================================================================
 ModelPatch::~ModelPatch()
 {}
 
 
 //==============================================================================
-// load                                                                        =
-//==============================================================================
-void ModelPatch::load(const char* meshFName, const char* mtlFName)
+bool ModelPatch::supportsHwSkinning() const
 {
-	// Load
-	mesh.load(meshFName);
-	mtl.load(mtlFName);
+	return mesh->hasVertWeights();
 }
 
 
 //==============================================================================
-// supportsHwSkinning                                                          =
+Vao* ModelPatch::createVao(const Material& mtl,
+	const VboArray& vbos,
+	const PassLevelKey& key)
+{
+	Vao* vao = new Vao;
+
+	if(mtl.variableExistsAndInKey("position", key))
+	{
+		ANKI_ASSERT(vbos[Mesh::VBO_VERT_POSITIONS] != NULL);
+
+		vao->attachArrayBufferVbo(*vbos[Mesh::VBO_VERT_POSITIONS],
+			0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
+	}
+
+	if(mtl.variableExistsAndInKey("normal", key))
+	{
+		ANKI_ASSERT(vbos[Mesh::VBO_VERT_NORMALS] != NULL);
+
+		vao->attachArrayBufferVbo(*vbos[Mesh::VBO_VERT_NORMALS],
+			1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
+	}
+
+	if(mtl.variableExistsAndInKey("tangent", key))
+	{
+		ANKI_ASSERT(vbos[Mesh::VBO_VERT_TANGENTS] != NULL);
+
+		vao->attachArrayBufferVbo(*vbos[Mesh::VBO_VERT_TANGENTS],
+			2, 4, GL_FLOAT, GL_FALSE, 0, NULL);
+	}
+
+	if(mtl.variableExistsAndInKey("texCoords", key))
+	{
+		vao->attachArrayBufferVbo(*vbos[Mesh::VBO_TEX_COORDS],
+			3, 2, GL_FLOAT, GL_FALSE, 0, NULL);
+	}
+
+	vao->attachElementArrayBufferVbo(*vbos[Mesh::VBO_VERT_INDECES]);
+
+	return vao;
+}
+
+
 //==============================================================================
-bool ModelPatch::supportsHwSkinning() const
+void ModelPatch::createVaos(const Material& mtl,
+	const VboArray& vbos,
+	VaosContainer& vaos,
+	PassLevelToVaoHashMap& vaosHashMap)
 {
-	return mesh->hasVertWeights();
+	for(uint level = 0; level < mtl.getLevelsOfDetail(); ++level)
+	{
+		for(uint pass = 0; pass < mtl.getPasses().size(); ++pass)
+		{
+			PassLevelKey key(pass, level);
+
+			Vao* vao = createVao(mtl, vbos, key);
+
+			vaos.push_back(vao);
+			vaosHashMap[key] = vao;
+		}
+	}
+
+
 }
 
 

+ 26 - 4
anki/resource/ModelPatch.h

@@ -2,19 +2,27 @@
 #define ANKI_RESOURCE_MODEL_PATCH_H
 
 #include "anki/resource/Resource.h"
+#include "anki/resource/PassLevelKey.h"
+#include "anki/resource/Mesh.h"
+#include "anki/gl/Vao.h"
+#include <boost/ptr_container/ptr_vector.hpp>
 
 
 namespace anki {
 
 
-class Mesh;
 class Material;
 
 
 /// Its one part of the many used in the Model class. Its basically a container
+/// for a Mesh and it's Material
 class ModelPatch
 {
 	public:
+		typedef boost::ptr_vector<Vao> VaosContainer;
+		typedef PassLevelHashMap<Vao*>::Type PassLevelToVaoHashMap;
+		typedef boost::array<const Vbo*, Mesh::VBOS_NUM> VboArray;
+
 		ModelPatch(const char* meshFName, const char* mtlFName);
 		~ModelPatch();
 
@@ -33,12 +41,26 @@ class ModelPatch
 
 		bool supportsHwSkinning() const;
 
+		const Vao& getVao(const PassLevelKey& key) const
+		{
+			return *vaosHashMap.at(key);
+		}
+
+		static void createVaos(const Material& mtl,
+			const VboArray& vbos,
+			VaosContainer& vaos,
+			PassLevelToVaoHashMap& vaosHashMap);
+
 	private:
 		MeshResourcePointer mesh; ///< The geometry
-		MaterialResourcePointer mtl; ///< Material for MS and BS
+		MaterialResourcePointer mtl; ///< Material
+
+		VaosContainer vaos;
+		PassLevelToVaoHashMap vaosHashMap;
 
-		/// Load the resources
-		void load(const char* meshFName, const char* mtlFName);
+		static Vao* createVao(const Material& mtl,
+			const VboArray& vbos,
+			const PassLevelKey& key);
 };
 
 

+ 54 - 0
anki/resource/PassLevelKey.h

@@ -0,0 +1,54 @@
+#ifndef ANKI_RESOURCE_PASS_LEVEL_KEY_H
+#define ANKI_RESOURCE_PASS_LEVEL_KEY_H
+
+#include <boost/unordered_map.hpp>
+
+
+namespace anki {
+
+
+/// XXX
+struct PassLevelKey
+{
+	uint pass;
+	uint level;
+
+	PassLevelKey()
+	:	pass(0),
+	 	level(0)
+	{}
+
+	PassLevelKey(uint pass_, uint level_)
+	:	pass(pass_),
+	 	level(level_)
+	{}
+
+	/// Hash creation method
+	size_t operator()(const PassLevelKey& b) const
+	{
+		return pass * 1000 + level;
+	}
+
+	/// Values comparisons
+	bool operator()(const PassLevelKey& a,
+		const PassLevelKey& b) const
+	{
+		return a.pass == b.pass && a.level == b.level;
+	}
+};
+
+
+/// XXX
+template<typename T>
+struct PassLevelHashMap
+{
+	typedef boost::unordered_map<PassLevelKey, T,
+		PassLevelKey, PassLevelKey> Type;
+};
+
+
+
+} // end namespace
+
+
+#endif

+ 9 - 19
anki/scene/MaterialRuntime.cpp

@@ -7,8 +7,6 @@
 namespace anki {
 
 
-//==============================================================================
-// Constructor                                                                 =
 //==============================================================================
 MaterialRuntime::MaterialRuntime(const Material& mtl_)
 :	mtl(mtl_)
@@ -19,51 +17,43 @@ MaterialRuntime::MaterialRuntime(const Material& mtl_)
 	me = he;
 
 	// Create vars
-	BOOST_FOREACH(const MaterialUserVariable* var, mtl.getUserVariables())
+	BOOST_FOREACH(const MaterialVariable& var, mtl.getVariables())
 	{
-		MaterialRuntimeVariable* varr = new MaterialRuntimeVariable(*var);
+		MaterialRuntimeVariable* varr = new MaterialRuntimeVariable(var);
 		vars.push_back(varr);
-		varNameToVar[varr->getMaterialUserVariable().getName()] = varr;
+		varNameToVar[varr->getMaterialVariable().getName().c_str()] = varr;
 	}
 }
 
 
-//==============================================================================
-// Destructor                                                                  =
 //==============================================================================
 MaterialRuntime::~MaterialRuntime()
 {}
 
 
-//==============================================================================
-// findVariableByName                                                          =
 //==============================================================================
 MaterialRuntimeVariable& MaterialRuntime::findVariableByName(
 	const char* name)
 {
-	ConstCharPtrHashMap<MaterialRuntimeVariable*>::Type::iterator it =
-		varNameToVar.find(name);
+	VariablesHashMap::iterator it = varNameToVar.find(name);
 	if(it == varNameToVar.end())
 	{
-		throw ANKI_EXCEPTION("Cannot get user defined variable with name \"" +
-			name + '\"');
+		throw ANKI_EXCEPTION("Cannot get material runtime variable "
+			"with name \"" + name + '\"');
 	}
 	return *(it->second);
 }
 
 
-//==============================================================================
-// findVariableByName                                                          =
 //==============================================================================
 const MaterialRuntimeVariable& MaterialRuntime::findVariableByName(
 	const char* name) const
 {
-	ConstCharPtrHashMap<MaterialRuntimeVariable*>::Type::const_iterator
-		it = varNameToVar.find(name);
+	VariablesHashMap::const_iterator it = varNameToVar.find(name);
 	if(it == varNameToVar.end())
 	{
-		throw ANKI_EXCEPTION("Cannot get user defined variable with name \"" +
-			name + '\"');
+		throw ANKI_EXCEPTION("Cannot get material runtime variable "
+			"with name \"" + name + '\"');
 	}
 	return *(it->second);
 }

+ 94 - 31
anki/scene/MaterialRuntime.h

@@ -3,14 +3,15 @@
 
 #include "anki/resource/MaterialProperties.h"
 #include "anki/util/ConstCharPtrHashMap.h"
+#include "anki/scene/MaterialRuntimeVariable.h"
 #include <boost/ptr_container/ptr_vector.hpp>
+#include <boost/range/iterator_range.hpp>
 
 
 namespace anki {
 
 
 class Material;
-class MaterialRuntimeVariable;
 
 
 /// One layer above material resource
@@ -21,7 +22,15 @@ class MaterialRuntime: public MaterialProperties
 		typedef boost::ptr_vector<MaterialRuntimeVariable>
 			VariablesContainer;
 
-		/// @name Constructors & destructors
+		typedef boost::iterator_range<VariablesContainer::const_iterator>
+			ConstIteratorRange;
+		typedef boost::iterator_range<VariablesContainer::iterator>
+			MutableIteratorRange;
+
+		typedef ConstCharPtrHashMap<MaterialRuntimeVariable*>::Type
+			VariablesHashMap;
+
+		/// @name Constructors & destructor
 		/// @{
 		MaterialRuntime(const Material& mtl);
 		~MaterialRuntime();
@@ -29,34 +38,83 @@ class MaterialRuntime: public MaterialProperties
 
 		/// @name Accessors
 		/// @{
-		bool getCastShadow() const {return castsShadowFlag;}
-		bool& getCastShadow() {return castsShadowFlag;}
-		void setCastShadow(bool x) {castsShadowFlag = x;}
-
-		bool getRenderInBledingStage() const {return renderInBlendingStageFlag;}
-		bool& getRenderInBledingStage() {return renderInBlendingStageFlag;}
-		void setRenderInBledingStage(bool x) {renderInBlendingStageFlag = x;}
-
-		int getBlendingSFactor() const {return blendingSfactor;}
-		int& getBlendingSFactor() {return blendingSfactor;}
-		void setBlendingSFactor(int x) {blendingSfactor = x;}
-
-		int getBlendingDFactor() const {return blendingDfactor;}
-		int& getBlendingDFactor() {return blendingDfactor;}
-		void setBlendingDFactor(int x) {blendingDfactor = x;}
-
-		bool getDepthTesting() const {return depthTesting;}
-		bool& getDepthTesting() {return depthTesting;}
-		void setDepthTesting(bool x) {depthTesting = x;}
-
-		bool getWireframe() const {return wireframe;}
-		bool& getWireframe() {return wireframe;}
-		void setWireframe(bool x) {wireframe = x;}
-
-		const VariablesContainer& getVariables() const {return vars;}
-		VariablesContainer& getVariables() {return vars;}
-
-		const Material& getMaterial() const {return mtl;}
+		using MaterialProperties::getRenderingStage;
+		uint& getRenderingStage()
+		{
+			return renderingStage;
+		}
+		void setRenderingStage(uint x)
+		{
+			renderingStage = x;
+		}
+
+		using MaterialProperties::getPasses;
+
+		using MaterialProperties::getLevelsOfDetail;
+
+		using MaterialProperties::getShadow;
+		bool& getShadow()
+		{
+			return shadow;
+		}
+		void setShadow(bool x)
+		{
+			shadow = x;
+		}
+
+		using MaterialProperties::getBlendingSfactor;
+		int& getBlendingSFactor()
+		{
+			return blendingSfactor;
+		}
+		void setBlendingSFactor(int x)
+		{
+			blendingSfactor = x;
+		}
+
+		using MaterialProperties::getBlendingDfactor;
+		int& getBlendingDFactor()
+		{
+			return blendingDfactor;
+		}
+		void setBlendingDFactor(int x)
+		{
+			blendingDfactor = x;
+		}
+
+		using MaterialProperties::getDepthTesting;
+		bool& getDepthTesting()
+		{
+			return depthTesting;
+		}
+		void setDepthTesting(bool x)
+		{
+			depthTesting = x;
+		}
+
+		using MaterialProperties::getWireframe;
+		bool& getWireframe()
+		{
+			return wireframe;
+		}
+		void setWireframe(bool x)
+		{
+			wireframe = x;
+		}
+
+		ConstIteratorRange getVariables() const
+		{
+			return ConstIteratorRange(vars.begin(), vars.end());
+		}
+		MutableIteratorRange getVariables()
+		{
+			return MutableIteratorRange(vars.begin(), vars.end());
+		}
+
+		const Material& getMaterial() const
+		{
+			return mtl;
+		}
 		/// @}
 
 		/// Find a material runtime variable. On failure it throws an exception
@@ -70,10 +128,15 @@ class MaterialRuntime: public MaterialProperties
 		const MaterialRuntimeVariable& findVariableByName(
 			const char* name) const;
 
+		bool variableExists(const char* name) const
+		{
+			return varNameToVar.find(name) != vars.end();
+		}
+
 	private:
 		const Material& mtl; ///< The resource
 		VariablesContainer vars;
-		ConstCharPtrHashMap<MaterialRuntimeVariable*>::Type varNameToVar;
+		VariablesHashMap varNameToVar;
 };
 
 

+ 5 - 11
anki/scene/MaterialRuntimeVariable.cpp

@@ -1,35 +1,29 @@
 #include "anki/scene/MaterialRuntimeVariable.h"
-#include "anki/resource/MaterialUserVariable.h"
+#include "anki/resource/MaterialVariable.h"
 
 
 namespace anki {
 
 
-//==============================================================================
-// ConstructVisitor::operator() <TextureResourcePointer >                            =
 //==============================================================================
 template <>
 void MaterialRuntimeVariable::ConstructVisitor::
 	operator()<TextureResourcePointer >(const TextureResourcePointer& x) const
 {
-	udvr.data = &x;
+	var.data = &x;
 }
 
 
-//==============================================================================
-// Constructor                                                                 =
 //==============================================================================
 MaterialRuntimeVariable::MaterialRuntimeVariable(
-	const MaterialUserVariable& umv_)
-:	umv(umv_)
+	const MaterialVariable& mvar_)
+:	mvar(mvar_)
 {
 	// Initialize the data using a visitor
-	boost::apply_visitor(ConstructVisitor(*this), umv.getDataVariant());
+	boost::apply_visitor(ConstructVisitor(*this), mvar.getVariant());
 }
 
 
-//==============================================================================
-// Destructor                                                                  =
 //==============================================================================
 MaterialRuntimeVariable::~MaterialRuntimeVariable()
 {}

+ 54 - 21
anki/scene/MaterialRuntimeVariable.h

@@ -10,7 +10,7 @@ namespace anki {
 
 
 class Texture;
-class MaterialUserVariable;
+class MaterialVariable;
 
 
 /// Variable of runtime materials
@@ -24,37 +24,54 @@ class MaterialRuntimeVariable
 		/// The data union. The Texture resource is read-only at runtime
 		/// Don't EVER replace the texture with const Texture*. The asynchronous
 		/// operations will fail
-		typedef boost::variant<float, Vec2, Vec3, Vec4,
-			ConstPtrRsrcPtrTexture> DataVariant;
+		typedef boost::variant<float, Vec2, Vec3, Vec4, Mat3,
+			Mat4, ConstPtrRsrcPtrTexture> Variant;
 
 		/// Constructor
-		MaterialRuntimeVariable(const MaterialUserVariable& umv);
+		MaterialRuntimeVariable(const MaterialVariable& mv);
+
 		/// Destructor
 		~MaterialRuntimeVariable();
 
 		/// @name Accessors
 		/// @{
-		const MaterialUserVariable& getMaterialUserVariable() const
-			{return umv;}
-
+		const MaterialVariable& getMaterialVariable() const
+		{
+			return mvar;
+		}
 
-		const DataVariant& getDataVariant() const {return data;}
-		DataVariant& getDataVariant() {return data;}
+		const Variant& getDataVariant() const
+		{
+			return data;
+		}
+		Variant& getDataVariant()
+		{
+			return data;
+		}
 
 		/// Get the value of the variant
 		/// @exception boost::exception when you try to get the incorrect data
 		/// type
 		template<typename Type>
-		const Type& getValue() const {return boost::get<Type>(data);}
+		const Type& getValue() const
+		{
+			return boost::get<Type>(data);
+		}
 
 		/// Get the value of the variant
 		/// @exception boost::exception when you try to get the incorrect data
 		/// type
 		template<typename Type>
-		Type& getValue() {return boost::get<Type>(data);}
+		Type& getValue()
+		{
+			return boost::get<Type>(data);
+		}
 
 		template<typename Type>
-		void setValue(const Type& v) {boost::get<Type>(data) = v;}
+		void setValue(const Type& v)
+		{
+			boost::get<Type>(data) = v;
+		}
 		/// @}
 
 	private:
@@ -62,26 +79,42 @@ class MaterialRuntimeVariable
 		class ConstructVisitor: public boost::static_visitor<void>
 		{
 			public:
-				MaterialRuntimeVariable& udvr;
+				MaterialRuntimeVariable& var;
 
-				ConstructVisitor(MaterialRuntimeVariable& udmvr);
+				ConstructVisitor(MaterialRuntimeVariable& var_)
+				:	var(var_)
+				{}
 
 				/// Template method that applies to all DataVariant values
 				/// except texture resource
 				template<typename Type>
 				void operator()(const Type& x) const
-					{udvr.getDataVariant() = x;}
+				{
+					var.getDataVariant() = x;
+				}
 		};
 
-		const MaterialUserVariable& umv; ///< Know the resource
-		DataVariant data; /// The data
+		const MaterialVariable& mvar; ///< Know the resource
+		Variant data; /// The data
 };
 
 
-inline MaterialRuntimeVariable::ConstructVisitor::ConstructVisitor(
-	MaterialRuntimeVariable& udvr_)
-:	udvr(udvr_)
-{}
+// Declare specialized
+template <>
+void MaterialRuntimeVariable::ConstructVisitor::
+	operator()<TextureResourcePointer >(const TextureResourcePointer& x) const;
+
+// Declare specialized
+template<>
+MaterialRuntimeVariable::ConstPtrRsrcPtrTexture&
+	MaterialRuntimeVariable::getValue<
+	MaterialRuntimeVariable::ConstPtrRsrcPtrTexture>();
+
+// Declare specialized
+template<>
+void MaterialRuntimeVariable::setValue<
+	MaterialRuntimeVariable::ConstPtrRsrcPtrTexture>(
+	const ConstPtrRsrcPtrTexture& v);
 
 
 } // end namespace

+ 5 - 5
anki/scene/PatchNode.cpp

@@ -21,12 +21,12 @@ PatchNode::PatchNode(const ModelPatch& modelPatch, ulong flags,
 //==============================================================================
 // createVao                                                                   =
 //==============================================================================
-void PatchNode::createVao(const Material& mtl, const VboArray& vbos,
+void PatchNode::createVao(const MaterialRuntime& mtl, const VboArray& vbos,
 	Vao& vao)
 {
 	vao.create();
 
-	if(mtl.buildinVariableExits(MaterialBuildinVariable::MV_POSITION))
+	if(mtl.variableExits("position"))
 	{
 		ANKI_ASSERT(vbos[Mesh::VBO_VERT_POSITIONS] != NULL);
 
@@ -34,7 +34,7 @@ void PatchNode::createVao(const Material& mtl, const VboArray& vbos,
 			0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
 	}
 
-	if(mtl.buildinVariableExits(MaterialBuildinVariable::MV_NORMAL))
+	if(mtl.variableExits("normal"))
 	{
 		ANKI_ASSERT(vbos[Mesh::VBO_VERT_NORMALS] != NULL);
 
@@ -42,7 +42,7 @@ void PatchNode::createVao(const Material& mtl, const VboArray& vbos,
 			1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
 	}
 
-	if(mtl.buildinVariableExits(MaterialBuildinVariable::MV_TANGENT))
+	if(mtl.variableExits("tangent"))
 	{
 		ANKI_ASSERT(vbos[Mesh::VBO_VERT_TANGENTS] != NULL);
 
@@ -50,7 +50,7 @@ void PatchNode::createVao(const Material& mtl, const VboArray& vbos,
 			2, 4, GL_FLOAT, GL_FALSE, 0, NULL);
 	}
 
-	if(mtl.buildinVariableExits(MaterialBuildinVariable::MV_TEX_COORDS))
+	if(mtl.variableExits("texCoords"))
 	{
 		vao.attachArrayBufferVbo(*vbos[Mesh::VBO_TEX_COORDS],
 			3, 2, GL_FLOAT, GL_FALSE, 0, NULL);

+ 1 - 1
anki/scene/PatchNode.h

@@ -61,7 +61,7 @@ class PatchNode: public RenderableNode
 		/// Create a VAO given a material and an array of VBOs
 		/// The location of the uniform variables are hard coded. See
 		/// MaterialVertex.glsl
-		static void createVao(const Material& material,
+		static void createVao(const MaterialRuntime& material,
 			const VboArray& vbos,
 			Vao& vao);
 };

+ 1 - 2
anki/scene/SkinPatchNode.cpp

@@ -98,7 +98,6 @@ SkinPatchNode::SkinPatchNode(const ModelPatch& modelPatch_, SkinNode& parent)
 		sizeof(MeshData::VertexWeight),
 		BUFFER_OFFSET(0));
 
-
 	tfVao.attachArrayBufferVbo(mesh.getVbo(Mesh::VBO_VERT_WEIGHTS),
 		VERT_WEIGHT_BONE_IDS_LOC,
 		4,
@@ -118,7 +117,7 @@ SkinPatchNode::SkinPatchNode(const ModelPatch& modelPatch_, SkinNode& parent)
 	// Create the rendering VAOs
 	for(uint i = 0; i < PASS_TYPES_NUM; i++)
 	{
-		createVao(rsrc.getMaterial(), vboArr, vaos[i]);
+		createVao(mtlRun, vboArr, vaos[i]);
 	}
 }
 

+ 6 - 2
anki/util/StringList.h

@@ -15,12 +15,14 @@ class StringList: public std::vector<std::string>
 		typedef std::vector<std::string> Base; ///< Its the vector of strings
 		typedef Base::value_type ValueType; ///< Its string
 
-		void join(const ValueType& sep, ValueType& out) const;
+		std::string join(const ValueType& sep) const;
 };
 
 
-inline void StringList::join(const ValueType& sep, ValueType& out) const
+inline std::string StringList::join(const ValueType& sep) const
 {
+	std::string out;
+
 	Base::const_iterator it = begin();
 	for(; it != end(); it++)
 	{
@@ -30,6 +32,8 @@ inline void StringList::join(const ValueType& sep, ValueType& out) const
 			out += sep;
 		}
 	}
+
+	return out;
 }