Operating System: :Pop! OS (Ubuntu derivative):
Render System: :OpenGL 3+:
I modified the ninja tutorial (light, camera, and shadows) https://goo.gl/Lr7d4X to present the robot walking from the animation tutorial https://goo.gl/vRmqbW. This works with no surprises other than that the "Walk" animation for the robot doesn't seem to be properly triggered. The robot slides across the floor, but its legs don't move. I've seen a movie with the robot animation going https://goo.gl/2Z7qX1 so I figured there is something wrong with my program.
I thought I might inspect the "robot.mesh" file https://goo.gl/anrFgU, first to get a list of all the animations in it so I might try one of the others, and second to see if I could find a clue to the problem. That thought led me down a rabbit hole.
Amongst several other viewers and Blender plugins that all seem moribund for several years or didn't yield to a half-hour's attempt to build, I found DisplaySweet's Ogre-v2-mesh-viewer https://goo.gl/ExyJ34, which requires Qt5 (a download of 67 GB [sic]), and Ogre-v2. Which leads me to the first question:
Can Ogre-v2-1 and Ogre-1.11.1 coexist on the same machine?
That's a question at the bottom of the rabbit hole. At the top is the question:
Is there a quicker way to troubleshoot this app, and what might it be?
Fortunately, my app is short and I can paste it all, here.
Code: Select all
#include <exception>
#include <iostream>
#include <Ogre.h>
#include <OgreApplicationContext.h>
#include <OgreInput.h>
#include <OgreRTShaderSystem.h>
#include <OgreApplicationContext.h>
//#include <OgreWindowEventUtilities.h> // ?
//#include <OgreFrameListener.h> // ?
#include <OgreCameraMan.h>
#include <OgreWindowEventUtilities.h>
using namespace Ogre;
using namespace OgreBites;
class TheApp :
public ApplicationContext,
public WindowEventListener,
public InputListener
{
public:
std::deque<Vector3> mWaypoints;
SceneManager * mSceneMgr;
SceneNode * mCamNode;
Real mDistance;
Real mWalkSpeed;
Vector3 mDirection;
Vector3 mDestination;
AnimationState * mAnimationState;
Entity * mRobotEntity;
SceneNode * mRobotNode;
TheApp();
virtual ~TheApp();
void setup();
void frameRendered(const Ogre::FrameEvent& evt);
bool keyPressed(const KeyboardEvent& evt);
bool nextLocation();
void mkBaseAndRoot();
void mkCamAndViewport();
void mkLights() const;
void mkAmbientLight() const;
void mkSpotLight() const;
void mkDirectionalLight() const;
void mkPointLight() const;
void mkGroundPlane() const;
void mkGroundMarkers() const;
void mkKnot(Real x_, Real y_, Real z_) const;
};
TheApp::TheApp(): ApplicationContext("OgreTutorialApp"),
mSceneMgr(0),
mCamNode(0),
mDistance(0),
mWalkSpeed(70.0),
mDirection(Vector3::ZERO),
mDestination(Vector3::ZERO),
mAnimationState(0),
mRobotEntity(0),
mRobotNode(0) {}
TheApp::~TheApp() {}
void TheApp::setup()
{ mkBaseAndRoot();
mkCamAndViewport();
mkGroundMarkers();
mkGroundPlane();
mkLights();
mRobotEntity = mSceneMgr->createEntity("robot.mesh");
mRobotEntity->setCastShadows(true);
mRobotNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0, 0, 25.0));
mRobotNode->attachObject(mRobotEntity);
mWaypoints.emplace_back(550.0, 0, 50.0);
mWaypoints.emplace_back(-100.0, 0, -200.0);
mWaypoints.emplace_back(0, 0, 25.0);
mAnimationState = mRobotEntity->getAnimationState("Idle");
mAnimationState->setLoop(true);
mAnimationState->setEnabled(true);
}
void TheApp::mkGroundMarkers() const {
mkKnot(0.0, -10.0, -25.0);
mkKnot(550.0, -10.0, 50.0);
mkKnot(-100.0, -10.0, -200.0);
}
void TheApp::mkBaseAndRoot() {
ApplicationContext::setup();
addInputListener(this);
// get a pointer to the already created root
mSceneMgr = getRoot()->createSceneManager();
// register our scene with the RTSS
RTShader::ShaderGenerator* shadergen = RTShader::ShaderGenerator::getSingletonPtr();
shadergen->addSceneManager(mSceneMgr);
}
void TheApp::mkCamAndViewport() {
mCamNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
Camera* cam = mSceneMgr->createCamera("myCam");
cam->setNearClipDistance(5);
mCamNode->attachObject(cam);
// The old stuff
// camNode->setPosition(200, 300, 400);
// camNode->lookAt(Vector3(0, 0, 0), Node::TransformSpace::TS_WORLD);
mCamNode->setPosition(90.0, 280.0, 535.0);
mCamNode->pitch(Degree(-30.0));
mCamNode->yaw(Degree(-15.0));
Viewport* vp = getRenderWindow()->addViewport(cam);
vp->setBackgroundColour(ColourValue(0, 0, 0));
cam->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight()));
}
void TheApp::mkLights() const {
mkAmbientLight();
mkSpotLight();
mkDirectionalLight();
mkPointLight();
}
void TheApp::mkPointLight() const {
Light* pointLight = mSceneMgr->createLight("PointLight");
pointLight->setType(Light::LT_POINT);
pointLight->setDiffuseColour(0.3, 0.3, 0.3);
pointLight->setSpecularColour(0.3, 0.3, 0.3);
SceneNode* pointLightNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
pointLightNode->attachObject(pointLight);
pointLightNode->setPosition(Vector3(0, 150, 250));
}
void TheApp::mkDirectionalLight() const {
Light* directionalLight = mSceneMgr->createLight("DirectionalLight");
directionalLight->setType(Light::LT_DIRECTIONAL);
directionalLight->setDiffuseColour(ColourValue(0.4, 0, 0));
directionalLight->setSpecularColour(ColourValue(0.4, 0, 0));
SceneNode* directionalLightNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
directionalLightNode->attachObject(directionalLight);
directionalLightNode->setDirection(Vector3(0, -1, 1));
}
void TheApp::mkSpotLight() const {
Light* spotLight = mSceneMgr->createLight("SpotLight");
spotLight->setDiffuseColour(0, 0, 1.0);
spotLight->setSpecularColour(0, 0, 1.0);
spotLight->setType(Light::LT_SPOTLIGHT);
SceneNode* spotLightNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
spotLightNode->attachObject(spotLight);
spotLightNode->setDirection(-1, -1, 0);
spotLightNode->setPosition(Vector3(200, 200, 0));
spotLight->setSpotlightRange(Degree(35), Degree(50));
}
void TheApp::mkAmbientLight() const {
mSceneMgr->setAmbientLight(ColourValue(0.75, 0.75, 0.75));
mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_MODULATIVE);
}
void TheApp::mkGroundPlane() const {
Plane plane(Vector3::UNIT_Y, 0);
MeshManager::getSingleton().createPlane(
"ground",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
plane,
1500, 1500, 20, 20,
true,
1, 5, 5,
Vector3::UNIT_Z);
Entity* groundEntity = mSceneMgr->createEntity("ground");
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(groundEntity);
groundEntity->setCastShadows(false);
groundEntity->setMaterialName("Examples/Rockwall");
}
void TheApp::mkKnot(Real x_, Real y_, Real z_) const {
auto ent = mSceneMgr->createEntity("knot.mesh");
auto node = mSceneMgr->getRootSceneNode()->createChildSceneNode(
Vector3(x_, y_, z_));
node->attachObject(ent);
node->setScale(0.1, 0.1, 0.1);
node->setScale(0.25, 0.25, 0.25);
}
bool TheApp::nextLocation() {
if (mWaypoints.empty())
{ return false; }
mDestination = mWaypoints.front();
mWaypoints.pop_front();
mDirection = mDestination - mRobotNode->getPosition();
mDistance = mDirection.normalise();
return true;
}
void TheApp::frameRendered(
const Ogre::FrameEvent& evt) {
if(mDirection == Vector3::ZERO)
{ if (nextLocation())
{ mAnimationState = mRobotEntity->getAnimationState("Walk");
mAnimationState->setLoop(true);
mAnimationState->setEnabled(true);
} }
else
{ Real move = mWalkSpeed * evt.timeSinceLastFrame;
mDistance -= move;
if (mDistance <= 0.0)
{ mRobotNode->setPosition(mDestination);
mDirection = Vector3::ZERO;
if (nextLocation())
{ auto src = mRobotNode->getOrientation() * Vector3::UNIT_X;
if ((1.0 + src.dotProduct(mDirection)) < 0.0001)
{ mRobotNode->yaw(Degree(180)); }
else
{ auto quat = src.getRotationTo(mDirection);
mRobotNode->rotate(quat);
} }
else
{ mAnimationState = mRobotEntity->getAnimationState("Idle");
mAnimationState->setLoop(true);
mAnimationState->setEnabled(true);
} }
else
{ mRobotNode->translate(move * mDirection);
} } }
bool TheApp::keyPressed(const KeyboardEvent& evt) {
if (evt.keysym.sym == SDLK_ESCAPE)
{ getRoot()->queueEndRendering(); }
return true;
}
int main(int argc, char **argv) {
try
{
TheApp app;
app.initApp();
app.getRoot()->startRendering();
app.closeApp();
}
catch (const std::exception& e)
{
std::cerr << "Error occurred during execution: " << e.what() << '\n';
return 1;
}
return 0;
}