Rigs of Rods 2026.01
Soft-body Physics Simulation
Loading...
Searching...
No Matches
ImpostorPage.cpp
Go to the documentation of this file.
1/*-------------------------------------------------------------------------------------
2Copyright (c) 2006 John Judnich
3Modified 2008 by Erik Hjortsberg (erik.hjortsberg@iteam.se)
4
5This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
6Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
7 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
8 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
9 3. This notice may not be removed or altered from any source distribution.
10-------------------------------------------------------------------------------------*/
11
12//ImpostorPage.cpp
13//ImposterPage is an extension to PagedGeometry which displays entities as imposters.
14//-------------------------------------------------------------------------------------
15
16#include <OgreRoot.h>
17#include <OgreTimer.h>
18#include <OgreCamera.h>
19#include <OgreVector3.h>
20#include <OgreQuaternion.h>
21#include <OgreEntity.h>
22#include <OgreSubEntity.h>
23#include <OgreHardwarePixelBuffer.h>
24#include <OgreViewport.h>
25#include <OgreTechnique.h>
26
27#include "ImpostorPage.h"
28#include "StaticBillboardSet.h"
29
30using namespace Ogre;
31using namespace Forests;
32
33// static members initialization
37ColourValue Forests::ImpostorPage::s_clrImpostorBackground = ColourValue(0.0f, 0.3f, 0.0f, 0.0f);
38BillboardOrigin Forests::ImpostorPage::s_impostorPivot = BBO_CENTER;
39
40
41
42//-----------------------------------------------------------------------------
45m_pSceneMgr (NULL),
46m_pPagedGeom (NULL),
47m_blendMode (ALPHA_REJECT_IMPOSTOR),
48m_nInstanceID (0),
49m_nAveCount (0),
50m_vecCenter (0, 0, 0)
51{
53}
54
55
56//-----------------------------------------------------------------------------
59{
60 TImpostorBatchs::iterator iter = m_mapImpostorBatches.begin(), iend = m_mapImpostorBatches.end();
61 while (iter != iend)
62 {
63 delete iter->second;
64 ++iter;
65 }
66
67 if (--s_nSelfInstances == 0 && m_pPagedGeom)
68 {
70 {
71 m_pPagedGeom->getSceneNode()->removeAndDestroyChild("ImpostorPage::renderNode");
72 m_pPagedGeom->getSceneNode()->removeAndDestroyChild("ImpostorPage::cameraNode");
73 }
74 else if (m_pSceneMgr)
75 {
76 m_pSceneMgr->destroySceneNode("ImpostorPage::renderNode");
77 m_pSceneMgr->destroySceneNode("ImpostorPage::cameraNode");
78 }
79 else
80 {
81 assert(false && "Who must delete scene node???");
82 }
83
84 ResourceGroupManager::getSingleton().destroyResourceGroup("Impostors");
85 }
86}
87
88
89//-----------------------------------------------------------------------------
91void ImpostorPage::init(PagedGeometry *geom, const Ogre::Any &data)
92{
93 assert(geom && "Null pointer to PagedGeometry");
95 m_pPagedGeom = geom;
96
97 if (s_nSelfInstances == 1) // first instance
98 {
99 // Set up a single instance of a scene node which will be used when rendering impostor textures
100 geom->getSceneNode()->createChildSceneNode("ImpostorPage::renderNode");
101 geom->getSceneNode()->createChildSceneNode("ImpostorPage::cameraNode");
102 ResourceGroupManager::getSingleton().createResourceGroup("Impostors");
103 }
104}
105
106
107//-----------------------------------------------------------------------------
109void ImpostorPage::setRegion(Ogre::Real left, Ogre::Real top, Ogre::Real right, Ogre::Real bottom)
110{
111 // Calculate center of region
112 m_vecCenter.x = (left + right) * 0.5f;
113 m_vecCenter.z = (top + bottom) * 0.5f;
114 m_vecCenter.y = 0.0f; // The center.y value is calculated when the entities are added
115 m_nAveCount = 0;
116}
117
118
119//-----------------------------------------------------------------------------
121void ImpostorPage::addEntity(Entity *ent, const Vector3 &position, const Quaternion &rotation, const Vector3 &scale, const Ogre::ColourValue &color)
122{
123 //Get the impostor batch that this impostor will be added to
124 ImpostorBatch *ibatch = ImpostorBatch::getBatch(this, ent);
125
126 //Then add the impostor to the batch
127 ibatch->addBillboard(position, rotation, scale, color);
128
129 //Add the Y position to the center.y value (to be averaged later)
130 m_vecCenter.y += position.y + ent->getBoundingBox().getCenter().y * scale.y;
131 ++m_nAveCount;
132}
133
134
135//-----------------------------------------------------------------------------
138{
139 if (m_mapImpostorBatches.empty())
140 return;
141
142 // Calculate the average Y value of all the added entities
144
145 //Build all batches
146 TImpostorBatchs::iterator it = m_mapImpostorBatches.begin(), iend = m_mapImpostorBatches.end();
147 while (it != iend)
148 {
149 it->second->build();
150 ++it;
151 }
152}
153
154//-----------------------------------------------------------------------------
156void ImpostorPage::setVisible(bool visible)
157{
158 // Update visibility status of all batches
159 TImpostorBatchs::iterator it = m_mapImpostorBatches.begin(), iend = m_mapImpostorBatches.end();
160 while (it != iend)
161 {
162 it->second->setVisible(visible);
163 ++it;
164 }
165}
166
167
168//-----------------------------------------------------------------------------
170void ImpostorPage::setFade(bool enabled, Real visibleDist, Real invisibleDist)
171{
172 // Update fade status of all batches
173 TImpostorBatchs::iterator it = m_mapImpostorBatches.begin(), iend = m_mapImpostorBatches.end();
174 while (it != iend)
175 {
176 it->second->setFade(enabled, visibleDist, invisibleDist);
177 ++it;
178 }
179}
180
181
182//-----------------------------------------------------------------------------
185{
186 TImpostorBatchs::iterator iter = m_mapImpostorBatches.begin(), iend = m_mapImpostorBatches.end();
187 while (iter != iend)
188 {
189 iter->second->clear();
190 ++iter;
191 }
192
193 //Reset y center
194 m_vecCenter.y = 0;
195 m_nAveCount = 0;
196}
197
198
199//-----------------------------------------------------------------------------
202{
203 if (m_mapImpostorBatches.empty()) // SVA speed up
204 return;
205
206 //Calculate the direction the impostor batches should be facing
207 Vector3 camPos = m_pPagedGeom->getCamera()->getDerivedPosition();
208
209 // Update all batches
210 Ogre::Real distX = camPos.x - m_vecCenter.x;
211 Ogre::Real distZ = camPos.z - m_vecCenter.z;
212 Ogre::Real distY = camPos.y - m_vecCenter.y;
213 Ogre::Real distRelZ = Math::Sqrt(distX * distX + distZ * distZ);
214 Radian pitch = Math::ATan2(distY, distRelZ);
215
216 Radian yaw;
217 if (distRelZ > m_pPagedGeom->getPageSize() * 3)
218 {
219 yaw = Math::ATan2(distX, distZ);
220 }
221 else
222 {
223 Vector3 dir = m_pPagedGeom->getCamera()->getDerivedDirection();
224 yaw = Math::ATan2(-dir.x, -dir.z);
225 }
226
227 TImpostorBatchs::iterator iter = m_mapImpostorBatches.begin(), iend = m_mapImpostorBatches.end();
228 while (iter != iend)
229 {
230 iter->second->setAngle(pitch.valueDegrees(), yaw.valueDegrees());
231 ++iter;
232 }
233}
234
236{
238 if (tex != NULL)
239 tex->regenerate();
240}
241
246
247
248//-------------------------------------------------------------------------------------
249
250unsigned long ImpostorBatch::GUID = 0;
251
253m_pTexture (NULL)
254{
255 // Render impostor texture for this entity
257
258 //Create billboard set
262
264
265 //Default the angle to 0 degrees
266 pitchIndex = -1;
267 yawIndex = -1;
268 setAngle(0.0f, 0.0f);
269
270 //Init. variables
271 igroup = group;
272}
273
275{
276 //Delete billboard set
277 delete bbset;
278
279 // Delete texture
281}
282
283//Returns a pointer to an ImpostorBatch for the specified entity in the specified
284//ImpostorPage. If one does not already exist, one will automatically be created.
286{
287 //Search for an existing impostor batch for this entity
288 String entityKey = ImpostorBatch::generateEntityKey(entity);
289 ImpostorBatch *batch = group->getImpostorBatch(entityKey);
290 if (batch) // If found return it
291 return batch;
292
293 // Otherwise, create a new batch
294 batch = new ImpostorBatch(group, entity);
295 group->injectImpostorBatch(entityKey, batch); // warning! function can return false
296 return batch;
297}
298
299//Rotates all the impostors to the specified angle (virtually - it actually changes
300//their materials to produce this same effect)
301void ImpostorBatch::setAngle(Ogre::Real pitchDeg, Ogre::Real yawDeg)
302{
303 // Calculate pitch material index
304 int newPitchIndex = 0;
305#ifdef IMPOSTOR_RENDER_ABOVE_ONLY
306 if (pitchDeg > 0)
307 {
308 float maxPitchIndexDeg = (90.0f * (IMPOSTOR_PITCH_ANGLES-1)) / IMPOSTOR_PITCH_ANGLES;
309 newPitchIndex = (int)(IMPOSTOR_PITCH_ANGLES * (pitchDeg / maxPitchIndexDeg));
310 if (newPitchIndex > IMPOSTOR_PITCH_ANGLES-1) newPitchIndex = IMPOSTOR_PITCH_ANGLES-1;
311 }
312#else
313 float minPitchIndexDeg = -90.0f;
314 float maxPitchIndexDeg = ((180.0f * (IMPOSTOR_PITCH_ANGLES-1)) / IMPOSTOR_PITCH_ANGLES) - 90.0f;
315 newPitchIndex = (int)(IMPOSTOR_PITCH_ANGLES * ((pitchDeg - minPitchIndexDeg) / (maxPitchIndexDeg - minPitchIndexDeg)));
316 if (newPitchIndex > IMPOSTOR_PITCH_ANGLES-1) newPitchIndex = IMPOSTOR_PITCH_ANGLES-1;
317 if (newPitchIndex < 0) newPitchIndex = 0;
318#endif
319
320 // Calculate yaw material index
321 int newYawIndex = yawDeg > 0 ? int(IMPOSTOR_YAW_ANGLES * (yawDeg / 360.0f) + 0.5f) % IMPOSTOR_YAW_ANGLES :
322 int(IMPOSTOR_YAW_ANGLES + IMPOSTOR_YAW_ANGLES * (yawDeg / 360.0f) + 0.5f) % IMPOSTOR_YAW_ANGLES;
323
324 // Change materials if necessary
325 if (newPitchIndex != pitchIndex || newYawIndex != yawIndex)
326 {
327 pitchIndex = newPitchIndex;
328 yawIndex = newYawIndex;
330 }
331}
332
333void ImpostorBatch::setBillboardOrigin(BillboardOrigin origin)
334{
335 bbset->setBillboardOrigin(origin);
336
337 if (bbset->getBillboardOrigin() == BBO_CENTER)
339 else if (bbset->getBillboardOrigin() == BBO_BOTTOM_CENTER)
341}
342
344{
345 Ogre::StringStream entityKey;
346 entityKey << entity->getMesh()->getName();
347 for (unsigned int i = 0; i < entity->getNumSubEntities(); ++i)
348 {
349 entityKey << "-" << entity->getSubEntity(i)->getMaterialName();
350 }
351 entityKey << "-" << IMPOSTOR_YAW_ANGLES << "_" << IMPOSTOR_PITCH_ANGLES;
352#ifdef IMPOSTOR_RENDER_ABOVE_ONLY
353 entityKey << "_RAO";
354#endif
355 return entityKey.str();
356}
357
358//-------------------------------------------------------------------------------------
359
360
362: texture(impostorTexture)
363{
364}
365
366void ImpostorTextureResourceLoader::loadResource (Ogre::Resource *resource)
367{
368 if (resource->getLoadingState() == Ogre::Resource::LOADSTATE_UNLOADED) {
370 }
371}
372
373//-------------------------------------------------------------------------------------
374
375
376std::map<String, ImpostorTexture *> ImpostorTexture::selfList;
377unsigned long ImpostorTexture::GUID = 0;
378
379//Do not use this constructor yourself - instead, call getTexture()
380//to get/create an ImpostorTexture for an Entity.
382loader(0)
383{
384 //Store scene manager and entity
388
389 //Add self to list of ImpostorTexture's
391 typedef std::pair<String, ImpostorTexture *> ListItem;
392 selfList.insert(ListItem(entityKey, this));
393
394 //Calculate the entity's bounding box and it's diameter
395 boundingBox = entity->getBoundingBox();
396
397 entityRadius = Math::boundingRadiusFromAABB(boundingBox);
399 entityCenter = boundingBox.getCenter();
400
401 //Render impostor textures
402 renderTextures(false);
403
404 //Set up materials
405 for (int o = 0; o < IMPOSTOR_YAW_ANGLES; ++o){
406 for (int i = 0; i < IMPOSTOR_PITCH_ANGLES; ++i){
407 material[i][o] = MaterialManager::getSingleton().create(getUniqueID("ImpostorMaterial"), "Impostors");
408
409 Material *m = material[i][o].get();
410 Pass *p = m->getTechnique(0)->getPass(0);
411
412 TextureUnitState *t = p->createTextureUnitState(texture->getName());
413
414 t->setTextureUScroll((float)o / IMPOSTOR_YAW_ANGLES);
415 t->setTextureVScroll((float)i / IMPOSTOR_PITCH_ANGLES);
416
417 p->setLightingEnabled(false);
418 m->setReceiveShadows(false);
419
421 p->setAlphaRejectSettings(CMPF_GREATER_EQUAL, 128);
422 //p->setAlphaRejectSettings(CMPF_GREATER_EQUAL, 64);
423 } else if (group->getBlendMode() == ALPHA_BLEND_IMPOSTOR){
424 p->setSceneBlending(SBF_SOURCE_ALPHA, SBF_ONE_MINUS_SOURCE_ALPHA);
425 p->setDepthWriteEnabled(false);
426 }
427 }
428 }
429}
430
432{
433 for (int o = 0; o < IMPOSTOR_YAW_ANGLES; ++o){
434 for (int i = 0; i < IMPOSTOR_PITCH_ANGLES; ++i){
435 Material *m = material[i][o].get();
436 Pass *p = m->getTechnique(0)->getPass(0);
437
438 TextureUnitState *t = p->getTextureUnitState(0);
439
440 t->setTextureName(texture->getName());
441 }
442 }
443}
444
446{
447 //Delete textures
448 if (TextureManager::getSingletonPtr())
449 TextureManager::getSingleton().remove(texture);
450 texture.reset();
451
452 //Delete materials
453 for (int o = 0; o < IMPOSTOR_YAW_ANGLES; ++o){
454 for (int i = 0; i < IMPOSTOR_PITCH_ANGLES; ++i){
455 if (MaterialManager::getSingletonPtr())
456 MaterialManager::getSingleton().remove(material[i][o]);
457 material[i][o].reset();
458 }
459 }
460
461 //Remove self from list of ImpostorTexture's
462 selfList.erase(entityKey);
463}
464
466{
467 if (TextureManager::getSingletonPtr())
468 TextureManager::getSingleton().remove(texture);
469 texture.reset();
470 renderTextures(true);
472}
473
475{
476 std::map<String, ImpostorTexture *>::iterator iter;
477 for (iter = selfList.begin(); iter != selfList.end(); ++iter){
478 iter->second->regenerate();
479 }
480}
481
483{
484#ifdef IMPOSTOR_FILE_SAVE
485 TexturePtr renderTexture;
486#else
487 TexturePtr renderTexture(texture);
488 //if we're not using a file image we need to set up a resource loader, so that the texture is regenerated if it's ever unloaded (such as switching between fullscreen and the desktop in win32)
489 loader = std::auto_ptr<ImpostorTextureResourceLoader>(new ImpostorTextureResourceLoader(*this));
490#endif
491 RenderTexture *renderTarget;
492 Camera *renderCamera;
493 Viewport *renderViewport;
494 SceneNode *camNode;
495
496 //Set up RTT texture
497 Ogre::uint textureSize = ImpostorPage::getImpostorResolution();
498 if (!renderTexture)
499 {
500 renderTexture = TextureManager::getSingleton().createManual(getUniqueID("ImpostorTexture"), "Impostors",
501 TEX_TYPE_2D, textureSize * IMPOSTOR_YAW_ANGLES, textureSize * IMPOSTOR_PITCH_ANGLES, 0, PF_BYTE_RGBA, TU_RENDERTARGET, loader.get());
502 }
503 renderTexture->setNumMipmaps(MIP_UNLIMITED);
504
505 //Set up render target
506 renderTarget = renderTexture->getBuffer()->getRenderTarget();
507 renderTarget->setAutoUpdated(false);
508
509 //Set up camera
510 camNode = sceneMgr->getSceneNode("ImpostorPage::cameraNode");
511 renderCamera = sceneMgr->createCamera(getUniqueID("ImpostorCam"));
512 camNode->attachObject(renderCamera);
513 renderCamera->setLodBias(1000.0f);
514 renderViewport = renderTarget->addViewport(renderCamera);
515 renderViewport->setOverlaysEnabled(false);
516 renderViewport->setClearEveryFrame(true);
517 renderViewport->setShadowsEnabled(false);
518 renderViewport->setBackgroundColour(ImpostorPage::getImpostorBackgroundColor());
519
520 //Set up scene node
521 SceneNode* node = sceneMgr->getSceneNode("ImpostorPage::renderNode");
522
523 Ogre::SceneNode* oldSceneNode = entity->getParentSceneNode();
524 if (oldSceneNode) {
525 oldSceneNode->detachObject(entity);
526 }
527
528 node->attachObject(entity);
529 node->setPosition(-entityCenter);
530
531 //Set up camera FOV
532 const Real objDist = entityRadius * 100;
533 const Real nearDist = objDist - (entityRadius + 1);
534 const Real farDist = objDist + (entityRadius + 1);
535
536 renderCamera->setAspectRatio(1.0f);
537 renderCamera->setFOVy(Math::ATan(entityDiameter / objDist));
538 renderCamera->setNearClipDistance(nearDist);
539 renderCamera->setFarClipDistance(farDist);
540
541 //Disable mipmapping (without this, masked textures look bad)
542 MaterialManager *mm = MaterialManager::getSingletonPtr();
543 FilterOptions oldMinFilter = mm->getDefaultTextureFiltering(FT_MIN);
544 FilterOptions oldMagFilter = mm->getDefaultTextureFiltering(FT_MAG);
545 FilterOptions oldMipFilter = mm->getDefaultTextureFiltering(FT_MIP);
546 mm->setDefaultTextureFiltering(FO_POINT, FO_LINEAR, FO_NONE);
547
548 //Disable fog
549 FogMode oldFogMode = sceneMgr->getFogMode();
550 ColourValue oldFogColor = sceneMgr->getFogColour();
551 Real oldFogDensity = sceneMgr->getFogDensity();
552 Real oldFogStart = sceneMgr->getFogStart();
553 Real oldFogEnd = sceneMgr->getFogEnd();
554 sceneMgr->setFog(FOG_NONE);
555
556 // Get current status of the queue mode
557 Ogre::SceneManager::SpecialCaseRenderQueueMode OldSpecialCaseRenderQueueMode = sceneMgr->getSpecialCaseRenderQueueMode();
558 //Only render the entity
559 sceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_INCLUDE);
560 sceneMgr->addSpecialCaseRenderQueue(group->getParentPagedGeometry()->getRenderQueue() + 1);
561
562 uint8 oldRenderQueueGroup = entity->getRenderQueueGroup();
563 entity->setRenderQueueGroup(group->getParentPagedGeometry()->getRenderQueue() + 1);
564 bool oldVisible = entity->getVisible();
565 entity->setVisible(true);
566 Ogre::Real oldMaxDistance = entity->getRenderingDistance();
567 entity->setRenderingDistance(0);
568
569 bool needsRegen = true;
570#ifdef IMPOSTOR_FILE_SAVE
571 //Calculate the filename hash used to uniquely identity this render
572 uint32 key = FastHash(entityKey.c_str(), entityKey.size(), 0);
573 String tempdir = this->group->getParentPagedGeometry()->getTempdir();
574 ResourceGroupManager::getSingleton().addResourceLocation(tempdir, "FileSystem", "Impostors");
575
576 String fileName = StringUtil::format("Impostor.%08X.%d", key, textureSize);
577
578 //Attempt to load the pre-render file if allowed
579 needsRegen = force;
580 if (!needsRegen){
581 try{
582 texture = TextureManager::getSingleton().load(fileName+".dds", "Impostors", TEX_TYPE_2D, MIP_UNLIMITED);
583 }
584 catch (Exception&){
585 try{
586 texture = TextureManager::getSingleton().load(fileName+".png", "Impostors", TEX_TYPE_2D, MIP_UNLIMITED);
587 }
588 catch (Exception&){
589 needsRegen = true;
590 }
591 }
592 }
593#endif
594
595 if (needsRegen){
596 //If this has not been pre-rendered, do so now
597 const float xDivFactor = 1.0f / IMPOSTOR_YAW_ANGLES;
598 const float yDivFactor = 1.0f / IMPOSTOR_PITCH_ANGLES;
599 for (int o = 0; o < IMPOSTOR_PITCH_ANGLES; ++o){ //4 pitch angle renders
600#ifdef IMPOSTOR_RENDER_ABOVE_ONLY
601 Radian pitch = Degree((90.0f * o) * yDivFactor); //0, 22.5, 45, 67.5
602#else
603 Radian pitch = Degree((180.0f * o) * yDivFactor - 90.0f);
604#endif
605
606 for (int i = 0; i < IMPOSTOR_YAW_ANGLES; ++i){ //8 yaw angle renders
607 Radian yaw = Degree((360.0f * i) * xDivFactor); //0, 45, 90, 135, 180, 225, 270, 315
608
609 //Position camera
610 camNode->setPosition(0, 0, 0);
611 camNode->setOrientation(Quaternion(yaw, Vector3::UNIT_Y) * Quaternion(-pitch, Vector3::UNIT_X));
612 camNode->translate(Vector3(0, 0, objDist), Node::TS_LOCAL);
613
614 //Render the impostor
615 renderViewport->setDimensions((float)(i) * xDivFactor, (float)(o) * yDivFactor, xDivFactor, yDivFactor);
616 renderTarget->update();
617 }
618 }
619
620#ifdef IMPOSTOR_FILE_SAVE
621 //Save RTT to file with respecting the temp dir
622 renderTarget->writeContentsToFile(tempdir + fileName+".png");
623 // force re-index
624 ResourceGroupManager::getSingleton().removeResourceLocation(tempdir, "Impostors");
625 ResourceGroupManager::getSingleton().addResourceLocation(tempdir, "FileSystem", "Impostors");
626
627 //Load the render into the appropriate texture view
628 texture = TextureManager::getSingleton().load(fileName+".png", "Impostors", TEX_TYPE_2D, MIP_UNLIMITED);
629#else
630 texture = renderTexture;
631#endif
632 }
633
634
635 entity->setVisible(oldVisible);
636 entity->setRenderQueueGroup(oldRenderQueueGroup);
637 entity->setRenderingDistance(oldMaxDistance);
638
639 sceneMgr->removeSpecialCaseRenderQueue(group->getParentPagedGeometry()->getRenderQueue() + 1);
640 // Restore original state
641 sceneMgr->setSpecialCaseRenderQueueMode(OldSpecialCaseRenderQueueMode);
642
643 //Re-enable mipmapping
644 mm->setDefaultTextureFiltering(oldMinFilter, oldMagFilter, oldMipFilter);
645
646 //Re-enable fog
647 sceneMgr->setFog(oldFogMode, oldFogColor, oldFogDensity, oldFogStart, oldFogEnd);
648
649 //Delete camera
650 renderTarget->removeViewport(0);
651 renderCamera->getSceneManager()->destroyCamera(renderCamera);
652
653 //Delete scene node
654 node->detachAllObjects();
655 if (oldSceneNode) {
656 oldSceneNode->attachObject(entity);
657 }
658
659#ifdef IMPOSTOR_FILE_SAVE
660 //Delete RTT texture
661 assert(renderTexture);
662
663 if (TextureManager::getSingletonPtr())
664 TextureManager::getSingleton().remove(renderTexture);
665#endif
666}
667
669{
670 //Search for an existing impostor texture, in case it was already deleted
671 for(std::map<String, ImpostorTexture *>::iterator iter=selfList.begin();
672 iter!=selfList.end(); ++iter)
673 {
674 if(iter->second==Texture)
675 {
676 delete Texture;
677 return;
678 }
679 }
680 // no need to anything if it was not found, chances are that it was already deleted
681}
682
684{
685 //Search for an existing impostor texture for the given entity
687 std::map<String, ImpostorTexture *>::iterator iter;
688 iter = selfList.find(entityKey);
689
690 //If found..
691 if (iter != selfList.end()){
692 //Return it
693 return iter->second;
694 } else {
695 if (group){
696 //Otherwise, return a new texture
697 return (new ImpostorTexture(group, entity));
698 } else {
699 //But if group is null, return null
700 return NULL;
701 }
702 }
703}
#define IMPOSTOR_PITCH_ANGLES
#define IMPOSTOR_YAW_ANGLES
static Ogre::String generateEntityKey(Ogre::Entity *entity)
static unsigned long GUID
ImpostorPage * igroup
void addBillboard(const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, const Ogre::Vector3 &scale, const Ogre::ColourValue &color=Ogre::ColourValue::White)
StaticBillboardSet * bbset
void setBillboardOrigin(Ogre::BillboardOrigin origin)
ImpostorTexture * m_pTexture
void setAngle(Ogre::Real pitchDeg, Ogre::Real yawDeg)
static ImpostorBatch * getBatch(ImpostorPage *group, Ogre::Entity *entity)
Ogre::Vector3 entityBBCenter
ImpostorBatch(ImpostorPage *group, Ogre::Entity *entity)
The ImpostorPage class renders entities as impostors (billboard images that look just like the real e...
void update()
Do whatever needs to be done to keep the page geometry up-to-date.
static Ogre::uint s_nImpostorResolution
void build()
Perform any final steps to make added entities appear in the scene.
PagedGeometry * m_pPagedGeom
static void regenerate(Ogre::Entity *ent)
Regenerates the impostor texture for the specified entity.
static void regenerateAll()
Regenerates all impostor textures currently being used in the scene.
void addEntity(Ogre::Entity *ent, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, const Ogre::Vector3 &scale, const Ogre::ColourValue &color)
Add an entity to the page, at the specified position, rotation, and scale.
TImpostorBatchs m_mapImpostorBatches
void setRegion(Ogre::Real left, Ogre::Real top, Ogre::Real right, Ogre::Real bottom)
Prepare a geometry page for entities.
static Ogre::uint s_nSelfInstances
static Ogre::uint getImpostorResolution()
ImpostorBlendMode getBlendMode() const
Ogre::Vector3 m_vecCenter
void setFade(bool enabled, Ogre::Real visibleDist, Ogre::Real invisibleDist)
Sets fade behavior for this page.
Ogre::SceneManager * m_pSceneMgr
~ImpostorPage()
Destructor.
ImpostorBatch * getImpostorBatch(const Ogre::String &key) const
static Ogre::BillboardOrigin getImpostorPivot()
static Ogre::uint s_nUpdateInstanceID
void setVisible(bool visible)
Toggle the entire page's visibility.
static Ogre::BillboardOrigin s_impostorPivot
bool injectImpostorBatch(const Ogre::String &key, ImpostorBatch *injectedBatch)
ImpostorPage()
Default constructor.
void removeEntities()
Remove all geometry/entities from the page completely.
static Ogre::ColourValue s_clrImpostorBackground
static const Ogre::ColourValue & getImpostorBackgroundColor()
void init(PagedGeometry *geom, const Ogre::Any &data)
Prepare a geometry page for use.
PagedGeometry * getParentPagedGeometry() const
Ogre::MaterialPtr material[IMPOSTOR_PITCH_ANGLES][IMPOSTOR_YAW_ANGLES]
static Ogre::String getUniqueID(const Ogre::String &prefix)
static ImpostorTexture * getTexture(ImpostorPage *group, Ogre::Entity *entity)
Returns a pointer to an ImpostorTexture for the specified entity.
static unsigned long GUID
static std::map< Ogre::String, ImpostorTexture * > selfList
ImpostorTexture(ImpostorPage *group, Ogre::Entity *entity)
static void removeTexture(ImpostorTexture *Texture)
remove created texture, note that all of the ImposterTextures must be deleted at once,...
Ogre::TexturePtr texture
Ogre::SceneManager * sceneMgr
friend class ImpostorTextureResourceLoader
void renderTextures(bool force)
std::auto_ptr< ImpostorTextureResourceLoader > loader
Ogre::AxisAlignedBox boundingBox
virtual void loadResource(Ogre::Resource *resource)
At load time the texture will be rerendered.
ImpostorTextureResourceLoader(ImpostorTexture &impostorTexture)
Ctor.
A class providing highly optimized methods for rendering massive amounts of geometry.
Ogre::Real getPageSize()
Gets the current page size.
Ogre::uint8 getRenderQueue() const
Returns the rendering queue that paged geometry was constructed with.
Ogre::SceneNode * getSceneNode() const
Gets the scene node to which all PagedGeometry geometry is attached.
Ogre::String getTempdir()
Ogre::SceneManager * getSceneManager() const
Gets the scene manager which is being used to display the geometry.
Ogre::Camera * getCamera() const
Gets the camera which is used to calculate levels of detail.
A faster alternative to Ogre's built-in BillboardSet class.
Ogre::BillboardOrigin getBillboardOrigin() const
Returns the current billboard origin.
void setBillboardOrigin(Ogre::BillboardOrigin origin)
Sets the billboard's origin (pivotal point)
void setTextureStacksAndSlices(Ogre::uint16 stacks, Ogre::uint16 slices)
Sets how many horizontal slices and vertical stacks the currently applied material is using.
void setMaterial(const Ogre::String &materialName, const Ogre::String &resourceGroup=Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME)
Applies a material to the billboards in this set.
@ ALPHA_BLEND_IMPOSTOR
@ ALPHA_REJECT_IMPOSTOR