Explorar el Código

Animation and material rework

Panagiotis Christopoulos Charitos hace 12 años
padre
commit
87b4ab2ad3

+ 61 - 0
include/anki/resource/Animation.h

@@ -0,0 +1,61 @@
+#ifndef ANKI_RESOURCE_ANIMATION_H
+#define ANKI_RESOURCE_ANIMATION_H
+
+#include "anki/Math.h"
+#include "anki/util/Vector.h"
+
+namespace anki {
+
+/// A keyframe 
+template<typename T> 
+class Key
+{
+	friend class Animation;
+
+public:
+	F64 getTime() const
+	{
+		return time;
+	}
+
+	const T& getValue() const
+	{
+		return value;
+	}
+
+private:
+	F64 time;
+	T value;
+};
+
+/// Animation channel
+struct AnimationChannel
+{
+	std::string name;
+
+	I32 boneIndex = -1; ///< For skeletal animations
+
+	Vector<Key<Vec3>> positions;
+	Vector<Key<Quat>> rotations;
+	Vector<Key<F32>> scales;
+	Vector<Key<F32>> cameraFovs;
+};
+
+/// Animation
+class Animation
+{
+public:
+	void load(const char* filename);
+
+	const Vector<AnimationChannel>& getChannels() const
+	{
+		return channels;
+	}
+
+private:
+	Vector<AnimationChannel> channels;
+};
+
+} // end namespace anki
+
+#endif

+ 11 - 4
include/anki/resource/MaterialShaderProgramCreator.h

@@ -23,6 +23,8 @@ public:
 		StringList value;
 		Bool constant;
 		U32 arraySize;
+		std::string line;
+		U32 foundIn = 0; ///< Found in shader
 	};
 
 	explicit MaterialShaderProgramCreator(const XmlElement& pt, 
@@ -42,6 +44,12 @@ public:
 	}
 
 private:
+	enum Shader
+	{
+		VERTEX = 1,
+		FRAGMENT = 2
+	}
+
 	/// The lines of the shader program source
 	StringList srcLines;
 
@@ -59,12 +67,11 @@ private:
 	/// @code <shader></shader> @endcode
 	void parseShaderTag(const XmlElement& el);
 
-	/// Parse what is within the @code <input></input> @endcode
-	void parseInputTag(const XmlElement& el,
-		std::string& line);
+	/// Parse what is within the @code <inputs></inputs> @endcode
+	void parseInputsTag(const XmlElement& programEl);
 
 	/// Parse what is within the @code <operation></operation> @endcode
-	void parseOperationTag(const XmlElement& el);
+	void parseOperationTag(const XmlElement& el, Shader shader);
 };
 
 } // end namespace anki

+ 11 - 4
include/anki/resource/Model.h

@@ -6,13 +6,13 @@
 #include "anki/collision/Obb.h"
 #include "anki/resource/PassLevelKey.h"
 #include "anki/resource/Mesh.h"
+#include "anki/resource/Material.h"
+#include "anki/resource/Skeleton.h"
+#include "anki/resource/Animation.h"
 #include "anki/util/Vector.h"
 
 namespace anki {
 
-// Forward
-class ShaderProgram;
-
 /// Model patch interface class. Its very important class and it binds the
 /// material with the mesh
 class ModelPatchBase
@@ -153,6 +153,11 @@ private:
 /// 		...
 /// 		<modelPatch>...</modelPatch>
 /// 	</modelPatches>
+/// 	[<skeleton>path/to/skeleton.skel</skeleton>]
+/// 	[<skeletonAnimations>
+/// 		<animation>path/to/animation.anim</animation>
+/// 		...
+/// 	</skeletonAnimations>]
 /// </model>
 /// @endcode
 ///
@@ -188,8 +193,10 @@ private:
 	/// The vector of ModelPatch
 	ModelPatchesContainer modelPatches;
 	Obb visibilityShape;
+	SkeletonResourcePointer skeleton;
+	Vector<AnimationResourcePointer> animations;
 };
 
-} // end namespace
+} // end namespace anki
 
 #endif

+ 2 - 1
include/anki/resource/Resource.h

