Skip to content

Commit be8c2a2

Browse files
authored
DotScene: add Node Animation support & definition in DTD (#1974)
1 parent 6f4e9d9 commit be8c2a2

File tree

3 files changed

+152
-2
lines changed

3 files changed

+152
-2
lines changed

PlugIns/DotScene/include/OgreDotSceneLoader.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ class _OgreDotScenePluginExport DotSceneLoader : public Ogre::SceneLoader
5151
void processParticleSystem(pugi::xml_node& XMLNode, Ogre::SceneNode* pParent);
5252
void processBillboardSet(pugi::xml_node& XMLNode, Ogre::SceneNode* pParent);
5353
void processPlane(pugi::xml_node& XMLNode, Ogre::SceneNode* pParent);
54+
void processNodeAnimations(pugi::xml_node& XMLNode, Ogre::SceneNode* pParent);
55+
void processNodeAnimation(pugi::xml_node& XMLNode, Ogre::SceneNode* pParent);
56+
void processKeyframe(pugi::xml_node& XMLNode, Ogre::NodeAnimationTrack* pTrack);
5457

5558
void processFog(pugi::xml_node& XMLNode);
5659
void processSkyBox(pugi::xml_node& XMLNode);

PlugIns/DotScene/misc/dotscene.dtd

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

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

25-
<!ELEMENT node (position?, rotation?, scale?, lookTarget?, trackTarget?, userData?, node*, entity*, light*, camera*, particleSystem*, billboardSet*, plane*)>
25+
<!ELEMENT node (position?, rotation?, scale?, lookTarget?, trackTarget?, userData?, animations?, node*, entity*, light*, camera*, particleSystem*, billboardSet*, plane*)>
2626
<!ATTLIST node
2727
name CDATA #IMPLIED
2828
id ID #IMPLIED
@@ -43,7 +43,7 @@
4343
type (point | directional | spot ) "point"
4444
visible (true | false) "true"
4545
castShadows (true | false) "true"
46-
powerScale CDATA "1.0"
46+
powerScale CDATA "1.0"
4747
>
4848

4949
<!ELEMENT camera (clipping?, userData?)>
@@ -274,3 +274,22 @@
274274
type ( bool | float | int | str ) "str"
275275
data CDATA #REQUIRED
276276
>
277+
278+
<!-- https://www.w3schools.com/xml/xml_dtd_elements.asp -->
279+
280+
<!ELEMENT animations (animation+)>
281+
282+
<!ELEMENT animation (keyframe+)>
283+
<!ATTLIST animation
284+
name PCDATA #REQUIRED
285+
length PCDATA #REQUIRED
286+
enable (true | false) "false"
287+
loop (true | false) "false"
288+
interpolationMode (linear | spline) "linear"
289+
rotationInterpolationMode (linear | spherical) "linear"
290+
>
291+
292+
<!ELEMENT keyframe (translation?, rotation?, scale?)>
293+
<!ATTLIST keyframe
294+
time PCDATA #REQUIRED
295+
>

PlugIns/DotScene/src/DotSceneLoader.cpp

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ void DotSceneLoader::processScene(pugi::xml_node& XMLRoot)
206206

207207
void DotSceneLoader::processNodes(pugi::xml_node& XMLNode)
208208
{
209+
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Nodes...", LML_TRIVIAL);
210+
209211
// Process node (*)
210212
for (auto pElement : XMLNode.children("node"))
211213
{
@@ -241,6 +243,8 @@ void DotSceneLoader::processExternals(pugi::xml_node& XMLNode)
241243

242244
void DotSceneLoader::processEnvironment(pugi::xml_node& XMLNode)
243245
{
246+
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Environment...", LML_TRIVIAL);
247+
244248
// Process camera (?)
245249
if (auto pElement = XMLNode.child("camera"))
246250
processCamera(pElement);
@@ -273,6 +277,8 @@ void DotSceneLoader::processEnvironment(pugi::xml_node& XMLNode)
273277
void DotSceneLoader::processTerrainGroup(pugi::xml_node& XMLNode)
274278
{
275279
#ifdef OGRE_BUILD_COMPONENT_TERRAIN
280+
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Terrain Group...", LML_TRIVIAL);
281+
276282
Real worldSize = getAttribReal(XMLNode, "worldSize");
277283
int mapSize = StringConverter::parseInt(XMLNode.attribute("size").value());
278284
int compositeMapDistance = StringConverter::parseInt(XMLNode.attribute("tuningCompositeMapDistance").value());
@@ -311,6 +317,8 @@ void DotSceneLoader::processLight(pugi::xml_node& XMLNode, SceneNode* pParent)
311317
// Process attributes
312318
String name = getAttrib(XMLNode, "name");
313319

320+
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Light: " + name, LML_TRIVIAL);
321+
314322
// Create the light
315323
Light* pLight = mSceneMgr->createLight(name);
316324
if (pParent)
@@ -357,6 +365,9 @@ void DotSceneLoader::processCamera(pugi::xml_node& XMLNode, SceneNode* pParent)
357365
{
358366
// Process attributes
359367
String name = getAttrib(XMLNode, "name");
368+
369+
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Camera: " + name, LML_TRIVIAL);
370+
360371
// Real fov = getAttribReal(XMLNode, "fov", 45);
361372
Real aspectRatio = getAttribReal(XMLNode, "aspectRatio", 1.3333);
362373
String projectionType = getAttrib(XMLNode, "projectionType", "perspective");
@@ -403,6 +414,8 @@ void DotSceneLoader::processNode(pugi::xml_node& XMLNode, SceneNode* pParent)
403414
// Construct the node's name
404415
String name = getAttrib(XMLNode, "name");
405416

417+
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Node: " + name, LML_TRIVIAL);
418+
406419
// Create the scene node
407420
SceneNode* pNode;
408421
if (name.empty())
@@ -498,6 +511,10 @@ void DotSceneLoader::processNode(pugi::xml_node& XMLNode, SceneNode* pParent)
498511
// Process userDataReference (?)
499512
if (auto pElement = XMLNode.child("userData"))
500513
processUserData(pElement, pNode->getUserObjectBindings());
514+
515+
// Process node animations (?)
516+
if (auto pElement = XMLNode.child("animations"))
517+
processNodeAnimations(pElement, pNode);
501518
}
502519

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

527+
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Look Target, nodeName: " + nodeName, LML_TRIVIAL);
528+
510529
Node::TransformSpace relativeTo = Node::TS_PARENT;
511530
String sValue = getAttrib(XMLNode, "relativeTo");
512531
if (sValue == "local")
@@ -548,6 +567,8 @@ void DotSceneLoader::processTrackTarget(pugi::xml_node& XMLNode, SceneNode* pPar
548567
// Process attributes
549568
String nodeName = getAttrib(XMLNode, "nodeName");
550569

570+
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Track Target, nodeName: " + nodeName, LML_TRIVIAL);
571+
551572
// Process localDirection (?)
552573
Vector3 localDirection = Vector3::NEGATIVE_UNIT_Z;
553574
if (auto pElement = XMLNode.child("localDirection"))
@@ -574,6 +595,9 @@ void DotSceneLoader::processEntity(pugi::xml_node& XMLNode, SceneNode* pParent)
574595
{
575596
// Process attributes
576597
String name = getAttrib(XMLNode, "name");
598+
599+
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Entity: " + name, LML_TRIVIAL);
600+
577601
String meshFile = getAttrib(XMLNode, "meshFile");
578602
bool castShadows = getAttribBool(XMLNode, "castShadows", true);
579603

@@ -603,6 +627,9 @@ void DotSceneLoader::processParticleSystem(pugi::xml_node& XMLNode, SceneNode* p
603627
{
604628
// Process attributes
605629
String name = getAttrib(XMLNode, "name");
630+
631+
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Particle System: " + name, LML_TRIVIAL);
632+
606633
String templateName = getAttrib(XMLNode, "template");
607634

608635
if (templateName.empty())
@@ -628,6 +655,9 @@ void DotSceneLoader::processBillboardSet(pugi::xml_node& XMLNode, SceneNode* pPa
628655
void DotSceneLoader::processPlane(pugi::xml_node& XMLNode, SceneNode* pParent)
629656
{
630657
String name = getAttrib(XMLNode, "name");
658+
659+
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Plane: " + name, LML_TRIVIAL);
660+
631661
Real distance = getAttribReal(XMLNode, "distance");
632662
Real width = getAttribReal(XMLNode, "width");
633663
Real height = getAttribReal(XMLNode, "height");
@@ -654,6 +684,8 @@ void DotSceneLoader::processPlane(pugi::xml_node& XMLNode, SceneNode* pParent)
654684

655685
void DotSceneLoader::processFog(pugi::xml_node& XMLNode)
656686
{
687+
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Fog...", LML_TRIVIAL);
688+
657689
// Process attributes
658690
Real expDensity = getAttribReal(XMLNode, "density", 0.001);
659691
Real linearStart = getAttribReal(XMLNode, "start", 0.0);
@@ -684,6 +716,8 @@ void DotSceneLoader::processFog(pugi::xml_node& XMLNode)
684716

685717
void DotSceneLoader::processSkyBox(pugi::xml_node& XMLNode)
686718
{
719+
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing SkyBox...", LML_TRIVIAL);
720+
687721
// Process attributes
688722
String material = getAttrib(XMLNode, "material", "BaseWhite");
689723
Real distance = getAttribReal(XMLNode, "distance", 5000);
@@ -704,6 +738,8 @@ void DotSceneLoader::processSkyBox(pugi::xml_node& XMLNode)
704738

705739
void DotSceneLoader::processSkyDome(pugi::xml_node& XMLNode)
706740
{
741+
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing SkyDome...", LML_TRIVIAL);
742+
707743
// Process attributes
708744
String material = XMLNode.attribute("material").value();
709745
Real curvature = getAttribReal(XMLNode, "curvature", 10);
@@ -725,6 +761,8 @@ void DotSceneLoader::processSkyDome(pugi::xml_node& XMLNode)
725761

726762
void DotSceneLoader::processSkyPlane(pugi::xml_node& XMLNode)
727763
{
764+
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing SkyPlane...", LML_TRIVIAL);
765+
728766
// Process attributes
729767
String material = getAttrib(XMLNode, "material");
730768
Real planeX = getAttribReal(XMLNode, "planeX", 0);
@@ -789,6 +827,96 @@ void DotSceneLoader::processUserData(pugi::xml_node& XMLNode, UserObjectBindings
789827
}
790828
}
791829

830+
void DotSceneLoader::processNodeAnimations(pugi::xml_node& XMLNode, SceneNode* pParent)
831+
{
832+
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Node Animations for SceneNode: " + pParent->getName(), LML_TRIVIAL);
833+
834+
// Process node animations (*)
835+
for (auto pElement : XMLNode.children("animation"))
836+
{
837+
processNodeAnimation(pElement, pParent);
838+
}
839+
}
840+
841+
void DotSceneLoader::processNodeAnimation(pugi::xml_node& XMLNode, SceneNode* pParent)
842+
{
843+
// Process node animation (*)
844+
845+
// Construct the animation name
846+
String name = getAttrib(XMLNode, "name");
847+
848+
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Node Animation: " + name, LML_TRIVIAL);
849+
850+
Real length = getAttribReal(XMLNode, "length");
851+
852+
Animation* anim = mSceneMgr->createAnimation(name, length);
853+
854+
bool enable = getAttribBool(XMLNode, "enable", false);
855+
bool loop = getAttribBool(XMLNode, "loop", false);
856+
857+
String interpolationMode = getAttrib(XMLNode, "interpolationMode");
858+
859+
if (interpolationMode == "linear")
860+
anim->setInterpolationMode(Animation::IM_LINEAR);
861+
else if (interpolationMode == "spline")
862+
anim->setInterpolationMode(Animation::IM_SPLINE);
863+
else
864+
LogManager::getSingleton().logError("DotSceneLoader - Invalid interpolationMode: " + interpolationMode);
865+
866+
String rotationInterpolationMode = getAttrib(XMLNode, "rotationInterpolationMode");
867+
868+
if (rotationInterpolationMode == "linear")
869+
anim->setRotationInterpolationMode(Animation::RIM_LINEAR);
870+
else if (rotationInterpolationMode == "spherical")
871+
anim->setRotationInterpolationMode(Animation::RIM_SPHERICAL);
872+
else
873+
LogManager::getSingleton().logError("DotSceneLoader - Invalid rotationInterpolationMode: " + rotationInterpolationMode);
874+
875+
// create a track to animate the camera's node
876+
NodeAnimationTrack* track = anim->createNodeTrack(0, pParent);
877+
878+
// Process keyframes (*)
879+
for (auto pElement : XMLNode.children("keyframe"))
880+
{
881+
processKeyframe(pElement, track);
882+
}
883+
884+
// create a new animation state to track this
885+
auto animState = mSceneMgr->createAnimationState(name);
886+
animState->setEnabled(enable);
887+
animState->setLoop(loop);
888+
}
889+
890+
void DotSceneLoader::processKeyframe(pugi::xml_node& XMLNode, NodeAnimationTrack* pTrack)
891+
{
892+
// Process node animation keyframe (*)
893+
Real time = getAttribReal(XMLNode, "time");
894+
895+
LogManager::getSingleton().logMessage("[DotSceneLoader] Processing Keyframe: " + StringConverter::toString(time), LML_TRIVIAL);
896+
897+
auto keyframe = pTrack->createNodeKeyFrame(time);
898+
899+
// Process translation (?)
900+
if (auto pElement = XMLNode.child("position")) {
901+
Vector3 translation = parseVector3(pElement);
902+
keyframe->setTranslate(translation);
903+
}
904+
905+
// Process rotation (?)
906+
//Quaternion rotation = Quaternion::IDENTITY;
907+
if (auto pElement = XMLNode.child("rotation")) {
908+
Quaternion rotation = parseQuaternion(pElement);
909+
keyframe->setRotation(rotation);
910+
}
911+
912+
// Process scale (?)
913+
//Vector3 scale = parseVector3(XMLNode.child("scale"));
914+
if (auto pElement = XMLNode.child("scale")) {
915+
Vector3 scale = parseVector3(pElement);
916+
keyframe->setScale(scale);
917+
}
918+
}
919+
792920
const Ogre::String& DotScenePlugin::getName() const {
793921
static Ogre::String name = "DotScene Loader";
794922
return name;

0 commit comments

Comments
 (0)