AnnGameObjectManager.cpp
Go to the documentation of this file.
1 // This is an open source non-commercial project. Dear PVS-Studio, please check it.
2 // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
3 
4 
5 #include <OgreMeshManager.h>
6 #include <OgreMeshManager2.h>
7 
9 #include "AnnLogger.hpp"
10 #include "AnnEngine.hpp"
11 #include "AnnGetter.hpp"
12 #include "AnnException.hpp"
13 
14 using namespace Annwvyn;
15 
17  AnnSubSystem("GameObjectManager"), halfPos(true), halfTexCoord(true), qTan(true)
18 {
19  //There will only be one manager, set the id to 0
20  autoID = 0;
21 
22  if(const auto plugin = Ogre_glTF::gltfPluginAccessor::findPlugin(); plugin)
23  glTFLoader = plugin->getLoader();
24  else
25  AnnDebug(Log::Important) << "Could not get glTFLoader!, please check if the plugin is located next to the executable!";
26 
27 }
28 
30 {
31  //Run animations and update OpenAL sources position
32  for(auto gameObject : Objects)
33  {
34  gameObject->addAnimationTime(AnnGetEngine()->getFrameTime());
35  gameObject->updateOpenAlPos();
36  gameObject->update();
37  gameObject->callUpdateOnScripts();
38  }
39 }
40 
41 Ogre::MeshPtr AnnGameObjectManager::getAndConvertFromV1Mesh(const char* meshName, Ogre::v1::MeshPtr& v1Mesh, Ogre::MeshPtr& v2Mesh) const
42 {
43  static const std::string sufix = "_V2mesh";
44  const auto meshManager = Ogre::MeshManager::getSingletonPtr();
45 
46  v1Mesh = Ogre::v1::MeshManager::getSingleton().load(meshName,
47  Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME,
48  Ogre::v1::HardwareBuffer::HBU_STATIC,
49  Ogre::v1::HardwareBuffer::HBU_STATIC);
50 
51  //Generate the name of the v2 mesh
52  const auto v2meshName = meshName + sufix;
53  AnnDebug() << "Mesh v2 name : " << v2meshName;
54 
55  //v2Mesh
56  v2Mesh = meshManager->getByName(v2meshName);
57  if(!v2Mesh) //create and import
58  {
59  AnnDebug() << v2meshName << " doesn't exist yet in the v2 MeshManager, creating it and loading the v1 " << meshName << " geometry";
60  v2Mesh = meshManager->createManual(v2meshName, AnnResourceManager::getDefaultResourceGroupName());
61  v2Mesh->importV1(v1Mesh.get(), halfPos, halfTexCoord, qTan);
62  }
63 
64  return v2Mesh;
65 }
66 
68 {
69  AnnDebug("Creating a game object from the mesh file: " + std::string(meshName));
70  auto smgr{ AnnGetEngine()->getSceneManager() };
71 
72  Ogre::Item* item = nullptr;
73 
74  //Check filename extension:
75  auto ext = meshName.substr(meshName.find_last_of('.')+1);
76  std::transform(ext.begin(), ext.end(), ext.begin(), [](char c) { return char(::tolower(int(c))); });
77 
78  if(ext == "mesh")
79  {
80  Ogre::v1::MeshPtr v1Mesh;
81  Ogre::MeshPtr v2Mesh;
82  (void)getAndConvertFromV1Mesh(meshName.c_str(), v1Mesh, v2Mesh);
83  v1Mesh.setNull();
84 
85  //Create an item
86  item = smgr->createItem(v2Mesh);
87  }
88  else if(ext == "glb")
89  {
90  item = glTFLoader->getModelData(meshName, Ogre_glTF::glTFLoader::LoadFrom::ResourceManager).makeItem(smgr);
91  }
92 
93  //Create a node
94  auto node = smgr->getRootSceneNode()->createChildSceneNode();
95 
96  //Attach
97  node->attachObject(item);
98 
99  //Set GameObject members
100  obj->setNode(node);
101  obj->setItem(item);
102  obj->audioSource = AnnGetAudioEngine()->createSource();
103 
104  //id will be unique to every non-identified object.
105  //The identifier name can be empty, meaning that we have to figure out an unique name.
106  //In that case we will append to the entity name + a number that will always be incremented.
107  if(identifier.empty())
108  identifier = meshName + std::to_string(nextID());
109 
110  AnnDebug() << "The object " << identifier << " has been created. Annwvyn memory address " << obj;
111  AnnDebug() << "This object take " << sizeof *obj.get() << " bytes";
112 
113  obj->name = identifier;
114  identifiedObjects[identifier] = obj;
115  Objects.push_back(obj);
116 
117  obj->postInit();
118  return obj;
119 }
120 
122 {
123  AnnDebug() << "Removed object " << object->getName();
124 
125  if(!object) throw AnnNullGameObjectError();
126 
127  Objects.erase(
129  std::end(Objects));
130 
131  identifiedObjects.erase(object->getName());
132 }
133 
135 {
136  AnnDebug() << "Trying to identify object at address " << static_cast<void*>(node);
137 
138  const auto result = std::find_if(begin(Objects), end(Objects), [&](std::shared_ptr<AnnGameObject> object) { return object->getNode() == node; });
139  if(result != end(Objects)) return *result;
140 
141  AnnDebug() << "The Scene Node" << static_cast<void*>(node) << " doesn't belong to any AnnGameObject";
142  return nullptr;
143 }
144 
146 {
147  if(!light) throw AnnNullGameObjectError();
148  Lights.erase(
150  std::end(Lights));
151 
152  identifiedLights.erase(light->getName());
153 }
154 
156 {
157  AnnDebug("Creating a light");
158  if(lightObjectName.empty()) lightObjectName = "light" + std::to_string(nextID());
159  auto Light = std::make_shared<AnnLightObject>(AnnGetEngine()->getSceneManager()->createLight(), lightObjectName);
160  Light->setType(AnnLightObject::LightTypes::ANN_LIGHT_POINT);
161  Lights.push_back(Light);
162  identifiedLights[lightObjectName] = Light;
163  return Light;
164 }
165 
167 {
168  AnnDebug("Creating a trigger object");
169  if(triggerObjectName.empty()) triggerObjectName = "trigger" + std::to_string(nextID());
170  auto trigger = std::make_shared<AnnTriggerObject>(triggerObjectName);
171  Triggers.push_back(trigger);
172  identifiedTriggerObjects[triggerObjectName] = trigger;
173  return trigger;
174 }
175 
177 {
178  Triggers.erase(
180  std::end(Triggers));
181 
182  identifiedTriggerObjects.erase(trigger->getName());
183 }
184 
186 {
187  //Origin vector of the ray is the HMD pose position
188  const auto pose = AnnGetVRRenderer()->trackedHeadPose;
189  const auto hmdPosition{ AnnVect3(pose.position) };
190  const auto rayDirection{ AnnQuaternion(pose.orientation).getAtVector() };
191 
192  //create ray
193  const Ogre::Ray ray(hmdPosition, rayDirection);
194 
195  //create query
196  auto raySceneQuery(AnnGetEngine()->getSceneManager()->createRayQuery(ray));
197  //Sort by distance. Nearest is first. Limit to `limit` results.
198  raySceneQuery->setSortByDistance(true, limit);
199 
200  //execute and get the results
201  auto& results(raySceneQuery->execute());
202 
203  //read the result list
204  const auto result = std::find_if(begin(results), end(results), [](const Ogre::RaySceneQueryResultEntry& entry) {
205  return entry.movable && entry.movable->getMovableType() == "Item";
206  });
207 
208  //If can't find it? return nullptr
209  if(result == end(results))
210  return nullptr; //means that we don't know what the player is looking at.
211 
212  //We got access to the node, we want the object
213  return getFromNode(result->movable->getParentSceneNode());
214 }
215 
217 {
218  const auto object = identifiedObjects.find(gameObjectName);
219  if(object != end(identifiedObjects))
220  return object->second;
221  return nullptr;
222 }
223 
225 {
226  const auto light = identifiedLights.find(lightObjectName);
227  if(light != end(identifiedLights))
228  return light->second;
229  return nullptr;
230 }
231 
233 {
234  const auto trigger = identifiedTriggerObjects.find(triggerObjectName);
235  if(trigger != end(identifiedTriggerObjects))
236  return trigger->second;
237  return nullptr;
238 }
239 
240 void AnnGameObjectManager::setImportParameter(bool halfPosition, bool halfTextureCoord, bool qTangents)
241 {
242  halfPos = halfPosition;
243  halfTexCoord = halfTextureCoord;
244  qTan = qTangents;
245 }
246 
248 {
249  return ++autoID;
250 }
std::unordered_map< std::string, std::shared_ptr< AnnGameObject > > identifiedObjects
objects mapped to ID strings
T empty(T... args)
std::shared_ptr< AnnGameObject > createGameObject(const std::string &mesh, std::string identifier="", std::shared_ptr< AnnGameObject > object=std::make_shared< AnnGameObject >())
AnnEngine * AnnGetEngine()
Get the current instance of AnnEngine.
Definition: AnnGetter.cpp:10
std::shared_ptr< AnnGameObject > playerLookingAt(unsigned short limit=5)
Get the AnnGameObject the player is looking at.
std::shared_ptr< AnnLightObject > createLightObject(std::string identifier="")
Add a light source to the scene. return a pointer to the new light.
T to_string(T... args)
void removeLightObject(std::shared_ptr< AnnLightObject > light)
void removeTriggerObject(std::shared_ptr< AnnTriggerObject > trigger)
Remove the object from the engine.
A 3D Vector.
Definition: AnnVect3.hpp:16
std::shared_ptr< AnnGameObject > getGameObject(std::string gameObjectName)
Get an AnnGameObject for the required string; return nullptr if object cannot be found.
void update() override
Update from the game engine.
T end(T... args)
Namespace containing the totality of Annwvyn components.
Definition: AnnGetter.cpp:8
AnnOgreVRRendererPtr AnnGetVRRenderer()
Get the VR renderer.
Definition: AnnGetter.cpp:20
T remove(T... args)
Ogre_glTF::glTFLoaderInterface * glTFLoader
std::unordered_map< std::string, std::shared_ptr< AnnLightObject > > identifiedLights
lights mapped to ID strings
std::shared_ptr< AnnTriggerObject > createTriggerObject(std::string identifier="")
Create a trigger object.
static const char * getDefaultResourceGroupName()
Return the default resource group name.
T find_last_of(T... args)
T push_back(T... args)
std::shared_ptr< AnnLightObject > getLightObject(std::string lightObjectName)
Get an AnnLightObject from it&#39;s name; return nullptr if object not found.
Create a ostream to the Ogre logger.
Ogre::SceneManager * getSceneManager() const
Get ogre scene manager.
Definition: AnnEngine.cpp:331
unsigned long long uID
Definition: AnnTypes.h:39
AnnGameObjectList Objects
Dynamic container for Game objects present in engine.
T erase(T... args)
AnnAudioEnginePtr AnnGetAudioEngine()
Get the audio engine.
Definition: AnnGetter.cpp:12
Represent a Quaternion.
Open an output stream to the engine log.
Definition: AnnLogger.hpp:24
std::shared_ptr< AnnGameObject > getFromNode(Ogre::SceneNode *node)
Search for an AnnGameObject that holds this node, returns it if found. Return nullptr if not found...
Main Annwvyn Engine class Initialize the renderer and all subsystem. Provide access to all of the eng...
std::unordered_map< std::string, std::shared_ptr< AnnTriggerObject > > identifiedTriggerObjects
triggers identified to ID string
Parent class of all Annwvyn SubSystem.
T find_if(T... args)
Ogre::MeshPtr getAndConvertFromV1Mesh(const char *meshName, Ogre::v1::MeshPtr &v1Mesh, Ogre::MeshPtr &v2Mesh) const
Get a MeshPtr by loading a v1Mesh ptr, specify the name and where to put the 2 pointers.
T begin(T... args)
void setImportParameter(bool halfPosition, bool halfTextureCoord, bool qTangents)
Set the options to pass while converting Ogre V1 meshes to Ogre V2 meshes.
T c_str(T... args)
AnnVect3 getAtVector() const
Get a vector pointing in the direction if this quaternion.
T substr(T... args)
void removeGameObject(std::shared_ptr< AnnGameObject > object)
std::shared_ptr< AnnTriggerObject > getTriggerObject(std::string triggerObjectName)
Get an AnnTriggerObject from it&#39;s name; return nullptr if object not found.
T transform(T... args)
AnnLightList Lights
Dynamic container for lights objects present in engine.
Exception regarding an AnnGameObject that was null when it wasnt.
AnnTriggerObjectList Triggers
Dynamic container for triggers objects present in engine.