My Project
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 #include <OgreMeshManager.h>
5 #include <OgreMeshManager2.h>
6 
8 #include "AnnLogger.hpp"
9 #include "AnnEngine.hpp"
10 #include "AnnGetter.hpp"
11 #include "AnnException.hpp"
12 
13 using namespace Annwvyn;
14 
16  AnnSubSystem("GameObjectManager"), halfPos(true), halfTexCoord(true), qTan(true)
17 {
18  //There will only be one manager, set the id to 0
19  autoID = 0;
20 
21  if(const auto plugin = Ogre_glTF::gltfPluginAccessor::findPlugin(); plugin)
22  glTFLoader = plugin->getLoader();
23  else
24  AnnDebug(Log::Important) << "Could not get glTFLoader!, please check if the plugin is located next to the executable!";
25 }
26 
28 {
29  //Run animations and update OpenAL sources position
30  for(auto gameObject : Objects)
31  {
32  gameObject->addAnimationTime(AnnGetEngine()->getFrameTime());
33  gameObject->updateOpenAlPos();
34  gameObject->update();
35  gameObject->callUpdateOnScripts();
36  }
37 }
38 
39 Ogre::MeshPtr AnnGameObjectManager::getAndConvertFromV1Mesh(const char* meshName, Ogre::v1::MeshPtr& v1Mesh, Ogre::MeshPtr& v2Mesh) const
40 {
41  static const std::string sufix = "_V2mesh";
42  const auto meshManager = Ogre::MeshManager::getSingletonPtr();
43 
44  v1Mesh = Ogre::v1::MeshManager::getSingleton().load(meshName,
45  Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME,
46  Ogre::v1::HardwareBuffer::HBU_STATIC,
47  Ogre::v1::HardwareBuffer::HBU_STATIC);
48 
49  //Generate the name of the v2 mesh
50  const auto v2meshName = meshName + sufix;
51  AnnDebug() << "Mesh v2 name : " << v2meshName;
52 
53  //v2Mesh
54  v2Mesh = meshManager->getByName(v2meshName);
55  if(!v2Mesh) //create and import
56  {
57  AnnDebug() << v2meshName << " doesn't exist yet in the v2 MeshManager, creating it and loading the v1 " << meshName << " geometry";
58  v2Mesh = meshManager->createManual(v2meshName, AnnResourceManager::getDefaultResourceGroupName());
59  v2Mesh->importV1(v1Mesh.get(), halfPos, halfTexCoord, qTan);
60  }
61 
62  return v2Mesh;
63 }
64 
66 {
67  AnnDebug("Creating a game object from the mesh file: " + std::string(meshName));
68  auto smgr { AnnGetEngine()->getSceneManager() };
69 
70  Ogre::Item* item = nullptr;
71 
72  //Check filename extension:
73  auto ext = meshName.substr(meshName.find_last_of('.') + 1);
74  std::transform(ext.begin(), ext.end(), ext.begin(), [](char c) { return char(::tolower(int(c))); });
75 
76  if(ext == "mesh")
77  {
78  Ogre::v1::MeshPtr v1Mesh;
79  Ogre::MeshPtr v2Mesh;
80  (void)getAndConvertFromV1Mesh(meshName.c_str(), v1Mesh, v2Mesh);
81  v1Mesh.setNull();
82 
83  //Create an item
84  item = smgr->createItem(v2Mesh);
85  }
86  else if(ext == "glb")
87  {
88  item = glTFLoader->getModelData(meshName, Ogre_glTF::glTFLoader::LoadFrom::ResourceManager).makeItem(smgr);
89  }
90 
91  //Create a node
92  auto node = smgr->getRootSceneNode()->createChildSceneNode();
93 
94  //Attach
95  node->attachObject(item);
96 
97  //Set GameObject members
98  obj->setNode(node);
99  obj->setItem(item);
100  obj->audioSource = AnnGetAudioEngine()->createSource();
101 
102  //id will be unique to every non-identified object.
103  //The identifier name can be empty, meaning that we have to figure out an unique name.
104  //In that case we will append to the entity name + a number that will always be incremented.
105  if(identifier.empty())
106  identifier = meshName + std::to_string(nextID());
107 
108  AnnDebug() << "The object " << identifier << " has been created. Annwvyn memory address " << obj;
109  AnnDebug() << "This object take " << sizeof *obj.get() << " bytes";
110 
111  obj->name = identifier;
112  identifiedObjects[identifier] = obj;
113  Objects.push_back(obj);
114 
115  obj->postInit();
116  return obj;
117 }
118 
120 {
121  AnnDebug() << "Removed object " << object->getName();
122 
123  if(!object) throw AnnNullGameObjectError();
124 
125  Objects.erase(
127  std::end(Objects));
128 
129  identifiedObjects.erase(object->getName());
130 }
131 
133 {
134  AnnDebug() << "Trying to identify object at address " << static_cast<void*>(node);
135 
136  const auto result = std::find_if(begin(Objects), end(Objects), [&](std::shared_ptr<AnnGameObject> object) { return object->getNode() == node; });
137  if(result != end(Objects)) return *result;
138 
139  AnnDebug() << "The Scene Node" << static_cast<void*>(node) << " doesn't belong to any AnnGameObject";
140  return nullptr;
141 }
142 
144 {
145  if(!light) throw AnnNullGameObjectError();
146  Lights.erase(
148  std::end(Lights));
149 
150  identifiedLights.erase(light->getName());
151 }
152 
154 {
155  AnnDebug("Creating a light");
156  if(lightObjectName.empty()) lightObjectName = "light" + std::to_string(nextID());
157  auto Light = std::make_shared<AnnLightObject>(AnnGetEngine()->getSceneManager()->createLight(), lightObjectName);
158  Light->setType(AnnLightObject::LightTypes::ANN_LIGHT_POINT);
159  Lights.push_back(Light);
160  identifiedLights[lightObjectName] = Light;
161  return Light;
162 }
163 
165 {
166  AnnDebug("Creating a trigger object");
167  if(triggerObjectName.empty()) triggerObjectName = "trigger" + std::to_string(nextID());
168  auto trigger = std::make_shared<AnnTriggerObject>(triggerObjectName);
169  Triggers.push_back(trigger);
170  identifiedTriggerObjects[triggerObjectName] = trigger;
171  return trigger;
172 }
173 
175 {
176  Triggers.erase(
178  std::end(Triggers));
179 
180  identifiedTriggerObjects.erase(trigger->getName());
181 }
182 
184 {
185  //Origin vector of the ray is the HMD pose position
186  const auto pose = AnnGetVRRenderer()->trackedHeadPose;
187  const auto hmdPosition { AnnVect3(pose.position) };
188  const auto rayDirection { AnnQuaternion(pose.orientation).getAtVector() };
189 
190  //create ray
191  const Ogre::Ray ray(hmdPosition, rayDirection);
192 
193  //create query
194  auto raySceneQuery(AnnGetEngine()->getSceneManager()->createRayQuery(ray));
195  //Sort by distance. Nearest is first. Limit to `limit` results.
196  raySceneQuery->setSortByDistance(true, limit);
197 
198  //execute and get the results
199  auto& results(raySceneQuery->execute());
200 
201  //read the result list
202  const auto result = std::find_if(begin(results), end(results), [](const Ogre::RaySceneQueryResultEntry& entry) {
203  return entry.movable && entry.movable->getMovableType() == "Item";
204  });
205 
206  //If can't find it? return nullptr
207  if(result == end(results))
208  return nullptr; //means that we don't know what the player is looking at.
209 
210  //We got access to the node, we want the object
211  return getFromNode(result->movable->getParentSceneNode());
212 }
213 
215 {
216  const auto object = identifiedObjects.find(gameObjectName);
217  if(object != end(identifiedObjects))
218  return object->second;
219  return nullptr;
220 }
221 
223 {
224  const auto light = identifiedLights.find(lightObjectName);
225  if(light != end(identifiedLights))
226  return light->second;
227  return nullptr;
228 }
229 
231 {
232  const auto trigger = identifiedTriggerObjects.find(triggerObjectName);
233  if(trigger != end(identifiedTriggerObjects))
234  return trigger->second;
235  return nullptr;
236 }
237 
238 void AnnGameObjectManager::setImportParameter(bool halfPosition, bool halfTextureCoord, bool qTangents)
239 {
240  halfPos = halfPosition;
241  halfTexCoord = halfTextureCoord;
242  qTan = qTangents;
243 }
244 
246 {
247  return ++autoID;
248 }
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'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:23
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'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.