SO3Engine
SO3VirtualPointer.cpp
Go to the documentation of this file.
1
11#include "SO3Renderer/SO3Root.h"
14
15namespace SO3
16{
18
19 SVirtualPointer::SVirtualPointer() : SNode(0, "", SNode::VIRTUAL_POINTER_TYPE_ID)
20 {
21 // Forbiden (private)
22 }
23
24 SVirtualPointer::SVirtualPointer(SScene* parent, const std::string& name, const float maxlength) : SNode(parent, name, SNode::VIRTUAL_POINTER_TYPE_ID)
25 {
26 mState = false;
27 mAutoUpdate = false;
28 mRenderSize = 32;
29 mCameraSelector = 0;
30 mMaxlength = maxlength;
31 mId = VIRTUAL_POINTER_ID++;
32
33#if defined(ANDROID) || defined(APPLE_IOS) || defined(OSX) || defined(RPI)
34 mSelectorMode = SWindow::SO3_SELECTOR_LIMITED;
35#else
36 mSelectorMode = SWindow::SO3_SELECTOR_FAST;
37#endif
38
39 // create the camera used to render to our cubemap
40 mRayCam = currentScene->GetOgreScenePointer()->createCamera("camera_" + name);
41 mRayCam->setFOVy(Ogre::Degree(5));
42 mRayCam->setAspectRatio(1);
43 mRayCam->setNearClipDistance(Ogre::Real(0.01));
44 mRayCam->setFarClipDistance(Ogre::Real(mMaxlength));
45 O3SceneNode->attachObject(mRayCam);
46 }
47
49 {
50 SetEnable(false);
51
52 // Destroy the camera
53 O3SceneNode->detachObject(mRayCam);
54 currentScene->GetOgreScenePointer()->destroyCamera(mRayCam);
55 }
56
58 {
59 if (mSelectorMode != mode)
60 {
61#if defined(ANDROID) || defined(APPLE_IOS) || defined(OSX) || defined(RPI)
62 mSelectorMode = (mode == SWindow::SO3_SELECTOR_FAST) ? SWindow::SO3_SELECTOR_LIMITED : mode;
63#else
64 mSelectorMode = mode;
65#endif
66
67#if !defined(OSX) && !defined(APPLE_IOS)
68 bool reload = false;
69
70 if (mCameraSelector)
71 {
72 SO3_SAFE_DELETE(mCameraSelector);
73 mCameraSelector = new SSubEntityCameraSelectorBuffer(mRayCam, name, mRenderSize, mRenderSize, (mSelectorMode == SWindow::SO3_SELECTOR_FAST) ? true : false);
74 }
75#endif
76 }
77 }
78
79 void SVirtualPointer::SetMaxLength(const float& length)
80 {
81 mMaxlength = length;
82 mRayCam->setFarClipDistance(Ogre::Real(mMaxlength));
83 }
84
86 {
87 return mMaxlength;
88 }
89
91 {
92 return mId;
93 }
94
95 void SVirtualPointer::SetEnable(const bool& newState)
96 {
97 if ((newState == true) && (mState == false))
98 {
99 mCameraSelector = new SSubEntityCameraSelectorBuffer(mRayCam, name, mRenderSize, mRenderSize, (mSelectorMode == SWindow::SO3_SELECTOR_FAST) ? true : false);
100 mState = true;
101 }
102 else if ((newState == false) && (mState == true))
103 {
104 SAFE_DELETE(mCameraSelector);
105 mState = false;
106 }
107 }
108
110 {
111 return mState;
112 }
113
115 {
116 if (!mState)
117 return;
118
119 SRaycastResult nRaycastValue;
120
121 float xR = 0.5f;
122 float yR = 0.5f;
123 unsigned int pixelsX = mRenderSize / 2;
124 unsigned int pixelsY = mRenderSize / 2;
125
126 //subentity raycast
127 if (mCameraSelector)
128 {
129 // First, use our selection buffer to find which sub-entity was hit
130 Ogre::SubEntity* subEntity = 0;
131 Ogre::Vector3 pos(0.0f, 0.0f, 0.0f);
132 float rayLenght = 0.0f;
133
134 subEntity = mCameraSelector->GetSelectedSubEntity(pixelsX, pixelsY);
135
136 if (subEntity && mCameraSelector->UseDepthBuffer())
137 {
138 float zdepth = mCameraSelector->GetSelectedZdepth(pixelsX, pixelsY);
139
140 if (mRayCam)
141 {
142 // x & y are in range [-1; 1];
143 Ogre::Real nx = (2.0f * xR) - 1.0f;
144 Ogre::Real ny = 1.0f - (2.0f * yR);
145 Ogre::Vector3 nearPoint(nx, ny, -1.0f);
146 Ogre::Vector3 midPoint(nx, ny, 0.0f);
147
148 //get ray world position and direction
149 Ogre::Matrix4 invViewMat = (mRayCam->getProjectionMatrix() * mRayCam->getViewMatrix(true)).inverse();
150 Ogre::Vector3 rayOrigin = invViewMat * nearPoint;
151 Ogre::Vector3 rayDest = invViewMat * midPoint;
152 Ogre::Vector3 rayDirection = rayDest - rayOrigin;
153 rayDirection.normalise();
154
155 float farclip = mRayCam->getFarClipDistance();
156 float nearclip = mRayCam->getNearClipDistance();
157
158 // correct perspective
159 if (mRayCam->getProjectionType() == Ogre::PT_PERSPECTIVE)
160 {
161 // non linear depth
162 Ogre::Vector4 viewpos = mRayCam->getProjectionMatrixWithRSDepth().inverse() * Ogre::Vector4(nx, ny, zdepth, 1.0f);
163 zdepth = viewpos.z / viewpos.w;
164
165 //restore view distance from linear depth
166 //zdepth *= farclip - nearclip;
167
168 if (SRoot::getSingleton().GetRenderSystem() == SRoot::SO3_OPENGL3_RENDERER ||
169 SRoot::getSingleton().GetRenderSystem() == SRoot::SO3_OPENGL_RENDERER ||
170 SRoot::getSingleton().GetRenderSystem() == SRoot::SO3_METAL_RENDERER ||
171 SRoot::getSingleton().GetRenderSystem() == SRoot::SO3_VULKAN_RENDERER)
172 zdepth += nearclip;
173 else
174 zdepth -= nearclip;
175
176 // get new distance for ray direction
177 // A B C triangle : tan(fov / 2) gives AB : AC is depth : then use pythagore to get hypotenuse BC
178 double ylenght = Ogre::Math::Tan(mRayCam->getFOVy().valueRadians() * 0.5f);
179 double xlenght = ylenght * mRayCam->getAspectRatio();
180 double opx = zdepth * abs(xlenght * nx);
181 double opy = zdepth * abs(ylenght * ny);
182 rayLenght = Ogre::Math::Sqrt((zdepth * zdepth) + (opx * opx) + (opy * opy));
183 }
184 else
185 {
186 zdepth *= (farclip - nearclip);
187
192 zdepth *= 0.5f;
193
194 rayLenght = zdepth;
195 }
196
197 pos = rayOrigin + (rayDirection * rayLenght);
198 }
199 }
200 //MMechostr(MSKDEBUG, ">>>>>> RayCast : %i:%i\n", pixelsX, pixelsY);
201
202 if (subEntity != 0)
203 {
204 //MMechostr(MSKDEBUG, ">>>>>> RayCast : Entity found > %s\n", subEntity->getParent()->getName().c_str());
205
206 int subid = -1;
207 for (unsigned int i = 0; i < subEntity->getParent()->getNumSubEntities() && (subid == -1); i++)
208 {
209 if (subEntity->getParent()->getSubEntity(i) == subEntity)
210 subid = i;
211 }
212
213 //Only on widgets when the depth is available
214 if (mCameraSelector != 0)
215 {
216 if (mCameraSelector->UseDepthBuffer())
217 {
218 Ogre::Any bindedCustomEntity = subEntity->getUserObjectBindings().getUserAny("SEntity");
219 SEntity* entity = Ogre::any_cast<SEntity*> (bindedCustomEntity);
220 SScene* scene = entity->GetParentScene();
221 SMaterial* mat = scene->GetMaterial(entity->GetGroupName(), subEntity->getMaterial()->getName());
222
223 nRaycastValue.entity = entity;
224 nRaycastValue.entityName = entity->GetName();
225 nRaycastValue.scene = entity->GetParentScene();
226 nRaycastValue.sceneName = scene->GetName();
227 nRaycastValue.material = mat;
228
229 // Should we force uv coordonate retrieving too?
230 if (mat && (mat->GetAssociatedWidget() != 0))
231 nRaycastValue = SRaycast::Cast(mRayCam, xR, yR, subEntity, true);
232
233 nRaycastValue.point = pos;
234 nRaycastValue.closestDistance = rayLenght;
235 }
236 else if (mSelectorMode == SWindow::SO3_SELECTOR_LIMITED) // position only on widgets
237 {
238 Ogre::Any bindedCustomEntity = subEntity->getUserObjectBindings().getUserAny("SEntity");
239 SEntity* entity = Ogre::any_cast<SEntity*> (bindedCustomEntity);
240 SScene* scene = entity->GetParentScene();
241 SMaterial* mat = scene->GetMaterial(entity->GetGroupName(), subEntity->getMaterial()->getName());
242
243 // Should we force uv coordonate retrieving too?
244 if (mat && (mat->GetAssociatedWidget() != 0))
245 {
246 nRaycastValue.entity = entity;
247 nRaycastValue.entityName = entity->GetName();
248 nRaycastValue.scene = entity->GetParentScene();
249 nRaycastValue.sceneName = scene->GetName();
250 nRaycastValue.material = mat;
251 nRaycastValue = SRaycast::Cast(mRayCam, xR, yR, subEntity, true);
252 }
253 else
254 {
255 float xR = 0.5f;
256 float yR = 0.5f;
257 Ogre::Ray ray = mRayCam->getCameraToViewportRay(fabs(xR), fabs(yR));
258 ray.setOrigin(GetGlobalPosition());
259 GetParentScene()->GetSimpleRayCast(ray, entity, nRaycastValue);
260 nRaycastValue.material = mat;
261 }
262 }
263 else
264 {
265 nRaycastValue = SRaycast::Cast(mRayCam, xR, yR, subEntity);
266 }
267 }
268
269 nRaycastValue.indexSubEntity = subid;
270 }
271 }
272 else
273 {
274 //simple raycast
275 if (mRayCam != 0)
276 {
277 float xR = 0.5f;
278 float yR = 0.5f;
279 Ogre::Ray ray = mRayCam->getCameraToViewportRay(fabs(xR), fabs(yR));
280 ray.setOrigin(GetGlobalPosition());
281
282 GetParentScene()->GetSimpleRayCast(ray, nRaycastValue);
283 }
284 }
285
286 mRaycastValue = nRaycastValue;
287 }
288
290 {
291 CheckRayCastValidity();
292
293 if (mRaycastValue.material == 0)
294 return;
295
296 SWidget* widget = mRaycastValue.material->GetAssociatedWidget();
297 if (widget != 0)
298 SWidgetManager::getSingleton().InjectMouseDown(widget, mRaycastValue, btn, mId);
299 }
300
302 {
303 SWidgetManager::getSingleton().InjectMouseUp(mRaycastValue, btn, mId);
304 }
305
307 {
308 SWidget* widget = 0;
309 CheckRayCastValidity();
310
311 if (mRaycastValue.material != 0)
312 widget = mRaycastValue.material->GetAssociatedWidget();
313
314 SWidgetManager::getSingleton().InjectMouseMove(widget, mRaycastValue, btn, mId);
315 }
316
317 void SVirtualPointer::Wheel(const int delta)
318 {
319 SWidget* widget = 0;
320 CheckRayCastValidity();
321
322 if (mRaycastValue.material != 0)
323 widget = mRaycastValue.material->GetAssociatedWidget();
324
325 SWidgetManager::getSingleton().InjectMouseWheel(widget, mRaycastValue, delta, mId);
326 }
327
329 {
330 return (mState && mRaycastValue.material && (mRaycastValue.material->GetAssociatedWidget() != 0) && (mRaycastValue.material->GetAssociatedWidget()->GetMouseEnable())) ? true : false;
331 }
332
334 {
335 if (!mState)
336 return 0.0f;
337
338 return mRaycastValue.closestDistance;
339 }
340
342 {
343 if (!mState)
344 return Ogre::Vector3::ZERO;
345
346 return mRaycastValue.point;
347 }
348
350 {
351 if (!mState)
352 return 0;
353
354 CheckRayCastValidity();
355 return mRaycastValue.entity;
356 }
357
359 {
360 if (!mState)
361 return 0;
362
363 CheckRayCastValidity();
364 return mRaycastValue.material;
365 }
366
368 {
369 if (!mState)
370 return 0;
371
372 return mRaycastValue.indexSubEntity;
373 }
374
376 {
377 return mRaycastValue;
378 }
379
380 void SVirtualPointer::CheckRayCastValidity()
381 {
382 try
383 {
384 if (mRaycastValue.sceneName != "")
385 {
386 Ogre::SceneManager* sceneManager = Ogre::Root::getSingleton().getSceneManager(mRaycastValue.sceneName);
387 Ogre::Entity* entity = sceneManager->getEntity(mRaycastValue.entityName);
388 // If no error occurs, then no need to invalidate lastRaycast
389 }
390 else
391 {
392 // Invalidate lastRaycast.
393 mRaycastValue = SRaycastResult();
394 }
395 }
396 catch (Ogre::Exception&)
397 {
398 // Invalidate lastRaycast.
399 mRaycastValue = SRaycastResult();
400 }
401 }
402}
std::string GetName() const
std::string name
Definition SO3DataScol.h:44
std::string GetGroupName()
SWidget * GetAssociatedWidget()
SScene * currentScene
Definition SO3NodeScol.h:68
Ogre::SceneNode * O3SceneNode
Definition SO3NodeScol.h:69
SScene * GetParentScene()
virtual Ogre::Vector3 GetGlobalPosition()
static SRaycastResult Cast(SCamera *camera, const float &relativePosX, const float &relativePosY, Ogre::SubEntity *subEntity, bool getUvCoordonate=false)
Ogre::Vector3 point
Definition SO3RayCast.h:50
std::string sceneName
Definition SO3RayCast.h:44
std::string entityName
Definition SO3RayCast.h:47
SMaterial * material
Definition SO3RayCast.h:48
RenderSystem GetRenderSystem()
Definition SO3Root.cpp:860
@ SO3_METAL_RENDERER
Definition SO3Root.h:83
@ SO3_OPENGL3_RENDERER
Definition SO3Root.h:81
@ SO3_OPENGL_RENDERER
Definition SO3Root.h:80
@ SO3_VULKAN_RENDERER
Definition SO3Root.h:82
static SRoot & getSingleton()
Definition SO3Root.cpp:116
SMaterial * GetMaterial(const std::string &groupName, const std::string &materialName, bool searchOtherGroups=true)
Ogre::SceneManager * GetOgreScenePointer()
Definition SO3Scene.cpp:449
void GetSimpleRayCast(Ogre::Ray cameraRay, SRaycastResult &result)
Ogre::SubEntity * GetSelectedSubEntity(int posX, int posY)
Ogre::Vector3 GetTargetPosition()
const SRaycastResult & GetRaycastResult()
void MoveCursor(const MouseButtonId &btn)
void Click(const MouseButtonId &btn)
void UnClick(const MouseButtonId &btn)
void SetMaxLength(const float &length)
void SetSelectorMode(SWindow::SelectorMode mode)
void SetEnable(const bool &newState)
SMaterial * GetSelectedMaterial()
void Wheel(const int delta)
bool GetMouseEnable()
void InjectMouseUp(SWindow *originWindow, const int &xPos, const int &yPos, const MouseButtonId &button)
void InjectMouseMove(SWindow *originWindow, const int &xPos, const int &yPos, const MouseButtonId &button)
void InjectMouseWheel(SWindow *originWindow, const int &scrollX, const int &scrollY, const int &relativeScroll)
void InjectMouseDown(SWindow *originWindow, const int &xPos, const int &yPos, const MouseButtonId &button)
static SWidgetManager & getSingleton()
@ SO3_SELECTOR_LIMITED
Definition SO3Window.h:50
@ SO3_SELECTOR_FAST
Definition SO3Window.h:49
int VIRTUAL_POINTER_ID