Browse Source

Animation & animation event

Panagiotis Christopoulos Charitos 12 years ago
parent
commit
39d0f1ea6b

+ 1 - 1
bench/Main.cpp

@@ -221,7 +221,7 @@ void initScene()
 	}
 #endif
 
-	scene.load("maps/sponza/master.scene");
+	scene.load("maps/sponza/master.ankiscene");
 
 	PointLight* pl = new PointLight("pl0", &scene, nullptr, Movable::MF_NONE);
 	pl->setRadius(12.5);

+ 24 - 0
include/anki/event/AnimationEvent.h

@@ -0,0 +1,24 @@
+#include "anki/event/Event.h"
+#include "anki/resource/Resource.h"
+
+namespace anki {
+
+/// @addtogroup Event
+/// @{
+
+/// Event controled by animation resource
+class AnimationEvent: public Event
+{
+public:
+	AnimationEvent(const AnimationResourcePointer& anim, 
+		SceneNode* movableSceneNode);
+
+	/// Implements Event::update
+	void update(F32 prevUpdateTime, F32 crntTime);
+
+private:
+	AnimationResourcePointer anim;
+};
+/// @}
+
+} // end namespace anki

+ 5 - 0
include/anki/gl/GlState.h

@@ -45,6 +45,11 @@ public:
 		return gpu;
 	}
 
+	Bool isStd430Supported() const
+	{
+		return major >= 4 && minor >= 3;
+	}
+
 	void init(const U32 major_, const U32 minor_, 
 		Bool registerDebugMessages = false);
 

+ 11 - 2
include/anki/misc/Xml.h

@@ -43,12 +43,21 @@ public:
 		return el->GetText();
 	}
 
-	/// Return the text inside as a string
+	/// Return the text inside as an int
 	I getInt() const;
 
-	/// Return a Mat4
+	/// Return the text inside as a float
+	F64 getFloat() const;
+
+	/// Return the text inside as a Mat4
 	Mat4 getMat4() const;
 
+	/// Return the text inside as a Vec3
+	Vec3 getVec3() const;
+
+	/// Return the text inside as a Vec4
+	Vec4 getVec4() const;
+
 	/// Get a child element quietly
 	XmlElement getChildElementOptional(const char* name) const;
 

+ 26 - 3
include/anki/resource/Animation.h

@@ -6,6 +6,11 @@
 
 namespace anki {
 
+class XmlElement;
+
+/// @addtogroup Resources
+/// @{
+
 /// A keyframe 
 template<typename T> 
 class Key
@@ -13,7 +18,7 @@ class Key
 	friend class Animation;
 
 public:
-	F64 getTime() const
+	F32 getTime() const
 	{
 		return time;
 	}
@@ -24,7 +29,7 @@ public:
 	}
 
 private:
-	F64 time;
+	F32 time;
 	T value;
 };
 
@@ -41,20 +46,38 @@ struct AnimationChannel
 	Vector<Key<F32>> cameraFovs;
 };
 
-/// Animation
+/// Animation consists of keyframe data
 class Animation
 {
 public:
 	void load(const char* filename);
 
+	/// @name Accessors
+	/// @{
 	const Vector<AnimationChannel>& getChannels() const
 	{
 		return channels;
 	}
 
+	F32 getDuration() const
+	{
+		return duration;
+	}
+
+	F32 getStartingTime() const
+	{
+		return startingTime;
+	}
+	/// @}
+
 private:
 	Vector<AnimationChannel> channels;
+	F32 duration;
+	F32 startingTime;
+
+	void loadInternal(const XmlElement& el);
 };
+/// @}
 
 } // end namespace anki
 

+ 80 - 0
src/misc/Xml.cpp

@@ -21,6 +21,19 @@ I XmlElement::getInt() const
 	return std::stoi(txt);
 }
 
