Skip to content

Commit

Permalink
DotScene: add Node Animation support & definition in DTD (#1974)
Browse files Browse the repository at this point in the history
  • Loading branch information
sercero authored Apr 17, 2021
1 parent 6f4e9d9 commit be8c2a2
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 2 deletions.
3 changes: 3 additions & 0 deletions PlugIns/DotScene/include/OgreDotSceneLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ class _OgreDotScenePluginExport DotSceneLoader : public Ogre::SceneLoader
void processParticleSystem(pugi::xml_node& XMLNode, Ogre::SceneNode* pParent);
void processBillboardSet(pugi::xml_node& XMLNode, Ogre::SceneNode* pParent);
void processPlane(pugi::xml_node& XMLNode, Ogre::SceneNode* pParent);
void processNodeAnimations(pugi::xml_node& XMLNode, Ogre::SceneNode* pParent);
void processNodeAnimation(pugi::xml_node& XMLNode, Ogre::SceneNode* pParent);
void processKeyframe(pugi::xml_node& XMLNode, Ogre::NodeAnimationTrack* pTrack);

void processFog(pugi::xml_node& XMLNode);
void processSkyBox(pugi::xml_node& XMLNode);
Expand Down
23 changes: 21 additions & 2 deletions PlugIns/DotScene/misc/dotscene.dtd
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

<!ELEMENT nodes (node*, position?, rotation?, scale?)>

<!ELEMENT node (position?, rotation?, scale?, lookTarget?, trackTarget?, userData?, node*, entity*, light*, camera*, particleSystem*, billboardSet*, plane*)>
<!ELEMENT node (position?, rotation?, scale?, lookTarget?, trackTarget?, userData?, animations?, node*, entity*, light*, camera*, particleSystem*, billboardSet*, plane*)>
<!ATTLIST node
name CDATA #IMPLIED
id ID #IMPLIED
Expand All @@ -43,7 +43,7 @@
type (point | directional | spot ) "point"
visible (true | false) "true"
castShadows (true | false) "true"
powerScale CDATA "1.0"
powerScale CDATA "1.0"
>

<!ELEMENT camera (clipping?, userData?)>
Expand Down Expand Up @@ -274,3 +274,22 @@
type ( bool | float | int | str ) "str"
data CDATA #REQUIRED
>

<!-- https://www.w3schools.com/xml/xml_dtd_elements.asp -->

<!ELEMENT animations (animation+)>

<!ELEMENT animation (keyframe+)>
<!ATTLIST animation
name PCDATA #REQUIRED
length PCDATA #REQUIRED
enable (true | false) "false"
loop (true | false) "false"
interpolationMode (linear | spline) "linear"
rotationInterpolationMode (linear | spherical) "linear"
>

<!ELEMENT keyframe (translation?, rotation?, scale?)>
<!ATTLIST keyframe
time PCDATA #REQUIRED
>
128 changes: 128 additions & 0 deletions PlugIns/DotScene/src/DotSceneLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ void DotSceneLoader::processScene(pugi::xml_node& XMLRoot)

void DotSceneLoader::processNodes(pugi::xml_node& XMLNode)
{
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Nodes...", LML_TRIVIAL);

// Process node (*)
for (auto pElement : XMLNode.children("node"))
{
Expand Down Expand Up @@ -241,6 +243,8 @@ void DotSceneLoader::processExternals(pugi::xml_node& XMLNode)

void DotSceneLoader::processEnvironment(pugi::xml_node& XMLNode)
{
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Environment...", LML_TRIVIAL);

// Process camera (?)
if (auto pElement = XMLNode.child("camera"))
processCamera(pElement);
Expand Down Expand Up @@ -273,6 +277,8 @@ void DotSceneLoader::processEnvironment(pugi::xml_node& XMLNode)
void DotSceneLoader::processTerrainGroup(pugi::xml_node& XMLNode)
{
#ifdef OGRE_BUILD_COMPONENT_TERRAIN
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Terrain Group...", LML_TRIVIAL);

Real worldSize = getAttribReal(XMLNode, "worldSize");
int mapSize = StringConverter::parseInt(XMLNode.attribute("size").value());
int compositeMapDistance = StringConverter::parseInt(XMLNode.attribute("tuningCompositeMapDistance").value());
Expand Down Expand Up @@ -311,6 +317,8 @@ void DotSceneLoader::processLight(pugi::xml_node& XMLNode, SceneNode* pParent)
// Process attributes
String name = getAttrib(XMLNode, "name");

LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Light: " + name, LML_TRIVIAL);

// Create the light
Light* pLight = mSceneMgr->createLight(name);
if (pParent)
Expand Down Expand Up @@ -357,6 +365,9 @@ void DotSceneLoader::processCamera(pugi::xml_node& XMLNode, SceneNode* pParent)
{
// Process attributes
String name = getAttrib(XMLNode, "name");

LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Camera: " + name, LML_TRIVIAL);

// Real fov = getAttribReal(XMLNode, "fov", 45);
Real aspectRatio = getAttribReal(XMLNode, "aspectRatio", 1.3333);
String projectionType = getAttrib(XMLNode, "projectionType", "perspective");
Expand Down Expand Up @@ -403,6 +414,8 @@ void DotSceneLoader::processNode(pugi::xml_node& XMLNode, SceneNode* pParent)
// Construct the node's name
String name = getAttrib(XMLNode, "name");

LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Node: " + name, LML_TRIVIAL);

// Create the scene node
SceneNode* pNode;
if (name.empty())
Expand Down Expand Up @@ -498,6 +511,10 @@ void DotSceneLoader::processNode(pugi::xml_node& XMLNode, SceneNode* pParent)
// Process userDataReference (?)
if (auto pElement = XMLNode.child("userData"))
processUserData(pElement, pNode->getUserObjectBindings());

// Process node animations (?)
if (auto pElement = XMLNode.child("animations"))
processNodeAnimations(pElement, pNode);
}

void DotSceneLoader::processLookTarget(pugi::xml_node& XMLNode, SceneNode* pParent)
Expand All @@ -507,6 +524,8 @@ void DotSceneLoader::processLookTarget(pugi::xml_node& XMLNode, SceneNode* pPare
// Process attributes
String nodeName = getAttrib(XMLNode, "nodeName");

LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Look Target, nodeName: " + nodeName, LML_TRIVIAL);

Node::TransformSpace relativeTo = Node::TS_PARENT;
String sValue = getAttrib(XMLNode, "relativeTo");
if (sValue == "local")
Expand Down Expand Up @@ -548,6 +567,8 @@ void DotSceneLoader::processTrackTarget(pugi::xml_node& XMLNode, SceneNode* pPar
// Process attributes
String nodeName = getAttrib(XMLNode, "nodeName");

LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Track Target, nodeName: " + nodeName, LML_TRIVIAL);

// Process localDirection (?)
Vector3 localDirection = Vector3::NEGATIVE_UNIT_Z;
if (auto pElement = XMLNode.child("localDirection"))
Expand All @@ -574,6 +595,9 @@ void DotSceneLoader::processEntity(pugi::xml_node& XMLNode, SceneNode* pParent)
{
// Process attributes
String name = getAttrib(XMLNode, "name");

LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Entity: " + name, LML_TRIVIAL);

String meshFile = getAttrib(XMLNode, "meshFile");
bool castShadows = getAttribBool(XMLNode, "castShadows", true);

Expand Down Expand Up @@ -603,6 +627,9 @@ void DotSceneLoader::processParticleSystem(pugi::xml_node& XMLNode, SceneNode* p
{
// Process attributes
String name = getAttrib(XMLNode, "name");

LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Particle System: " + name, LML_TRIVIAL);

String templateName = getAttrib(XMLNode, "template");

if (templateName.empty())
Expand All @@ -628,6 +655,9 @@ void DotSceneLoader::processBillboardSet(pugi::xml_node& XMLNode, SceneNode* pPa
void DotSceneLoader::processPlane(pugi::xml_node& XMLNode, SceneNode* pParent)
{
String name = getAttrib(XMLNode, "name");

LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Plane: " + name, LML_TRIVIAL);

Real distance = getAttribReal(XMLNode, "distance");
Real width = getAttribReal(XMLNode, "width");
Real height = getAttribReal(XMLNode, "height");
Expand All @@ -654,6 +684,8 @@ void DotSceneLoader::processPlane(pugi::xml_node& XMLNode, SceneNode* pParent)

void DotSceneLoader::processFog(pugi::xml_node& XMLNode)
{
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Fog...", LML_TRIVIAL);

// Process attributes
Real expDensity = getAttribReal(XMLNode, "density", 0.001);
Real linearStart = getAttribReal(XMLNode, "start", 0.0);
Expand Down Expand Up @@ -684,6 +716,8 @@ void DotSceneLoader::processFog(pugi::xml_node& XMLNode)

void DotSceneLoader::processSkyBox(pugi::xml_node& XMLNode)
{
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing SkyBox...", LML_TRIVIAL);

// Process attributes
String material = getAttrib(XMLNode, "material", "BaseWhite");
Real distance = getAttribReal(XMLNode, "distance", 5000);
Expand All @@ -704,6 +738,8 @@ void DotSceneLoader::processSkyBox(pugi::xml_node& XMLNode)

void DotSceneLoader::processSkyDome(pugi::xml_node& XMLNode)
{
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing SkyDome...", LML_TRIVIAL);

// Process attributes
String material = XMLNode.attribute("material").value();
Real curvature = getAttribReal(XMLNode, "curvature", 10);
Expand All @@ -725,6 +761,8 @@ void DotSceneLoader::processSkyDome(pugi::xml_node& XMLNode)

void DotSceneLoader::processSkyPlane(pugi::xml_node& XMLNode)
{
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing SkyPlane...", LML_TRIVIAL);

// Process attributes
String material = getAttrib(XMLNode, "material");
Real planeX = getAttribReal(XMLNode, "planeX", 0);
Expand Down Expand Up @@ -789,6 +827,96 @@ void DotSceneLoader::processUserData(pugi::xml_node& XMLNode, UserObjectBindings
}
}

void DotSceneLoader::processNodeAnimations(pugi::xml_node& XMLNode, SceneNode* pParent)
{
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Node Animations for SceneNode: " + pParent->getName(), LML_TRIVIAL);

// Process node animations (*)
for (auto pElement : XMLNode.children("animation"))
{
processNodeAnimation(pElement, pParent);
}
}

void DotSceneLoader::processNodeAnimation(pugi::xml_node& XMLNode, SceneNode* pParent)
{
// Process node animation (*)

// Construct the animation name
String name = getAttrib(XMLNode, "name");

LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Node Animation: " + name, LML_TRIVIAL);

Real length = getAttribReal(XMLNode, "length");

Animation* anim = mSceneMgr->createAnimation(name, length);

bool enable = getAttribBool(XMLNode, "enable", false);
bool loop = getAttribBool(XMLNode, "loop", false);

String interpolationMode = getAttrib(XMLNode, "interpolationMode");

if (interpolationMode == "linear")
anim->setInterpolationMode(Animation::IM_LINEAR);
else if (interpolationMode == "spline")
anim->setInterpolationMode(Animation::IM_SPLINE);
else
LogManager::getSingleton().logError("DotSceneLoader - Invalid interpolationMode: " + interpolationMode);

String rotationInterpolationMode = getAttrib(XMLNode, "rotationInterpolationMode");

if (rotationInterpolationMode == "linear")
anim->setRotationInterpolationMode(Animation::RIM_LINEAR);
else if (rotationInterpolationMode == "spherical")
anim->setRotationInterpolationMode(Animation::RIM_SPHERICAL);
else
LogManager::getSingleton().logError("DotSceneLoader - Invalid rotationInterpolationMode: " + rotationInterpolationMode);

// create a track to animate the camera's node
NodeAnimationTrack* track = anim->createNodeTrack(0, pParent);

// Process keyframes (*)
for (auto pElement : XMLNode.children("keyframe"))
{
processKeyframe(pElement, track);
}

// create a new animation state to track this
auto animState = mSceneMgr->createAnimationState(name);
animState->setEnabled(enable);
animState->setLoop(loop);
}

void DotSceneLoader::processKeyframe(pugi::xml_node& XMLNode, NodeAnimationTrack* pTrack)
{
// Process node animation keyframe (*)
Real time = getAttribReal(XMLNode, "time");

LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Keyframe: " + StringConverter::toString(time), LML_TRIVIAL);

auto keyframe = pTrack->createNodeKeyFrame(time);

// Process translation (?)
if (auto pElement = XMLNode.child("position")) {
Vector3 translation = parseVector3(pElement);
keyframe->setTranslate(translation);
}

// Process rotation (?)
//Quaternion rotation = Quaternion::IDENTITY;
if (auto pElement = XMLNode.child("rotation")) {
Quaternion rotation = parseQuaternion(pElement);
keyframe->setRotation(rotation);
}

// Process scale (?)
//Vector3 scale = parseVector3(XMLNode.child("scale"));
if (auto pElement = XMLNode.child("scale")) {
Vector3 scale = parseVector3(pElement);
keyframe->setScale(scale);
}
}

const Ogre::String& DotScenePlugin::getName() const {
static Ogre::String name = "DotScene Loader";
return name;
Expand Down

0 comments on commit be8c2a2

Please sign in to comment.