init
This commit is contained in:
+134
@@ -0,0 +1,134 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsCGenericStimulatorApplication.h"
|
||||
|
||||
#include "../log/ovkCLogListenerFileBuffered.h"
|
||||
|
||||
#include "../ovamsCCommandStartStop.h"
|
||||
#include "../ovamsCCommandStimulatorControl.h"
|
||||
#include "../ovamsCCommandReceiveTarget.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
#if !((CEGUI_VERSION_MAJOR > 0) || (CEGUI_VERSION_MINOR >= 8))
|
||||
namespace CEGUI
|
||||
{
|
||||
typedef CEGUI::UVector2 USize;
|
||||
};
|
||||
#endif
|
||||
|
||||
bool CGenericStimulatorApplication::setup(Kernel::IKernelContext* poKernelContext)
|
||||
{
|
||||
CApplication::setup(poKernelContext);
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << " * CGenericStimulatorApplication::setup()\n";
|
||||
Kernel::IConfigurationManager* configManager = &(m_kernelCtx->getConfigurationManager());
|
||||
configManager->addConfigurationFromFile(m_ScenarioDir + "/appconf/generic-configuration.conf");
|
||||
std::cout << m_ScenarioDir << "/appconf/generic-configuration.conf" << "\n";
|
||||
|
||||
|
||||
poKernelContext->getLogManager().activate(Kernel::LogLevel_First, Kernel::LogLevel_Last, true);
|
||||
|
||||
Kernel::ILogListener* logListenerFileBuffered = new Kernel::CLogListenerFileBuffered(*poKernelContext, "ssvep-stimulator",
|
||||
configManager->expand(
|
||||
"${SSVEP_UserDataFolder}/log-[$core{date}-$core{time}].log"));
|
||||
poKernelContext->getLogManager().addListener(logListenerFileBuffered);
|
||||
|
||||
|
||||
CGenericStimulatorFlickeringObject::initialize(this);
|
||||
|
||||
// paint targets
|
||||
|
||||
const size_t nTarget = size_t(configManager->expandAsUInteger("${SSVEP_TargetCount}"));
|
||||
|
||||
for (size_t i = 0; i < nTarget; ++i) { this->addObject(CGenericStimulatorFlickeringObject::createGenericFlickeringObject(i)); }
|
||||
|
||||
// draw the initial text
|
||||
m_instructionsReady = m_guiWindowManager->createWindow("TaharezLook/StaticImage", "InstructionsReady");
|
||||
m_instructionsReady->setPosition(CEGUI::UVector2(cegui_reldim(0.0F), cegui_reldim(0.0F)));
|
||||
m_instructionsReady->setSize(CEGUI::USize(CEGUI::UDim(0.0F, 640.F), CEGUI::UDim(0.0F, 32.F)));
|
||||
|
||||
#if (CEGUI_VERSION_MAJOR > 0) || (CEGUI_VERSION_MINOR >= 8)
|
||||
m_sheet->addChild(m_instructionsReady);
|
||||
CEGUI::ImageManager::getSingleton().addFromImageFile("InstructionsReady", "InstructionText-Start.png");
|
||||
m_instructionsReady->setProperty("Image", "InstructionsReady");
|
||||
#else
|
||||
m_sheet->addChildWindow(m_instructionsReady);
|
||||
CEGUI::ImagesetManager::getSingleton().createFromImageFile("InstructionsReady", "InstructionText-Start.png");
|
||||
m_instructionsReady->setProperty("Image", "set:InstructionsReady image:full_image");
|
||||
#endif
|
||||
|
||||
m_instructionsReady->setProperty("FrameEnabled", "False");
|
||||
m_instructionsReady->setProperty("BackgroundEnabled", "False");
|
||||
m_instructionsReady->setVisible(true);
|
||||
|
||||
|
||||
// initialize commands
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ addCommand(new CCommandStartStop(...)\n";
|
||||
this->addCommand(new CCommandStartStop(this));
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ addCommand(new CCommandStimulatorControl(...))\n";
|
||||
this->addCommand(new CCommandStimulatorControl(this));
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ addCommand(new CC(...))\n";
|
||||
this->addCommand(new CCommandReceiveTarget(this));
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << " * CTrainerApplication::setup() completed successfully\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CGenericStimulatorApplication::processFrame(const size_t frame)
|
||||
{
|
||||
CApplication::processFrame(frame);
|
||||
if (!m_active) { return; }
|
||||
for (size_t i = 0; i < m_oObjects.size(); ++i) { m_oObjects[i]->processFrame(); }
|
||||
}
|
||||
|
||||
void CGenericStimulatorApplication::addObject(CGenericStimulatorFlickeringObject* obj)
|
||||
{
|
||||
m_oObjects.push_back(obj);
|
||||
obj->setVisible(true);
|
||||
}
|
||||
|
||||
void CGenericStimulatorApplication::setTarget(const int target)
|
||||
{
|
||||
const size_t currentTime = int(time(nullptr) - m_ttStartTime);
|
||||
(*m_logManager) << Kernel::LogLevel_Info << currentTime << " > Target set to " << target << "\n";
|
||||
|
||||
for (int i = 0; i < int(m_oObjects.size()); ++i) { m_oObjects[i]->setTarget(target == i); }
|
||||
}
|
||||
|
||||
void CGenericStimulatorApplication::startExperiment()
|
||||
{
|
||||
CApplication::startExperiment();
|
||||
|
||||
m_ttStartTime = time(nullptr);
|
||||
|
||||
this->stopFlickering();
|
||||
m_instructionsReady->setVisible(false);
|
||||
}
|
||||
|
||||
void CGenericStimulatorApplication::startFlickering()
|
||||
{
|
||||
const size_t currentTime = size_t(time(nullptr) - m_ttStartTime);
|
||||
(*m_logManager) << Kernel::LogLevel_Info << currentTime << " > Starting Visual Stimulation\n";
|
||||
m_active = true;
|
||||
}
|
||||
|
||||
void CGenericStimulatorApplication::stopFlickering()
|
||||
{
|
||||
const size_t currentTime = size_t(time(nullptr) - m_ttStartTime);
|
||||
(*m_logManager) << Kernel::LogLevel_Info << currentTime << " > Stopping Visual Stimulation\n";
|
||||
m_active = false;
|
||||
|
||||
for (size_t i = 0; i < m_oObjects.size(); ++i) { m_oObjects[i]->setVisible(true); }
|
||||
|
||||
this->setTarget(-1);
|
||||
}
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <CEGUI.h>
|
||||
|
||||
#include "../ovamsCApplication.h"
|
||||
#include "ovamsCGenericStimulatorFlickeringObject.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CGenericStimulatorApplication final : public CApplication
|
||||
{
|
||||
public:
|
||||
explicit CGenericStimulatorApplication(const CString& sScenarioDir) : CApplication(sScenarioDir) {}
|
||||
~CGenericStimulatorApplication() override {}
|
||||
|
||||
bool setup(Kernel::IKernelContext* poKernelContext) override;
|
||||
void setTarget(int target) override;
|
||||
|
||||
void startExperiment() override;
|
||||
void startFlickering() override;
|
||||
void stopFlickering() override;
|
||||
|
||||
|
||||
private:
|
||||
bool m_active = false;
|
||||
void processFrame(const size_t frame) override;
|
||||
void addObject(CGenericStimulatorFlickeringObject* obj);
|
||||
|
||||
std::vector<CGenericStimulatorFlickeringObject*> m_oObjects;
|
||||
|
||||
time_t m_ttStartTime = 0;
|
||||
|
||||
CEGUI::Window* m_instructionsReady = nullptr;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsCGenericStimulatorFlickeringObject.h"
|
||||
#include "ovamsCGenericStimulatorApplication.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
Ogre::SceneNode* CGenericStimulatorFlickeringObject::m_parentNode = nullptr;
|
||||
CBasicPainter* CGenericStimulatorFlickeringObject::m_painter = nullptr;
|
||||
Ogre::ColourValue CGenericStimulatorFlickeringObject::m_lightColor = Ogre::ColourValue(1.0F, 1.0F, 1.0F);
|
||||
Ogre::ColourValue CGenericStimulatorFlickeringObject::m_darkColor = Ogre::ColourValue(0.0F, 0.0F, 0.0F);
|
||||
float CGenericStimulatorFlickeringObject::m_targetWidth = 0.2F;
|
||||
float CGenericStimulatorFlickeringObject::m_targetHeight = 0.2F;
|
||||
CGenericStimulatorApplication* CGenericStimulatorFlickeringObject::m_application = nullptr;
|
||||
|
||||
void CGenericStimulatorFlickeringObject::initialize(CGenericStimulatorApplication* application)
|
||||
{
|
||||
m_application = application;
|
||||
Kernel::IConfigurationManager* configManager = application->getConfigurationManager();
|
||||
|
||||
m_painter = application->getPainter();
|
||||
m_parentNode = application->getSceneNode();
|
||||
|
||||
m_targetWidth = float(configManager->expandAsFloat("${SSVEP_TargetWidth}"));
|
||||
m_targetHeight = float(configManager->expandAsFloat("${SSVEP_TargetHeight}"));
|
||||
|
||||
m_lightColor = Ogre::ColourValue(float(configManager->expandAsFloat("${SSVEP_TargetLightColourRed}")),
|
||||
float(configManager->expandAsFloat("${SSVEP_TargetLightColourGreen}")),
|
||||
float(configManager->expandAsFloat("${SSVEP_TargetLightColourBlue}")));
|
||||
|
||||
m_darkColor = Ogre::ColourValue(float(configManager->expandAsFloat("${SSVEP_TargetDarkColourRed}")),
|
||||
float(configManager->expandAsFloat("${SSVEP_TargetDarkColourGreen}")),
|
||||
float(configManager->expandAsFloat("${SSVEP_TargetDarkColourBlue}")));
|
||||
|
||||
m_application->getLogManager() << Kernel::LogLevel_Info << "Target Size : (" << m_targetWidth << ", " << m_targetHeight << ")\n";
|
||||
//m_application->getLogManager() << Kernel::LogLevel_Info << "Target Default Colour : Light = " << Ogre::String(m_lightColor) << ", Dark = " << Ogre::String(m_darkColor) << "\n";
|
||||
}
|
||||
|
||||
CGenericStimulatorFlickeringObject* CGenericStimulatorFlickeringObject::createGenericFlickeringObject(const size_t targetId)
|
||||
{
|
||||
Kernel::IConfigurationManager* configManager = m_application->getConfigurationManager();
|
||||
|
||||
if (m_painter != nullptr)
|
||||
{
|
||||
const Ogre::ColourValue currentTargetColour = (targetId == 0) ? m_darkColor : m_lightColor;
|
||||
|
||||
const CIdentifier id = configManager->createConfigurationToken("SSVEPTarget_Id", std::to_string(targetId).c_str());
|
||||
|
||||
const float targetX = float(configManager->expandAsFloat("${SSVEP_Target_X_${SSVEPTarget_Id}}"));
|
||||
const float targetY = float(configManager->expandAsFloat("${SSVEP_Target_Y_${SSVEPTarget_Id}}"));
|
||||
const CString material = CString(configManager->expand("${SSVEP_Target_Material_${SSVEPTarget_Id}}"));
|
||||
const size_t stimulationPattern = size_t((*(m_application->getFrequencies()))[targetId]);
|
||||
|
||||
m_application->getLogManager() << Kernel::LogLevel_Info << "Target (" << targetId << ") : Position = ("
|
||||
<< targetX << ", " << targetY << "), Texture = " << material << "\n";
|
||||
|
||||
configManager->releaseConfigurationToken(id);
|
||||
|
||||
return new CGenericStimulatorFlickeringObject(targetX, targetY, currentTargetColour, material, stimulationPattern);
|
||||
}
|
||||
m_application->getLogManager() << Kernel::LogLevel_Fatal << "TrainerTarget object was not properly initialized\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CGenericStimulatorFlickeringObject::CGenericStimulatorFlickeringObject(const float posX, const float posY, const Ogre::ColourValue color,
|
||||
const CString& material, const size_t stimulationPattern)
|
||||
: CSSVEPFlickeringObject(nullptr, stimulationPattern)
|
||||
{
|
||||
Ogre::MovableObject* litObject;
|
||||
Ogre::MovableObject* darkObject;
|
||||
|
||||
m_elementNode = m_parentNode->createChildSceneNode();
|
||||
m_objectNode = m_elementNode->createChildSceneNode();
|
||||
Ogre::SceneNode* pointerNode = m_elementNode->createChildSceneNode();
|
||||
|
||||
const Ogre::RealRect rectangle(posX - m_targetWidth / 2, posY + m_targetHeight / 2, posX + m_targetWidth / 2, posY - m_targetHeight / 2);
|
||||
|
||||
if (strcmp(material.toASCIIString(), "default") == 0)
|
||||
{
|
||||
litObject = m_painter->paintRectangle(rectangle, color);
|
||||
darkObject = m_painter->paintRectangle(rectangle, m_darkColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
litObject = m_painter->paintTexturedRectangle(rectangle, std::string("GenericSurface/").append(material));
|
||||
darkObject = m_painter->paintTexturedRectangle(rectangle, std::string("GenericSurface/").append(material).append("-dark"));
|
||||
}
|
||||
|
||||
m_objectNode->attachObject(litObject);
|
||||
litObject->setVisible(true);
|
||||
|
||||
m_objectNode->attachObject(darkObject);
|
||||
darkObject->setVisible(false);
|
||||
|
||||
m_pointer = m_painter->paintTriangle(Ogre::Vector2(posX - 0.05F, posY + m_targetHeight), Ogre::Vector2(posX, posY + m_targetHeight - 0.05F),
|
||||
Ogre::Vector2(posX + 0.05F, posY + m_targetHeight), Ogre::ColourValue(1, 1, 0));
|
||||
|
||||
pointerNode->attachObject(m_pointer);
|
||||
m_pointer->setVisible(false);
|
||||
}
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
#include <Ogre.h>
|
||||
|
||||
#include "../ovamsCSSVEPFlickeringObject.h"
|
||||
#include "../ovamsCBasicPainter.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CGenericStimulatorApplication;
|
||||
|
||||
class CGenericStimulatorFlickeringObject final : public CSSVEPFlickeringObject
|
||||
{
|
||||
public:
|
||||
static CGenericStimulatorFlickeringObject* createGenericFlickeringObject(size_t targetId);
|
||||
static void initialize(CGenericStimulatorApplication* application);
|
||||
|
||||
static void connectToNode(Ogre::SceneNode* /*sceneNode*/) { }
|
||||
void setTarget(const bool isTarget) const { m_pointer->setVisible(isTarget); }
|
||||
bool isTarget() const { return m_pointer->getVisible(); }
|
||||
|
||||
private:
|
||||
static CGenericStimulatorApplication* m_application;
|
||||
static Ogre::SceneNode* m_parentNode;
|
||||
static CBasicPainter* m_painter;
|
||||
static float m_targetWidth;
|
||||
static float m_targetHeight;
|
||||
static Ogre::ColourValue m_lightColor;
|
||||
static Ogre::ColourValue m_darkColor;
|
||||
|
||||
CGenericStimulatorFlickeringObject(float posX, float posY, Ogre::ColourValue color, const CString& material, size_t stimulationPattern);
|
||||
|
||||
|
||||
Ogre::SceneNode* m_elementNode = nullptr;
|
||||
Ogre::MovableObject* m_pointer = nullptr;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
+1285
File diff suppressed because it is too large
Load Diff
+130
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* @author Ogre
|
||||
* @note This code likely originates from the Ogre project
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Includes
|
||||
#include <OgreVector3.h>
|
||||
#include <OgreQuaternion.h>
|
||||
#include <vector>
|
||||
|
||||
#include "rapidxml.hpp"
|
||||
|
||||
// Forward declarations
|
||||
namespace Ogre {
|
||||
class SceneManager;
|
||||
class SceneNode;
|
||||
class TerrainGroup;
|
||||
class TerrainGlobalOptions;
|
||||
}
|
||||
|
||||
/*
|
||||
namespace Forests
|
||||
{
|
||||
class PagedGeometry;
|
||||
class TreeLoader3D;
|
||||
class GrassLoader;
|
||||
class GrassLayer;
|
||||
}
|
||||
*/
|
||||
|
||||
class nodeProperty
|
||||
{
|
||||
public:
|
||||
Ogre::String m_NodeName;
|
||||
Ogre::String m_PropertyName;
|
||||
Ogre::String m_ValueName;
|
||||
Ogre::String m_TypeName;
|
||||
|
||||
nodeProperty(const Ogre::String& node, const Ogre::String& propertyName, const Ogre::String& value, const Ogre::String& type)
|
||||
: m_NodeName(node), m_PropertyName(propertyName), m_ValueName(value), m_TypeName(type) {}
|
||||
};
|
||||
|
||||
class DotSceneLoader
|
||||
{
|
||||
public:
|
||||
Ogre::TerrainGlobalOptions* m_TerrainGlobalOptions = nullptr;
|
||||
|
||||
DotSceneLoader();
|
||||
virtual ~DotSceneLoader();
|
||||
|
||||
void parseDotScene(const Ogre::String& sceneName, const Ogre::String& groupName, Ogre::SceneManager* yourSceneMgr,
|
||||
Ogre::SceneNode* pAttachNode = nullptr, const Ogre::String& prependNode = "");
|
||||
Ogre::String getProperty(const Ogre::String& ndNm, const Ogre::String& prop);
|
||||
|
||||
Ogre::String getResourceLocationBaseDir() const { return m_resLocationsBaseDir; }
|
||||
void setResourceLocationBaseDir(const Ogre::String& newBaseDir) { m_resLocationsBaseDir = newBaseDir; }
|
||||
|
||||
// Ogre::TerrainGroup* getTerrainGroup() { return mTerrainGroup; }
|
||||
|
||||
|
||||
std::vector<nodeProperty> m_NodeProperties;
|
||||
std::vector<Ogre::String> m_StaticObjects;
|
||||
std::vector<Ogre::String> m_DynamicObjects;
|
||||
// std::vector<Forests::PagedGeometry *> mPGHandles;
|
||||
// std::vector<Forests::TreeLoader3D *> mTreeHandles;
|
||||
// Forests::GrassLoader* mGrassLoaderHandle; // Handle to Forests::GrassLoader object
|
||||
std::vector<Ogre::ParticleSystem*> m_ParticleSystemList; // contains all the Particle Systems created
|
||||
|
||||
protected:
|
||||
void processScene(rapidxml::xml_node<>* xmlRoot);
|
||||
|
||||
void processNodes(rapidxml::xml_node<>* xmlNode);
|
||||
//! @todo Implement this
|
||||
static void processExternals(rapidxml::xml_node<>* /*xmlNode*/) { }
|
||||
void processEnvironment(rapidxml::xml_node<>* xmlNode) const;
|
||||
void processResourceLocations(rapidxml::xml_node<>* xmlNode) const;
|
||||
// void processTerrain(rapidxml::xml_node<>* xmlNode);
|
||||
// void processTerrainPage(rapidxml::xml_node<>* xmlNode);
|
||||
// void processGrassLayers(rapidxml::xml_node<>* xmlNode);
|
||||
// void processBlendmaps(rapidxml::xml_node<>* xmlNode);
|
||||
static void processUserDataReference(rapidxml::xml_node<>* xmlNode, Ogre::SceneNode* pParent = nullptr);
|
||||
static void processUserDataReference(rapidxml::xml_node<>* xmlNode, Ogre::Entity* pEntity);
|
||||
static void processOctree(rapidxml::xml_node<>* xmlNode);
|
||||
void processLight(rapidxml::xml_node<>* xmlNode, Ogre::SceneNode* parent = nullptr);
|
||||
void processCamera(rapidxml::xml_node<>* xmlNode, Ogre::SceneNode* pParent = nullptr) const;
|
||||
|
||||
void processNode(rapidxml::xml_node<>* xmlNode, Ogre::SceneNode* pParent = nullptr);
|
||||
void processLookTarget(rapidxml::xml_node<>* xmlNode, Ogre::SceneNode* parent) const;
|
||||
void processTrackTarget(rapidxml::xml_node<>* xmlNode, Ogre::SceneNode* pParent) const;
|
||||
void processEntity(rapidxml::xml_node<>* xmlNode, Ogre::SceneNode* pParent);
|
||||
static void processSubEntity(rapidxml::xml_node<>* xmlNode, Ogre::Entity* pEntity);
|
||||
void processParticleSystem(rapidxml::xml_node<>* xmlNode, Ogre::SceneNode* pParent);
|
||||
static void processBillboardSet(rapidxml::xml_node<>* xmlNode, Ogre::SceneNode* pParent);
|
||||
void processPlane(rapidxml::xml_node<>* xmlNode, Ogre::SceneNode* pParent) const;
|
||||
// void processPagedGeometry(rapidxml::xml_node<>* xmlNode, Ogre::SceneNode *pParent);
|
||||
|
||||
void processFog(rapidxml::xml_node<>* xmlNode) const;
|
||||
void processSkyBox(rapidxml::xml_node<>* xmlNode) const;
|
||||
void processSkyDome(rapidxml::xml_node<>* xmlNode) const;
|
||||
void processSkyPlane(rapidxml::xml_node<>* xmlNode) const;
|
||||
static void processClipping(rapidxml::xml_node<>* xmlNode);
|
||||
|
||||
static void processLightRange(rapidxml::xml_node<>* xmlNode, Ogre::Light* pLight);
|
||||
static void processLightAttenuation(rapidxml::xml_node<>* xmlNode, Ogre::Light* pLight);
|
||||
|
||||
static Ogre::String getAttrib(rapidxml::xml_node<>* xmlNode, const Ogre::String& attrib, const Ogre::String& defaultValue = "");
|
||||
static Ogre::Real getAttribReal(rapidxml::xml_node<>* xmlNode, const Ogre::String& attrib, Ogre::Real defaultValue = 0);
|
||||
static bool getAttribBool(rapidxml::xml_node<>* xmlNode, const Ogre::String& attrib, bool defaultValue = false);
|
||||
|
||||
static Ogre::Vector3 parseVector3(rapidxml::xml_node<>* xmlNode);
|
||||
static Ogre::Quaternion parseQuaternion(rapidxml::xml_node<>* xmlNode);
|
||||
static Ogre::ColourValue parseColour(rapidxml::xml_node<>* xmlNode);
|
||||
|
||||
|
||||
Ogre::SceneManager* m_sceneMgr = nullptr;
|
||||
Ogre::SceneNode* m_attachNode = nullptr;
|
||||
Ogre::String m_groupName;
|
||||
Ogre::String m_prependNode;
|
||||
// Ogre::TerrainGroup* mTerrainGroup = nullptr;
|
||||
Ogre::Vector3 m_terrainPosition;
|
||||
Ogre::Vector3 m_lightDirection;
|
||||
|
||||
// paged geometry related values
|
||||
// int mPGPageSize = 0;
|
||||
// int mPGDetailDistance = 0;
|
||||
// resource locations basedir
|
||||
Ogre::String m_resLocationsBaseDir;
|
||||
};
|
||||
+2587
File diff suppressed because it is too large
Load Diff
+202
@@ -0,0 +1,202 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsCCommandControlAnalog.h"
|
||||
#include "ovamsCImpactApplication.h"
|
||||
|
||||
#include <CEGUI.h>
|
||||
#if !((CEGUI_VERSION_MAJOR > 0) || (CEGUI_VERSION_MINOR >= 8))
|
||||
namespace CEGUI
|
||||
{
|
||||
typedef CEGUI::UVector2 USize;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
CCommandControlAnalog::CCommandControlAnalog(CImpactApplication* application, const bool takeControl)
|
||||
: ICommandVRPNAnalog(application, "SSVEP_VRPN_AnalogControl"), m_application(application), m_inControl(takeControl)
|
||||
{
|
||||
m_cmdStates[0] = 0;
|
||||
m_cmdStates[1] = 0;
|
||||
m_cmdStates[2] = 0;
|
||||
|
||||
m_maxFeedbackLevel[0] = 0;
|
||||
m_maxFeedbackLevel[1] = 0;
|
||||
m_maxFeedbackLevel[2] = 0;
|
||||
}
|
||||
|
||||
void CCommandControlAnalog::execute(const int channelCount, double* channel)
|
||||
{
|
||||
CImpactApplication* application = dynamic_cast<CImpactApplication*>(m_application);
|
||||
|
||||
if (m_inControl)
|
||||
{
|
||||
if (channelCount == 4)
|
||||
{
|
||||
// 'Modern' multiclass Mind Shooter assumed
|
||||
// The input class coding is assumed to contain the following probabilities,
|
||||
// 0 == 'focus on the middle of the ship')
|
||||
// 1 == focus tip
|
||||
// 2 == focus left
|
||||
// 3 == focus right
|
||||
const std::array<double, 4> probs = { channel[0], channel[1], channel[2], channel[3] };
|
||||
commandeerShip(probs);
|
||||
}
|
||||
else if (channelCount == 6)
|
||||
{
|
||||
// 'Classic' Mind Shooter. The input class probabilities are assumed as follows [class1in,class1Out,class2In,class2Out,class3In,class3Out]
|
||||
// Note that with this control scheme, class 0 will never be selected.
|
||||
std::array<double, 4> probs = { 0, channel[0], channel[2], channel[4] };
|
||||
const double sum = probs[1] + probs[2] + probs[3];
|
||||
|
||||
if (sum > 0)
|
||||
{
|
||||
probs[1] = probs[1] / sum;
|
||||
probs[2] = probs[2] / sum;
|
||||
probs[3] = probs[3] / sum;
|
||||
}
|
||||
commandeerShip(probs);
|
||||
}
|
||||
else
|
||||
{
|
||||
application->getLogManager() << Kernel::LogLevel_Error << "Incorrect analog VRPN input with " << channelCount
|
||||
<< " channels. Mind Shooter needs 4 or 6 channels.\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const int nChannels = 3;
|
||||
static std::array<int, nChannels> prevLevels = { 0, 0, 0 };
|
||||
|
||||
// Assume input is layered like [prob1,prob2,prob3,prob4]. First ignored for feedback (focus middle of ship).
|
||||
std::array<double, nChannels> feedback = { channel[1], channel[2], channel[3] };
|
||||
|
||||
std::array<int, nChannels> level = { 0, 0, 0 };
|
||||
|
||||
//std::cout << "feedback: ";
|
||||
for (int i = 0; i < nChannels; ++i)
|
||||
{
|
||||
if (feedback[i] < 0)
|
||||
{
|
||||
// Note: shouldn't happen, we're expecting positive numbers
|
||||
feedback[i] = 0;
|
||||
}
|
||||
|
||||
if (feedback[i] > m_maxFeedbackLevel[i]) { m_maxFeedbackLevel[i] += 0.1; }
|
||||
else
|
||||
{
|
||||
// Slowly decrease max over time in case it was due to artifact
|
||||
m_maxFeedbackLevel[i] *= 0.995;
|
||||
}
|
||||
|
||||
const double cLevel = (m_maxFeedbackLevel[i] > 0 ? (feedback[i] / m_maxFeedbackLevel[i]) : 0);
|
||||
|
||||
if (cLevel > 0.7) { level[i] = 3; }
|
||||
else if (cLevel > 0.3) { level[i] = 2; }
|
||||
else if (cLevel > 0.0) { level[i] = 1; }
|
||||
}
|
||||
|
||||
|
||||
if (level[0] != prevLevels[0] || level[1] != prevLevels[1] || level[2] != prevLevels[2])
|
||||
{
|
||||
application->getLogManager() << Kernel::LogLevel_Trace << "Feedback levels : " << level[0] << " " << level[1] << " " << level[2] << "\n";
|
||||
|
||||
prevLevels[0] = level[0];
|
||||
prevLevels[1] = level[1];
|
||||
prevLevels[2] = level[2];
|
||||
|
||||
application->getShip()->setFeedbackLevels(level[0], level[1], level[2]);
|
||||
}
|
||||
}
|
||||
|
||||
std::string stateToString(const CImpactShip::ETargetState ts)
|
||||
{
|
||||
if (ts == CImpactShip::TS_NORMAL) { return "N"; }
|
||||
if (ts == CImpactShip::TS_INHIBITED) { return "I"; }
|
||||
if (ts == CImpactShip::TS_OFF) { return "X"; }
|
||||
|
||||
return "-";
|
||||
}
|
||||
|
||||
// Expects 4 non-negative inputs
|
||||
void CCommandControlAnalog::commandeerShip(const std::array<double, 4>& probs)
|
||||
{
|
||||
m_cmdStates[0] = 0;
|
||||
m_cmdStates[1] = 0;
|
||||
m_cmdStates[2] = 0;
|
||||
|
||||
// If true, a NOP classification (class 0) will never be selected
|
||||
// const bool ignoreIdle = false;
|
||||
|
||||
// Find the strongest activation.
|
||||
size_t maxIdx = 0;
|
||||
double maxVal = -std::numeric_limits<double>::max();
|
||||
//double sum = 0;
|
||||
for (size_t i = 0; i < 4; ++i)
|
||||
{
|
||||
if (probs[i] >= maxVal)
|
||||
// && !(i==0 && ignoreIdle))
|
||||
{
|
||||
maxVal = probs[i];
|
||||
maxIdx = i;
|
||||
}
|
||||
//sum += probs[i];
|
||||
}
|
||||
//if (sum <= 0) { sum = 1; }
|
||||
|
||||
/*
|
||||
const bool paralyzed = false;
|
||||
if (l_bParalyzed)
|
||||
{
|
||||
// In this mode, the ship does not move but the prediction is displayed instead. May be useful for debugging.
|
||||
char text[512];
|
||||
sprintf(text, "Button %d", maxIdx);
|
||||
|
||||
double pos = (maxIdx / 3.0) * 0.85;
|
||||
|
||||
m_application->getInstructionWindow()->setSize(CEGUI::USize(CEGUI::UDim(0.10f, 0), CEGUI::UDim(0.10f, 0)));
|
||||
m_application->getInstructionWindow()->setPosition(CEGUI::UVector2(CEGUI::UDim(pos, 0), CEGUI::UDim(0.5f, 0)));
|
||||
m_application->getInstructionWindow()->setText(text);
|
||||
m_application->getInstructionWindow()->show();
|
||||
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
// In principle here we could do different things with the probabilities. If we predict just the
|
||||
// maximum, this can be expected to be identical to the Classifier Processor box label output,
|
||||
// hence no difference is expected between the two control schemes (discrete vs analog).
|
||||
// To make the two controls a bit different, the probabilities can be used to
|
||||
// modulate the strength of the ship movement.
|
||||
|
||||
// Modulating with the probabilities makes the movements a bit jittery
|
||||
// const double strength = maxVal / sum;
|
||||
|
||||
// This choice is smoother, but will make the behavior identical to discrete control
|
||||
const double strength = 1.0;
|
||||
|
||||
CImpactShip* ship = m_application->getShip();
|
||||
|
||||
if (maxIdx == NOTHING) { } // NOP
|
||||
else if (maxIdx == SHOOT && m_application->getShip()->getTargetState(0) != CImpactShip::TS_OFF)
|
||||
{
|
||||
m_cmdStates[0] = 1;
|
||||
ship->shoot();
|
||||
}
|
||||
else if (maxIdx == MOVE_LEFT && m_application->getShip()->getTargetState(1) != CImpactShip::TS_OFF)
|
||||
{
|
||||
m_cmdStates[1] = 1;
|
||||
ship->move(int(-6 * strength));
|
||||
}
|
||||
else if (maxIdx == MOVE_RIGHT && m_application->getShip()->getTargetState(2) != CImpactShip::TS_OFF)
|
||||
{
|
||||
m_cmdStates[2] = 1;
|
||||
ship->move(int(6 * strength));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/// Controls the ship movement by the continuous values from the classifier probabilities
|
||||
// If bTakeControl is false, feedback levels will still be provided by the analog control.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../ovamsICommandVRPNAnalog.h"
|
||||
#include <array>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CImpactApplication;
|
||||
|
||||
class CCommandControlAnalog final : public ICommandVRPNAnalog
|
||||
{
|
||||
enum EShipCommand { NOTHING = 0, SHOOT, MOVE_LEFT, MOVE_RIGHT };
|
||||
|
||||
public:
|
||||
CCommandControlAnalog(CImpactApplication* application, bool takeControl);
|
||||
~CCommandControlAnalog() override {}
|
||||
|
||||
void execute(int channelCount, double* channel) override;
|
||||
|
||||
private:
|
||||
CImpactApplication* m_application = nullptr;
|
||||
std::array<int, 3> m_cmdStates;
|
||||
std::array<double, 3> m_maxFeedbackLevel;
|
||||
|
||||
void commandeerShip(const std::array<double, 4>& probs);
|
||||
|
||||
bool m_inControl = false;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsCCommandControlDiscrete.h"
|
||||
#include "ovamsCImpactApplication.h"
|
||||
|
||||
#include <CEGUI.h>
|
||||
#if !((CEGUI_VERSION_MAJOR > 0) || (CEGUI_VERSION_MINOR >= 8))
|
||||
namespace CEGUI
|
||||
{
|
||||
typedef CEGUI::UVector2 USize;
|
||||
};
|
||||
#endif
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
CCommandControlDiscrete::CCommandControlDiscrete(CImpactApplication* application, const bool takeControl)
|
||||
: ICommandVRPNButton(application, "SSVEP_VRPN_DiscreteControl"), m_inControl(takeControl) {}
|
||||
|
||||
void CCommandControlDiscrete::execute(const int button, const int /*state*/)
|
||||
{
|
||||
if (!m_inControl) { return; }
|
||||
|
||||
CImpactApplication* application = dynamic_cast<CImpactApplication*>(m_application);
|
||||
|
||||
switch (button)
|
||||
{
|
||||
case 0:
|
||||
// Nop
|
||||
break;
|
||||
case 1:
|
||||
application->getShip()->shoot();
|
||||
break;
|
||||
case 2:
|
||||
application->getShip()->move(-6);
|
||||
break;
|
||||
case 3:
|
||||
application->getShip()->move(6);
|
||||
break;
|
||||
default:
|
||||
m_application->getLogManager() << Kernel::LogLevel_Warning << "Unhandled button " << button << " received\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/// Control ship movements with VRPN using label predictions from the classifier
|
||||
// If bTakeControl is false, the class will do nothing.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../ovamsICommandVRPNButton.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CImpactApplication;
|
||||
|
||||
class CCommandControlDiscrete final : public ICommandVRPNButton
|
||||
{
|
||||
public:
|
||||
CCommandControlDiscrete(CImpactApplication* application, bool takeControl);
|
||||
~CCommandControlDiscrete() override {}
|
||||
|
||||
void execute(const int button, const int state) override;
|
||||
protected:
|
||||
bool m_inControl = false;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsCCommandControlDiscreteOIS.h"
|
||||
#include "ovamsCImpactApplication.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
CCommandControlDiscreteOIS::CCommandControlDiscreteOIS(CImpactApplication* application)
|
||||
: ICommandOIS(application) {}
|
||||
|
||||
void CCommandControlDiscreteOIS::processFrame()
|
||||
{
|
||||
ICommandOIS::processFrame();
|
||||
|
||||
CImpactApplication* application = dynamic_cast<CImpactApplication*>(m_application);
|
||||
|
||||
if (m_keysPressed[OIS::KC_UP] || m_keysPressed[OIS::KC_DOWN]) { application->getShip()->shoot(); }
|
||||
if (m_keysPressed[OIS::KC_LEFT]) { application->getShip()->move(-6); }
|
||||
if (m_keysPressed[OIS::KC_RIGHT]) { application->getShip()->move(6); }
|
||||
}
|
||||
|
||||
void CCommandControlDiscreteOIS::receiveKeyPressedEvent(const OIS::KeyCode key)
|
||||
{
|
||||
if (key == OIS::KC_UP) { m_keysPressed[OIS::KC_UP] = true; }
|
||||
if (key == OIS::KC_DOWN) { m_keysPressed[OIS::KC_DOWN] = true; }
|
||||
if (key == OIS::KC_LEFT) { m_keysPressed[OIS::KC_LEFT] = true; }
|
||||
if (key == OIS::KC_RIGHT) { m_keysPressed[OIS::KC_RIGHT] = true; }
|
||||
}
|
||||
|
||||
void CCommandControlDiscreteOIS::receiveKeyReleasedEvent(const OIS::KeyCode key)
|
||||
{
|
||||
if (key == OIS::KC_UP) { m_keysPressed[OIS::KC_UP] = false; }
|
||||
if (key == OIS::KC_DOWN) { m_keysPressed[OIS::KC_DOWN] = false; }
|
||||
if (key == OIS::KC_LEFT) { m_keysPressed[OIS::KC_LEFT] = false; }
|
||||
if (key == OIS::KC_RIGHT) { m_keysPressed[OIS::KC_RIGHT] = false; }
|
||||
}
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/// Control ship movements with the keyboard
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "../ovamsICommandOIS.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CImpactApplication;
|
||||
|
||||
class CCommandControlDiscreteOIS final : public ICommandOIS
|
||||
{
|
||||
public:
|
||||
explicit CCommandControlDiscreteOIS(CImpactApplication* application);
|
||||
~CCommandControlDiscreteOIS() override {}
|
||||
|
||||
void processFrame() override;
|
||||
|
||||
void receiveKeyPressedEvent(OIS::KeyCode key) override;
|
||||
void receiveKeyReleasedEvent(OIS::KeyCode key) override;
|
||||
private:
|
||||
std::map<OIS::KeyCode, bool> m_keysPressed;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsCCommandImpactCustomTargetControl.h"
|
||||
#include "ovamsCImpactApplication.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
CCommandImpactCustomTargetControl::CCommandImpactCustomTargetControl(CImpactApplication* application)
|
||||
: ICommandVRPNButton(application, "SSVEP_VRPN_TargetControl")
|
||||
{
|
||||
m_vrpnServer = CVRPNServer::getInstance(application);
|
||||
m_vrpnServer->addButton("SSVEP_VRPN_TargetRequest", 1);
|
||||
}
|
||||
|
||||
void CCommandImpactCustomTargetControl::processFrame()
|
||||
{
|
||||
CImpactApplication* application = dynamic_cast<CImpactApplication*>(m_application);
|
||||
|
||||
ICommandVRPNButton::processFrame();
|
||||
|
||||
if (application->m_TargetRequest)
|
||||
{
|
||||
m_application->getLogManager() << Kernel::LogLevel_Info << "Requesting target\n";
|
||||
m_vrpnServer->changeButtonState("SSVEP_VRPN_TargetRequest", 0, 1);
|
||||
application->m_TargetRequest = false;
|
||||
}
|
||||
else { m_vrpnServer->changeButtonState("SSVEP_VRPN_TargetRequest", 0, 0); }
|
||||
|
||||
m_vrpnServer->processFrame();
|
||||
}
|
||||
|
||||
/// Add enemies on specified positions depending on the vrpn button triggered
|
||||
void CCommandImpactCustomTargetControl::execute(const int button, const int /*state*/)
|
||||
{
|
||||
m_application->getLogManager() << Kernel::LogLevel_Info << "Adding target, position : " << button << "\n";
|
||||
|
||||
CImpactApplication* application = dynamic_cast<CImpactApplication*>(m_application);
|
||||
|
||||
application->m_NextOrigin = 0.0;
|
||||
if (button == 0)
|
||||
{
|
||||
application->m_NextOrigin = -0.21F;
|
||||
application->addTarget(1);
|
||||
application->addTarget(6);
|
||||
application->addTarget(4);
|
||||
}
|
||||
else if (button == 1)
|
||||
{
|
||||
application->m_NextOrigin = 0.21F;
|
||||
application->addTarget(6);
|
||||
application->addTarget(1);
|
||||
application->addTarget(3);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
/// Used to insert enemy ships into the scene upon receiving a trigger
|
||||
#include "../ovamsICommandVRPNButton.h"
|
||||
#include "../ovamsCVRPNServer.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CImpactApplication;
|
||||
|
||||
class CCommandImpactCustomTargetControl final : public ICommandVRPNButton
|
||||
{
|
||||
public:
|
||||
explicit CCommandImpactCustomTargetControl(CImpactApplication* application);
|
||||
~CCommandImpactCustomTargetControl() override {}
|
||||
|
||||
void execute(const int button, const int state) override;
|
||||
void processFrame() override;
|
||||
|
||||
private:
|
||||
CVRPNServer* m_vrpnServer = nullptr;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsCCommandImpactTargetControl.h"
|
||||
#include "ovamsCImpactApplication.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
CCommandImpactTargetControl::CCommandImpactTargetControl(CImpactApplication* application)
|
||||
: ICommandVRPNButton(application, "SSVEP_VRPN_TargetControl")
|
||||
{
|
||||
m_vrpnServer = CVRPNServer::getInstance(application);
|
||||
m_vrpnServer->addButton("SSVEP_VRPN_TargetRequest", 1);
|
||||
}
|
||||
|
||||
void CCommandImpactTargetControl::processFrame()
|
||||
{
|
||||
CImpactApplication* application = dynamic_cast<CImpactApplication*>(m_application);
|
||||
|
||||
ICommandVRPNButton::processFrame();
|
||||
|
||||
if (application->m_TargetRequest)
|
||||
{
|
||||
m_application->getLogManager() << Kernel::LogLevel_Info << "Requesting target\n";
|
||||
m_vrpnServer->changeButtonState("SSVEP_VRPN_TargetRequest", 0, 1);
|
||||
application->m_TargetRequest = false;
|
||||
}
|
||||
else { m_vrpnServer->changeButtonState("SSVEP_VRPN_TargetRequest", 0, 0); }
|
||||
|
||||
m_vrpnServer->processFrame();
|
||||
}
|
||||
|
||||
void CCommandImpactTargetControl::execute(const int button, const int /*state*/)
|
||||
{
|
||||
m_application->getLogManager() << Kernel::LogLevel_Info << "Adding target, position : " << button << "\n";
|
||||
dynamic_cast<CImpactApplication*>(m_application)->addTarget(button);
|
||||
}
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "../ovamsICommandVRPNButton.h"
|
||||
#include "../ovamsCVRPNServer.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CImpactApplication;
|
||||
|
||||
class CCommandImpactTargetControl final : public ICommandVRPNButton
|
||||
{
|
||||
public:
|
||||
explicit CCommandImpactTargetControl(CImpactApplication* application);
|
||||
~CCommandImpactTargetControl() override {}
|
||||
|
||||
void execute(const int button, const int state) override;
|
||||
void processFrame() override;
|
||||
|
||||
private:
|
||||
CVRPNServer* m_vrpnServer = nullptr;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
+527
@@ -0,0 +1,527 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsCImpactApplication.h"
|
||||
|
||||
#include "openvibe/ov_all.h"
|
||||
|
||||
#include "../ovamsCCommandStartStop.h"
|
||||
#include "../ovamsCCommandStimulatorControl.h"
|
||||
#include "../ovamsCCommandCamera.h"
|
||||
#include "ovamsCCommandImpactTargetControl.h"
|
||||
#include "ovamsCCommandImpactCustomTargetControl.h"
|
||||
|
||||
#include "ovamsCCommandControlAnalog.h"
|
||||
#include "ovamsCCommandControlDiscrete.h"
|
||||
#include "ovamsCCommandControlDiscreteOIS.h"
|
||||
|
||||
#include "../log/ovkCLogListenerFileBuffered.h"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#define DIALOG_CYCLES_TO_REMOVE 180
|
||||
//#define NO_KEYBOARD
|
||||
//#define NO_VRPN
|
||||
|
||||
#if !((CEGUI_VERSION_MAJOR > 0) || (CEGUI_VERSION_MINOR >= 8))
|
||||
namespace CEGUI
|
||||
{
|
||||
typedef CEGUI::UVector2 USize;
|
||||
};
|
||||
#endif
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
CImpactApplication::CImpactApplication(const CString& scenarioDir, const CString& applicationSubtype)
|
||||
: CApplication(scenarioDir), m_applicationSubtype(applicationSubtype) {}
|
||||
|
||||
CImpactApplication::~CImpactApplication()
|
||||
{
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "- m_ship\n";
|
||||
delete m_ship;
|
||||
}
|
||||
|
||||
bool CImpactApplication::setup(Kernel::IKernelContext* kernelCtx)
|
||||
{
|
||||
if (!CApplication::setup(kernelCtx)) { return false; }
|
||||
|
||||
Kernel::IConfigurationManager* configurationManager = &(m_kernelCtx->getConfigurationManager());
|
||||
|
||||
if (m_applicationSubtype == CString("shooter"))
|
||||
{
|
||||
// A config file appended for the online session
|
||||
const CString configFile = m_ScenarioDir + "/appconf/shooter-configuration.conf";
|
||||
if (!configurationManager->addConfigurationFromFile(configFile))
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "Unable to open [" << configFile << "]. Has the shooter-controller.lua been run?\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const uint64_t logLevel = kernelCtx->getTypeManager().getEnumerationEntryValueFromName(
|
||||
OV_TypeId_LogLevel, configurationManager->expand("${SSVEP_LogLevel}"));
|
||||
this->getLogManager() << Kernel::LogLevel_Info << "Parsed loglevel is " << logLevel << "\n";
|
||||
if (logLevel != 0xffffffffffffffffULL) { kernelCtx->getLogManager().activate(Kernel::ELogLevel(logLevel), Kernel::LogLevel_Last, true); }
|
||||
|
||||
Kernel::ILogListener* logListenerFileBuffered = new Kernel::CLogListenerFileBuffered(*kernelCtx, "ssvep-mind-shooter-stimulator",
|
||||
configurationManager->expand(
|
||||
"${SSVEP_UserDataFolder}/mind-shooter-[$core{date}-$core{time}]-app.log"));
|
||||
kernelCtx->getLogManager().addListener(logListenerFileBuffered);
|
||||
|
||||
|
||||
m_sceneLoader = new DotSceneLoader();
|
||||
|
||||
std::stringstream enemyOrder;
|
||||
enemyOrder << configurationManager->expand("${SSVEP_EnemyOrder}");
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "Enemy order: " << configurationManager->expand("${SSVEP_EnemyOrder}") << "\n";
|
||||
|
||||
while (enemyOrder.peek() != EOF)
|
||||
{
|
||||
int nextType;
|
||||
enemyOrder >> nextType;
|
||||
m_enemyOrder.push(nextType);
|
||||
}
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "Adding Impact game resources\n";
|
||||
|
||||
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
CString(configurationManager->expand("${Path_Data}/applications/${SSVEP_MindShooterFolderName}/resources/impact")).toASCIIString(), "FileSystem",
|
||||
"SSVEPImpact", true);
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
CString(configurationManager->expand("${Path_Data}/applications/${SSVEP_MindShooterFolderName}/resources/impact/battleship")).toASCIIString(),
|
||||
"FileSystem", "SSVEPImpact");
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
CString(configurationManager->expand("${Path_Data}/applications/${SSVEP_MindShooterFolderName}/resources/impact/battleship-destroyed")).toASCIIString(),
|
||||
"FileSystem", "SSVEPImpact");
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
CString(configurationManager->expand("${Path_Data}/applications/${SSVEP_MindShooterFolderName}/resources/impact/enemy1")).toASCIIString(), "FileSystem",
|
||||
"SSVEPImpact");
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
CString(configurationManager->expand("${Path_Data}/applications/${SSVEP_MindShooterFolderName}/resources/impact/enemy2")).toASCIIString(), "FileSystem",
|
||||
"SSVEPImpact");
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
CString(configurationManager->expand("${Path_Data}/applications/${SSVEP_MindShooterFolderName}/resources/impact/enemy3")).toASCIIString(), "FileSystem",
|
||||
"SSVEPImpact");
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
CString(configurationManager->expand("${Path_Data}/applications/${SSVEP_MindShooterFolderName}/resources/impact/ships")).toASCIIString(), "FileSystem",
|
||||
"SSVEPImpact");
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
CString(configurationManager->expand("${Path_Data}/applications/${SSVEP_MindShooterFolderName}/resources/impact/starsky")).toASCIIString(),
|
||||
"FileSystem", "SSVEPImpact");
|
||||
Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("SSVEPImpact");
|
||||
|
||||
setupScene();
|
||||
|
||||
// Create the StarShip object
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ m_ship = new CStarShip(...)\n";
|
||||
m_ship = new CImpactShip(this, m_sceneNode, &m_frequencies);
|
||||
m_ship->activatePilotAssist(configurationManager->expandAsBoolean("${SSVEP_PilotAssist}"));
|
||||
m_ship->activateTargetLockdown(configurationManager->expandAsBoolean("${SSVEP_TargetLockdown}") && (m_applicationSubtype == CString("shooter")));
|
||||
m_ship->setFeedbackLevels(0, 0, 0);
|
||||
m_ship->activateFeedback(configurationManager->expandAsBoolean("${SSVEP_Feedback}") && (m_applicationSubtype == CString("shooter")));
|
||||
m_ship->activateFocusPoint(configurationManager->expandAsBoolean("${SSVEP_FocusPoint}"));
|
||||
|
||||
// Initialize the Target class
|
||||
|
||||
CImpactEnemyShip::initialize(this);
|
||||
|
||||
// create CEGUI windows
|
||||
m_instructionWindow = static_cast<CEGUI::Window*>(m_guiWindowManager->createWindow("TaharezLook/StaticText", "InstructionsWindow"));
|
||||
m_instructionWindow->setFont("BlueHighway-impact");
|
||||
m_statusWindow = static_cast<CEGUI::Window*>(m_guiWindowManager->createWindow("TaharezLook/StaticText", "StatusWindow"));
|
||||
m_statusWindow->setFont("BlueHighway-impact");
|
||||
m_statusWindow->hide();
|
||||
|
||||
#if (CEGUI_VERSION_MAJOR > 0) || (CEGUI_VERSION_MINOR >= 8)
|
||||
m_sheet->addChild(m_statusWindow);
|
||||
m_sheet->addChild(m_instructionWindow);
|
||||
#else
|
||||
m_sheet->addChildWindow(m_statusWindow);
|
||||
m_sheet->addChildWindow(m_instructionWindow);
|
||||
#endif
|
||||
|
||||
// Create commands
|
||||
|
||||
|
||||
#ifndef NO_KEYBOARD
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ addCommand(new CCommandCamera(...)\n";
|
||||
this->addCommand(new CCommandCamera(this));
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ addCommand(new CCommandShipControlOIS(...))\n";
|
||||
this->addCommand(new CCommandControlDiscreteOIS(this));
|
||||
#endif
|
||||
|
||||
#ifndef NO_VRPN
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ addCommand(new CCommandStartStop(...)\n";
|
||||
this->addCommand(new CCommandStartStop(this));
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ addCommand(new CCommandStimulatorControl(...))\n";
|
||||
this->addCommand(new CCommandStimulatorControl(this));
|
||||
|
||||
if (m_applicationSubtype == CString("trainer"))
|
||||
{
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ addCommand(new CCommandTargetControl(...)\n";
|
||||
this->addCommand(new CCommandImpactTargetControl(this));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (configurationManager->expandAsBoolean("${SSVEP_OneByOne}", false))
|
||||
{
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ addCommand(new CCommandTargetControl(...)\n";
|
||||
this->addCommand(new CCommandImpactTargetControl(this));
|
||||
}
|
||||
else
|
||||
{
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ addCommand(new CCommandImpactCustomTargetControl(...)\n";
|
||||
this->addCommand(new CCommandImpactCustomTargetControl(this));
|
||||
}
|
||||
|
||||
const bool analogControls = configurationManager->expandAsBoolean("${SSVEP_AnalogControl}", false);
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ addCommand(new CCommandControlAnalog(...))\n";
|
||||
this->addCommand(new CCommandControlAnalog(this, analogControls));
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ addCommand(new CCommandControlDiscrete(...))\n";
|
||||
this->addCommand(new CCommandControlDiscrete(this, !analogControls));
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "Analog control mode: " << (analogControls ? "true" : "false") << "\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_applicationSubtype == CString("shooter"))
|
||||
{
|
||||
m_gameState = IDLE_STARTED;
|
||||
m_ship->moveToPosition();
|
||||
|
||||
// draw the initial text
|
||||
m_instructionWindow->show();
|
||||
m_instructionWindow->setSize(CEGUI::USize(CEGUI::UDim(0.50F, 0), CEGUI::UDim(0.10F, 0)));
|
||||
m_instructionWindow->setPosition(CEGUI::UVector2(CEGUI::UDim(0.25F, 0), CEGUI::UDim(0.45F, 0)));
|
||||
// m_instructionWindow->setText("Appuyez sur la touche ESPACE pour commencer le jeu ...");
|
||||
m_instructionWindow->setText("Press SPACE to start the game ...");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_gameState = IDLE_TRAINING;
|
||||
|
||||
// draw the initial text
|
||||
m_instructionWindow->show();
|
||||
m_instructionWindow->setSize(CEGUI::USize(CEGUI::UDim(0.50F, 0), CEGUI::UDim(0.15F, 0)));
|
||||
m_instructionWindow->setPosition(CEGUI::UVector2(CEGUI::UDim(0.25F, 0), CEGUI::UDim(0.425F, 0)));
|
||||
// m_instructionWindow->setText("Le systeme a besoin de faire quelques reglages.\nVeuillez vous concentrer sur les cibles indiques par les instructions.\n\nAppuyez sur la touche ESPACE pour commencer l'entrainement ...");
|
||||
m_instructionWindow->setText(
|
||||
"The system needs to calibrate.\nPlease concentrate on the targets as instructed.\n\nPlease press SPACE to start the process ...");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CImpactApplication::setupScene() const
|
||||
{
|
||||
m_sceneManager->setAmbientLight(Ogre::ColourValue(1.0F, 1.0F, 1.0F));
|
||||
m_camera->setNearClipDistance(5);
|
||||
|
||||
m_camera->setPosition(Ogre::Vector3(0, 100, 0));
|
||||
m_camera->lookAt(0, 0, 1);
|
||||
m_camera->move(Ogre::Vector3(0, 0, 0));
|
||||
|
||||
Ogre::Light* pointLight = m_sceneManager->createLight();
|
||||
pointLight->setType(Ogre::Light::LT_POINT);
|
||||
pointLight->setPosition(Ogre::Vector3(0, 50, 0));
|
||||
|
||||
pointLight->setDiffuseColour(1.0F, 1.0F, 0.8F);
|
||||
pointLight->setSpecularColour(1.0F, 1.0F, 1.0F);
|
||||
|
||||
pointLight = m_sceneManager->createLight();
|
||||
pointLight->setType(Ogre::Light::LT_POINT);
|
||||
pointLight->setPosition(Ogre::Vector3(10, -10, 0));
|
||||
|
||||
pointLight->setDiffuseColour(0.5F, 0.0F, 0.0F);
|
||||
|
||||
m_sceneLoader->parseDotScene("v6.scene", "SSVEPImpact", m_sceneManager);
|
||||
m_sceneManager->getSceneNode("v6_sky")->showBoundingBox(true);
|
||||
m_sceneManager->getSceneNode("v6_sky")->scale(200.0, 300.0, 300.0);
|
||||
m_sceneManager->getSceneNode("v6_sky")->translate(0.0, 100.0, 0.0);
|
||||
}
|
||||
|
||||
bool CImpactApplication::enemyDestroyed(CImpactEnemyShip* es) { return es->isDestroyed(); }
|
||||
|
||||
|
||||
void CImpactApplication::processFrame(const size_t frame)
|
||||
{
|
||||
CApplication::processFrame(frame);
|
||||
//std::cout << m_window->getAverageFPS() << "\n";
|
||||
|
||||
m_ship->processFrame(frame);
|
||||
m_ship->setTargetLocked(false);
|
||||
m_sceneManager->getSceneNode("v6_sky")->pitch(Ogre::Radian(0.0001F));
|
||||
|
||||
if (m_gameState == STARTED)
|
||||
{
|
||||
size_t nEnemy = 0;
|
||||
bool targetWasDestroyed = false;
|
||||
|
||||
int currentEnemyPointValue = 0;
|
||||
|
||||
if (m_CurrEnemy != nullptr) { currentEnemyPointValue = m_CurrEnemy->getPointValue(); }
|
||||
|
||||
m_CurrEnemy = nullptr;
|
||||
for (auto it = m_targets.begin(); it != m_targets.end(); ++it)
|
||||
{
|
||||
(*it)->processFrame();
|
||||
|
||||
if ((*it)->isTouchable())
|
||||
{
|
||||
m_ship->evaluateHit(*it);
|
||||
|
||||
const Ogre::Vector2 enemyPosition = (*it)->getEnemyPosition();
|
||||
if (enemyPosition.x > m_ship->getNormalizedPosition().x - (*it)->getWidth() / 2.0
|
||||
&& enemyPosition.x < m_ship->getNormalizedPosition().x + (*it)->getWidth() / 2.0)
|
||||
{
|
||||
m_CurrEnemy = (*it);
|
||||
m_ship->setTargetLocked(true);
|
||||
|
||||
if (currentEnemyPointValue != m_CurrEnemy->getPointValue())
|
||||
{
|
||||
m_ship->activateCannonInhibitor(m_CurrEnemy->getPointValue() < 0);
|
||||
|
||||
logPrefix() << "Targeting enemy : point value = " << m_CurrEnemy->getPointValue() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ((*it)->getPointValue() > 0) { nEnemy++; }
|
||||
}
|
||||
|
||||
|
||||
if ((*it)->isDestroyed())
|
||||
{
|
||||
m_score += (*it)->getPointValue();
|
||||
delete *it;
|
||||
m_statusWindow->setText(("Score: " + std::to_string(m_score)).c_str());
|
||||
targetWasDestroyed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentEnemyPointValue != 0 && m_CurrEnemy == nullptr) { logPrefix() << "Focus on enemy lost\n"; }
|
||||
|
||||
if (targetWasDestroyed)
|
||||
{
|
||||
const size_t targetCount = m_targets.size();
|
||||
|
||||
m_targets.erase(std::remove_if(m_targets.begin(), m_targets.end(), enemyDestroyed), m_targets.end());
|
||||
|
||||
if (m_targets.empty() && m_targets.size() < targetCount) { m_TargetRequest = true; }
|
||||
|
||||
// if there are only friendly targets remaining make them leave
|
||||
if (targetCount > 0 && nEnemy == 0)
|
||||
{
|
||||
for (auto it = m_targets.begin(); it != m_targets.end(); ++it) { if (!(*it)->m_EnemyLeaving) { (*it)->m_LeaveCountdown = 0; } }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_dialogHideDelay > 0) { if (--m_dialogHideDelay == 0) { m_instructionWindow->hide(); } }
|
||||
}
|
||||
|
||||
int CImpactApplication::getNextTargetType()
|
||||
{
|
||||
if (!m_enemyOrder.empty())
|
||||
{
|
||||
const int iNtt = m_enemyOrder.front();
|
||||
m_enemyOrder.pop();
|
||||
|
||||
return iNtt;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CImpactApplication::addTarget(const size_t targetPosition)
|
||||
{
|
||||
float textSize = 0.25F;
|
||||
|
||||
logPrefix() << "Add Target : position = " << targetPosition << "\n";
|
||||
|
||||
getLogManager() << Kernel::LogLevel_Info << "Adding target on position " << targetPosition << "\n";
|
||||
|
||||
if (m_gameState == TRAINING)
|
||||
{
|
||||
switch (targetPosition)
|
||||
{
|
||||
case 0:
|
||||
textSize = 0.35F;
|
||||
// m_instructionWindow->setText("Regardez au milieu (MIDDLE) du vaisseau!");
|
||||
m_instructionWindow->setText("Focus on the MIDDLE of the ship");
|
||||
this->m_StimulusSender->sendStimulation(OVTK_StimulationId_Label_00);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
textSize = 0.35F;
|
||||
// m_instructionWindow->setText("Regardez le CANON (CANNON) du vaisseau pour tirer!");
|
||||
m_instructionWindow->setText("Focus on the CANNON to fire!");
|
||||
this->m_StimulusSender->sendStimulation(OVTK_StimulationId_Label_01);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
textSize = 0.50F;
|
||||
// m_instructionWindow->setText("Regardez l'aile GAUCHE (LEFT WING) du vaisseau pour de`placer le vaisseau vers la gauche");
|
||||
m_instructionWindow->setText("Focus on the LEFT WING to turn the ship to the left");
|
||||
this->m_StimulusSender->sendStimulation(OVTK_StimulationId_Label_02);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
textSize = 0.50F;
|
||||
// m_instructionWindow->setText("Regardez l'aile DROITE (RIGHT WING) du vaisseau pour de`placer le vaisseau vers la droite");
|
||||
m_instructionWindow->setText("Focus on the RIGHT WING to turn the ship to the right");
|
||||
this->m_StimulusSender->sendStimulation(OVTK_StimulationId_Label_03);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
m_instructionWindow->setSize(CEGUI::USize(CEGUI::UDim(textSize, 0), CEGUI::UDim(0.10F, 0)));
|
||||
m_instructionWindow->setPosition(CEGUI::UVector2(CEGUI::UDim((1.0F - textSize) / 2.0F, 0), CEGUI::UDim(0.45F, 0)));
|
||||
m_instructionWindow->show();
|
||||
m_dialogHideDelay = DIALOG_CYCLES_TO_REMOVE;
|
||||
}
|
||||
else if (m_gameState == STARTED)
|
||||
{
|
||||
// std::cout << (Ogre::Real( targetPosition ) - 3.5) / 7.0 * 100.0 << "\n";
|
||||
if (!m_enemyOrder.empty()) { m_ship->returnToMiddleAndWaitForFoe(targetPosition, m_NextOrigin); }
|
||||
else { getLogManager() << Kernel::LogLevel_Error << "No more enemy types\n"; }
|
||||
}
|
||||
}
|
||||
|
||||
void CImpactApplication::insertEnemy(const size_t targetPosition)
|
||||
{
|
||||
logPrefix() << "Creating Enemy : position = " << targetPosition << "\n";
|
||||
m_targets.push_back(CImpactEnemyShip::createTarget((Ogre::Real(targetPosition) - 3.5F) / 7.0F * 100.0F));
|
||||
}
|
||||
|
||||
void CImpactApplication::startFlickering()
|
||||
{
|
||||
m_instructionWindow->hide();
|
||||
const size_t currentTime = size_t(time(nullptr) - m_startTime);
|
||||
(*m_logManager) << Kernel::LogLevel_Info << currentTime << " > Starting Visual Stimulation\n";
|
||||
m_active = true;
|
||||
}
|
||||
|
||||
void CImpactApplication::stopFlickering()
|
||||
{
|
||||
const size_t currentTime = size_t(time(nullptr) - m_startTime);
|
||||
(*m_logManager) << Kernel::LogLevel_Info << currentTime << " > Stopping Visual Stimulation\n";
|
||||
m_active = false;
|
||||
m_ship->setAllTargetsVisibility(true);
|
||||
}
|
||||
|
||||
void CImpactApplication::startExperiment()
|
||||
{
|
||||
CApplication::startExperiment();
|
||||
|
||||
if (m_gameState == IDLE_TRAINING)
|
||||
{
|
||||
m_startTime = time(nullptr);
|
||||
m_instructionWindow->hide();
|
||||
m_dialogHideDelay = 0;
|
||||
m_gameState = TRAINING;
|
||||
|
||||
m_ship->activatePilotAssist(false);
|
||||
|
||||
logPrefix() << "Start Experiment : IDLE_TRAINING -> TRAINING\n";
|
||||
}
|
||||
else if (m_gameState == IDLE_STARTED)
|
||||
{
|
||||
m_TargetRequest = true;
|
||||
m_active = true;
|
||||
m_instructionWindow->hide();
|
||||
m_dialogHideDelay = 0;
|
||||
m_statusWindow->setPosition(CEGUI::UVector2(CEGUI::UDim(0.0F, 0), CEGUI::UDim(0.0F, 0)));
|
||||
m_statusWindow->setSize(CEGUI::USize(CEGUI::UDim(0.15F, 0), CEGUI::UDim(0.05F, 0)));
|
||||
m_statusWindow->setText("Score: 0");
|
||||
m_statusWindow->show();
|
||||
m_gameState = STARTED;
|
||||
|
||||
logPrefix() << "Start Experiment : IDLE_STARTED -> STARTED\n";
|
||||
}
|
||||
}
|
||||
|
||||
void CImpactApplication::stopExperiment()
|
||||
{
|
||||
if (m_gameState == TRAINING)
|
||||
{
|
||||
if (m_applicationSubtype == CString("trainer"))
|
||||
{
|
||||
logPrefix() << "Stop Experiment : exiting\n";
|
||||
this->exit();
|
||||
}
|
||||
else
|
||||
{
|
||||
const float textSize = 0.35F;
|
||||
// m_instructionWindow->setText("L'application va prendre quelque temps pour le calcul, veuillez patienter.\nLe jeu va commencer automatiquement une fois l'application est prete.");
|
||||
m_instructionWindow->setText(
|
||||
"The application needs some time to compute, please be patient.\nThe game starts automatically when the application is ready.");
|
||||
m_instructionWindow->setSize(CEGUI::USize(CEGUI::UDim(textSize, 0), CEGUI::UDim(0.10F, 0)));
|
||||
m_instructionWindow->setPosition(CEGUI::UVector2(CEGUI::UDim((1.0F - textSize) / 2.0F, 0), CEGUI::UDim(0.45F, 0)));
|
||||
m_instructionWindow->show();
|
||||
|
||||
logPrefix() << "Stop Experiment : Training Finished\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (m_gameState == STARTED)
|
||||
{
|
||||
const float textSize = 0.45F;
|
||||
m_instructionWindow->setText(("Bravo!\nYou have obtained " + std::to_string(m_score) + " points!\nPress ESC to close the program").c_str());
|
||||
m_instructionWindow->setSize(CEGUI::USize(CEGUI::UDim(textSize, 0), CEGUI::UDim(0.10F, 0)));
|
||||
m_instructionWindow->setPosition(CEGUI::UVector2(CEGUI::UDim((1.0F - textSize) / 2.0F, 0), CEGUI::UDim(0.45F, 0)));
|
||||
m_instructionWindow->show();
|
||||
m_active = false;
|
||||
m_ship->setAllTargetsVisibility(true);
|
||||
|
||||
logPrefix() << "Stop Experiment : Game Ended\n";
|
||||
}
|
||||
}
|
||||
|
||||
void CImpactApplication::debugAction1()
|
||||
{
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "Debug Action 1 triggered\n";
|
||||
this->startExperiment();
|
||||
m_ship->activatePilotAssist(true);
|
||||
}
|
||||
|
||||
void CImpactApplication::debugAction2()
|
||||
{
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "Debug Action 2 triggered\n";
|
||||
|
||||
//if (m_TargetRequest && m_enemyOrder.size() > 2)
|
||||
{
|
||||
this->addTarget(1);
|
||||
this->addTarget(6);
|
||||
this->addTarget(4);
|
||||
m_TargetRequest = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CImpactApplication::debugAction3()
|
||||
{
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "Debug Action 3 triggered\n";
|
||||
|
||||
m_TargetRequest = true;
|
||||
}
|
||||
|
||||
void CImpactApplication::debugAction4()
|
||||
{
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "Debug Action 4 triggered\n";
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "You (X: " << m_ship->getPosition().x << ", Y: " << m_ship->getPosition().y << ")\n";
|
||||
|
||||
if (!m_targets.empty())
|
||||
{
|
||||
const Ogre::Vector2 enemyPosition = m_targets[0]->getEnemyPosition();
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "Him (X: " << enemyPosition.x << ", Y: " << enemyPosition.y << ")\n";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
#include "dotscene/DotSceneLoader.h"
|
||||
|
||||
#include "../ovamsCApplication.h"
|
||||
#include "ovamsCImpactEnemyShip.h"
|
||||
#include "ovamsCImpactShip.h"
|
||||
#include <array>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CImpactApplication final : public CApplication
|
||||
{
|
||||
public:
|
||||
enum EGameState { BOOTING, IDLE_TRAINING, TRAINING, IDLE_STARTED, STARTED };
|
||||
|
||||
struct SStimulatorState
|
||||
{
|
||||
float ship_position;
|
||||
std::array<double, 3> feedback_level;
|
||||
int ship_direction;
|
||||
bool shooting;
|
||||
};
|
||||
|
||||
struct SGameState
|
||||
{
|
||||
int movements_right;
|
||||
int movements_left;
|
||||
int shoots_fired;
|
||||
};
|
||||
|
||||
CImpactApplication(const CString& scenarioDir, const CString& applicationSubtype);
|
||||
~CImpactApplication() override;
|
||||
|
||||
bool setup(Kernel::IKernelContext* kernelCtx) override;
|
||||
|
||||
CImpactShip* getShip() const { return m_ship; }
|
||||
bool isActive() const { return m_active; }
|
||||
|
||||
void startExperiment() override;
|
||||
void stopExperiment() override;
|
||||
void startFlickering() override;
|
||||
void stopFlickering() override;
|
||||
|
||||
void debugAction1() override;
|
||||
void debugAction2() override;
|
||||
void debugAction3() override;
|
||||
void debugAction4() override;
|
||||
|
||||
int getNextTargetType();
|
||||
void addTarget(size_t targetPosition);
|
||||
|
||||
void insertEnemy(size_t targetPosition);
|
||||
CImpactEnemyShip* getCurrentEnemy() const { return m_CurrEnemy; }
|
||||
CString getSubtype() const { return m_applicationSubtype; }
|
||||
EGameState getState() const { return m_gameState; }
|
||||
DotSceneLoader* getSceneLoader() const { return m_sceneLoader; }
|
||||
CEGUI::Window* getInstructionWindow() const { return m_instructionWindow; }
|
||||
|
||||
CImpactEnemyShip* m_CurrEnemy = nullptr;
|
||||
bool m_TargetRequest = false;
|
||||
Ogre::Real m_NextOrigin = 0.0;
|
||||
|
||||
private:
|
||||
void setupScene() const;
|
||||
void processFrame(const size_t frame) override;
|
||||
static bool enemyDestroyed(CImpactEnemyShip* /*es*/);
|
||||
|
||||
|
||||
CString m_applicationSubtype;
|
||||
EGameState m_gameState = BOOTING;
|
||||
|
||||
std::queue<int> m_enemyOrder;
|
||||
|
||||
bool m_active = false;
|
||||
|
||||
time_t m_startTime;
|
||||
|
||||
DotSceneLoader* m_sceneLoader = nullptr;
|
||||
CEGUI::Window* m_statusWindow = nullptr;
|
||||
CEGUI::Window* m_instructionWindow = nullptr;
|
||||
size_t m_dialogHideDelay = 0;
|
||||
|
||||
CImpactShip* m_ship = nullptr;
|
||||
std::vector<CImpactEnemyShip*> m_targets;
|
||||
int m_score = 0;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
+258
@@ -0,0 +1,258 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsCImpactEnemyShip.h"
|
||||
#include "ovamsCImpactApplication.h"
|
||||
|
||||
#define IMPACTSHIP_SIZE 0.2f
|
||||
#define SCREEN_RATIO ( 16.0f / 9.0f )
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
CImpactApplication* CImpactEnemyShip::m_application = nullptr;
|
||||
Ogre::SceneNode* CImpactEnemyShip::m_parentNode = nullptr;
|
||||
CBasicPainter* CImpactEnemyShip::m_painter = nullptr;
|
||||
int CImpactEnemyShip::m_nCurrentExplosion = 0;
|
||||
|
||||
void CImpactEnemyShip::initialize(CImpactApplication* application)
|
||||
{
|
||||
m_application = application;
|
||||
m_painter = m_application->getPainter();
|
||||
m_parentNode = m_application->getSceneNode();
|
||||
}
|
||||
|
||||
CImpactEnemyShip* CImpactEnemyShip::createTarget(const Ogre::Real position)
|
||||
{
|
||||
if (m_application == nullptr)
|
||||
{
|
||||
std::cerr << "The CImpactEnemyShip was not initialized" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new CImpactEnemyShip(position);
|
||||
}
|
||||
|
||||
CImpactEnemyShip::CImpactEnemyShip(const Ogre::Real position)
|
||||
{
|
||||
m_EnemyLeaving = false;
|
||||
const int type = m_application->getNextTargetType();
|
||||
m_application->logPrefix() << "Creating enemy " << type << "\n";
|
||||
|
||||
if (type > 0 && type <= 6)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 1:
|
||||
m_application->getSceneLoader()->parseDotScene("v2.scene", "SSVEPImpact", m_application->getSceneManager());
|
||||
|
||||
m_enemyNode = m_application->getSceneManager()->getSceneNode("v2_vaisseau");
|
||||
m_enemyNode->scale(1.0F, 1.0F, 1.0F);
|
||||
m_shipWidth = 0.5F;
|
||||
m_LeaveCountdown = int(2.0F * 3600);
|
||||
m_pointValue = 100;
|
||||
break;
|
||||
case 2:
|
||||
m_application->getSceneLoader()->parseDotScene("v1.scene", "SSVEPImpact", m_application->getSceneManager());
|
||||
|
||||
m_enemyNode = m_application->getSceneManager()->getSceneNode("v1_vaisseau");
|
||||
m_enemyNode->scale(1.9F, 1.9F, 1.9F);
|
||||
m_shipWidth = 0.45F;
|
||||
m_LeaveCountdown = int(1.5F * 3600);
|
||||
m_pointValue = 200;
|
||||
break;
|
||||
case 3:
|
||||
m_application->getSceneLoader()->parseDotScene("v3.scene", "SSVEPImpact", m_application->getSceneManager());
|
||||
|
||||
m_enemyNode = m_application->getSceneManager()->getSceneNode("v3_vaisseau");
|
||||
m_enemyNode->scale(2.2F, 2.0F, 2.0F);
|
||||
m_shipWidth = 0.4F;
|
||||
m_LeaveCountdown = int(1.0F * 3600);
|
||||
m_pointValue = 400;
|
||||
break;
|
||||
case 4:
|
||||
m_application->getSceneLoader()->parseDotScene("ship-cheap.scene", "SSVEPImpact", m_application->getSceneManager());
|
||||
m_enemyNode = m_application->getSceneManager()->getSceneNode("ship-cheap_node");
|
||||
m_pointValue = 500;
|
||||
break;
|
||||
case 5:
|
||||
m_application->getSceneLoader()->parseDotScene("ship-costly.scene", "SSVEPImpact", m_application->getSceneManager());
|
||||
m_enemyNode = m_application->getSceneManager()->getSceneNode("ship-costly_node");
|
||||
m_pointValue = 1500;
|
||||
break;
|
||||
case 6:
|
||||
m_application->getSceneLoader()->parseDotScene("ship-friend.scene", "SSVEPImpact", m_application->getSceneManager());
|
||||
m_enemyNode = m_application->getSceneManager()->getSceneNode("ship-friend_node");
|
||||
m_pointValue = -500;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (type >= 4 && type <= 6)
|
||||
{
|
||||
m_enemyNode->scale(1.2F, 1.2F, 1.2F);
|
||||
m_shipWidth = 0.3F;
|
||||
m_LeaveCountdown = int(1.0F * 3600);
|
||||
}
|
||||
|
||||
|
||||
m_enemyNode->yaw(Ogre::Radian(Ogre::Math::PI));
|
||||
|
||||
m_hitBox = m_application->getSceneNode()->createChildSceneNode();
|
||||
|
||||
|
||||
//m_hitBox->attachObject(m_painter->paintTriangle(Vector2(+ m_shipWidth / 2, +0.9), Vector2(- m_shipWidth / 2, +0.9), Vector2( 0.0, +0.5)));
|
||||
|
||||
|
||||
m_hitBox->translate(position / 70.0F, 1.2F, 0.0F, Ogre::Node::TS_LOCAL);
|
||||
m_enemyNode->translate(position, 0.0F, -60.0F, Ogre::Node::TS_LOCAL);
|
||||
m_incomingStatus = 30.0F;
|
||||
}
|
||||
else { m_application->getLogManager() << Kernel::LogLevel_Fatal << "Unknown enemy type " << type << " ! The application will now crash!\n"; }
|
||||
}
|
||||
|
||||
void CImpactEnemyShip::destroyAllAttachedMovableObjects(Ogre::SceneNode* sceneNode)
|
||||
{
|
||||
if (!sceneNode) { return; }
|
||||
|
||||
// Destroy all the attached objects
|
||||
Ogre::SceneNode::ObjectIterator itObject = sceneNode->getAttachedObjectIterator();
|
||||
|
||||
while (itObject.hasMoreElements())
|
||||
{
|
||||
Ogre::MovableObject* pObject = static_cast<Ogre::MovableObject*>(itObject.getNext());
|
||||
sceneNode->getCreator()->destroyMovableObject(pObject);
|
||||
}
|
||||
|
||||
Ogre::SceneNode::ChildNodeIterator itChild = sceneNode->getChildIterator();
|
||||
|
||||
while (itChild.hasMoreElements())
|
||||
{
|
||||
Ogre::SceneNode* pChildNode = dynamic_cast<Ogre::SceneNode*>(itChild.getNext());
|
||||
destroyAllAttachedMovableObjects(pChildNode);
|
||||
}
|
||||
}
|
||||
|
||||
CImpactEnemyShip::~CImpactEnemyShip()
|
||||
{
|
||||
m_application->logPrefix() << "Enemy Destroyed\n";
|
||||
|
||||
destroyAllAttachedMovableObjects(m_enemyNode);
|
||||
m_enemyNode->removeAndDestroyAllChildren();
|
||||
m_enemyNode->getCreator()->destroySceneNode(m_enemyNode);
|
||||
|
||||
destroyAllAttachedMovableObjects(m_hitBox);
|
||||
m_hitBox->removeAndDestroyAllChildren();
|
||||
m_hitBox->getCreator()->destroySceneNode(m_hitBox);
|
||||
}
|
||||
|
||||
void CImpactEnemyShip::processFrame()
|
||||
{
|
||||
// oscillation animation
|
||||
static int oscillator = 90;
|
||||
|
||||
if (m_LeaveCountdown > 0 && !m_EnemyLeaving) { m_LeaveCountdown--; }
|
||||
if (m_LeaveCountdown == 0 && !m_EnemyLeaving)
|
||||
{
|
||||
m_application->logPrefix() << "Enemy Leaving\n";
|
||||
|
||||
m_EnemyLeaving = true;
|
||||
m_pointValue = 0;
|
||||
}
|
||||
|
||||
if (!m_EnemyLeaving)
|
||||
{
|
||||
oscillator++;
|
||||
oscillator = oscillator % 360;
|
||||
// m_enemyNode->roll(Radian(Math::Sin(Degree(sin_oscillator)) / 80));
|
||||
m_enemyNode->translate(Ogre::Math::Sin(Ogre::Degree(Ogre::Real(oscillator))) / 20.0F * 0,
|
||||
Ogre::Math::Sin(Ogre::Degree(Ogre::Real(oscillator * 2 + 90))) / 20, 0.0F, Ogre::Node::TS_LOCAL);
|
||||
m_hitBox->translate(Ogre::Math::Sin(Ogre::Degree(Ogre::Real(oscillator))) / 20.0F / 50.0F * 0, 0.0F, 0.0F, Ogre::Node::TS_LOCAL);
|
||||
|
||||
|
||||
// incoming enemy animation
|
||||
if (m_incomingStatus > 0)
|
||||
{
|
||||
m_hitBox->translate(0.0F, -0.04F, 0.0F, Ogre::Node::TS_LOCAL);
|
||||
m_enemyNode->translate(0.0F, 0.0F, 1.0F, Ogre::Node::TS_LOCAL);
|
||||
m_incomingStatus -= 1.0F;
|
||||
}
|
||||
|
||||
// exploding ship animation
|
||||
if (m_destructionStatus > 3)
|
||||
{
|
||||
m_destructionStatus++;
|
||||
|
||||
m_enemyNode->translate(0.1F, 2, 1, Ogre::Node::TS_PARENT);
|
||||
m_enemyNode->rotate(Ogre::Vector3(0.3F, 0.25F, 1.0F), Ogre::Radian(3.14F / 20.0F), Ogre::Node::TS_LOCAL);
|
||||
m_enemyNode->scale(0.95F, 0.95F, 0.95F);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_enemyNode->translate(0.0F, -1.0F, float(m_LeaveCountdown) * 0.5F, Ogre::Node::TS_LOCAL);
|
||||
m_LeaveCountdown++;
|
||||
|
||||
if (m_enemyNode->getPosition().z < -100)
|
||||
{
|
||||
m_shipDestroyed = true;
|
||||
m_application->logPrefix() << "Enemy Left : marked as destroyed\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (m_destructionStatus > 50)
|
||||
{
|
||||
m_shipDestroyed = true;
|
||||
if (this->getPointValue() > 0) { m_application->logPrefix() << "Enemy Shot Down : marked as destroyed\n"; }
|
||||
else { m_application->logPrefix() << "Friendly Target Shot Down : marked as destroyed\n"; }
|
||||
}
|
||||
|
||||
|
||||
// handle the explosions
|
||||
for (auto it = m_explosions.begin(); it != m_explosions.end(); ++it)
|
||||
{
|
||||
(*it)->ttl--;
|
||||
|
||||
if ((*it)->ttl < 4 && (*it)->ttl >= 0)
|
||||
{
|
||||
Ogre::ParticleEmitter* emitter = (*it)->particleSystem->getEmitter(0);
|
||||
emitter->setEmissionRate(emitter->getEmissionRate() - 50);
|
||||
}
|
||||
|
||||
if (explostionExhausted(*it))
|
||||
{
|
||||
m_painter->getSceneManager()->destroyParticleSystem((*it)->particleSystem);
|
||||
(*it)->node->getCreator()->destroySceneNode((*it)->node);
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
m_explosions.erase(std::remove_if(m_explosions.begin(), m_explosions.end(), explostionExhausted), m_explosions.end());
|
||||
}
|
||||
|
||||
void CImpactEnemyShip::processHit(const Ogre::Vector2 point)
|
||||
{
|
||||
// set status of the ship as exploding
|
||||
if (m_destructionStatus <= 3)
|
||||
{
|
||||
m_destructionStatus++;
|
||||
m_application->logPrefix() << "Enemy Lost a Hitpoint : current hits = " << m_destructionStatus << "\n";
|
||||
}
|
||||
|
||||
// create the explosion upon hit
|
||||
struct SExplosionAnimation* explosion = new struct SExplosionAnimation;
|
||||
const char* projectileName = ("Explosion " + std::to_string(++m_nCurrentExplosion)).c_str();
|
||||
explosion->particleSystem = m_painter->getSceneManager()->createParticleSystem(projectileName, "Particle/Explosion");
|
||||
|
||||
|
||||
explosion->ttl = 25;
|
||||
explosion->node = m_parentNode->createChildSceneNode();
|
||||
explosion->node->attachObject(explosion->particleSystem);
|
||||
explosion->node->translate(point.x * -65.0F, 0.0F, 30.0F, Ogre::Node::TS_WORLD);
|
||||
|
||||
m_explosions.push_back(explosion);
|
||||
}
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include <Ogre.h>
|
||||
|
||||
#include "../ovamsCBasicPainter.h"
|
||||
|
||||
#define SSVEP_SHOOTER_TARGET_SIZE 0.15f
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CImpactApplication;
|
||||
|
||||
class CImpactEnemyShip
|
||||
{
|
||||
public:
|
||||
static CImpactEnemyShip* createTarget(Ogre::Real position);
|
||||
static void initialize(CImpactApplication* application);
|
||||
~CImpactEnemyShip();
|
||||
|
||||
void processFrame();
|
||||
void processHit(Ogre::Vector2 point);
|
||||
|
||||
Ogre::Vector2 getEnemyPosition() const { return Ogre::Vector2(m_hitBox->getPosition().x, m_hitBox->getPosition().y); }
|
||||
bool isDestroyed() const { return m_shipDestroyed; }
|
||||
bool isTouchable() const { return m_destructionStatus < 10 && !m_EnemyLeaving; }
|
||||
int getPointValue() const { return m_pointValue; }
|
||||
Ogre::Real getWidth() const { return m_shipWidth; }
|
||||
int m_LeaveCountdown = 0;
|
||||
bool m_EnemyLeaving = false;
|
||||
|
||||
private:
|
||||
|
||||
struct SExplosionAnimation
|
||||
{
|
||||
Ogre::ParticleSystem* particleSystem;
|
||||
Ogre::SceneNode* node;
|
||||
int ttl;
|
||||
};
|
||||
|
||||
static bool explostionExhausted(struct SExplosionAnimation* ea) { return ea->ttl < -25; }
|
||||
static void destroyAllAttachedMovableObjects(Ogre::SceneNode* sceneNode);
|
||||
|
||||
static CImpactApplication* m_application;
|
||||
static Ogre::SceneNode* m_parentNode;
|
||||
static CBasicPainter* m_painter;
|
||||
|
||||
Ogre::SceneNode* m_enemyNode = nullptr;
|
||||
Ogre::SceneNode* m_hitBox = nullptr;
|
||||
Ogre::Real m_incomingStatus = 0;
|
||||
Ogre::Real m_shipWidth = 0.1F;
|
||||
Ogre::uint32 m_destructionStatus = 0;
|
||||
bool m_shipDestroyed = false;
|
||||
int m_pointValue = 100;
|
||||
|
||||
explicit CImpactEnemyShip(Ogre::Real position);
|
||||
|
||||
static int m_nCurrentExplosion;
|
||||
std::vector<struct SExplosionAnimation*> m_explosions;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
+403
@@ -0,0 +1,403 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsCImpactShip.h"
|
||||
|
||||
#include "ovamsCImpactEnemyShip.h"
|
||||
#include "ovamsCImpactApplication.h"
|
||||
#include "../ovamsCSSVEPFlickeringObject.h"
|
||||
|
||||
#define SSVEP_SHIP_HULL_COLOUR Ogre::ColourValue(0.0f, 0.5f, 0.5f)
|
||||
#define SIGN(x) ( (x) < 0 ? -1 : 1 )
|
||||
|
||||
#define SCREEN_RATIO ( 16.0f / 9.0f )
|
||||
#define IMPACTSHIP_SIZE 0.2f
|
||||
#define IMPACTSHIP_SPEEDFACTOR 0.7f
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
//SP CImpactShip::CImpactShip(CImpactApplication* application, Ogre::SceneNode* parentNode, std::vector<std::pair<size_t, size_t> >* pFrequencies) :
|
||||
CImpactShip::CImpactShip(CImpactApplication* application, Ogre::SceneNode* parentNode, std::vector<size_t>* pFrequencies)
|
||||
: m_application(application), m_currentAngle(0)
|
||||
{
|
||||
m_application->getLogManager() << Kernel::LogLevel_Info << "Loading ship\n";
|
||||
|
||||
m_application->getSceneLoader()->parseDotScene("v5.scene", "SSVEPImpact", m_application->getSceneManager());
|
||||
|
||||
m_targetStates[0] = TS_NORMAL;
|
||||
m_targetStates[1] = TS_NORMAL;
|
||||
m_targetStates[2] = TS_NORMAL;
|
||||
|
||||
Ogre::SceneManager* sceneManager = m_application->getSceneManager();
|
||||
m_projectilesNode = parentNode->createChildSceneNode();
|
||||
|
||||
m_shipNode = sceneManager->getSceneNode("battleship");
|
||||
m_shipNode->scale(0.6F, 0.6F, 0.6F);
|
||||
m_shipNode->yaw(Ogre::Radian(-Ogre::Math::PI / 2.0F));
|
||||
m_shipNode->translate(-25.0F, 0.0F, 0.0F, Ogre::Node::TS_LOCAL);
|
||||
|
||||
if (!pFrequencies || pFrequencies->size() < 4)
|
||||
{
|
||||
std::cout << "Error: Expected the frequencies vector to contain indexes 0...3 but its size is " << (pFrequencies ? pFrequencies->size() : -1) <<
|
||||
". Crash is likely imminent.\n";
|
||||
}
|
||||
|
||||
sceneManager->getSceneNode("v5_ecran_avant2")->setVisible(false);
|
||||
m_shipCannon = new CSSVEPFlickeringObject(sceneManager->getSceneNode("shipCannon"), (*pFrequencies)[1]);
|
||||
|
||||
sceneManager->getSceneNode("v5_aile_gauche2")->setVisible(false);
|
||||
m_shipLeftWing = new CSSVEPFlickeringObject(sceneManager->getSceneNode("shipLeftWing"), (*pFrequencies)[2]);
|
||||
|
||||
sceneManager->getSceneNode("v5_aile_droite2")->setVisible(false);
|
||||
m_shipRightWing = new CSSVEPFlickeringObject(sceneManager->getSceneNode("shipRightWing"), (*pFrequencies)[3]);
|
||||
|
||||
|
||||
sceneManager->getSceneNode("feedback")->setVisible(true);
|
||||
|
||||
m_targetingNode = sceneManager->getSceneNode("v5_viseur");
|
||||
}
|
||||
|
||||
void CImpactShip::activatePilotAssist(const bool activate)
|
||||
{
|
||||
m_pilotAssistActive = activate;
|
||||
m_application->logPrefix() << "Pilot Assist : " << (activate ? "ON" : "OFF") << "\n";
|
||||
}
|
||||
|
||||
void CImpactShip::activateCannonInhibitor(const bool activate)
|
||||
{
|
||||
m_cannonInhibited = activate;
|
||||
|
||||
m_application->logPrefix() << "Cannon Inhibitor : " << (activate ? "ON" : "OFF") << "\n";
|
||||
}
|
||||
|
||||
void CImpactShip::activateTargetLockdown(const bool activate)
|
||||
{
|
||||
m_targetLockdownActive = activate;
|
||||
m_application->logPrefix() << "Target Lockdown : " << (activate ? "ON" : "OFF") << "\n";
|
||||
}
|
||||
|
||||
void CImpactShip::activateFeedback(const bool activate)
|
||||
{
|
||||
m_feedbackActive = activate;
|
||||
m_application->getSceneManager()->getSceneNode("feedback")->setVisible(activate);
|
||||
m_application->logPrefix() << "Feedback : " << (activate ? "ON" : "OFF") << "\n";
|
||||
}
|
||||
|
||||
void CImpactShip::activateFocusPoint(const bool activate)
|
||||
{
|
||||
m_focusPointActive = activate;
|
||||
m_application->getSceneManager()->getSceneNode("feedback")->setVisible(!m_focusPointActive && m_feedbackActive);
|
||||
|
||||
if (activate)
|
||||
{
|
||||
m_application->getSceneManager()->getSceneNode("v5_a1a")->setVisible(false);
|
||||
m_application->getSceneManager()->getSceneNode("v5_a2a")->setVisible(true);
|
||||
m_application->getSceneManager()->getSceneNode("v5_a3a")->setVisible(false);
|
||||
m_application->getSceneManager()->getSceneNode("v5_g1a")->setVisible(true);
|
||||
m_application->getSceneManager()->getSceneNode("v5_g2a")->setVisible(false);
|
||||
m_application->getSceneManager()->getSceneNode("v5_g3a")->setVisible(false);
|
||||
m_application->getSceneManager()->getSceneNode("v5_d1a")->setVisible(true);
|
||||
m_application->getSceneManager()->getSceneNode("v5_d2a")->setVisible(false);
|
||||
m_application->getSceneManager()->getSceneNode("v5_d3a")->setVisible(false);
|
||||
}
|
||||
|
||||
m_application->logPrefix() << "FocusPoint : " << (activate ? "ON" : "OFF") << "\n";
|
||||
}
|
||||
|
||||
|
||||
bool CImpactShip::projectileExhausted(struct SBlasterProjectile* bp) { return bp->iTTL <= 0; }
|
||||
|
||||
void CImpactShip::setAllTargetsVisibility(const bool visible) const
|
||||
{
|
||||
m_shipCannon->setVisible(visible);
|
||||
m_shipLeftWing->setVisible(visible);
|
||||
m_shipRightWing->setVisible(visible);
|
||||
}
|
||||
|
||||
void CImpactShip::processFrame(const size_t /*currentFrame*/)
|
||||
{
|
||||
if (m_shootingCooldown > 0) { m_shootingCooldown--; }
|
||||
if (m_application->isActive())
|
||||
{
|
||||
// deactivate the wing targets when the ship is on the border
|
||||
// std::cout << this->getNormalizedPosition() << "\n";
|
||||
|
||||
if (getNormalizedPosition().x >= -0.75 || !m_targetLockdownActive)
|
||||
{
|
||||
m_shipLeftWing->processFrame();
|
||||
m_targetStates[1] = TS_NORMAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_shipLeftWing->setVisible(false);
|
||||
m_targetStates[1] = TS_OFF;
|
||||
}
|
||||
|
||||
|
||||
if (getNormalizedPosition().x <= 0.75 || !m_targetLockdownActive)
|
||||
{
|
||||
m_shipRightWing->processFrame();
|
||||
m_targetStates[2] = TS_NORMAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_shipRightWing->setVisible(false);
|
||||
m_targetStates[2] = TS_OFF;
|
||||
}
|
||||
|
||||
// deactivate the cannon when there is no target locked
|
||||
if (m_targetLocked || (!m_targetLockdownActive))
|
||||
{
|
||||
m_shipCannon->processFrame();
|
||||
m_targetStates[0] = (m_cannonInhibited ? TS_INHIBITED : TS_NORMAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_shipCannon->setVisible(false);
|
||||
m_targetStates[0] = TS_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
m_targetingNode->pitch(Ogre::Degree(2), Ogre::Node::TS_PARENT);
|
||||
|
||||
if (m_targetLocked) { m_targetingNode->setVisible(true); }
|
||||
else { m_targetingNode->setVisible(false); }
|
||||
|
||||
/*
|
||||
if (m_prepareAnimationFrame > 0)
|
||||
{
|
||||
m_shipNode->translate(0.0f, -0.01f, 0.0f);
|
||||
m_prepareAnimationFrame--;
|
||||
}
|
||||
*/
|
||||
if (m_returning)
|
||||
{
|
||||
if (getNormalizedPosition().x < m_origin - 5e-2 || getNormalizedPosition().x > m_origin + 5e-2)
|
||||
{
|
||||
m_nCurrentDisplacement = (getNormalizedPosition().x < m_origin) ? 1 : -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_application->logPrefix() << "Ship Returned to Initial Position\n";
|
||||
m_returning = false;
|
||||
m_application->startFlickering();
|
||||
while (!m_nextEnemyPosition.empty())
|
||||
{
|
||||
const size_t nextEnemyPosition = m_nextEnemyPosition.front();
|
||||
m_nextEnemyPosition.pop_front();
|
||||
m_application->insertEnemy(nextEnemyPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_nCurrentDisplacement != 0)
|
||||
{
|
||||
// m_application->logPrefix() << "Displacement Vector : value = " << m_nCurrentDisplacement << "\n";
|
||||
|
||||
if (m_returning || !m_targetLocked || !m_pilotAssistActive)
|
||||
{
|
||||
m_application->logPrefix() << "Ship Moving : direction " << (m_nCurrentDisplacement > 0 ? "left" : "right") << ", full speed\n";
|
||||
m_shipNode->translate(0.5F * -float(SIGN(m_nCurrentDisplacement)) * IMPACTSHIP_SPEEDFACTOR, 0.0F, 0.0F);
|
||||
}
|
||||
else
|
||||
{
|
||||
Ogre::Real slowdown = 0.0;
|
||||
|
||||
if (m_application->getCurrentEnemy() != nullptr && m_application->getCurrentEnemy()->getPointValue() > 0)
|
||||
{
|
||||
const Ogre::Real enemyPos = m_application->getCurrentEnemy()->getEnemyPosition().x;
|
||||
const Ogre::Real shipPos = getNormalizedPosition().x;
|
||||
|
||||
|
||||
if (fabs(enemyPos - shipPos) < m_application->getCurrentEnemy()->getWidth() / 2)
|
||||
{
|
||||
const Ogre::Real distance = fabs(shipPos - enemyPos) / (m_application->getCurrentEnemy()->getWidth() / 2);
|
||||
|
||||
if (SIGN(m_nCurrentDisplacement) == SIGN(shipPos - enemyPos)) { slowdown = 1.0F - distance * distance * distance; }
|
||||
|
||||
if (SIGN(m_nCurrentDisplacement) > 0) { m_targetStates[2] = TS_INHIBITED; }
|
||||
else { m_targetStates[1] = TS_INHIBITED; }
|
||||
}
|
||||
}
|
||||
m_application->logPrefix() << "Ship Moving : direction " << (m_nCurrentDisplacement > 0 ? "left" : "right") << ", slowdown = " << slowdown << "\n";
|
||||
m_shipNode->translate((0.5F - slowdown * 0.3F) * -float(SIGN(m_nCurrentDisplacement)) * IMPACTSHIP_SPEEDFACTOR, 0.0F, 0.0F);
|
||||
}
|
||||
|
||||
// m_targetingNode->translate( 0.007f * SIGN(m_nCurrentDisplacement), 0.0f, 0.0f );
|
||||
m_nCurrentDisplacement -= SIGN(m_nCurrentDisplacement);
|
||||
}
|
||||
|
||||
|
||||
for (auto it = m_projectiles.begin(); it != m_projectiles.end(); ++it)
|
||||
{
|
||||
(*it)->iTTL--;
|
||||
|
||||
(*it)->pNode->translate(0.0, -2.0, 0.0, Ogre::Node::TS_LOCAL);
|
||||
(*it)->rRelY -= 1.0F / 65.0F;
|
||||
|
||||
|
||||
if (projectileExhausted(*it))
|
||||
{
|
||||
m_application->getSceneManager()->destroyParticleSystem((*it)->pParticleSystem);
|
||||
(*it)->pNode->getCreator()->destroySceneNode((*it)->pNode);
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
m_projectiles.erase(std::remove_if(m_projectiles.begin(), m_projectiles.end(), projectileExhausted), m_projectiles.end());
|
||||
|
||||
|
||||
if (m_oldPosition != m_shipNode->getPosition().x)
|
||||
{
|
||||
m_oldPosition = m_shipNode->getPosition().x;
|
||||
m_application->logPrefix() << "New Ship Position : " << m_oldPosition << " / Normalized X : " << getNormalizedPosition().x << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void CImpactShip::move(const int displacement)
|
||||
{
|
||||
if (displacement < 0 && getNormalizedPosition().x <= -0.75) { return; }
|
||||
if (displacement > 0 && getNormalizedPosition().x >= 0.75) { return; }
|
||||
|
||||
//m_application->logPrefix() << "Move : diff vector = " << displacement << ", current vector = " << m_nCurrentDisplacement;
|
||||
|
||||
if (abs(m_nCurrentDisplacement) < 6) { m_nCurrentDisplacement += displacement; }
|
||||
|
||||
//m_application->getLogManager() << ", resulting vector = " << m_nCurrentDisplacement << "\n";
|
||||
}
|
||||
|
||||
void CImpactShip::shoot()
|
||||
{
|
||||
m_application->logPrefix() << "Shoot : ";
|
||||
|
||||
if (m_targetLockdownActive && !m_targetLocked)
|
||||
{
|
||||
m_application->logPrefix() << "CANCELED : pilot assist blocked the shot\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (m_shootingCooldown > 0)
|
||||
{
|
||||
m_application->logPrefix() << "CANCELED : shooting cooldown blocked the shot\n";
|
||||
return;
|
||||
}
|
||||
|
||||
m_shootingCooldown = (m_targetStates[0] == TS_INHIBITED) ? 24 : 12;
|
||||
|
||||
struct SBlasterProjectile* projectile = new struct SBlasterProjectile;
|
||||
|
||||
const std::string projectileName = "Projectile_" + std::to_string(++m_nShot);
|
||||
projectile->pParticleSystem = m_application->getSceneManager()->createParticleSystem(projectileName, "Particle/PurpleFountain");
|
||||
|
||||
|
||||
projectile->iTTL = 70;
|
||||
projectile->pNode = m_projectilesNode->createChildSceneNode();
|
||||
projectile->pNode->pitch(Ogre::Radian(-Ogre::Math::PI / 2.0F));
|
||||
projectile->pNode->translate(this->getPosition().x, 20.0, 0.0, Ogre::Node::TS_LOCAL);
|
||||
|
||||
projectile->pNode->attachObject(projectile->pParticleSystem);
|
||||
|
||||
projectile->rRelX = -m_shipNode->getPosition().x / 70.0F;
|
||||
projectile->rRelY = 0.6F;
|
||||
|
||||
|
||||
m_application->getLogManager() << "OK : creating particle system\n";
|
||||
m_projectiles.push_back(projectile);
|
||||
}
|
||||
|
||||
void CImpactShip::setFeedbackLevels(const int f1, int f2, int f3)
|
||||
{
|
||||
if (m_focusPointActive) { return; }
|
||||
|
||||
Ogre::SceneManager* sceneManager = m_application->getSceneManager();
|
||||
|
||||
if (m_targetStates[1] == TS_OFF) { f2 = 0; }
|
||||
if (m_targetStates[2] == TS_OFF) { f3 = 0; }
|
||||
|
||||
sceneManager->getSceneNode("v5_a1b")->setVisible(false);
|
||||
sceneManager->getSceneNode("v5_a2b")->setVisible(false);
|
||||
sceneManager->getSceneNode("v5_a3b")->setVisible(false);
|
||||
sceneManager->getSceneNode("v5_g1b")->setVisible(false);
|
||||
sceneManager->getSceneNode("v5_g2b")->setVisible(false);
|
||||
sceneManager->getSceneNode("v5_g3b")->setVisible(false);
|
||||
sceneManager->getSceneNode("v5_d1b")->setVisible(false);
|
||||
sceneManager->getSceneNode("v5_d2b")->setVisible(false);
|
||||
sceneManager->getSceneNode("v5_d3b")->setVisible(false);
|
||||
|
||||
if (m_feedbackActive)
|
||||
{
|
||||
int nActives = 0;
|
||||
|
||||
if (f1 > 0) { sceneManager->getSceneNode("v5_a1b")->setVisible(true); }
|
||||
if (f1 > 1) { sceneManager->getSceneNode("v5_a2b")->setVisible(true); }
|
||||
if (f1 > 2)
|
||||
{
|
||||
sceneManager->getSceneNode("v5_a3b")->setVisible(true);
|
||||
nActives++;
|
||||
}
|
||||
if (f2 > 0) { sceneManager->getSceneNode("v5_g1b")->setVisible(true); }
|
||||
if (f2 > 1) { sceneManager->getSceneNode("v5_g2b")->setVisible(true); }
|
||||
if (f2 > 2)
|
||||
{
|
||||
sceneManager->getSceneNode("v5_g3b")->setVisible(true);
|
||||
nActives++;
|
||||
}
|
||||
if (f3 > 0) { sceneManager->getSceneNode("v5_d1b")->setVisible(true); }
|
||||
if (f3 > 1) { sceneManager->getSceneNode("v5_d2b")->setVisible(true); }
|
||||
if (f3 > 2)
|
||||
{
|
||||
sceneManager->getSceneNode("v5_d3b")->setVisible(true);
|
||||
nActives++;
|
||||
}
|
||||
|
||||
if (nActives > 1)
|
||||
{
|
||||
sceneManager->getSceneNode("v5_a3b")->setVisible(false);
|
||||
sceneManager->getSceneNode("v5_g3b")->setVisible(false);
|
||||
sceneManager->getSceneNode("v5_d3b")->setVisible(false);
|
||||
}
|
||||
|
||||
if (m_targetLockdownActive && !m_targetLocked)
|
||||
{
|
||||
sceneManager->getSceneNode("v5_a1b")->setVisible(false);
|
||||
sceneManager->getSceneNode("v5_a2b")->setVisible(false);
|
||||
sceneManager->getSceneNode("v5_a3b")->setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CImpactShip::returnToMiddleAndWaitForFoe(const size_t targetPosition, const Ogre::Real position)
|
||||
{
|
||||
m_application->logPrefix() << "Ship Returning to Middle Position\n";
|
||||
m_nextEnemyPosition.push_back(targetPosition);
|
||||
m_application->stopFlickering();
|
||||
m_origin = position;
|
||||
m_returning = true;
|
||||
}
|
||||
|
||||
bool CImpactShip::evaluateHit(CImpactEnemyShip* enemy)
|
||||
{
|
||||
const Ogre::Vector2 point = enemy->getEnemyPosition();
|
||||
// std::cout << "enemy:" << enemy->getEnemyPosition() << "\n";
|
||||
for (auto it = m_projectiles.begin(); it != m_projectiles.end(); ++it)
|
||||
{
|
||||
// std::cout << "proj: " << (*it)->rRelX << " " << (*it)->rRelY << "\n";
|
||||
|
||||
if (Ogre::Math::pointInTri2D(Ogre::Vector2((*it)->rRelX, (*it)->rRelY),
|
||||
Ogre::Vector2(point.x + enemy->getWidth() / 2.0F, point.y + enemy->getWidth() / 2.0F),
|
||||
Ogre::Vector2(point.x - enemy->getWidth() / 2.0F, point.y + enemy->getWidth() / 2.0F),
|
||||
Ogre::Vector2(point.x, point.y - 0.1F)))
|
||||
{
|
||||
m_application->logPrefix() << "Enemy Hit!\n";
|
||||
(*it)->iTTL = 1;
|
||||
enemy->processHit(Ogre::Vector2((*it)->rRelX, (*it)->rRelY));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <Ogre.h>
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CImpactApplication;
|
||||
class CImpactEnemyShip;
|
||||
class CSSVEPFlickeringObject;
|
||||
|
||||
class CImpactShip
|
||||
{
|
||||
public:
|
||||
enum ETargetState { TS_NORMAL, TS_INHIBITED, TS_OFF };
|
||||
|
||||
//SP CImpactShip( CImpactApplication* application, Ogre::SceneNode* parentNode, std::vector<std::pair<size_t, size_t> >* pFrequencies);
|
||||
CImpactShip(CImpactApplication* application, Ogre::SceneNode* parentNode, std::vector<size_t>* pFrequencies);
|
||||
void processFrame(const size_t currentFrame);
|
||||
|
||||
void moveToPosition() { m_prepareAnimationFrame = 70; }
|
||||
void move(int displacement);
|
||||
void shoot();
|
||||
bool evaluateHit(CImpactEnemyShip* enemy);
|
||||
void setAllTargetsVisibility(bool visible) const;
|
||||
Ogre::Vector2 getPosition() const { return Ogre::Vector2(m_shipNode->getPosition().x, m_shipNode->getPosition().y); }
|
||||
Ogre::Vector2 getNormalizedPosition() const { return Ogre::Vector2(-m_shipNode->getPosition().x / 70.0F, m_shipNode->getPosition().y); }
|
||||
void setTargetLocked(const bool targetLocked) { m_targetLocked = targetLocked; }
|
||||
|
||||
void setFeedbackLevels(int f1, int f2, int f3);
|
||||
void activatePilotAssist(const bool activate);
|
||||
void activateCannonInhibitor(const bool activate);
|
||||
void activateTargetLockdown(const bool activate);
|
||||
void activateFeedback(const bool activate);
|
||||
void activateFocusPoint(const bool activate);
|
||||
void returnToMiddleAndWaitForFoe(size_t targetPosition, Ogre::Real position = 0.0);
|
||||
|
||||
ETargetState getTargetState(const int target) { return m_targetStates[target]; }
|
||||
|
||||
private:
|
||||
|
||||
struct SBlasterProjectile
|
||||
{
|
||||
Ogre::ParticleSystem* pParticleSystem;
|
||||
Ogre::SceneNode* pNode;
|
||||
Ogre::SceneNode* pOutlineNode;
|
||||
int iTTL;
|
||||
Ogre::Real rRelX, rRelY;
|
||||
};
|
||||
|
||||
static bool projectileExhausted(struct SBlasterProjectile* /*bp*/);
|
||||
|
||||
CImpactApplication* m_application = nullptr;
|
||||
|
||||
Ogre::SceneNode* m_shipNode = nullptr;
|
||||
Ogre::SceneNode* m_targetingNode = nullptr;
|
||||
Ogre::SceneNode* m_projectilesNode = nullptr;
|
||||
|
||||
CSSVEPFlickeringObject* m_shipCannon = nullptr;
|
||||
CSSVEPFlickeringObject* m_shipLeftWing = nullptr;
|
||||
CSSVEPFlickeringObject* m_shipRightWing = nullptr;
|
||||
|
||||
ETargetState m_targetStates[3];
|
||||
|
||||
int m_prepareAnimationFrame = 0;
|
||||
bool m_targetLocked = true;
|
||||
bool m_returning = false;
|
||||
std::deque<size_t> m_nextEnemyPosition;
|
||||
bool m_pilotAssistActive = false;
|
||||
bool m_targetLockdownActive = false;
|
||||
bool m_feedbackActive = false;
|
||||
bool m_focusPointActive = false;
|
||||
bool m_cannonInhibited = false;
|
||||
|
||||
Ogre::Radian m_currentAngle;
|
||||
int m_nCurrentDisplacement = 0;
|
||||
|
||||
int m_shootingCooldown = 0;
|
||||
std::vector<struct SBlasterProjectile*> m_projectiles;
|
||||
int m_nShot = 0;
|
||||
Ogre::Real m_origin = 0.0;
|
||||
Ogre::Real m_oldPosition = 0;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovkCLogListenerFileBuffered.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Kernel {
|
||||
|
||||
CLogListenerFileBuffered::CLogListenerFileBuffered(const IKernelContext& /*context*/, const CString& applicationName, const CString& logFilename)
|
||||
: m_applicationName(applicationName), m_logFilename(logFilename)
|
||||
{
|
||||
m_f = fopen(m_logFilename.toASCIIString(), "wt");
|
||||
if (m_f == nullptr)
|
||||
{
|
||||
std::cout << "[ ERROR ] Unable to open [" << m_logFilename << "] for writing. This log listener can not be initialized, it will do nothing!" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
CLogListenerFileBuffered::~CLogListenerFileBuffered() { if (m_f != nullptr) { fclose(m_f); } }
|
||||
|
||||
bool CLogListenerFileBuffered::isActive(const ELogLevel level)
|
||||
{
|
||||
const auto it = m_activeLevels.find(level);
|
||||
if (it == m_activeLevels.end()) { return true; }
|
||||
return it->second;
|
||||
}
|
||||
|
||||
bool CLogListenerFileBuffered::activate(const ELogLevel level, const bool active)
|
||||
{
|
||||
m_activeLevels[level] = active;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CLogListenerFileBuffered::activate(const ELogLevel startLevel, const ELogLevel endLevel, const bool active)
|
||||
{
|
||||
for (int i = startLevel; i <= endLevel; ++i) { m_activeLevels[ELogLevel(i)] = active; }
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CLogListenerFileBuffered::activate(const bool active) { return activate(LogLevel_First, LogLevel_Last, active); }
|
||||
|
||||
void CLogListenerFileBuffered::log(const CTime value) { if (m_f != nullptr) { fprintf(m_f, "%llu", value.time()); } }
|
||||
void CLogListenerFileBuffered::log(const uint64_t value) { if (m_f != nullptr) { fprintf(m_f, "%llu", value); } }
|
||||
void CLogListenerFileBuffered::log(const uint32_t value) { if (m_f != nullptr) { fprintf(m_f, "%u", value); } }
|
||||
void CLogListenerFileBuffered::log(const int64_t value) { if (m_f != nullptr) { fprintf(m_f, "%lli", value); } }
|
||||
void CLogListenerFileBuffered::log(const int value) { if (m_f != nullptr) { fprintf(m_f, "%i", value); } }
|
||||
void CLogListenerFileBuffered::log(const double value) { if (m_f != nullptr) { fprintf(m_f, "%lf", value); } }
|
||||
void CLogListenerFileBuffered::log(const bool value) { if (m_f != nullptr) { fprintf(m_f, "%s", (value ? "true" : "false")); } }
|
||||
void CLogListenerFileBuffered::log(const CIdentifier& value) { if (m_f != nullptr) { fprintf(m_f, "%s", value.str().c_str()); } }
|
||||
void CLogListenerFileBuffered::log(const CString& value) { if (m_f != nullptr) { fprintf(m_f, "%s", value.toASCIIString()); } }
|
||||
void CLogListenerFileBuffered::log(const std::string& value) { if (m_f != nullptr) { fprintf(m_f, "%s", value.c_str()); } }
|
||||
void CLogListenerFileBuffered::log(const char* value) { if (m_f != nullptr) { fprintf(m_f, "%s", value); } }
|
||||
|
||||
void CLogListenerFileBuffered::log(const ELogLevel level)
|
||||
{
|
||||
if (m_f != nullptr)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case LogLevel_Debug:
|
||||
fprintf(m_f, "[ DEBUG ] ");
|
||||
break;
|
||||
|
||||
case LogLevel_Benchmark:
|
||||
fprintf(m_f, "[ BENCH ] ");
|
||||
break;
|
||||
|
||||
case LogLevel_Trace:
|
||||
fprintf(m_f, "[ TRACE ] ");
|
||||
break;
|
||||
|
||||
case LogLevel_Info:
|
||||
fprintf(m_f, "[ INF ] ");
|
||||
break;
|
||||
|
||||
case LogLevel_Warning:
|
||||
fprintf(m_f, "[WARNING] ");
|
||||
break;
|
||||
|
||||
case LogLevel_ImportantWarning:
|
||||
fprintf(m_f, "[WARNING] ");
|
||||
break;
|
||||
|
||||
case LogLevel_Error:
|
||||
fprintf(m_f, "[ ERROR ] ");
|
||||
break;
|
||||
|
||||
case LogLevel_Fatal:
|
||||
fprintf(m_f, "[ FATAL ] ");
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(m_f, "[UNKNOWN] ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
#include <map>
|
||||
#include <cstdio>
|
||||
|
||||
#define OVK_ClassId_Kernel_Log_LogListenerFileBuffered OpenViBE::CIdentifier(0x0FD252FB, 0x315C1A97)
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Kernel {
|
||||
class CLogListenerFileBuffered final : public ILogListener
|
||||
{
|
||||
public:
|
||||
|
||||
CLogListenerFileBuffered(const IKernelContext& context, const CString& applicationName, const CString& logFilename);
|
||||
~CLogListenerFileBuffered() override;
|
||||
|
||||
bool isActive(const ELogLevel level) override;
|
||||
bool activate(const ELogLevel level, const bool active) override;
|
||||
bool activate(const ELogLevel startLevel, const ELogLevel endLevel, const bool active) override;
|
||||
bool activate(const bool active) override;
|
||||
|
||||
void log(const CTime value) override;
|
||||
|
||||
void log(const uint64_t value) override;
|
||||
void log(const uint32_t value) override;
|
||||
|
||||
void log(const int64_t value) override;
|
||||
void log(const int value) override;
|
||||
|
||||
void log(const double value) override;
|
||||
|
||||
void log(const bool value) override;
|
||||
|
||||
void log(const CIdentifier& value) override;
|
||||
void log(const CString& value) override;
|
||||
void log(const std::string& value) override;
|
||||
void log(const char* value) override;
|
||||
|
||||
void log(const ELogLevel level) override;
|
||||
void log(const ELogColor /*color*/) override {}
|
||||
|
||||
_IsDerivedFromClass_Final_(ILogListener, OVK_ClassId_Kernel_Log_LogListenerFileBuffered)
|
||||
|
||||
protected:
|
||||
|
||||
std::map<ELogLevel, bool> m_activeLevels;
|
||||
CString m_applicationName;
|
||||
CString m_logFilename;
|
||||
|
||||
FILE* m_f = nullptr;
|
||||
};
|
||||
} // namespace Kernel
|
||||
} // namespace OpenViBE
|
||||
Executable
+378
@@ -0,0 +1,378 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsCApplication.h"
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
#include "fs/Files.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
CApplication::~CApplication()
|
||||
{
|
||||
delete m_StimulusSender;
|
||||
|
||||
if (m_painter != nullptr)
|
||||
{
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "- m_painter\n";
|
||||
delete m_painter;
|
||||
m_painter = nullptr;
|
||||
}
|
||||
|
||||
for (auto it = m_commands.begin();
|
||||
it != m_commands.end(); ++it)
|
||||
{
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "- ICommand\n";
|
||||
if (*it != nullptr)
|
||||
{
|
||||
delete *it;
|
||||
*it = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "- m_root\n";
|
||||
if (m_root != nullptr)
|
||||
{
|
||||
delete m_root;
|
||||
m_root = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool CApplication::setup(Kernel::IKernelContext* poKernelContext)
|
||||
{
|
||||
m_kernelCtx = poKernelContext;
|
||||
m_logManager = &(m_kernelCtx->getLogManager());
|
||||
|
||||
Kernel::IConfigurationManager* configManager = &(m_kernelCtx->getConfigurationManager());
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << " * CApplication::setup()\n";
|
||||
|
||||
// Plugin config path setup
|
||||
Ogre::String pluginsPath;
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
#if defined TARGET_BUILDTYPE_Debug
|
||||
pluginsPath = std::string(getenv("OGRE_HOME")) + std::string("/bin/debug/plugins_d.cfg");
|
||||
#else
|
||||
pluginsPath = std::string(getenv("OGRE_HOME")) + std::string("/bin/release/plugins.cfg");
|
||||
#endif
|
||||
#elif defined TARGET_OS_Linux
|
||||
pluginsPath = std::string(configManager->expand("${Path_Data}/openvibe-ogre-plugins.cfg").toASCIIString());
|
||||
#else
|
||||
#error "No OS defined."
|
||||
#endif
|
||||
|
||||
// Create LogManager to stop Ogre flooding the console and creating random files
|
||||
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ Creating Ogre logmanager\n";
|
||||
Ogre::LogManager* logManager = new Ogre::LogManager();
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "Log level: " << configManager->expand("${Kernel_ConsoleLogLevel}") << "\n";
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "Application will output Ogre console log : " << configManager->expandAsBoolean(
|
||||
"${SSVEP_Ogre_LogToConsole}", false) << "\n";
|
||||
const CString ogreLog = configManager->expand("${SSVEP_UserDataFolder}/mind-shooter-[$core{date}-$core{time}]-ogre.log");
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "Ogre log file : " << ogreLog << "\n";
|
||||
FS::Files::createParentPath(ogreLog);
|
||||
logManager->createLog(ogreLog.toASCIIString(), true, configManager->expandAsBoolean("${SSVEP_Ogre_LogToConsole}", false), false);
|
||||
|
||||
// Root creation
|
||||
const CString ogreCfg = configManager->expand("${SSVEP_MindShooterScenarioPath}") + "/appconf/mind-shooter-ogre.conf";
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ m_root = new Ogre::Root(...)\n";
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "Ogre cfg file : " << ogreCfg << "\n";
|
||||
m_root = new Ogre::Root(pluginsPath, ogreCfg.toASCIIString(), ogreLog.toASCIIString());
|
||||
|
||||
// Resource handling
|
||||
this->setupResources();
|
||||
|
||||
// Configuration from file or dialog window if needed
|
||||
if (!this->configure())
|
||||
{
|
||||
(*m_logManager) << Kernel::LogLevel_Fatal << "The configuration process ended unexpectedly.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// m_window = m_root->initialise(true);
|
||||
|
||||
|
||||
Ogre::NameValuePairList optionList;
|
||||
m_root->initialise(false);
|
||||
|
||||
|
||||
optionList["vsync"] = "1";
|
||||
|
||||
const int width = int(configManager->expandAsInteger("${SSVEP_Ogre_ScreenWidth}", 800));
|
||||
const int height = int(configManager->expandAsInteger("${SSVEP_Ogre_ScreenHeight}", 600));
|
||||
const bool fullScreen = configManager->expandAsBoolean("${SSVEP_Ogre_FullScreen}", false);
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "Width : " << width << " Height : " << height << " Fullscreen : " << fullScreen << "\n";
|
||||
|
||||
//m_window = m_root->createRenderWindow("SSVEP Stimulator", 960, 600, false, &l_oOptionList);
|
||||
m_window = m_root->createRenderWindow("SSVEP Stimulator", width, height, fullScreen, &optionList);
|
||||
|
||||
m_windowWidth = m_window->getWidth();
|
||||
m_windowHeight = m_window->getHeight();
|
||||
|
||||
m_sceneManager = m_root->createSceneManager(Ogre::ST_GENERIC);
|
||||
m_camera = m_sceneManager->createCamera("SSVEPApplicationCamera");
|
||||
m_cameraNode = m_sceneManager->getRootSceneNode()->createChildSceneNode();
|
||||
m_cameraNode->attachObject(m_camera);
|
||||
|
||||
Ogre::SceneManager* fillSceneManager = m_root->createSceneManager(Ogre::ST_GENERIC);
|
||||
Ogre::Camera* fillCamera = fillSceneManager->createCamera("SSVEPFillCamera");
|
||||
m_window->addViewport(fillCamera, 0);
|
||||
|
||||
m_viewport = m_window->addViewport(m_camera, 1);
|
||||
//this->resizeViewport();
|
||||
// m_viewport->setBackgroundColour(Ogre::ColourValue(0.0, 0.5, 0.5));
|
||||
|
||||
m_camera->setAspectRatio(Ogre::Real(m_viewport->getActualWidth()) / Ogre::Real(m_viewport->getActualHeight()));
|
||||
|
||||
m_sceneNode = m_sceneManager->getRootSceneNode()->createChildSceneNode("SSVEPApplicationNode");
|
||||
|
||||
// initialize the painter object
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ m_painter = new CBasicPainter(...)\n";
|
||||
m_painter = new CBasicPainter(this);
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << " * initializing CEGUI\n";
|
||||
this->initCEGUI(configManager->expand("${SSVEP_UserDataFolder}/mind-shooter-[$core{date}-$core{time}]-cegui.log"));
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << " * CEGUI initialized\n";
|
||||
|
||||
// create the vector of stimulation frequencies
|
||||
|
||||
m_screenRefreshRate = double(configManager->expandAsUInteger("${SSVEP_ScreenRefreshRate}", 60));
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "Specified screen refresh rate :" << m_screenRefreshRate << "Hz\n";
|
||||
|
||||
if (m_screenRefreshRate > 64)
|
||||
{
|
||||
(*m_logManager) << Kernel::LogLevel_Error << "Screen refresh rate exceeds the max bit pattern length of 64\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t i = 1;
|
||||
|
||||
CIdentifier frequencyId = configManager->createConfigurationToken("SSVEP_FrequencyId", "1");
|
||||
|
||||
m_frequencies.push_back(30);
|
||||
|
||||
size_t patternsLoaded = 0;
|
||||
|
||||
// TODO: Load patterns
|
||||
|
||||
// Load pre-defined stimulation patterns (binary encoded dark/light frames inside a 64bit integer)
|
||||
while (configManager->lookUpConfigurationTokenIdentifier(configManager->expand("SSVEP_Pattern_${SSVEP_FrequencyId}")) !=
|
||||
CIdentifier::undefined())
|
||||
{
|
||||
size_t stimulationPattern = size_t(configManager->expandAsInteger("${SSVEP_Pattern_${SSVEP_FrequencyId}}"));
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "Pattern number " << i << " pattern : " << stimulationPattern << "\n";
|
||||
m_frequencies[i] = stimulationPattern;
|
||||
|
||||
configManager->releaseConfigurationToken(frequencyId);
|
||||
|
||||
frequencyId = configManager->createConfigurationToken("SSVEP_FrequencyId", std::to_string(++i).c_str());
|
||||
patternsLoaded++;
|
||||
}
|
||||
|
||||
|
||||
// Generate patterns from frequencies
|
||||
if (patternsLoaded == 0)
|
||||
{
|
||||
// Load frequencies
|
||||
while (configManager->lookUpConfigurationTokenIdentifier(configManager->expand("SSVEP_Frequency_${SSVEP_FrequencyId}")) != CIdentifier::undefined())
|
||||
{
|
||||
const double currentFrequency = double(configManager->expandAsFloat("${SSVEP_Frequency_${SSVEP_FrequencyId}}"));
|
||||
const double approximatedFrameCount = m_screenRefreshRate / currentFrequency;
|
||||
const size_t nRoundedFrame = size_t(floor(approximatedFrameCount + 0.5));
|
||||
|
||||
// test if the desired frequency can be reasonably created on the screen
|
||||
if (fabs(approximatedFrameCount - nRoundedFrame) < 0.003)
|
||||
{
|
||||
const size_t framesL = nRoundedFrame / 2 + nRoundedFrame % 2;
|
||||
const size_t framesD = nRoundedFrame / 2;
|
||||
|
||||
// the pattern is procedurally generated and always starts by a 1,
|
||||
// following by as many 0s as there are Dark frames and finally as many 1s as there are Light frames.
|
||||
// The frame loop will consume one bit per frame from the right and then reset when the reset marker is hit.
|
||||
|
||||
// Start with the reset marker
|
||||
uint64_t stimulationPattern = 1;
|
||||
|
||||
// The dark zeroes
|
||||
stimulationPattern <<= framesD;
|
||||
|
||||
// The light ones
|
||||
for (size_t j = 0; j < framesL; ++j)
|
||||
{
|
||||
stimulationPattern <<= 1;
|
||||
stimulationPattern += 1;
|
||||
}
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "Frequency number " << i << ": " << currentFrequency << "Hz / " <<
|
||||
floor(approximatedFrameCount + 0.5) << " ( " << framesL << " light, " << framesD << " dark) frames @ " <<
|
||||
m_screenRefreshRate << "fps\n";
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "Frequency number " << i << " pattern : " << stimulationPattern << "\n";
|
||||
|
||||
std::stringstream binary;
|
||||
binary << std::bitset<64>(stimulationPattern);
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "Frequency number " << i << " binary : " << binary.str() << "\n";
|
||||
|
||||
m_frequencies.push_back(stimulationPattern);
|
||||
patternsLoaded++;
|
||||
}
|
||||
else { (*m_logManager) << Kernel::LogLevel_Error << "The selected frequency (" << currentFrequency << "Hz) is not supported by your screen.\n"; }
|
||||
|
||||
configManager->releaseConfigurationToken(frequencyId);
|
||||
|
||||
frequencyId = configManager->createConfigurationToken("SSVEP_FrequencyId", std::to_string(++i).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (!patternsLoaded)
|
||||
{
|
||||
(*m_logManager) << Kernel::LogLevel_Error << "No flashing frequencies loaded. Have you run the SSVEP Impact Shooter configuring scenario?\n";
|
||||
(*m_logManager) << Kernel::LogLevel_Error << "Are you running this app from the correct scenario with the previous stages run properly?\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_StimulusSender->connect("localhost", "15361");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set hard-coded parameters, VSync in particular, for all known render systems
|
||||
void CApplication::setOgreParameters() const
|
||||
{
|
||||
const bool fullScreen = m_kernelCtx->getConfigurationManager().expandAsBoolean("${SSVEP_Ogre_FullScreen}", false);
|
||||
const Ogre::RenderSystemList& list = m_root->getAvailableRenderers();
|
||||
for (size_t i = 0; i < list.size(); ++i)
|
||||
{
|
||||
list[i]->setConfigOption("VSync", "Yes");
|
||||
list[i]->setConfigOption("Full Screen", (fullScreen ? "Yes" : "No"));
|
||||
}
|
||||
}
|
||||
|
||||
bool CApplication::configure() const
|
||||
{
|
||||
if (! m_root->restoreConfig())
|
||||
{
|
||||
setOgreParameters();
|
||||
|
||||
if (! m_root->showConfigDialog())
|
||||
{
|
||||
(*m_logManager) << Kernel::LogLevel_Error << "No configuration created from the dialog window.\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Override 'unsuitable' user choices
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "Forcing vsync and using fullscreen settings from configuration scenario.\n";
|
||||
setOgreParameters();
|
||||
|
||||
// Save the config again after we have forced the params, otherwise the conf file looks misleading
|
||||
m_root->saveConfig();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CApplication::initCEGUI(const char* logFilename)
|
||||
{
|
||||
// Instantiate logger before bootstrapping the system, this way we will be able to get the log redirected
|
||||
if (!CEGUI::Logger::getSingletonPtr()) { new CEGUI::DefaultLogger(); } // singleton; instantiate only, no delete
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "+ CEGUI log will be in '" << logFilename << "'\n";
|
||||
FS::Files::createParentPath(logFilename);
|
||||
CEGUI::Logger::getSingleton().setLogFilename(logFilename, false);
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ Creating CEGUI Ogre bootstrap\n";
|
||||
m_guiRenderer = &(CEGUI::OgreRenderer::bootstrapSystem(*m_window));
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ Creating CEGUI Scheme Manager\n";
|
||||
|
||||
#if (CEGUI_VERSION_MAJOR > 0) || (CEGUI_VERSION_MINOR >= 8)
|
||||
CEGUI::SchemeManager::getSingleton().createFromFile(const_cast<CEGUI::utf8*>(reinterpret_cast<const CEGUI::utf8*>("TaharezLook-ov-0.8.scheme")));
|
||||
#else
|
||||
CEGUI::SchemeManager::getSingleton().create((CEGUI::utf8*)"TaharezLook-ov.scheme");
|
||||
#endif
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ Creating CEGUI WindowManager\n";
|
||||
m_guiWindowManager = CEGUI::WindowManager::getSingletonPtr();
|
||||
m_sheet = m_guiWindowManager->createWindow("DefaultWindow", "RootSheet");
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "+ Setting CEGUI StyleSheet\n";
|
||||
#if (CEGUI_VERSION_MAJOR > 0) || (CEGUI_VERSION_MINOR >= 8)
|
||||
CEGUI::System::getSingleton().getDefaultGUIContext().setRootWindow(m_sheet);
|
||||
#else
|
||||
CEGUI::System::getSingleton().setGUISheet(m_sheet);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CApplication::resizeViewport() const
|
||||
{
|
||||
(*m_logManager) << Kernel::LogLevel_Trace << "Creating a new viewport\n";
|
||||
|
||||
const Ogre::uint32 viewportSize = std::min(m_windowWidth, m_windowHeight);
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "New viewport size : " << viewportSize << "\n";
|
||||
|
||||
m_viewport->setDimensions(Ogre::Real(m_windowWidth - viewportSize) / Ogre::Real(m_windowWidth) / 2,
|
||||
Ogre::Real(m_windowHeight - viewportSize) / Ogre::Real(m_windowHeight) / 2,
|
||||
Ogre::Real(viewportSize) / Ogre::Real(m_windowWidth),
|
||||
Ogre::Real(viewportSize) / Ogre::Real(m_windowHeight));
|
||||
}
|
||||
|
||||
void CApplication::setupResources() const
|
||||
{
|
||||
Kernel::IConfigurationManager* configManager = &(m_kernelCtx->getConfigurationManager());
|
||||
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
configManager->expand("${Path_Data}/applications/${SSVEP_MindShooterFolderName}/resources").toASCIIString(), "FileSystem", "SSVEP");
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
configManager->expand("${Path_Data}/applications/${SSVEP_MindShooterFolderName}/resources/generic").toASCIIString(), "FileSystem", "SSVEPGeneric");
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
configManager->expand("${Path_Data}/applications/${SSVEP_MindShooterFolderName}/resources/generic/textures").toASCIIString(), "FileSystem",
|
||||
"SSVEPGeneric");
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
configManager->expand("${Path_Data}/applications/${SSVEP_MindShooterFolderName}/resources/trainer").toASCIIString(), "FileSystem", "SSVEPTrainer");
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
configManager->expand("${Path_Data}/applications/${SSVEP_MindShooterFolderName}/resources/gui").toASCIIString(), "FileSystem", "CEGUI");
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(CString(m_ScenarioDir + "/appconf/materials").toASCIIString(), "FileSystem", "CEGUI");
|
||||
|
||||
Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("SSVEP");
|
||||
Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("SSVEPTrainer");
|
||||
Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("SSVEPGeneric");
|
||||
Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("CEGUI");
|
||||
}
|
||||
|
||||
bool CApplication::frameStarted(const Ogre::FrameEvent& /*evt*/)
|
||||
{
|
||||
m_currentFrame++;
|
||||
m_currentFrame %= int(m_screenRefreshRate);
|
||||
|
||||
|
||||
for (size_t i = 0; i < m_commands.size(); ++i) { m_commands[i]->processFrame(); }
|
||||
|
||||
this->processFrame(m_currentFrame);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CApplication::go()
|
||||
{
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "Associating application as Ogre frame listener\n";
|
||||
|
||||
m_root->addFrameListener(this);
|
||||
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "Entering Ogre rendering loop\n";
|
||||
m_root->startRendering();
|
||||
(*m_logManager) << Kernel::LogLevel_Debug << "Ogre rendering loop finished ... exiting\n";
|
||||
}
|
||||
|
||||
void CApplication::stopExperiment()
|
||||
{
|
||||
(*m_logManager) << Kernel::LogLevel_Info << "[!] Experiment halting\n";
|
||||
this->exit();
|
||||
}
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
Executable
+114
@@ -0,0 +1,114 @@
|
||||
#pragma once
|
||||
|
||||
#include "ovams_defines.h"
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
#include <Ogre.h>
|
||||
#include <vector>
|
||||
#include <CEGUI.h>
|
||||
#if (CEGUI_VERSION_MAJOR > 0) || (CEGUI_VERSION_MINOR >= 8)
|
||||
#include <CEGUI/RendererModules/Ogre/Renderer.h>
|
||||
#else
|
||||
#include <RendererModules/Ogre/CEGUIOgreRenderer.h>
|
||||
#endif
|
||||
|
||||
#include "ovamsICommand.h"
|
||||
#include "ovamsCBasicPainter.h"
|
||||
|
||||
#include <tcptagging/IStimulusSender.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CApplication : public Ogre::FrameListener, public Ogre::WindowEventListener
|
||||
{
|
||||
public:
|
||||
explicit CApplication(const CString& scenarioDir) : m_ScenarioDir(scenarioDir) { m_StimulusSender = TCPTagging::CreateStimulusSender(); }
|
||||
~CApplication() override;
|
||||
|
||||
void addCommand(ICommand* cmd) { m_commands.push_back(cmd); }
|
||||
virtual bool setup(Kernel::IKernelContext* poKernelContext);
|
||||
void go();
|
||||
|
||||
virtual void startExperiment() { (*m_logManager) << Kernel::LogLevel_Info << "[!] Experiment starting\n"; }
|
||||
virtual void stopExperiment();
|
||||
virtual void startFlickering() { }
|
||||
virtual void stopFlickering() { }
|
||||
|
||||
virtual void debugAction1() { }
|
||||
virtual void debugAction2() { }
|
||||
virtual void debugAction3() { }
|
||||
virtual void debugAction4() { }
|
||||
|
||||
virtual void setTarget(int /*i*/) { }
|
||||
|
||||
Ogre::RenderWindow* getWindow() const { return m_window; }
|
||||
Ogre::SceneManager* getSceneManager() const { return m_sceneManager; }
|
||||
Ogre::SceneNode* getSceneNode() const { return m_sceneNode; }
|
||||
Ogre::Camera* getCamera() const { return m_camera; }
|
||||
Ogre::SceneNode* getCameraNode() const { return m_cameraNode; }
|
||||
CBasicPainter* getPainter() const { return m_painter; }
|
||||
Kernel::ILogManager& getLogManager() const { return (*m_logManager); }
|
||||
Kernel::IConfigurationManager* getConfigurationManager() const { return &(m_kernelCtx->getConfigurationManager()); }
|
||||
std::vector<size_t>* getFrequencies() { return &m_frequencies; }
|
||||
|
||||
void exit() { m_continueRendering = false; }
|
||||
|
||||
void resizeViewport() const;
|
||||
|
||||
Kernel::ILogManager& logPrefix() const
|
||||
{
|
||||
(*m_logManager) << Kernel::LogLevel_Trace << "% [" << m_currentTime << "] ";
|
||||
return (*m_logManager);
|
||||
}
|
||||
|
||||
CString m_ScenarioDir;
|
||||
|
||||
TCPTagging::IStimulusSender* m_StimulusSender = nullptr;
|
||||
|
||||
protected:
|
||||
Kernel::IKernelContext* m_kernelCtx = nullptr;
|
||||
Kernel::ILogManager* m_logManager = nullptr;
|
||||
|
||||
double m_screenRefreshRate = 0;
|
||||
CBasicPainter* m_painter = nullptr;
|
||||
|
||||
bool m_continueRendering = true;
|
||||
size_t m_currentFrame = 0;
|
||||
uint64_t m_currentTime = 0;
|
||||
|
||||
Ogre::Root* m_root = nullptr;
|
||||
Ogre::SceneManager* m_sceneManager = nullptr;
|
||||
Ogre::Camera* m_camera = nullptr;
|
||||
Ogre::SceneNode* m_cameraNode = nullptr;
|
||||
Ogre::RenderWindow* m_window = nullptr;
|
||||
Ogre::Viewport* m_viewport = nullptr;
|
||||
Ogre::SceneNode* m_sceneNode = nullptr;
|
||||
|
||||
CEGUI::OgreRenderer* m_guiRenderer = nullptr;
|
||||
CEGUI::WindowManager* m_guiWindowManager = nullptr;
|
||||
CEGUI::Window* m_sheet = nullptr;
|
||||
|
||||
std::vector<size_t> m_frequencies;
|
||||
|
||||
std::vector<ICommand*> m_commands;
|
||||
|
||||
virtual void processFrame(const size_t /*currentFrame*/) { m_currentTime++; }
|
||||
|
||||
bool frameRenderingQueued(const Ogre::FrameEvent& evt) override { return (m_continueRendering && !m_window->isClosed()); }
|
||||
bool frameStarted(const Ogre::FrameEvent& evt) override;
|
||||
|
||||
bool configure() const;
|
||||
void setupResources() const;
|
||||
|
||||
private:
|
||||
void setOgreParameters() const; // Set some render parameters
|
||||
|
||||
void initCEGUI(const char* logFilename);
|
||||
|
||||
Ogre::uint32 m_windowWidth = 0;
|
||||
Ogre::uint32 m_windowHeight = 0;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
Masterarbeit/openvibe/extras-master/applications/demos/ssvep-mind-shooter/src/ovamsCBasicPainter.cpp
Executable
+248
@@ -0,0 +1,248 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsCBasicPainter.h"
|
||||
#include "ovamsCApplication.h"
|
||||
|
||||
#if (OGRE_VERSION_MAJOR > 1) || ((OGRE_VERSION_MAJOR == 1) && (OGRE_VERSION_MINOR >= 9))
|
||||
#include "Overlay/OgreOverlaySystem.h"
|
||||
#include "Overlay/OgreOverlayContainer.h"
|
||||
#include "Overlay/OgreOverlayElement.h"
|
||||
#endif
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
CBasicPainter::CBasicPainter(CApplication* application)
|
||||
: m_application(application), m_sceneManager(application->getSceneManager())
|
||||
{
|
||||
m_aabInf.setInfinite();
|
||||
|
||||
#if (OGRE_VERSION_MAJOR > 1) || ((OGRE_VERSION_MAJOR == 1) && (OGRE_VERSION_MINOR >= 9))
|
||||
// on Ogre 1.9, overlay system needs to be manually created
|
||||
Ogre::OverlaySystem* pOverlaySystem = OGRE_NEW Ogre::OverlaySystem();
|
||||
m_sceneManager->addRenderQueueListener(pOverlaySystem);
|
||||
#endif
|
||||
|
||||
m_overlayManager = Ogre::OverlayManager::getSingletonPtr();
|
||||
|
||||
(m_application->getLogManager()) << Kernel::LogLevel_Debug << " + Creating OverlayManager\n";
|
||||
Ogre::Overlay* overlay = m_overlayManager->create("TextOverlay");
|
||||
|
||||
|
||||
m_overlayContainer = dynamic_cast<Ogre::OverlayContainer*>(m_overlayManager->createOverlayElement("Panel", "TextContainer"));
|
||||
m_overlayContainer->setDimensions(1, 1);
|
||||
m_overlayContainer->setPosition(0, 0);
|
||||
|
||||
overlay->add2D(m_overlayContainer);
|
||||
overlay->show();
|
||||
}
|
||||
|
||||
|
||||
Ogre::ManualObject* CBasicPainter::paintRectangle(const Ogre::RealRect& oRectangle, const Ogre::ColourValue color, const int plane) const
|
||||
{
|
||||
Ogre::ManualObject* object = m_sceneManager->createManualObject();
|
||||
object->begin("BasicSurface/Diffuse", Ogre::RenderOperation::OT_TRIANGLE_FAN);
|
||||
object->setUseIdentityProjection(true);
|
||||
object->setUseIdentityView(true);
|
||||
|
||||
object->position(oRectangle.right, oRectangle.top, 0.0);
|
||||
object->colour(color);
|
||||
object->index(0);
|
||||
|
||||
object->position(oRectangle.left, oRectangle.top, 0.0);
|
||||
object->colour(color);
|
||||
object->index(1);
|
||||
|
||||
object->position(oRectangle.left, oRectangle.bottom, 0.0);
|
||||
object->colour(color);
|
||||
object->index(2);
|
||||
|
||||
object->position(oRectangle.right, oRectangle.bottom, 0.0);
|
||||
object->colour(color);
|
||||
object->index(3);
|
||||
|
||||
object->index(0);
|
||||
|
||||
object->end();
|
||||
|
||||
object->setBoundingBox(m_aabInf);
|
||||
object->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY - plane);
|
||||
|
||||
object->setVisible(true);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
Ogre::ManualObject* CBasicPainter::paintTexturedRectangle(const Ogre::RealRect& oRectangle, const Ogre::String& sSurface, const int plane) const
|
||||
{
|
||||
Ogre::ManualObject* object = m_sceneManager->createManualObject();
|
||||
object->begin(sSurface, Ogre::RenderOperation::OT_TRIANGLE_FAN);
|
||||
object->setUseIdentityProjection(true);
|
||||
object->setUseIdentityView(true);
|
||||
|
||||
object->position(oRectangle.right, oRectangle.top, 0.0);
|
||||
object->textureCoord(0, 0);
|
||||
object->index(0);
|
||||
|
||||
object->position(oRectangle.left, oRectangle.top, 0.0);
|
||||
object->textureCoord(1, 0);
|
||||
object->index(1);
|
||||
|
||||
object->position(oRectangle.left, oRectangle.bottom, 0.0);
|
||||
object->textureCoord(1, 1);
|
||||
object->index(2);
|
||||
|
||||
object->position(oRectangle.right, oRectangle.bottom, 0.0);
|
||||
object->textureCoord(0, 1);
|
||||
object->index(3);
|
||||
|
||||
object->index(0);
|
||||
|
||||
object->end();
|
||||
|
||||
object->setBoundingBox(m_aabInf);
|
||||
object->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY - plane);
|
||||
|
||||
object->setVisible(true);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
Ogre::ManualObject* CBasicPainter::paintTriangle(const Ogre::Vector2 p1, const Ogre::Vector2 p2, const Ogre::Vector2 p3,
|
||||
const Ogre::ColourValue color, const int plane) const
|
||||
{
|
||||
Ogre::ManualObject* object = m_sceneManager->createManualObject();
|
||||
object->begin("BasicSurface/Diffuse", Ogre::RenderOperation::OT_TRIANGLE_FAN);
|
||||
object->setUseIdentityProjection(true);
|
||||
object->setUseIdentityView(true);
|
||||
|
||||
object->position(p1.x, p1.y, 0.0);
|
||||
object->colour(color);
|
||||
object->index(0);
|
||||
|
||||
object->position(p2.x, p2.y, 0.0);
|
||||
object->colour(color);
|
||||
object->index(1);
|
||||
|
||||
object->position(p3.x, p3.y, 0.0);
|
||||
object->colour(color);
|
||||
object->index(2);
|
||||
|
||||
object->index(0);
|
||||
|
||||
object->end();
|
||||
|
||||
object->setBoundingBox(m_aabInf);
|
||||
object->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY - plane);
|
||||
|
||||
object->setVisible(true);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
Ogre::ManualObject* CBasicPainter::paintTriangle(const Ogre::Vector3 p1, const Ogre::Vector3 p2, const Ogre::Vector3 p3,
|
||||
const Ogre::ColourValue color, const int plane) const
|
||||
{
|
||||
Ogre::ManualObject* object = m_sceneManager->createManualObject();
|
||||
object->begin("BasicSurface/Diffuse", Ogre::RenderOperation::OT_TRIANGLE_FAN);
|
||||
object->setUseIdentityProjection(true);
|
||||
object->setUseIdentityView(true);
|
||||
|
||||
object->position(p1.x, p1.y, p1.z);
|
||||
object->colour(color);
|
||||
object->index(0);
|
||||
|
||||
object->position(p2.x, p2.y, p2.z);
|
||||
object->colour(color);
|
||||
object->index(1);
|
||||
|
||||
object->position(p3.x, p3.y, p3.z);
|
||||
object->colour(color);
|
||||
object->index(2);
|
||||
|
||||
object->index(0);
|
||||
|
||||
object->end();
|
||||
|
||||
object->setBoundingBox(m_aabInf);
|
||||
object->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY - plane);
|
||||
|
||||
object->setVisible(true);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
Ogre::ManualObject* CBasicPainter::paintCircle(const Ogre::Real rX, const Ogre::Real rY, const Ogre::Real rR, const Ogre::ColourValue color,
|
||||
const bool bFilled, const int plane) const
|
||||
{
|
||||
Ogre::ManualObject* object = m_sceneManager->createManualObject();
|
||||
|
||||
if (bFilled) { object->begin("BasicSurface/Diffuse", Ogre::RenderOperation::OT_TRIANGLE_FAN); }
|
||||
else { object->begin("BasicSurface/Diffuse", Ogre::RenderOperation::OT_LINE_STRIP); }
|
||||
|
||||
object->setUseIdentityProjection(true);
|
||||
object->setUseIdentityView(true);
|
||||
|
||||
float const fAccuracy = 16;
|
||||
unsigned uiIndex = 0;
|
||||
|
||||
for (float theta = 0; theta <= 2 * Ogre::Math::PI; theta += Ogre::Math::PI / fAccuracy)
|
||||
{
|
||||
object->position(rX + rR * cos(theta), rY + rR * sin(theta), 0);
|
||||
object->colour(color);
|
||||
object->index(uiIndex++);
|
||||
}
|
||||
|
||||
object->index(0);
|
||||
object->end();
|
||||
object->setBoundingBox(m_aabInf);
|
||||
object->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY - plane);
|
||||
object->setVisible(true);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
Ogre::ManualObject* CBasicPainter::beginPainingPolygon(bool /*filled*/, const Ogre::String& material) const
|
||||
{
|
||||
Ogre::ManualObject* object = m_sceneManager->createManualObject();
|
||||
object->begin(material, Ogre::RenderOperation::OT_TRIANGLE_FAN);
|
||||
object->setUseIdentityProjection(true);
|
||||
object->setUseIdentityView(true);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
void CBasicPainter::addPointToPolygon(Ogre::ManualObject* pPolygon, const Ogre::Real rX, const Ogre::Real rY, const Ogre::ColourValue color)
|
||||
{
|
||||
pPolygon->position(rX, rY, 0.0);
|
||||
pPolygon->colour(color);
|
||||
}
|
||||
|
||||
void CBasicPainter::finishPaintingPolygon(Ogre::ManualObject* pPolygon, const int plane) const
|
||||
{
|
||||
pPolygon->end();
|
||||
pPolygon->setBoundingBox(m_aabInf);
|
||||
pPolygon->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY - plane);
|
||||
pPolygon->setVisible(true);
|
||||
}
|
||||
|
||||
|
||||
void CBasicPainter::paintText(const std::string& sID, const std::string& sText, const Ogre::Real rX, const Ogre::Real rY,
|
||||
const Ogre::Real rWidth, const Ogre::Real rHeight, const Ogre::ColourValue& color) const
|
||||
{
|
||||
Ogre::OverlayElement* text = m_overlayManager->createOverlayElement("TextArea", sID);
|
||||
|
||||
text->setDimensions(rWidth, rHeight);
|
||||
text->setMetricsMode(Ogre::GMM_PIXELS);
|
||||
text->setPosition(rX, rY);
|
||||
text->setParameter("font_name", "DejaVu");
|
||||
text->setColour(color);
|
||||
text->setCaption(sText);
|
||||
|
||||
m_overlayContainer->addChild(text);
|
||||
}
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
|
||||
#endif
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
/// this class is a wrapper around some ogre methods to display basic shapes
|
||||
|
||||
#include <Ogre.h>
|
||||
|
||||
#if (OGRE_VERSION_MAJOR > 1) || ((OGRE_VERSION_MAJOR == 1) && (OGRE_VERSION_MINOR >= 9))
|
||||
#include "Overlay/OgreOverlayManager.h"
|
||||
#endif
|
||||
|
||||
#define SSVEP_DEFAULT_COLOUR Ogre::ColourValue(1.0f, 1.0f, 1.0f)
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CApplication;
|
||||
|
||||
class CBasicPainter
|
||||
{
|
||||
public:
|
||||
explicit CBasicPainter(CApplication* application);
|
||||
~CBasicPainter() {}
|
||||
|
||||
Ogre::SceneManager* getSceneManager() const { return m_sceneManager; }
|
||||
|
||||
Ogre::ManualObject* paintRectangle(const Ogre::RealRect& oRectangle, const Ogre::ColourValue color = SSVEP_DEFAULT_COLOUR, const int plane = 1) const;
|
||||
Ogre::ManualObject* paintTexturedRectangle(const Ogre::RealRect& oRectangle, const Ogre::String& sSurface, const int plane = 1) const;
|
||||
Ogre::ManualObject* paintTriangle(Ogre::Vector2 p1, Ogre::Vector2 p2, Ogre::Vector2 p3, Ogre::ColourValue color = SSVEP_DEFAULT_COLOUR,
|
||||
int plane = 1) const;
|
||||
Ogre::ManualObject* paintTriangle(Ogre::Vector3 p1, Ogre::Vector3 p2, Ogre::Vector3 p3, Ogre::ColourValue color = SSVEP_DEFAULT_COLOUR,
|
||||
int plane = 1) const;
|
||||
//Ogre::ManualObject* paintTexturedTriangle(Ogre::Vector2 p1, Ogre::Vector2 p2, Ogre::Vector2 p3, Ogre::String sSurface, int plane = 1);
|
||||
Ogre::ManualObject* paintCircle(Ogre::Real rX, Ogre::Real rY, Ogre::Real rR, Ogre::ColourValue color = SSVEP_DEFAULT_COLOUR, bool bFilled = true,
|
||||
int plane = 1) const;
|
||||
|
||||
Ogre::ManualObject* beginPainingPolygon(bool filled = true, const Ogre::String& material = "BasicSurface/Diffuse") const;
|
||||
static void addPointToPolygon(Ogre::ManualObject* pPolygon, Ogre::Real rX, Ogre::Real rY, Ogre::ColourValue color = SSVEP_DEFAULT_COLOUR);
|
||||
void finishPaintingPolygon(Ogre::ManualObject* pPolygon, int plane = 1) const;
|
||||
|
||||
void paintText(const std::string& sID, const std::string& sText, Ogre::Real rX, Ogre::Real rY, Ogre::Real rWidth, Ogre::Real rHeight,
|
||||
const Ogre::ColourValue& color) const;
|
||||
|
||||
protected:
|
||||
CApplication* m_application = nullptr;
|
||||
Ogre::OverlayManager* m_overlayManager = nullptr;
|
||||
Ogre::OverlayContainer* m_overlayContainer = nullptr;
|
||||
Ogre::SceneManager* m_sceneManager = nullptr;
|
||||
Ogre::AxisAlignedBox m_aabInf;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsCCommandCamera.h"
|
||||
#include "ovamsCApplication.h"
|
||||
#include "ovamsCVRPNServer.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
void CCommandCamera::updateCamera()
|
||||
{
|
||||
Ogre::Vector3 translation(0, 0, 0);
|
||||
const Ogre::Real translationSpeed = 10.0;
|
||||
|
||||
if (m_keysPressed[OIS::KC_W]) { translation.z -= translationSpeed; }
|
||||
if (m_keysPressed[OIS::KC_D]) { translation.x += translationSpeed; }
|
||||
if (m_keysPressed[OIS::KC_A]) { translation.x -= translationSpeed; }
|
||||
if (m_keysPressed[OIS::KC_S]) { translation.z += translationSpeed; }
|
||||
|
||||
|
||||
const Ogre::Vector3 translateVectorFinal = m_application->getCamera()->getDerivedOrientation() * translation;
|
||||
m_application->getCameraNode()->translate(translateVectorFinal, Ogre::Node::TS_WORLD);
|
||||
}
|
||||
|
||||
void CCommandCamera::processFrame()
|
||||
{
|
||||
ICommandOIS::processFrame();
|
||||
|
||||
this->updateCamera();
|
||||
|
||||
if (m_keysPressed[OIS::KC_NUMPAD1])
|
||||
{
|
||||
m_application->debugAction1();
|
||||
m_keysPressed[OIS::KC_NUMPAD1] = false;
|
||||
}
|
||||
if (m_keysPressed[OIS::KC_NUMPAD2])
|
||||
{
|
||||
m_application->debugAction2();
|
||||
m_keysPressed[OIS::KC_NUMPAD2] = false;
|
||||
}
|
||||
if (m_keysPressed[OIS::KC_NUMPAD3])
|
||||
{
|
||||
m_application->debugAction3();
|
||||
m_keysPressed[OIS::KC_NUMPAD3] = false;
|
||||
}
|
||||
if (m_keysPressed[OIS::KC_NUMPAD4])
|
||||
{
|
||||
m_application->debugAction4();
|
||||
m_keysPressed[OIS::KC_NUMPAD4] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CCommandCamera::receiveKeyPressedEvent(const OIS::KeyCode key)
|
||||
{
|
||||
if (key == OIS::KC_LCONTROL) { m_bCameraMode = true; }
|
||||
|
||||
if (key == OIS::KC_W) { m_keysPressed[OIS::KC_W] = true; }
|
||||
if (key == OIS::KC_A) { m_keysPressed[OIS::KC_A] = true; }
|
||||
if (key == OIS::KC_S) { m_keysPressed[OIS::KC_S] = true; }
|
||||
if (key == OIS::KC_D) { m_keysPressed[OIS::KC_D] = true; }
|
||||
if (key == OIS::KC_NUMPAD1) { m_keysPressed[OIS::KC_NUMPAD1] = true; }
|
||||
if (key == OIS::KC_NUMPAD2) { m_keysPressed[OIS::KC_NUMPAD2] = true; }
|
||||
if (key == OIS::KC_NUMPAD3) { m_keysPressed[OIS::KC_NUMPAD3] = true; }
|
||||
if (key == OIS::KC_NUMPAD4) { m_keysPressed[OIS::KC_NUMPAD4] = true; }
|
||||
if (key == OIS::KC_ESCAPE) { m_application->exit(); }
|
||||
}
|
||||
|
||||
void CCommandCamera::receiveKeyReleasedEvent(const OIS::KeyCode key)
|
||||
{
|
||||
if (key == OIS::KC_LCONTROL) { m_bCameraMode = false; }
|
||||
|
||||
if (key == OIS::KC_W) { m_keysPressed[OIS::KC_W] = false; }
|
||||
if (key == OIS::KC_A) { m_keysPressed[OIS::KC_A] = false; }
|
||||
if (key == OIS::KC_S) { m_keysPressed[OIS::KC_S] = false; }
|
||||
if (key == OIS::KC_D) { m_keysPressed[OIS::KC_D] = false; }
|
||||
if (key == OIS::KC_NUMPAD1) { m_keysPressed[OIS::KC_NUMPAD1] = false; }
|
||||
if (key == OIS::KC_NUMPAD2) { m_keysPressed[OIS::KC_NUMPAD2] = false; }
|
||||
if (key == OIS::KC_NUMPAD3) { m_keysPressed[OIS::KC_NUMPAD3] = false; }
|
||||
if (key == OIS::KC_NUMPAD4) { m_keysPressed[OIS::KC_NUMPAD4] = false; }
|
||||
}
|
||||
|
||||
void CCommandCamera::receiveMouseEvent(const OIS::MouseEvent& event)
|
||||
{
|
||||
const Ogre::Real rotationSpeedMouse = 1.0F;
|
||||
|
||||
std::cout << m_application->getCamera()->getOrientation() << "\n";
|
||||
if (m_bCameraMode)
|
||||
{
|
||||
m_application->getCamera()->yaw(Ogre::Degree(-float(event.state.X.rel) * rotationSpeedMouse));
|
||||
m_application->getCamera()->pitch(Ogre::Degree(-float(event.state.Y.rel) * rotationSpeedMouse));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "ovamsICommandOIS.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CVRPNServer;
|
||||
|
||||
class CCommandCamera final : public ICommandOIS
|
||||
{
|
||||
public:
|
||||
explicit CCommandCamera(CApplication* application): ICommandOIS(application) { }
|
||||
~CCommandCamera() override { }
|
||||
void processFrame() override;
|
||||
|
||||
void receiveKeyPressedEvent(OIS::KeyCode key) override;
|
||||
void receiveKeyReleasedEvent(OIS::KeyCode key) override;
|
||||
void receiveMouseEvent(const OIS::MouseEvent& event) override;
|
||||
|
||||
private:
|
||||
void updateCamera();
|
||||
std::map<OIS::KeyCode, bool> m_keysPressed;
|
||||
|
||||
bool m_bCameraMode = false;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "ovamsICommandVRPNButton.h"
|
||||
#include "ovamsCApplication.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CApplication;
|
||||
|
||||
class CCommandReceiveTarget final : public ICommandVRPNButton
|
||||
{
|
||||
public:
|
||||
explicit CCommandReceiveTarget(CApplication* application) : ICommandVRPNButton(application, "SSVEP_VRPN_TargetControl") {}
|
||||
~CCommandReceiveTarget() override {}
|
||||
|
||||
void execute(const int button, const int state) override { dynamic_cast<CApplication*>(m_application)->setTarget(button); }
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsCCommandStartStop.h"
|
||||
#include "ovamsCApplication.h"
|
||||
#include "ovamsCVRPNServer.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
CCommandStartStop::CCommandStartStop(CApplication* application)
|
||||
: ICommandOIS(application)
|
||||
{
|
||||
m_vrpnServer = CVRPNServer::getInstance(application);
|
||||
m_vrpnServer->addButton("SSVEP_VRPN_StartStop", 2);
|
||||
}
|
||||
|
||||
CCommandStartStop::~CCommandStartStop()
|
||||
{
|
||||
m_application->getLogManager() << Kernel::LogLevel_Info << "End message sent\n";
|
||||
m_vrpnServer->changeButtonState("SSVEP_VRPN_StartStop", 1, 1);
|
||||
m_vrpnServer->processFrame();
|
||||
}
|
||||
|
||||
void CCommandStartStop::processFrame()
|
||||
{
|
||||
ICommandOIS::processFrame();
|
||||
m_vrpnServer->processFrame();
|
||||
}
|
||||
|
||||
void CCommandStartStop::receiveKeyPressedEvent(const OIS::KeyCode key)
|
||||
{
|
||||
if (key == OIS::KC_SPACE)
|
||||
{
|
||||
m_application->getLogManager() << Kernel::LogLevel_Info << "Start message sent\n";
|
||||
m_vrpnServer->changeButtonState("SSVEP_VRPN_StartStop", 0, 1);
|
||||
}
|
||||
|
||||
if (key == OIS::KC_ESCAPE) { m_application->exit(); }
|
||||
if (key == OIS::KC_INSERT) { m_application->getWindow()->writeContentsToFile("screenshot.png"); }
|
||||
}
|
||||
|
||||
void CCommandStartStop::receiveKeyReleasedEvent(const OIS::KeyCode key)
|
||||
{
|
||||
if (key == OIS::KC_SPACE) { m_vrpnServer->changeButtonState("SSVEP_VRPN_StartStop", 0, 0); }
|
||||
}
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "ovamsICommandOIS.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CVRPNServer;
|
||||
|
||||
class CCommandStartStop final : public ICommandOIS
|
||||
{
|
||||
public:
|
||||
explicit CCommandStartStop(CApplication* application);
|
||||
~CCommandStartStop() override;
|
||||
|
||||
void processFrame() override;
|
||||
|
||||
void receiveKeyPressedEvent(OIS::KeyCode key) override;
|
||||
void receiveKeyReleasedEvent(OIS::KeyCode key) override;
|
||||
|
||||
private:
|
||||
CVRPNServer* m_vrpnServer = nullptr;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsCCommandStimulatorControl.h"
|
||||
#include "ovamsCApplication.h"
|
||||
|
||||
#include <toolkit/ovtk_stimulations.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
void CCommandStimulatorControl::execute(const int button, const int /*state*/)
|
||||
{
|
||||
// only run the commands once, skip
|
||||
|
||||
switch (button)
|
||||
{
|
||||
case 0:
|
||||
m_application->startExperiment();
|
||||
m_application->m_StimulusSender->sendStimulation(OVTK_StimulationId_ExperimentStart);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
m_application->stopExperiment();
|
||||
m_application->m_StimulusSender->sendStimulation(OVTK_StimulationId_ExperimentStop);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_application->startFlickering();
|
||||
m_application->m_StimulusSender->sendStimulation(OVTK_StimulationId_VisualStimulationStart);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
m_application->stopFlickering();
|
||||
m_application->m_StimulusSender->sendStimulation(OVTK_StimulationId_VisualStimulationStop);
|
||||
break;
|
||||
|
||||
default:
|
||||
m_application->getLogManager() << Kernel::LogLevel_Error << "[ERROR] Unknown command\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "ovamsICommandVRPNButton.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CCommandStimulatorControl final : public ICommandVRPNButton
|
||||
{
|
||||
public:
|
||||
explicit CCommandStimulatorControl(CApplication* application) : ICommandVRPNButton(application, "SSVEP_VRPN_StimulatorControl") {}
|
||||
~CCommandStimulatorControl() override { }
|
||||
|
||||
void execute(const int button, const int state) override;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsCSSVEPFlickeringObject.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
CSSVEPFlickeringObject::CSSVEPFlickeringObject(Ogre::SceneNode* objectNode, const uint64_t stimulationPattern)
|
||||
: m_objectNode(objectNode), m_stimulationPattern(stimulationPattern)
|
||||
{
|
||||
static int nextid = 0;
|
||||
m_iId = ++nextid;
|
||||
}
|
||||
|
||||
void CSSVEPFlickeringObject::setVisible(const bool visibility)
|
||||
{
|
||||
if ((!m_visible && visibility) || (m_visible && !visibility)) { m_objectNode->flipVisibility(); }
|
||||
m_visible = visibility;
|
||||
}
|
||||
|
||||
void CSSVEPFlickeringObject::processFrame()
|
||||
{
|
||||
// If the bit for the frame is '1', set to visible
|
||||
if (((m_stimulationPattern >> m_currentFrame) % 2) == 1) { this->setVisible(true); }
|
||||
else { this->setVisible(false); }
|
||||
|
||||
m_currentFrame++;
|
||||
|
||||
// Start over when only '1' is left
|
||||
if (m_stimulationPattern >> m_currentFrame == 1) { m_currentFrame = 0; }
|
||||
}
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
#include <Ogre.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CSSVEPFlickeringObject
|
||||
{
|
||||
public:
|
||||
//SP CSSVEPFlickeringObject( Ogre::SceneNode* objectNode, size_t LitFrames, size_t DarkFrames );
|
||||
CSSVEPFlickeringObject(Ogre::SceneNode* objectNode, uint64_t stimulationPattern);
|
||||
virtual ~CSSVEPFlickeringObject() { }
|
||||
|
||||
virtual void setVisible(bool visibility);
|
||||
virtual void processFrame();
|
||||
|
||||
protected:
|
||||
Ogre::SceneNode* m_objectNode = nullptr;
|
||||
size_t m_currentFrame = 0;
|
||||
//SP size_t m_litFrames = 0;
|
||||
//SP size_t m_darkFrames = 0;
|
||||
uint64_t m_stimulationPattern = 0;
|
||||
|
||||
private:
|
||||
|
||||
bool m_visible = true;
|
||||
int m_iId = 0;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
Executable
Executable
Executable
+52
@@ -0,0 +1,52 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsCVRPNServer.h"
|
||||
#include "ovamsCApplication.h"
|
||||
|
||||
#include <vrpn_Connection.h>
|
||||
#include <vrpn_Button.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
CVRPNServer* CVRPNServer::m_vrpnServerInstance = nullptr;
|
||||
CApplication* CVRPNServer::m_application = nullptr;
|
||||
|
||||
CVRPNServer::CVRPNServer(CApplication* application)
|
||||
{
|
||||
m_application = application;
|
||||
|
||||
const int port = int(m_application->getConfigurationManager()->expandAsInteger("${VRPN_ExternalServerPort}"));
|
||||
|
||||
m_application->getLogManager() << Kernel::LogLevel_Debug << "VRPN SERVER PORT :" << port << "\n";
|
||||
m_connection = vrpn_create_server_connection(port);
|
||||
}
|
||||
|
||||
CVRPNServer* CVRPNServer::getInstance(CApplication* application)
|
||||
{
|
||||
if (m_vrpnServerInstance == nullptr) { m_vrpnServerInstance = new CVRPNServer(application); }
|
||||
return m_vrpnServerInstance;
|
||||
}
|
||||
|
||||
void CVRPNServer::addButton(const std::string& name, const int buttonCount)
|
||||
{
|
||||
m_oButtonServer.insert(std::pair<std::string, vrpn_Button_Server*>(name, new vrpn_Button_Server(name.c_str(), m_connection, buttonCount)));
|
||||
m_oButtonCache[name].clear();
|
||||
m_oButtonCache[name].resize(buttonCount);
|
||||
}
|
||||
|
||||
void CVRPNServer::processFrame()
|
||||
{
|
||||
for (auto it = m_oButtonServer.begin(); it != m_oButtonServer.end(); ++it) { it->second->mainloop(); }
|
||||
m_connection->mainloop();
|
||||
}
|
||||
|
||||
void CVRPNServer::changeButtonState(const std::string& name, const int iIndex, const int state)
|
||||
{
|
||||
m_oButtonServer[name]->set_button(iIndex, state);
|
||||
m_oButtonCache[name][iIndex] = state;
|
||||
}
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
class vrpn_Connection;
|
||||
class vrpn_Button_Server;
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CApplication;
|
||||
|
||||
class CVRPNServer
|
||||
{
|
||||
public:
|
||||
static CVRPNServer* getInstance(CApplication* application);
|
||||
~CVRPNServer() = default;
|
||||
void processFrame();
|
||||
|
||||
void addButton(const std::string& name, const int buttonCount);
|
||||
void changeButtonState(const std::string& name, const int iIndex, const int state);
|
||||
int getButtonState(const std::string& name, const int iIndex) { return m_oButtonCache[name][iIndex]; }
|
||||
|
||||
private:
|
||||
static CVRPNServer* m_vrpnServerInstance;
|
||||
static CApplication* m_application;
|
||||
|
||||
explicit CVRPNServer(CApplication* application);
|
||||
|
||||
vrpn_Connection* m_connection = nullptr;
|
||||
std::map<std::string, vrpn_Button_Server*> m_oButtonServer;
|
||||
std::map<std::string, std::vector<int>> m_oButtonCache;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class CApplication;
|
||||
|
||||
class ICommand
|
||||
{
|
||||
public:
|
||||
explicit ICommand(CApplication* application) : m_application(application) {}
|
||||
virtual ~ICommand() {}
|
||||
virtual void processFrame() = 0;
|
||||
|
||||
protected:
|
||||
CApplication* m_application = nullptr;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
Executable
+107
@@ -0,0 +1,107 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsICommandOIS.h"
|
||||
#include "ovamsCApplication.h"
|
||||
|
||||
#define SSVEP_NO_MOUSE_CAPTURE
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
OIS::InputManager* ICommandOIS::m_inputManager = nullptr;
|
||||
OIS::Keyboard* ICommandOIS::m_keyboard = nullptr;
|
||||
OIS::Mouse* ICommandOIS::m_mouse = nullptr;
|
||||
|
||||
int ICommandOIS::m_nInstance = 0;
|
||||
std::vector<ICommandOIS*> ICommandOIS::m_instances;
|
||||
|
||||
|
||||
ICommandOIS::ICommandOIS(CApplication* application)
|
||||
: ICommand(application)
|
||||
{
|
||||
if (m_keyboard == nullptr)
|
||||
{
|
||||
OIS::ParamList paramList;
|
||||
std::ostringstream windowHandleString;
|
||||
size_t windowHandle;
|
||||
|
||||
|
||||
m_application->getWindow()->getCustomAttribute("WINDOW", &windowHandle);
|
||||
|
||||
windowHandleString << windowHandle;
|
||||
|
||||
paramList.insert(std::make_pair(std::string("WINDOW"), windowHandleString.str()));
|
||||
paramList.insert(std::make_pair(std::string("x11_keyboard_grab"), "false"));
|
||||
|
||||
m_inputManager = OIS::InputManager::createInputSystem(paramList);
|
||||
|
||||
m_keyboard = dynamic_cast<OIS::Keyboard*>(m_inputManager->createInputObject(OIS::OISKeyboard, true));
|
||||
m_keyboard->setEventCallback(this);
|
||||
|
||||
#ifndef SSVEP_NO_MOUSE_CAPTURE
|
||||
m_mouse = static_cast<OIS::Mouse*>(m_inputManager->createInputObject(OIS::OISMouse, true));
|
||||
m_mouse->setEventCallback( this );
|
||||
#endif
|
||||
}
|
||||
|
||||
m_nInstance++;
|
||||
m_instances.push_back(this);
|
||||
}
|
||||
|
||||
ICommandOIS::~ICommandOIS()
|
||||
{
|
||||
--m_nInstance;
|
||||
|
||||
if (m_nInstance == 0)
|
||||
{
|
||||
if (m_inputManager != nullptr)
|
||||
{
|
||||
if (m_keyboard != nullptr)
|
||||
{
|
||||
m_application->getLogManager() << Kernel::LogLevel_Debug << "- destroy m_keyboard\n";
|
||||
m_inputManager->destroyInputObject(m_keyboard);
|
||||
m_keyboard = nullptr;
|
||||
#ifndef SSVEP_NO_MOUSE_CAPTURE
|
||||
m_application->getLogManager() << Kernel::LogLevel_Debug << "- destroy m_mouse\n";
|
||||
m_inputManager->destroyInputObject( m_mouse );
|
||||
m_mouse = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
OIS::InputManager::destroyInputSystem(m_inputManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ICommandOIS::processFrame()
|
||||
{
|
||||
m_keyboard->capture();
|
||||
#ifndef SSVEP_NO_MOUSE_CAPTURE
|
||||
m_mouse->capture();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool ICommandOIS::keyPressed(const OIS::KeyEvent& oEvent)
|
||||
{
|
||||
for (size_t i = 0; i < m_instances.size(); ++i) { m_instances[i]->receiveKeyPressedEvent(oEvent.key); }
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ICommandOIS::keyReleased(const OIS::KeyEvent& oEvent)
|
||||
{
|
||||
for (size_t i = 0; i < m_instances.size(); ++i) { m_instances[i]->receiveKeyReleasedEvent(oEvent.key); }
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef SSVEP_NO_MOUSE_CAPTURE
|
||||
bool ICommandOIS::mouseMoved(const OIS::MouseEvent & event)
|
||||
{
|
||||
for (size_t i = 0; i < m_instances.size(); ++i) { m_instances[i]->receiveMouseEvent(event); }
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <OIS.h>
|
||||
#include <OISKeyboard.h>
|
||||
#include <OISMouse.h>
|
||||
#include "ovamsICommand.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class ICommandOIS : public ICommand, OIS::KeyListener, OIS::MouseListener
|
||||
{
|
||||
static std::vector<ICommandOIS*> m_instances;
|
||||
static int m_nInstance;
|
||||
|
||||
protected:
|
||||
static OIS::InputManager* m_inputManager;
|
||||
static OIS::Keyboard* m_keyboard;
|
||||
static OIS::Mouse* m_mouse;
|
||||
|
||||
public:
|
||||
explicit ICommandOIS(CApplication* application);
|
||||
~ICommandOIS() override;
|
||||
|
||||
void processFrame() override;
|
||||
|
||||
protected:
|
||||
virtual void receiveKeyPressedEvent(OIS::KeyCode key) = 0;
|
||||
virtual void receiveKeyReleasedEvent(OIS::KeyCode key) = 0;
|
||||
virtual void receiveMouseEvent(const OIS::MouseEvent& /*oEvent*/) {}
|
||||
|
||||
private:
|
||||
bool keyPressed(const OIS::KeyEvent& oEvent) override;
|
||||
bool keyReleased(const OIS::KeyEvent& oEvent) override;
|
||||
bool mouseMoved(const OIS::MouseEvent& event) override { return true; }
|
||||
bool mousePressed(const OIS::MouseEvent& /*arg*/, OIS::MouseButtonID /*id*/) override { return true; }
|
||||
bool mouseReleased(const OIS::MouseEvent& /*arg*/, OIS::MouseButtonID /*id*/) override { return true; }
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsICommandVRPNAnalog.h"
|
||||
#include "ovamsCApplication.h"
|
||||
|
||||
#include <vrpn_Connection.h>
|
||||
#include <vrpn_Analog.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
static void VRPN_CALLBACK ssvep_vrpn_callback_analog(void* command, vrpn_ANALOGCB analog)
|
||||
{
|
||||
static_cast<ICommandVRPNAnalog*>(command)->execute(analog.num_channel, analog.channel);
|
||||
}
|
||||
|
||||
ICommandVRPNAnalog::ICommandVRPNAnalog(CApplication* application, const CString& name) : ICommand(application)
|
||||
{
|
||||
Kernel::IConfigurationManager* configManager = application->getConfigurationManager();
|
||||
|
||||
const std::string analogName = std::string(name.toASCIIString()) + "@" + (configManager->expand("${SSVEP_VRPNHost}")).toASCIIString();
|
||||
m_application->getLogManager() << Kernel::LogLevel_Debug << "+ m_vrpnAnalog = new vrpn_Analog_Remote(" << analogName << ")\n";
|
||||
|
||||
|
||||
m_vrpnAnalog = new vrpn_Analog_Remote(analogName.c_str());
|
||||
m_vrpnAnalog->register_change_handler(static_cast<void*>(this), ssvep_vrpn_callback_analog);
|
||||
}
|
||||
|
||||
ICommandVRPNAnalog::~ICommandVRPNAnalog()
|
||||
{
|
||||
m_application->getLogManager() << Kernel::LogLevel_Debug << "- delete m_vrpnAnalog\n";
|
||||
delete m_vrpnAnalog;
|
||||
}
|
||||
|
||||
void ICommandVRPNAnalog::processFrame() { m_vrpnAnalog->mainloop(); }
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "ovamsICommand.h"
|
||||
#include <array>
|
||||
|
||||
class vrpn_Analog_Remote;
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class ICommandVRPNAnalog : public ICommand
|
||||
{
|
||||
public:
|
||||
ICommandVRPNAnalog(CApplication* application, const CString& name);
|
||||
~ICommandVRPNAnalog() override;
|
||||
|
||||
void processFrame() override;
|
||||
virtual void execute(int channelCount, double* channel) = 0;
|
||||
|
||||
protected:
|
||||
vrpn_Analog_Remote* m_vrpnAnalog = nullptr;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovamsICommandVRPNButton.h"
|
||||
#include "ovamsCApplication.h"
|
||||
|
||||
#include <vrpn_Connection.h>
|
||||
#include <vrpn_Button.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
|
||||
static void VRPN_CALLBACK ssvep_vrpn_callback_button(void* command, vrpn_BUTTONCB button)
|
||||
{
|
||||
static_cast<ICommandVRPNButton*>(command)->execute(button.button, button.state);
|
||||
}
|
||||
|
||||
ICommandVRPNButton::ICommandVRPNButton(CApplication* application, const CString& name)
|
||||
: ICommand(application)
|
||||
{
|
||||
Kernel::IConfigurationManager* configManager = application->getConfigurationManager();
|
||||
const std::string buttonName = std::string(name.toASCIIString()) + std::string("@") + std::string(
|
||||
(configManager->expand("${SSVEP_VRPNHost}")).toASCIIString());
|
||||
|
||||
m_application->getLogManager() << Kernel::LogLevel_Debug << "+ m_vrpnButton = new vrpn_Button_Remote(" << buttonName << ")\n";
|
||||
|
||||
|
||||
m_vrpnButton = new vrpn_Button_Remote(buttonName.c_str());
|
||||
m_vrpnButton->register_change_handler(static_cast<void*>(this), ssvep_vrpn_callback_button);
|
||||
}
|
||||
|
||||
ICommandVRPNButton::~ICommandVRPNButton()
|
||||
{
|
||||
m_application->getLogManager() << Kernel::LogLevel_Debug << "- delete m_vrpnButton\n";
|
||||
delete m_vrpnButton;
|
||||
}
|
||||
|
||||
void ICommandVRPNButton::processFrame() { m_vrpnButton->mainloop(); }
|
||||
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "ovamsICommand.h"
|
||||
|
||||
class vrpn_Button_Remote;
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SSVEPMindShooter {
|
||||
class ICommandVRPNButton : public ICommand
|
||||
{
|
||||
public:
|
||||
ICommandVRPNButton(CApplication* application, const CString& name);
|
||||
~ICommandVRPNButton() override;
|
||||
|
||||
void processFrame() override;
|
||||
virtual void execute(const int button, const int state) = 0;
|
||||
|
||||
protected:
|
||||
vrpn_Button_Remote* m_vrpnButton = nullptr;
|
||||
};
|
||||
} // namespace SSVEPMindShooter
|
||||
} // namespace OpenViBE
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
Executable
+153
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Notes:
|
||||
*
|
||||
* - This demo used to be called 'Impact Shooter' before being renamed to 'Mind Shooter'. The various
|
||||
* mentions of 'Impact' are propagating from that time and should be cleaned up one day.
|
||||
*
|
||||
*
|
||||
*/
|
||||
#if defined(TARGET_HAS_ThirdPartyOgre3DTerrain)
|
||||
|
||||
#include "ovams_defines.h"
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
#include <openvibe/ov_directories.h>
|
||||
|
||||
#include "ovamsCApplication.h"
|
||||
#include "GenericStimulator/ovamsCGenericStimulatorApplication.h"
|
||||
#include "Impact/ovamsCImpactApplication.h"
|
||||
|
||||
int main(const int argc, char** argv)
|
||||
{
|
||||
if (argc != 3)
|
||||
{
|
||||
std::cout << "Usage : " << argv[0] << " <application-type> <scenario path>\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// initialize the OpenViBE kernel
|
||||
|
||||
OpenViBE::CKernelLoader kernelLoader;
|
||||
OpenViBE::CString error;
|
||||
OpenViBE::Kernel::IKernelDesc* kernelDesc = nullptr;
|
||||
OpenViBE::Kernel::IKernelContext* kernelContext = nullptr;
|
||||
OpenViBE::Kernel::ILogManager* logManager = nullptr;
|
||||
|
||||
const OpenViBE::CString applicationString = OpenViBE::CString(argv[1]);
|
||||
const OpenViBE::CString scenarioFolder = OpenViBE::CString(argv[2]);
|
||||
|
||||
OpenViBE::CString applicationType, applicationSubtype;
|
||||
|
||||
if (applicationString == OpenViBE::CString("generic"))
|
||||
{
|
||||
applicationType = "generic";
|
||||
applicationSubtype = "";
|
||||
}
|
||||
else if (applicationString == OpenViBE::CString("impact-trainer"))
|
||||
{
|
||||
applicationType = "impact";
|
||||
applicationSubtype = "trainer";
|
||||
}
|
||||
else if (applicationString == OpenViBE::CString("impact-shooter"))
|
||||
{
|
||||
applicationType = "impact";
|
||||
applicationSubtype = "shooter";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "[ERROR] unknown command line parameter '" << applicationString << "'\n";
|
||||
exit(3);
|
||||
}
|
||||
|
||||
#ifdef TARGET_OS_Windows
|
||||
std::cout << "[ INF ] Loading Windows kernel\n";
|
||||
if (!kernelLoader.load(OpenViBE::Directories::getBinDir() + "/openvibe-kernel.dll", &error))
|
||||
#else
|
||||
std::cout << "[ INF ] Loading Linux kernel\n";
|
||||
if(!kernelLoader.load(OpenViBE::Directories::getLibDir() + "/libopenvibe-kernel.so", &error))
|
||||
#endif
|
||||
{
|
||||
std::cout << "[ FAILED ] Error loading kernel (" << error << ")" << "\n";
|
||||
exit(1);
|
||||
}
|
||||
std::cout << "[ INF ] Kernel module loaded, trying to get kernel descriptor\n";
|
||||
|
||||
kernelLoader.initialize();
|
||||
kernelLoader.getKernelDesc(kernelDesc);
|
||||
|
||||
if (!kernelDesc) { std::cout << "[ FAILED ] No kernel descriptor\n"; }
|
||||
else
|
||||
{
|
||||
std::cout << "[ INF ] Got kernel descriptor, trying to create kernel\n";
|
||||
|
||||
kernelContext = kernelDesc->createKernel("ssvep-stimulator", OpenViBE::Directories::getDataDir() + "/kernel/openvibe.conf");
|
||||
|
||||
if (!kernelContext) { std::cout << "[ FAILED ] No kernel created by kernel descriptor\n"; }
|
||||
else
|
||||
{
|
||||
kernelContext->initialize();
|
||||
|
||||
OpenViBE::Toolkit::initialize(*kernelContext);
|
||||
|
||||
OpenViBE::Kernel::IConfigurationManager* configManager = &(kernelContext->getConfigurationManager());
|
||||
configManager->addConfigurationFromFile(configManager->expand("${Path_Data}/kernel/openvibe.conf"));
|
||||
logManager = &(kernelContext->getLogManager());
|
||||
|
||||
// (*l_poLogManager) << Kernel::LogLevel_Info << configManager->expand("${UserHome}") << "\n";
|
||||
const OpenViBE::CString configFile = scenarioFolder + "/appconf/application-configuration.conf";
|
||||
if (!configManager->addConfigurationFromFile(configFile))
|
||||
{
|
||||
(*logManager) << OpenViBE::Kernel::LogLevel_Error << "Unable to read [" << configFile << "]\n";
|
||||
exit(3);
|
||||
}
|
||||
|
||||
// This folder contains resources such as textures etc
|
||||
configManager->createConfigurationToken("SSVEP_MindShooterFolderName", "ssvep-mind-shooter");
|
||||
|
||||
// This folder is the runtime scenario path
|
||||
configManager->createConfigurationToken("SSVEP_MindShooterScenarioPath", scenarioFolder);
|
||||
}
|
||||
}
|
||||
|
||||
OpenViBE::SSVEPMindShooter::CApplication* app;
|
||||
|
||||
if (applicationType == OpenViBE::CString("generic"))
|
||||
{
|
||||
(*logManager) << OpenViBE::Kernel::LogLevel_Debug << "+ app = new SSVEPMindShooter::CGenericStimulatorApplication(...)\n";
|
||||
app = new OpenViBE::SSVEPMindShooter::CGenericStimulatorApplication(scenarioFolder);
|
||||
}
|
||||
else if (applicationType == OpenViBE::CString("impact"))
|
||||
{
|
||||
(*logManager) << OpenViBE::Kernel::LogLevel_Debug << "+ app = new SSVEPMindShooter::CImpactApplication(...)\n";
|
||||
(*logManager) << OpenViBE::Kernel::LogLevel_Info << "application subtype " << applicationSubtype << "\n";
|
||||
app = new OpenViBE::SSVEPMindShooter::CImpactApplication(scenarioFolder, applicationSubtype);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*logManager) << OpenViBE::Kernel::LogLevel_Error << "Wrong application identifier specified\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!app->setup(kernelContext))
|
||||
{
|
||||
(*logManager) << OpenViBE::Kernel::LogLevel_Error << "Cannot proceed, exiting\n";
|
||||
exit(2);
|
||||
}
|
||||
|
||||
app->go();
|
||||
|
||||
(*logManager) << OpenViBE::Kernel::LogLevel_Debug << "- app\n";
|
||||
delete app;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::cout << "SSVEP Mind Shooter has not been compiled as it depends on Ogre (missing/disabled)\n";
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user