+//==============================================================================
+F64 XmlElement::getFloat() const
+{
+	check();
+	const char* txt = getText();
+	if(txt == nullptr)
+	{
+		throw ANKI_EXCEPTION(std::string("Failed to return float. Element: ")
+			+ el->Value());
+	}
+	return std::stof(txt);
+}
+
 //==============================================================================
 Mat4 XmlElement::getMat4() const
 {
@@ -55,6 +68,73 @@ Mat4 XmlElement::getMat4() const
 	return out;
 }
 
+//==============================================================================
+Vec3 XmlElement::getVec3() const
+{
+	check();
+
+	const char* txt = getText();
+	if(txt == nullptr)
+	{
+		throw ANKI_EXCEPTION("Failed to return Vec3");
+	}
+
+	StringList list = StringList::splitString(txt, ' ');
+	if(list.size() != 3)
+	{
+		throw ANKI_EXCEPTION("Expecting 3 elements for Vec3");
+	}
+
+	Vec3 out;
+
+	try
+	{
+		for(U i = 0; i < 3; i++)
+		{
+			out[i] = std::stof(list[i]);
+		}
+	}
+	catch(const std::exception& e)
+	{
+		throw ANKI_EXCEPTION("Found non-float element for Vec3");
+	}
+
+	return out;
+}
+//==============================================================================
+Vec4 XmlElement::getVec4() const
+{
+	check();
+
+	const char* txt = getText();
+	if(txt == nullptr)
+	{
+		throw ANKI_EXCEPTION("Failed to return Vec4");
+	}
+
+	StringList list = StringList::splitString(txt, ' ');
+	if(list.size() != 4)
+	{
+		throw ANKI_EXCEPTION("Expecting 3 elements for Vec4");
+	}
+
+	Vec4 out;
+
+	try
+	{
+		for(U i = 0; i < 4; i++)
+		{
+			out[i] = std::stof(list[i]);
+		}
+	}
+	catch(const std::exception& e)
+	{
+		throw ANKI_EXCEPTION("Found non-float element for Vec4");
+	}
+
+	return out;
+}
+
 //==============================================================================
 XmlElement XmlElement::getChildElementOptional(const char* name) const
 {

+ 16 - 16
src/renderer/Is.cpp

@@ -438,22 +438,22 @@ void Is::initInternal(const RendererInitializer& initializer)
 	//
 	std::stringstream pps;
 
-	pps << "#define TILES_X_COUNT " << TILES_X_COUNT << "\n"
-		<< "#define TILES_Y_COUNT " << TILES_Y_COUNT << "\n"
-		<< "#define TILES_COUNT " << TILES_COUNT << "\n"
-		<< "#define RENDERER_WIDTH " << r->getWidth() << "\n"
-		<< "#define RENDERER_HEIGHT " << r->getHeight() << "\n"
-		<< "#define MAX_POINT_LIGHTS_PER_TILE " << (U32)maxPointLightsPerTile
-		<< "\n"
-		<< "#define MAX_SPOT_LIGHTS_PER_TILE " << (U32)maxSpotLightsPerTile
-		<< "\n"
-		<< "#define MAX_SPOT_TEX_LIGHTS_PER_TILE " 
-		<< (U32)maxSpotTexLightsPerTile << "\n"
-		<< "#define MAX_POINT_LIGHTS " << (U32)maxPointLights << "\n"
-		<< "#define MAX_SPOT_LIGHTS " << (U32)maxSpotLights << "\n"
-		<< "#define MAX_SPOT_TEX_LIGHTS " << (U32)maxSpotTexLights << "\n"
-		<< "#define GROUND_LIGHT " << groundLightEnabled << "\n"
-		<< "#define USE_MRT " << r->getUseMrt() << "\n";
+	pps << "\n#define TILES_X_COUNT " << TILES_X_COUNT
+		<< "\n#define TILES_Y_COUNT " << TILES_Y_COUNT 
+		<< "\n#define TILES_COUNT " << TILES_COUNT
+		<< "\n#define RENDERER_WIDTH " << r->getWidth()
+		<< "\n#define RENDERER_HEIGHT " << r->getHeight()
+		<< "\n#define MAX_POINT_LIGHTS_PER_TILE " << (U32)maxPointLightsPerTile
+		<< "\n#define MAX_SPOT_LIGHTS_PER_TILE " << (U32)maxSpotLightsPerTile
+		<< "\n#define MAX_SPOT_TEX_LIGHTS_PER_TILE " 
+		<< (U32)maxSpotTexLightsPerTile
+		<< "\n#define MAX_POINT_LIGHTS " << (U32)maxPointLights
+		<< "\n#define MAX_SPOT_LIGHTS " << (U32)maxSpotLights 
+		<< "\n#define MAX_SPOT_TEX_LIGHTS " << (U32)maxSpotTexLights
+		<< "\n#define GROUND_LIGHT " << groundLightEnabled
+		<< "\n#define USE_MRT " << r->getUseMrt()
+		<< "\n#define TILES_BLOCK_BINDING " << TILES_BLOCK_BINDING
+		<< "\n";
 
 	if(sm.getPcfEnabled())
 	{

+ 97 - 0
src/resource/Animation.cpp

@@ -1,11 +1,108 @@
 #include "anki/resource/Animation.h"
+#include "anki/misc/Xml.h"
+#include "anki/util/Exception.h"
 
 namespace anki {
 
 //==============================================================================
 void Animation::load(const char* filename)
 {
+	try
+	{
+		XmlDocument doc;
+		doc.loadFile(filename);
+		loadInternal(doc.getChildElement("animation"));
+	}
+	catch(const std::exception& e)
+	{
+		throw ANKI_EXCEPTION("Animation loading failed: " + filename) << e;
+	}
+}
+
+//==============================================================================
+void Animation::loadInternal(const XmlElement& el)
+{
+	// <duration>
+	duration = el.getChildElement("duration").getFloat();
+
+	// <channels>
+	XmlElement channelsEl = el.getChildElement("channels");
+	XmlElement chEl = channelsEl.getChildElement("channel");
+
+	do
+	{
+		channels.push_back(AnimationChannel());	
+		AnimationChannel& ch = channels.back();
+
+		// <name>
+		ch.name = chEl.getChildElement("name").getText();
+
+		// <positionKeys>
+		XmlElement keysEl = chEl.getChildElement("positionsKeys");
+		XmlElement keyEl = keysEl.getChildElement("key");
+		do
+		{
+			Key<Vec3> key;
+
+			// <time>
+			key.time = keyEl.getFloat();
+
+			// <value>
+			key.value = keyEl.getVec3();
+
+			// push_back
+			ch.positions.push_back(key);
+
+			// Move to next
+			keyEl = keyEl.getNextSiblingElement("key");
+		} while(keyEl);
+
+		// <rotationKeys>
+		keysEl = chEl.getChildElement("rotationKeys");
+		keyEl = keysEl.getChildElement("key");
+		do
+		{
+			Key<Quat> key;
+
+			// <time>
+			key.time = keyEl.getFloat();
+
+			// <value>
+			key.value = Quat(keyEl.getVec4());
+
+			// push_back
+			ch.rotations.push_back(key);
+
+			// Move to next
+			keyEl = keyEl.getNextSiblingElement("key");
+		} while(keyEl);
+
+		// <scalingKeys>
+		keysEl = chEl.getChildElementOptional("scalingKeys");
+		if(keysEl)
+		{
+			XmlElement keyEl = keysEl.getChildElement("key");
+			do
+			{
+				Key<F32> key;
+
+				// <time>
+				key.time = keyEl.getFloat();
+
+				// <value>
+				key.value = keyEl.getFloat();
+
+				// push_back
+				ch.scales.push_back(key);
+
+				// Move to next
+				keyEl = keyEl.getNextSiblingElement("key");
+			} while(keyEl);
+		}
 
+		// Move to next channel
+		chEl = chEl.getNextSiblingElement("channel");
+	} while(chEl);
 }
 
 } // end namespace anki

+ 1 - 1
src/scene/SceneGraph.cpp

@@ -297,7 +297,7 @@ void SceneGraph::load(const char* filename)
 	}
 	catch(const std::exception& e)
 	{
-		throw ANKI_EXCEPTION("Sceno loading failed") << e;
+		throw ANKI_EXCEPTION("Scene loading failed") << e;
 	}
 }
 

