AnnSplashLevel.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 "AnnSplashLevel.hpp"
5 #include "AnnEngine.hpp"
6 #include "AnnLogger.hpp"
7 #include "AnnGetter.hpp"
8 #include "AnnException.hpp"
9 #include "OgreHlmsUnlitDatablock.h"
10 
11 using namespace Annwvyn;
12 
13 AnnSplashLevel::AnnSplashLevel(Ogre::String resourceName, std::shared_ptr<AnnLevel> nextLevel, float timeoutTime) :
15  timeout(timeoutTime * 1000),
16  currentTime(0),
17  startTime(-1),
18  next(nextLevel),
19  CurvedPlane{ nullptr },
20  Splash{ nullptr },
21  splashImageName(resourceName),
22  hasBGM(false) {}
23 
24 std::vector<AnnVect3> AnnSplashLevel::createCurvedPlaneVertices(float curvature, float width, float height, float definition)
25 {
26  //This will return a vertex list describing a vertical plane with a parabolic curve.
27  //The curvature of the plane follow the equation
28  //
29  // z = - (1 / curvature) * x^2
30  //
31  //Used as a vertex buffer, the pivot point of the object is in the center of the plane
32  //The definition parameter set the "resolution" of the curve. It's the number of points
33  //in the x axis used to define it.
34 
35  //Compute some basic parameters
36  const auto resolution = width / definition;
37  const auto alpha = 1 / curvature;
38  const auto xmax = width / 2;
39  const auto xmin = -xmax;
40  const auto ymax = height / 2;
41  const auto ymin = -ymax;
42 
43  //how the z component is calculated
44  auto depth = [=](float x) { return alpha * (x * x); };
45 
46  //Where the data is stored. Take advantage of RVO
48  curve.reserve(size_t(definition));
49 
50  for(float x = xmin; x < xmax; x += resolution)
51  {
52  curve.emplace_back(x, ymax, depth(x));
53  curve.emplace_back(x, ymin, depth(x));
54  }
55 
56  return curve;
57 }
58 
60 {
61  //Create manual object
62  AnnDebug() << "Creating the display \"plane\" for the splash";
63  auto smgr(AnnGetEngine()->getSceneManager());
64 
65  CurvedPlane = smgr->createManualObject();
66  CurvedPlane->begin("Splash", Ogre::OT_TRIANGLE_STRIP);
67 
68  const float curvature = 50;
69  const float width = 40;
70  const float height = 40;
71  const float definiton = 10;
72 
73  auto vertices = createCurvedPlaneVertices(curvature, width, height, definiton);
74 
75  Ogre::uint32 index = 0;
76  for(const auto& pos : vertices)
77  {
78  CurvedPlane->position(pos);
79  CurvedPlane->textureCoord((pos.x + width / 2.f) / width, 1.0f - ((pos.y + height / 2.f) / height));
80  CurvedPlane->index(index++);
81  }
82 
83  CurvedPlane->end();
84 
85  AnnDebug() << "Add plane to scene";
86  Splash = smgr->getRootSceneNode()->createChildSceneNode();
87  Splash->attachObject(CurvedPlane);
88 }
89 
90 Ogre::HlmsUnlitDatablock* AnnSplashLevel::createSplashDatablock(Ogre::HlmsUnlit* unlit)
91 {
92  auto macroblock = Ogre::HlmsMacroblock();
93  auto blendblock = Ogre::HlmsBlendblock();
94  macroblock.mCullMode = Ogre::CULL_NONE;
95  macroblock.mDepthCheck = false;
96  macroblock.mDepthWrite = false;
97  macroblock.mScissorTestEnabled = false;
98 
99  auto block = static_cast<Ogre::HlmsUnlitDatablock*>(unlit->createDatablock("Splash", "Splash", macroblock, blendblock, Ogre::HlmsParamVec(), true, Ogre::BLANKSTRING, AnnGetResourceManager()->getDefaultResourceGroupName()));
100  block->setUseColour(true);
101 
102  return block;
103 }
104 
106 {
107  AnnDebug() << "Ignore physics";
108  AnnGetPlayer()->setPosition({ 0, 0, 10 });
109  AnnGetPlayer()->resetPlayerPhysics();
110  AnnGetPlayer()->setOrientation(Ogre::Euler(0, 0, 0));
111  AnnGetPlayer()->ignorePhysics = false;
112  AnnGetPhysicsEngine()->changeGravity(AnnVect3::ZERO);
113 
114  float ev = 1;
115  AnnGetSceneryManager()->setExposure(ev, ev, ev);
116  AnnGetSceneryManager()->setSkyColor(AnnColor(0, 0, 0), 0);
117 
118  auto sun = addLightObject();
120  sun->setDirection({ 0, 1, 0.5f });
121 
122  //Get splashscreen material
123  auto unlit = static_cast<Ogre::HlmsUnlit*>(AnnGetVRRenderer()->getRoot()->getHlmsManager()->getHlms(Ogre::HLMS_UNLIT));
124  auto splashDatablock = static_cast<Ogre::HlmsUnlitDatablock*>(unlit->getDatablock("Splash"));
125  if(!splashDatablock) splashDatablock = createSplashDatablock(unlit);
126 
127  //Get splashscreen texture
128  auto textureManager = Ogre::TextureManager::getSingletonPtr();
129  auto texture = textureManager->getByName(splashImageName);
130  if(!texture) texture = textureManager->load(splashImageName, AnnGetResourceManager()->getDefaultResourceGroupName(), Ogre::TEX_TYPE_2D, 0, 1, false, Ogre::PF_UNKNOWN, true);
131  if(!texture) throw AnnInitializationError(ANN_ERR_NOTINIT, "Texture not found for splash " + splashImageName);
132 
133  //Set datablock parameters
134  splashDatablock->setColour(Ogre::ColourValue::White * 1);
135  splashDatablock->setTexture(Ogre::HlmsTextureManager::TEXTURE_TYPE_DIFFUSE, 0, texture);
136 
138 }
139 
140 void AnnSplashLevel::setBGM(std::string soundfileName, bool preload)
141 {
142  if(preload) AnnGetAudioEngine()->preLoadBuffer(soundfileName);
143  bgmName = soundfileName;
144  hasBGM = true;
145 }
146 
148 {
149  Splash->setPosition(AnnGetPlayer()->getPosition() + AnnVect3{ 0, 0, -10 });
150 
151  //If start time not set yet
152  if(startTime == -1)
153  {
154  //The app is "not visible" if the user isn't wearing the HMD, or if a system menu is up
155  if(AnnGetEngine()->appVisibleInHMD())
156  {
157  //This set the "startTime" variable, preventing this piece of code to be ran twice
158  AnnDebug() << "Starting time at : " << AnnGetEngine()->getTimeFromStartUp();
159  startTime = float(AnnGetEngine()->getTimeFromStartUp());
160 
161  //If you put some background music or sound for the splash-screen, we start it
162  if(hasBGM)
163  {
164  AnnGetAudioEngine()->playBGM(bgmName);
165  }
166  }
167  else
168  {
169  return;
170  }
171  }
172 
173  //Run the following only if you set a "next" level to jump to
174  auto nextLevel = next.lock();
175  if(nextLevel && AnnGetEngine()->getTimeFromStartUp() - startTime > timeout)
176  {
177  startTime = -1;
178  AnnGetEngine()->getLevelManager()->switchToLevel(nextLevel);
179  }
180 }
181 
183 {
184  //Normal level unload
186 
187  AnnDebug() << "Removing object from scene";
188  auto smgr(AnnGetEngine()->getSceneManager());
189  smgr->destroySceneNode(Splash);
190  Ogre::MaterialManager::getSingleton().remove("Splash");
191 
192  AnnDebug() << "Restore Player's normal state : ";
193  AnnGetPlayer()->ignorePhysics = false;
194  AnnGetPlayer()->setPosition(AnnVect3(0, 0, 10));
195  AnnGetPlayer()->resetPlayerPhysics();
196 }
197 
199 {
200  next = level;
201 }
202 
204 {
205  if(time > 0) timeout = 1000 * time;
206 }
207 
209 {
210  timeout = float(time);
211 }
void runLogic() override
Run the logic of the splash screen. This will check for the time and switchToLevel to next level if t...
AnnEngine * AnnGetEngine()
Get the current instance of AnnEngine.
Definition: AnnGetter.cpp:10
virtual void unload()
Unload the level by destroying every objects in "levelContent" and every lights in "levelLighting"...
Definition: AnnLevel.cpp:21
Class that represent a 4 channel color value.
Definition: AnnColor.hpp:17
Ogre::ManualObject * CurvedPlane
The plane that present the object.
Directional lights simulate parallel light beams from a distant source, hence have direction but no p...
A 3D Vector.
Definition: AnnVect3.hpp:16
#define constructLevel()
Definition: AnnLevel.hpp:19
Namespace containing the totality of Annwvyn components.
Definition: AnnGetter.cpp:8
AnnOgreVRRendererPtr AnnGetVRRenderer()
Get the VR renderer.
Definition: AnnGetter.cpp:20
Exception regarding engine utilisation. See message.
std::shared_ptr< AnnLightObject > addLightObject(std::string id="")
Add a light object to the level.
Definition: AnnLevel.cpp:59
std::weak_ptr< AnnLevel > next
Pointer to the next level to load.
Create a ostream to the Ogre logger.
std::string bgmName
Path to the file that is loaded as an audio buffer.
Ogre::SceneNode * Splash
Node where the splash screen is attached.
AnnAudioEnginePtr AnnGetAudioEngine()
Get the audio engine.
Definition: AnnGetter.cpp:12
Open an output stream to the engine log.
Definition: AnnLogger.hpp:24
AnnLevelManagerPtr getLevelManager() const
Get the current level manager.
Definition: AnnEngine.cpp:325
void load() override
Load the level. This create a manual material and a manual object to present the splash image...
unsigned long getTimeFromStartUp() const
Get elapsed time from engine startup in millisecond.
Definition: AnnEngine.cpp:332
Ogre::String splashImageName
Name of the image of the splash-screen.
void setBGM(std::string name, bool preload=true)
Set the background music.
Scene (level) to put a splashing logo.
Main Annwvyn Engine class Initialize the renderer and all subsystem. Provide access to all of the eng...
AnnSceneryManagerPtr AnnGetSceneryManager()
Get the scenery manager.
Definition: AnnGetter.cpp:19
AnnPhysicsEnginePtr AnnGetPhysicsEngine()
Get the physics engine.
Definition: AnnGetter.cpp:13
#define ANN_ERR_NOTINIT
void createSplashCurvedPlane()
Create the plane where the splash will go.
Class for Euler rotations.
Definition: euler.h:25
void setTimeout(float time)
Set timeout time in seconds.
void setNextLevel(std::shared_ptr< AnnLevel > level)
Set the level to switchToLevel to after timeout.
Ogre::HlmsUnlitDatablock * createSplashDatablock(Ogre::HlmsUnlit *unlit)
AnnResourceManagerPtr AnnGetResourceManager()
Get the resource manager.
Definition: AnnGetter.cpp:18
bool hasBGM
True if music is set.
AnnPlayerBodyPtr AnnGetPlayer()
Get the player object.
Definition: AnnGetter.cpp:17
void unload() override
Clean up the manually allocated object.
AnnSplashLevel(Ogre::String splashTexture, std::shared_ptr< AnnLevel > nextLevel=nullptr, float timeoutTime=10)
T reserve(T... args)
std::vector< AnnVect3 > createCurvedPlaneVertices(float curvature, float width, float height, float definition)
void setTimeoutMillisec(unsigned time)
Set timeout time in milliseconds.
T emplace_back(T... args)
float timeout
Time values.