@@ -21,6 +21,7 @@ ANKI_RESOURCE_TYPEDEFS(Mesh, MeshResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(BucketMesh, BucketMeshResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(Skeleton, SkeletonResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(SkelAnim, SkelAnimResourcePointer)
+ANKI_RESOURCE_TYPEDEFS(Animation, AnimationResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(LightRsrc, LightRsrcResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(ParticleEmitterResource, ParticleEmitterResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(Script, ScriptResourcePointer)
@@ -28,6 +29,6 @@ ANKI_RESOURCE_TYPEDEFS(Model, ModelResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(Skin, SkinResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(DummyRsrc, DummyRsrcResourcePointer)
 
-} // end namespace
+} // end namespace anki
 
 #endif

+ 2 - 2
include/anki/resource/ResourceManager.h

@@ -26,7 +26,7 @@ struct ResourceHook
 	}
 };
 
-/// XXX
+/// Manage resources of a certain type
 template<typename Type>
 class ResourceManager
 {
@@ -62,7 +62,7 @@ protected:
 	virtual void deallocRsrc(Type* rsrc);
 };
 
-} // end namespace
+} // end namespace anki
 
 #include "anki/resource/ResourceManager.inl.h"
 

+ 11 - 0
src/resource/Animation.cpp

@@ -0,0 +1,11 @@
+#include "anki/resource/SkelAnim.h"
+
+namespace anki {
+
+//==============================================================================
+void Animation::load(const char* filename)
+{
+
+}
+
+} // end namespace anki

+ 111 - 84
src/resource/MaterialShaderProgramCreator.cpp

@@ -9,6 +9,15 @@
 
 namespace anki {
 
+//==============================================================================
+struct InputSortFunctor
+{
+	bool operator()(const Input* a, const Input* b)
+	{
+		return a->name < b->name;
+	}
+};
+
 //==============================================================================
 MaterialShaderProgramCreator::MaterialShaderProgramCreator(
 	const XmlElement& el, Bool enableUniformBlocks_)
@@ -25,6 +34,10 @@ MaterialShaderProgramCreator::~MaterialShaderProgramCreator()
 void MaterialShaderProgramCreator::parseShaderProgramTag(
 	const XmlElement& shaderProgramEl)
 {
+	// First the inputs
+	parseInputs(shaderProgramEl);
+
+	// Then the shaders
 	XmlElement shaderEl = shaderProgramEl.getChildElement("shader");
 
 	do
@@ -78,6 +91,16 @@ void MaterialShaderProgramCreator::parseShaderTag(
 	std::string type = shaderEl.getChildElement("type").getText();
 	srcLines.push_back("#pragma anki start " + type + "Shader");
 
+	Shader shader;
+	if(type == "vertex")
+	{
+		shader = VERTEX;
+	}
+	else
+	{
+		shader = FRAGMENT;
+	}
+
 	// <includes></includes>
 	//
 	StringList includeLines;
@@ -94,33 +117,8 @@ void MaterialShaderProgramCreator::parseShaderTag(
 		includeEl = includeEl.getNextSiblingElement("include");
 	} while(includeEl);
 
-	//includeLines.sortAll();
 	srcLines.insert(srcLines.end(), includeLines.begin(), includeLines.end());
 
-	// <inputs></inputs>
-	//
-	XmlElement inputsEl = shaderEl.getChildElementOptional("inputs");
-	if(inputsEl)
-	{
-		// Store the source of the uniform vars
-		StringList uniformsLines;
-	
-		XmlElement inputEl = inputsEl.getChildElement("input");
-		do
-		{
-			std::string line;
-			parseInputTag(inputEl, line);
-			uniformsLines.push_back(line);
-
-			inputEl = inputEl.getNextSiblingElement("input");
-		} while(inputEl);
-
-		srcLines.push_back("");
-		uniformsLines.sortAll();
-		srcLines.insert(srcLines.end(), uniformsLines.begin(),
-			uniformsLines.end());
-	}
-
 	// <operations></operations>
 	//
 	srcLines.push_back("\nvoid main()\n{");
@@ -129,7 +127,7 @@ void MaterialShaderProgramCreator::parseShaderTag(
 	XmlElement opEl = opsEl.getChildElement("operation");
 	do
 	{
-		parseOperationTag(opEl);
+		parseOperationTag(opEl, shader);
 
 		opEl = opEl.getNextSiblingElement("operation");
 	} while(opEl);
@@ -138,83 +136,99 @@ void MaterialShaderProgramCreator::parseShaderTag(
 }
 
 //==============================================================================
-void MaterialShaderProgramCreator::parseInputTag(
-	const XmlElement& inputEl, std::string& line)
+void MaterialShaderProgramCreator::parseInputTags(const XmlElement& programEl)
 {
-	Input* inpvar = new Input;
-
-	inpvar->name = inputEl.getChildElement("name").getText();
-	inpvar->type = inputEl.getChildElement("type").getText();
-	XmlElement constEl = inputEl.getChildElementOptional("const");
-	XmlElement valueEl = inputEl.getChildElement("value");
-	XmlElement arrSizeEl = inputEl.getChildElementOptional("arraySize");
-
-	// Is const?
-	if(constEl)
-	{
-		inpvar->constant = constEl.getInt();
-	}
-	else
+	XmlElement inputsEl = programEl.getChildElementOptional("inputs");
+	if(!inputsEl)
 	{
-		inpvar->constant = false;
+		return;
 	}
 
-	// Is array?
-	if(arrSizeEl)
-	{
-		inpvar->arraySize = arrSizeEl.getInt();
-	}
-	else
+	XmlElement inputEl = inputsEl.getChildElement("input");
+	do
 	{
-		inpvar->arraySize = 0;
-	}
+		Input* inpvar = new Input;
 
-	// Get value
-	if(valueEl.getText())
-	{
-		inpvar->value = StringList::splitString(valueEl.getText(), ' ');
-	}
+		inpvar->name = inputEl.getChildElement("name").getText();
+		inpvar->type = inputEl.getChildElement("type").getText();
+		XmlElement constEl = inputEl.getChildElementOptional("const");
+		XmlElement valueEl = inputEl.getChildElement("value");
+		XmlElement arrSizeEl = inputEl.getChildElementOptional("arraySize");
 
-	if(inpvar->constant == false)
-	{
-		// Handle non-consts
-
-		if(!(enableUniformBlocks && inpvar->type != "sampler2D"))
+		// Is const?
+		if(constEl)
 		{
-			line = "uniform " + inpvar->type + " " + inpvar->name;
-			
-			if(inpvar->arraySize > 1)
-			{
-				line += "[" + std::to_string(inpvar->arraySize) + "U]";
-			}
+			inpvar->constant = constEl.getInt();
+		}
+		else
+		{
+			inpvar->constant = false;
+		}
 
-			line += ";";
+		// Is array?
+		if(arrSizeEl)
+		{
+			inpvar->arraySize = arrSizeEl.getInt();
+		}
+		else
+		{
+			inpvar->arraySize = 0;
 		}
-	}
-	else
-	{
-		// Handle consts
 
-		if(inpvar->value.size() == 0)
+		// Get value
+		if(valueEl.getText())
 		{
-			throw ANKI_EXCEPTION("Empty value and const is illogical");
+			inpvar->value = StringList::splitString(valueEl.getText(), ' ');
 		}
 
-		if(inpvar->arraySize > 0)
+		if(inpvar->constant == false)
+		{
+			// Handle non-consts
+
+			if(!(enableUniformBlocks && inpvar->type != "sampler2D"))
+			{
+				inpvar->line = "uniform " + inpvar->type + " " + inpvar->name;
+				
+				if(inpvar->arraySize > 1)
+				{
+					inpvar->line += "[" + std::to_string(inpvar->arraySize) 
+						+ "U]";
+				}
+
+				inpvar->line += ";";
+			}
+		}
+		else
 		{
-			throw ANKI_EXCEPTION("Const arrays currently cannot be handled");
+			// Handle consts
+
+			if(inpvar->value.size() == 0)
+			{
+				throw ANKI_EXCEPTION("Empty value and const is illogical");
+			}
+
+			if(inpvar->arraySize > 0)
+			{
+				throw ANKI_EXCEPTION("Const arrays currently cannot be handled");
+			}
+
+			inpvar->line = "const " + inpvar->type + " " + inpvar->name 
+				+ " = " + inpvar->type + "(" + inpvar->value.join(", ") +  ");";
 		}
 
-		line = "const " + inpvar->type + " " + inpvar->name + " = "
-			+ inpvar->type + "(" + inpvar->value.join(", ") +  ");";
-	}
+		inputs.push_back(inpvar);
+
+		// Advance
+		inputEl = inputEl.getNextSiblingElement("input");
+	} while(inputEl);
 
-	inputs.push_back(inpvar);
+	// Sort them by name to decrease the change of creating unique shaders
+	std::sort(inputs.begin(), inputs.end(), InputSortFunctor);
 }
 
 //==============================================================================
 void MaterialShaderProgramCreator::parseOperationTag(
-	const XmlElement& operationTag)
+	const XmlElement& operationTag, Shader shader)
 {
 	// <id></id>
 	int id = operationTag.getChildElement("id").getInt();
@@ -241,7 +255,21 @@ void MaterialShaderProgramCreator::parseOperationTag(
 		XmlElement argEl = argsEl.getChildElement("argument");
 		do
 		{
+			// Search for all the inputs and mark the appropriate
+			Input* in = nullptr;
+			for(in : inputs)
+			{
+				if(in->name == argEl.getText())
+				{
+					in->shaders |= (U32)shader;
+					break;
+				}
+			}
+
+			// Add to a list
 			argsList.push_back(argEl.getText());
+
+			// Advance
 			argEl = argEl.getNextSiblingElement("argument");
 		} while(argEl);
 	}
@@ -250,11 +278,9 @@ void MaterialShaderProgramCreator::parseOperationTag(
 	std::stringstream line;
 	line << "#if defined(" << funcName << "_DEFINED)";
 
-	// XXX Regexpr features still missing
-	//std::regex expr("^operationOut[0-9]*$");
+	// Write the defines for the operationOuts
 	for(const std::string& arg : argsList)
 	{
-		//if(std::regex_match(arg, expr))
 		if(arg.find("operationOut") == 0)
 		{
 			line << " && defined(" << arg << "_DEFINED)";
@@ -272,6 +298,7 @@ void MaterialShaderProgramCreator::parseOperationTag(
 		line << '\t';
 	}
 	
+	// write the blah = func(args...)
 	line << funcName << "(";
 	line << argsList.join(", ");
 	line << ");\n";

+ 1 - 4
src/resource/Model.cpp

@@ -1,9 +1,7 @@
 #include "anki/resource/Model.h"
 #include "anki/resource/Material.h"
 #include "anki/resource/Mesh.h"
-#include "anki/resource/SkelAnim.h"
 #include "anki/resource/MeshLoader.h"
-#include "anki/resource/Skeleton.h"
 #include "anki/resource/ShaderProgramResource.h"
 #include "anki/misc/Xml.h"
 
@@ -326,5 +324,4 @@ void Model::load(const char* filename)
 	}
 }
 
-
-} // end namespace
+} // end namespace anki

+ 23 - 6
tools/2anki/Main.cpp

@@ -578,12 +578,14 @@ void exportAnimation(const aiAnimation& anim, uint32_t index,
 		file << "\t\t\t<name>" << nAnim.mNodeName.C_Str() << "</name>\n";
 
 		// Positions
-		file << "\t\t\t<positionKeys>";
+		file << "\t\t\t<positionKeys>\n";
 		for(uint32_t j = 0; j < nAnim.mNumPositionKeys; j++)
 		{
 			const aiVectorKey& key = nAnim.mPositionKeys[j];
-			file << key.mTime << " " << key.mValue[0] << " " 
-				<< key.mValue[1] << " " << key.mValue[2] << " ";
+
+			file << "\t\t\t\t<key><time>" << key.mTime << "</time>"
+				<< "<value>" << key.mValue[0] << " " 
+				<< key.mValue[1] << " " << key.mValue[2] << "</value></key>\n";
 		}
 		file << "</positionKeys>\n";
 
@@ -592,12 +594,27 @@ void exportAnimation(const aiAnimation& anim, uint32_t index,
 		for(uint32_t j = 0; j < nAnim.mNumRotationKeys; j++)
 		{
 			const aiQuatKey& key = nAnim.mRotationKeys[j];
-			file << key.mTime << " " << key.mValue.x << " " 
-				<< key.mValue.y << " " << key.mValue.z << " "
-				<< key.mValue.w << " ";
+
+			file << "\t\t\t\t<key><time>" << key.mTime << "</time>"
+				<< "<value>" << key.mValue.y << " " << key.mValue.z << " "
+				<< key.mValue.w << "</value></key>\n";
 		}
 		file << "</rotationKeys>\n";
 
+		// Scale
+		file << "\t\t\t<scalingKeys>";
+		for(uint32_t j = 0; j < nAnim.mNumScalingKeys; j++)
+		{
+			const aiVectorKey& key = nAnim.mScalingKeys[j];
+
+			// Note: only uniform scale
+			file << "\t\t\t\t<key><time>" << key.mTime << "</time>"
+				<< "<value>" 
+				<< ((key.mValue[0] + key.mValue[1] + key.mValue[2]) / 3.0)
+				<< "</value></key>\n";
+		}
+		file << "</scalingKeys>\n";
+
 		file << "\t\t</channel>\n";
 	}