+ 2 - 2
testapp/Main.cpp

@@ -260,7 +260,7 @@ void init()
 
 	(void)sponzaModel;
 #endif
-	scene.load("maps/sponza/master.scene");
+	scene.load("maps/sponza/master.ankiscene");
 
 	//initPhysics();
 
@@ -476,7 +476,7 @@ void mainLoop()
 
 		// Sleep
 		//
-#if 0
+#if 1
 		timer.stop();
 		if(timer.getElapsedTime() < AppSingleton::get().getTimerTick())
 		{

+ 17 - 8
tools/scene/Main.cpp

@@ -667,7 +667,7 @@ static void exportAnimation(
 	std::fstream file;
 	LOGI("Exporting animation %s\n", name.c_str());
 
-	file.open(config.outDir + name + ".anim", std::ios::out);
+	file.open(config.outDir + name + ".ankianim", std::ios::out);
 
 	file << xmlHeader << "\n";
 	file << "<animation>\n";
@@ -695,22 +695,23 @@ static void exportAnimation(
 				<< "<value>" << key.mValue[0] << " " 
 				<< key.mValue[1] << " " << key.mValue[2] << "</value></key>\n";
 		}
-		file << "</positionKeys>\n";
+		file << "\t\t\t</positionKeys>\n";
 
 		// Rotations
-		file << "\t\t\t<rotationKeys>";
+		file << "\t\t\t<rotationKeys>\n";
 		for(uint32_t j = 0; j < nAnim.mNumRotationKeys; j++)
 		{
 			const aiQuatKey& key = nAnim.mRotationKeys[j];
 
 			file << "\t\t\t\t<key><time>" << key.mTime << "</time>"
-				<< "<value>" << key.mValue.y << " " << key.mValue.z << " "
+				<< "<value>" << key.mValue.x << " " << key.mValue.y 
+				<< " " << key.mValue.z << " "
 				<< key.mValue.w << "</value></key>\n";
 		}
-		file << "</rotationKeys>\n";
+		file << "\t\t\t</rotationKeys>\n";
 
 		// Scale
-		file << "\t\t\t<scalingKeys>";
+		file << "\t\t\t<scalingKeys>\n";
 		for(uint32_t j = 0; j < nAnim.mNumScalingKeys; j++)
 		{
 			const aiVectorKey& key = nAnim.mScalingKeys[j];
@@ -721,7 +722,7 @@ static void exportAnimation(
 				<< ((key.mValue[0] + key.mValue[1] + key.mValue[2]) / 3.0)
 				<< "</value></key>\n";
 		}
-		file << "</scalingKeys>\n";
+		file << "\t\t\t</scalingKeys>\n";
 
 		file << "\t\t</channel>\n";
 	}
@@ -778,7 +779,7 @@ static void exportScene(const aiScene& scene)
 	// Open scene file
 	//
 	std::ofstream file;
-	file.open(config.outDir + "master.scene");
+	file.open(config.outDir + "master.ankiscene");
 
 	file << xmlHeader << "\n"
 		<< "<scene>\n";
@@ -980,6 +981,14 @@ static void exportScene(const aiScene& scene)
 	file << "</model>\n";
 #endif
 
+	//
+	// Animations
+	//
+	for(unsigned i = 0; i < scene.mNumAnimations; i++)
+	{
+		exportAnimation(*scene.mAnimations[i], i, scene);
+	}
+
 	file << "</scene>\n";
 
 	LOGI("Done exporting scene!\n");