Project

General

Profile

SO3Engine
SO3SubEntitySelectorMaterialSwitcher.cpp
Go to the documentation of this file.
1/*
2-----------------------------------------------------------------------------
3This source file is part of OpenSpace3D
4For the latest info, see http://www.openspace3d.com
5
6Copyright (c) 2012 I-maginer
7
8This program is free software; you can redistribute it and/or modify it under
9the terms of the GNU Lesser General Public License as published by the Free Software
10Foundation; either version 2 of the License, or (at your option) any later
11version.
12
13This program is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16
17You should have received a copy of the GNU Lesser General Public License along with
18this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20http://www.gnu.org/copyleft/lesser.txt
21
22-----------------------------------------------------------------------------
23*/
24
33#include "SO3Renderer/SO3Root.h"
38
39namespace SO3
40{
41
42 SSubEntitySelectorMaterialSwitcher::SSubEntitySelectorMaterialSwitcher(const std::string& baseResourceName, bool useDepth) : resetColour(0.0f, 0.0f, 0.0f)
43 {
44 // Get our base "transparent colour" material...
45 materialTransparent = Ogre::MaterialManager::getSingleton().getByName(std::string(SO3_INTERNAL_SUBENTITY_SELECTOR_RESOURCE_GROUP) + "/Material/Transparent", SO3_INTERNAL_SUBENTITY_SELECTOR_RESOURCE_GROUP);
46 if (!materialTransparent->isLoaded())
47 materialTransparent->load();
48 materialTransparent = materialTransparent->clone(baseResourceName + "/Material/Transparent", baseResourceName);
49 materialTransparent->getTechnique(0)->setSchemeName(baseResourceName);
50
51 // Get our base "plain colour" material...
52 std::string matName = "/Material/PlainColor";
53 if (useDepth)
54 matName = "/Material/PlainColorWithDepth";
55
56 materialPlainColour = Ogre::MaterialManager::getSingleton().getByName(std::string(SO3_INTERNAL_SUBENTITY_SELECTOR_RESOURCE_GROUP) + matName, SO3_INTERNAL_SUBENTITY_SELECTOR_RESOURCE_GROUP);
57 if (!materialPlainColour->isLoaded())
58 materialPlainColour->load();
59
60 //check compatibility
61 if (!materialPlainColour->getTechnique(0)->isSupported())
62 {
63 matName = "/Material/PlainColor";
64 materialPlainColour = Ogre::MaterialManager::getSingleton().getByName(std::string(SO3_INTERNAL_SUBENTITY_SELECTOR_RESOURCE_GROUP) + matName, SO3_INTERNAL_SUBENTITY_SELECTOR_RESOURCE_GROUP);
65 if (!materialPlainColour->isLoaded())
66 materialPlainColour->load();
67 }
68
69 //with slice plane support
70 materialPlainColourSP = Ogre::MaterialManager::getSingleton().getByName(std::string(SO3_INTERNAL_SUBENTITY_SELECTOR_RESOURCE_GROUP) + matName + "SP", SO3_INTERNAL_SUBENTITY_SELECTOR_RESOURCE_GROUP);
71 if (!materialPlainColourSP->isLoaded())
72 materialPlainColourSP->load();
73
74 materialPlainColour = materialPlainColour->clone(baseResourceName + matName, baseResourceName);
75 materialPlainColour->getTechnique(0)->setSchemeName(baseResourceName);
76
77 materialPlainColourSP = materialPlainColourSP->clone(baseResourceName + matName + "SP", baseResourceName);
78 materialPlainColourSP->getTechnique(0)->setSchemeName(baseResourceName);
79
80 materialDots = materialPlainColour->clone(baseResourceName + matName + "_DOT", baseResourceName);
81 materialDots->getTechnique(0)->setSchemeName(baseResourceName);
82
83 materialDotsSP = materialPlainColourSP->clone(baseResourceName + matName + "SP" + "_DOT", baseResourceName);
84 materialDotsSP->getTechnique(0)->setSchemeName(baseResourceName);
85
86 // Get our special "plain colour foreground" material...
87 matName = "/Material/PlainColorForeground";
88 if (useDepth)
89 matName = "/Material/PlainColorForegroundWithDepth";
90
91 materialPlainColorForeground = Ogre::MaterialManager::getSingleton().getByName(std::string(SO3_INTERNAL_SUBENTITY_SELECTOR_RESOURCE_GROUP) + matName, SO3_INTERNAL_SUBENTITY_SELECTOR_RESOURCE_GROUP);
92 if (!materialPlainColorForeground->isLoaded())
93 materialPlainColorForeground->load();
94
95 //check compatibility
96 if (!materialPlainColorForeground->getTechnique(0)->isSupported())
97 {
98 matName = "/Material/PlainColorForeground";
99 materialPlainColorForeground = Ogre::MaterialManager::getSingleton().getByName(std::string(SO3_INTERNAL_SUBENTITY_SELECTOR_RESOURCE_GROUP) + matName, SO3_INTERNAL_SUBENTITY_SELECTOR_RESOURCE_GROUP);
100 if (!materialPlainColorForeground->isLoaded())
101 materialPlainColorForeground->load();
102 }
103
104 materialPlainColorForeground = materialPlainColorForeground->clone(baseResourceName + matName, baseResourceName);
105 materialPlainColorForeground->getTechnique(0)->setSchemeName(baseResourceName);
106
107 materialPlainColorForegroundSP = Ogre::MaterialManager::getSingleton().getByName(std::string(SO3_INTERNAL_SUBENTITY_SELECTOR_RESOURCE_GROUP) + matName + "SP", SO3_INTERNAL_SUBENTITY_SELECTOR_RESOURCE_GROUP);
108 if (!materialPlainColorForegroundSP->isLoaded())
109 materialPlainColorForegroundSP->load();
110
111 materialPlainColorForegroundSP = materialPlainColorForegroundSP->clone(baseResourceName + matName + "SP", baseResourceName);
112 materialPlainColorForegroundSP->getTechnique(0)->setSchemeName(baseResourceName);
113
114 // Initialize
116 }
117
119 {
120 Ogre::MaterialManager::getSingleton().unload(materialPlainColorForeground->getHandle());
121 Ogre::MaterialManager::getSingleton().unload(materialPlainColour->getHandle());
122 Ogre::MaterialManager::getSingleton().unload(materialDots->getHandle());
123
124 Ogre::MaterialManager::getSingleton().unload(materialPlainColorForegroundSP->getHandle());
125 Ogre::MaterialManager::getSingleton().unload(materialPlainColourSP->getHandle());
126 Ogre::MaterialManager::getSingleton().unload(materialDotsSP->getHandle());
127
128 Ogre::MaterialManager::getSingleton().unload(materialTransparent->getHandle());
129 }
130
131 Ogre::Technique* SSubEntitySelectorMaterialSwitcher::handleSchemeNotFound(unsigned short schemeIndex, const Ogre::String& schemeName, Ogre::Material* originalMaterial, unsigned short lodIndex, const Ogre::Renderable* rend)
132 {
133 bool ignore = true;
134 bool priorized = false;
135 Ogre::Technique* lastTechnique = 0;
136 Ogre::Renderable* lastRenderable = 0;
137 bool forcePointsRender = false;
138 Ogre::Real pointSize = 1.0f;
139
140 if (rend != 0)
141 {
142 // Set the new last renderable.
143 lastRenderable = const_cast <Ogre::Renderable*> (rend);
144
145 if ((originalMaterial->getNumTechniques() > 0) && (originalMaterial->getTechnique(0)->getNumPasses() > 0) && (!originalMaterial->getTechnique(0)->getPass(0)->getPolygonModeOverrideable()) && (originalMaterial->getTechnique(0)->getPass(0)->getPolygonMode() == Ogre::PM_POINTS))
146 {
147 forcePointsRender = true;
148 pointSize = originalMaterial->getTechnique(0)->getPass(0)->getPointSize();
149 }
150
151 bool UsePlane = false;
152 if ((originalMaterial->getNumTechniques() > 0) && (originalMaterial->getTechnique(0)))
153 {
154 Ogre::Any bindedSTechnique = originalMaterial->getTechnique(0)->getUserObjectBindings().getUserAny("STechnique");
155
156 if (bindedSTechnique.has_value())
157 {
158 STechnique* technique = Ogre::any_cast<STechnique*>(bindedSTechnique);
159 UsePlane = technique->GetParentMaterial()->GetIgnoreSlicePlane() ? false : true;
160 }
161 }
162
163 // Check if it was always processed during this selection buffer update.
164 ProcessedRenderables::iterator iSearchedRenderable = processedRenderables.find(lastRenderable);
165 if (iSearchedRenderable == processedRenderables.end())
166 {
167 // First, check if it's a subentity. We can know that cause we had an "UserObjectBinding" named "SEntity" to subentities when loading a mesh.
168 Ogre::Any bindedCustomEntity = rend->getUserObjectBindings().getUserAny("SEntity");
169 if (bindedCustomEntity.has_value())
170 {
171 // Cast to our SEntity class
172 SEntity* entity = Ogre::any_cast<SEntity*> (bindedCustomEntity);
173
174 // Get the parent scene manager
175 Ogre::SceneManager* ogreSceneManager = entity->GetParentScene()->GetOgreScenePointer();
176
177 // Non clickable object not rendered
178 if (entity->GetSceneNodeIsMouseClick())
179 {
180 // Priorized entities must be rendered after, change rendering queue.
181 if (entity->GetSceneNodeIsMouseForeground())
182 {
183 // Store entity render queue if not already in the list
184 Ogre::Entity* ogreEntity = static_cast<Ogre::SubEntity*> (lastRenderable)->getParent();
185 if (!priorizedEntityList.count(ogreEntity))
186 {
187 // Store old render queue group.
188 priorizedEntityList[ogreEntity] = ogreEntity->getRenderQueueGroup();
189
190 // Change render queue.
191 ogreEntity->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY);
192 }
193 priorized = true;
194 }
195
196 // Store scene manager informations).
197 if (!sceneManagerList.count(ogreSceneManager))
198 {
199 // Selection do not work correctly if fog is activated on the scene, cause fog is computed AFTER the pixel shader call!
200 SceneManagerInformations sceneInformations;
201 sceneInformations.fogMode = ogreSceneManager->getFogMode();
202 sceneInformations.fogColour = ogreSceneManager->getFogColour();
203 sceneInformations.fogDensity = ogreSceneManager->getFogDensity();
204 sceneInformations.fogStart = ogreSceneManager->getFogStart();
205 sceneInformations.fogEnd = ogreSceneManager->getFogEnd();
206
207 // Set fog mode to none
208 ogreSceneManager->setFog(Ogre::FOG_NONE);
209
210 sceneManagerList.insert(SceneManagerList::value_type(ogreSceneManager, sceneInformations));
211 }
212
213 // Store colour to renderable, this parameter will be used by the pixel shader to colorize the object.
214 GetNextColour();
215 lastRenderable->setCustomParameter(1, Ogre::Vector4(currentColour.r, currentColour.g, currentColour.b, 1.0f));
216
217 SubEntityInformations infos;
218 infos.entityName = entity->GetName();
219 infos.sceneManagerName = ogreSceneManager->getName();
220 infos.subEntity = static_cast <Ogre::SubEntity*> (lastRenderable);
221 infos.entity = infos.subEntity->getParent();
222 colorIndexedSubEntitiesMap[currentColour] = infos;
223 ignore = false;
224 }
225 }
226 else
227 {
228 ignore = true;
229 // Ogre internal mesh, ignore completly.
230 //lastTechnique = originalMaterial->createTechnique();
231
232 // Clone transparent technique
233 //(*lastTechnique) = (*(materialTransparent->getTechnique(0)));
234 //lastTechnique->setSchemeName(schemeName);
235 }
236
237 // If renderable is ignored, return the "transparent" technique, renderable will be ignored during rendering.
238 if (ignore)
239 lastTechnique = materialTransparent->getTechnique(0);
240 else
241 if (forcePointsRender)
242 {
243 if (UsePlane)
244 lastTechnique = materialDotsSP->getTechnique(0);
245 else
246 lastTechnique = materialDots->getTechnique(0);
247
248 lastTechnique->getPass(0)->setPolygonMode(Ogre::PM_POINTS);
249 lastTechnique->getPass(0)->setPointSize(pointSize * 2.0f);
250 }
251 else
252 {
253 if (priorized)
254 if (UsePlane)
255 lastTechnique = materialPlainColorForegroundSP->getTechnique(0);
256 else
257 lastTechnique = materialPlainColorForeground->getTechnique(0);
258 else
259 if (UsePlane)
260 lastTechnique = materialPlainColourSP->getTechnique(0);
261 else
262 lastTechnique = materialPlainColour->getTechnique(0);
263 }
264 // Store as processed
265 processedRenderables.insert(ProcessedRenderables::value_type(lastRenderable, lastTechnique));
266 }
267 else
268 lastTechnique = iSearchedRenderable->second;
269 }
270
271 return lastTechnique;
272 }
273
274 void SSubEntitySelectorMaterialSwitcher::GetNextColour()
275 {
276#if SO3_SUBENTITY_SELECTOR_RANDOM_COLORS
277 currentColour.setAsARGB(static_cast <Ogre::ARGB> (Ogre::Math::UnitRandom() * 0x00FFFFFF + 0xFF000000)); // ignore alpha
278#else
279 Ogre::ARGB argbColour = currentColour.getAsARGB();
280 argbColour++;
281 currentColour.setAsARGB(argbColour);
282#endif
283 }
284
286 {
287 currentColour = resetColour;
288 colorIndexedSubEntitiesMap.clear();
289 processedRenderables.clear();
291 }
292
294 {
295 // Reset the render queue to the old one.
296 PriorizedEntityMap::iterator iPriorizedEntityList = priorizedEntityList.begin();
297 while (iPriorizedEntityList != priorizedEntityList.end())
298 {
299 iPriorizedEntityList->first->setRenderQueueGroup(iPriorizedEntityList->second);
300 iPriorizedEntityList++;
301 }
302 priorizedEntityList.clear();
303
304 // Undo modifications done on scene managers
305 SceneManagerList::iterator iSceneManagerList = sceneManagerList.begin();
306 while (iSceneManagerList != sceneManagerList.end())
307 {
308 // Reset fog mode to the value before selection buffer update was called.
309 iSceneManagerList->first->setFog(iSceneManagerList->second.fogMode,
310 iSceneManagerList->second.fogColour,
311 iSceneManagerList->second.fogDensity,
312 iSceneManagerList->second.fogStart,
313 iSceneManagerList->second.fogEnd);
314
315 iSceneManagerList++;
316 }
317 sceneManagerList.clear();
318 }
319
320 Ogre::SubEntity* SSubEntitySelectorMaterialSwitcher::GetSubEntity(const Ogre::ColourValue& searchedColour)
321 {
322 Ogre::SubEntity* findedSubEntity = 0;
323 if (colorIndexedSubEntitiesMap.count(searchedColour))
324 {
325 try
326 {
327 SubEntityInformations infos = colorIndexedSubEntitiesMap[searchedColour];
328 if (infos.sceneManagerName != "")
329 {
330 Ogre::SceneManager* sceneManager = Ogre::Root::getSingleton().getSceneManager(infos.sceneManagerName);
331 Ogre::Entity* entity = sceneManager->getEntity(infos.entityName);
332
333 // Entity could have been destroyed and recreated with the same name since last rtt update, check this!
334 if (entity == infos.entity)
335 findedSubEntity = infos.subEntity;
336 }
337 }
338 catch (Ogre::Exception&)
339 {
340 // Catching Exception::ERR_ITEM_NOT_FOUND in case sceneManager or entity was deleted since last rtt update. Forwarding other errors.
341 /*if (e.getNumber() != Ogre::Exception::ERR_ITEM_NOT_FOUND)
342 {
343 Ogre::LogManager::getSingletonPtr()->logMessage(e.getFullDescription(), Ogre::LML_CRITICAL, true);
344 //throw e;
345 }*/
346 }
347 }
348
349 return findedSubEntity;
350 }
351
352}
std::string GetName() const
bool GetIgnoreSlicePlane()
bool GetSceneNodeIsMouseClick()
SScene * GetParentScene()
bool GetSceneNodeIsMouseForeground()
Ogre::SceneManager * GetOgreScenePointer()
Definition SO3Scene.cpp:449
Ogre::SubEntity * GetSubEntity(const Ogre::ColourValue &searchedColour)
virtual Ogre::Technique * handleSchemeNotFound(unsigned short schemeIndex, const Ogre::String &schemeName, Ogre::Material *originalMaterial, unsigned short lodIndex, const Ogre::Renderable *rend)
SMaterial * GetParentMaterial()