1 //
// C++ Implementation: AttributeObserver
//
// Description:
//
//
// Author: Erik Hjortsberg <erik.hjortsberg@iteam.se>, ( C ) 2007
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "AttributeObserver.h"
#include <Eris/Entity.h>
#include "services/logging/LoggingService.h"
namespace EmberOgre {
33 AttributeObserver::AttributeObserver( Eris::Entity* entity, const std::string& attributeName )
: mSlot( sigc::mem_fun( *this, &AttributeObserver::attributeChanged ) )
{
if ( entity ) {
entity->observe( attributeName, mSlot );
} else {
S_LOG_WARNING( "Tried to observer the attribute " << attributeName << " or a null entity." );
}
}
43 AttributeObserver::~AttributeObserver( )
{
mSlot.disconnect( );
}
48 void AttributeObserver::attributeChanged( const Atlas::Message::Element& attributeValue )
{
EventChanged.emit( attributeValue );
}
}
1 //
// C++ Interface: AttributeObserver
//
// Description:
//
//
// Author: Erik Hjortsberg <erik.hjortsberg@iteam.se>, ( C ) 2007
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGREATTRIBUTEOBSERVER_H
#define EMBEROGREATTRIBUTEOBSERVER_H
#include <sigc++/trackable.h>
#include <Eris/Entity.h>
namespace Eris {
31 class Entity;
}
namespace EmberOgre {
/**
Observes changes to a specific attribute and emits a signal.
@author Erik Hjortsberg <erik.hjortsberg@iteam.se>
*/
40 class AttributeObserver : public sigc::trackable
{
public:
44 AttributeObserver( Eris::Entity* entity, const std::string& attributeName );
45 ~AttributeObserver( );
47 sigc::signal<void, const Atlas::Message::Element&> EventChanged;
protected:
50 Eris::Entity::AttrChangedSlot mSlot;
52 void attributeChanged( const Atlas::Message::Element& attributeValue );
};
}
#endif
1 /*
Avatar.cpp by Erik Hjortsberg
Copyright ( C ) 2002 Miguel Guzman, Erik Hjortsberg & The Worldforge
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Avatar.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <typeinfo>
#include "services/EmberServices.h"
#include "services/server/ServerService.h"
#include "services/config/ConfigService.h"
// #include "services/sound/SoundService.h"
#include "EmberEntity.h"
#include "EmberPhysicalEntity.h"
#include "AvatarController.h"
#include "AvatarCamera.h"
#include "AvatarEmberEntity.h"
#include "model/Model.h"
#include "model/SubModel.h"
#include "EmberOgre.h"
#include "MathConverter.h"
#include "input/Input.h"
#include <Eris/Avatar.h>
#include <Eris/Connection.h>
#include <Eris/TypeInfo.h>
namespace EmberOgre {
54 Avatar::Avatar( )
: mErisAvatarEntity( 0 ), mHasChangedLocation( false )
{
mTimeSinceLastServerMessage = 0;
setMinIntervalOfRotationChanges( 1000 ); //milliseconds
mAccumulatedHorizontalRotation = 0;
mThresholdDegreesOfYawForAvatarRotation = 100;
///these are the defaults, but if anything is set in the config file that will override these values as updateFromConfig is called
mWalkSpeed = 2.47;
mRunSpeed = 5; ///5 seems to be the max speed in cyphesis
/// Create the Avatar tree of nodes, with a base entity
/// and attach all the needed cameras
createAvatar( );
Ogre::Root::getSingleton( ).addFrameListener( this );
Ember::EmberServices::getSingletonPtr( )->getConfigService( )->EventChangedConfigItem.connect( sigc::mem_fun( *this, &Avatar::ConfigService_EventChangedConfigItem ) );
///update values from the config
updateFromConfig( );
}
82 Avatar::~Avatar( )
{
}
87 void Avatar::setMinIntervalOfRotationChanges( Ogre::Real milliseconds )
{
mMinIntervalOfRotationChanges = milliseconds;
}
92 void Avatar::createAvatar( )
{
// The avatar itself
mAvatarNode = static_cast<Ogre::SceneNode*>( EmberOgre::getSingleton( ).getSceneManager( )->getRootSceneNode( )->createChild( ) );
mAvatarNode->setPosition( Ogre::Vector3( 0, 0, 0 ) );
//mAvatarNode->setOrientation( 0, 1, 0, 0 );
//mAvatarNode->setScale( Ogre::Vector3( 0.01, 0.01, 0.01 ) );
/* // Model Node and Entity for display
// TODO: do also the scaling here! That way the other nodes can be positioned in their real places
mAvatarModelNode = static_cast<Ogre::SceneNode*>( mAvatarNode->createChild( "AvatarModelNode" ) );
Model* model = new Model( "AvatarEntity" );
model->create( "settler" );
// Model* model = Model::Create( "spider.modeldef.xml", "AvatarEntity" );
//Model::Create( "malebuilder.modeldef.xml", "AvatarEntity1" );
mAvatarModel = model;
mAvatarModelNode->attachObject( mAvatarModel );
mAvatarModelNode->rotate( Ogre::Vector3::UNIT_Y, ( Ogre::Degree )90 );*/
/* Ogre::Light* light = mSceneMgr->createLight( "AvatarLight__" );
light->setType( Ogre::Light::LT_POINT );
light->setCastShadows( true );
light->setDiffuseColour( 0.6, 0.6, 0.6 );
//light->setSpecularColour( 1, 1, 1 );
light->setAttenuation( 50, 1, 0.0005, 0 );
mAvatarModelNode->attachObject( light );*/
//
// mAvatarModelNode->showBoundingBox( true );
}
129 bool Avatar::frameStarted( const Ogre::FrameEvent & event )
{
if ( mEntitiesToBeAddedToInventory.size( ) > 0 ) {
std::set<Eris::Entity*>::iterator I = mEntitiesToBeAddedToInventory.begin( );
std::set<Eris::Entity*>::iterator I_end = mEntitiesToBeAddedToInventory.end( );
for ( ; I != I_end; ++I ) {
//no need to do dynamic cast here
EmberEntity* emberEntity = static_cast<EmberEntity*>( *I );
EventAddedEntityToInventory.emit( emberEntity );
}
mEntitiesToBeAddedToInventory.clear( );
}
/* if ( mEntitiesToBeRemovedFromInventory.size( ) > 0 ) {
std::set<Eris::Entity*>::iterator J = mEntitiesToBeRemovedFromInventory.begin( );
std::set<Eris::Entity*>::iterator J_end = mEntitiesToBeRemovedFromInventory.end( );
for ( ; J != J_end; ++J ) {
EmberEntity* emberEntity = dynamic_cast<EmberEntity*>( *J );
if ( emberEntity )
EventRemovedEntityFromInventory.emit( emberEntity );
}
mEntitiesToBeRemovedFromInventory.clear( );
}*/
return true;
}
163 void Avatar::updateFrame( AvatarControllerMovement& movement )
{
///for now we'll just rotate without notifying the server
///except when moving!
attemptRotate( movement );
///this next method will however send send stuff to the server
attemptMove( movement );
///only adjust if there is actual movement. If we adjust when there's only rotation we'll get a strange jerky effect ( some bug I guess )
if ( movement.isMoving ) {
adjustAvatarToNewPosition( &movement );
}
}
181 void Avatar::attemptMove( AvatarControllerMovement& movement )
{
Ogre::Vector3 move = movement.movementDirection;
bool isRunning = movement.mode == AvatarMovementMode::MM_RUN;
Ogre::Real timeSlice = movement.timeSlice;
float speed = isRunning ? mRunSpeed : mWalkSpeed;
Ogre::Vector3 rawVelocity = move * speed;
///first we'll register the current state in newMovementState and compare to mCurrentMovementState
///that way we'll only send stuff to the server if our movement changes
AvatarMovementState newMovementState;
newMovementState.orientation = mAvatarNode->getOrientation( );
newMovementState.velocity = rawVelocity;// * newMovementState.orientation.xAxis( );
if ( move != Ogre::Vector3::ZERO ) {
newMovementState.isMoving = true;
newMovementState.isRunning = isRunning;
} else {
newMovementState.isMoving = false;
newMovementState.isRunning = false;
}
bool sendToServer = false;
//first we check if we are already moving
if ( !mCurrentMovementState.isMoving ) {
//we are not moving. Should we start to move?
if ( newMovementState.isMoving ) {
//we'll start moving
//let's send the movement command to the server
sendToServer = true;
} else if ( !( newMovementState.orientation == mMovementStateAtLastServerMessage.orientation ) ) {
//we have rotated since last server update
//let's see if it's ok to send server message
//if not we have to wait some more frames until we'll send an update
if ( isOkayToSendRotationMovementChangeToServer( ) ) {
sendToServer = true;
}
}
} else {
//we are already moving
//let's see if we've changed speed or direction or even stopped
if ( !newMovementState.isMoving ) {
S_LOG_VERBOSE( "Avatar stopped moving." );
//we have stopped; we must alert the server
sendToServer = true;
} else if ( newMovementState.velocity != mCurrentMovementState.velocity || !( newMovementState.orientation == mCurrentMovementState.orientation ) ){
//either the speed or the direction has changed
sendToServer = true;
}
}
if ( sendToServer ) {
S_LOG_VERBOSE( "Sending move op to server." );
mMovementStateAtBeginningOfMovement = newMovementState;
mMovementStateAtLastServerMessage = newMovementState;
mTimeSinceLastServerMessage = 0;
//for now we'll only send velocity
Ember::EmberServices::getSingletonPtr( )->getServerService( )->moveInDirection( Ogre2Atlas_Vector3( newMovementState.orientation * newMovementState.velocity ), Ogre2Atlas( newMovementState.orientation ) );
// Ember::EmberServices::getSingletonPtr( )->getServerService( )->moveInDirection( Ogre2Atlas( mCurrentMovementState.velocity ), Ogre2Atlas( mCurrentMovementState.orientation ) );
} else {
mTimeSinceLastServerMessage += timeSlice * 1000;
}
if ( newMovementState.isMoving ) {
//do the actual movement of the avatar node
mAvatarNode->translate( mAvatarNode->getOrientation( ) * ( rawVelocity * timeSlice ) );
}
mCurrentMovementState = newMovementState;
}
259 void Avatar::adjustAvatarToNewPosition( AvatarControllerMovement* movement )
{
///allow the eris entity to adjust to the containing node
if ( mErisAvatarEntity ) {
mErisAvatarEntity->adjustPosition( );
}
// MotionManager::getSingleton( ).adjustHeightPositionForNode( mAvatarNode );
}
269 void Avatar::attemptJump( ) {}
272 void Avatar::attemptRotate( AvatarControllerMovement& movement )
{
//TODO: remove the direct references to AvatarCamera
/* float degHoriz = movement.rotationDegHoriz;
float degVert = movement.rotationDegVert;
Ogre::Real timeSlice = movement.timeSlice;*/
// mAccumulatedHorizontalRotation += ( degHoriz * timeSlice );
//if we're moving we must sync the rotation with messages sent to the server
if ( !movement.isMoving && fabs( getAvatarCamera( )->getYaw( ).valueDegrees( ) ) > mThresholdDegreesOfYawForAvatarRotation ) {
// mAvatarNode->setOrientation( movement.cameraOrientation );
mAvatarNode->rotate( Ogre::Vector3::UNIT_Y, getAvatarCamera( )->getYaw( ) );
Ogre::Degree yaw = getAvatarCamera( )->getYaw( );
getAvatarCamera( )->yaw( -yaw );
// mAccumulatedHorizontalRotation = 0;
} else if ( isOkayToSendRotationMovementChangeToServer( ) && ( getAvatarCamera( )->getYaw( ).valueDegrees( ) ) ) {
// rotate the Avatar Node only in X position ( no vertical rotation )
// mAvatarNode->setOrientation( movement.cameraOrientation );
mAvatarNode->rotate( Ogre::Vector3::UNIT_Y, getAvatarCamera( )->getYaw( ) );
Ogre::Degree yaw = getAvatarCamera( )->getYaw( );
getAvatarCamera( )->yaw( -yaw );
// mAvatarNode->rotate( Ogre::Vector3::UNIT_Y, mAccumulatedHorizontalRotation );
// mAccumulatedHorizontalRotation = 0;
}
}
301 bool Avatar::isOkayToSendRotationMovementChangeToServer( )
{
return mTimeSinceLastServerMessage > mMinIntervalOfRotationChanges;
}
307 AvatarCamera* Avatar::getAvatarCamera( ) const
{
return mAvatarController->getAvatarCamera( );
}
312 AvatarEmberEntity* Avatar::getAvatarEmberEntity( )
{
return mErisAvatarEntity;
}
318 void Avatar::setAvatarController( AvatarController* avatarController )
{
mAvatarController = avatarController;
}
323 void Avatar::movedInWorld( )
{
///only snap the avatar to the postiion and orientation sent from the server if we're not moving or if we're not recently changed location
///The main reason when moving is that we don't want to have the avatar snapping back in the case of lag
///However, if we've just recently changed location, we need to also update the orientation to work with the new location.
if ( !mCurrentMovementState.isMoving || mHasChangedLocation )
{
mAvatarNode->setPosition( Atlas2Ogre( mErisAvatarEntity->getPosition( ) ) );
const WFMath::Quaternion& orient = mErisAvatarEntity->getOrientation( );
mAvatarNode->setOrientation( Atlas2Ogre( orient ) );
///we must set this, else ember will think that we've rotated the avatar ourselves and try to send an update to the server
mMovementStateAtLastServerMessage.orientation = mAvatarNode->getOrientation( );
mHasChangedLocation = false;
}
/*
Ember::SoundService* mySoundService = Ember::EmberServices::getSingleton( ).getSoundService( );
{
mySoundService->updateAvatarSourcePosition(
mErisAvatarEntity->getPosition( ),
mErisAvatarEntity>getOrientation( ) );
mySoundService->playAvatarSound( );
}
*/
}
349 void Avatar::avatar_LocationChanged( Eris::Entity* entity )
{
///if we've changed location, we need to update the orientation. This is done on the next onMoved event, which is why we must honour the updated values on next onMoved event, even though we might be moving.
mHasChangedLocation = true;
}
356 void Avatar::createdAvatarEmberEntity( AvatarEmberEntity *emberEntity )
{
Ogre::SceneNode* oldAvatar = mAvatarNode;
///check if the user is of type "creator" and thus an admin
Eris::TypeService* typeService = emberEntity->getErisAvatar( )->getConnection( )->getTypeService( );
if ( emberEntity->getType( )->isA( typeService->getTypeByName( "creator" ) ) ) {
mIsAdmin = true;
} else {
mIsAdmin = false;
}
//mAvatarNode->getParent( )->removeChild( mAvatarNode->getName( ) );
//HACK!!! DEBUG!!
//mAvatarNode->getParent( )->removeChild( mAvatarNode->getName( ) );
//EmberEntity->getSceneNode( )->addChild( mAvatarNode );
// mSceneMgr->getRootSceneNode( )->addChild( mAvatarNode );
//HACK!!! DEBUG!!
mAvatarNode = emberEntity->getSceneNode( );
mAvatarModel = emberEntity->getModel( );
mErisAvatarEntity = emberEntity;
emberEntity->setAvatar( this );
mAvatarController->createAvatarCameras( emberEntity->getSceneNode( ) );
EmberOgre::getSingleton( ).getSceneManager( )->destroySceneNode( oldAvatar->getName( ) );
Input::getSingleton( ).setMovementModeEnabled( true );
mErisAvatarEntity->LocationChanged.connect( sigc::mem_fun( *this, &Avatar::avatar_LocationChanged ) );
}
393 void Avatar::ConfigService_EventChangedConfigItem( const std::string& section, const std::string& key )
{
if ( section == "general" ) {
if ( key == "avatarrotationupdatefrequency" ) {
updateFromConfig( );
}
} else if ( section == "input" ) {
if ( key == "walkspeed" ) {
updateFromConfig( );
}
} else if ( section == "input" ) {
if ( key == "runspeed" ) {
updateFromConfig( );
}
}
}
410 void Avatar::updateFromConfig( )
{
if ( Ember::EmberServices::getSingletonPtr( )->getConfigService( )->itemExists( "general", "avatarrotationupdatefrequency" ) ) {
double frequency = static_cast<double>( Ember::EmberServices::getSingletonPtr( )->getConfigService( )->getValue( "general", "avatarrotationupdatefrequency" ) );
setMinIntervalOfRotationChanges( static_cast<Ogre::Real>( frequency ) );
}
if ( Ember::EmberServices::getSingletonPtr( )->getConfigService( )->itemExists( "input", "walkspeed" ) ) {
mWalkSpeed = static_cast<double>( Ember::EmberServices::getSingletonPtr( )->getConfigService( )->getValue( "input", "walkspeed" ) );
}
if ( Ember::EmberServices::getSingletonPtr( )->getConfigService( )->itemExists( "input", "runspeed" ) ) {
mRunSpeed = static_cast<double>( Ember::EmberServices::getSingletonPtr( )->getConfigService( )->getValue( "input", "runspeed" ) );
}
}
// void Avatar::touch( EmberEntity* entity )
// {
// Ember::EmberServices::getSingletonPtr( )->getServerService( )->touch( entity );
// }
/*
Ogre::Camera* Avatar::getCamera( ) const
{
return mAvatarController->getCamera( );
}
*/
}
1 /*
Avatar.h by Miguel Guzman ( Aglanor )
Copyright ( C ) 2002 Miguel Guzman & The Viewforge Project
Copyright ( C ) 2004 Erik Hjortsberg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef AVATAR_H
#define AVATAR_H
#include "EmberOgrePrerequisites.h"
#include <sigc++/trackable.h>
#include <sigc++/signal.h>
#include "framework/Singleton.h"
namespace Eris {
32 class Entity;
}
namespace EmberOgre {
namespace Model {
39 class Model;
}
class EmberEntity;
43 class AvatarCamera;
44 class AvatarController;
45 class AvatarEmberEntity;
struct AvatarControllerMovement;
struct AvatarMovementState
{
public:
bool isMoving;
bool isRunning;
Ogre::Vector3 velocity;
Ogre::Quaternion orientation;
};
/**
* This class holds the Avatar. In general it recieves instructions from mainly
* AvatarController to attempt to move or rotate the avatar. After checking
* with the world rules if such a thing is allowed, the world node is manipulated.
* If it's a movement it has to be animated.
*
*/
64 class Avatar :
65 public sigc::trackable,
66 public Ogre::FrameListener
{
68 friend class AvatarController;
69 friend class AvatarEmberEntity;
public:
73 Avatar( );
74 virtual ~Avatar( );
/**
* Gets the avatar camera.
* @return
*/
81 AvatarCamera* getAvatarCamera( ) const;
/**
* Gets the scene node which the avatar is attached to.
* @return
*/
87 inline Ogre::SceneNode* getAvatarSceneNode( ) const;
/**
* Called each frame.
* @param event
* @return
*/
94 virtual bool frameStarted( const Ogre::FrameEvent & event );
/**
* Call this when the Eris::Entity representing the avatar has been created.
* @param EmberEntity
*/
100 void createdAvatarEmberEntity( AvatarEmberEntity *EmberEntity );
/**
* Call this when the avatar entity has moved in the world.
*/
105 void movedInWorld( );
/**
* Called each frame.
* @param movement
*/
112 void updateFrame( AvatarControllerMovement& movement );
/**
* Sets the controller object responsible for controlling the avatar.
* @param avatarController
*/
118 void setAvatarController( AvatarController* avatarController );
/**
* Access for the Eris::Entity which represents the Avatar.
* @return
*/
124 AvatarEmberEntity* getAvatarEmberEntity( );
/**
* sets the minimum interval to wait before sending new rotation changes to the server
* this is not done instantly to prevent swamping of data to the server
* set this lower if you experience too jerky game play
* @param milliseconds
*/
133 void setMinIntervalOfRotationChanges( Ogre::Real milliseconds );
/**
Emitted when an entity is added to the inventory.
*/
138 sigc::signal<void, EmberEntity* > EventAddedEntityToInventory;
/**
Emitted when an entity is removed from the inventory.
*/
143 sigc::signal<void, EmberEntity* > EventRemovedEntityFromInventory;
/**
True if the current user have admin rights, i.e. is a "creator".
*/
148 inline bool isAdmin( ) const;
protected:
/**
* adjust the avatar to the new position in the terrain
* for now this means setting the correct heigth
* accoring to mercator terrain, but it will probably
* be extended to also include stuff as positioning the avatars feet
* right
*/
159 void adjustAvatarToNewPosition( AvatarControllerMovement* movement );
/**
* This method will determine if it's ok to send a small movement change, such as
* a small deviation direction during an already begun movement to the server.
*/
165 bool isOkayToSendRotationMovementChangeToServer( );
/**
Time in milliseconds since we last sent an movement update to the server.
*/
170 Ogre::Real mTimeSinceLastServerMessage;
/**
In milliseconds, the minimum time we must wait between sending updates to the server. Set this higher to avoid spamming the server.
*/
175 Ogre::Real mMinIntervalOfRotationChanges;
/**
In degrees the minimum amount of degrees we can yaw the camera until we need to send an update to the server of our new position.
*/
180 Ogre::Real mThresholdDegreesOfYawForAvatarRotation;
/**
In degrees the accumulated yaw movement since we last sent an update to the server. If this exceeds mThresholdDegreesOfYawForAvatarRotation we need to send an update to the server.
*/
float mAccumulatedHorizontalRotation;
/**
* Attempts to move the avatar in a certain direction
* Note that depending on what the rules allows ( i.e. collision detection,
* character rules etc. ) the outcome of the attempt is uncertain.
*
* The parameter timeSlice denotes the slice of time under which the movement
* shall take place.
*/
195 void attemptMove( AvatarControllerMovement& movement );
/**
* Attempts to rotate the avatar to a certain direction
* Note that depending on what the rules allows ( i.e. collision detection,
* character rules etc. ) the outcome of the attempt is uncertain.
*
* When standing still one can rotate how much one want.
* But when moving, rotation happens in interval
*
*/
206 void attemptRotate( AvatarControllerMovement& movement );
/**
* Attempts to stop the avatar.
* This should work in most cases.
*
*/
214 void attemptStop( );
/**
* Attempt to jump.
*/
219 void attemptJump( );
/**
* Creates the avatar. We'll have to extend this functionality later on to
* allow for different avatars.
*/
226 void createAvatar( );
/**
* Creates and sets up the different cameras.
*/
232 void createAvatarCameras( Ogre::SceneNode* avatarSceneNode );
/**
* How many meters per second the avatar can walk.
* This should be set through some kind of rule checking with the server
* depending on the character. To be done later.
*/
float mWalkSpeed;
/**
* How many meters per second the avatar can run.
* This should be set through some kind of rule checking with the server
* depending on the character. To be done later.
*/
float mRunSpeed;
/**
* The main avatar model
*/
251 Model::Model* mAvatarModel;
/**
* The main avatar scenenode
*/
256 Ogre::SceneNode* mAvatarNode;
/** node for rotating the model for the entity
* if it's not looking in the -Z direction ( default )
* To be removed once we've standarized on models
*/
264 Ogre::SceneNode* mAvatarModelNode;
/**
The Eris::Entity which represents the Avatar.
*/
269 AvatarEmberEntity* mErisAvatarEntity;
/**
* this is used to make sure starts and stops of movement is only sent to the server once
*/
AvatarMovementState mCurrentMovementState;
AvatarMovementState mMovementStateAtBeginningOfMovement; //this is perhaps not needed
AvatarMovementState mMovementStateAtLastServerMessage;
/**
The instance responsible for listening for movement updates and sending those to the server.
*/
281 AvatarController* mAvatarController;
/**
Keep a temporary list of entities that needs to be added to the inventory.
*/
286 std::set<Eris::Entity*> mEntitiesToBeAddedToInventory;
/**
Keep a temporary list of entities that needs to be removed from the inventory.
*/
291 std::set<Eris::Entity*> mEntitiesToBeRemovedFromInventory;
/**
* catch changes to the configuration
* @param section
* @param key
*/
299 void ConfigService_EventChangedConfigItem( const std::string& section, const std::string& key );
/**
* Listen for location changes, since after a location change we need to honour the onMoved updates even if we're in movement mode.
* @param entity
*/
305 void avatar_LocationChanged( Eris::Entity* entity );
/**
* updates values from the configuration
*/
310 void updateFromConfig( );
/**
True if the current user have admin rights, i.e. is a "creator".
*/
315 bool mIsAdmin;
/**
If set to true, the avatar has just changed location, so the next onMoved operation will contain the new orientation and position information for the new location.
*/
320 bool mHasChangedLocation;
}; //End of class declaration
325 bool Avatar::isAdmin( ) const
{
return mIsAdmin;
}
329 Ogre::SceneNode* Avatar::getAvatarSceneNode( ) const
{
return mAvatarNode;
}
}
#endif // ENTITY_LISTENER_H
/*
Copyright ( C ) 2004 Erik Hjortsberg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "AvatarCamera.h"
#include "Avatar.h"
#include "GUIManager.h"
#include "EmberOgre.h"
#include "EmberEntity.h"
// #include "WorldEmberEntity.h"
#include "MathConverter.h"
#include "services/EmberServices.h"
#include "services/config/ConfigService.h"
#ifndef WIN32
#include "services/sound/SoundService.h"
#endif
#include "MousePicker.h"
// #include "jesus/JesusPickerObject.h"
#include "SceneManagers/EmberPagingSceneManager/include/OgrePagingLandScapeRaySceneQuery.h"
#include "framework/Tokeniser.h"
#include "framework/ConsoleBackend.h"
#include "GUIManager.h"
#include "input/Input.h"
#include "IWorldPickListener.h"
#include "framework/osdir.h"
#ifdef __WIN32__
#include <windows.h>
#include <direct.h>
#endif
namespace EmberOgre {
56 Recorder::Recorder( ): mSequence( 0 ), mAccruedTime( 0.0f ), mFramesPerSecond( 20.0f )
{
}
60 void Recorder::startRecording( )
{
Ogre::Root::getSingleton( ).addFrameListener( this );
}
64 void Recorder::stopRecording( )
{
Ogre::Root::getSingleton( ).removeFrameListener( this );
}
69 bool Recorder::frameStarted( const Ogre::FrameEvent& event )
{
mAccruedTime += event.timeSinceLastFrame;
if ( mAccruedTime >= ( 1.0f / mFramesPerSecond ) ) {
mAccruedTime = 0.0f;
std::stringstream filename;
filename << "screenshot_" << mSequence++ << ".tga";
const std::string dir = Ember::EmberServices::getSingletonPtr( )->getConfigService( )->getHomeDirectory( ) + "/recordings/";
try {
//make sure the directory exists
struct stat tagStat;
int ret;
ret = stat( dir.c_str( ), &tagStat );
if ( ret == -1 ) {
#ifdef __WIN32__
mkdir( dir.c_str( ) );
#else
mkdir( dir.c_str( ), S_IRWXU );
#endif
}
} catch ( const std::exception& ex ) {
S_LOG_FAILURE( "Error when creating directory for screenshots. Message: " << std::string( ex.what( ) ) );
stopRecording( );
return true;
}
try {
// take screenshot
EmberOgre::getSingleton( ).getRenderWindow( )->writeContentsToFile( dir + filename.str( ) );
} catch ( const Ogre::Exception& ex ) {
S_LOG_FAILURE( "Could not write screenshot to disc. Message: "<< ex.getFullDescription( ) );
stopRecording( );
return true;
}
}
return true;
}
109 AvatarCamera::AvatarCamera( Ogre::SceneNode* avatarNode, Ogre::SceneManager* sceneManager, Ogre::RenderWindow* window, GUIManager* guiManager, Ogre::Camera* camera ) :
SetCameraDistance( "setcameradistance", this, "Set the distance of the camera." ),
ToggleRendermode( "toggle_rendermode", this, "Toggle between wireframe and solid render modes." ),
ToggleFullscreen( "toggle_fullscreen", this, "Switch between windowed and full screen mode." ),
Screenshot( "screenshot", this, "Take a screenshot and write to disk." ),
Record( "+record", this, "Record to disk." ),
mInvertCamera( false ),
mGUIManager( guiManager ),
mCamera( camera ),
mAvatarNode( 0 ),
mSceneManager( sceneManager ),
mDegreeOfPitchPerSecond( 50 ),
mDegreeOfYawPerSecond( 50 ),
degreePitch( 0 ),
degreeYaw( 0 ),
mWindow( window ),
mViewPort( 0 ),
mClosestPickingDistance( 10000 ),
mLastPosition( Ogre::Vector3::ZERO ),
mAdjustTerrainRaySceneQuery( 0 ),
mCameraRaySceneQuery( 0 ),
mIsAdjustedToTerrain( true )
// mLastOrientationOfTheCamera( avatar->getOrientation( ) )
{
createNodesForCamera( );
createViewPort( );
setAvatarNode( avatarNode );
/// Register this as a frame listener
Ogre::Root::getSingleton( ).addFrameListener( this );
if ( mGUIManager ) {
mGUIManager->getInput( ).EventMouseMoved.connect( sigc::mem_fun( *this, &AvatarCamera::Input_MouseMoved ) );
}
Ember::EmberServices::getSingletonPtr( )->getConfigService( )->EventChangedConfigItem.connect( sigc::mem_fun( *this, &AvatarCamera::ConfigService_EventChangedConfigItem ) );
updateValuesFromConfig( );
createRayQueries( );
}
AvatarCamera::~AvatarCamera( )
{
Ogre::Root::getSingleton( ).removeFrameListener( this );
EmberOgre::getSingleton( ).getSceneManager( )->destroyQuery( mAdjustTerrainRaySceneQuery );
EmberOgre::getSingleton( ).getSceneManager( )->destroyQuery( mCameraRaySceneQuery );
}
void AvatarCamera::createRayQueries( )
{
mAdjustTerrainRaySceneQuery = EmberOgre::getSingletonPtr( )->getSceneManager( )->createRayQuery( mAdjustTerrainRay, Ogre::SceneManager::WORLD_GEOMETRY_TYPE_MASK );
///only test for terrain
mAdjustTerrainRaySceneQuery->setWorldFragmentType( Ogre::SceneQuery::WFT_SINGLE_INTERSECTION );
mAdjustTerrainRaySceneQuery->setSortByDistance( true );
mAdjustTerrainRaySceneQuery->setQueryTypeMask( Ogre::SceneManager::WORLD_GEOMETRY_TYPE_MASK );
unsigned long queryMask = Ogre::SceneManager::WORLD_GEOMETRY_TYPE_MASK;
queryMask |= MousePicker::CM_AVATAR;
queryMask |= MousePicker::CM_ENTITY;
queryMask |= MousePicker::CM_NATURE;
queryMask |= MousePicker::CM_UNDEFINED;
// queryMask |= Ogre::RSQ_FirstTerrain;
mCameraRaySceneQuery = mSceneManager->createRayQuery( Ogre::Ray( ), queryMask );
mCameraRaySceneQuery->setWorldFragmentType( Ogre::SceneQuery::WFT_SINGLE_INTERSECTION );
mCameraRaySceneQuery->setSortByDistance( true );
}
void AvatarCamera::createNodesForCamera( )
{
mAvatarCameraRootNode = mSceneManager->createSceneNode( "AvatarCameraRootNode" );
//we need to adjust for the height of the avatar mesh
mAvatarCameraRootNode->setPosition( Ogre::Vector3( 0, 2, 0 ) );
//rotate to sync with WF world
mAvatarCameraRootNode->rotate( Ogre::Vector3::UNIT_Y, ( Ogre::Degree )-90 );
mAvatarCameraPitchNode = mAvatarCameraRootNode->createChildSceneNode( "AvatarCameraPitchNode" );
mAvatarCameraPitchNode->setPosition( Ogre::Vector3( 0, 0, 0 ) );
mAvatarCameraNode = mAvatarCameraPitchNode->createChildSceneNode( "AvatarCameraNode" );
setCameraDistance( 10 );
// mCamera = mSceneManager->createCamera( "AvatarCamera" );
mAvatarCameraNode->attachObject( mCamera );
// Look to the Avatar's head
//mAvatar3pCamera->setAutoTracking( true, mAvatar1pCameraNode );
mCamera->setNearClipDistance( 0.5 );
///set the far clip distance high to make sure that the sky is completely shown
if ( Ogre::Root::getSingleton( ).getRenderSystem( )->getCapabilities( )->hasCapability( Ogre::RSC_INFINITE_FAR_PLANE ) )
{
/* //NOTE: this won't currently work with the sky
mCamera->setFarClipDistance( 0 );*/
mCamera->setFarClipDistance( 10000 );
} else {
mCamera->setFarClipDistance( 10000 );
}
//create the nodes for the camera
setMode( MODE_THIRD_PERSON );
// createViewPort( );
}
void AvatarCamera::setMode( Mode mode )
{
mMode = mode;
/* if ( mMode == MODE_THIRD_PERSON ) {
mCamera->setAutoTracking( true, mAvatarCameraRootNode );
} else {
mCamera->setAutoTracking( false );
}*/
}
const Ogre::Quaternion& AvatarCamera::getOrientation( bool onlyHorizontal ) const {
if ( !onlyHorizontal ) {
return getCamera( )->getDerivedOrientation( );
} else {
static Ogre::Quaternion quat;
quat = getCamera( )->getDerivedOrientation( );
quat.x = 0;
quat.z = 0;
return quat;
}
}
const Ogre::Vector3& AvatarCamera::getPosition( ) const
{
return mCamera->getDerivedPosition( );
}
void AvatarCamera::attach( Ogre::SceneNode* toNode ) {
mIsAttached = true;
assert( mAvatarCameraRootNode );
if ( mAvatarCameraRootNode->getParent( ) ) {
mAvatarCameraRootNode->getParent( )->removeChild( mAvatarCameraRootNode->getName( ) );
}
toNode->addChild( mAvatarCameraRootNode );
setCameraDistance( 10 );
mAvatarCameraNode->setOrientation( Ogre::Quaternion::IDENTITY );
mAvatarCameraNode->_update( true, true );
std::stringstream ss;
ss << "Attached camera to node: " << toNode->getName( ) <<". New position: " << mCamera->getWorldPosition( ) << " New orientation: " << mCamera->getWorldOrientation( );
S_LOG_VERBOSE( ss.str( ) );
}
void AvatarCamera::enableCompositor( const std::string& compositorName, bool enable )
{
if ( std::find( mLoadedCompositors.begin( ), mLoadedCompositors.end( ), compositorName ) == mLoadedCompositors.end( ) ) {
Ogre::CompositorManager::getSingleton( ).addCompositor( mWindow->getViewport( 0 ), compositorName );
}
Ogre::CompositorManager::getSingleton( ).setCompositorEnabled( mWindow->getViewport( 0 ), compositorName, enable );
}
void AvatarCamera::createViewPort( )
{
// Ogre::CompositorManager::getSingleton( ).addCompositor( mWindow->getViewport( 0 ), "Bloom" );
// Ogre::CompositorManager::getSingleton( ).setCompositorEnabled( mWindow->getViewport( 0 ), "Bloom", true );
// assert( mCamera );
// assert( !mViewPort );
// // Create 1st person viewport, entire window
// mViewPort = mWindow->addViewport( mCamera );
// mViewPort->setBackgroundColour( Ogre::ColourValue( 0, 0, 0 ) );
// mCamera->setAspectRatio(
// Ogre::Real( mViewPort->getActualWidth( ) ) / Ogre::Real( mViewPort->getActualHeight( ) ) );
}
void AvatarCamera::toggleRenderMode( )
{
S_LOG_INFO( "Switching render mode." );
if ( mCamera->getPolygonMode( ) == Ogre::PM_SOLID ) {
mCamera->setPolygonMode( Ogre::PM_WIREFRAME );
} else {
mCamera->setPolygonMode( Ogre::PM_SOLID );
}
}
void AvatarCamera::setAvatarNode( Ogre::SceneNode* sceneNode )
{
mAvatarNode = sceneNode;
attach( mAvatarNode );
}
void AvatarCamera::setCameraDistance( Ogre::Real distance )
{
mWantedCameraDistance = distance;
_setCameraDistance( distance );
}
void AvatarCamera::_setCameraDistance( Ogre::Real distance )
{
mCurrentCameraDistance = distance;
Ogre::Vector3 pos( 0, 0, distance );
mAvatarCameraNode->setPosition( pos );
EventChangedCameraDistance.emit( distance );
}
void AvatarCamera::pitch( Ogre::Degree degrees )
{
if ( mInvertCamera ) {
degrees -= degrees * 2;
}
if ( mMode == MODE_THIRD_PERSON ) {
degreePitch += degrees;
mAvatarCameraPitchNode->pitch( degrees );
} else {
mAvatarCameraNode->pitch( degrees );
}
}
void AvatarCamera::yaw( Ogre::Degree degrees )
{
if ( mMode == MODE_THIRD_PERSON ) {
degreeYaw += degrees;
mAvatarCameraRootNode->yaw( degrees );
mAvatarCameraRootNode->needUpdate( );
// Ogre::Quaternion q = mAvatarCameraRootNode->_getDerivedOrientation( );
} else {
mAvatarCameraNode->yaw( degrees );
}
}
void AvatarCamera::Input_MouseMoved( const MouseMotion& motion, Input::InputMode mode )
/*( int xPosition, int yPosition, Ogre::Real xRelativeMovement, Ogre::Real yRelativeMovement, Ogre::Real timeSinceLastMovement )*/
{
if ( mode == Input::IM_MOVEMENT ) {
Ogre::Degree diffX( mDegreeOfYawPerSecond * motion.xRelativeMovement );
Ogre::Degree diffY( mDegreeOfPitchPerSecond * motion.yRelativeMovement );
if ( diffX.valueDegrees( ) ) {
this->yaw( diffX );
// this->yaw( diffX * e->timeSinceLastFrame );
}
if ( diffY.valueDegrees( ) ) {
this->pitch( diffY );
// this->pitch( diffY * e->timeSinceLastFrame );
}
if ( diffY.valueDegrees( ) || diffX.valueDegrees( ) ) {
MovedCamera.emit( mCamera );
}
}
}
void AvatarCamera::pickInWorld( Ogre::Real mouseX, Ogre::Real mouseY, const MousePickerArgs& mousePickerArgs )
{
S_LOG_INFO( "Trying to pick an entity at mouse coords: " << Ogre::StringConverter::toString( mouseX ) << ":" << Ogre::StringConverter::toString( mouseY ) << "." );
/// Start a new ray query
Ogre::Ray cameraRay = getCamera( )->getCameraToViewportRay( mouseX, mouseY );
mCameraRaySceneQuery->setRay( cameraRay );
mCameraRaySceneQuery->execute( );
///now check the entity picking
Ogre::RaySceneQueryResult& queryResult = mCameraRaySceneQuery->getLastResults( );
bool continuePicking = true;
for ( WorldPickListenersStore::iterator I = mPickListeners.begin( ); I != mPickListeners.end( ); ++I ) {
( *I )->initializePickingContext( );
}
Ogre::RaySceneQueryResult::iterator rayIterator = queryResult.begin( );
Ogre::RaySceneQueryResult::iterator rayIterator_end = queryResult.end( );
if ( rayIterator != rayIterator_end ) {
for ( ; rayIterator != rayIterator_end && continuePicking; rayIterator++ ) {
for ( WorldPickListenersStore::iterator I = mPickListeners.begin( ); I != mPickListeners.end( ); ++I ) {
( *I )->processPickResult( continuePicking, *rayIterator, cameraRay, mousePickerArgs );
if ( !continuePicking ) {
break;
}
}
}
}
for ( WorldPickListenersStore::iterator I = mPickListeners.begin( ); I != mPickListeners.end( ); ++I ) {
( *I )->endPickingContext( mousePickerArgs );
}
}
bool AvatarCamera::worldToScreen( const Ogre::Vector3& worldPos, Ogre::Vector3& screenPos )
{
Ogre::Vector3 hcsPosition = mCamera->getProjectionMatrix( ) * ( mCamera->getViewMatrix( ) * worldPos );
if ( ( hcsPosition.x < -1.0f ) ||
( hcsPosition.x > 1.0f ) ||
( hcsPosition.y < -1.0f ) ||
( hcsPosition.y > 1.0f ) )
return false;
screenPos.x = ( hcsPosition.x + 1 ) * 0.5;
screenPos.y = ( -hcsPosition.y + 1 ) * 0.5;
return true;
}
void AvatarCamera::setClosestPickingDistance( Ogre::Real distance )
{
mClosestPickingDistance = distance;
}
Ogre::Real AvatarCamera::getClosestPickingDistance( )
{
return mClosestPickingDistance;
}
bool AvatarCamera::adjustForTerrain( )
{
/// We will shoot a ray from the camera base node to the camera. If it hits anything on the way we know that there's something between the camera and the avatar and we'll position the camera closer to the avatar. Thus we'll avoid having the camera dip below the terrain
///For now we'll only check against the terrain
const Ogre::Vector3 direction( -mCamera->getDerivedDirection( ) );
///If the direction if pointing straight upwards we'll end up in an infinite loop in the ray query
if ( direction.z != 0 ) {
mAdjustTerrainRay.setDirection( direction );
mAdjustTerrainRay.setOrigin( mAvatarCameraRootNode->getWorldPosition( ) );
mAdjustTerrainRaySceneQuery->setRay( mAdjustTerrainRay );
mAdjustTerrainRaySceneQuery->execute( );
Ogre::RaySceneQueryResult queryResult = mAdjustTerrainRaySceneQuery->getLastResults( );
Ogre::RaySceneQueryResult::iterator rayIterator = queryResult.begin( );
for ( ; rayIterator != queryResult.end( ); ++rayIterator ) {
Ogre::RaySceneQueryResultEntry& entry = *rayIterator;
if ( entry.worldFragment ) {
Ogre::Vector3 position = entry.worldFragment->singleIntersection;
Ogre::Real distance = mAvatarCameraRootNode->getWorldPosition( ).distance( position );
if ( distance < mWantedCameraDistance ) {
_setCameraDistance( distance - 0.1 );
} else {
if ( mWantedCameraDistance != mCurrentCameraDistance ) {
_setCameraDistance( mWantedCameraDistance );
}
}
break;
}
}
}
/* Ogre::RaySceneQuery *raySceneQueryHeight = EmberOgre::getSingletonPtr( )->getSceneManager( )->createRayQuery( Ogre::Ray( mCamera->getDerivedPosition( ), Ogre::Vector3::NEGATIVE_UNIT_Y ), Ogre::SceneManager::WORLD_GEOMETRY_TYPE_MASK );
raySceneQueryHeight->execute( );
//first check the terrain picking
Ogre::RaySceneQueryResult queryResult = raySceneQueryHeight->getLastResults( );
if ( queryResult.begin( ) != queryResult.end( ) ) {
Ogre::Vector3 position = queryResult.begin( )->worldFragment->singleIntersection;
Ogre::Real terrainHeight = position.y;
//pad it a little
//terrainHeight += 0.4;
Ogre::Real cameraHeight = mCamera->getDerivedPosition( ).y;
Ogre::Real cameraNodeHeight = mAvatarCameraNode->getWorldPosition( ).y;
if ( terrainHeight > cameraHeight ) {
mCamera->move( mCamera->getDerivedOrientation( ).Inverse( ) * Ogre::Vector3( 0, terrainHeight - cameraHeight, 0 ) );
// mCamera->lookAt( mAvatarCameraRootNode->getPosition( ) );
} else if ( cameraHeight != cameraNodeHeight ) {
Ogre::Real newHeight = std::max<Ogre::Real>( terrainHeight, cameraNodeHeight );
mCamera->move( Ogre::Vector3( 0, newHeight - cameraHeight, 0 ) );
mCamera->lookAt( mAvatarCameraRootNode->getWorldPosition( ) );
}
}*/
return true;
}
void AvatarCamera::runCommand( const std::string &command, const std::string &args )
{
if( Screenshot == command ) {
//just take a screen shot
takeScreenshot( );
} else if( SetCameraDistance == command )
{
Ember::Tokeniser tokeniser;
tokeniser.initTokens( args );
std::string distance = tokeniser.nextToken( );
if ( distance != "" ) {
float fDistance = Ogre::StringConverter::parseReal( distance );
setCameraDistance( fDistance );
}
} else if ( ToggleFullscreen == command ){
SDL_WM_ToggleFullScreen( SDL_GetVideoSurface( ) );
} else if ( ToggleRendermode == command ) {
toggleRenderMode( );
} else if ( Record == command ) {
mRecorder.startRecording( );
} else if ( Record.getInverseCommand( ) == command ) {
mRecorder.stopRecording( );
}
}
void AvatarCamera::updateValuesFromConfig( )
{
if ( Ember::EmberServices::getSingletonPtr( )->getConfigService( )->itemExists( "input", "invertcamera" ) ) {
mInvertCamera = static_cast<bool>( Ember::EmberServices::getSingletonPtr( )->getConfigService( )->getValue( "input", "invertcamera" ) );
}
if ( Ember::EmberServices::getSingletonPtr( )->getConfigService( )->itemExists( "input", "cameradegreespersecond" ) ) {
mDegreeOfPitchPerSecond = mDegreeOfYawPerSecond = ( double )Ember::EmberServices::getSingletonPtr( )->getConfigService( )->getValue( "input", "cameradegreespersecond" );
}
if ( Ember::EmberServices::getSingletonPtr( )->getConfigService( )->itemExists( "input", "adjusttoterrain" ) ) {
mIsAdjustedToTerrain = static_cast<bool>( Ember::EmberServices::getSingletonPtr( )->getConfigService( )->getValue( "input", "adjusttoterrain" ) );
}
}
void AvatarCamera::ConfigService_EventChangedConfigItem( const std::string& section, const std::string& key )
{
if ( section == "input" ) {
if ( key == "invertcamera" || key == "cameradegreespersecond" || key == "adjusttoterrain" ) {
updateValuesFromConfig( );
}
}
}
bool AvatarCamera::frameStarted( const Ogre::FrameEvent& event )
{
if ( mIsAdjustedToTerrain ) {
if ( mCamera->getDerivedPosition( ) != mLastPosition ) {
adjustForTerrain( );
}
}
mLastPosition = mCamera->getDerivedPosition( );
// #ifndef WIN32
// Ember::SoundService* mySoundService = Ember::EmberServices::getSingleton( ).getSoundService( );
// {
// mySoundService->updateListenerPosition(
// Ogre2Atlas( mCamera->getPosition( ) ),
// Ogre2Atlas( mCamera->getOrientation( ) ) );
// }
// #endif
return true;
}
void AvatarCamera::pushWorldPickListener( IWorldPickListener* worldPickListener )
{
mPickListeners.push_front( worldPickListener );
}
const std::string AvatarCamera::_takeScreenshot( )
{
// retrieve current time
time_t rawtime;
struct tm* timeinfo;
time( &rawtime );
timeinfo = localtime( &rawtime );
// construct filename string
// padding with 0 for single-digit values
std::stringstream filename;
filename << "screenshot_" << ( ( *timeinfo ).tm_year + 1900 ); // 1900 is year "0"
int month = ( ( *timeinfo ).tm_mon + 1 ); // January is month "0"
if( month <= 9 )
{
filename << "0";
}
filename << month;
int day = ( *timeinfo ).tm_mday;
if( day <= 9 )
{
filename << "0";
}
filename << day << "_";
int hour = ( *timeinfo ).tm_hour;
if( hour <= 9 )
{
filename << "0";
}
filename << hour;
int min = ( *timeinfo ).tm_min;
if( min <= 9 )
{
filename << "0";
}
filename << min;
int sec = ( *timeinfo ).tm_sec;
if( sec <= 9 )
{
filename << "0";
}
filename << sec << ".jpg";
const std::string dir = Ember::EmberServices::getSingletonPtr( )->getConfigService( )->getHomeDirectory( ) + "/screenshots/";
try {
//make sure the directory exists
oslink::directory osdir( dir );
if ( !osdir.isExisting( ) ) {
#ifdef __WIN32__
mkdir( dir.c_str( ) );
#else
mkdir( dir.c_str( ), S_IRWXU );
#endif
}
} catch ( const std::exception& ex ) {
S_LOG_FAILURE( "Error when creating directory for screenshots. Message: " << std::string( ex.what( ) ) );
throw Ember::Exception( "Error when saving screenshot. Message: " + std::string( ex.what( ) ) );
}
try {
// take screenshot
mWindow->writeContentsToFile( dir + filename.str( ) );
} catch ( const Ogre::Exception& ex ) {
S_LOG_FAILURE( "Could not write screenshot to disc. Message: "<< ex.getFullDescription( ) );
throw Ember::Exception( "Error when saving screenshot. Message: " + ex.getDescription( ) );
}
return dir + filename.str( );
}
void AvatarCamera::takeScreenshot( )
{
try {
const std::string& result = _takeScreenshot( );
S_LOG_INFO( result );
Ember::ConsoleBackend::getMainConsole( )->pushMessage( "Wrote image: " + result );
} catch ( const Ember::Exception& ex ) {
Ember::ConsoleBackend::getMainConsole( )->pushMessage( "Error when saving screenshot: " + ex.getError( ) );
}
}
}
1 /*
Copyright ( C ) 2004 Erik Hjortsberg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* An instance of this is a player controlled camera fastened to the Avatar.
* It should be possible to subclass this in order to provide different behaviour
*/
#ifndef AVATARCAMERA_H
#define AVATARCAMERA_H
#include "EmberOgrePrerequisites.h"
#include <sigc++/trackable.h>
#include "framework/ConsoleObject.h"
#include "input/Input.h"
#include <stack>
namespace EmberOgre {
41 class Avatar;
42 class InputManager;
43 class GUIManager;
44 class EmberEntity;
struct MouseMotion;
struct EntityPickResult;
47 class IWorldPickListener;
struct MousePickerArgs;
50 class Recorder :public Ogre::FrameListener
{
public:
53 Recorder( );
54 void startRecording( );
55 void stopRecording( );
/**
* Methods from Ogre::FrameListener
*/
59 bool frameStarted( const Ogre::FrameEvent& event );
private:
int mSequence;
float mAccruedTime;
float mFramesPerSecond;
};
67 class AvatarCamera
:
69 public sigc::trackable,
70 public Ember::ConsoleObject,
71 public Ogre::FrameListener
{
public:
enum Mode {
MODE_THIRD_PERSON = 1,
MODE_FIRST_PERSON = 2
};
80 AvatarCamera( Ogre::SceneNode* avatarNode, Ogre::SceneManager* sceneManager, Ogre::RenderWindow* window, GUIManager* guiManager, Ogre::Camera* camera );
81 virtual ~AvatarCamera( );
/**
* Pitches the camera the supplied degrees
*/
86 virtual void pitch( Ogre::Degree degrees );
/**
* Yaws the camera the supplied degrees
*/
91 virtual void yaw( Ogre::Degree degrees );
/**
* returns the current degrees of pitch from the cameras initial position
*/
96 inline const Ogre::Degree& getPitch( ) const;
/**
* returns the current degrees of yaw from the cameras initial position
*/
101 inline const Ogre::Degree& getYaw( ) const;
/**
* returns a pointer to the Ogre::Camera instance
*/
106 inline Ogre::Camera* getCamera( );
107 inline Ogre::Camera* getCamera( ) const;
/**
* Returns the current camera orientation in the world
*/
112 virtual const Ogre::Quaternion& getOrientation( bool onlyHorizontal = true ) const;
/**
* Returns the position of the camera in the world.
* @return
*/
119 const Ogre::Vector3& getPosition( ) const;
122 void setMode( Mode mode );
/**
* sets the node to which the camera is attached
*/
127 virtual void setAvatarNode( Ogre::SceneNode* sceneNode );
/**
* emitted when the camra moves
*/
132 sigc::signal<void, Ogre::Camera*> MovedCamera;
/**
* emitted when the distance between the camera and the avatar has changed
* @param Ogre::Real the new distance
*/
138 sigc::signal<void, Ogre::Real> EventChangedCameraDistance;
// int xPosition, int yPosition, Ogre::Real xRelativeMovement, Ogre::Real yRelativeMovement, Ogre::Real timeSinceLastMovement );
// void mouseMoved ( Ogre::MouseEvent *e );
// void mouseDragged ( Ogre::MouseEvent *e ) {};
145 void pickInWorld( Ogre::Real mouseX, Ogre::Real mouseY, const MousePickerArgs& args );
// EntityPickResult pickAnEntity( Ogre::Real mouseX, Ogre::Real mouseY );
// std::vector<Ogre::RaySceneQueryResultEntry> AvatarCamera::pickObject( Ogre::Real mouseX, Ogre::Real mouseY, std::vector<Ogre::UserDefinedObject*> exclude, unsigned long querymask );
150 void setClosestPickingDistance( Ogre::Real distance );
151 Ogre::Real getClosestPickingDistance( );
/**
* returns true if the worldPos is on screen, putting the screen pos into the x & y of the second Vector3
* returns false if the worldPos is off screen
* @param worldPos
* @param screenPos
* @return
*/
160 bool worldToScreen( const Ogre::Vector3& worldPos, Ogre::Vector3& screenPos );
/**
* Attaches the camera to the specified scene node.
* @param toNode
*/
166 void attach( Ogre::SceneNode* toNode );
/**
* Adjusts the camera for the terrain, so it doesn't dip below it.
* @return
*/
172 bool adjustForTerrain( );
/**
* Reimplements the ConsoleObject::runCommand method
* @param command
* @param args
*/
180 virtual void runCommand( const std::string &command, const std::string &args );
/**
* Sets the distance from the camera to the avatar.
* @param distance the new distance
*/
187 void setCameraDistance( Ogre::Real distance );
/**
* Methods from Ogre::FrameListener
*/
192 bool frameStarted( const Ogre::FrameEvent& event );
//bool frameEnded( const Ogre::FrameEvent& event );
/**
* Enables and disables a compositor by name.
* @param compositorName
* @param enable
*/
200 void enableCompositor( const std::string& compositorName, bool enable );
/**
* Adds a new world pick listener to the queue of listeners.
* @param worldPickListener
*/
207 void pushWorldPickListener( IWorldPickListener* worldPickListener );
209 const Ember::ConsoleCommandWrapper SetCameraDistance;
210 const Ember::ConsoleCommandWrapper ToggleRendermode;
211 const Ember::ConsoleCommandWrapper ToggleFullscreen;
212 const Ember::ConsoleCommandWrapper Screenshot;
213 const Ember::ConsoleCommandWrapper Record;
/**
Toggles between wireframe and solid render mode.
*/
218 void toggleRenderMode( );
/**
* takes a screen shot and writes it to disk
*/
223 void takeScreenshot( );
protected:
typedef std::deque<IWorldPickListener*> WorldPickListenersStore;
228 WorldPickListenersStore mPickListeners;
typedef std::vector<std::string> CompositorNameStore;
232 Recorder mRecorder;
234 CompositorNameStore mLoadedCompositors;
Mode mMode;
238 bool mIsAttached;
/**
If true, the camera is inverted in the y axis.
*/
243 bool mInvertCamera;
/**
Creates the rays needed for mouse picking and camera adjustment.
*/
248 void createRayQueries( );
/**
* creates all nodes needed for the camera
*/
254 void createNodesForCamera( );
256 const std::string _takeScreenshot( );
258 void createViewPort( );
259 GUIManager* mGUIManager;
262 Ogre::Camera* mCamera;
263 Ogre::SceneNode* mAvatarNode;
264 Ogre::SceneManager* mSceneManager;
//Ogre::Quaternion mLastOrientationOfTheCamera;
267 Ogre::SceneNode* mAvatarCameraRootNode;
268 Ogre::SceneNode* mAvatarCameraPitchNode;
269 Ogre::SceneNode* mAvatarCameraNode;
271 Ogre::Degree mDegreeOfPitchPerSecond;
272 Ogre::Degree mDegreeOfYawPerSecond;
274 Ogre::Degree degreePitch;
275 Ogre::Degree degreeYaw;
276 Ogre::RenderWindow* mWindow;
277 Ogre::Viewport* mViewPort;
//in meters how far we can pick objects
280 Ogre::Real mClosestPickingDistance;
282 Ogre::Vector3 mLastPosition;
283 Ogre::Real mWantedCameraDistance, mCurrentCameraDistance;
285 Ogre::RaySceneQuery *mAdjustTerrainRaySceneQuery, *mCameraRaySceneQuery;
286 Ogre::Ray mAdjustTerrainRay;
288 bool mIsAdjustedToTerrain;
290 void Input_MouseMoved( const MouseMotion& motion, Input::InputMode mode );
292 void ConfigService_EventChangedConfigItem( const std::string& section, const std::string& key );
294 void updateValuesFromConfig( );
/**
* Internal method for setting the camera distance.
* @param distance the new distance
*/
300 void _setCameraDistance( Ogre::Real distance );
};
///inline implementations
307 const Ogre::Degree& AvatarCamera::getPitch( ) const
{
return degreePitch;
}
312 const Ogre::Degree& AvatarCamera::getYaw( ) const
{
return degreeYaw;
}
317 Ogre::Camera* AvatarCamera::getCamera( ) {
return mCamera;
}
320 Ogre::Camera* AvatarCamera::getCamera( ) const {
return mCamera;
}
326 class ICameraMount
{
328 virtual ~ICameraMount( ) {};
/**
* Pitches the camera the supplied degrees
*/
333 virtual void pitch( Ogre::Degree degrees ) = 0;
/**
* Yaws the camera the supplied degrees
*/
338 virtual void yaw( Ogre::Degree degrees ) = 0;
/**
* returns the current degrees of pitch from the cameras initial position
*/
343 virtual const Ogre::Degree& getPitch( ) const = 0;
/**
* returns the current degrees of yaw from the cameras initial position
*/
348 virtual const Ogre::Degree& getYaw( ) const = 0;
/**
* Returns the current camera orientation in the world
*/
353 virtual const Ogre::Quaternion& getOrientation( bool onlyHorizontal = true ) const = 0;
/**
* Returns the position of the camera in the world.
* @return
*/
359 virtual const Ogre::Vector3& getPosition( ) const = 0;
361 void setMode( AvatarCamera::Mode mode );
/**
* sets the node to which the camera is attached
*/
366 virtual void setAvatarNode( Ogre::SceneNode* sceneNode );
};
370 class MainCamera
{
372 virtual ~MainCamera( ) {}
/**
* returns a pointer to the Ogre::Camera instance
*/
377 inline Ogre::Camera* getCamera( );
378 inline Ogre::Camera* getCamera( ) const;
/**
* emitted when the camra moves
*/
383 sigc::signal<void, Ogre::Camera*> MovedCamera;
386 void pickInWorld( Ogre::Real mouseX, Ogre::Real mouseY, const MousePickerArgs& args );
388 void setClosestPickingDistance( Ogre::Real distance );
389 Ogre::Real getClosestPickingDistance( );
/**
* returns true if the worldPos is on screen, putting the screen pos into the x & y of the second Vector3
* returns false if the worldPos is off screen
* @param worldPos
* @param screenPos
* @return
*/
398 bool worldToScreen( const Ogre::Vector3& worldPos, Ogre::Vector3& screenPos );
/**
* Reimplements the ConsoleObject::runCommand method
* @param command
* @param args
*/
405 virtual void runCommand( const std::string &command, const std::string &args );
/**
* Methods from Ogre::FrameListener
*/
410 bool frameStarted( const Ogre::FrameEvent& event );
/**
* Enables and disables a compositor by name.
* @param compositorName
* @param enable
*/
417 void enableCompositor( const std::string& compositorName, bool enable );
/**
* Adds a new world pick listener to the queue of listeners.
* @param worldPickListener
*/
424 void pushWorldPickListener( IWorldPickListener* worldPickListener );
426 const Ember::ConsoleCommandWrapper ToggleRendermode;
427 const Ember::ConsoleCommandWrapper ToggleFullscreen;
428 const Ember::ConsoleCommandWrapper Screenshot;
429 const Ember::ConsoleCommandWrapper Record;
/**
Toggles between wireframe and solid render mode.
*/
434 void toggleRenderMode( );
/**
* takes a screen shot and writes it to disk
*/
439 void takeScreenshot( );
};
443 class AvatarCameraMount : ICameraMount
{
/**
* emitted when the distance between the camera and the avatar has changed
* @param Ogre::Real the new distance
*/
449 sigc::signal<void, Ogre::Real> EventChangedCameraDistance;
/**
* Sets the distance from the camera to the avatar.
* @param distance the new distance
*/
455 void setCameraDistance( Ogre::Real distance );
457 const Ember::ConsoleCommandWrapper SetCameraDistance;
};
461 class FreeFlyingMount : ICameraMount
{
};
}
#endif // AVATARCAMERA_H
/*
Copyright ( C ) 2004 Erik Hjortsberg
some parts Copyright ( C ) 2004 bad_camel at Ogre3d forums
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "AvatarController.h"
#include "EmberEntity.h"
#include "EmberPhysicalEntity.h"
#include "AvatarEmberEntity.h"
#include "AvatarCamera.h"
#include "GUIManager.h"
#include "Avatar.h"
#include "EmberOgre.h"
// #include "SceneManagers/EmberPagingSceneManager/include/EmberPagingSceneManager.h"
#include "terrain/TerrainGenerator.h"
#include "terrain/ISceneManagerAdapter.h"
#include "input/Input.h"
#include "framework/Tokeniser.h"
#include "MathConverter.h"
#include "services/EmberServices.h"
#include "services/server/ServerService.h"
using namespace Ogre;
namespace EmberOgre {
AvatarControllerMovement::AvatarControllerMovement( ) :
rotationDegHoriz( 0 ),
rotationDegVert( 0 ),
timeSlice( 0 ),
movementDirection( Ogre::Vector3::ZERO ),
mode( AvatarMovementMode::MM_WALK ),
isMoving( false )
{
}
61 AvatarControllerInputListener::AvatarControllerInputListener( AvatarController& controller )
: mController( controller )
{
Input::getSingleton( ).EventMouseButtonPressed.connect( sigc::mem_fun( *this, &AvatarControllerInputListener::input_MouseButtonPressed ) );
Input::getSingleton( ).EventMouseButtonReleased.connect( sigc::mem_fun( *this, &AvatarControllerInputListener::input_MouseButtonReleased ) );
}
69 void AvatarControllerInputListener::input_MouseButtonPressed( Input::MouseButton button, Input::InputMode mode )
{
if ( mode == Input::IM_MOVEMENT && button == Input::MouseButtonLeft ) {
mController.mMovementDirection.x = 1;
}
}
76 void AvatarControllerInputListener::input_MouseButtonReleased( Input::MouseButton button, Input::InputMode mode )
{
if ( mode == Input::IM_MOVEMENT && button == Input::MouseButtonLeft ) {
mController.mMovementDirection.x = 0;
}
}
83 AvatarController::AvatarController( Avatar* avatar, Ogre::RenderWindow* window, GUIManager* guiManager, Ogre::Camera* camera )
: RunToggle( "+run", this, "Toggle running mode." )
85 , ToggleCameraAttached( "toggle_cameraattached", this, "Toggle between the camera being attached to the avatar and free flying." )
, CharacterMoveForward( "+character_move_forward", this, "Move the avatar forward." )
, CharacterMoveBackward( "+character_move_backward", this, "Move the avatar backward." )
, CharacterMoveDownwards( "+character_move_downwards", this, "Move the avatar downwards." )
, CharacterMoveUpwards( "+character_move_upwards", this, "Move the avatar upwards." )
, CharacterStrafeLeft( "+character_strafe_left", this, "Strafe left." )
, CharacterStrafeRight( "+character_strafe_right", this, "Strafe right." )
/*, CharacterRotateLeft( "+character_rotate_left", this, "Rotate left." )
, CharacterRotateRight( "+character_rotate_right", this, "Rotate right." )*/
, MoveCameraTo( "movecamerato", this, "Moves the camera to a point." )
, mMovementCommandMapper( "movement", "key_bindings_movement" )
, mWindow( window )
, mGUIManager( guiManager )
, mAvatarCamera( 0 )
, mCamera( camera )
, mEntityUnderCursor( 0 )
, mSelectedEntity( 0 )
, mFreeFlyingCameraNode( 0 )
, mIsRunning( false )
, mMovementDirection( Ogre::Vector3::ZERO )
, mDecalObject( 0 )
, mDecalNode( 0 )
, mControllerInputListener( *this )
{
mMovementCommandMapper.restrictToInputMode( Input::IM_MOVEMENT );
setAvatar( avatar );
mAvatar->setAvatarController( this );
Ogre::Root::getSingleton( ).addFrameListener( this );
mFreeFlyingCameraNode = EmberOgre::getSingleton( ).getSceneManager( )->getRootSceneNode( )->createChildSceneNode( );
mFreeFlyingCameraNode->setPosition( 0, 30, 0 );
detachCamera( );
mMovementCommandMapper.bindToInput( Input::getSingleton( ) );
GUIManager::getSingleton( ).getEntityPickListener( )->EventPickedEntity.connect( sigc::mem_fun( *this, &AvatarController::entityPicker_PickedEntity ) );
}
130 AvatarController::~AvatarController( )
{
Ogre::Root::getSingleton( ).removeFrameListener( this );
delete mAvatarCamera;
}
136 void AvatarController::createAvatarCameras( Ogre::SceneNode* avatarSceneNode )
{
if ( mAvatarCamera == 0 ) {
mAvatarCamera = new AvatarCamera( avatarSceneNode, EmberOgre::getSingletonPtr( )->getSceneManager( ), mWindow, mGUIManager, mCamera );
} else {
attachCamera( );
}
}
145 void AvatarController::setAvatar( Avatar* avatar )
{
mAvatar = avatar;
createAvatarCameras( avatar->getAvatarSceneNode( ) );
attachCamera( );
}
154 void AvatarController::runCommand( const std::string &command, const std::string &args )
{
if ( RunToggle == command ) {
mIsRunning = true;
} else if ( RunToggle.getInverseCommand( ) == command ) {
mIsRunning = false;
} else if ( ToggleCameraAttached == command )
{
if ( mIsAttached ) {
detachCamera( );
} else {
attachCamera( );
}
} else if ( CharacterMoveForward == command ) {
mMovementDirection.x = 1;
} else if ( CharacterMoveForward.getInverseCommand( ) == command ) {
mMovementDirection.x = 0;
} else if ( CharacterMoveBackward == command ) {
mMovementDirection.x = -1;
} else if ( CharacterMoveBackward.getInverseCommand( ) == command ) {
mMovementDirection.x = 0;
} else if ( CharacterStrafeLeft == command ) {
mMovementDirection.z = -1;
} else if ( CharacterStrafeLeft.getInverseCommand( ) == command ) {
mMovementDirection.z = 0;
} else if ( CharacterStrafeRight == command ) {
mMovementDirection.z = 1;
} else if ( CharacterStrafeRight.getInverseCommand( ) == command ) {
mMovementDirection.z = 0;
} else if ( CharacterMoveUpwards == command ) {
mMovementDirection.y = 1;
} else if ( CharacterMoveUpwards.getInverseCommand( ) == command ) {
mMovementDirection.y = 0;
} else if ( CharacterMoveDownwards == command ) {
mMovementDirection.y = -1;
} else if ( CharacterMoveDownwards.getInverseCommand( ) == command ) {
mMovementDirection.y = 0;
/* } else if ( CharacterRotateLeft == command ) {
mAvatarCamera->yaw( Ogre::Degree( -15 ) );
} else if ( CharacterRotateRight == command ) {
mAvatarCamera->yaw( Ogre::Degree( 15 ) );*/
} else if ( MoveCameraTo == command ) {
if ( !mIsAttached ) {
Ember::Tokeniser tokeniser;
tokeniser.initTokens( args );
std::string x = tokeniser.nextToken( );
std::string y = tokeniser.nextToken( );
std::string z = tokeniser.nextToken( );
if ( x == "" || y == "" || z == "" ) {
return;
} else {
Ogre::Vector3 position( Ogre::StringConverter::parseReal( x ), Ogre::StringConverter::parseReal( y ), Ogre::StringConverter::parseReal( z ) );
mFreeFlyingCameraNode->setPosition( position );
}
}
}
}
214 void AvatarController::detachCamera( )
{
mIsAttached = false;
mAvatarCamera->attach( mFreeFlyingCameraNode );
//mAvatarCamera->setMode( AvatarCamera::MODE_FIRST_PERSON );
}
222 void AvatarController::attachCamera( )
{
mIsAttached = true;
mAvatarCamera->attach( mAvatar->getAvatarSceneNode( ) );
//mAvatarCamera->setMode( AvatarCamera::MODE_FIRST_PERSON );
}
230 bool AvatarController::frameStarted( const Ogre::FrameEvent& event )
{
if ( mDecalObject )
{
///hide the decal when we're close to it
if ( mDecalNode->getWorldPosition( ).distance( mAvatar->getAvatarSceneNode( )->getWorldPosition( ) ) < 1 ) {
mDecalNode->setVisible( false );
}
}
// if ( mDecalObject ) {
// Ogre::Real newSize = mPulsatingController->calculate( event.timeSinceLastFrame );
// //mDecalNode->setScale( Ogre::Vector3( newSize, 1.0f, newSize ) );
// // mDecalNode->yaw( Ogre::Radian( 0.1f ) );
// }
// EmberPagingSceneManager* mScnMgr = static_cast<EmberPagingSceneManager*>( EmberOgre::getSingleton( ).getSceneManager( ) );
// if ( mGUIManager->getInput( )->isKeyDown( SDLK_F4 ) ) {
// /* Real change;
// mScnMgr->getOption( "MaxPixelError", &change );
// change -= 0.5f;
// mScnMgr->setOption( "MaxPixelError", &change ); */
// --Ogre::PagingLandScapeOptions::getSingleton( ).maxPixelError;
// Ogre::PagingLandScapeOptions::getSingleton( ).calculateCFactor( );
// mScnMgr->WorldDimensionChange( );
// }
// if ( mGUIManager->getInput( )->isKeyDown( SDLK_F5 ) ) {
// /* Real change;
// mScnMgr->getOption( "MaxPixelError", &change );
// change += 0.5f;
// mScnMgr->setOption( "MaxPixelError", &change ); */
// ++Ogre::PagingLandScapeOptions::getSingleton( ).maxPixelError;
// Ogre::PagingLandScapeOptions::getSingleton( ).calculateCFactor( );
// mScnMgr->WorldDimensionChange( );
// }
//
movementForFrame = AvatarControllerMovement( );
/* if ( mMovementDirection != Ogre::Vector3::ZERO ) {*/
movementForFrame.mode = mIsRunning ? AvatarMovementMode::MM_RUN : AvatarMovementMode::MM_WALK;
movementForFrame.isMoving = true;
movementForFrame.movementDirection = mMovementDirection;
movementForFrame.timeSlice = event.timeSinceLastFrame;
if ( movementForFrame.mode != mPreviousMovementForFrame.mode ) {
EventMovementModeChanged.emit( movementForFrame.mode );
}
// } else {
// }
// if ( mGUIManager->isInMovementKeysMode( ) ) {
// movementForFrame.movementDirection = Ogre::Vector3::ZERO;
// movementForFrame.mIsRunning = false;
// movementForFrame.isMoving = false;
/* checkMovementKeys( event, EmberOgre::getSingleton( ).getInput( ) );
movementForFrame.timeSlice = event.timeSinceLastFrame;
} */
if ( mIsAttached ) {
// mAvatarCamera->adjustForTerrain( );
mAvatar->updateFrame( movementForFrame );
} else {
Ogre::Real scaler = 50;
//make this inverse, so that when the run key is pressed, the free flying camera goes slower
//this is since we assume that one wants to go fast when in free flying mode
if ( movementForFrame.mode == AvatarMovementMode::MM_RUN ) {
scaler = 10;
}
Ogre::Vector3 correctDirection( movementForFrame.movementDirection.z, movementForFrame.movementDirection.y, -movementForFrame.movementDirection.x );
mFreeFlyingCameraNode->translate( mAvatarCamera->getOrientation( false ) * ( correctDirection * movementForFrame.timeSlice * scaler ) );
}
mPreviousMovementForFrame = movementForFrame;
return true;
}
314 const AvatarControllerMovement & AvatarController::getCurrentMovement( ) const
{
return movementForFrame;
}
320 AvatarCamera* AvatarController::getAvatarCamera( ) const
{
return mAvatarCamera;
}
325 void AvatarController::entityPicker_PickedEntity( const EntityPickResult& result, const MousePickerArgs& args )
{
///don't do this now that we have a "move to" option in the menu, since it will confuse the users
/* if ( args.pickType == MPT_DOUBLECLICK ) {
moveToPoint( result.position );
}*/
}
333 void AvatarController::moveToPoint( const Ogre::Vector3& point )
{
if ( !mDecalNode ) {
createDecal( point );
}
if ( mDecalNode ) {
///make sure it's at the correct height, since the visibility of it is determined by the bounding box
Ogre::Real height = EmberOgre::getSingleton( ).getTerrainGenerator( )->getAdapter( )->getHeightAt( point.x, point.z );
mDecalNode->setPosition( Ogre::Vector3( point.x, height, point.z ) );
mDecalNode->setVisible( true );
}
WFMath::Vector<3> atlasVector = Ogre2Atlas_Vector3( point );
WFMath::Point<3> atlasPos( atlasVector.x( ), atlasVector.y( ), atlasVector.z( ) );
/* WFMath::Point<3> atlas2dPos( atlasVector.x( ), atlasVector.y( ), 0 );
WFMath::Point<3> avatar2dPos( mAvatar->getAvatarEmberEntity( )->getPosition( ).x( ), mAvatar->getAvatarEmberEntity( )->getPosition( ).y( ), 0 );
WFMath::Vector<3> direction( 1, 0, 0 );
direction = direction.rotate( mAvatar->getAvatarEmberEntity( )->getOrientation( ) );
WFMath::Vector<3> directionToPoint = atlas2dPos - avatar2dPos;
WFMath::Quaternion rotation;
rotation = rotation.rotation( directionToPoint, direction );*/
//Ember::EmberServices::getSingletonPtr( )->getServerService( )->moveInDirection( WFMath::Vector<3>( 0, 0, 0 ), rotation );
Ember::EmberServices::getSingletonPtr( )->getServerService( )->moveToPoint( atlasPos );
}
362 void AvatarController::teleportTo( const Ogre::Vector3& point, EmberEntity* locationEntity )
{
WFMath::Vector<3> atlasVector = Ogre2Atlas_Vector3( point );
WFMath::Point<3> atlasPos( atlasVector.x( ), atlasVector.y( ), atlasVector.z( ) );
Ember::EmberServices::getSingletonPtr( )->getServerService( )->place( mAvatar->getAvatarEmberEntity( ), locationEntity, atlasPos );
}
372 void AvatarController::createDecal( Ogre::Vector3 position )
{
try {
// Create object MeshDecal
Ogre::SceneManager* sceneManager = EmberOgre::getSingleton( ).getSceneManager( );
Ogre::NameValuePairList params;
params["materialName"] = "/global/ember/terraindecal";
params["width"] = StringConverter::toString( 2 );
params["height"] = StringConverter::toString( 2 );
params["sceneMgrInstance"] = sceneManager->getName( );
mDecalObject = sceneManager->createMovableObject(
"AvatarControllerMoveToDecal",
"PagingLandScapeMeshDecal",
¶ms );
// Add MeshDecal to Scene
mDecalNode = sceneManager->createSceneNode( "AvatarControllerMoveToDecalNode" );
///the decal code is a little shaky and relies on us setting the position of the node before we add the moveable object
EmberOgre::getSingleton( ).getWorldSceneNode( )->addChild( mDecalNode );
mDecalNode->setPosition( position );
mDecalNode->attachObject( mDecalObject );
// mDecalNode->showBoundingBox( true );
mPulsatingController = new Ogre::WaveformControllerFunction( Ogre::WFT_SINE, 1, 0.33, 0.25 );
} catch ( const Ogre::Exception& ex )
{
S_LOG_WARNING( "Error when creating terrain decal: " << ex.what( ) );
}
}
}
1 /*
Copyright ( C ) 2004 Erik Hjortsberg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef AVATARCONTROLLER_H
#define AVATARCONTROLLER_H
#include "EmberOgrePrerequisites.h"
// #include <SDL.h>
#include <sigc++/trackable.h>
#include "input/Input.h"
#include "input/InputCommandMapper.h"
#include "framework/ConsoleObject.h"
#include "EntityWorldPickListener.h"
namespace EmberOgre {
36 class Avatar;
37 class EmberEntity;
38 class AvatarCamera;
40 class GUIManager;
42 class InputManager;
43 class Input;
44 class AvatarController;
/**
The movement mode of the avatar, run or walk.
*/
49 class AvatarMovementMode {
public:
enum Mode
{
MM_WALK = 0,
MM_RUN = 1
};
};
/**
Used for sending the current desired movement to the actual avatar.
*/
struct AvatarControllerMovement
{
AvatarControllerMovement( );
float rotationDegHoriz;
float rotationDegVert;
Ogre::Real timeSlice;
Ogre::Vector3 movementDirection;
AvatarMovementMode::Mode mode;
bool isMoving;
Ogre::Quaternion cameraOrientation;
};
/**
Listens for left mouse button pressed in movement mode and moves the character forward.
*/
78 class AvatarControllerInputListener
{
public:
81 AvatarControllerInputListener( AvatarController& controller );
protected:
85 void input_MouseButtonPressed( Input::MouseButton button, Input::InputMode mode );
86 void input_MouseButtonReleased( Input::MouseButton button, Input::InputMode mode );
87 AvatarController& mController;
};
/**
Controls the avatar. All avatar movement is handled by an instance of this class.
*/
93 class AvatarController
94 : public Ogre::FrameListener,
95 public sigc::trackable,
96 public Ember::ConsoleObject
{
public:
99 friend class AvatarControllerInputListener;
101 AvatarController( Avatar* avatar, Ogre::RenderWindow* window, GUIManager* guiManager, Ogre::Camera* camera );
103 virtual ~AvatarController( );
/**
Each frame we check if we should update the avatar.
*/
108 virtual bool frameStarted( const Ogre::FrameEvent & event );
/**
Emitted when the movement mode changes between run and walk.
*/
114 sigc::signal<void, AvatarMovementMode::Mode> EventMovementModeChanged;
118 void createAvatarCameras( Ogre::SceneNode* avatarSceneNode );
/**
* Gets the AvatarCamera.
* @return
*/
124 AvatarCamera* getAvatarCamera( ) const;
/**
* Detaches the camera from the avatar and attaches it to the free flying node.
*/
129 void detachCamera( );
/**
* Attaches the camera to the avatar.
*/
134 void attachCamera( );
/**
* Gets the current movement for this frame.
* @return
*/
140 const AvatarControllerMovement& getCurrentMovement( ) const;
142 const Ember::ConsoleCommandWrapper RunToggle;
143 const Ember::ConsoleCommandWrapper ToggleCameraAttached;
145 const Ember::ConsoleCommandWrapper CharacterMoveForward;
146 const Ember::ConsoleCommandWrapper CharacterMoveBackward;
147 const Ember::ConsoleCommandWrapper CharacterMoveDownwards;
148 const Ember::ConsoleCommandWrapper CharacterMoveUpwards;
149 const Ember::ConsoleCommandWrapper CharacterStrafeLeft;
150 const Ember::ConsoleCommandWrapper CharacterStrafeRight;
/* const Ember::ConsoleCommandWrapper CharacterRotateLeft;
const Ember::ConsoleCommandWrapper CharacterRotateRight;*/
154 const Ember::ConsoleCommandWrapper MoveCameraTo;
/**
* Reimplements the ConsoleObject::runCommand method
* @param command
* @param args
*/
162 virtual void runCommand( const std::string &command, const std::string &args );
/**
Moves the avatar to the specified point.
A terrain decal will be shown.
*/
168 void moveToPoint( const Ogre::Vector3& point );
/**
* Teleports the avatar to the specified point.
* @param point
* @param locationEntity
*/
175 void teleportTo( const Ogre::Vector3& point, EmberEntity* locationEntity );
protected:
179 InputCommandMapper mMovementCommandMapper;
181 Ogre::RenderWindow* mWindow;
183 GUIManager* mGUIManager;
// void checkMovementKeys( const Ogre::FrameEvent & event, const Input& input );
189 AvatarCamera* mAvatarCamera;
190 void setAvatar( Avatar* avatar );
191 Ogre::Camera* mCamera;
/**
* Avatar
*/
197 Avatar* mAvatar;
199 EmberEntity* mEntityUnderCursor;
200 EmberEntity* mSelectedEntity;
AvatarControllerMovement movementForFrame, mPreviousMovementForFrame;
204 Ogre::SceneNode* mFreeFlyingCameraNode;
205 bool mIsAttached;
/**
True if we're in running mode.
*/
209 bool mIsRunning;
211 Ogre::Vector3 mMovementDirection;
/**
Listen for double clicks and send the avatar to the double clicked position.
*/
216 void entityPicker_PickedEntity( const EntityPickResult& result, const MousePickerArgs& args );
/**
Creates the terrain decal needed for displaying where the avatar is heading.
*/
221 void createDecal( Ogre::Vector3 position );
223 Ogre::MovableObject* mDecalObject;
224 Ogre::SceneNode* mDecalNode;
225 Ogre::WaveformControllerFunction* mPulsatingController;
227 AvatarControllerInputListener mControllerInputListener;
};
}
#endif // AvatarController_H
/*
Copyright ( C ) 2004 Erik Hjortsberg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "EmberEntity.h"
#include "EmberPhysicalEntity.h"
// #include "PersonEmberEntity.h"
#include "framework/ConsoleBackend.h"
#include "Avatar.h"
#include "GUIManager.h"
#include "model/Model.h"
#include "AvatarEmberEntity.h"
#include "EmberOgre.h"
#include "MousePicker.h"
#include <Eris/Entity.h>
#include <Eris/Avatar.h>
#include <OgreTagPoint.h>
namespace EmberOgre {
38 AvatarEmberEntity::AvatarEmberEntity( const std::string& id, Eris::TypeInfo* type, Eris::View* vw, Ogre::SceneManager* sceneManager, Eris::Avatar* erisAvatar ) : EmberPhysicalEntity( id, type, vw, sceneManager ), SetAttachedOrientation( "setattachedorientation", this, "Sets the orienation of an item attached to the avatar: <attachpointname> <x> <y> <z> <degrees>" ),
39 mAvatar( 0 ), mErisAvatar( erisAvatar )
{
}
43 AvatarEmberEntity::~AvatarEmberEntity( )
{}
47 void AvatarEmberEntity::runCommand( const std::string &command, const std::string &args )
{
if( SetAttachedOrientation == command ) {
Ember::Tokeniser tokeniser;
tokeniser.initTokens( args );
std::string attachPointName = tokeniser.nextToken( );
if ( attachPointName != "" ) {
std::string x = tokeniser.nextToken( );
std::string y = tokeniser.nextToken( );
std::string z = tokeniser.nextToken( );
std::string degrees = tokeniser.nextToken( );
if ( x != "" && y != "" && z != "" && degrees != "" ) {
Ogre::Degree ogreDegrees( Ogre::StringConverter::parseReal( degrees ) );
Ogre::Quaternion rotation( ogreDegrees, Ogre::Vector3( Ogre::StringConverter::parseReal( x ), Ogre::StringConverter::parseReal( y ), Ogre::StringConverter::parseReal( z ) ) );
if ( getModel( ) ) {
const Model::Model::AttachPointWrapperStore* attachPoints = getModel( )->getAttachedPoints( );
if ( attachPoints ) {
for ( Model::Model::AttachPointWrapperStore::const_iterator I = attachPoints->begin( ); I != attachPoints->end( ); ++I ) {
if ( I->AttachPointName == attachPointName ) {
I->TagPoint->setOrientation( rotation );
}
}
}
}
}
}
}
}
76 void AvatarEmberEntity::init( const Atlas::Objects::Entity::RootEntity &ge, bool fromCreateOp )
{
EmberPhysicalEntity::init( ge, fromCreateOp );
mModel->setQueryFlags( MousePicker::CM_AVATAR );
}
84 void AvatarEmberEntity::onMoved( )
{
//EmberPhysicalEntity::onMoved( );
if ( getAvatar( ) ) {
getAvatar( )->movedInWorld( );
}
Eris::Entity::onMoved( );
}
94 void AvatarEmberEntity::onImaginary( const Atlas::Objects::Root& act )
{
Atlas::Message::Element attr;
if ( act->copyAttr( "description", attr ) != 0 || !attr.isString( ) ) {
return;
}
/// Make the message appear in the chat box
GUIManager::getSingleton( ).AppendAvatarImaginary.emit( getName( ) + " " + attr.String( ) );
}
/*
void AvatarEmberEntity::handleTalk( const std::string &msg )
{
std::string message = "<";
message.append( getName( ) );
message.append( "> " );
message.append( msg );
GUIManager::getSingleton( ).AppendIGChatLine.emit( message );
std::cout << "TRACE - AVATAR SAYS: [" << message << "]\n" << std::endl;
Ember::ConsoleBackend::getMainConsole( )->pushMessage( message );
}
*/
/*
void AvatarEmberEntity::setVisible( bool vis )
{
//TODO
//mOgreEntity->setVisible( true );
}
*/
//void AvatarEmberEntity::addMember( Entity *e )
126 void AvatarEmberEntity::onChildAdded( Entity *e )
{
//mAvatar->EventAddedEntityToInventory.emit( static_cast<EmberEntity*>( e ) );
EmberOgre::getSingleton( ).getAvatar( )->mEntitiesToBeAddedToInventory.insert( e );
//PersonEmberEntity::addMember( e );
EmberPhysicalEntity::onChildAdded( e );
}
/*void AvatarEmberEntity::rmvMember( Entity *e )*/
137 void AvatarEmberEntity::onChildRemoved( Entity *e )
{
EmberOgre::getSingleton( ).getAvatar( )->EventRemovedEntityFromInventory.emit( static_cast<EmberEntity*>( e ) );
EmberPhysicalEntity::onChildRemoved( e );
// mAvatar->mEntitiesToBeRemovedFromInventory.insert( e );
// PersonEmberEntity::rmvMember( e );
}
// void AvatarEmberEntity::onLocationChanged( Eris::Entity *oldLocation, Eris::Entity *newLocation )
// {
// return EmberEntity::onLocationChanged( oldLocation, newLocation );
//
//
//
// Ogre::Vector3 oldWorldPosition = getSceneNode( )->getWorldPosition( );
// EmberEntity* EmberEntity = dynamic_cast<EmberEntity*>( newLocation );
// Ogre::SceneNode* newOgreParentNode = EmberEntity->getSceneNode( );
//
// /* if ( EmberEntity )
// {
// newOgreParentNode = EmberEntity->getSceneNode( );
// } else {
// newOgreParentNode = EmberOgre::getSingleton( ).getSceneManager( )->getSceneNode( newLocation->getId( ) );
// }*/
//
// if ( getSceneNode( )->getParent( ) ) {
// //detach from our current object and add to the new entity
// getSceneNode( )->getParent( )->removeChild( getSceneNode( )->getName( ) );
// }
// newOgreParentNode->addChild( getSceneNode( ) );
//
//
// // Entity::setContainer( pr );
// Eris::Entity::onLocationChanged( oldLocation, newLocation );
//
// //we adjust the entity so it retains it's former position in the world
// Ogre::Vector3 newWorldPosition = getSceneNode( )->getWorldPosition( );
// getSceneNode( )->translate( oldWorldPosition - newWorldPosition );
// }
179 Ogre::SceneNode* AvatarEmberEntity::getAvatarSceneNode( )
{
return getScaleNode( );
}
}
1 /*
Copyright ( C ) 2004 Erik Hjortsberg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef AVATARDIMEENTITY_H
#define AVATARDIMEENTITY_H
namespace Eris
{
25 class Entity;
26 class Avatar;
}
namespace EmberOgre {
namespace Model {
32 class Model;
}
class EmberPhysicalEntity;
36 class EmberEntity;
37 class Avatar;
/**
* This is the main player avatar. We want this one to behave a little different
* than the other game entities, thus it has it's own subclass.
*
*/
44 class AvatarEmberEntity
45 : public EmberPhysicalEntity,
46 public Ember::ConsoleObject
{
public:
50 AvatarEmberEntity( const std::string& id, Eris::TypeInfo* type, Eris::View* vw, Ogre::SceneManager* sceneManager, Eris::Avatar* erisAvatar );
51 virtual ~AvatarEmberEntity( );
/**
* used by the main application to set the EmberOgre::Avatar connected to this instance
*/
56 inline void setAvatar( Avatar* avatar );
57 inline Avatar* getAvatar( );
/**
* returns the Ogre::SceneNode which represents the avatar
*/
62 Ogre::SceneNode* getAvatarSceneNode( );
/**
* Returns the Eris Avatar instance.
* @return
*/
68 inline Eris::Avatar* getErisAvatar( );
/**
* Reimplements the ConsoleObject::runCommand method
* @param command
* @param args
*/
75 virtual void runCommand( const std::string &command, const std::string &args );
77 const Ember::ConsoleCommandWrapper SetAttachedOrientation;
protected:
81 virtual void onChildAdded( Entity *e );
82 virtual void onChildRemoved( Entity *e );
/**Eris methods, see Eris::Entity.h for documentation */
// virtual void handleTalk( const std::string &msg );
86 virtual void onMoved( );
87 virtual void onImaginary( const Atlas::Objects::Root& act );
/* virtual void addMember( Entity *e );
virtual void rmvMember( Entity *e );*/
//virtual void setVisible( bool vis );
//virtual void setContainer( Eris::Entity *pr );
//virtual void onLocationChanged( Eris::Entity *oldLocation, Eris::Entity *newLocation );
93 virtual void init( const Atlas::Objects::Entity::RootEntity &ge, bool fromCreateOp );
96 Avatar* mAvatar;
97 Eris::Avatar* mErisAvatar;
};
///inline implementations
101 void AvatarEmberEntity::setAvatar( Avatar* avatar )
{
mAvatar = avatar;
}
105 Avatar* AvatarEmberEntity::getAvatar( )
{
return mAvatar;
}
109 Eris::Avatar* AvatarEmberEntity::getErisAvatar( )
{
return mErisAvatar;
}
}
#endif // AVATARDIMEENTITY_H
1 //
// C++ Implementation: CameraMount
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "CameraMount.h"
namespace EmberOgre {
27 CameraMount::CameraMount( )
{
}
32 CameraMount::~CameraMount( )
{
}
}
1 //
// C++ Interface: CameraMount
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGRECAMERAMOUNT_H
#define EMBEROGRECAMERAMOUNT_H
namespace EmberOgre {
/**
@author Erik Hjortsberg
*/
31 class CameraMount{
public:
33 CameraMount( );
35 ~CameraMount( );
};
}
#endif
/*
ConsoleObjectImpl.cpp by Miguel Guzman ( Aglanor )
Copyright ( C ) 2002 Miguel Guzman & The Worldforge Project
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
// config headers
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
// system headers
// library headers
#include "EmberOgrePrerequisites.h"
// local headers
#include "ConsoleObjectImpl.h"
#include "framework/ConsoleBackend.h"
#include "framework/Tokeniser.h"
#include "main/Application.h"
// #include <SDL.h>
template<> EmberOgre::ConsoleObjectImpl* Ember::Singleton<EmberOgre::ConsoleObjectImpl>::ms_Singleton = 0;
namespace EmberOgre {
43 ConsoleObjectImpl::ConsoleObjectImpl( void ) :
Quit( "quit", this, "Quit Ember." ),
45 ToggleErisPolling( "toggle_erispolling", this, "Switch server polling on and off." )
{
}
48 ConsoleObjectImpl::~ConsoleObjectImpl( )
{
}
54 void ConsoleObjectImpl::runCommand( const std::string &command, const std::string &args )
{
if( command == Quit.getCommand( ) ) {
Ember::ConsoleBackend::getMainConsole( )->pushMessage( "Bye" );
quit( );
} else if ( ToggleErisPolling == command ){
Ember::Application::getSingleton( ).setErisPolling( !Ember::Application::getSingleton( ).getErisPolling( ) );
}
}
64 void ConsoleObjectImpl::quit( )
{
Ember::Application::getSingleton( ).quit( );
}
}
1 /*
ConsoleObjectImpl.h by Miguel Guzman ( Aglanor )
Copyright ( C ) 2002 Miguel Guzman & The Worldforge Project
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __EmberOgre_ConsoleObjectImpl_H__
#define __EmberOgre_ConsoleObjectImpl_H__
#include "framework/ConsoleObject.h"
#include "framework/Singleton.h"
namespace EmberOgre {
27 class ConsoleObjectImpl: public Ember::ConsoleObject, public Ember::Singleton<ConsoleObjectImpl>
{
public:
31 ConsoleObjectImpl( void );
32 ~ConsoleObjectImpl( );
/**
* Receive commands from console
*/
37 void runCommand( const std::string &command, const std::string &args );
private:
43 void quit( );
/// List of Ogre's console commands
46 const Ember::ConsoleCommandWrapper Quit;
47 const Ember::ConsoleCommandWrapper ToggleErisPolling;
}; // End of class declaration
}
#endif
1 /*
Copyright ( C ) 2004 Erik Hjortsberg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "EmberEntity.h"
#include "framework/Service.h"
#include "framework/ConsoleBackend.h"
#include "services/EmberServices.h"
#include "services/sound/SoundService.h"
#include "EmberEntityFactory.h"
#include "MotionManager.h"
#include "GUIManager.h"
#include "terrain/TerrainArea.h"
#include "MathConverter.h"
#include "EmberOgre.h"
#include <OgreWireBoundingBox.h>
#include <OgreException.h>
#include <Mercator/Area.h>
//#include <Atlas/Objects/ObjectsFwd.h>
#include <Eris/TypeInfo.h>
#include <Eris/View.h>
#include <Atlas/Formatter.h>
#include <Atlas/Objects/Decoder.h>
#include <Atlas/Codecs/XML.h>
#include <Atlas/Message/MEncoder.h>
#include <Atlas/Message/QueuedDecoder.h>
#include "model/Model.h"
using namespace Ogre;
namespace Ogre {
/**
This is just like a WireBoundBox but not aligned to the axes, hence it will correctly line up according to it's orientation.
*/
56 class OOBBWireBoundingBox : public WireBoundingBox
{
public:
60 void getWorldTransforms( Matrix4* xform ) const
{
SimpleRenderable::getWorldTransforms( xform );
}
//-----------------------------------------------------------------------
65 const Quaternion& getWorldOrientation( void ) const
{
return SimpleRenderable::getWorldOrientation( );
}
//-----------------------------------------------------------------------
70 const Vector3& getWorldPosition( void ) const
{
return SimpleRenderable::getWorldPosition( );
}
};
};
namespace EmberOgre {
95 const std::string EmberEntity::MODE_STANDING( "standing" );
96 const std::string EmberEntity::MODE_RUNNING( "running" );
97 const std::string EmberEntity::MODE_WALKING( "walking" );
98 const std::string EmberEntity::MODE_SWIMMING( "swimming" );
99 const std::string EmberEntity::MODE_FLOATING( "floating" );
100 const std::string EmberEntity::MODE_FIXED( "fixed" );
102 const std::string EmberEntity::BboxMaterialName( "BaseYellowNoLightning" );
105 EmberEntity::EmberEntity( const std::string& id, Eris::TypeInfo* ty, Eris::View* vw, Ogre::SceneManager* sceneManager )
:
Eris::Entity( id, ty, vw )
, mIsInitialized( false )
, mIsInMotionManager( false )
, mErisEntityBoundingBox( 0 )
, mOgreNode( 0 )
, mTerrainArea( 0 )
{
createSceneNode( sceneManager );
}
117 EmberEntity::~EmberEntity( )
{
//detach all children so we don't destroy them
while ( getSceneNode( )->numChildren( ) ) {
getSceneNode( )->removeChild( ( short unsigned int )0 );
}
Ogre::SceneNode* parent = static_cast<Ogre::SceneNode*>( getSceneNode( )->getParent( ) );
if ( parent ) {
parent->removeAndDestroyChild( getSceneNode( )->getName( ) );
} else {
getSceneNode( )->getCreator( )->destroySceneNode( getSceneNode( )->getName( ) );
}
///make sure it's not in the MotionManager
///TODO: keep a marker in the entity so we don't need to call this for all entities
MotionManager::getSingleton( ).removeEntity( this );
if ( mErisEntityBoundingBox ) {
mErisEntityBoundingBox->getParentSceneNode( )->getCreator( )->destroySceneNode( mErisEntityBoundingBox->getParentSceneNode( )->getName( ) );
}
delete mErisEntityBoundingBox;
//mSceneManager->destroySceneNode( getSceneNode( )->getName( ) );
}
141 void EmberEntity::init( const Atlas::Objects::Entity::RootEntity &ge, bool fromCreateOp )
{
Eris::Entity::init( ge, fromCreateOp );
synchronizeWithServer( );
// set the Ogre node position and orientation based on Atlas data
std::stringstream ss;
ss << "Entity " << getId( ) << "( " << getName( ) << " ) placed at ( " << getPredictedPos( ).x( ) << ", " << getPredictedPos( ).y( ) << ", " << getPredictedPos( ).x( ) << " )";
S_LOG_VERBOSE( ss.str( ) );
if ( hasAttr( "area" ) ) {
mTerrainArea = std::auto_ptr<Terrain::TerrainArea>( new Terrain::TerrainArea( this ) );
if ( mTerrainArea->init( ) ) {
addArea( mTerrainArea.get( ) );
}
}
mIsInitialized = true;
}
163 void EmberEntity::synchronizeWithServer( )
{
if ( getPosition( ).isValid( ) ) {
getSceneNode( )->setPosition( Atlas2Ogre( getPredictedPos( ) ) );
adjustPosition( );
}
if ( getOrientation( ).isValid( ) ) {
getSceneNode( )->setOrientation( Atlas2Ogre( getOrientation( ) ) );
}
}
176 void EmberEntity::createSceneNode( Ogre::SceneManager* sceneManager )
{
EmberEntity* container = getEmberLocation( );
if ( container == 0 ) {
//S_LOG_VERBOSE( "Entity created in limbo: "<< this->getId( ) << " ( " << this->getName( ) << " )" )
mOgreNode = sceneManager->createSceneNode( getId( ) );
} else {
Ogre::SceneNode * node = container->getSceneNode( );
mOgreNode = node->createChildSceneNode( getId( ) );
}
}
190 void EmberEntity::updateMotion( Ogre::Real timeSlice )
{
getSceneNode( )->setPosition( Atlas2Ogre( getPredictedPos( ) ) );
adjustPosition( );
//if there's a debug bounding box for the eris entity, update it's position
if ( mErisEntityBoundingBox ) {
mErisEntityBoundingBox->getParentSceneNode( )->setPosition( getSceneNode( )->getPosition( ) );
mErisEntityBoundingBox->getParentSceneNode( )->setOrientation( getSceneNode( )->getOrientation( ) );
}
}
206 void EmberEntity::onMoved( )
{
Eris::Entity::onMoved( );
const WFMath::Quaternion& orient = getOrientation( );
getSceneNode( )->setOrientation( Atlas2Ogre( orient ) );
updateMotion( 0 );
}
214 void EmberEntity::setMoving( bool moving )
{
// Call the overridden method
Eris::Entity::setMoving( moving );
MotionManager* motionManager = &MotionManager::getSingleton( );
if ( moving ) {
//the entity is moving
if ( !mIsInMotionManager ) {
motionManager->addEntity( this );
mIsInMotionManager = true;
}
} else {
//the entity has stopped moving
if ( mIsInMotionManager ) {
motionManager->removeEntity( this );
mIsInMotionManager = false;
}
}
}
238 void EmberEntity::onTalk( const Atlas::Objects::Operation::RootOperation& talkArgs )
{
const std::vector<Atlas::Objects::Root>& args = talkArgs->getArgs( );
if ( args.empty( ) ) {
Eris::Entity::onTalk( talkArgs );
return;
}
const Atlas::Objects::Root& talk = args.front( );
if ( !talk->hasAttr( "say" ) ) {
Eris::Entity::onTalk( talkArgs );
return;
}
///some talk operations come with a predefined set of suitable responses, so we'll store those so that they can later on be queried by the GUI for example
mSuggestedResponses.clear( );
if ( talk->hasAttr( "responses" ) ) {
if ( talk->getAttr( "responses" ).isList( ) ) {
const Atlas::Message::ListType & responseList = talk->getAttr( "responses" ).asList( );
Atlas::Message::ListType::const_iterator I = responseList.begin( );
for( ; I != responseList.end( ); ++I ) {
mSuggestedResponses.push_back( I->asString( ) );
}
}
}
const std::string& msg = talk->getAttr( "say" ).asString( );
std::string message = "<";
message.append( getName( ) );
message.append( ", " );
const std::string& type = getType( )->getName( ); // Eris type as a string
message.append( type );
message.append( "> " );
message.append( msg );
S_LOG_VERBOSE( "Entity says: [" << message << "]\n" )
/// Make the message appear in the chat box
GUIManager::getSingleton( ).AppendIGChatLine.emit( msg, this );
/// Make a sound in OpenAL
// Ember::EmberServices::getSingleton( ).getSoundService( )->playTalk( msg,
// getPosition( ), getOrientation( ) );
/// Call the method of the base class ( since we've overloaded it )
Eris::Entity::onTalk( talkArgs );
}
294 void EmberEntity::onSoundAction( const Atlas::Objects::Operation::RootOperation & op )
{
Eris::Entity::onSoundAction( op );
}
300 void EmberEntity::onVisibilityChanged( bool vis )
{
checkVisibility( vis );
Eris::Entity::onVisibilityChanged( vis );
}
306 void EmberEntity::checkVisibility( bool vis )
{
///since we don't want to show all entities solely by their server flags ( for example, an inventory item belonging to a character might not be shown even though the server thinks it's visible ) we have to some more checks before we decide whether to show this or not
EmberEntity* container = static_cast<EmberEntity*>( getLocation( ) );
if ( container ) {
///check with the parent first if we should show ourselves
if ( vis && container->allowVisibilityOfMember( this ) ) {
///don't cascade, only change the top node
setVisible( true );
} else {
setVisible( false );
}
} else {
setVisible( vis );
}
}
325 void EmberEntity::setVisible( bool visible )
{
///when entities are hidden, we detach them from the rendering scene graph altogether. this speeds up Ogre since it doesn't have to calculate visibility for nodes that are hidden anyway
if ( !visible ) {
if ( getSceneNode( )->getParent( ) ) {
getSceneNode( )->getParent( )->removeChild( getSceneNode( ) );
}
} else {
if ( getLocation( ) ) {
if ( !getSceneNode( )->getParent( ) ) {
getEmberLocation( )->getSceneNode( )->addChild( getSceneNode( ) );
}
}
}
getSceneNode( )->setVisible( visible && getLocation( ), false );
}
344 void EmberEntity::adjustPosition( )
{
if ( getPredictedPos( ).isValid( ) ) {
adjustPosition( Atlas2Ogre( getPredictedPos( ) ) );
}
}
351 void EmberEntity::adjustPosition( const Ogre::Vector3& position )
{
if ( mMovementMode == MM_FIXED ) {
} else {
EmberEntity* container = getEmberLocation( );
if ( container ) {
container->adjustPositionForContainedNode( this, position );
}
}
}
363 const Ogre::Vector3& EmberEntity::getOffsetForContainedNode( const Ogre::Vector3& localPosition, EmberEntity* const entity )
{
///send it upwards until we get a an entity which knows how to set the position ( we'll in most cases end up in the world which will adjust the height a bit )
EmberEntity* container = getEmberLocation( );
if ( container ) {
//TerrainPosition derivedPosition( getPredictedPos( ).x( ) + position.x( ), getPredictedPos( ).y( ) + position.y( ) );
return container->getOffsetForContainedNode( localPosition + getSceneNode( )->getPosition( ), entity );
} else {
return Ogre::Vector3::ZERO;
}
}
379 void EmberEntity::adjustPositionForContainedNode( EmberEntity* const entity, const Ogre::Vector3& position )
{
Ogre::SceneNode* sceneNode = entity->getSceneNode( );
//Ogre::Vector3 position = sceneNode->getPosition( );
const Ogre::Vector3& offset = getOffsetForContainedNode( position, entity );
if ( offset != Ogre::Vector3::ZERO ) {
sceneNode->setPosition( position + offset );
}
}
391 void EmberEntity::onLocationChanged( Eris::Entity *oldLocation )
{
if ( getLocation( ) == oldLocation )
{
S_LOG_WARNING( "Same new location as old for entity: " << this->getId( ) << " ( " << this->getName( ) << " )" );
return Eris::Entity::onLocationChanged( oldLocation );
}
Eris::Entity::onLocationChanged( oldLocation );
///if we're attached to something, detach from it
detachFromModel( );
if ( !getLocation( ) ) {
return;
} else {
EmberEntity* newLocationEntity = getEmberLocation( );
const Ogre::Vector3 oldWorldPosition = getSceneNode( )->getWorldPosition( );
// const Ogre::Quaternion oldWorldOrientation = getSceneNode( )->getWorldOrientation( );
if ( getSceneNode( )->getParentSceneNode( ) ) {
///detach from our current object
getSceneNode( )->getParentSceneNode( )->removeChild( getSceneNode( )->getName( ) );
}
if ( newLocationEntity ) {
// add to the new entity
newLocationEntity->getSceneNode( )->addChild( getSceneNode( ) );
S_LOG_VERBOSE( "Entity: " << this->getId( ) << " ( " << this->getName( ) << " ) relocated to: "<< newLocationEntity->getId( ) << " ( " << newLocationEntity->getName( ) << " )" );
if ( getPosition( ).isValid( ) ) {
///note that in some instances, for instance when the avatar enters the sty, the position isn't updated yet, which will make the avatar "snap" to an incorrect position ( since the parent node has changed ) until next frame, when the position should have been updated
getSceneNode( )->setPosition( Atlas2Ogre( getPredictedPos( ) ) );
adjustPosition( );
std::stringstream ss;
ss << getPredictedPos( );
S_LOG_VERBOSE( "New position for entity: " << this->getId( ) << " ( " << this->getName( ) << " ) :" << ss.str( ) );
}
if ( getOrientation( ).isValid( ) ) {
getSceneNode( )->setOrientation( Atlas2Ogre( getOrientation( ) ) );
std::stringstream ss;
ss << getOrientation( );
S_LOG_VERBOSE( "New orientation for entity: " << this->getId( ) << " ( " << this->getName( ) << " ) :" << ss.str( ) );
}
// getSceneNode( )->rotate( newLocationEntity->getSceneNode( )->getWorldOrientation( ) - oldWorldOrientation );
} else {
///the entity has no current parent, and should be placed in limbo ( hopefully a more correct parent will be submitted in a future LocationChanged event
S_LOG_VERBOSE( "Entity relocated to limbo: "<< this->getId( ) << " ( " << this->getName( ) << " )" );
// mSceneManager->getRootSceneNode( )->addChild( getSceneNode( ) );
}
checkVisibility( isVisible( ) );
///we'll adjust the entity so it retains it's former position in the world, but only for moving entities
///since else we'll get a "gap" when we're waiting on updated positions from the server
///this isn't optimal
if ( isMoving( ) ) {
const Ogre::Vector3& newWorldPosition = getSceneNode( )->getWorldPosition( );
getSceneNode( )->translate( oldWorldPosition - newWorldPosition );
}
}
}
456 void EmberEntity::onAction( const Atlas::Objects::Operation::RootOperation& act )
{
const std::list<std::string> &p = act->getParents( );
std::list<std::string>::const_iterator I = p.begin( );
if ( I == p.end( ) ) return;
const std::string& name = *I;
std::string message = getName( ) + " performs a " + name + ".";
Ember::ConsoleBackend::getMainConsole( )->pushMessage( message );
S_LOG_VERBOSE( "Entity: " << this->getId( ) << " ( " << this->getName( ) << " ) action: " << name );
Entity::onAction( act );
}
472 void EmberEntity::onImaginary( const Atlas::Objects::Root& act )
{
Atlas::Message::Element attr;
if ( act->copyAttr( "description", attr ) && attr.isString( ) ) {
std::string message = getName( ) + " " + attr.asString( ) + ".";
Ember::ConsoleBackend::getMainConsole( )->pushMessage( message );
S_LOG_VERBOSE( "Entity: " << this->getId( ) << " ( " << this->getName( ) << " ) imaginary: " << attr.String( ) );
}
Entity::onImaginary( act );
}
488 bool EmberEntity::allowVisibilityOfMember( EmberEntity* entity ) {
return true;
}
492 const std::vector< std::string >& EmberEntity::getSuggestedResponses( ) const
{
return mSuggestedResponses;
}
497 bool EmberEntity::hasSuggestedResponses( ) const
{
return mSuggestedResponses.size( ) > 0;
}
503 void EmberEntity::addArea( Terrain::TerrainArea* area )
{
///just pass it on to the parent until we get to someone who knows how to handle this ( preferrably the terrain )
if ( getEmberLocation( ) ) {
getEmberLocation( )->addArea( area );
}
}
511 void EmberEntity::onAttrChanged( const std::string& str, const Atlas::Message::Element& v )
{
if ( str == "mode" ) {
parseModeChange( v );
} else if ( str == "bbox" ) {
Entity::onAttrChanged( str, v );
onBboxChanged( );
return;
}
Entity::onAttrChanged( str, v );
}
523 void EmberEntity::parseModeChange( const Atlas::Message::Element& v )
{
const std::string& mode = v.asString( );
MovementMode newMode;
if ( mode.empty( ) ) {
newMode = MM_DEFAULT;
} else if ( mode == MODE_STANDING ) {
newMode = MM_STANDING;
} else if ( mode == MODE_RUNNING ) {
newMode = MM_RUNNING;
} else if ( mode == MODE_WALKING ) {
newMode = MM_WALKING;
} else if ( mode == MODE_SWIMMING ) {
newMode = MM_SWIMMING;
} else if ( mode == MODE_FLOATING ) {
newMode = MM_FLOATING;
} else if ( mode == MODE_FIXED ) {
newMode = MM_FIXED;
} else {
newMode = MM_DEFAULT;
}
onModeChanged( newMode );
}
548 void EmberEntity::onModeChanged( MovementMode newMode )
{
if ( newMode == MM_FIXED ) {
adjustPosition( );
}
mMovementMode = newMode;
}
556 void EmberEntity::setVisualize( const std::string& visualization, bool visualize )
{
if ( visualization == "OgreBBox" ) {
showOgreBoundingBox( visualize );
} else if ( visualization == "ErisBBox" ) {
showErisBoundingBox( visualize );
}
}
565 bool EmberEntity::getVisualize( const std::string& visualization ) const
{
if ( visualization == "OgreBBox" ) {
return getShowOgreBoundingBox( );
} else if ( visualization == "ErisBBox" ) {
return getShowErisBoundingBox( );
}
return false;
}
576 void EmberEntity::showOgreBoundingBox( bool show )
{
getSceneNode( )->showBoundingBox( show );
}
581 void EmberEntity::showErisBoundingBox( bool show )
{
createErisBboxMaterial( );
///if there's no bounding box, create one now
///allowing for some lazy loading
if ( !mErisEntityBoundingBox ) {
mErisEntityBoundingBox = new Ogre::OOBBWireBoundingBox( );
mErisEntityBoundingBox->setMaterial( BboxMaterialName );
Ogre::SceneNode* boundingBoxNode = EmberOgre::getSingleton( ).getWorldSceneNode( )->createChildSceneNode( );
boundingBoxNode->attachObject( mErisEntityBoundingBox );
Ogre::AxisAlignedBox aabb( Atlas2Ogre( getBBox( ) ) );
mErisEntityBoundingBox->setupBoundingBox( aabb );
boundingBoxNode->setPosition( Atlas2Ogre( getPredictedPos( ) ) );
boundingBoxNode->setOrientation( Atlas2Ogre( getOrientation( ) ) );
}
mErisEntityBoundingBox->setVisible( show );
}
605 void EmberEntity::createErisBboxMaterial( )
{
if ( !Ogre::MaterialManager::getSingleton( ).resourceExists( BboxMaterialName ) ) {
Ogre::MaterialPtr baseYellowNoLighting = Ogre::MaterialManager::getSingleton( ).create( BboxMaterialName,
Ogre::ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME );
baseYellowNoLighting->setLightingEnabled( false );
baseYellowNoLighting->setAmbient( Ogre::ColourValue( 1, 1, 0.7 ) );
baseYellowNoLighting->setDiffuse( Ogre::ColourValue( 1, 1, 0.7 ) );
}
}
616 void EmberEntity::onBboxChanged( )
{
if ( mErisEntityBoundingBox ) {
mErisEntityBoundingBox->setupBoundingBox( Atlas2Ogre( getBBox( ) ) );
}
}
624 bool EmberEntity::getShowOgreBoundingBox( ) const
{
return getSceneNode( )->getShowBoundingBox( );
}
628 bool EmberEntity::getShowErisBoundingBox( ) const
{
return ( mErisEntityBoundingBox && mErisEntityBoundingBox->isVisible( ) );
}
//inline
635 Ogre::SceneNode* EmberEntity::getSceneNode( ) const
{
return mOgreNode;
}
640 EmberEntity* EmberEntity::getEmberLocation( ) const
{
return static_cast<EmberEntity*>( getLocation( ) );
}
646 const Ogre::AxisAlignedBox& EmberEntity::getWorldBoundingBox( bool derive ) const
{
static Ogre::AxisAlignedBox boundingBox( 0, 0, 0, 0, 0, 0 );
return boundingBox;
}
652 const Ogre::Sphere & EmberEntity::getWorldBoundingSphere ( bool derive ) const
{
static Ogre::Sphere sphere;
return sphere;
}
658 std::vector<std::string> EmberEntity::getDefaultUseOperators( )
{
///get the use operations from Eris and return them a simple vector of strings
std::vector<std::string> operators;
Eris::TypeInfoArray types = getUseOperations( );
for ( Eris::TypeInfoArray::iterator I = types.begin( ); I != types.end( ); ++I ) {
operators.push_back( ( *I )->getName( ) );
}
return operators;
}
672 Ogre::SceneManager* EmberEntity::getSceneManager( )
{
assert( mOgreNode );
return mOgreNode->getCreator( );
}
678 static void dumpElement( const std::string &prefix, const std::string &name, const Atlas::Message::Element &e, std::ostream& outstream, std::ostream& logOutstream )
{
if ( e.isMap( ) ) {
logOutstream << prefix << name << ": Dumping Map" << std::endl;
Atlas::Message::MapType::const_iterator itr = e.asMap( ).begin( );
Atlas::Message::MapType::const_iterator end = e.asMap( ).end( );
outstream << prefix << name << ":" << std::endl;
for ( ; itr != end; ++itr ) {
dumpElement( prefix + " ", itr->first, itr->second, outstream, logOutstream );
}
logOutstream << prefix << "Finished Dumping Map" << std::endl;
} else if ( e.isList( ) ) {
logOutstream << prefix << name << ": Dumping List" << std::endl;
Atlas::Message::ListType::const_iterator itr = e.asList( ).begin( );
Atlas::Message::ListType::const_iterator end = e.asList( ).end( );
outstream << prefix << name << ":" << std::endl;
for ( ; itr != end; ++itr ) {
dumpElement( prefix + " ", "", *itr, outstream, logOutstream );
}
logOutstream << prefix << "Finished Dumping List" << std::endl;
} else {
if ( e.isString( ) ) outstream << prefix << name << ": " << e.asString( ) << std::endl;
if ( e.isNum( ) ) outstream << prefix << name << ": " << e.asNum( ) << std::endl;
}
}
705 void EmberEntity::dumpAttributes( std::iostream& outstream, std::ostream& logOutstream ) const
{
logOutstream << "Dumping attributes for entity " << getId( ) << "( " << getName( ) << " )" << std::endl;
Atlas::Message::QueuedDecoder decoder;
//std::fstream file;
Atlas::Codecs::XML codec( outstream, decoder );
Atlas::Formatter formatter( outstream, codec );
Atlas::Message::Encoder encoder( formatter );
formatter.streamBegin( );
encoder.streamMessageElement( getAttributes( ) );
formatter.streamEnd( );
// const Eris::Entity::AttrMap &attribs = getAttributes( );
// Eris::Entity::AttrMap::const_iterator itr = attribs.begin( );
// Eris::Entity::AttrMap::const_iterator end = attribs.end( );
// for ( ; itr != end; ++itr ) {
// dumpElement( "", itr->first, itr->second, outstream, logOutstream );
// }
}
}
1 /*
Copyright ( C ) 2004 Erik Hjortsberg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef DIMEENTITY_H
#define DIMEENTITY_H
#include "EmberOgrePrerequisites.h"
#include <Atlas/Objects/Entity.h>
#include <Atlas/Objects/Operation.h>
#include <Eris/Entity.h>
namespace Ogre
{
32 class OOBBWireBoundingBox;
}
namespace Mercator
{
37 class Area;
}
40 namespace Eris
{
class View;
}
namespace EmberOgre {
namespace Model {
48 class Model;
}
51 namespace Terrain
{
class TerrainArea;
}
56 class EmberEntityFactory;
/**
* A representation of an Eris::Entity, ie. a world entity.
* Note that most entities in the game world will be of type EmberPhysicalEntity
* as they will have some sort of physical representation.
* For things such as boundaries and weather, this is a nice class.
*/
63 class EmberEntity : public Eris::Entity {
64 friend class EmberEntityFactory;
public:
enum MovementMode
{
MM_DEFAULT = 0,
MM_STANDING = 1,
MM_FLOATING = 2,
MM_PROJECTILE = 3,
MM_SWIMMING = 4,
MM_WALKING = 5,
MM_RUNNING = 6,
MM_FIXED = 7
};
80 static const std::string MODE_STANDING;
81 static const std::string MODE_RUNNING;
82 static const std::string MODE_WALKING;
83 static const std::string MODE_SWIMMING;
84 static const std::string MODE_FLOATING;
85 static const std::string MODE_FIXED;
/**
The material used for showing the eris bbox.
*/
90 static const std::string BboxMaterialName;
94 EmberEntity( const std::string& id, Eris::TypeInfo* ty, Eris::View* vw, Ogre::SceneManager* sceneManager );
95 virtual ~EmberEntity( );
/**
* Called by contained entites to determine how they should be adjusted, for example snap to the ground.
* For instance a house entitiy containing a player entity.
* This should of course be extended to a more dynamic physics simulation
* in the future
*/
104 virtual void adjustPositionForContainedNode( EmberEntity* const entity, const Ogre::Vector3& position );
/**
* Adjust the height of the entity so that it "snaps" to the ground.
* This is most often done by making a call to the containing node's
* adjustPositionForContainedNode method.
*/
112 virtual void adjustPosition( );
113 virtual void adjustPosition( const Ogre::Vector3& position );
/**
* return the scenenode to which this entity belongs
*/
118 Ogre::SceneNode* getSceneNode( ) const;
/**
* Called by a contained member to see if the member is allowed to be shown.
* This can be reimplemented in a subclass such as AvatarEmberEntity to
* disallow things that belongs to a characters inventory to be shown.
*/
125 virtual bool allowVisibilityOfMember( EmberEntity* entity );
/**
*return true if the entity has a list of suggested responses
*/
131 bool hasSuggestedResponses( ) const;
/**
* returns a list of all suggested responses
*/
136 const std::vector< std::string >& getSuggestedResponses( ) const;
/**
* Sets the visibity of the Entity
* @param visible
*/
143 virtual void setVisible( bool visible );
/**
* gets the location as cast to an EmberEntity
* @return
*/
150 EmberEntity* getEmberLocation( ) const;
/**
attaches the entity to another entity ( or in reality another Model )
*/
155 virtual void attachToPointOnModel( const std::string& point, Model::Model* model ) {};
/**
detaches the entity from another entity ( or in reality another Model )
*/
160 virtual void detachFromModel( ) {};
/**
if this is true, init( ... ) has been called and the entity been set up
*/
165 inline bool isInitialized( ) const;
/**
the mode the entity is in, like walking, running, swimming etc.
*/
170 inline MovementMode getMovementMode( ) const;
/**
Call this method once per frame to update the motion of the entity
*/
175 virtual void updateMotion( Ogre::Real timeSlice );
/**
For debugging.
Shows the Ogre bounding box.
*/
181 virtual void showOgreBoundingBox( bool show );
/**
For debugging.
Shows the eris/atlas bounding box.
@see mErisEntityBoundingBox
*/
189 virtual void showErisBoundingBox( bool show );
/**
returns whether the ogre bounding box is shown
*/
194 virtual bool getShowOgreBoundingBox( ) const;
/**
returns whether the eris/atlas bounding box is shown
@see mErisEntityBoundingBox
*/
200 virtual bool getShowErisBoundingBox( ) const;
/**
* returns the world bounding box of the entity
* @param derive whether to derive from attached objects too
* @return
*/
207 virtual const Ogre::AxisAlignedBox& getWorldBoundingBox( bool derive = true ) const;
210 virtual const Ogre::Sphere & getWorldBoundingSphere ( bool derive=true ) const;
/**
* Returns a list of the default use operators that can be used with this entity.
For example, an axe would have a list of operators such as "chop" and "sharpen".
* @return
*/
217 std::vector<std::string> getDefaultUseOperators( );
/**
* Synchronizes the position and orientation of the entity with the server.
*/
223 void synchronizeWithServer( );
/**
Dumps all of this entity's attributes to the supplied outstream.
*/
229 void dumpAttributes( std::iostream& outstream, std::ostream& logOutstream ) const;
/**
* General method for turning on and off debug visualizations. Subclasses might support more types of visualizations than the ones defined here.
* @param visualization The type of visualization. Currently supports "OgreBBox" and "ErisBBox".
* @param visualize Whether to visualize or not.
*/
236 virtual void setVisualize( const std::string& visualization, bool visualize );
/**
* Gets whether a certain visualization is turned on or off.
* @param visualization The type of visualization. Currently supports "OgreBBox" and "ErisBBox".
* @return true if visualization is turned on, else false
*/
244 virtual bool getVisualize( const std::string& visualization ) const;
protected:
/**
* Gets the position of a contained node.
* @param position
* @param entity
* @return
*/
255 virtual const Ogre::Vector3& getOffsetForContainedNode( const Ogre::Vector3& position, EmberEntity* const entity );
/**
if this is true, init( ... ) has been called and the entity been set up
*/
261 bool mIsInitialized;
/**
if true, the entity is already registered with the motion manager, so we don't need to add it again ( which can be expensive since
the motionmanager holds all entities needing updated motions in a std::set )
*/
267 bool mIsInMotionManager;
/**
* Overridden from Eris::Entity
* @see Eris::Entity
*/
273 virtual void onMoved( );
274 virtual void setMoving( bool moving );
275 virtual void onTalk( const Atlas::Objects::Operation::RootOperation& talk );
// virtual void setContainer( Entity *pr );
277 virtual void onVisibilityChanged( bool vis );
278 virtual void onLocationChanged( Eris::Entity *oldLocation );
279 virtual void onAction( const Atlas::Objects::Operation::RootOperation& act );
280 virtual void onImaginary( const Atlas::Objects::Root& act );
281 virtual void onSoundAction( const Atlas::Objects::Operation::RootOperation& op );
283 virtual void addArea( Terrain::TerrainArea* area );
284 virtual void onAttrChanged( const std::string& str, const Atlas::Message::Element& v );
287 virtual void onModeChanged( MovementMode newMode );
/**
* Called when the bounding box has changed.
*/
292 virtual void onBboxChanged( );
/**
For debugging purposes. This holds a bounding box of how the entity appears in the eris/atlas world.
This is often different from the Ogre bounding box.
*/
299 Ogre::OOBBWireBoundingBox* mErisEntityBoundingBox;
/**
* Creates the material used for the eris bboxes, if not already created.
*/
304 void createErisBboxMaterial( );
/**
* Creates the main scene node which holds the entity.
*/
311 void createSceneNode( Ogre::SceneManager* sceneManager );
/**
override from eris
this is called by eris just after the entity has been put into the world
*/
317 virtual void init( const Atlas::Objects::Entity::RootEntity &ge, bool fromCreateOp );
319 virtual void checkVisibility( bool vis );
/**
Sometimes when talking to an entity, the server will provide suggested responses. These are stored here.
*/
324 std::vector<std::string> mSuggestedResponses;
/**
* The main SceneNode which holds the entity in the ogre world space.
*/
329 Ogre::SceneNode* mOgreNode;
/**
Gets the scene manager that manages the Ogre scene node held by this.
*/
334 Ogre::SceneManager* getSceneManager( );
/**
If there's a terrainarea belonging to this entity, that's stored here.
*/
339 std::auto_ptr<Terrain::TerrainArea> mTerrainArea;
/**
the mode the entity is in, like walking, running, swimming etc.
*/
MovementMode mMovementMode;
/**
* parses the current mode from the submitted element, which should be taken from the "mode" attribute
* this method will in turn call onModeChanged if the mode is changed
* @param v
*/
353 void parseModeChange( const Atlas::Message::Element& v );
};
///inline implementations
359 bool EmberEntity::isInitialized( ) const
{
return mIsInitialized;
}
364 EmberEntity::MovementMode EmberEntity::getMovementMode( ) const
{
return mMovementMode;
}
}
#endif // DIMEENTITY_H
1 //
// C++ Implementation: EmberEntityActionCreator
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2007
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "EmberEntityActionCreator.h"
#include "EmberEntityModelAction.h"
#include "EmberEntityPartAction.h"
#include "model/mapping/Cases/CaseBase.h"
using namespace EmberOgre::Model::Mapping;
namespace EmberOgre {
32 EmberEntityActionCreator::EmberEntityActionCreator( EmberPhysicalEntity& entity )
: mEntity( entity )
{
}
38 EmberEntityActionCreator::~EmberEntityActionCreator( )
{
}
42 void EmberEntityActionCreator::createActions( ModelMapping& modelMapping, Cases::CaseBase* aCase, Definitions::CaseDefinition& caseDefinition )
{
Definitions::CaseDefinition::ActionStore::iterator endJ = caseDefinition.getActions( ).end( );
for ( Definitions::CaseDefinition::ActionStore::iterator J = caseDefinition.getActions( ).begin( ); J != endJ; ++J ) {
if ( J->getType( ) == "display-part" ) {
EmberEntityPartAction* action = new EmberEntityPartAction( mEntity, J->getValue( ) );
aCase->addAction( action );
} else if ( J->getType( ) == "display-model" ) {
EmberEntityModelAction* action = new EmberEntityModelAction( mEntity, J->getValue( ) );
aCase->addAction( action );
}
}
}
}
1 //
// C++ Interface: EmberEntityActionCreator
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2007
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGREEMBERENTITYACTIONCREATOR_H
#define EMBEROGREEMBERENTITYACTIONCREATOR_H
#include "EmberOgrePrerequisites.h"
#include "EmberPhysicalEntity.h"
#include "model/mapping/ModelMapping.h"
#include "model/mapping/Definitions/ModelMappingDefinition.h"
#include "model/mapping/ModelMappingManager.h"
#include "model/mapping/IActionCreator.h"
namespace EmberOgre {
/**
@author Erik Hjortsberg <erik@katastrof.nu>
*/
38 class EmberEntityActionCreator : public Model::Mapping::IActionCreator
{
public:
41 EmberEntityActionCreator( EmberPhysicalEntity& entity );
43 ~EmberEntityActionCreator( );
44 virtual void createActions( Model::Mapping::ModelMapping& modelMapping, Model::Mapping::Cases::CaseBase* aCase, Model::Mapping::Definitions::CaseDefinition& caseDefinition );
protected:
46 EmberPhysicalEntity& mEntity;
};
}
#endif
/*
Copyright ( C ) 2004 Erik Hjortsberg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "EmberEntityFactory.h"
#include <Eris/Entity.h>
#include <Eris/View.h>
#include <Eris/TypeInfo.h>
#include <Eris/Avatar.h>
#include "services/server/ServerService.h"
#include "services/EmberServices.h"
#include "EmberEntity.h"
#include "WorldEmberEntity.h"
#include "EmberPhysicalEntity.h"
#include "AvatarEmberEntity.h"
#include "EmberOgre.h"
#include "model/Model.h"
#include "model/ModelDefinition.h"
#include "model/ModelDefinitionManager.h"
#include "model/mapping/EmberModelMappingManager.h"
#include "framework/ConsoleBackend.h"
#include "terrain/TerrainGenerator.h"
#include "Avatar.h"
#include "services/EmberServices.h"
#include "services/config/ConfigService.h"
#include "framework/osdir.h"
#ifdef WIN32
#include <tchar.h>
#define snprintf _snprintf
#include <io.h> // for _access, Win32 version of stat( )
#include <direct.h> // for _mkdir
// #include <sys/stat.h>
#include <iostream>
#include <fstream>
#include <ostream>
#else
#include <dirent.h>
#endif
namespace EmberOgre {
74 EmberEntityFactory::EmberEntityFactory( Eris::View* view, Terrain::TerrainGenerator* terrainGenerator, Eris::TypeService* typeService )
: ShowModels( "showmodels", this, "Show or hide models." )
76 , DumpAttributes( "dump_attributes", this, "Dumps the attributes of a supplied entity to a file. If no entity id is supplied the current avatar will be used." )
, mTerrainGenerator( terrainGenerator )
, mTypeService( typeService )
, mTerrainType( 0 )
, mWorldEntity( 0 )
, mView( view )
{
mView->registerFactory( this );
mTerrainType = mTypeService->getTypeByName( "world" );
getErisAvatar( )->GotCharacterEntity.connect( sigc::mem_fun( *this, &EmberEntityFactory::gotAvatarCharacter ) );
}
93 EmberEntityFactory::~EmberEntityFactory( )
{
/// there is no way to deregister the factory from the View, instead the View will delete the factory when deleted
// mView->deregisterFactory( this );
}
/// create whatever entity the client desires
100 Eris::Entity* EmberEntityFactory::instantiate( const Atlas::Objects::Entity::RootEntity &ge, Eris::TypeInfo* type, Eris::View* w )
{
Eris::Entity* emberEntity( 0 );
bool isPhysical = Model::Mapping::EmberModelMappingManager::getSingleton( ).getManager( ).getDefinitionForType( type ) != 0;
if ( ge->getId( ) == getErisAvatar( )->getId( ) ) {
AvatarEmberEntity* avatarEntity = createAvatarEntity( ge, type, w );
emberEntity = avatarEntity;
} else if ( type->isA( mTerrainType ) ) {
emberEntity = createWorld( ge, type, w );
} else if ( !isPhysical ) {
S_LOG_VERBOSE( "Creating immaterial entity." );
///we don't want this to have any Ogre::Entity
emberEntity = new EmberEntity( ge->getId( ), type, w, EmberOgre::getSingleton( ).getSceneManager( ) );
} else {
emberEntity = createPhysicalEntity( ge, type, w );
}
S_LOG_VERBOSE( "Entity added to game view." );
return emberEntity;
}
132 bool EmberEntityFactory::accept( const Atlas::Objects::Entity::RootEntity &ge, Eris::TypeInfo* type )
{
return true;
}
138 Eris::Entity* EmberEntityFactory::createWorld( const Atlas::Objects::Entity::RootEntity & ge, Eris::TypeInfo* type, Eris::View *world ) {
assert( !mWorldEntity );
mWorldEntity = new WorldEmberEntity( ge->getId( ), type, world, EmberOgre::getSingleton( ).getSceneManager( ), mTerrainGenerator );
return mWorldEntity;
}
144 WorldEmberEntity* EmberEntityFactory::getWorld( ) const
{
return mWorldEntity;
}
149 void EmberEntityFactory::gotAvatarCharacter( Eris::Entity* entity )
{
AvatarEmberEntity* avatarEntity = static_cast<AvatarEmberEntity*>( entity );
EmberOgre::getSingleton( ).getAvatar( )->createdAvatarEmberEntity( avatarEntity );
EmberOgre::getSingleton( ).EventCreatedAvatarEntity.emit( avatarEntity );
}
161 EmberPhysicalEntity* EmberEntityFactory::createPhysicalEntity( const Atlas::Objects::Entity::RootEntity &ge, Eris::TypeInfo* type, Eris::View *world ) {
EmberPhysicalEntity* entity = new EmberPhysicalEntity( ge->getId( ), type, world, EmberOgre::getSingleton( ).getSceneManager( ) );
return entity;
}
169 AvatarEmberEntity* EmberEntityFactory::createAvatarEntity( const Atlas::Objects::Entity::RootEntity &ge, Eris::TypeInfo* type, Eris::View *world )
{
return new AvatarEmberEntity( ge->getId( ), type, world, EmberOgre::getSingleton( ).getSceneManager( ), getErisAvatar( ) );
}
174 int EmberEntityFactory::priority( ) {
return 10;
}
178 Eris::Avatar* EmberEntityFactory::getErisAvatar( )
{
return mView->getAvatar( );
}
183 void EmberEntityFactory::dumpAttributesOfEntity( const std::string& entityId ) const
{
EmberEntity* entity = EmberOgre::getSingleton( ).getEmberEntity( entityId );
if ( entity ) {
///make sure the directory exists
std::string dir( Ember::EmberServices::getSingletonPtr( )->getConfigService( )->getHomeDirectory( ) + "/entityexport/" );
if ( !oslink::directory( dir ).isExisting( ) ) {
S_LOG_INFO( "Creating directory " << dir );
#ifdef __WIN32__
mkdir( dir.c_str( ) );
#else
mkdir( dir.c_str( ), S_IRWXU );
#endif
}
const std::string fileName( dir + entityId + ".atlas" );
std::fstream exportFile( fileName.c_str( ), std::fstream::out );
S_LOG_INFO( "Dumping attributes to " << fileName );
entity->dumpAttributes( exportFile, std::cout );
Ember::ConsoleBackend::getMainConsole( )->pushMessage( std::string( "Dumped attributes to " ) + fileName );
}
}
209 void EmberEntityFactory::runCommand( const std::string &command, const std::string &args )
{
if( command == ShowModels.getCommand( ) )
{
Ember::Tokeniser tokeniser;
tokeniser.initTokens( args );
std::string value = tokeniser.nextToken( );
if ( value == "true" ) {
S_LOG_INFO( "Showing models." );
Model::ModelDefinitionManager::getSingleton( ).setShowModels( true );
} else if ( value == "false" ) {
S_LOG_INFO( "Hiding models." );
Model::ModelDefinitionManager::getSingleton( ).setShowModels( false );
}
} else if ( DumpAttributes == command ) {
Ember::Tokeniser tokeniser;
tokeniser.initTokens( args );
std::string value = tokeniser.nextToken( );
if ( value == "" ) {
if ( getErisAvatar( ) ) {
dumpAttributesOfEntity( getErisAvatar( )->getEntity( )->getId( ) );
}
} else {
dumpAttributesOfEntity( value );
}
}
}
}
1 /*
Copyright ( C ) 2004 Erik Hjortsberg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef DIMEENTITYFACTORY_H
#define DIMEENTITYFACTORY_H
#include "EmberOgrePrerequisites.h"
#include <Eris/Factory.h>
#include <Atlas/Objects/Entity.h>
#include <sigc++/trackable.h>
#include "framework/ConsoleObject.h"
namespace Eris
{
32 class Entity;
33 class View;
34 class TypeService;
35 class TypeInfo;
36 class Avatar;
}
namespace EmberOgre {
namespace Terrain
{
43 class TerrainGenerator;
}
class AvatarEmberEntity;
47 class EmberTerrainPageSource;
48 class EmberPhysicalEntity;
49 class EmberEntity;
50 class ViewEmberEntity;
51 class WorldEmberEntity;
/**
* Creates the EmberEntities required.
* Basically this attaches to Eris and creates Entites on demand.
* @see Eris::Factory
*
*/
59 class EmberEntityFactory :
60 public Eris::Factory,
61 public sigc::trackable,
62 public Ember::ConsoleObject
{
public:
typedef std::set<Ogre::String> StringSet;
/**
Default constructor. This should be instantiated by EmberOgre or similiar high level object. Note that Eris upon shutdown will delete all registered factories, so don't delete an instance of this yourself.
*/
72 EmberEntityFactory( Eris::View* view, Terrain::TerrainGenerator* terrainGenerator, Eris::TypeService* typeService );
73 virtual ~EmberEntityFactory( );
/**
Will always return true.
*/
78 virtual bool accept( const Atlas::Objects::Entity::RootEntity &ge, Eris::TypeInfo* type );
/**
Creates instances of EmberEntity and its subclasses.
*/
83 virtual Eris::Entity* instantiate( const Atlas::Objects::Entity::RootEntity &ge, Eris::TypeInfo* type, Eris::View* w );
/** retrieve this factory's priority level; higher priority factories
get first chance to process a recieved Atlas entity. The default implementation
returns one. */
88 virtual int priority( );
/**
Returns the main world entity.
*/
93 WorldEmberEntity* getWorld( ) const;
/**
* Reimplements the ConsoleObject::runCommand method
* @param command
* @param args
*/
100 virtual void runCommand( const std::string &command, const std::string &args );
/**
Command for setting whether models should be shown or not.
*/
106 const Ember::ConsoleCommandWrapper ShowModels;
/**
Dumps the attributes of a supplied entity to the std::out.
*/
111 const Ember::ConsoleCommandWrapper DumpAttributes;
/**
* Dumps the attributes of the entity with the supplied id to the std::out.
* @param entityId
* @return
*/
119 void dumpAttributesOfEntity( const std::string& entityId ) const;
protected:
/**
Creates a WorldEmberEntity instance.
*/
127 Eris::Entity* createWorld( const Atlas::Objects::Entity::RootEntity & ge, Eris::TypeInfo* type, Eris::View *world );
/**
Creates a EmberPhysicalEntity instance.
*/
131 EmberPhysicalEntity* createPhysicalEntity( const Atlas::Objects::Entity::RootEntity &ge, Eris::TypeInfo* type, Eris::View *world );
/**
Creates a AvatarEmberEntity instance.
*/
135 AvatarEmberEntity* createAvatarEntity( const Atlas::Objects::Entity::RootEntity &ge, Eris::TypeInfo* type, Eris::View *world );
137 void gotAvatarCharacter( Eris::Entity* entity );
141 Terrain::TerrainGenerator* mTerrainGenerator;
142 Eris::TypeService* mTypeService;
143 Eris::TypeInfo* mTerrainType;
145 Eris::Avatar* getErisAvatar( );
147 WorldEmberEntity *mWorldEntity;
149 Eris::View* mView;
};
}
#endif // DIMEENTITYFACTORY_H
1 //
// C++ Implementation: EmberEntityModelAction
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2007
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "EmberEntityModelAction.h"
namespace EmberOgre {
27 EmberEntityModelAction::EmberEntityModelAction( EmberPhysicalEntity& entity, std::string modelName )
: mEntity( entity ), mModelName( modelName )
{
}
33 EmberEntityModelAction::~EmberEntityModelAction( )
{
}
37 void EmberEntityModelAction::activate( )
{
mEntity.setModel( mModelName );
S_LOG_VERBOSE( "Showing model " << mModelName );
}
43 void EmberEntityModelAction::deactivate( )
{
mEntity.setModel( "" );
S_LOG_VERBOSE( "Hiding model " << mModelName );
}
}
1 //
// C++ Interface: EmberEntityModelAction
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2007
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGREEMBERENTITYMODELACTION_H
#define EMBEROGREEMBERENTITYMODELACTION_H
#include "EmberOgrePrerequisites.h"
#include "EmberPhysicalEntity.h"
// #include "model/mapping/ModelMapping.h"
#include "model/mapping/Actions/Action.h"
namespace EmberOgre {
/**
@author Erik Hjortsberg <erik@katastrof.nu>
*/
37 class EmberEntityModelAction : public Model::Mapping::Actions::Action
{
public:
40 EmberEntityModelAction( EmberPhysicalEntity& entity, std::string modelName );
41 ~EmberEntityModelAction( );
43 virtual void activate( );
44 virtual void deactivate( );
protected:
47 EmberPhysicalEntity& mEntity;
49 std::string mModelName;
};
}
#endif
1 //
// C++ Implementation: EmberEntityPartAction
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2007
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "EmberEntityPartAction.h"
#include "model/Model.h"
namespace EmberOgre {
32 EmberEntityPartAction::EmberEntityPartAction( EmberPhysicalEntity& entity, std::string partName )
: mEntity( entity ), mPartName( partName )
{
}
38 EmberEntityPartAction::~EmberEntityPartAction( )
{
}
42 void EmberEntityPartAction::activate( )
{
S_LOG_VERBOSE( "Showing part " << mPartName );
mEntity.showModelPart( mPartName );
// Model::Model* model = mEntity.getModel( );
// if ( model ) {
// model->showPart( mPartName );
//
// }
}
53 void EmberEntityPartAction::deactivate( )
{
S_LOG_VERBOSE( "Hiding part " << mPartName );
mEntity.hideModelPart( mPartName );
// Model::Model* model = mEntity.getModel( );
// if ( model ) {
// model->hidePart( mPartName, false );
// }
}
}
1 //
// C++ Interface: EmberEntityPartAction
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2007
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGREEMBERENTITYPARTACTION_H
#define EMBEROGREEMBERENTITYPARTACTION_H
#include "EmberOgrePrerequisites.h"
#include "EmberPhysicalEntity.h"
#include "model/mapping/ModelMapping.h"
#include "model/mapping/Actions/Action.h"
namespace EmberOgre {
/**
@author Erik Hjortsberg <erik@katastrof.nu>
*/
36 class EmberEntityPartAction : public Model::Mapping::Actions::Action
{
public:
39 EmberEntityPartAction( EmberPhysicalEntity& entity, std::string partName );
40 ~EmberEntityPartAction( );
42 virtual void activate( );
43 virtual void deactivate( );
protected:
46 EmberPhysicalEntity& mEntity;
48 std::string mPartName;
};
}
#endif
1 //
// C++ Implementation: EmberEntityUserObject
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2005
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "EmberEntityUserObject.h"
#include "ogreopcode/include/OgreCollisionObject.h"
#include "EmberEntity.h"
#include "model/Model.h"
namespace EmberOgre {
const Ogre::String EmberEntityUserObject::s_TypeName = "EmberEntityPickerObject";
34 EmberEntityUserObject::EmberEntityUserObject( EmberEntity* emberEntity, Model::Model* model, ICollisionDetector* collisionDetector )
: mEmberEntity( emberEntity ),
mModel( model ),
mCollisionDetector( collisionDetector )
// mCollisionObjects( collisionObjects ),
{
}
// CollisionObjectStore EmberEntityUserObject::getCollisionObjects( ) const
// {
// return mCollisionObjects;
// }
47 EmberEntityUserObject::~EmberEntityUserObject( )
{
delete mCollisionDetector;
/* OgreOpcode::CollisionContext* collideContext = OgreOpcode::CollisionManager::getSingletonPtr( )->getDefaultContext( );
for ( EmberEntityUserObject::CollisionObjectStore::iterator I = mCollisionObjects.begin( ); I != mCollisionObjects.end( ); ++I )
{
collideContext->removeObject( *I );
OgreOpcode::CollisionManager::getSingleton( ).destroyShape( ( *I )->getShape( ) );
delete *I;
}*/
}
59 void EmberEntityUserObject::refit( )
{
if ( mCollisionDetector ) {
mCollisionDetector->refit( );
}
/* for ( EmberEntityUserObject::CollisionObjectStore::iterator I = mCollisionObjects.begin( ); I != mCollisionObjects.end( ); ++I )
{
( *I )->refit( );;
}*/
}
70 EmberEntity* EmberEntityUserObject::getEmberEntity( ) const
{
return mEmberEntity;
}
75 Model::Model* EmberEntityUserObject::getModel( ) const
{
return mModel;
}
80 const Ogre::String & EmberEntityUserObject::getTypeName ( void ) const
{
return s_TypeName;
}
};
1 //
// C++ Interface: EmberEntityUserObject
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2005
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGREEMBERENTITYUSEROBJECT_H
#define EMBEROGREEMBERENTITYUSEROBJECT_H
#include "EmberOgrePrerequisites.h"
namespace Ogre
{
32 class Entity;
};
namespace EmberOgre {
namespace Model {
38 class Model;
}
40 class EmberEntity;
struct CollisionResult
{
bool collided;
Ogre::Vector3 position;
Ogre::Real distance;
};
/**
@author Erik Hjortsberg
* Interface for collision detectors, responsible for determining collision information for the entity that they are attached to.
*/
55 class ICollisionDetector
{
public:
58 virtual ~ICollisionDetector( ) {};
/**
* Testa whether the provided ray hits the entity.
* @param ray The ray to test.
* @param result The result of the collision. If the ray hits, the collision detector must update this object.
*/
65 virtual void testCollision( Ogre::Ray& ray, CollisionResult& result ) = 0;
/**
* Refits the collision mesh against the entity. This is called to ensure that the collision mesh fits animated entities.
*/
69 virtual void refit( ) = 0;
/**
* Called when the entity changes, such as a subentity being hidden or shown. Implementations must reload the collision data.
*/
75 virtual void reload( ) = 0;
/**
* Sets whether the collision data should be visualized for debugging purposes.
* @param visualize
*/
81 virtual void setVisualize( bool visualize ) = 0;
/**
* Gets whether the collision data should be visualized for debugging purposes.
* @return
*/
86 virtual bool getVisualize( ) const = 0;
};
/**
@author Erik Hjortsberg
Instances of this class can be attached to scene nodes in the ogre system. They will allow for the Ember system to be accessed directly from Ogre, without having to do lookups.
This is generally mostly used for mouse picking and collision handling.
*/
98 class EmberEntityUserObject : public Ogre::UserDefinedObject
{
public:
/**
The type of UserDefinedObject
*/
105 static const std::string s_TypeName;
// typedef std::vector<OgreOpcode::CollisionObject*> CollisionObjectStore;
/**
* Constructor.
* @param emberEntity A valid EmberEntity instance.
* @param model A valid Model instance.
* @param collisionObject A valid vector of collision objects.
* @return
*/
115 EmberEntityUserObject( EmberEntity* emberEntity, Model::Model* model, ICollisionDetector* collisionDetector );
117 virtual ~EmberEntityUserObject( );
/**
* Gets the EmberEntity contained.
* @return
*/
123 EmberEntity* getEmberEntity( ) const;
/**
* Gets the Model instance.
* @return
*/
129 Model::Model* getModel( ) const ;
/**
* Gets a pointer to a vector of CollisionObjects. This can be used for checking collisions.
* @return
*/
// CollisionObjectStore* getCollisionObjects( ) { return &mCollisionObjects; }
/**
* Overloaded method for getting the type name of this instance.
* @param
* @return
*/
142 virtual const Ogre::String & getTypeName ( void ) const;
144 void refit( );
146 inline ICollisionDetector* getCollisionDetector( ) const;
private:
149 EmberEntity* mEmberEntity;
150 Model::Model* mModel;
//CollisionObjectStore mCollisionObjects;
152 ICollisionDetector* mCollisionDetector;
};
156 ICollisionDetector* EmberEntityUserObject::getCollisionDetector( ) const
{
return mCollisionDetector;
}
};
#endif
1 /*
-----------------------------------------------------------------------------
OgreApp.cpp by Miguel Guzman Miranda ( Aglanor )
Based on OGRE sample applications:
OGRE ( Object-oriented Graphics Rendering Engine )
For the latest info, see http://ogre.sourceforge.net
Based on the Ember main application by the Ember team
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "EmberOgre.h"
// Headers to stop compile problems from headers
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <sys/types.h>
#ifdef WIN32
#include <tchar.h>
#define snprintf _snprintf
#include <io.h> // for _access, Win32 version of stat( )
#include <direct.h> // for _mkdir
// #include <sys/stat.h>
#include <iostream>
#include <fstream>
#include <ostream>
#else
#include <dirent.h>
#endif
#include "EmberOgrePrerequisites.h"
// ------------------------------
// Include Eris header files
// ------------------------------
/*#include <Eris/PollDefault.h>*/
#include <Eris/Connection.h>
#include <Eris/View.h>
//Ember headers
#include "services/EmberServices.h"
#include "services/logging/LoggingService.h"
#include "services/server/ServerService.h"
#include "services/config/ConfigService.h"
#include "services/metaserver/MetaserverService.h"
#include "services/sound/SoundService.h"
#include "services/scripting/ScriptingService.h"
#include "services/wfut/WfutService.h"
#include "framework/ConsoleBackend.h"
#include "framework/ConsoleObject.h" //TODO: this will be included in a different class
#include "framework/binreloc.h" //this is needed for binreloc functionality
// ------------------------------
// Include OGRE Ember client files
// ------------------------------
#include "terrain/TerrainGenerator.h"
#include "terrain/TerrainLayerDefinitionManager.h"
#include "ConsoleObjectImpl.h"
#include "Avatar.h"
#include "AvatarController.h"
#include "EmberEntityFactory.h"
#include "MotionManager.h"
#include "AvatarCamera.h"
#include "GUIManager.h"
#include "manipulation/EntityMoveManager.h"
#include "EmberEntity.h"
#include "WorldEmberEntity.h"
#include "environment/meshtree/TParameters.h"
#include "environment/Tree.h"
#include "carpenter/Carpenter.h"
#include "carpenter/BluePrint.h"
#include <OgreSceneManager.h>
#include "SceneManagers/EmberPagingSceneManager/include/EmberPagingSceneManager.h"
#include "SceneManagers/EmberPagingSceneManager/include/EmberPagingSceneManagerAdapter.h"
#include "model/ModelDefinitionManager.h"
#include "model/ModelDefinition.h"
#include "model/mapping/EmberModelMappingManager.h"
#include "ogreopcode/include/OgreCollisionManager.h"
#include "OpcodeCollisionDetectorVisualizer.h"
// ------------------------------
// Include Ember header files
// ------------------------------
#include "framework/ConsoleBackend.h"
#include "jesus/Jesus.h"
#include "jesus/XMLJesusSerializer.h"
#include "framework/osdir.h"
#include "framework/Exception.h"
#include "OgreLogObserver.h"
#include "OgreResourceLoader.h"
#include "widgets/LoadingBar.h"
#include "sound/OgreSoundProvider.h"
#include "OgreSetup.h"
#include "manipulation/MaterialEditor.h"
#include "MediaUpdater.h"
#include "main/Application.h"
#include "input/InputCommandMapper.h"
#include "input/Input.h"
#include "OgreResourceProvider.h"
#include "scripting/LuaScriptingProvider.h"
template<> EmberOgre::EmberOgre* Ember::Singleton<EmberOgre::EmberOgre>::ms_Singleton = 0;
namespace EmberOgre {
152 void assureConfigFile( const std::string& filename, const std::string& originalConfigFileDir )
{
struct stat tagStat;
int ret = stat( filename.c_str( ), &tagStat );
if ( ret == -1 ) {
ret = stat( ( originalConfigFileDir +filename ).c_str( ), &tagStat );
if ( ret == 0 ) {
///copy conf file from shared
std::ifstream instream ( ( originalConfigFileDir + filename ).c_str( ) );
std::ofstream outstream ( filename.c_str( ) );
outstream << instream.rdbuf( );
}
}
}
169 EmberOgre::EmberOgre( ) :
mAvatar( 0 ),
mAvatarController( 0 ),
mRoot( 0 ),
mSceneMgr( 0 ),
mWindow( 0 ),
mInput( std::auto_ptr<Input>( new Input ) ),
mGeneralCommandMapper( std::auto_ptr<InputCommandMapper>( new InputCommandMapper( "general" ) ) ),
mEmberEntityFactory( 0 ),
mTerrainGenerator( 0 ),
mMotionManager( 0 ),
mGUIManager( 0 ),
mModelDefinitionManager( 0 ),
mModelMappingManager( 0 ),
mTerrainLayerManager( 0 ),
mMoveManager( 0 ),
mKeepOnRunning( true ),
mJesus( 0 ),
mLogObserver( 0 ),
mMaterialEditor( 0 ),
mCollisionManager( 0 ),
mCollisionDetectorVisualizer( 0 )
{
Ember::Application::getSingleton( ).EventServicesInitialized.connect( sigc::mem_fun( *this, &EmberOgre::Application_ServicesInitialized ) );
}
195 EmberOgre::~EmberOgre( )
{
delete mCollisionDetectorVisualizer;
delete mCollisionManager;
delete mMaterialEditor;
delete mJesus;
delete mMoveManager;
///The factory will be deleted by the mWorldView when that is deleted later on, so we shall not delete it here
// delete mEmberEntityFactory;
delete mAvatarController;
delete mAvatar;
///start with deleting the eris world, then shut down ogre
// delete mWorldView;
delete mMotionManager;
delete mTerrainGenerator;
delete mGUIManager;
delete mTerrainLayerManager;
delete mModelMappingManager;
///we need to make sure that all Models are destroyed before Ogre begins destroying other movable objects ( such as Entities )
///this is because Model internally uses Entities, so if those Entities are destroyed by Ogre before the Models are destroyed, the Models will try to delete them again, causing segfaults and other wickedness
///by deleting the model manager we'll assure that
delete mModelDefinitionManager;
if ( mWindow ) {
mRoot->detachRenderTarget( mWindow );
}
Ogre::LogManager::getSingleton( ).getDefaultLog( )->removeListener( mLogObserver );
delete mLogObserver;
if ( mOgreSetup.get( ) ) {
mOgreSetup->shutdown( );
mOgreSetup.release( );
}
/* delete mOgreResourceLoader;
// mSceneMgr->shutdown( );
// delete mWorldView;
//mSceneMgr->removeAllCameras( );
// mSceneMgr->clearScene( );
delete mGUIManager;
delete mTerrainGenerator;
delete mMotionManager;
// if ( mAvatar )
// delete mAvatar;
delete mAvatarController;*/
// delete mModelDefinitionManager;
/* if ( mEmberEntityFactory )
delete mEmberEntityFactory;*/
// delete mRoot;
}
259 bool EmberOgre::frameEnded( const Ogre::FrameEvent & evt )
{
return true;
}
264 bool EmberOgre::frameStarted( const Ogre::FrameEvent & evt )
{
//OgreOpcode::CollisionManager::getSingletonPtr( )->getDefaultContext( )->visualize( true, false, false, false, true, true );
// if ( !mKeepOnRunning )
// S_LOG_INFO( "Shutting down Ember." );
// return mKeepOnRunning;
return true;
}
273 bool EmberOgre::renderOneFrame( )
{
mInput->processInput( );
if ( mInput->isApplicationVisible( ) ) {
return mRoot->renderOneFrame( );
}
return true;
}
282 void EmberOgre::shutdownGui( )
{
delete mGUIManager;
mGUIManager = 0;
}
288 void EmberOgre::go( )
{
if ( !setup( ) )
return;
}
// These internal methods package up the stages in the startup process
/** Sets up the application - returns false if the user chooses to abandon configuration. */
298 bool EmberOgre::setup( )
{
S_LOG_INFO( "Compiled against ogre version " << OGRE_VERSION );
Ember::ConfigService* configSrv = Ember::EmberServices::getSingleton( ).getConfigService( );
checkForConfigFiles( );
///Create a setup object through which we will start up Ogre.
mOgreSetup = std::auto_ptr<OgreSetup>( new OgreSetup );
mLogObserver = new OgreLogObserver( );
///if we do this we will override the automatic creation of a LogManager and can thus route all logging from ogre to the ember log
new Ogre::LogManager( );
Ogre::LogManager::getSingleton( ).createLog( "Ogre", true, false, true );
Ogre::LogManager::getSingleton( ).getDefaultLog( )->addListener( mLogObserver );
///We need a root object.
mRoot = mOgreSetup->createOgreSystem( );
if ( !mRoot ) {
throw Ember::Exception( "There was a problem setting up the Ogre environment, aborting." );
}
///Create the model definition manager
mModelDefinitionManager = new Model::ModelDefinitionManager( );
mModelMappingManager = new Model::Mapping::EmberModelMappingManager( );
mTerrainLayerManager = new Terrain::TerrainLayerDefinitionManager( );
///Create a resource loader which loads all the resources we need.
OgreResourceLoader ogreResourceLoader;
ogreResourceLoader.initialize( );
///check if we should preload the media
bool preloadMedia = configSrv->itemExists( "media", "preloadmedia" ) && ( bool )configSrv->getValue( "media", "preloadmedia" );
bool useWfut = configSrv->itemExists( "wfut", "enabled" ) && ( bool )configSrv->getValue( "wfut", "enabled" );
bool carryOn = mOgreSetup->configure( );
if ( !carryOn ) return false;
mWindow = mOgreSetup->getRenderWindow( );
///start with the bootstrap resources, after those are loaded we can show the LoadingBar
ogreResourceLoader.loadBootstrap( );
mSceneMgr = mOgreSetup->chooseSceneManager( );
///create the main camera, we will of course have a couple of different cameras, but this will be the main one
Ogre::Camera* camera = mSceneMgr->createCamera( "MainCamera" );
Ogre::Viewport* viewPort = mWindow->addViewport( camera );
///set the background colour to black
viewPort->setBackgroundColour( Ogre::ColourValue( 0, 0, 0 ) );
camera->setAspectRatio( Ogre::Real( viewPort->getActualWidth( ) ) / Ogre::Real( viewPort->getActualHeight( ) ) );
///The input object must know the resoluton of the screen
unsigned int height, width, depth;
int top, left;
mWindow->getMetrics( width, height, depth, left, top );
mInput->initialize( width, height );
///bind general commands
mGeneralCommandMapper->readFromConfigSection( "key_bindings_general" );
mGeneralCommandMapper->bindToInput( *mInput );
///we need a nice loading bar to show the user how far the setup has progressed
Gui::LoadingBar loadingBar;
Gui::LoadingBarSection wfutSection( loadingBar, 0.2, "Media update" );
loadingBar.addSection( &wfutSection );
Gui::WfutLoadingBarSection wfutLoadingBarSection( wfutSection );
Gui::LoadingBarSection resourceGroupSection( loadingBar, 0.8, "Resource loading" );
loadingBar.addSection( &resourceGroupSection );
unsigned int numberOfSections = ogreResourceLoader.numberOfSections( ) - 1; ///remove bootstrap since that's already loaded
Gui::ResourceGroupLoadingBarSection resourceGroupSectionListener( resourceGroupSection, numberOfSections, ( preloadMedia ? numberOfSections : 0 ), 0.7 );
loadingBar.start( mWindow );
loadingBar.setVersionText( std::string( "Version " ) + VERSION );
/// Turn off rendering of everything except overlays
mSceneMgr->clearSpecialCaseRenderQueues( );
mSceneMgr->addSpecialCaseRenderQueue( Ogre::RENDER_QUEUE_OVERLAY );
mSceneMgr->setSpecialCaseRenderQueueMode( Ogre::SceneManager::SCRQM_INCLUDE );
if ( useWfut ) {
S_LOG_INFO( "Updating media." );
MediaUpdater updater;
updater.performUpdate( );
}
///create the collision manager
mCollisionManager = new OgreOpcode::CollisionManager( mSceneMgr );
mCollisionDetectorVisualizer = new OpcodeCollisionDetectorVisualizer( );
ogreResourceLoader.loadGui( );
ogreResourceLoader.loadGeneral( );
///add ourself as a frame listener
Ogre::Root::getSingleton( ).addFrameListener( this );
///should media be preloaded?
if ( preloadMedia )
{
S_LOG_INFO( "Begin preload." );
ogreResourceLoader.preloadMedia( );
S_LOG_INFO( "End preload." );
}
try {
mGUIManager = new GUIManager( mWindow, mSceneMgr );
EventGUIManagerCreated.emit( *mGUIManager );
} catch ( ... ) {
///we failed at creating a gui, abort ( since the user could be running in full screen mode and could have some trouble shutting down )
throw Ember::Exception( "Could not load gui, aborting. Make sure that all media got downloaded and installed correctly." );
}
if ( chdir( configSrv->getHomeDirectory( ).c_str( ) ) ) {
S_LOG_WARNING( "Failed to change directory to '"<< configSrv->getHomeDirectory( ) << "'" );
}
// Avatar
mAvatar = new Avatar( );
mAvatarController = new AvatarController( mAvatar, mWindow, mGUIManager, camera );
EventAvatarControllerCreated.emit( *mAvatarController );
mTerrainGenerator = new Terrain::TerrainGenerator( new EmberPagingSceneManagerAdapter( mSceneMgr ) );
EventTerrainGeneratorCreated.emit( *mTerrainGenerator );
mMotionManager = new MotionManager( );
// mMotionManager->setTerrainGenerator( mTerrainGenerator );
EventMotionManagerCreated.emit( *mMotionManager );
// mSceneMgr->setPrimaryCamera( mAvatar->getAvatarCamera( )->getCamera( ) );
mMoveManager = new EntityMoveManager( );
mRoot->addFrameListener( mMotionManager );
new ConsoleObjectImpl( );
try {
mGUIManager->initialize( );
EventGUIManagerInitialized.emit( *mGUIManager );
} catch ( ... ) {
///we failed at creating a gui, abort ( since the user could be running in full screen mode and could have some trouble shutting down )
throw Ember::Exception( "Could not initialize gui, aborting. Make sure that all media got downloaded and installed correctly." );
}
/// Create the scene
createScene( );
EventSceneCreated.emit( );
///this should be in a separate class, a separate plugin even
///disable for now, since it's not used
//setupJesus( );
/// Back to full rendering
mSceneMgr->clearSpecialCaseRenderQueues( );
mSceneMgr->setSpecialCaseRenderQueueMode( Ogre::SceneManager::SCRQM_EXCLUDE );
mMaterialEditor = new MaterialEditor( );
loadingBar.finish( );
return true;
}
476 EmberEntity* EmberOgre::getEmberEntity( const std::string & eid )
{
assert( getMainView( ) );
return static_cast<EmberEntity*>( getMainView( )->getEntity( eid ) );
}
483 void EmberOgre::checkForConfigFiles( )
{
if ( chdir( Ember::EmberServices::getSingleton( ).getConfigService( )->getHomeDirectory( ).c_str( ) ) ) {
S_LOG_WARNING( "Failed to change directory to '"<< Ember::EmberServices::getSingleton( ).getConfigService( )->getHomeDirectory( ) << "', will not copy config files." );
return;
}
const std::string& sharePath( Ember::EmberServices::getSingleton( ).getConfigService( )->getSharedConfigDirectory( ) );
///make sure that there are files
assureConfigFile( "ogre.cfg", sharePath );
//assureConfigFile( "plugins.cfg", sharePath );
}
498 void EmberOgre::preloadMedia( void )
{
Ogre::ResourceGroupManager::getSingleton( ).initialiseAllResourceGroups( );
Ember::ConfigService* configSrv = Ember::EmberServices::getSingleton( ).getConfigService( );
std::vector<std::string> shaderTextures;
shaderTextures.push_back( std::string( configSrv->getValue( "shadertextures", "rock" ) ) );
shaderTextures.push_back( std::string( configSrv->getValue( "shadertextures", "sand" ) ) );
shaderTextures.push_back( std::string( configSrv->getValue( "shadertextures", "grass" ) ) );
for ( std::vector<std::string>::iterator I = shaderTextures.begin( ); I != shaderTextures.end( ); ++I ) {
try {
Ogre::TextureManager::getSingleton( ).load( *I, "General" );
} catch ( const Ogre::Exception& e ) {
S_LOG_FAILURE( "Error when loading texture " << *I << ".\n\rError message: " << e.getDescription( ) );
}
}
//only autogenerate trees if we're not using the pregenerated ones
if ( configSrv->itemExists( "tree", "usedynamictrees" ) && ( ( bool )configSrv->getValue( "tree", "usedynamictrees" ) ) ) {
Environment::Tree tree;
tree.makeMesh( "GeneratedTrees/European_Larch", Ogre::TParameters::European_Larch );
tree.makeMesh( "GeneratedTrees/Fir", Ogre::TParameters::Fir );
}
}
531 void EmberOgre::setupJesus( )
{
const std::string datadir = Ember::EmberServices::getSingleton( ).getConfigService( )->getSharedDataDirectory( );
Carpenter::Carpenter* carpenter = new Carpenter::Carpenter( );
mJesus = new Jesus( carpenter );
XMLJesusSerializer serializer( mJesus );
std::string dir( Ember::EmberServices::getSingleton( ).getConfigService( )->getSharedDataDirectory( ) + "carpenter/blockspec" );
std::string filename;
//oslink::directory needs to be destroyed before a new one can be used, regular copy constructor doesn't seem to work
//we could also use new/delete, but scopes works as well
{
oslink::directory osdir( dir );
while ( osdir ) {
filename = osdir.next( );
S_LOG_VERBOSE( "Loading blockspec: " << filename );
serializer.loadBlockSpec( dir + "/" + filename );
}
}
//load all buildingblockspecs
dir = Ember::EmberServices::getSingleton( ).getConfigService( )->getSharedDataDirectory( ) + "carpenter/modelblockspecs";
{
oslink::directory osdir( dir );
while ( osdir ) {
filename = osdir.next( );
S_LOG_VERBOSE( "Loading buildingblockspecC: " << filename );
serializer.loadBuildingBlockSpecDefinition( dir + "/" + filename );
}
}
//load all modelmappings
dir = Ember::EmberServices::getSingleton( ).getConfigService( )->getSharedDataDirectory( ) + "jesus/modelmappings";
{
oslink::directory osdir( dir );
while ( osdir ) {
filename = osdir.next( );
S_LOG_VERBOSE( "Loading modelmapping: " << filename );
serializer.loadModelBlockMapping( dir + "/" + filename );
}
}
//load all global blueprints
dir = Ember::EmberServices::getSingleton( ).getConfigService( )->getSharedDataDirectory( ) + "carpenter/blueprints";
{
oslink::directory osdir( dir );
while ( osdir ) {
filename = osdir.next( );
S_LOG_VERBOSE( "Loading blueprint: " << filename );
Carpenter::BluePrint* blueprint = serializer.loadBlueprint( dir + "/" + filename );
if ( blueprint ) {
blueprint->compile( );
bool result = mJesus->addBluePrint( blueprint );
if ( !result )
{
S_LOG_FAILURE( "Could not add blueprint: " << filename );
}
}
}
}
//load all local blueprints
dir = Ember::EmberServices::getSingleton( ).getConfigService( )->getHomeDirectory( ) + "carpenter/blueprints";
{
oslink::directory osdir( dir );
while ( osdir ) {
filename = osdir.next( );
S_LOG_VERBOSE( "Loading local blueprint: " << filename );
Carpenter::BluePrint* blueprint = serializer.loadBlueprint( dir + "/" + filename );
if ( blueprint ) {
blueprint->compile( );
bool result = mJesus->addBluePrint( blueprint );
if ( !result )
{
S_LOG_FAILURE( "Could not add blueprint: " << filename );
}
}
}
}
EventCreatedJesus.emit( mJesus );
}
615 void EmberOgre::createScene( void )
{
///initially, while in the "void", we'll use a clear ambient light
mSceneMgr->setAmbientLight( Ogre::ColourValue( 1, 1, 1 ) );
}
623 void EmberOgre::Server_GotView( Eris::View* view )
{
// mWorldView = view;
mEmberEntityFactory = new EmberEntityFactory( view, mTerrainGenerator, Ember::EmberServices::getSingleton( ).getServerService( )->getConnection( )->getTypeService( ) );
}
629 EmberEntity* EmberOgre::getEntity( const std::string & id )
{
///this of course relies upon all entities being created by our factory
return static_cast<EmberEntity*>( getMainView( )->getEntity( id ) );
}
636 void EmberOgre::connectedToServer( Eris::Connection* connection )
{
//EventCreatedAvatarEntity.connect( sigc::mem_fun( *mAvatar, &Avatar::createdAvatarEmberEntity ) );
EventCreatedEmberEntityFactory.emit( mEmberEntityFactory );
}
644 Avatar* EmberOgre::getAvatar( ) const {
return mAvatar;
}
649 Ogre::SceneManager* EmberOgre::getSceneManager( ) const
{
return mSceneMgr;
}
654 Terrain::TerrainGenerator* EmberOgre::getTerrainGenerator( ) const
{
return mTerrainGenerator;
}
659 MotionManager* EmberOgre::getMotionManager( ) const
{
return mMotionManager;
}
664 Ogre::Root* EmberOgre::getOgreRoot( ) const
{
assert( mRoot );
return mRoot;
}
670 Ogre::SceneNode * EmberOgre::getWorldSceneNode( ) const
{
if ( mEmberEntityFactory && mEmberEntityFactory->getWorld( ) ) {
return mEmberEntityFactory->getWorld( )->getSceneNode( );
} else {
return mSceneMgr->getRootSceneNode( );
}
/* Ogre::SceneNode* node = mSceneMgr->getSceneNode( "0" );
//TODO: implement better exception handling
if ( node == 0 )
throw Exception( );
return node;*/
}
684 Ogre::SceneNode* EmberOgre::getRootSceneNode( ) const
{
return mSceneMgr->getRootSceneNode( );
}
690 AvatarCamera* EmberOgre::getMainCamera( ) const
{
return mAvatar->getAvatarCamera( );
}
695 EmberEntityFactory* EmberOgre::getEntityFactory( ) const
{
return mEmberEntityFactory;
}
700 AvatarController* EmberOgre::getAvatarController( ) const
{
return mAvatarController;
}
// // void EmberOgre::setErisPolling( bool doPoll )
// // {
// // mPollEris = doPoll;
// // }
// //
// // bool EmberOgre::getErisPolling( ) const
// // {
// // return mPollEris;
// // }
716 void EmberOgre::initializeEmberServices( const std::string& prefix, const std::string& homeDir )
{
}
721 void EmberOgre::Application_ServicesInitialized( )
{
Ember::EmberServices::getSingleton( ).getServerService( )->GotConnection.connect( sigc::mem_fun( *this, &EmberOgre::connectedToServer ) );
Ember::EmberServices::getSingleton( ).getServerService( )->GotView.connect( sigc::mem_fun( *this, &EmberOgre::Server_GotView ) );
mScriptingResourceProvider = std::auto_ptr<OgreResourceProvider>( new OgreResourceProvider( "Scripting" ) );
Ember::EmberServices::getSingleton( ).getScriptingService( )->setResourceProvider( mScriptingResourceProvider.get( ) );
///register the lua scripting provider
Ember::EmberServices::getSingleton( ).getScriptingService( )->registerScriptingProvider( new LuaScriptingProvider( ) );
}
733 Eris::View* EmberOgre::getMainView( )
{
return Ember::Application::getSingleton( ).getMainView( );
}
}
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://ogre.sourceforge.net/
Copyright � 2000-2002 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
*/
#ifndef __EmberOgre_H__
#define __EmberOgre_H__
#include "EmberOgrePrerequisites.h"
// ------------------------------
// Include sigc header files
// ------------------------------
#include <sigc++/trackable.h>
#include <sigc++/signal.h>
#include "framework/Singleton.h"
namespace Eris {
42 class View;
43 class Connection;
}
namespace Carpenter
{
48 class Carpenter;
49 class BluePrint;
}
52 namespace Ember
{
class StreamLogObserver;
}
namespace OgreOpcode {
58 class CollisionManager;
}
61 namespace EmberOgre {
namespace Terrain
{
class TerrainGenerator;
class TerrainLayerDefinitionManager;
}
namespace Model {
class ModelDefinitionManager;
namespace Mapping {
class EmberModelMappingManager;
}
}
class CameraRotator;
class CameraFrameListener;
class Avatar;
class AvatarCamera;
class AvatarController;
class AvatarEmberEntity;
class EmberEntityFactory;
class EmberPagingSceneManager;
class MotionManager;
class Input;
class InputManager;
class InputCommandMapper;
class GUIManager;
class Jesus;
class EmberEntity;
class OgreResourceLoader;
class OgreLogObserver;
class EntityMoveManager;
class MaterialEditor;
class OgreSetup;
class OgreResourceProvider;
class OpcodeCollisionDetectorVisualizer;
/**
The main class of ember. This functions as a hub for almost all subsystems. ( Perhaps this should be refactored? )
*/
class EmberOgre : public Ember::Singleton<EmberOgre>,
public sigc::trackable,
public Ogre::FrameListener
{
public:
/// Standard constructor
EmberOgre( );
/// Standard destructor
~EmberOgre( );
virtual bool frameStarted( const Ogre::FrameEvent & evt );
virtual bool frameEnded( const Ogre::FrameEvent & evt );
/**
* starts the main app
*/
virtual void go( );
// void shutdown( );
/**
* Initialize all Ember services needed for this application
* @param the prefix for the application, not appliable if running under win32
* @param the an alternative home directory. If the default should be used, send an empty string.
*/
void initializeEmberServices( const std::string& prefix, const std::string& homeDir );
void Server_GotView( Eris::View* world );
void connectedToServer( Eris::Connection* connection );
// TODO: possibly we'd like to do the following in a different way,
// perhaps refactoring stuff
Avatar* getAvatar( ) const;
Ogre::SceneManager* getSceneManager( ) const;
Terrain::TerrainGenerator* getTerrainGenerator( ) const;
MotionManager* getMotionManager( ) const;
Ogre::Root* getOgreRoot( ) const;
EmberEntityFactory* getEntityFactory( ) const;
AvatarCamera* getMainCamera( ) const;
AvatarController* getAvatarController( ) const;
inline EntityMoveManager* getMoveManager( ) const;
// inline Input& getInput( );
/**
* Gets the entity with the supplies id from the world.
*/
EmberEntity* getEmberEntity( const std::string & eid );
inline Jesus* getJesus( ) const;
inline Ogre::RenderWindow* getRenderWindow( ) const;
sigc::signal<void, EmberEntityFactory*> EventCreatedEmberEntityFactory;
sigc::signal<void, AvatarEmberEntity*> EventCreatedAvatarEntity;
sigc::signal<void, Jesus*> EventCreatedJesus;
/**
Emitted before the eris polling is started
*/
// sigc::signal<void> EventStartErisPoll;
/**
Emitted after the eris polling has finished
*/
// sigc::signal<void> EventEndErisPoll;
/**
* returns the scenenode of the world entity
* throws en exception if no such node has been created
* @return
*/
Ogre::SceneNode* getWorldSceneNode( ) const;
/**
* returns the root scene node
* @return
*/
Ogre::SceneNode* getRootSceneNode( ) const;
/**
Emitted after the GUIManager has been created, but not yet initialized
*/
sigc::signal<void, GUIManager&> EventGUIManagerCreated;
/**
Emitted after the GUIManager has been initilized
*/
sigc::signal<void, GUIManager&> EventGUIManagerInitialized;
/**
Emitted after the Motion has been created
*/
sigc::signal<void, MotionManager&> EventMotionManagerCreated;
/**
Emitted after the TerrainGenerator has been created
*/
sigc::signal<void, Terrain::TerrainGenerator&> EventTerrainGeneratorCreated;
/**
Emitted after the AvatarController has been created
*/
sigc::signal<void, AvatarController&> EventAvatarControllerCreated;
/**
Emitted after the base Ogre scene has been created
*/
sigc::signal<void> EventSceneCreated;
EmberEntity* getEntity( const std::string & id );
/**
* Call this to "soft quit" the app. This means that an signal will be emitted, which hopefully will be taken care of by some widget, which will show a confirmation window, asking the user if he/she wants to quit.
However, if there is no widget etc. handling the request, the application will instantly quit.
*/
// void requestQuit( );
/**
* Sets whether eris should be polled each frame. Defaults to true.
* @param doPoll
*/
// void setErisPolling( bool doPoll );
/**
* Gets whether eris should be polled each frame.
* @return
*/
// bool getErisPolling( ) const;
/**
Renders one frame.
*/
bool renderOneFrame( );
/**
* Sets up the application - returns false if the user chooses to abandon configuration.
* @return
*/
bool setup( );
void shutdownGui( );
protected:
/**
utility object for setting up and tearing down ogre
*/
std::auto_ptr<OgreSetup> mOgreSetup;
Eris::View* getMainView( );
/**
* The main user avatar
*/
Avatar* mAvatar;
/**
When connected to a world, handles the avatar and patches mouse and keyboard movement events on the avatar.
*/
AvatarController* mAvatarController;
/**
The main Ogre root object. All of Ogre is accessed through this.
*/
Ogre::Root *mRoot;
/**
The main scene manager of the world.
*/
EmberPagingSceneManager* mSceneMgr;
/**
The main render window. There can be many more render targets in the system, but they will all reside within this render window ( such as entity preview through CEGUI ).
*/
Ogre::RenderWindow* mWindow;
/**
The main input object.
*/
std::auto_ptr<Input> mInput;
/**
An InputCommandMapper that will handle all general input events.
*/
std::auto_ptr<InputCommandMapper> mGeneralCommandMapper;
/**
Main factory for all entities created in the world.
*/
EmberEntityFactory* mEmberEntityFactory;
/**
* Creates the basic scene with a single avatar, just for testing purpose.
* NOTE: remove this when going final
* @param
*/
void createScene( void );
/**
* Sets up Jesus. This inialized the mJesus member and loads all building blocks, blueprint and modelblocks etc.
*/
void setupJesus( );
/**
* Preloads the media, thus avoiding frame rate drops ingame.
* @param
*/
void preloadMedia( void );
/**
makes sure that there are files in ~/.ember
*/
void checkForConfigFiles( );
/**
Responsible for handling of terrain.
*/
Terrain::TerrainGenerator* mTerrainGenerator;
/**
Responsible for updating motions and animations of entities.
*/
MotionManager* mMotionManager;
/**
Responsible for the GUI.
*/
GUIManager* mGUIManager;
/**
Resonsible for managing all Model definitions;
*/
Model::ModelDefinitionManager* mModelDefinitionManager;
/**
Handles all model mappings.
*/
Model::Mapping::EmberModelMappingManager* mModelMappingManager;
Terrain::TerrainLayerDefinitionManager* mTerrainLayerManager;
/**
Responsible for allowing movement of entities in the world by the user.
*/
EntityMoveManager* mMoveManager;
/**
when this is false the app will exit
*/
bool mKeepOnRunning;
/**
main entry point for the Jesus system ( which is an Ember wrapper for the Carpenter lib )
*/
Jesus* mJesus;
/**
Once connected to a world, this will hold the main world view.
*/
// Eris::View* mWorldView;
/**
Controls whether eris should be polled at each frame update.
*/
// bool mPollEris;
/**
The main log observer used for all logging. This will send Ogre logging events on to the internal Ember logging framework.
*/
OgreLogObserver* mLogObserver;
/**
Patches logging events from the Ember logging framework on to a file writer.
*/
// Ember::StreamLogObserver* mStreamLogObserver;
/**
Helper object that allows for easy Ogre material editing.
*/
MaterialEditor* mMaterialEditor;
void Application_ServicesInitialized( );
std::auto_ptr<OgreResourceProvider> mScriptingResourceProvider;
OgreOpcode::CollisionManager* mCollisionManager;
OpcodeCollisionDetectorVisualizer* mCollisionDetectorVisualizer;
};
// Input& EmberOgre::getInput( )
// {
// return mInput;
// }
EntityMoveManager* EmberOgre::getMoveManager( ) const
{
return mMoveManager;
}
Jesus* EmberOgre::getJesus( ) const
{
return mJesus;
}
Ogre::RenderWindow* EmberOgre::getRenderWindow( ) const
{
return mWindow;
}
}
#endif
1 /*
Copyright ( C ) 2004 Erik Hjortsberg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __EmberPrerequisites_H__
#define __EmberPrerequisites_H__
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "OgreIncludes.h"
// #include "MathConverter.h"
///include the Logging service, since we want logging available from most classes
///in most cases, use the S_LOG* defines
///such as:
///S_LOG_INFO( "some info" )
#include "services/logging/LoggingService.h"
#include "framework/Exception.h"
///utility defines for stl containers
///for example:
///TYPEDEF_STL_VECTOR( std::string, StringVector )
///defines a new type called StringVector
///you can then use StringVector::iterator etc..
#define TYPEDEF_STL_MKITERATORS( name ) \
typedef name::iterator name##Iter; \
typedef name::const_iterator name##CIter; \
typedef name::reverse_iterator name##RIter; \
typedef name::const_reverse_iterator name##CRIter
#define TYPEDEF_STL_CONTAINER1( container, tp, name ) \
typedef std::container<tp> name; \
TYPEDEF_STL_MKITERATORS( name )
#define TYPEDEF_STL_CONTAINER2( container, tp1, tp2, name ) \
typedef std::container<tp1, tp2> name; \
TYPEDEF_STL_MKITERATORS( name )
#define TYPEDEF_STL_VECTOR( tp, name ) TYPEDEF_STL_CONTAINER1( vector, tp, name )
#define TYPEDEF_STL_LIST( tp, name ) TYPEDEF_STL_CONTAINER1( list, tp, name )
#define TYPEDEF_STL_SET( tp, name ) TYPEDEF_STL_CONTAINER1( set, tp, name )
#define TYPEDEF_STL_MAP( tpkey, tpval, name ) TYPEDEF_STL_CONTAINER2( map, tpkey, tpval, name )
typedef unsigned int uint;
#endif
1 /*
Copyright ( C ) 2004 Erik Hjortsberg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "EmberPhysicalEntity.h"
#include "framework/ConsoleBackend.h"
#include "MotionManager.h"
#include "model/Model.h"
#include "model/ModelDefinition.h"
#include "model/SubModel.h"
#include "model/ParticleSystemBinding.h"
#include "model/Action.h"
#include "model/mapping/EmberModelMappingManager.h"
#include "model/mapping/ModelMapping.h"
#include "model/mapping/ModelMappingManager.h"
#include "environment/Environment.h"
#include "environment/Forest.h"
#include "EmberEntityFactory.h"
#include "WorldEmberEntity.h"
#include "EmberEntityActionCreator.h"
#include <OgreException.h>
#include "EmberOgre.h"
#include "MousePicker.h"
#include "EmberEntityUserObject.h"
#include "OpcodeCollisionDetector.h"
#include "MeshCollisionDetector.h"
#include <Eris/Entity.h>
#include <Eris/View.h>
#include <Eris/TypeInfo.h>
namespace EmberOgre {
60 const char * const EmberPhysicalEntity::ACTION_STAND = "__movement_idle";
61 const char * const EmberPhysicalEntity::ACTION_RUN = "__movement_run";
62 const char * const EmberPhysicalEntity::ACTION_WALK = "__movement_walk";
63 const char * const EmberPhysicalEntity::ACTION_SWIM = "__movement_swim";
64 const char * const EmberPhysicalEntity::ACTION_FLOAT = "__movement_float";
68 EmberPhysicalEntity::EmberPhysicalEntity( const std::string& id, Eris::TypeInfo* ty, Eris::View* vw, Ogre::SceneManager* sceneManager ) :
EmberEntity( id, ty, vw, sceneManager ),
mCurrentMovementAction( 0 ),
mActiveAction( 0 ),
mModelAttachedTo( 0 ),
mModelMarkedToAttachTo( 0 ),
mModel( 0 ),
mScaleNode( 0 ),
mModelMapping( 0 )
{
}
80 EmberPhysicalEntity::~EmberPhysicalEntity( )
{
delete mModelMapping;
if ( mModel ) {
delete mModel->getUserObject( );
getSceneManager( )->destroyMovableObject( mModel );
}
Ogre::SceneNode *parent = static_cast<Ogre::SceneNode*>( getScaleNode( )->getParent( ) );
if ( parent ) {
parent->removeAndDestroyChild( getScaleNode( )->getName( ) );
}
///make sure it's not in the MotionManager
///TODO: keep a marker in the entity so we don't need to call this for all entities
MotionManager::getSingleton( ).removeAnimatedEntity( this );
/*
mSceneManager->removeEntity( mOgreEntity );
mSceneManager->removeEntity( mOgreEntity );
delete mOgreEntity;
delete mSceneNode;
*/
}
107 EmberEntity* EmberPhysicalEntity::getEntityAttachedToPoint( const std::string& attachPoint )
{
///first check with the attach points
const std::string* entityId( 0 );
for( AttachedEntitiesStore::const_iterator I = mAttachedEntities.begin( ); I != mAttachedEntities.end( ); ++I ) {
if ( I->second == attachPoint ) {
entityId = &I->first;
break;
}
}
if ( entityId ) {
///then get the entity from the world
EmberEntity* entity = EmberOgre::getSingleton( ).getEmberEntity( *entityId );
return entity;
}
return 0;
}
127 void EmberPhysicalEntity::setVisible( bool visible )
{
EmberEntity::setVisible( visible );
// if ( !visible ) {
// if ( getScaleNode( )->getParent( ) ) {
// mOgreNode->removeChild( getScaleNode( ) );
// }
// } else {
// if ( !getScaleNode( )->getParent( ) ) {
// mOgreNode->addChild( getScaleNode( ) );
// }
// }
getScaleNode( )->setVisible( visible && getLocation( ), false );
//getModel( )->setVisible( visible );
}
143 void EmberPhysicalEntity::createScaleNode( )
{
mScaleNode = mOgreNode->createChildSceneNode( getId( ) + "_scaleNode" );
}
148 void EmberPhysicalEntity::setModel( const std::string& modelName )
{
if ( mModel ) {
if ( mModel->getDefinition( )->getName( ) == modelName ) {
return;
} else {
getSceneManager( )->destroyMovableObject( mModel );
}
}
mModel = Model::Model::createModel( EmberOgre::getSingleton( ).getSceneManager( ), modelName, getId( ) );
///if the model definition isn't valid, use a placeholder
if ( !mModel->getDefinition( )->isValid( ) ) {
S_LOG_FAILURE( "Could not find " << modelName << ", using placeholder." );
///add a placeholder model
Model::ModelDefnPtr modelDef = mModel->getDefinition( );
modelDef->createSubModelDefinition( "placeholder.mesh" )->createPartDefinition( "main" )->setShow( true );
modelDef->setValid( true );
modelDef->reloadAllInstances( );
}
///rotate node to fit with WF space
///perhaps this is something to put in the model spec instead?
// scaleNode->rotate( Ogre::Vector3::UNIT_Y, ( Ogre::Degree )90 );
mScaleNode->attachObject( mModel );
}
176 void EmberPhysicalEntity::showModelPart( const std::string& partName )
{
Model::Model* model = getModel( );
if ( model ) {
model->showPart( partName );
///if we already have set up a collision object we must reload it
EmberEntityUserObject* userObject = static_cast<EmberEntityUserObject*>( getModel( )->getUserObject( ) );
if ( userObject && userObject->getCollisionDetector( ) ) {
userObject->getCollisionDetector( )->reload( );
}
}
}
190 void EmberPhysicalEntity::hideModelPart( const std::string& partName )
{
Model::Model* model = getModel( );
if ( model ) {
model->hidePart( partName );
///if we already have set up a collision object we must reload it
EmberEntityUserObject* userObject = static_cast<EmberEntityUserObject*>( getModel( )->getUserObject( ) );
if ( userObject && userObject->getCollisionDetector( ) ) {
userObject->getCollisionDetector( )->reload( );
}
}
}
204 void EmberPhysicalEntity::init( const Atlas::Objects::Entity::RootEntity &ge, bool fromCreateOp )
{
///first we need to create the scale node
createScaleNode( );
/// we need a model mapping
createModelMapping( );
assert( mModelMapping );
mModelMapping->initialize( );
if ( !mModel ) {
S_LOG_WARNING( "Entity of type " << getType( )->getName( ) << " have no default model, using placeholder." );
setModel( "placeholder" );
}
///once we have that, we need which model to use and can create the model
// createModel( );
onModeChanged( EmberEntity::MM_DEFAULT );
EmberEntity::init( ge, fromCreateOp );
getModel( )->setQueryFlags( MousePicker::CM_ENTITY );
/* assert( mOgreNode );
assert( mScaleNode );*/
//if there is no bounding box, scaleNode hasn't been called, so do it here
/* if ( !hasBBox( ) ) {
scaleNode( );
}*/
//translate the scale node according to the translate defined in the model
// getScaleNode( )->translate( getModel( )->getDefinition( )->getTranslate( ) );
initFromModel( );
/* EmberEntityUserObject* userObject = new EmberEntityUserObject( this, getModel( ), 0, 0 );
getModel( )->setUserObject( userObject );*/
/** If there's an idle animation, we'll randomize the entry value for that so we don't end up with too many similiar entities with synched animations ( such as when you enter the world at origo and have 20 settlers doing the exact same motions. */
Model::Action* idleaction = mModel->getAction( ACTION_STAND );
if ( idleaction ) {
idleaction->getAnimations( ).addTime( Ogre::Math::RangeRandom( 0, 15 ) );
}
//check if we should do delayed attachment
if ( mModelMarkedToAttachTo ) {
attachToPointOnModel( mAttachPointMarkedToAttachTo, mModelMarkedToAttachTo );
mModelMarkedToAttachTo = 0;
mAttachPointMarkedToAttachTo = "";
}
//NOTE: for now, add all particle systems. we will want to add some visibility flag or something in the future
for ( Model::ParticleSystemSet::iterator I = mModel->getParticleSystems( ).begin( ); I != mModel->getParticleSystems( ).end( ); ++I )
{
getScaleNode( )->attachObject( ( *I )->getOgreParticleSystem( ) );
}
getModel( )->Reloaded.connect( sigc::mem_fun( *this, &EmberPhysicalEntity::Model_Reloaded ) );
getModel( )->Resetting.connect( sigc::mem_fun( *this, &EmberPhysicalEntity::Model_Resetting ) );
}
268 void EmberPhysicalEntity::initFromModel( )
{
///make a copy of the original bbox
mDefaultOgreBoundingBox = mModel->getBoundingBox( );
getScaleNode( )->setOrientation( Ogre::Quaternion::IDENTITY );
///rotate node to fit with WF space
///perhaps this is something to put in the model spec instead?
getScaleNode( )->rotate( Ogre::Vector3::UNIT_Y, ( Ogre::Degree )90 );
getScaleNode( )->rotate( getModel( )->getRotation( ) );
scaleNode( );
getScaleNode( )->setPosition( Ogre::Vector3::ZERO );
///translate the scale node according to the translate defined in the model
getScaleNode( )->translate( getModel( )->getDefinition( )->getTranslate( ) );
connectEntities( );
const Model::RenderingDefinition* renderingDef = mModel->getDefinition( )->getRenderingDefinition( );
if ( renderingDef && renderingDef->getScheme( ) == "forest" ) {
Environment::Forest* forest = EmberOgre::getSingleton( ).getEntityFactory( )->getWorld( )->getEnvironment( )->getForest( );
for ( Model::Model::SubModelSet::const_iterator I = mModel->getSubmodels( ).begin( ); I != mModel->getSubmodels( ).end( ); ++I ) {
// if ( ( *I )->getEntity( )->isVisible( ) ) {
( *I )->getEntity( )->setVisible( true );
forest->addTree( ( *I )->getEntity( ), getScaleNode( )->getWorldPosition( ), getScaleNode( )->getWorldOrientation( ).getYaw( ), getScaleNode( )->getScale( ).y );
// }
}
mModel->setRenderingDistance( 100 );
// getScaleNode( )->detachObject( mModel );
// getSceneNode( )->removeChild( getScaleNode( ) );
// getScaleNode( )->setVisible( false );
}
}
305 void EmberPhysicalEntity::createModelMapping( )
{
delete mModelMapping;
EmberEntityActionCreator creator( *this );
mModelMapping = ::EmberOgre::Model::Mapping::EmberModelMappingManager::getSingleton( ).getManager( ).createMapping( this, &creator );
}
312 void EmberPhysicalEntity::connectEntities( )
{
if ( getModel( ) ) {
if ( getModel( )->getUserObject( ) ) {
delete getModel( )->getUserObject( );
}
// ICollisionDetector* collisionDetector = new OpcodeCollisionDetector( getModel( ) );
ICollisionDetector* collisionDetector = new MeshCollisionDetector( getModel( ) );
EmberEntityUserObject* userObject = new EmberEntityUserObject( this, getModel( ), collisionDetector );
getModel( )->setUserObject( userObject );
}
}
326 void EmberPhysicalEntity::attachToPointOnModel( const std::string& point, Model::Model* model )
{
//if we're not initialized, delay attachment until after init
if ( !isInitialized( ) ) {
mModelMarkedToAttachTo = model;
mAttachPointMarkedToAttachTo = point;
} else {
if ( model->hasAttachPoint( point ) && model->getSkeleton( ) ) {
getScaleNode( )->detachObject( getModel( ) );
getModel( )->setVisible( true );
model->attachObjectToAttachPoint( point, getModel( ), getScaleNode( )->getScale( ), getModel( )->getDefinition( )->getRotation( ) );
mModelAttachedTo = model;
}
}
}
342 void EmberPhysicalEntity::detachFromModel( )
{
if ( mModelAttachedTo ) {
mModelAttachedTo->detachObjectFromBone( getModel( )->getName( ) );
getScaleNode( )->attachObject( getModel( ) );
checkVisibility( isVisible( ) );
mModelAttachedTo = 0;
}
}
352 void EmberPhysicalEntity::showOgreBoundingBox( bool show )
{
getScaleNode( )->showBoundingBox( show );
}
358 bool EmberPhysicalEntity::getShowOgreBoundingBox( ) const
{
return getScaleNode( )->getShowBoundingBox( );
}
363 Model::Model* EmberPhysicalEntity::getModel( ) const
{
return mModel;
}
368 void EmberPhysicalEntity::Model_Reloaded( )
{
initFromModel( );
attachAllEntities( );
}
374 void EmberPhysicalEntity::Model_Resetting( )
{
if ( getModel( )->getUserObject( ) ) {
delete getModel( )->getUserObject( );
}
getModel( )->setUserObject( 0 );
detachAllEntities( );
}
383 void EmberPhysicalEntity::processWield( const std::string& wieldName, const Atlas::Message::Element& idElement )
{
S_LOG_VERBOSE( "Set " << wieldName << " to " << idElement.asString( ) );
const std::string& id = idElement.asString( );
if ( id.empty( ) ) {
detachEntity( wieldName );
} else {
//detach first
detachEntity( wieldName );
attachEntity( wieldName, id );
}
}
396 void EmberPhysicalEntity::processOutfit( const Atlas::Message::MapType & outfitMap )
{
}
401 void EmberPhysicalEntity::onAttrChanged( const std::string& str, const Atlas::Message::Element& v ) {
EmberEntity::onAttrChanged( str, v );
///this is kind of a hack, but it allows characters to wield other entities in their hands
if ( str == "right_hand_wield" || str == "left_hand_wield" ) {
processWield( str, v );
return;
}
// if ( str == "outfit" ) {
// if ( v.isMap( ) ) {
// const Atlas::Message::MapType & outfitMap = v.asMap( );
// int i = 0;
// }
// }
// if ( str == "bbox" ) {
// scaleNode( );
// }
//check if the changed attribute should affect any particle systems
if ( mModel->hasParticles( ) ) {
const Model::ParticleSystemBindingsPtrSet& bindings = mModel->getAllParticleSystemBindings( );
for ( Model::ParticleSystemBindingsPtrSet::const_iterator I = bindings.begin( ); I != bindings.end( ); ++I ) {
if ( ( *I )->getVariableName( ) == str && v.isNum( ) ) {
( *I )->scaleValue( v.asNum( ) );
}
}
}
}
432 void EmberPhysicalEntity::onModeChanged( MovementMode newMode )
{
/* if ( newMode != mMovementMode )
{*/
const char * actionName;
if ( newMode == EmberEntity::MM_WALKING ) {
actionName = ACTION_WALK;
} else if ( newMode == EmberEntity::MM_RUNNING ) {
actionName = ACTION_RUN;
} else if ( newMode == EmberEntity::MM_SWIMMING ) {
actionName = ACTION_SWIM;
} else {
actionName = ACTION_STAND;
}
if ( !mCurrentMovementAction || mCurrentMovementAction->getName( ) != actionName ) {
///first disable the current action
if ( mCurrentMovementAction ) {
mCurrentMovementAction->getAnimations( ).reset( );
}
Model::Action* newAction = mModel->getAction( actionName );
mCurrentMovementAction = newAction;
if ( newAction ) {
MotionManager::getSingleton( ).addAnimatedEntity( this );
// mCurrentMovementAction->getAnimations( )->setEnabled( true );
} else {
MotionManager::getSingleton( ).removeAnimatedEntity( this );
}
}
//might set mCurrentMovementAction to 0
// }
EmberEntity::onModeChanged( newMode );
}
469 void EmberPhysicalEntity::onChildAdded( Entity *e )
{
Eris::Entity::onChildAdded( e );
//see if it's in our attach map
if ( mAttachedEntities.find( e->getId( ) ) != mAttachedEntities.end( ) ) {
EmberEntity* emberEntity = static_cast<EmberEntity*>( e );
emberEntity->attachToPointOnModel( mAttachedEntities[e->getId( )], getModel( ) );
}
/* if ( hasChild( entityId ) ) {
}*/
}
486 void EmberPhysicalEntity::onChildRemoved( Entity *e )
{
//NOTE: we don't have to do detachment here, like we do attachment in onChildAdded, since that is done by the EmberEntity::onLocationChanged( ... ) method
Eris::Entity::onChildRemoved( e );
}
493 void EmberPhysicalEntity::scaleNode( ) {
getScaleNode( )->setScale( 1, 1, 1 );
const Ogre::Vector3& ogreMax = mDefaultOgreBoundingBox.getMaximum( );
const Ogre::Vector3& ogreMin = mDefaultOgreBoundingBox.getMinimum( );
if ( hasBBox( ) ) {
const WFMath::AxisBox<3>& wfBoundingBox = getBBox( );
const WFMath::Point<3>& wfMax = wfBoundingBox.highCorner( );
const WFMath::Point<3>& wfMin = wfBoundingBox.lowCorner( );
Ogre::Real scaleX;
Ogre::Real scaleY;
Ogre::Real scaleZ;
switch ( getModel( )->getUseScaleOf( ) ) {
case Model::ModelDefinition::MODEL_HEIGHT:
scaleX = scaleY = scaleZ = fabs( ( wfMax.z( ) - wfMin.z( ) ) / ( ogreMax.y - ogreMin.y ) );
break;
case Model::ModelDefinition::MODEL_WIDTH:
scaleX = scaleY = scaleZ = fabs( ( wfMax.x( ) - wfMin.x( ) ) / ( ogreMax.x - ogreMin.x ) );
break;
case Model::ModelDefinition::MODEL_DEPTH:
scaleX = scaleY = scaleZ = fabs( ( wfMax.y( ) - wfMin.y( ) ) / ( ogreMax.z - ogreMin.z ) );
break;
case Model::ModelDefinition::MODEL_NONE:
scaleX = scaleY = scaleZ = 1;
break;
case Model::ModelDefinition::MODEL_ALL:
default:
scaleX = fabs( ( wfMax.x( ) - wfMin.x( ) ) / ( ogreMax.x - ogreMin.x ) );
scaleY = fabs( ( wfMax.z( ) - wfMin.z( ) ) / ( ogreMax.y - ogreMin.y ) );
scaleZ = fabs( ( wfMax.y( ) - wfMin.y( ) ) / ( ogreMax.z - ogreMin.z ) );
}
//Ogre::Real finalScale = std::max( scaleX, scaleY );
//finalScale = std::max( finalScale, scaleZ );
getScaleNode( )->setScale( scaleX, scaleY, scaleZ );
} else if ( !getModel( )->getScale( ) ) {
//set to small size
Ogre::Real scaleX = ( 0.25 / ( ogreMax.x - ogreMin.x ) );
Ogre::Real scaleY = ( 0.25 / ( ogreMax.y - ogreMin.y ) );
Ogre::Real scaleZ = ( 0.25 / ( ogreMax.z - ogreMin.z ) );
getScaleNode( )->setScale( scaleX, scaleY, scaleZ );
}
if ( getModel( )->getScale( ) ) {
if ( getModel( )->getScale( ) != 1 ) {
//only scale if it's not 1
getScaleNode( )->scale( getModel( )->getScale( ), getModel( )->getScale( ), getModel( )->getScale( ) );
}
}
}
557 const Ogre::Vector3& EmberPhysicalEntity::getOffsetForContainedNode( const Ogre::Vector3& position, EmberEntity* const entity )
{
///if the model has an offset specified, use that, else just send to the base class
const Ogre::Vector3& offset = getModel( )->getDefinition( )->getContentOffset( );
if ( offset != Ogre::Vector3::ZERO ) {
return offset;
} else {
return EmberEntity::getOffsetForContainedNode( position, entity );
}
}
570 void EmberPhysicalEntity::updateMotion( Ogre::Real timeSlice )
{
EmberEntity::updateMotion( timeSlice );
}
576 void EmberPhysicalEntity::updateAnimation( Ogre::Real timeSlice )
{
if ( mActiveAction ) {
bool continuePlay = false;
mActiveAction->getAnimations( ).addTime( timeSlice, continuePlay );
if ( !continuePlay ) {
mActiveAction->getAnimations( ).reset( );
mActiveAction = 0;
}
} else {
if ( mCurrentMovementAction ) {
bool continuePlay = false;
//check if we're walking backward
if ( static_cast<int>( ( WFMath::Vector<3>( getVelocity( ) ).rotate( ( getOrientation( ).inverse( ) ) ) ).x( ) ) < 0 ) {
mCurrentMovementAction->getAnimations( ).addTime( -timeSlice, continuePlay );
} else {
mCurrentMovementAction->getAnimations( ).addTime( timeSlice, continuePlay );
}
}
}
}
598 void EmberPhysicalEntity::setMoving( bool moving )
{
// MotionManager* motionManager = &MotionManager::getSingleton( );
// if ( moving ) {
// if ( getModel( )->isAnimated( ) ) {
// getModel( )->stopAnimation( "idle" );
// getModel( )->startAnimation( "walk" );
// }
// } else {
// if ( getModel( )->isAnimated( ) ) {
// getModel( )->stopAnimation( "walk" );
// getModel( )->startAnimation( "idle" );
// }
// }
EmberEntity::setMoving( moving );
}
615 void EmberPhysicalEntity::detachEntity( const std::string & attachPoint )
{
const std::string* entityId( 0 );
for( AttachedEntitiesStore::const_iterator I = mAttachedEntities.begin( ); I != mAttachedEntities.end( ); ++I ) {
if ( I->second == attachPoint ) {
entityId = &I->first;
break;
}
}
if ( entityId ) {
if ( hasChild( *entityId ) ) {
//we already have the entity, do the detachment
EmberEntity* entity = EmberOgre::getSingleton( ).getEntity( *entityId );
if ( entity ) {
entity->detachFromModel( );
}
}
mAttachedEntities.erase( *entityId );
}
}
637 void EmberPhysicalEntity::attachEntity( const std::string & attachPoint, const std::string & entityId )
{
mAttachedEntities[entityId] = attachPoint;
if ( hasChild( entityId ) ) {
//we already have the entity, do the attachment now, else we will just wait for the onChildAdded event
EmberEntity* entity = EmberOgre::getSingleton( ).getEntity( entityId );
if ( entity ) {
entity->attachToPointOnModel( attachPoint, getModel( ) );
}
}
}
649 void EmberPhysicalEntity::detachAllEntities( )
{
for( AttachedEntitiesStore::const_iterator I = mAttachedEntities.begin( ); I != mAttachedEntities.end( ); ++I ) {
detachEntity( I->first );
}
}
656 void EmberPhysicalEntity::attachAllEntities( )
{
//HACK: this should be data driven
if ( hasAttr( "right_hand_wield" ) ) {
const Atlas::Message::Element& idElement = valueOfAttr( "right_hand_wield" );
attachEntity( "right_hand_wield", idElement.asString( ) );
} else if ( hasAttr( "left_hand_wield" ) ) {
const Atlas::Message::Element& idElement = valueOfAttr( "left_hand_wield" );
attachEntity( "left_hand_wield", idElement.asString( ) );
}
}
669 void EmberPhysicalEntity::onBboxChanged( )
{
EmberEntity::onBboxChanged( );
scaleNode( );
}
675 const Ogre::AxisAlignedBox& EmberPhysicalEntity::getWorldBoundingBox( bool derive ) const
{
return getModel( )->getWorldBoundingBox( derive );
}
680 const Ogre::Sphere & EmberPhysicalEntity::getWorldBoundingSphere ( bool derive ) const
{
return getModel( )->getWorldBoundingSphere( derive );
}
685 void EmberPhysicalEntity::onAction( const Atlas::Objects::Operation::RootOperation& act )
{
/* std::string allattribs;
//Atlas::Objects::BaseObjectData::const_iterator I = act->begin( );
std::list< std::string >::const_iterator I = act->getParents( ).begin( );
for ( ; I != act->getParents( ).end( ); ++I )
{
//const Atlas::Message::Element e = ( const Atlas::Message::Element )( *I ).second;
allattribs.append( ( *I ) + " : " );
}*/
const std::list<std::string> &p = act->getParents( );
std::list<std::string>::const_iterator I = p.begin( );
if ( I != p.end( ) ) {
const std::string& name = *I;
Model::Action* newAction = mModel->getAction( name );
///If there's no action found, try to see if we have a "default action" defined to play instead.
if ( !newAction ) {
newAction = mModel->getAction( "default_action" );
}
if ( newAction ) {
MotionManager::getSingleton( ).addAnimatedEntity( this );
mActiveAction = newAction;
newAction->getAnimations( ).reset( );
mCurrentMovementAction->getAnimations( ).reset( );
}
}
EmberEntity::onAction( act );
}
723 bool EmberPhysicalEntity::allowVisibilityOfMember( EmberEntity* entity ) {
return mModel->getDefinition( )->getShowContained( );
}
727 void EmberPhysicalEntity::setVisualize( const std::string& visualization, bool visualize )
{
if ( visualization == "CollisionObject" ) {
if ( getModel( ) ) {
EmberEntityUserObject* userObject = static_cast<EmberEntityUserObject*>( getModel( )->getUserObject( ) );
if ( userObject && userObject->getCollisionDetector( ) ) {
userObject->getCollisionDetector( )->setVisualize( visualize );
}
}
} else {
EmberEntity::setVisualize( visualization, visualize );
}
}
741 bool EmberPhysicalEntity::getVisualize( const std::string& visualization ) const
{
if ( visualization == "CollisionObject" ) {
if ( getModel( ) ) {
EmberEntityUserObject* userObject = static_cast<EmberEntityUserObject*>( getModel( )->getUserObject( ) );
if ( userObject && userObject->getCollisionDetector( ) ) {
return userObject->getCollisionDetector( )->getVisualize( );
}
}
return false;
} else {
return EmberEntity::getVisualize( visualization );
}
}
/*
void EmberPhysicalEntity::handleTalk( const std::string &msg )
{
std::string message = "<";
message.append( getName( ) );
message.append( "> " );
message.append( msg );
std::cout << "TRACE - ENTITY SAYS: [" << message << "]\n" << std::endl;
Ember::ConsoleBackend::getMainConsole( )->pushMessage( message );
}
*/
/*
void EmberPhysicalEntity::setContainer( Entity *pr )
{
EmberEntity* EmberEntity = dynamic_cast<EmberEntity*>( pr );
if ( EmberEntity ) {
//detach from our current object and add to the new entity
getSceneNode( )->getParent( )->removeChild( getSceneNode( )->getName( ) );
EmberEntity->getSceneNode( )->addChild( getSceneNode( ) );
} else {
//detach from our current object and add to the world
getSceneNode( )->getParent( )->removeChild( getSceneNode( )->getName( ) );
getSceneNode( )->getCreator( )->getRootSceneNode( )->addChild( getSceneNode( ) );
}
}
*/
}
/*
Copyright ( C ) 2004 Erik Hjortsberg
some parts Copyright ( C ) 2004 bad_camel at Ogre3d forums
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef DIMEPHYSICALENTITY_H
#define DIMEPHYSICALENTITY_H
#include "EmberOgrePrerequisites.h"
#include "EmberEntity.h"
namespace EmberOgre {
namespace Model {
31 class Model;
32 class Action;
namespace Mapping {
34 class ModelMapping;
}
};
40 class EmberEntity;
typedef std::list<Model::Action*> ActionStore;
/**
* Represents a Ember entity with a physical representation in the world.
* This is represented by a an Ogre::Entity.
*/
48 class EmberPhysicalEntity : public EmberEntity
{
50 friend class EmberEntityModelAction;
51 friend class EmberEntityPartAction;
public:
static const char * const ACTION_STAND;
55 static const char * const ACTION_RUN;
56 static const char * const ACTION_WALK;
57 static const char * const ACTION_SWIM;
58 static const char * const ACTION_FLOAT;
EmberPhysicalEntity( const std::string& id, Eris::TypeInfo* ty, Eris::View* vw, Ogre::SceneManager* sceneManager );
virtual ~EmberPhysicalEntity( );
/**
* return the Model of this object
*/
Model::Model* getModel( ) const;
inline Ogre::SceneNode* getScaleNode( ) const;
virtual void setVisible( bool visible );
virtual void attachToPointOnModel( const std::string& point, Model::Model* model );
virtual void detachFromModel( );
virtual void updateMotion( Ogre::Real timeSlice );
void updateAnimation( Ogre::Real timeSlice );
virtual void showOgreBoundingBox( bool show );
// virtual void showErisBoundingBox( bool show );
virtual bool getShowOgreBoundingBox( ) const;
// virtual bool getShowErisBoundingBox( );
/**
* Returns the entity that's attched to the specified point, if there is such
* @param attachPoint
* @return a pointer to the EmberEntity, or 0 if none found
*/
EmberEntity* getEntityAttachedToPoint( const std::string& attachPoint );
virtual const Ogre::AxisAlignedBox& getWorldBoundingBox( bool derive = true ) const;
virtual const Ogre::Sphere & getWorldBoundingSphere ( bool derive=true ) const;
/**
* Called by a contained member to see if the member is allowed to be shown.
* This can be reimplemented in a subclass such as AvatarEmberEntity to
* disallow things that belongs to a characters inventory to be shown.
*/
virtual bool allowVisibilityOfMember( EmberEntity* entity );
/**
* General method for turning on and off debug visualizations. Subclasses might support more types of visualizations than the ones defined here.
* @param visualization The type of visualization. Currently supports "OgreBBox" and "ErisBBox".
* @param visualize Whether to visualize or not.
*/
virtual void setVisualize( const std::string& visualization, bool visualize );
/**
* Gets whether a certain visualization is turned on or off.
* @param visualization The type of visualization. Currently supports "OgreBBox" and "ErisBBox".
* @return true if visualization is turned on, else false
*/
virtual bool getVisualize( const std::string& visualization ) const;
protected:
void setModel( const std::string& modelName );
void showModelPart( const std::string& partName );
void hideModelPart( const std::string& partName );
virtual const Ogre::Vector3& getOffsetForContainedNode( const Ogre::Vector3& position, EmberEntity* const entity );
/**
* creates EmberEntityUserObjects, connects them and sets up the collision detection system
* @return
*/
void connectEntities( );
void createModelMapping( );
void createScaleNode( );
/**
* Called when the bounding box has changed.
*/
virtual void onBboxChanged( );
/**
* Called when the movement mode has changed. We might want to update the animation of the entity, for example if it's a human.
* @param newMode
*/
virtual void onModeChanged( MovementMode newMode );
/**
The current movement action of the entity, for example a walk action or a run action.
*/
Model::Action* mCurrentMovementAction;
/**
All the active actions, except the movement action ( since it's stored in mCurrentMovementAction ).
These actions will be updated each frame.
NOTE: we currently don't allow for multiple actions playing at the same time
*/
//ActionStore mActiveActions;
Model::Action* mActiveAction;
/**
If the entity is attached to another entity, this is the model to which it is attached to.
This will be 0 if the entity isn't attached.
*/
Model::Model* mModelAttachedTo;
Model::Model* mModelMarkedToAttachTo;
std::string mAttachPointMarkedToAttachTo;
virtual void onChildAdded( Entity *e );
virtual void onChildRemoved( Entity *e );
/**
* Detaches an entity which is already wielded.
* @param entityId
*/
void detachEntity( const std::string & entityId );
/**
* Attaches an entity to a certain attach point
* @param attachPoint the name of the attachpoint to attach to
* @param entityId the id of the entity to attach to
*/
void attachEntity( const std::string & attachPoint, const std::string & entityId );
/**
Detaches all currently attached entities. Call this before the Model is resetted.
*/
void detachAllEntities( );
/**
Attaches all entities that aren't currently attached.
*/
void attachAllEntities( );
/**
* Process wield ops, which means wielding and unwielding entities. This methos will in turn call the appropriate attachEntity and detachEntity methods.
* @param wieldName the attachpoint to update
* @param idElement the id of the entity to wield
*/
void processWield( const std::string& wieldName, const Atlas::Message::Element& idElement );
/**
* Processes the outfit map and updates the appearance.
* @param outfitMap
*/
void processOutfit( const Atlas::Message::MapType & outfitMap );
/**
* Overridden from Eris::Entity
* @param str
* @param v
*/
virtual void onAttrChanged( const std::string& str, const Atlas::Message::Element& v );
/**
* Overridden from Eris::Entity
* @param act
*/
virtual void onAction( const Atlas::Objects::Operation::RootOperation& act );
typedef std::map<std::string, std::string> AttachedEntitiesStore;
/**
A store of all attached entities, indexed by their id.
*/
AttachedEntitiesStore mAttachedEntities;
// virtual void onMoved( );
/**
* Overridden from Eris::Entity
* @param moving
*/
virtual void setMoving( bool moving );
/**
* Overridden from Eris::Entity
* @param ge
*/
virtual void init( const Atlas::Objects::Entity::RootEntity &ge, bool fromCreateOp );
/**
The default size of the ogre bounding box, before any scaling is done.
*/
Ogre::AxisAlignedBox mDefaultOgreBoundingBox;
/**
* Scales the Ogre::SceneNode to the size of the AxisBox defined by Eris::Entity
*/
virtual void scaleNode( );
//void setNodes( );
/**
* The model of the entity
*/
Model::Model* mModel;
/**
* We need to scale the Ogre::Entity, because the underlying media is not
* always correctly scaled.
* But since each Eris::Entity can contain child entites, we'll get problems
* with scaling if we attach the children to a scaled node.
* Thus we use a separate, scaled node.
*/
Ogre::SceneNode* mScaleNode;
void Model_Reloaded( );
void Model_Resetting( );
void initFromModel( );
Model::Mapping::ModelMapping* mModelMapping;
};
Ogre::SceneNode* EmberPhysicalEntity::getScaleNode( ) const
{
return mScaleNode;
}
}
#endif // DIMEPHYSICALENTITY_H
//
// C++ Implementation: EntityWorldPickListener
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "EntityWorldPickListener.h"
#include "EmberOgre.h"
#include "EmberEntityUserObject.h"
#include "model/Model.h"
#include "EmberEntityFactory.h"
#include "EmberEntity.h"
#include "WorldEmberEntity.h"
#include "MousePicker.h"
namespace EmberOgre {
37 EntityWorldPickListenerVisualizer::EntityWorldPickListenerVisualizer( EntityWorldPickListener& pickListener )
: mEntity( 0 ), mDebugNode( 0 )
{
mDebugNode = EmberOgre::getSingleton( ).getSceneManager( )->getRootSceneNode( )->createChildSceneNode( );
Ogre::Entity* mEntity = EmberOgre::getSingleton( ).getSceneManager( )->createEntity( "pickerDebugObject", "fireball.mesh" );
///start out with a normal material
mEntity->setMaterialName( "BasePointMarkerMaterial" );
mEntity->setRenderingDistance( 300 );
mEntity->setQueryFlags( MousePicker::CM_NONPICKABLE );
mDebugNode->attachObject( mEntity );
pickListener.EventPickedEntity.connect( sigc::mem_fun( *this, &EntityWorldPickListenerVisualizer::picker_EventPickedEntity ) );
}
51 EntityWorldPickListenerVisualizer::~EntityWorldPickListenerVisualizer( )
{
EmberOgre::getSingleton( ).getSceneManager( )->destroyEntity( mEntity );
EmberOgre::getSingleton( ).getSceneManager( )->destroySceneNode( mDebugNode->getName( ) );
}
57 void EntityWorldPickListenerVisualizer::picker_EventPickedEntity( const EntityPickResult& result, const MousePickerArgs& mouseArgs )
{
mDebugNode->setPosition( result.position );
}
64 EntityWorldPickListener::EntityWorldPickListener( )
: VisualizePicking( "visualize_picking", this, "Visualize mouse pickings." )
66 , mClosestPickingDistance( 0 )
, mFurthestPickingDistance( 0 )
, mVisualizer( 0 )
{
}
73 EntityWorldPickListener::~EntityWorldPickListener( )
{
}
77 void EntityWorldPickListener::initializePickingContext( )
{
mClosestPickingDistance = 0;
mFurthestPickingDistance = 0;
mResult = EntityPickResult( );
mResult.entity = 0;
mResult.position = Ogre::Vector3::ZERO;
mResult.distance = 0;
}
87 void EntityWorldPickListener::endPickingContext( const MousePickerArgs& mousePickerArgs )
{
if ( mResult.entity ) {
std::stringstream ss;
ss << mResult.position;
S_LOG_VERBOSE( "Picked entity: " << ss.str( ) << " distance: " << mResult.distance );
EventPickedEntity( mResult, mousePickerArgs );
}
}
100 void EntityWorldPickListener::processPickResult( bool& continuePicking, Ogre::RaySceneQueryResultEntry& entry, Ogre::Ray& cameraRay, const MousePickerArgs& mousePickerArgs )
{
if ( entry.worldFragment ) {
///this is terrain
///a position of -1, -1, -1 is not valid terrain
Ogre::SceneQuery::WorldFragment* wf = entry.worldFragment;
static Ogre::Vector3 invalidPos( -1, -1, -1 );
if ( wf->singleIntersection != invalidPos ) {
if ( mFurthestPickingDistance == 0 ) {
mResult.entity = EmberOgre::getSingleton( ).getEntityFactory( )->getWorld( );
mResult.position = wf->singleIntersection;
mResult.distance = entry.distance;
continuePicking = false;
} else {
if ( entry.distance < mResult.distance ) {
mResult.entity = EmberOgre::getSingleton( ).getEntityFactory( )->getWorld( );
mResult.position = wf->singleIntersection;
mResult.distance = entry.distance;
continuePicking = false;
}
}
}
/* std::stringstream ss;
ss << wf->singleIntersection;
S_LOG_VERBOSE( "Picked in terrain: " << ss.str( ) << " distance: " << mResult.distance );*/
} else if ( entry.movable ) {
Ogre::MovableObject* pickedMovable = entry.movable;
if ( pickedMovable->isVisible( ) && pickedMovable->getUserObject( ) != 0 && pickedMovable->getUserObject( )->getTypeName( ) == "EmberEntityPickerObject" ) {
EmberEntityUserObject* anUserObject = static_cast<EmberEntityUserObject*>( pickedMovable->getUserObject( ) );
///refit the opcode mesh to adjust for changes in the mesh ( for example animations )
anUserObject->refit( );
ICollisionDetector* collisionDetector = anUserObject->getCollisionDetector( );
if ( collisionDetector ) {
CollisionResult collisionResult;
collisionResult.collided = false;
collisionDetector->testCollision( cameraRay, collisionResult );
if ( collisionResult.collided ) {
EntityPickResult result;
result.entity = anUserObject->getEmberEntity( );
result.position = collisionResult.position;
result.distance = collisionResult.distance;
if ( mFurthestPickingDistance == 0 ) {
///test all objects that fall into this distance
mFurthestPickingDistance = ( pickedMovable->getParentSceneNode( )->getWorldPosition( ) - cameraRay.getOrigin( ) ).length( ) + pickedMovable->getBoundingRadius( );
mResult = result;
} else {
if ( ( pickedMovable->getParentSceneNode( )->getWorldPosition( ) - cameraRay.getOrigin( ) ).length( ) - pickedMovable->getBoundingRadius( ) > mFurthestPickingDistance ) {
continuePicking = false;
} else {
if ( result.distance < mResult.distance ) {
mResult = result;
}
}
}
}
}
///only do opcode detection if there's a CollisionObject
// for ( EmberEntityUserObject::CollisionObjectStore::iterator I = collisionObjects->begin( ); I != collisionObjects->end( ); ++I ) {
// OgreOpcode::ICollisionShape* collisionShape = ( *I )->getShape( );
// OgreOpcode::CollisionPair pick_result;
//
// if ( collisionShape->rayCheck( OgreOpcode::COLLTYPE_QUICK, anUserObject->getModel( )->_getParentNodeFullTransform( ), cameraRay, 1000, pick_result ) ) {
// EntityPickResult result;
// result.entity = anUserObject->getEmberEntity( );
// result.position = pick_result.contact;
// result.distance = pick_result.distance;
//
// std::stringstream ss;
// ss << result.position;
// S_LOG_VERBOSE( "Picked entity: " << ss.str( ) << " distance: " << result.distance );
// EventPickedEntity( result, mousePickerArgs );
// continuePicking = false;
//
// }
// }
}
}
}
188 void EntityWorldPickListener::runCommand( const std::string &command, const std::string &args )
{
if( VisualizePicking == command ) {
if ( mVisualizer.get( ) ) {
mVisualizer.reset( );
} else {
mVisualizer = std::auto_ptr<EntityWorldPickListenerVisualizer>( new EntityWorldPickListenerVisualizer( *this ) );
}
}
}
}
1 //
// C++ Interface: EntityWorldPickListener
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGREENTITYWORLDPICKLISTENER_H
#define EMBEROGREENTITYWORLDPICKLISTENER_H
#include "EmberOgrePrerequisites.h"
#include "IWorldPickListener.h"
#include <sigc++/signal.h>
#include "framework/ConsoleObject.h"
namespace EmberOgre {
35 class EmberEntity;
36 class EntityWorldPickListener;
/**
* Struct used for returning the result of a mouse pick.
*/
struct EntityPickResult
{
EmberEntity* entity;
Ogre::Vector3 position;
Ogre::Real distance;
};
/**
Visualizes the picking operation by placing a large ball at the picked position.
*/
50 class EntityWorldPickListenerVisualizer : public virtual sigc::trackable
{
public:
53 EntityWorldPickListenerVisualizer( EntityWorldPickListener& pickListener );
54 virtual ~EntityWorldPickListenerVisualizer( );
private:
57 Ogre::Entity* mEntity;
58 Ogre::SceneNode* mDebugNode;
59 void picker_EventPickedEntity( const EntityPickResult& result, const MousePickerArgs& mouseArgs );
};
/**
@author Erik Hjortsberg <erik@katastrof.nu>
*/
65 class EntityWorldPickListener : public IWorldPickListener, public Ember::ConsoleObject
{
public:
68 EntityWorldPickListener( );
70 ~EntityWorldPickListener( );
72 virtual void initializePickingContext( );
74 virtual void endPickingContext( const MousePickerArgs& mousePickerArgs );
77 virtual void processPickResult( bool& continuePicking, Ogre::RaySceneQueryResultEntry& entry, Ogre::Ray& cameraRay, const MousePickerArgs& mousePickerArgs );
79 sigc::signal<void, const EntityPickResult&, const MousePickerArgs&> EventPickedEntity;
81 const Ember::ConsoleCommandWrapper VisualizePicking;
/**
* Reimplements the ConsoleObject::runCommand method
* @param command
* @param args
*/
88 virtual void runCommand( const std::string &command, const std::string &args );
protected:
float mClosestPickingDistance, mFurthestPickingDistance;
EntityPickResult mResult;
94 std::auto_ptr<EntityWorldPickListenerVisualizer> mVisualizer;
};
}
#endif
1 //
// C++ Implementation: FreeCameraController
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2005
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "FreeCameraController.h"
namespace EmberOgre {
27 FreeCameraController::FreeCameraController( )
{
}
32 FreeCameraController::~FreeCameraController( )
{
}
};
1 //
// C++ Interface: FreeCameraController
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2005
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGREFREECAMERACONTROLLER_H
#define EMBEROGREFREECAMERACONTROLLER_H
namespace EmberOgre {
/**
@author Erik Hjortsberg
This is a controller wchich allows for free flight.
*/
33 class FreeCameraController{
public:
35 FreeCameraController( );
37 ~FreeCameraController( );
};
};
#endif
1 //
// C++ Implementation: GUICEGUIAdapter
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2005
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "GUICEGUIAdapter.h"
#include <CEGUIExceptions.h>
#include <CEGUIGlobalEventSet.h>
#include <elements/CEGUIEditbox.h>
#include <elements/CEGUIMultiLineEditbox.h>
namespace EmberOgre {
32 GUICEGUIAdapter::GUICEGUIAdapter( CEGUI::System *system, CEGUI::OgreCEGUIRenderer *renderer ):
mGuiSystem( system )
, mGuiRenderer( renderer )
, mSelectedText( 0 )
{
//lookup table for sdl scancodes and CEGUI keys
mKeyMap[SDLK_BACKSPACE] = CEGUI::Key::Backspace;
mKeyMap[SDLK_TAB] = CEGUI::Key::Tab;
/* mKeyMap[SDLK_CLEAR] = CEGUI::Key::Clear;*/
mKeyMap[SDLK_RETURN] = CEGUI::Key::Return;
mKeyMap[SDLK_PAUSE] = CEGUI::Key::Pause;
mKeyMap[SDLK_ESCAPE] = CEGUI::Key::Escape;
mKeyMap[SDLK_SPACE] = CEGUI::Key::Space;
/* mKeyMap[SDLK_EXCLAIM] = CEGUI::Key::Exclaim;*/
/* mKeyMap[SDLK_QUOTEDBL] = CEGUI::Key::;
mKeyMap[SDLK_HASH] = CEGUI::Key::;
mKeyMap[SDLK_DOLLAR] = CEGUI::Key::;
mKeyMap[SDLK_AMPERSAND] = CEGUI::Key::;
mKeyMap[SDLK_QUOTE] = CEGUI::Key::;
mKeyMap[SDLK_LEFTPAREN] = CEGUI::Key::;
mKeyMap[SDLK_RIGHTPAREN] = CEGUI::Key::;
mKeyMap[SDLK_ASTERISK] = CEGUI::Key::;*/
mKeyMap[SDLK_PLUS] = CEGUI::Key::Add;
/* mKeyMap[SDLK_COMMA] = CEGUI::Key::;*/
mKeyMap[SDLK_MINUS] = CEGUI::Key::Minus;
mKeyMap[SDLK_PERIOD] = CEGUI::Key::Period;
/* mKeyMap[SDLK_SLASH] = CEGUI::Key::;*/
mKeyMap[SDLK_0] = CEGUI::Key::One;
mKeyMap[SDLK_1] = CEGUI::Key::Two;
mKeyMap[SDLK_2] = CEGUI::Key::Two;
mKeyMap[SDLK_3] = CEGUI::Key::Three;
mKeyMap[SDLK_4] = CEGUI::Key::Four;
mKeyMap[SDLK_5] = CEGUI::Key::Five;
mKeyMap[SDLK_6] = CEGUI::Key::Six;
mKeyMap[SDLK_7] = CEGUI::Key::Seven;
mKeyMap[SDLK_8] = CEGUI::Key::Eight;
mKeyMap[SDLK_9] = CEGUI::Key::Nine;
mKeyMap[SDLK_COLON] = CEGUI::Key::Colon;
mKeyMap[SDLK_SEMICOLON] = CEGUI::Key::Semicolon;
/* mKeyMap[SDLK_LESS] = CEGUI::Key::;*/
/* mKeyMap[SDLK_EQUALS] = CEGUI::Key::;
mKeyMap[SDLK_GREATER] = CEGUI::Key::;
mKeyMap[SDLK_QUESTION] = CEGUI::Key::;*/
/* mKeyMap[SDLK_AT] = CEGUI::Key::;*/
/* mKeyMap[SDLK_LEFTBRACKET] = CEGUI::Key::;*/
mKeyMap[SDLK_BACKSLASH] = CEGUI::Key::Backslash;
/* mKeyMap[SDLK_RIGHTBRACKET] = CEGUI::Key::;*/
/* mKeyMap[SDLK_CARET] = CEGUI::Key::;
mKeyMap[SDLK_UNDERSCORE] = CEGUI::Key::;
mKeyMap[SDLK_BACKQUOTE] = CEGUI::Key::;*/
mKeyMap[SDLK_a] = CEGUI::Key::A;
mKeyMap[SDLK_b] = CEGUI::Key::B;
mKeyMap[SDLK_c] = CEGUI::Key::C;
mKeyMap[SDLK_d] = CEGUI::Key::D;
mKeyMap[SDLK_e] = CEGUI::Key::E;
mKeyMap[SDLK_f] = CEGUI::Key::F;
mKeyMap[SDLK_g] = CEGUI::Key::G;
mKeyMap[SDLK_h] = CEGUI::Key::H;
mKeyMap[SDLK_i] = CEGUI::Key::I;
mKeyMap[SDLK_j] = CEGUI::Key::J;
mKeyMap[SDLK_k] = CEGUI::Key::K;
mKeyMap[SDLK_l] = CEGUI::Key::L;
mKeyMap[SDLK_m] = CEGUI::Key::M;
mKeyMap[SDLK_n] = CEGUI::Key::N;
mKeyMap[SDLK_o] = CEGUI::Key::O;
mKeyMap[SDLK_p] = CEGUI::Key::P;
mKeyMap[SDLK_q] = CEGUI::Key::Q;
mKeyMap[SDLK_r] = CEGUI::Key::R;
mKeyMap[SDLK_s] = CEGUI::Key::S;
mKeyMap[SDLK_t] = CEGUI::Key::T;
mKeyMap[SDLK_u] = CEGUI::Key::U;
mKeyMap[SDLK_v] = CEGUI::Key::V;
mKeyMap[SDLK_w] = CEGUI::Key::W;
mKeyMap[SDLK_x] = CEGUI::Key::X;
mKeyMap[SDLK_y] = CEGUI::Key::Y;
mKeyMap[SDLK_z] = CEGUI::Key::Z;
mKeyMap[SDLK_DELETE] = CEGUI::Key::Delete;
mKeyMap[SDLK_UP] = CEGUI::Key::ArrowUp;
mKeyMap[SDLK_DOWN] = CEGUI::Key::ArrowDown;
mKeyMap[SDLK_RIGHT] = CEGUI::Key::ArrowRight;
mKeyMap[SDLK_LEFT] = CEGUI::Key::ArrowLeft;
mKeyMap[SDLK_INSERT] = CEGUI::Key::Insert;
mKeyMap[SDLK_HOME] = CEGUI::Key::Home;
mKeyMap[SDLK_END] = CEGUI::Key::End;
mKeyMap[SDLK_PAGEUP] = CEGUI::Key::PageUp;
mKeyMap[SDLK_PAGEDOWN] = CEGUI::Key::PageDown;
mKeyMap[SDLK_F1] = CEGUI::Key::F1;
mKeyMap[SDLK_F2] = CEGUI::Key::F2;
mKeyMap[SDLK_F3] = CEGUI::Key::F3;
mKeyMap[SDLK_F4] = CEGUI::Key::F4;
mKeyMap[SDLK_F5] = CEGUI::Key::F5;
mKeyMap[SDLK_F6] = CEGUI::Key::F6;
mKeyMap[SDLK_F7] = CEGUI::Key::F7;
mKeyMap[SDLK_F8] = CEGUI::Key::F8;
mKeyMap[SDLK_F9] = CEGUI::Key::F9;
mKeyMap[SDLK_F10] = CEGUI::Key::F10;
mKeyMap[SDLK_F11] = CEGUI::Key::F11;
mKeyMap[SDLK_F12] = CEGUI::Key::F12;
mKeyMap[SDLK_F13] = CEGUI::Key::F13;
mKeyMap[SDLK_F14] = CEGUI::Key::F14;
mKeyMap[SDLK_F15] = CEGUI::Key::F15;
mKeyMap[SDLK_NUMLOCK] = CEGUI::Key::NumLock;
mKeyMap[SDLK_SCROLLOCK] = CEGUI::Key::ScrollLock;
mKeyMap[SDLK_RSHIFT] = CEGUI::Key::RightShift;
mKeyMap[SDLK_LSHIFT] = CEGUI::Key::LeftShift;
mKeyMap[SDLK_RCTRL] = CEGUI::Key::RightControl;
mKeyMap[SDLK_LCTRL] = CEGUI::Key::LeftControl;
mKeyMap[SDLK_RALT] = CEGUI::Key::RightAlt;
mKeyMap[SDLK_LALT] = CEGUI::Key::LeftAlt;
///set up the capturing of text selected event for the copy-and-paste functionality
//window->subscribeEvent( event, CEGUI::Event::Subscriber( &method, this ) );
CEGUI::GlobalEventSet::getSingleton( ).subscribeEvent( "MultiLineEditbox/TextSelectionChanged", CEGUI::Event::Subscriber( &GUICEGUIAdapter::MultiLineEditbox_selectionChangedHandler, this ) );
CEGUI::GlobalEventSet::getSingleton( ).subscribeEvent( "Editbox/TextSelectionChanged", CEGUI::Event::Subscriber( &GUICEGUIAdapter::Editbox_selectionChangedHandler, this ) );
//CEGUI::GlobalEventSet::getSingleton( ).subscribeEvent( "Editbox/TextSelectionChanged", &GUICEGUIAdapter::selectionChangedHandler );
}
157 GUICEGUIAdapter::~GUICEGUIAdapter( )
{
}
161 bool GUICEGUIAdapter::MultiLineEditbox_selectionChangedHandler( const CEGUI::EventArgs& args )
{
CEGUI::MultiLineEditbox* editbox = static_cast<CEGUI::MultiLineEditbox*>( mGuiSystem->getGUISheet( )->getActiveChild( ) );
mSelectedText = &editbox->getText( );
mSelectionStart = editbox->getSelectionStartIndex( );
mSelectionEnd = editbox->getSelectionEndIndex( );
/* const CEGUI::String& text = editbox->getText( );
if ( editbox->getSelectionLength( ) > 0 ) {
std::string selection = text.substr( editbox->getSelectionStartIndex( ), editbox->getSelectionEndIndex( ) ).c_str( );
S_LOG_VERBOSE( "Selected text: " << selection );
}*/
// S_LOG_VERBOSE( "Selected text." );
return true;
}
177 bool GUICEGUIAdapter::Editbox_selectionChangedHandler( const CEGUI::EventArgs& args )
{
CEGUI::Editbox* editbox = static_cast<CEGUI::Editbox*>( mGuiSystem->getGUISheet( )->getActiveChild( ) );
mSelectedText = &editbox->getText( );
mSelectionStart = editbox->getSelectionStartIndex( );
mSelectionEnd = editbox->getSelectionEndIndex( );
S_LOG_VERBOSE( "Selected text." );
return true;
}
// bool GUICEGUIAdapter::selectionChangedHandler( const CEGUI::EventArgs& args )
// {
// S_LOG_VERBOSE( "" );
// }
192 bool GUICEGUIAdapter::injectMouseMove( const MouseMotion& motion, bool& freezeMouse )
{
try {
CEGUI::MouseCursor::getSingleton( ).setPosition( CEGUI::Point( ( motion.xPosition ), ( motion.yPosition ) ) );
mGuiSystem->injectMouseMove( 0.0f, 0.0f );
} catch ( const CEGUI::Exception& ex ) {
S_LOG_WARNING( "Error in CEGUI: " << ex.getMessage( ).c_str( ) );
}
return true;
}
203 bool GUICEGUIAdapter::injectMouseButtonUp( const Input::MouseButton& button )
{
CEGUI::MouseButton ceguiButton;
if ( button == Input::MouseButtonLeft ) {
ceguiButton = CEGUI::LeftButton;
} else if( button == Input::MouseButtonRight ) {
ceguiButton = CEGUI::RightButton;
} else if( button == Input::MouseButtonMiddle ) {
ceguiButton = CEGUI::MiddleButton;
} else {
return true;
}
try {
mGuiSystem->injectMouseButtonUp( ceguiButton );
return false;
} catch ( const CEGUI::Exception& ex ) {
S_LOG_WARNING( "Error in CEGUI: " << ex.getMessage( ).c_str( ) );
} catch ( ... ) {
S_LOG_WARNING( "Unknown error in CEGUI." );
}
return true;
}
227 bool GUICEGUIAdapter::injectMouseButtonDown( const Input::MouseButton& button )
{
CEGUI::MouseButton ceguiButton;
if ( button == Input::MouseButtonLeft ) {
ceguiButton = CEGUI::LeftButton;
} else if( button == Input::MouseButtonRight ) {
ceguiButton = CEGUI::RightButton;
} else if( button == Input::MouseButtonMiddle ) {
ceguiButton = CEGUI::MiddleButton;
} else if( button == Input::MouseWheelDown ) {
try {
mGuiSystem->injectMouseWheelChange( -1.0 );
} catch ( const CEGUI::Exception& ex ) {
S_LOG_WARNING( "Error in CEGUI: " << ex.getMessage( ).c_str( ) );
}
return false;
} else if( button == Input::MouseWheelUp ) {
try {
mGuiSystem->injectMouseWheelChange( 1.0 );
} catch ( const CEGUI::Exception& ex ) {
S_LOG_WARNING( "Error in CEGUI: " << ex.getMessage( ).c_str( ) );
}
return false;
} else {
return true;
}
try {
mGuiSystem->injectMouseButtonDown( ceguiButton );
return false;
} catch ( const CEGUI::Exception& ex ) {
S_LOG_WARNING( "Error in CEGUI: " << ex.getMessage( ).c_str( ) );
}
return true;
}
263 bool GUICEGUIAdapter::injectChar( char character )
{
try {
//cegui can't handle tabs, so we have to convert it to a couple of spaces
if ( character == '\t' ) {
mGuiSystem->injectChar( ' ' );
mGuiSystem->injectChar( ' ' );
mGuiSystem->injectChar( ' ' );
mGuiSystem->injectChar( ' ' );
//can't handle CR either really, insert a line break ( 0x0a ) instead
} else if ( character == '\r' ) {
//mGuiSystem->injectChar( 0x0a );
mGuiSystem->injectKeyDown( CEGUI::Key::Return );
mGuiSystem->injectKeyUp( CEGUI::Key::Return );
} else {
mGuiSystem->injectChar( character );
}
} catch ( const CEGUI::Exception& ex ) {
S_LOG_WARNING( "Error in CEGUI: " << ex.getMessage( ).c_str( ) );
}
return true;
}
287 bool GUICEGUIAdapter::injectKeyDown( const SDLKey& key )
{
try {
mGuiSystem->injectKeyDown( mKeyMap[key] );
} catch ( const CEGUI::Exception& ex ) {
S_LOG_WARNING( "Error in CEGUI: " << ex.getMessage( ).c_str( ) );
}
return true;
}
298 bool GUICEGUIAdapter::injectKeyUp( const SDLKey& key )
{
try {
mGuiSystem->injectKeyUp( mKeyMap[key] );
} catch ( const CEGUI::Exception& ex ) {
S_LOG_WARNING( "Error in CEGUI: " << ex.getMessage( ).c_str( ) );
}
return true;
}
}
1 //
// C++ Interface: GUICEGUIAdapter
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2005
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGREGUICEGUIADAPTER_H
#define EMBEROGREGUICEGUIADAPTER_H
#include "EmberOgrePrerequisites.h"
#include <CEGUISystem.h>
#include <CEGUIEventArgs.h>
#include <CEGUIInputEvent.h>
#include "input/IInputAdapter.h"
#include "input/Input.h"
namespace CEGUI {
36 class System;
37 class OgreCEGUIRenderer;
}
namespace EmberOgre {
43 TYPEDEF_STL_MAP( SDLKey, CEGUI::Key::Scan, SDLKeyMap );
/**
@author Erik Hjortsberg
Provides an adapter between the input system and CEGUI.
*/
50 class GUICEGUIAdapter : public IInputAdapter {
public:
/**
* Creates a new instance.
* @param system A valid CEGUI::System
* @param renderer A valid CEGUI::OgreCEGUIRenderer
* @return
*/
59 GUICEGUIAdapter( CEGUI::System *system, CEGUI::OgreCEGUIRenderer *renderer );
61 ~GUICEGUIAdapter( );
63 virtual bool injectMouseMove( const MouseMotion& motion, bool& freezeMouse );
64 virtual bool injectMouseButtonUp( const Input::MouseButton& button );
65 virtual bool injectMouseButtonDown( const Input::MouseButton& button );
66 virtual bool injectChar( char character );
67 virtual bool injectKeyDown( const SDLKey& key );
68 virtual bool injectKeyUp( const SDLKey& key );
private:
71 CEGUI::System *mGuiSystem;
72 CEGUI::OgreCEGUIRenderer *mGuiRenderer;
/**
mapping of SDL-keys to CEGUI keys
*/
77 SDLKeyMap mKeyMap;
79 bool MultiLineEditbox_selectionChangedHandler( const CEGUI::EventArgs& args );
80 bool Editbox_selectionChangedHandler( const CEGUI::EventArgs& args );
82 const CEGUI::String* mSelectedText;
83 size_t mSelectionStart, mSelectionEnd;
};
}
#endif
/*
Copyright ( C ) 2004 Miguel Guzman ( Aganor )
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "GUIManager.h"
#include "services/EmberServices.h"
#include "services/config/ConfigService.h"
#include "services/scripting/ScriptingService.h"
#include <CEGUIWindowManager.h>
#include <CEGUISchemeManager.h>
#include <CEGUIExceptions.h>
#include <CEGUIFactoryModule.h>
#include <elements/CEGUIPushButton.h>
#include <elements/CEGUIGUISheet.h>
#include <elements/CEGUIMultiLineEditbox.h>
#include <elements/CEGUIEditbox.h>
#include "widgets/Widget.h"
#include "MousePicker.h"
#include "AvatarCamera.h"
#include "EmberOgre.h"
#include "input/Input.h"
#include "gui/ActiveWidgetHandler.h"
#include "widgets/WidgetDefinitions.h"
#include "EmberEntity.h"
#include "EmberPhysicalEntity.h"
#include "AvatarEmberEntity.h"
#include "framework/IScriptingProvider.h"
#include "components/ogre/scripting/LuaScriptingProvider.h"
#include "GUICEGUIAdapter.h"
#include "widgets/icons/IconManager.h"
#include "widgets/EntityIconManager.h"
#ifdef __WIN32__
#include <windows.h>
#include <direct.h>
#endif
#include "EntityWorldPickListener.h"
template<> EmberOgre::GUIManager* Ember::Singleton<EmberOgre::GUIManager>::ms_Singleton = 0;
using namespace CEGUI;
using namespace EmberOgre::Gui;
namespace EmberOgre {
72 unsigned long GUIManager::msAutoGenId( 0 );
75 GUIManager::GUIManager( Ogre::RenderWindow* window, Ogre::SceneManager* sceneMgr )
: ToggleInputMode( "toggle_inputmode", this, "Toggle the input mode." )
77 , ReloadGui( "reloadgui", this, "Reloads the gui." )
, mGuiCommandMapper( "gui", "key_bindings_gui" )
, mPicker( 0 )
, mEntityWorldPickListener( 0 )
, mSheet( 0 )
, mWindowManager( 0 )
, mDebugText( 0 )
, mWindow( window )
, mGuiSystem( 0 )
, mGuiRenderer( 0 )
, mLuaScriptModule( 0 )
, mIconManager( 0 )
, mActiveWidgetHandler( 0 )
{
mGuiCommandMapper.restrictToInputMode( Input::IM_GUI );
///we need this here just to force the linker to also link in the WidgetDefinitions
WidgetDefinitions w;
try {
S_LOG_INFO( "Starting CEGUI" );
mDefaultScheme = "EmberLook";
S_LOG_VERBOSE( "Setting default scheme to "<< mDefaultScheme );
Ember::ConfigService* configSrv = Ember::EmberServices::getSingletonPtr( )->getConfigService( );
if ( chdir( configSrv->getEmberDataDirectory( ).c_str( ) ) ) {
S_LOG_WARNING( "Failed to change to the data directory. Gui loading might fail." );
}
//use a macro from CEGUIFactoryModule
//DYNLIB_LOAD( "libCEGUIFalagardBase.so" );
mGuiRenderer = new CEGUI::OgreCEGUIRenderer( window, Ogre::RENDER_QUEUE_OVERLAY, false, 0, sceneMgr );
// mScriptManager = new GUIScriptManager( );
CEGUI::ResourceProvider* resourceProvider = mGuiRenderer->createResourceProvider( );
resourceProvider->setDefaultResourceGroup( "Gui" );
Ember::IScriptingProvider* provider;
provider = Ember::EmberServices::getSingleton( ).getScriptingService( )->getProviderFor( "LuaScriptingProvider" );
if ( provider != 0 ) {
LuaScriptingProvider* luaScriptProvider = static_cast<LuaScriptingProvider*>( provider );
mLuaScriptModule = new LuaScriptModule( luaScriptProvider->getLuaState( ) );
mGuiSystem = new CEGUI::System( mGuiRenderer, resourceProvider, 0, mLuaScriptModule, "cegui/datafiles/configs/cegui.config" );
Ember::EmberServices::getSingleton( ).getScriptingService( )->EventStopping.connect( sigc::mem_fun( *this, &GUIManager::scriptingServiceStopping ) );
} else {
mGuiSystem = new CEGUI::System( mGuiRenderer, resourceProvider, 0, 0, "cegui/datafiles/configs/cegui.config" );
}
mWindowManager = &CEGUI::WindowManager::getSingleton( );
try {
mGuiSystem->setDefaultMouseCursor( getDefaultScheme( ), "MouseArrow" );
} catch ( const CEGUI::Exception& ex ) {
S_LOG_FAILURE( "CEGUI - could not set mouse pointer. Make sure that the correct scheme " << getDefaultScheme( ) << " is available. Message: " << ex.getMessage( ).c_str( ) );
throw Ember::Exception( ex.getMessage( ).c_str( ) );
}
mSheet = mWindowManager->createWindow( ( CEGUI::utf8* )"DefaultGUISheet", ( CEGUI::utf8* )"root_wnd" );
mGuiSystem->setGUISheet( mSheet );
mSheet->activate( );
mSheet->moveToBack( );
mSheet->setDistributesCapturedInputs( false );
BIND_CEGUI_EVENT( mSheet, CEGUI::ButtonBase::EventMouseButtonDown, GUIManager::mSheet_MouseButtonDown );
BIND_CEGUI_EVENT( mSheet, CEGUI::Window::EventInputCaptureLost, GUIManager::mSheet_CaptureLost );
BIND_CEGUI_EVENT( mSheet, CEGUI::ButtonBase::EventMouseDoubleClick, GUIManager::mSheet_MouseDoubleClick );
//set a default tool tip
CEGUI::System::getSingleton( ).setDefaultTooltip( getDefaultScheme( ) + "/Tooltip" );
S_LOG_INFO( "CEGUI system set up" );
mPicker = new MousePicker( );
///create a new entity world pick listener which listens for event
///TODO: should this really be here?
mEntityWorldPickListener = new EntityWorldPickListener( );
///don't connect it yet since there's no AvatarCamera yet, wait until that's created
EmberOgre::getSingleton( ).EventAvatarControllerCreated.connect( sigc::mem_fun( *this, &GUIManager::EmberOgre_AvatarControllerCreated ) );
getInput( ).EventKeyPressed.connect( sigc::mem_fun( *this, &GUIManager::pressedKey ) );
getInput( ).setInputMode( Input::IM_GUI );
///add adapter for CEGUI
mCEGUIAdapter = new GUICEGUIAdapter( mGuiSystem, mGuiRenderer );
getInput( ).addAdapter( mCEGUIAdapter );
mGuiCommandMapper.bindToInput( getInput( ) );
///connect to the creation of the avatar, since we want to switch to movement mode when that happens
EmberOgre::getSingleton( ).EventCreatedAvatarEntity.connect( sigc::mem_fun( *this, &GUIManager::EmberOgre_CreatedAvatarEntity ) );
mActiveWidgetHandler = new Gui::ActiveWidgetHandler( *this );
Ogre::Root::getSingleton( ).addFrameListener( this );
} catch ( const CEGUI::Exception& ex ) {
S_LOG_FAILURE( "GUIManager - error when creating gui. Message: " << ex.getMessage( ).c_str( ) );
throw Ember::Exception( ex.getMessage( ).c_str( ) );
}
}
191 GUIManager::~GUIManager( )
{
S_LOG_INFO( "Shutting down GUI manager." );
WidgetStore widgetStoreCopy( mWidgets );
for ( WidgetStore::iterator I = widgetStoreCopy.begin( ); I != widgetStoreCopy.end( ); ++I ) {
S_LOG_INFO( "Deleting widget " << ( *I )->getPrefix( ) << "." );
delete *I;
}
delete mActiveWidgetHandler;
delete mEntityIconManager;
delete mIconManager;
delete mGuiSystem;
Ogre::Root::getSingleton( ).removeFrameListener( this );
delete mCEGUIAdapter;
delete mEntityWorldPickListener;
delete mPicker;
delete mGuiRenderer;
delete mLuaScriptModule;
//delete mMousePicker;
//mMousePicker = 0;
}
218 void GUIManager::initialize( )
{
Ember::ConfigService* configSrv = Ember::EmberServices::getSingletonPtr( )->getConfigService( );
chdir( configSrv->getEmberDataDirectory( ).c_str( ) );
try {
mDebugText = ( CEGUI::GUISheet* )mWindowManager->createWindow( "DefaultGUISheet", ( CEGUI::utf8* )"DebugText" );
mSheet->addChildWindow( mDebugText );
mDebugText->setMaxSize( CEGUI::UVector2( UDim( 1.0f, 0 ), UDim( 0, 25 ) ) );
mDebugText->setPosition( CEGUI::UVector2( UDim( 0.0f, 0 ), UDim( 1.0f, -25 ) ) );
mDebugText->setSize( CEGUI::UVector2( UDim( 1.0f, 0 ), UDim( 0, 25 ) ) );
/* mDebugText->setFrameEnabled( false );
mDebugText->setBackgroundEnabled( false );*/
//stxt->setHorizontalFormatting( StaticText::WordWrapCentred );
//the console and quit widgets are not lua scripts, and should be loaded explicit
// mConsoleWidget = static_cast<ConsoleWidget*>( createWidget( "ConsoleWidget" ) );
// if ( !mConsoleWidget ) {
// throw Ember::Exception( "Could not create console widget." );
// }
createWidget( "Quit" );
} catch ( const std::exception& e ) {
S_LOG_FAILURE( "GUIManager - error when initializing widgets: " << e.what( ) );
throw e;
} catch ( const CEGUI::Exception& e ) {
S_LOG_FAILURE( "GUIManager - error when initializing widgets: " << e.getMessage( ).c_str( ) );
throw e;
}
try {
mIconManager = new Gui::Icons::IconManager( );
} catch ( const std::exception& e ) {
S_LOG_FAILURE( "GUIManager - error when creating icon manager: " << e.what( ) );
} catch ( const CEGUI::Exception& e ) {
S_LOG_FAILURE( "GUIManager - error when creating icon manager: " << e.getMessage( ).c_str( ) );
}
try {
mEntityIconManager = new Gui::EntityIconManager( *this );
} catch ( const std::exception& e ) {
S_LOG_FAILURE( "GUIManager - error when creating entity icon manager: " << e.what( ) );
} catch ( const CEGUI::Exception& e ) {
S_LOG_FAILURE( "GUIManager - error when creating entity icon manager: " << e.getMessage( ).c_str( ) );
}
std::vector<std::string> widgetsToLoad;
widgetsToLoad.push_back( "StatusIconBar" );
widgetsToLoad.push_back( "IngameChatWidget" );
// widgetsToLoad.push_back( "InventoryWidget" );
widgetsToLoad.push_back( "InspectWidget" );
widgetsToLoad.push_back( "MakeEntityWidget" );
widgetsToLoad.push_back( "JesusEdit" );
widgetsToLoad.push_back( "ServerWidget" );
widgetsToLoad.push_back( "Help" );
widgetsToLoad.push_back( "MeshPreview" );
///this should be defined in some kind of text file, which should be different depending on what game you're playing ( like mason )
try {
///load the bootstrap script which will load all other scripts
Ember::EmberServices::getSingleton( ).getScriptingService( )->loadScript( "lua/Bootstrap.lua" );
} catch ( const std::exception& e ) {
S_LOG_FAILURE( "Error when loading bootstrap script. Error message: " << e.what( ) );
} catch ( const CEGUI::Exception& e ) {
S_LOG_FAILURE( "Error when loading bootstrap script. Error message: " << e.getMessage( ).c_str( ) );
}
for ( std::vector<std::string>::iterator I = widgetsToLoad.begin( ); I != widgetsToLoad.end( ); ++I ) {
try {
S_LOG_VERBOSE( "Loading widget " << *I );
createWidget( *I );
} catch ( const std::exception& e ) {
S_LOG_FAILURE( "Error when initializing widget " << *I << " : " << e.what( ) );
} catch ( const CEGUI::Exception& e ) {
S_LOG_FAILURE( "Error when initializing widget " << *I << " : " << e.getMessage( ).c_str( ) );
}
}
}
298 void GUIManager::scriptingServiceStopping( )
{
mGuiSystem->setScriptingModule( 0 );
delete mLuaScriptModule;
mLuaScriptModule = 0;
}
305 void GUIManager::EmitEntityAction( const std::string& action, EmberEntity* entity )
{
EventEntityAction.emit( action, entity );
}
311 CEGUI::Window* GUIManager::createWindow( const std::string& windowType )
{
std::stringstream ss;
ss << "_autoWindow_" << ( msAutoGenId++ );
return createWindow( windowType, ss.str( ) );
}
318 CEGUI::Window* GUIManager::createWindow( const std::string& windowType, const std::string& windowName )
{
try {
CEGUI::Window* window = mWindowManager->createWindow( windowType, windowName );
return window;
} catch ( const CEGUI::Exception& ex ) {
S_LOG_FAILURE( "Error when creating new window of type " << windowType << " with name " << windowName << ".\n" << ex.getMessage( ).c_str( ) );
return 0;
} catch ( const std::exception& ex ) {
S_LOG_FAILURE( "Error when creating new window of type " << windowType << " with name " << windowName << ".\n" << ex.what( ) );
return 0;
}
}
332 Widget* GUIManager::createWidget( )
{
return createWidget( "Widget" );
}
337 Widget* GUIManager::createWidget( const std::string& name )
{
Widget* widget( 0 );
try {
widget = WidgetLoader::createWidget( name );
if ( widget == 0 ) {
S_LOG_FAILURE( "Could not find widget with name " << name );
return 0;
}
widget->init( this );
widget->buildWidget( );
addWidget( widget );
S_LOG_INFO( "Successfully loaded widget " << name );
} catch ( const std::exception& e ) {
S_LOG_FAILURE( "Error when loading widget " << name << ": " << e.what( ) );
return 0;
} catch ( const CEGUI::Exception& e ) {
S_LOG_FAILURE( "Error when loading widget " << name << ": " << e.getMessage( ).c_str( ) );
return 0;
}
return widget;
}
361 void GUIManager::destroyWidget( Widget* widget )
{
if ( !widget )
{
S_LOG_WARNING( "Trying to destroy null widget." );
return;
}
removeWidget( widget );
delete widget;
}
373 void GUIManager::setDebugText( const std::string& text )
{
if ( mDebugText )
{
mDebugText->setText( text );
}
}
381 Input& GUIManager::getInput( ) const
{
return Input::getSingleton( );
}
387 CEGUI::Window* GUIManager::getMainSheet( ) const
{
return mSheet;
}
392 void GUIManager::removeWidget( Widget* widget )
{
WidgetStore::iterator I = std::find( mWidgets.begin( ), mWidgets.end( ), widget );
if ( I != mWidgets.end( ) ) {
mWidgets.erase( I );
}
}
400 void GUIManager::addWidget( Widget* widget )
{
mWidgets.push_back( widget );
}
410 bool GUIManager::frameStarted( const Ogre::FrameEvent& evt )
{
try {
CEGUI::System::getSingleton( ).injectTimePulse( evt.timeSinceLastFrame );
} catch ( const CEGUI::Exception& ex ) {
S_LOG_WARNING( "Error in CEGUI: " << ex.getMessage( ).c_str( ) );
}
// if ( mPreviousInputMode == IM_GUI ) {
// if ( !mInput->getInputMode( ) ) {
// EventInputModeChanged.emit( IM_MOVEMENT );
// mPreviousInputMode = IM_MOVEMENT;
// }
// } else {
// if ( mInput->isInGUIMode( ) ) {
// EventInputModeChanged.emit( IM_GUI );
// mPreviousInputMode = IM_GUI;
// }
// }
//iterate over all widgets and send them a frameStarted event
WidgetStore::iterator I = mWidgets.begin( );
WidgetStore::iterator I_end = mWidgets.end( );
for ( ; I != I_end; ++I ) {
Widget* aWidget = *I;
try {
aWidget->frameStarted( evt );
} catch ( const CEGUI::Exception& ex ) {
S_LOG_WARNING( "Error in CEGUI: " << ex.getMessage( ).c_str( ) );
}
}
EventFrameStarted.emit( evt.timeSinceLastFrame );
return true;
}
451 bool GUIManager::mSheet_MouseButtonDown( const CEGUI::EventArgs& args )
{
if ( isInGUIMode( ) ) {
const CEGUI::MouseEventArgs& mouseArgs = static_cast<const CEGUI::MouseEventArgs&>( args );
S_LOG_VERBOSE( "Main sheet is capturing input" );
CEGUI::Window* aWindow = CEGUI::Window::getCaptureWindow( );
if ( aWindow ) {
aWindow->releaseInput( );
aWindow->deactivate( );
}
//mSheet->activate( );
//mSheet->captureInput( );
if ( mPicker ) {
const CEGUI::Point& position = CEGUI::MouseCursor::getSingleton( ).getDisplayIndependantPosition( );
MousePickerArgs pickerArgs;
pickerArgs.windowX = mouseArgs.position.d_x;
pickerArgs.windowY = mouseArgs.position.d_y;
pickerArgs.pickType = MPT_CLICK;
mPicker->doMousePicking( position.d_x, position.d_y, pickerArgs );
}
}
return true;
}
478 bool GUIManager::mSheet_MouseDoubleClick( const CEGUI::EventArgs& args )
{
const CEGUI::MouseEventArgs& mouseArgs = static_cast<const CEGUI::MouseEventArgs&>( args );
S_LOG_VERBOSE( "Main sheet double click." );
CEGUI::Window* aWindow = CEGUI::Window::getCaptureWindow( );
if ( aWindow ) {
aWindow->releaseInput( );
aWindow->deactivate( );
}
//mSheet->activate( );
//mSheet->captureInput( );
if ( mPicker ) {
const CEGUI::Point& position = CEGUI::MouseCursor::getSingleton( ).getDisplayIndependantPosition( );
MousePickerArgs pickerArgs;
pickerArgs.windowX = mouseArgs.position.d_x;
pickerArgs.windowY = mouseArgs.position.d_y;
pickerArgs.pickType = MPT_DOUBLECLICK;
mPicker->doMousePicking( position.d_x, position.d_y, pickerArgs );
}
return true;
}
504 bool GUIManager::mSheet_CaptureLost( const CEGUI::EventArgs& args )
{
S_LOG_VERBOSE( "Main sheet lost input" );
return true;
}
510 const bool GUIManager::isInMovementKeysMode( ) const {
return mSheet->isCapturedByThis( ) || !isInGUIMode( );
}
514 const bool GUIManager::isInGUIMode( ) const {
return getInput( ).getInputMode( ) == Input::IM_GUI;
}
518 void GUIManager::pressedKey( const SDL_keysym& key, Input::InputMode inputMode )
{
if ( ( key.mod & KMOD_CTRL || key.mod & KMOD_LCTRL || key.mod & KMOD_RCTRL ) && ( key.sym == SDLK_c || key.sym == SDLK_x ) ) {
bool cut = ( key.sym == SDLK_x );
CEGUI::Window* active = mSheet->getActiveChild( );
if ( !active ) return;
CEGUI::String seltext;
const CEGUI::String& type = active->getType( );
if ( type.find( "/MultiLineEditbox" ) != CEGUI::String::npos ) {
CEGUI::MultiLineEditbox* edit = static_cast<CEGUI::MultiLineEditbox*>( active );
CEGUI::String::size_type beg = edit->getSelectionStartIndex( );
CEGUI::String::size_type len = edit->getSelectionLength( );
seltext = edit->getText( ).substr( beg, len ).c_str( );
// are we cutting or just copying?
if ( cut ) {
if ( edit->isReadOnly( ) ) return;
CEGUI::String newtext = edit->getText( );
edit->setText( newtext.erase( beg, len ) );
}
} else if ( type.find( "/Editbox" ) != CEGUI::String::npos ) {
CEGUI::Editbox* edit = static_cast<CEGUI::Editbox*>( active );
CEGUI::String::size_type beg = edit->getSelectionStartIndex( );
CEGUI::String::size_type len = edit->getSelectionLength( );
seltext = edit->getText( ).substr( beg, len ).c_str( );
// are we cutting or just copying?
if ( cut ) {
if ( edit->isReadOnly( ) ) return;
CEGUI::String newtext = edit->getText( );
edit->setText( newtext.erase( beg, len ) );
}
}
getInput( ).writeToClipboard( seltext.c_str( ) );
}
}
561 void GUIManager::runCommand( const std::string &command, const std::string &args )
{
if ( command == ToggleInputMode.getCommand( ) ) {
getInput( ).toggleInputMode( );
} else if ( command == ReloadGui.getCommand( ) ) {
Ogre::TextureManager* texMgr = Ogre::TextureManager::getSingletonPtr( );
Ogre::ResourcePtr resource = texMgr->getByName( "cegui/" + getDefaultScheme( ) + ".png" );
if ( !resource.isNull( ) ) {
resource->reload( );
}
}
}
// void GUIManager::pushMousePicker( MousePicker * mousePicker )
// {
// mMousePickers.push( mousePicker );
// }
// MousePicker * GUIManager::popMousePicker( )
// {
// ///only pop if there's more than one registered picker
// if ( mMousePickers.size( ) > 1 )
// mMousePickers.pop( );
// return mMousePickers.top( );
// }
587 void GUIManager::EmberOgre_CreatedAvatarEntity( AvatarEmberEntity* entity )
{
///switch to movement mode, since it appears most people don't know how to change from gui mode
getInput( ).setInputMode( Input::IM_MOVEMENT );
}
593 void GUIManager::EmberOgre_AvatarControllerCreated( AvatarController& controller )
{
EmberOgre::getSingleton( ).getMainCamera( )->pushWorldPickListener( mEntityWorldPickListener );
}
598 const std::string& GUIManager::getLayoutDir( ) const
{
static std::string dir( "cegui/datafiles/layouts/" );
return dir;
}
604 const std::string& GUIManager::getDefaultScheme( ) const
{
return mDefaultScheme;
}
609 EntityWorldPickListener* GUIManager::getEntityPickListener( ) const
{
return mEntityWorldPickListener;
}
614 Gui::Icons::IconManager* GUIManager::getIconManager( )
{
return mIconManager;
}
619 Gui::EntityIconManager* GUIManager::getEntityIconManager( )
{
return mEntityIconManager;
}
}
1 /*
Copyright ( C ) 2004 Miguel Guzman ( Aglanor )
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef GUIMANAGER_H
#define GUIMANAGER_H
#include "EmberOgrePrerequisites.h"
#include <CEGUIBase.h>
#include <OgreCEGUIRenderer.h>
#include <sigc++/trackable.h>
#include "framework/Singleton.h"
#include <SDL.h>
#include <stack>
#include "framework/ConsoleObject.h"
#include "input/Input.h"
#include "input/InputCommandMapper.h"
namespace CEGUI
{
42 class GUISheet;
43 class LuaScriptModule;
}
namespace Ember {
47 class IScriptingProvider;
}
50 namespace EmberOgre {
class EmberEntity;
class TerrainGenerator;
class CEGUI::Window;
class MousePicker;
class Input;
class AvatarEmberEntity;
class GUICEGUIAdapter;
class EntityWorldPickListener;
class AvatarController;
namespace Gui {
class Widget;
class EntityIconManager;
class ActiveWidgetHandler;
namespace Icons {
class IconManager;
}
}
/**
* This class will be responsible for all the GUI related things
*/
class GUIManager :
public Ember::Singleton<GUIManager>,
Ogre::FrameListener,
public sigc::trackable,
public Ember::ConsoleObject
{
public:
typedef std::vector<Gui::Widget*> WidgetStore;
static const std::string SCREENSHOT;
static const std::string TOGGLEINPUTMODE;
GUIManager( Ogre::RenderWindow* window, Ogre::SceneManager* sceneMgr );
virtual ~GUIManager( );
sigc::signal<void, const std::string&, EmberEntity*> AppendIGChatLine;
sigc::signal<void, const std::string&, EmberEntity*> AppendOOGChatLine;
sigc::signal<void, const std::string&> AppendAvatarImaginary;
sigc::signal<void, const std::string&, EmberEntity*> EventEntityAction;
/**
Emitted every frame.
*/
sigc::signal<void, float> EventFrameStarted;
/**
* Emits an action for a certain entity.
* An action could be something like "touch" or "inspect".
* @param action
*/
void EmitEntityAction( const std::string& action, EmberEntity* entity );
/**
* Removed a widget from the system.
* @param widget
*/
void removeWidget( Gui::Widget* widget );
/**
* Adds a new widget to the system. This means it will recieve FrameStarted events.
* @param widget
*/
void addWidget( Gui::Widget* widget );
/**
* Called by Ogre each frame.
* @param evt
* @return
*/
bool frameStarted( const Ogre::FrameEvent& evt );
/**
* Gets the root sheet of the CEGUI windowing system.
* @return
*/
CEGUI::Window* getMainSheet( ) const;
/**
* Called by EmberOgre at initialization.
*/
void initialize( );
/**
* sets a text to be shown somewhere on the screen, used for debugging purposes
* @param text
*/
void setDebugText( const std::string& text );
/**
* true if we're in GUI mode, which means that input events will be sent to the CEGUI system instead of the "world"
* @return
*/
const bool isInGUIMode( ) const;
/**
* true if keyboard input should make the avatar move
* this happens when wither 1 ) we're not in gui mode 2 ) the background sheet has the input control ( thus, when something else, like an edit box has input control, that edit box will recieve key strokes
* @return
*/
const bool isInMovementKeysMode( ) const;
/**
* Gets the currently active MousePicker instance.
* @return
*/
inline MousePicker* getMousePicker( ) { return mMousePickers.top( ); }
/**
* accessor for the Input instance object
* @return
*/
Input& getInput( ) const;
/**
* Pushes a new mouse picker onto the stack, "pushing down" the current mouse picker.
* @param mousePicker
*/
// void pushMousePicker( MousePicker* mousePicker );
/**
* Pops the current mouse picker from the stack and returns the next in line.
* It's not possible to empty the stack. If there's only one picker left, no popping will be done, and the last picker will be returned.
* @return
*/
// MousePicker* popMousePicker( );
inline CEGUI::OgreCEGUIRenderer* getGuiRenderer( ) const {return mGuiRenderer;}
/**
* Reimplements the ConsoleObject::runCommand method
* @param command
* @param args
*/
virtual void runCommand( const std::string &command, const std::string &args );
/**
* returns the path to the directory where all layouts are stored
* @return
*/
const std::string& getLayoutDir( ) const;
/**
Creates a new window of the supplied type, giving it an autogenerated, unique name.
*/
CEGUI::Window* createWindow( const std::string& windowType );
/**
Creates a new window of the supplied type with the supplied name.
*/
CEGUI::Window* createWindow( const std::string& windowType, const std::string& windowName );
/**
* Creates a new Widget
* @return
*/
Gui::Widget* createWidget( );
/**
* creates a widget
* @see WidgetLoader
* @param name the type of widget to create
* @return
*/
Gui::Widget* createWidget( const std::string& name );
/**
* Destroys a widget previously created by createWidget
* @param widget The widget to destroy.
*/
void destroyWidget( Gui::Widget* widget );
/**
* Gets the name of the default scheme used ( such as "EmberLook" or "WindowsLook" )
* @return
*/
const std::string& getDefaultScheme( ) const;
EntityWorldPickListener* getEntityPickListener( ) const;
/**
Command for toggling between the input modes.
*/
const Ember::ConsoleCommandWrapper ToggleInputMode;
/**
Command for reloading the gui.
*/
const Ember::ConsoleCommandWrapper ReloadGui;
/**
* Accessor for the IconManager which handles low level icons.
* @return The main IconManager
*/
Gui::Icons::IconManager* getIconManager( );
/**
* Accessor for the EntityIconManager, which handles entity icons and slots.
* @return The main EntityIconManager
*/
Gui::EntityIconManager* getEntityIconManager( );
protected:
/**
Counter for autonaming of windows.
*/
static unsigned long msAutoGenId;
InputCommandMapper mGuiCommandMapper;
MousePicker* mPicker;
EntityWorldPickListener* mEntityWorldPickListener;
CEGUI::Window* mSheet;
CEGUI::WindowManager* mWindowManager;
CEGUI::GUISheet* mDebugText;
Ogre::RenderWindow* mWindow;
CEGUI::System* mGuiSystem;
CEGUI::OgreCEGUIRenderer* mGuiRenderer;
std::string mDefaultScheme;
/**
all loaded widgets are stored here
*/
WidgetStore mWidgets;
/**
A stack of the mouse pickers used. This allows for a component to "push down" the current mouse picker in favor of its own
*/
std::stack<MousePicker*> mMousePickers;
//events
bool mSheet_MouseButtonDown( const CEGUI::EventArgs& args );
bool mSheet_MouseDoubleClick( const CEGUI::EventArgs& args );
bool mSheet_CaptureLost( const CEGUI::EventArgs& args );
/**
* hooked to EmberOgre::EventCreatedAvatarEntity, switches the input mode to movement mode
* @param entity
*/
void EmberOgre_CreatedAvatarEntity( AvatarEmberEntity* entity );
/**
* hooked to EmberOgre::EventAvatarControllerCreated, connects the mEntityWorldPickListener to the main AvatarCamera
* @param controller
*/
void EmberOgre_AvatarControllerCreated( AvatarController& controller );
// InputMode mPreviousInputMode;
void pressedKey( const SDL_keysym& key, Input::InputMode inputMode );
/**
Adapter for CEGUI which will send input events to CEGUI
*/
GUICEGUIAdapter* mCEGUIAdapter;
CEGUI::LuaScriptModule* mLuaScriptModule;
void scriptingServiceStopping( );
Gui::Icons::IconManager* mIconManager;
Gui::EntityIconManager* mEntityIconManager;
Gui::ActiveWidgetHandler* mActiveWidgetHandler;
};
}
#endif
1 //
// C++ Interface: IWorldPickListener
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGREIWORLDPICKLISTENER_H
#define EMBEROGREIWORLDPICKLISTENER_H
#include "EmberOgrePrerequisites.h"
namespace EmberOgre {
/**
@author Erik Hjortsberg <erik@katastrof.nu>
*/
/**
The kind of mouse click operation.
*/
enum MousePickType
{
///Simple click
MPT_CLICK = 1,
///Double click
MPT_DOUBLECLICK = 2
};
/**
Mouse picking info from the windowing system.
*/
struct MousePickerArgs
{
/**
The x and y coords in local window space.
*/
float windowX, windowY;
MousePickType pickType;
};
60 class IWorldPickListener
{
public:
64 virtual ~IWorldPickListener( ) {}
/**
Called at the start of a picking context. This allows the pickers to be reset and to keep state for each picking.
*/
69 virtual void initializePickingContext( ) {}
/**
Called when the picking is over, either because one of the processPickResult calls set continuePicking to false, or because there are no more objects to pick.
*/
74 virtual void endPickingContext( const MousePickerArgs& mousePickerArgs ) {}
/**
* Processes the pick result.
* This will be called for each picked object.
* @param continuePicking set this to false if you don't want to process any more pick results, or don't want any other IWorldPickListener to process the pick any more
* @param entry The actual pick entry.
* @param cameraRay The ray which resulted in the pick.
* @param mousePickerArgs The original mouse picker arguments.
*/
84 virtual void processPickResult( bool& continuePicking, Ogre::RaySceneQueryResultEntry& entry, Ogre::Ray& cameraRay, const MousePickerArgs& mousePickerArgs ) = 0;
};
}
#endif
1 /*
-----------------------------------------------------------------------------
MathConverter.h by Miguel Guzman Miranda ( Aglanor )
Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2005
Copyright © 2003 The Worldforge Project ( http://www.worldforge.org )
This file is part of Ember client ( http://www.worldforge.org/dev/eng/clients/Ember )
This code is distributed under the GNU GPL ( General Public License ).
See file COPYING for details.
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
Filename: MathConverter.h
Description: Point, Vector and Quaternion converter
for world-centric coordinates ( Atlas-wfmath like )
to/from screen-centric coordinates ( Ogre like ).
Atlas is World-centric ( picture a map ):
x is east
y is north
z is up
Ogre is screen-centric ( picture your monitor screen ):
x is right
y is up
z is depth ( negative towards the screen,
positive is towards you,
so the coord system is also dextrogyrous )
--------------------------------------------------------
Example of Atlas --> Ogre conversion
Picture this is the world map, in both cases:
^ North
|
| East
( Up )--->
Atlas Ogre
^ a.y ^ -o.z
| |
| a.x | o.x
( a.z )---> ( o.y )--->
--------------------------------------------------------
Example of Ogre --> Atlas conversion
Picture this is your computer screen, in both cases:
^ Up
|
| Left
( You )--->
Ogre Atlas
^ o.y ^ a.z
| |
| o.x | a.x
( o.z )---> ( -a.y )--->
The math is:
Atlas.x = Ogre.x
Atlas.y = -Ogre.z
Atlas.z = Ogre.y
Ogre.x = Atlas.x
Ogre.y = Atlas.z
Ogre.z = -Atlas.y
-----------------------------------------------------------------------------
*/
#ifndef __MATH_CONVERTER_H__
#define __MATH_CONVERTER_H__
// ------------------------------
// Include WFmath header files
// ------------------------------
#include <wfmath/point.h>
#include <wfmath/vector.h>
#include <wfmath/axisbox.h>
#include <wfmath/quaternion.h>
#include <wfmath/const.h>
#include <math.h>
namespace EmberOgre {
typedef WFMath::Point<2> TerrainPosition;
// //note that this will ignore the y value of the supplied ogre vector
// inline TerrainPosition Ogre2Atlas( Ogre::Vector3& p ) {
// return WFMath::Point<2>( p.x, -p.z );
// }
/*inline Ogre::Vector3 Atlas2Ogre( TerrainPosition& p ) {
return Ogre::Vector3( p.x( ), 0, -p.y( ) );
}*/
104 inline Ogre::Vector3 Atlas2Ogre( const TerrainPosition& p ) {
return Ogre::Vector3( p.x( ), 0, -p.y( ) );
}
108 inline Ogre::Vector2 Atlas2Ogre_Vector2( const TerrainPosition& p ) {
return Ogre::Vector2( p.x( ), -p.y( ) );
}
// inline WFMath::Point<3> Ogre2Atlas( Ogre::Vector3& p ) {
// return WFMath::Point<3>( p.x, -p.z, p.y );
// }
/*inline WFMath::Vector<3> Ogre2Atlas_Vector3( Ogre::Vector3& p ) {
return WFMath::Vector<3>( p.x, -p.z, p.y );
}*/
119 inline WFMath::Point<3> Ogre2Atlas( const Ogre::Vector3& p ) {
return WFMath::Point<3>( p.x, -p.z, p.y );
}
123 inline TerrainPosition Ogre2Atlas( const Ogre::Vector2& p ) {
return TerrainPosition( p.x, -p.y );
}
127 inline TerrainPosition Ogre2Atlas_TerrainPosition( const Ogre::Vector3& p ) {
return TerrainPosition( p.x, -p.z );
}
131 inline WFMath::Vector<3> Ogre2Atlas_Vector3( const Ogre::Vector3& p ) {
return WFMath::Vector<3>( p.x, -p.z, p.y );
}
// inline Ogre::Vector3 Atlas2Ogre( WFMath::Point<3>& p ){
// return Ogre::Vector3( p.x( ), p.z( ), -p.y( ) );
// }
139 inline Ogre::Vector3 Atlas2Ogre( const WFMath::Point<3>& p ){
return Ogre::Vector3( p.x( ), p.z( ), -p.y( ) );
}
// inline Ogre::Vector3 Atlas2Ogre( WFMath::Vector<3>& v ){
// return Ogre::Vector3( v.x( ), v.z( ), -v.y( ) );
// }
147 inline Ogre::Vector3 Atlas2Ogre( const WFMath::Vector<3>& v ){
return Ogre::Vector3( v.x( ), v.z( ), -v.y( ) );
}
// inline Ogre::Quaternion Atlas2Ogre( WFMath::Quaternion& aq ){
// if ( !aq.isValid( ) ) {
// return Ogre::Quaternion::IDENTITY;
// }
// return Ogre::Quaternion( aq.scalar( ), aq.vector( ).x( ), aq.vector( ).z( ), -aq.vector( ).y( ) );
// }
158 inline Ogre::Quaternion Atlas2Ogre( const WFMath::Quaternion& aq ){
if ( !aq.isValid( ) ) {
return Ogre::Quaternion::IDENTITY;
}
return Ogre::Quaternion( aq.scalar( ), aq.vector( ).x( ), aq.vector( ).z( ), -aq.vector( ).y( ) );
}
//is this correct?
// inline WFMath::Quaternion Ogre2Atlas( Ogre::Quaternion& aq ){
// return WFMath::Quaternion( aq.w, aq.x, -aq.z, aq.y );
// }
169 inline WFMath::Quaternion Ogre2Atlas( const Ogre::Quaternion& aq ){
return WFMath::Quaternion( aq.w, aq.x, -aq.z, aq.y );
}
173 inline Ogre::AxisAlignedBox Atlas2Ogre( const WFMath::AxisBox<3>& axisBox ){
if ( !axisBox.isValid( ) ) {
return Ogre::AxisAlignedBox( );
}
return Ogre::AxisAlignedBox( axisBox.lowCorner( ).x( ), axisBox.lowCorner( ).z( ), -axisBox.highCorner( ).y( ), axisBox.highCorner( ).x( ), axisBox.highCorner( ).z( ), -axisBox.lowCorner( ).y( ) );
}
180 inline Ogre::TRect<Ogre::Real> Atlas2Ogre( const WFMath::AxisBox<2>& atlasBox ) {
if ( !atlasBox.isValid( ) ) {
return Ogre::TRect<Ogre::Real>( );
}
return Ogre::TRect<Ogre::Real>( atlasBox.lowCorner( ).x( ), -atlasBox.highCorner( ).y( ), atlasBox.highCorner( ).x( ), -atlasBox.lowCorner( ).y( ) );
}
188 inline WFMath::AxisBox<3> Ogre2Atlas( const Ogre::AxisAlignedBox& axisBox ){
if ( axisBox.isNull( ) || axisBox.isInfinite( ) ) {
return WFMath::AxisBox<3>( );
}
return WFMath::AxisBox<3>( WFMath::Point<3>( axisBox.getMinimum( ).x, axisBox.getMinimum( ).z, -axisBox.getMaximum( ).y ), WFMath::Point<3>( axisBox.getMaximum( ).x, axisBox.getMaximum( ).z, -axisBox.getMinimum( ).y ) );
}
}
/*
Ogre::Vector3 Ogre::Vector3( WFMath::Vector<3> v ) {
return Ogre::Vector3( v.x( ), v.z( ), -v.y( ) );
}
WFMath::Point<3>::operator Ogre::Vector3( ) const{
return Ogre::Vector3( this.x( ), this.z( ), -this.y( ) );
}
*/
#endif
1 /*
ConsoleObjectImpl.cpp by Miguel Guzman ( Aglanor )
Copyright ( C ) 2002 Miguel Guzman & The Worldforge Project
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
// config headers
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
// system headers
// library headers
#include "EmberOgrePrerequisites.h"
// local headers
#include "MediaDeployer.h"
namespace EmberOgre {
//TODO: add a sequence for mediadeployer ids
//TODO: add several methods for adding media with different params
MediaDeployer* MediaDeployer::_mediaDeployerInstance = 0;
40 MediaDeployer & MediaDeployer::getSingleton( void )
{
if( _mediaDeployerInstance == 0 )
_mediaDeployerInstance = new MediaDeployer;
return *_mediaDeployerInstance;
}
47 MediaDeployer::MediaDeployer( void )
{
mSceneMgr = Ogre::Root::getSingleton( ).getSceneManager( Ogre::ST_EXTERIOR_CLOSE );
}
52 MediaDeployer::~MediaDeployer( )
{
}
57 bool MediaDeployer::addMedia( std::string modelName )
{
return true;
}
62 bool MediaDeployer::addMedia( std::string modelName, std::string id, Ogre::Vector3 position )
{
// create the ogre node and entity
Ogre::SceneNode* ogreNode = static_cast<Ogre::SceneNode*>( mSceneMgr->getRootSceneNode( )->createChild( ) );
Ogre::Entity* ogreEntity;
ogreEntity = mSceneMgr->createEntity( id, modelName );
ogreNode->setPosition( position );
ogreNode->attachObject( ogreEntity );
return true;
}
}
1 /*
ConsoleObjectImpl.h by Miguel Guzman ( Aglanor )
Copyright ( C ) 2002 Miguel Guzman & The Worldforge Project
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __EmberOgre_MediaDeployer_H__
#define __EmberOgre_MediaDeployer_H__
namespace EmberOgre {
25 class MediaDeployer
{
public:
30 ~MediaDeployer( );
32 static MediaDeployer & getSingleton( void );
34 bool addMedia( std::string );
35 bool addMedia( std::string, std::string, Ogre::Vector3 );
private:
/**
* Private constructor ( for singleton )
*/
42 MediaDeployer( void );
/**
* Instance variable for singleton console object implementation.
*/
static MediaDeployer* _mediaDeployerInstance;
/**
* Scene manager to which deploy the media
*/
52 Ogre::SceneManager* mSceneMgr;
}; // End of class declaration
}
#endif
1 //
// C++ Implementation: MediaUpdater
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2007
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "MediaUpdater.h"
#include "services/EmberServices.h"
#include "services/config/ConfigService.h"
#include "services/wfut/WfutService.h"
namespace EmberOgre {
31 MediaUpdater::MediaUpdater( )
{
}
36 MediaUpdater::~MediaUpdater( )
{
}
40 void MediaUpdater::performUpdate( )
{
Ember::ConfigService* configSrv = Ember::EmberServices::getSingleton( ).getConfigService( );
Ember::WfutService* wfutSrv= Ember::EmberServices::getSingleton( ).getWfutService( );
if ( configSrv->itemExists( "wfut", "server" ) ) {
std::string server( configSrv->getValue( "wfut", "server" ) );
if ( configSrv->itemExists( "wfut", "channel" ) ) {
std::string channel( configSrv->getValue( "wfut", "channel" ) );
wfutSrv->startUpdate( server, channel, configSrv->getHomeDirectory( ) , "" );
while ( wfutSrv->poll( ) ) {
}
}
}
}
}
1 //
// C++ Interface: MediaUpdater
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2007
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGREMEDIAUPDATER_H
#define EMBEROGREMEDIAUPDATER_H
namespace EmberOgre {
/**
@author Erik Hjortsberg <erik@katastrof.nu>
*/
31 class MediaUpdater{
public:
33 MediaUpdater( );
35 ~MediaUpdater( );
37 void performUpdate( );
};
}
#endif
1 //
// C++ Implementation: MeshCollisionDetector
//
// Description:
//
//
// Author: Erik Hjortsberg <erik.hjortsberg@iteam.se>, ( C ) 2008
// This code is taked from http://www.ogre3d.org/wiki/index.php/Raycasting_to_the_polygon_level ( 2008-01-13 ), where it's released as Public Domain, and now relicensed to GPL. Author is unknown.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "MeshCollisionDetector.h"
#include "EmberOgrePrerequisites.h"
#include "model/Model.h"
#include "model/SubModel.h"
namespace EmberOgre {
37 MeshCollisionDetector::MeshCollisionDetector( Model::Model* model )
:mModel( model )
{
}
43 MeshCollisionDetector::~MeshCollisionDetector( )
{
}
47 void MeshCollisionDetector::reload( )
{
}
51 void MeshCollisionDetector::refit( )
{
}
55 void MeshCollisionDetector::setVisualize( bool visualize )
{
}
58 bool MeshCollisionDetector::getVisualize( ) const
{
return false;
}
63 void MeshCollisionDetector::testCollision( Ogre::Ray& ray, CollisionResult& result )
{
// at this point we have raycast to a series of different objects bounding boxes.
// we need to test these different objects to see which is the first polygon hit.
// there are some minor optimizations ( distance based ) that mean we wont have to
// check all of the objects most of the time, but the worst case scenario is that
// we need to test every triangle of every object.
Ogre::Real closest_distance = -1.0f;
Ogre::Vector3 closest_result;
const Model::Model::SubModelSet& submodels = mModel->getSubmodels( );
for ( Model::Model::SubModelSet::const_iterator I = submodels.begin( ); I != submodels.end( ); ++I )
{
Ogre::Entity* pentity = ( *I )->getEntity( );
if ( pentity->isVisible( ) ) {
// mesh data to retrieve
size_t vertex_count;
size_t index_count;
Ogre::Vector3 *vertices;
unsigned long *indices;
// get the mesh information
getMeshInformation( pentity->getMesh( ), vertex_count, vertices, index_count, indices,
pentity->getParentNode( )->getWorldPosition( ),
pentity->getParentNode( )->getWorldOrientation( ),
pentity->getParentNode( )->getScale( ) );
// test for hitting individual triangles on the mesh
bool new_closest_found = false;
for ( int i = 0; i < static_cast<int>( index_count ); i += 3 )
{
// check for a hit against this triangle
std::pair<bool, Ogre::Real> hit = Ogre::Math::intersects( ray, vertices[indices[i]],
vertices[indices[i+1]], vertices[indices[i+2]], true, false );
// if it was a hit check if its the closest
if ( hit.first )
{
if ( ( closest_distance < 0.0f ) ||
( hit.second < closest_distance ) )
{
// this is the closest so far, save it off
closest_distance = hit.second;
new_closest_found = true;
}
}
}
// free the verticies and indicies memory
delete[] vertices;
delete[] indices;
// if we found a new closest raycast for this object, update the
// closest_result before moving on to the next object.
if ( new_closest_found )
{
closest_result = ray.getPoint( closest_distance );
}
}
}
// return the result
if ( closest_distance >= 0.0f )
{
// raycast success
result.collided = true;
result.position = closest_result;
result.distance = closest_distance;
}
else
{
// raycast failed
result.collided = false;
}
}
// Get the mesh information for the given mesh.
// Code found on this forum link: http://www.ogre3d.org/wiki/index.php/RetrieveVertexData
143 void MeshCollisionDetector::getMeshInformation( const Ogre::MeshPtr mesh,
144 size_t &vertex_count,
145 Ogre::Vector3* &vertices,
146 size_t &index_count,
unsigned long* &indices,
148 const Ogre::Vector3 &position,
149 const Ogre::Quaternion &orient,
150 const Ogre::Vector3 &scale )
{
bool added_shared = false;
size_t current_offset = 0;
size_t shared_offset = 0;
size_t next_offset = 0;
size_t index_offset = 0;
vertex_count = index_count = 0;
// Calculate how many vertices and indices we're going to need
for ( unsigned short i = 0; i < mesh->getNumSubMeshes( ); ++i )
{
Ogre::SubMesh* submesh = mesh->getSubMesh( i );
// We only need to add the shared vertices once
if( submesh->useSharedVertices )
{
if( !added_shared )
{
vertex_count += mesh->sharedVertexData->vertexCount;
added_shared = true;
}
}
else
{
vertex_count += submesh->vertexData->vertexCount;
}
// Add the indices
index_count += submesh->indexData->indexCount;
}
// Allocate space for the vertices and indices
vertices = new Ogre::Vector3[vertex_count];
indices = new unsigned long[index_count];
added_shared = false;
// Run through the submeshes again, adding the data into the arrays
for ( unsigned short i = 0; i < mesh->getNumSubMeshes( ); ++i )
{
Ogre::SubMesh* submesh = mesh->getSubMesh( i );
Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
if( ( !submesh->useSharedVertices )||( submesh->useSharedVertices && !added_shared ) )
{
if( submesh->useSharedVertices )
{
added_shared = true;
shared_offset = current_offset;
}
const Ogre::VertexElement* posElem =
vertex_data->vertexDeclaration->findElementBySemantic( Ogre::VES_POSITION );
Ogre::HardwareVertexBufferSharedPtr vbuf =
vertex_data->vertexBufferBinding->getBuffer( posElem->getSource( ) );
unsigned char* vertex =
static_cast<unsigned char*>( vbuf->lock( Ogre::HardwareBuffer::HBL_READ_ONLY ) );
// There is _no_ baseVertexPointerToElement( ) which takes an Ogre::Real or a double
// as second argument. So make it float, to avoid trouble when Ogre::Real will
// be comiled/typedefed as double:
// Ogre::Real* pReal;
float* pReal;
for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize( ) )
{
posElem->baseVertexPointerToElement( vertex, &pReal );
Ogre::Vector3 pt( pReal[0], pReal[1], pReal[2] );
vertices[current_offset + j] = ( orient * ( pt * scale ) ) + position;
}
vbuf->unlock( );
next_offset += vertex_data->vertexCount;
}
Ogre::IndexData* index_data = submesh->indexData;
size_t numTris = index_data->indexCount / 3;
Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
bool use32bitindexes = ( ibuf->getType( ) == Ogre::HardwareIndexBuffer::IT_32BIT );
unsigned long* pLong = static_cast<unsigned long*>( ibuf->lock( Ogre::HardwareBuffer::HBL_READ_ONLY ) );
unsigned short* pShort = reinterpret_cast<unsigned short*>( pLong );
size_t offset = ( submesh->useSharedVertices )? shared_offset : current_offset;
if ( use32bitindexes )
{
for ( size_t k = 0; k < numTris*3; ++k )
{
indices[index_offset++] = pLong[k] + static_cast<unsigned long>( offset );
}
}
else
{
for ( size_t k = 0; k < numTris*3; ++k )
{
indices[index_offset++] = static_cast<unsigned long>( pShort[k] ) +
static_cast<unsigned long>( offset );
}
}
ibuf->unlock( );
current_offset = next_offset;
}
}
}
1 //
// C++ Interface: MeshCollisionDetector
//
// Description:
//
//
// Author: Erik Hjortsberg <erik.hjortsberg@iteam.se>, ( C ) 2008
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGREMESHCOLLISIONDETECTOR_H
#define EMBEROGREMESHCOLLISIONDETECTOR_H
#include "EmberEntityUserObject.h"
namespace EmberOgre {
/**
Uses a brute force approach to checking for intersection by iterating through all vertices to see which intersects the ray.
@author Erik Hjortsberg <erik.hjortsberg@iteam.se>
*/
34 class MeshCollisionDetector : public ICollisionDetector
{
public:
37 MeshCollisionDetector( Model::Model* model );
39 virtual ~MeshCollisionDetector( );
41 virtual void testCollision( Ogre::Ray& ray, CollisionResult& result );
42 virtual void refit( );
/**
* Called when the entity changes, such as a subentity being hidden or shown. Implementations must reload the collision data.
*/
46 virtual void reload( );
48 virtual void setVisualize( bool visualize );
49 virtual bool getVisualize( ) const;
protected:
52 Model::Model* mModel;
53 void getMeshInformation( const Ogre::MeshPtr mesh,
54 size_t &vertex_count,
55 Ogre::Vector3* &vertices,
56 size_t &index_count,
unsigned long* &indices,
58 const Ogre::Vector3 &position,
59 const Ogre::Quaternion &orient,
60 const Ogre::Vector3 &scale );
};
}
#endif
1 /*
Copyright ( C ) 2004 Erik Hjortsberg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "EmberEntity.h"
#include "EmberPhysicalEntity.h"
#include "EmberOgre.h"
#include "MathConverter.h"
#include "MotionManager.h"
// #include "terrain/TerrainGenerator.h"
template<> EmberOgre::MotionManager* Ember::Singleton<EmberOgre::MotionManager>::ms_Singleton = 0;
namespace EmberOgre {
31 MotionManager::MotionManager( )
: mControllerManager( &Ogre::ControllerManager::getSingleton( ) )
{
mInfo.MovingEntities = mMotionSet.size( );
mInfo.AnimatedEntities = mAnimatedEntities.size( );
mInfo.Animations = mAnimations.size( );
}
40 MotionManager::~MotionManager( )
{}
44 void MotionManager::doMotionUpdate( Ogre::Real timeSlice )
{
std::set<EmberEntity*>::iterator I;
for ( I = mMotionSet.begin( ); I != mMotionSet.end( ); ++I ) {
updateMotionForEntity( *I, timeSlice );
}
}
52 void MotionManager::doAnimationUpdate( Ogre::Real timeSlice )
{
EntityStore::iterator I = mAnimatedEntities.begin( );
for ( ;I != mAnimatedEntities.end( ); ++I ) {
I->second->updateAnimation( timeSlice );
}
/* AnimationStateSet::iterator I = mAnimations.begin( );
AnimationStateSet::iterator I_end = mAnimations.end( );
for ( ;I != I_end; ++I ) {
if ( ( *I )->getEnabled( ) ) {
( *I )->addTime( timeSlice );
}
}*/
}
70 void MotionManager::updateMotionForEntity( EmberEntity* entity, Ogre::Real timeSlice )
{
entity->updateMotion( timeSlice );
}
// void MotionManager::adjustHeightPositionForNode( Ogre::SceneNode* sceneNode ) {
// Ogre::Vector3 position = sceneNode->getPosition( );
// //get the height from Mercator through the TerrainGenerator
// assert( mTerrainGenerator );
// TerrainPosition pos = Ogre2Atlas_TerrainPosition( position );
// float height = mTerrainGenerator->getHeight( pos );
// sceneNode->setPosition( position.x, height, position.z );
//
// }
85 bool MotionManager::frameStarted( const Ogre::FrameEvent& event )
{
doMotionUpdate( event.timeSinceLastFrame );
doAnimationUpdate( event.timeSinceLastFrame );
return true;
}
92 bool MotionManager::frameEnded( const Ogre::FrameEvent& event )
{
return true;
}
97 void MotionManager::addEntity( EmberEntity* entity )
{
mMotionSet.insert( entity );
mInfo.MovingEntities = mMotionSet.size( );
entity->updateMotion( 0 );
}
104 void MotionManager::removeEntity( EmberEntity* entity )
{
mMotionSet.erase( entity );
mInfo.MovingEntities = mMotionSet.size( );
// entity->updateMotion( 0 );
}
113 void MotionManager::addAnimatedEntity( EmberPhysicalEntity* entity )
{
mAnimatedEntities[entity->getId( )] = entity;
mInfo.AnimatedEntities = mAnimatedEntities.size( );
}
119 void MotionManager::removeAnimatedEntity( EmberPhysicalEntity* entity )
{
mAnimatedEntities.erase( entity->getId( ) );
mInfo.AnimatedEntities = mAnimatedEntities.size( );
}
126 void MotionManager::addAnimation( Ogre::AnimationState* animationState )
{
animationState->setEnabled( true );
mAnimations.insert( animationState );
mInfo.Animations = mAnimations.size( );
/*
//check if it's not already added
AnimationStateSet::const_iterator I = mAnimations.find( animationState );
if ( I == mAnimations.end( ) ) {
animationState->setEnabled( true );
mAnimations.insert( animationState );
//how is the overhead on creating a ControllerFunction for each single AnimationState?
//perhaps we should keep ControllerFunction bound to Animation instead?
Ogre::AnimationControllerFunction* controllerFunction = new Ogre::AnimationControllerFunction( animationState->getLength( ) );
animationControllerType* animationController = Ogre::ControllerManager::getSingleton( ).createController( mControllerManager->getFrameTimeSource( ), animationState, controllerFunction );
animationState->setEnabled( true );
mAnimations.insert( animationStateMap::value_type( animationState, animationController ) );
}
*/
}
155 void MotionManager::removeAnimation( Ogre::AnimationState* animationState )
{
AnimationStateSet::const_iterator I = mAnimations.find( animationState );
if ( I != mAnimations.end( ) ) {
mAnimations.erase( *I );
//animationControllerType* animationController = mAnimations[animationState];
/* don't need to do this as SharePtr uses reference counting
Ogre::SharedPtr< ControllerFunction<Ogre::Real> > controllerFunctionPtr = ( animationController->getFunction( ) );
delete *controllerFunctionPtr;
*/
/* mAnimations.erase( I->first );
animationControllerType* controllerFunction = I->second;
if ( controllerFunction )
{
}
Ogre::ControllerManager::getSingleton( ).destroyController( controllerFunction );
std::cout << "removed controller\n";
*/
// Ogre::ControllerManager::getSingleton( ).destroyController( I->second );
}
mInfo.Animations = mAnimations.size( );
}
182 void MotionManager::pauseAnimation( Ogre::AnimationState* animationState )
{
animationState->setEnabled( false );
/*
animationControllerType* animationController = mAnimations[animationState];
animationController->setEnabled( false );
*/
}
191 void MotionManager::unpauseAnimation( Ogre::AnimationState* animationState )
{
animationState->setEnabled( true );
/*
animationControllerType* animationController = mAnimations[animationState];
animationController->setEnabled( true );
*/
}
// void MotionManager::setTerrainGenerator( TerrainGenerator* generator ) {
// mTerrainGenerator = generator;
// }
}
1 /*
Copyright ( C ) 2004 Erik Hjortsberg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef MOTIONMANAGER_H
#define MOTIONMANAGER_H
#include "EmberOgrePrerequisites.h"
#include <OgrePredefinedControllers.h>
#include "framework/Singleton.h"
namespace EmberOgre {
28 class EmberEntity;
29 class EmberPhysicalEntity;
// class TerrainGenerator;
/**
* This class will be responsible for making sure that entites moves
* in a nice and fluid way. Eventually we'll also implement physics, perhaps it
* will go into here.
* The manager also takes care of keeping tabs on all animations.
*/
38 class MotionManager : public Ogre::FrameListener, public Ember::Singleton<MotionManager> {
public:
/**
A struct containing information about the MotionManager.
*/
struct MotionManagerInfo
{
size_t AnimatedEntities;
size_t MovingEntities;
size_t Animations;
};
51 MotionManager( );
52 virtual ~MotionManager( );
//static MotionManager & getSingleton( void );
/**
* Adds a EmberEntity to the movement list.
* That means that until removeEntity is called for the specific entity
* new positions for the entity will be calculated for each frame.
*/
60 void addEntity( EmberEntity* entity );
61 void removeEntity( EmberEntity* entity );
/**
* Registers an animationState. After registration it will be enough to use
* AnimationState::enabled( bool ) to toggle the animation on and off
*/
67 void addAnimation( Ogre::AnimationState* animationState );
/**
* Deregisters an animationState
*/
71 void removeAnimation( Ogre::AnimationState* animationState );
/**
* Pauses the supplies animationState
*/
75 void pauseAnimation( Ogre::AnimationState* animationState );
/**
* Unpauses ( starts ) an already paused animationState
*/
79 void unpauseAnimation( Ogre::AnimationState* animationState );
81 void addAnimatedEntity( EmberPhysicalEntity* entity );
82 void removeAnimatedEntity( EmberPhysicalEntity* entity );
/* void addAction( Action* action );
void removeAction( Action* action );*/
/**
* Methods from Ogre::FrameListener
*/
92 bool frameStarted( const Ogre::FrameEvent& event );
93 bool frameEnded( const Ogre::FrameEvent& event );
/**
* Adjusts the height of the supplied node
*/
//void adjustHeightPositionForNode( Ogre::SceneNode* sceneNode );
// void setTerrainGenerator( TerrainGenerator* generator );
/**
* Gets info about the MotionManager.
* @return
*/
106 inline const MotionManagerInfo& getInfo( ) const;
private:
typedef std::map<std::string , EmberPhysicalEntity*> EntityStore;
111 EntityStore mAnimatedEntities;
MotionManagerInfo mInfo;
// typedef std::set<Action*> ActionStore;
// ActionStore mActions;
/**
* A pointer to the applications ControllerManager. This will take care of
* keeping tabs on all controllers.
*/
122 Ogre::ControllerManager* mControllerManager;
typedef Ogre::Controller<Ogre::Real> animationControllerType;
typedef std::map<Ogre::AnimationState*, animationControllerType*> animationStateMap;
typedef std::set<Ogre::AnimationState*> AnimationStateSet;
/**
* A map of AnimationState's and their corresponding Controllers
*/
129 AnimationStateSet mAnimations;
//static MotionManager* _instance;
/** This method will iterate over all registered moving entities and update
* their positions.
*/
137 void doMotionUpdate( Ogre::Real timeSlice );
/** This method will iterate over all registered animationStates and update
* those that are enabled
*/
142 void doAnimationUpdate( Ogre::Real timeSlice );
/**
* Update the motion for a single EmberEntity
*/
148 void updateMotionForEntity( EmberEntity* entity, Ogre::Real timeSlice );
/**
* This contains all of the entities that will be moved each frame
*/
153 std::set<EmberEntity*> mMotionSet;
// TerrainGenerator* mTerrainGenerator;
};
159 const MotionManager::MotionManagerInfo& MotionManager::getInfo( ) const
{
return mInfo;
}
}
#endif // MOTIONMANAGER_H
1 //
// C++ Implementation: MousePicker
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2004
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "EmberEntity.h"
#include "EmberOgre.h"
//#include "EmberPhysicalEntity.h"
//#include "PersonEmberEntity.h"
//#include "AvatarEmberEntity.h"
#include "AvatarCamera.h"
#include "GUIManager.h"
//#include "AvatarController.h"
#include "MousePicker.h"
namespace EmberOgre {
37 MousePicker::MousePicker( )
{
}
42 MousePicker::~MousePicker( )
{
}
46 void MousePicker::doMousePicking( const Ogre::Real x, const Ogre::Real y, const MousePickerArgs& args )
{
AvatarCamera* camera = EmberOgre::getSingleton( ).getMainCamera( );
camera->pickInWorld( x, y, args );
/* if ( result.entity ) {
mLastPickedEntityResult = result;
onEventPickedEntity( mLastPickedEntityResult, args );
} else {
onEventPickedNothing( args );
}*/
}
// void MousePicker::onEventPickedEntity( const EntityPickResult & result, const MousePickerArgs& args )
// {
// EventPickedEntity.emit( result, args );
// }
//
// void MousePicker::onEventPickedNothing( const MousePickerArgs& args )
// {
// EventPickedNothing.emit( args );
// }
};
1 //
// C++ Interface: MousePicker
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2004
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef DIMEOGREMOUSEPICKER_H
#define DIMEOGREMOUSEPICKER_H
#include <sigc++/signal.h>
#include "IWorldPickListener.h"
#include "EmberOgrePrerequisites.h"
namespace EmberOgre {
/**
Class used for picking stuff in the world.
Since we sometimes want different picking behaviour ( sometimes we want to pick building blocks, sometimes we want to pick entities ) it's possible to create derived classes and register them with the GUIManager.
@author Erik Hjortsberg
*/
41 class MousePicker
{
public:
enum ClickMasks
{
CM_AVATAR = 1<<9,
CM_ENTITY = 1<<10,
CM_NATURE = 1<<11,
CM_UNDEFINED = 1<<12,
CM_NONPICKABLE = 1<<13
};
53 MousePicker( );
55 virtual ~MousePicker( );
/**
* Try to pick something at the specified coordinates
* @param x
* @param y
* @param args
*/
63 virtual void doMousePicking( const Ogre::Real x, const Ogre::Real y, const MousePickerArgs& args );
// sigc::signal<void, const MousePickerArgs&> EventPickedNothing;
// inline EmberEntity* getLastPickedEntity( ) { return mLastPickedEntityResult.entity; }
protected:
// virtual void onEventPickedEntity( const EntityPickResult & result, const MousePickerArgs& args );
// virtual void onEventPickedNothing( const MousePickerArgs& args );
//the currently selected entity
// EmberEntity* mEntityUnderCursor;
//the last clicked entity
// EntityPickResult mLastPickedEntityResult;
};
}
#endif
1 //
// C++ Interface: OgreIncludes
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
//base include files needed for Ogre
//we don't want to use the ogre memory manager, since it messes with Atlas in debug mode, so we'll simply define __MemoryManager_H__ here so that the OgreMemoryMacros.h never will be parsed
//however, we'll put this in config.h for now instead
// #ifndef __MemoryManager_H__
// #define __MemoryManager_H__
// #endif
// #define OGRE_MEMORY_MACROS
// #include <OgreMemoryMacros.h>
// #include <OgreNoMemoryMacros.h>
//#include <OgreNoMemoryMacros.h>
#include <Ogre.h>
1 //
// C++ Implementation: OgreInfo
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "OgreInfo.h"
#ifdef WIN32
#else
#include <GL/gl.h>
#endif
namespace EmberOgre {
33 OgreInfo::OgreInfo( )
{
}
38 OgreInfo::~OgreInfo( )
{
}
43 bool OgreInfo::isIndirect( ) const
{
#ifdef WIN32
///TODO: add checks for win32 too
return false;
#else
const GLubyte* pcRenderer = glGetString( GL_RENDERER );
const std::string renderer( ( const char* )pcRenderer );
return renderer.find( "Indirect" ) != std::string::npos;
#endif
}
}
1 //
// C++ Interface: OgreInfo
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGREOGREINFO_H
#define EMBEROGREOGREINFO_H
#include "EmberOgrePrerequisites.h"
namespace EmberOgre {
/**
Provides methods for getting some basic information about the Ogre environment.
@author Erik Hjortsberg <erik@katastrof.nu>
*/
36 class OgreInfo{
public:
38 OgreInfo( );
40 ~OgreInfo( );
/**
* True if the rendering is indirect, for example when using Mesa drivers on Linux. This will result in _very_ bad performance, and is usually caused by the user not having vendor drivers installed.
* @return
*/
47 bool isIndirect( ) const;
};
}
#endif
1 //
// C++ Implementation: OgreLogObserver
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "OgreLogObserver.h"
#include "services/EmberServices.h"
#include "services/logging/LoggingService.h"
using namespace Ogre;
namespace EmberOgre {
34 OgreLogObserver::OgreLogObserver( )
{
}
38 OgreLogObserver::~OgreLogObserver( )
{
}
45 void OgreLogObserver::messageLogged( const String& message, LogMessageLevel lml, bool maskDebug, const String &logName )
{
static std::string ogre( "( Ogre ) " );
switch ( lml ) {
case Ogre::LML_TRIVIAL:
Ember::EmberServices::getSingletonPtr( )->getLoggingService( )->log( "Ogre", Ember::LoggingService::VERBOSE, ( ogre + message ).c_str( ) );
break;
case Ogre::LML_NORMAL:
Ember::EmberServices::getSingletonPtr( )->getLoggingService( )->log( "Ogre", Ember::LoggingService::INFO, ( ogre + message ).c_str( ) );
break;
case Ogre::LML_CRITICAL:
Ember::EmberServices::getSingletonPtr( )->getLoggingService( )->log( "Ogre", Ember::LoggingService::FAILURE, ( ogre + message ).c_str( ) );
break;
}
}
}
1 //
// C++ Interface: OgreLogObserver
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGREOGRELOGOBSERVER_H
#define EMBEROGREOGRELOGOBSERVER_H
#include "EmberOgrePrerequisites.h"
#include "framework/StreamLogObserver.h"
namespace EmberOgre {
/**
@author Erik Hjortsberg
A log observer which writes to the Ogre log system.
This is a combined Ogre::LogListener and a Ember::StreamLogObserver.
The Ember::StreamLogObserver part does the main work, while the Ogre::LogListener implementation allow us to recieve ogre log events.
*/
37 class OgreLogObserver: public Ogre::LogListener
{
public:
/**
* Creates a new OgreLogObserver using default values.
*/
43 OgreLogObserver( );
44 ~OgreLogObserver( );
45 virtual void messageLogged( const Ogre::String& message, Ogre::LogMessageLevel lml, bool maskDebug, const Ogre::String &logName );
protected:
};
}
#endif
1 //
// C++ Implementation: OgreResourceLoader
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "OgreResourceLoader.h"
#include "services/EmberServices.h"
#include "services/logging/LoggingService.h"
#include "services/server/ServerService.h"
#include "services/config/ConfigService.h"
#include "model/ModelDefinitionManager.h"
#include "framework/osdir.h"
#include <fstream>
namespace EmberOgre {
35 OgreResourceLoader::OgreResourceLoader( ) : mLoadRecursive( false )
{
}
40 OgreResourceLoader::~OgreResourceLoader( )
{
}
44 void OgreResourceLoader::initialize( )
{
Ember::ConfigService* configSrv = Ember::EmberServices::getSingletonPtr( )->getConfigService( );
///check from the config if we should load media recursively
///this is needed for most authoring, since it allows us to find all meshes before they are loaded
if ( configSrv->itemExists( "media", "loadmediarecursive" ) ) {
mLoadRecursive = ( bool )configSrv->getValue( "media", "loadmediarecursive" );
}
// chdir( Ember::EmberServices::getSingletonPtr( )->getConfigService( )->getHomeDirectory( ).c_str( ) );
///load the resource file
const std::string configPath( Ember::EmberServices::getSingletonPtr( )->getConfigService( )->getSharedConfigDirectory( ) + "/resources.cfg" );
S_LOG_VERBOSE( "Loading resources definitions from " << configPath );
mConfigFile.load( configPath );
}
62 unsigned int OgreResourceLoader::numberOfSections( )
{
unsigned int numberOfSections = 0;
Ogre::ConfigFile::SectionIterator I = mConfigFile.getSectionIterator( );
while ( I.hasMoreElements( ) ) {
numberOfSections++;
I.moveNext( );
}
return numberOfSections - 1;
}
74 bool OgreResourceLoader::addSharedMedia( const std::string& path, const std::string& type, const std::string& section, bool recursive )
{
static const std::string& sharedMediaPath = Ember::EmberServices::getSingletonPtr( )->getConfigService( )->getSharedMediaDirectory( );
bool foundDir = false;
S_LOG_INFO( "Looking for " << sharedMediaPath + path );
if ( isExistingDir( sharedMediaPath + path ) ) {
S_LOG_INFO( "Adding dir " << sharedMediaPath + path );
try {
Ogre::ResourceGroupManager::getSingleton( ).addResourceLocation(
sharedMediaPath + path, type, section, recursive );
foundDir = true;
} catch ( const Ogre::Exception& ex ) {
const std::string& message = ex.getFullDescription( );
S_LOG_FAILURE( "Couldn't load " + sharedMediaPath + path + ". Error: "<< message );
}
}
return foundDir;
}
96 bool OgreResourceLoader::addUserMedia( const std::string& path, const std::string& type, const std::string& section, bool recursive )
{
static const std::string& userMediaPath = Ember::EmberServices::getSingletonPtr( )->getConfigService( )->getUserMediaDirectory( );
static const std::string& emberMediaPath = Ember::EmberServices::getSingletonPtr( )->getConfigService( )->getEmberMediaDirectory( );
bool foundDir = false;
S_LOG_VERBOSE( "Looking for " << userMediaPath + path );
if ( isExistingDir( userMediaPath + path ) ) {
S_LOG_VERBOSE( "Adding dir " << userMediaPath + path );
try {
Ogre::ResourceGroupManager::getSingleton( ).addResourceLocation(
userMediaPath + path, type, section, recursive );
foundDir = true;
} catch ( const Ogre::Exception& ) {
///don't report anything
}
}
///try with ember-media
S_LOG_VERBOSE( "Looking for " << emberMediaPath + path );
if ( isExistingDir( emberMediaPath + path ) ) {
S_LOG_VERBOSE( "Adding dir " << emberMediaPath + path );
try {
Ogre::ResourceGroupManager::getSingleton( ).addResourceLocation(
emberMediaPath + path, type, section, recursive );
foundDir = true;
} catch ( const Ogre::Exception& ) {
S_LOG_FAILURE( "Couldn't load " + emberMediaPath + path + ". Continuing as if nothing happened." );
}
}
return foundDir;
}
131 void OgreResourceLoader::loadBootstrap( )
{
loadSection( "Bootstrap" );
}
136 void OgreResourceLoader::loadGui( )
{
loadSection( "Gui" );
}
141 void OgreResourceLoader::loadGeneral( )
{
loadSection( "General" );
loadSection( "ModelDefinitions" );
loadAllUnloadedSections( );
///out of pure interest we'll print out how many modeldefinitions we've loaded
Ogre::ResourceManager::ResourceMapIterator I = Model::ModelDefinitionManager::getSingleton( ).getResourceIterator( );
int count = 0;
while ( I.hasMoreElements( ) ) {
++count;
I.moveNext( );
}
S_LOG_INFO( "Finished loading " << count << " modeldefinitions." );
}
160 void OgreResourceLoader::preloadMedia( )
{
try {
Ogre::ResourceGroupManager::getSingleton( ).loadResourceGroup( "General" );
} catch ( const Ogre::Exception& ex ) {
S_LOG_FAILURE( "An error occurred when preloading media. Message:\n\t"<< ex.getFullDescription( ) );
}
try {
Ogre::ResourceGroupManager::getSingleton( ).loadResourceGroup( "Gui" );
} catch ( const Ogre::Exception& ex ) {
S_LOG_FAILURE( "An error occurred when preloading media. Message:\n\t"<< ex.getFullDescription( ) );
}
try {
Ogre::ResourceGroupManager::getSingleton( ).loadResourceGroup( "ModelDefinitions" );
} catch ( const Ogre::Exception& ex ) {
S_LOG_FAILURE( "An error occurred when preloading media. Message:\n\t"<< ex.getFullDescription( ) );
}
// Ember::ConfigService* configSrv = Ember::EmberServices::getSingletonPtr( )->getConfigService( );
//
//
// std::vector<std::string> shaderTextures;
//
// shaderTextures.push_back( std::string( configSrv->getValue( "shadertextures", "rock" ) ) );
// shaderTextures.push_back( std::string( configSrv->getValue( "shadertextures", "sand" ) ) );
// shaderTextures.push_back( std::string( configSrv->getValue( "shadertextures", "grass" ) ) );
//
// for ( std::vector<std::string>::iterator I = shaderTextures.begin( ); I != shaderTextures.end( ); ++I ) {
// try {
// Ogre::TextureManager::getSingleton( ).load( *I, "General" );
// } catch ( const Ogre::Exception& e ) {
// S_LOG_FAILURE( "Error when loading texture " << *I )
// }
// }
}
197 void OgreResourceLoader::loadSection( const std::string& sectionName )
{
if ( sectionName != "" && std::find( mLoadedSections.begin( ), mLoadedSections.end( ), sectionName ) == mLoadedSections.end( ) )
{
bool mediaAdded = false;
S_LOG_VERBOSE( "Adding resource section " << sectionName );
// Ogre::ResourceGroupManager::getSingleton( ).createResourceGroup( sectionName );
Ogre::ConfigFile::SettingsIterator I = mConfigFile.getSettingsIterator( sectionName );
std::string finalTypename;
while ( I.hasMoreElements( ) ) {
//Ogre::ConfigFile::SettingsMultiMap J = I.getNext( );
const std::string& typeName = I.peekNextKey( );
const std::string& archName = I.peekNextValue( );
finalTypename = typeName.substr( 0, typeName.find( "[" ) );
if ( Ogre::StringUtil::endsWith( typeName, "[shared]" ) ) {
mediaAdded |= addSharedMedia( archName, finalTypename, sectionName, mLoadRecursive );
} else {
mediaAdded |= addUserMedia( archName, finalTypename, sectionName, mLoadRecursive );
}
I.moveNext( );
}
mLoadedSections.push_back( sectionName );
///only initialize the resource group if it has media
if ( mediaAdded ) {
try {
Ogre::ResourceGroupManager::getSingleton( ).initialiseResourceGroup( sectionName );
} catch ( const Ogre::Exception& ex ) {
S_LOG_FAILURE( "An error occurred when loading media from section '" << sectionName << "'. Message:\n\t"<< ex.getFullDescription( ) );
} catch ( const std::exception& ex ) {
S_LOG_FAILURE( "An error occurred when loading media from section '" << sectionName << "'. Message:\n\t"<< ex.what( ) );
} catch ( ... ) {
S_LOG_FAILURE( "An unknown error occurred when loading media from section '" << sectionName << "'." );
}
}
}
}
238 void OgreResourceLoader::loadAllUnloadedSections( )
{
S_LOG_VERBOSE( "Now loading all unloaded sections." );
Ogre::ConfigFile::SectionIterator I = mConfigFile.getSectionIterator( );
while ( I.hasMoreElements( ) ) {
const std::string& sectionName = I.peekNextKey( );
loadSection( sectionName );
I.moveNext( );
}
}
251 bool OgreResourceLoader::isExistingDir( const std::string& path ) const
{
bool exists = false;
oslink::directory osdir( path );
exists = osdir.isExisting( );
if ( !exists ) {
///perhaps it's a file?
std::ifstream fin( path.c_str( ) , std::ios::in );
exists = !fin.fail( );
}
return exists;
}
}
1 //
// C++ Interface: OgreResourceLoader
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGREOGRERESOURCELOADER_H
#define EMBEROGREOGRERESOURCELOADER_H
#include "EmberOgrePrerequisites.h"
namespace EmberOgre {
/**
@author Erik Hjortsberg
*/
33 class OgreResourceLoader{
public:
35 OgreResourceLoader( );
37 ~OgreResourceLoader( );
39 void initialize( );
41 void loadBootstrap( );
42 void loadGui( );
43 void loadGeneral( );
45 void preloadMedia( );
47 unsigned int numberOfSections( );
protected:
50 bool mLoadRecursive;
51 Ogre::ConfigFile mConfigFile;
53 void loadSection( const std::string& sectionName );
55 bool addUserMedia( const std::string& path, const std::string& type, const std::string& section, bool recursive );
56 bool addSharedMedia( const std::string& path, const std::string& type, const std::string& section, bool recursive );
58 bool isExistingDir( const std::string& path ) const;
60 void loadAllUnloadedSections( );
62 std::vector<std::string> mLoadedSections;
};
}
#endif
1 //
// C++ Implementation: OgreResourceProvider
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2007
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "OgreResourceProvider.h"
#include "framework/Exception.h"
namespace EmberOgre {
28 OgreResourceWrapper::OgreResourceWrapper( Ogre::DataStreamPtr dataStream )
{
mSize = dataStream->size( );
mBuffer = new char[mSize];
dataStream->read( mBuffer, mSize );
}
35 OgreResourceWrapper::~OgreResourceWrapper( )
{
delete[] mBuffer;
}
40 char* OgreResourceWrapper::getDataPtr( )
{
return mBuffer;
}
45 bool OgreResourceWrapper::hasData( )
{
return mSize != 0;
}
50 size_t OgreResourceWrapper::getSize( )
{
return mSize;
}
57 OgreResourceProvider::OgreResourceProvider( const std::string& groupName )
: mGroupName( groupName )
{
}
63 OgreResourceProvider::~OgreResourceProvider( )
{
}
67 Ember::ResourceWrapper OgreResourceProvider::getResource( const std::string& name )
{
Ogre::DataStreamPtr input =
Ogre::ResourceGroupManager::getSingleton( ).openResource( name.c_str( ), mGroupName.c_str( ) );
if ( input.isNull( ) )
{
throw Ember::Exception( "Unable to open resource file '" + name + "' in resource group '" + name + "'." );
}
OgreResourceWrapper* wrapper = new OgreResourceWrapper( input );
input->close( );
return Ember::ResourceWrapper( wrapper, name );
// Ogre::String buf = input->getAsString( );
// const size_t memBuffSize = buf.length( );
//
// unsigned char* mem = new unsigned char[memBuffSize];
// memcpy( mem, buf.c_str( ), memBuffSize );
//
// output.setData( mem );
// output.setSize( memBuffSize );
}
}
1 //
// C++ Interface: OgreResourceProvider
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2007
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGREOGRERESOURCEPROVIDER_H
#define EMBEROGREOGRERESOURCEPROVIDER_H
#include "framework/IScriptingProvider.h"
#include <Ogre.h>
namespace EmberOgre {
32 class OgreResourceWrapper : public Ember::IResourceWrapper
{
public:
35 OgreResourceWrapper( Ogre::DataStreamPtr dataStream );
36 virtual ~OgreResourceWrapper( );
38 virtual char* getDataPtr( );
39 virtual bool hasData( );
40 virtual size_t getSize( );
private:
char* mBuffer;
43 size_t mSize;
};
/**
@author Erik Hjortsberg <erik@katastrof.nu>
*/
50 class OgreResourceProvider : public Ember::IResourceProvider
{
public:
53 OgreResourceProvider( const std::string& groupName );
55 virtual ~OgreResourceProvider( );
57 virtual Ember::ResourceWrapper getResource( const std::string& name );
private:
59 std::string mGroupName;
};
}
#endif
1 //
// C++ Implementation: OgreSetup
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "OgreSetup.h"
#include "services/EmberServices.h"
#include "services/config/ConfigService.h"
#ifdef WIN32
#include <SDL.h>
#include <SDL_syswm.h>
#else
#include <SDL/SDL.h>
#include <SDL/SDL_syswm.h>
#include "framework/binreloc.h"
#include <GL/glx.h>
#endif
#include "SceneManagers/EmberPagingSceneManager/include/EmberPagingSceneManager.h"
// #include "image/OgreILCodecs.h"
#include "framework/Tokeniser.h"
extern "C" {
#include <signal.h> /* signal name macros, and the signal( ) prototype */
}
namespace EmberOgre {
55 OgreSetup::OgreSetup( )
{
}
60 OgreSetup::~OgreSetup( )
{
}
64 void OgreSetup::shutdown( )
{
// Ogre::ILCodecs::deleteCodecs( );
delete mRoot;
mRoot = 0;
SDL_Quit( );
}
73 Ogre::Root* OgreSetup::createOgreSystem( )
{
// const std::string& sharePath( Ember::EmberServices::getSingleton( ).getConfigService( )->getSharedConfigDirectory( ) );
std::string pluginExtension = ".so";
mRoot = new Ogre::Root( "", "ogre.cfg", "" );
///we will try to load the plugins from series of different location, with the hope of getting at least one right
std::vector<std::string> pluginLocations;
Ember::ConfigService* configSrv = Ember::EmberServices::getSingleton( ).getConfigService( );
if ( configSrv->itemExists( "ogre", "plugins" ) ) {
std::string plugins( configSrv->getValue( "ogre", "plugins" ) );
///if it's defined in the config, use that location first
if ( configSrv->itemExists( "ogre", "plugindir" ) ) {
std::string pluginDir( configSrv->getValue( "ogre", "plugindir" ) );
pluginLocations.push_back( pluginDir );
}
#ifdef __WIN32__
pluginExtension = ".dll";
#else
pluginExtension = ".so";
#ifdef ENABLE_BINRELOC
///binreloc might be used
char* br_libdir = br_find_lib_dir( br_strcat( PREFIX, "/lib" ) );
std::string libDir( br_libdir );
free( br_libdir );
pluginLocations.push_back( libDir + "/ember/OGRE" );
#endif
#ifdef OGRE_PLUGINDIR
///also try with the plugindir defined for Ogre
pluginLocations.push_back( OGRE_PLUGINDIR );
#endif
///enter the usual locations if Ogre is installed system wide, with local installations taking precedence
pluginLocations.push_back( "/usr/local/lib/OGRE" );
pluginLocations.push_back( "/usr/lib/OGRE" );
#endif
Ember::Tokeniser tokeniser( plugins, ", " );
std::string token = tokeniser.nextToken( );
while ( token != "" ) {
for ( std::vector<std::string>::iterator I = pluginLocations.begin( ); I != pluginLocations.end( ); ++I ) {
std::string pluginPath( ( *I ) + "/" + token + pluginExtension );
bool success = false;
try {
S_LOG_INFO( "Trying to load the plugin " << pluginPath );
mRoot->loadPlugin( pluginPath );
success = true;
break;
} catch ( ... ) {
S_LOG_INFO( "Error when loading plugin '" << token << "' with path '" << pluginPath << "'. This is not fatal, we will continue trying with some other paths." );
}
if ( !success ) {
S_LOG_WARNING( "Error when loading plugin '" << token << "' after trying different parts. We'll continue, but there might be problems later on." );
}
}
token = tokeniser.nextToken( );
}
}
// std::vector<Ogre::String> tokens = Ogre::StringUtil::split( dsp, "." );
Ember::Tokeniser tokeniser( );
// Register image codecs
// Ogre::ILCodecs::registerCodecs( );
return mRoot;
}
/**
Shut down SDL correctly, else if run in full screen the display might be messed up.
*/
145 extern "C" void shutdownHandler( int signal )
{
std::cerr << "Crashed with signal " << signal << ", will try to shut down SDL gracefully. Please report bugs at https://bugs.launchpad.net/ember" << std::endl;
SDL_Quit( );
exit( signal );
}
/** Configures the application - returns false if the user chooses to abandon configuration. */
154 bool OgreSetup::configure( void )
{
bool suppressConfig = false;
bool success = false;
if ( Ember::EmberServices::getSingleton( ).getConfigService( )->itemExists( "ogre", "suppressconfigdialog" ) ) {
suppressConfig = static_cast<bool>( Ember::EmberServices::getSingleton( ).getConfigService( )->getValue( "ogre", "suppressconfigdialog" ) );
}
if ( suppressConfig ) {
success = mRoot->restoreConfig( );
} else {
success = mRoot->showConfigDialog( );
}
if( success )
{
#if __WIN32__
///this will only apply on DirectX
///it will force DirectX _not_ to set the FPU to single precision mode ( since this will mess with mercator amongst others )
try {
mRoot->getRenderSystem( )->setConfigOption( "Floating-point mode", "Consistent" );
} catch ( const Ogre::Exception& )
{
///we don't know what kind of render system is used, so we'll just swallow the error since it doesn't affect anything else than DirectX
}
mRenderWindow = mRoot->initialise( true, "Ember" );
///do some FPU fiddling, since we need the correct settings for stuff like mercator ( which uses fractals etc. ) to work
_fpreset( );
_controlfp( _PC_64, _MCW_PC );
_controlfp( _RC_NEAR , _MCW_RC );
// Allow SDL to use the window Ogre just created
// Old method: do not use this, because it only works
// when there is 1 ( one ) window with this name!
// HWND hWnd = FindWindow( tmp, 0 );
// New method: As proposed by Sinbad.
// This method always works.
HWND hWnd;
mRenderWindow->getCustomAttribute( "WINDOW", &hWnd );
char tmp[64];
// Set the SDL_WINDOWID environment variable
sprintf( tmp, "SDL_WINDOWID=%d", hWnd );
putenv( tmp );
if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE ) < 0 )
{
S_LOG_FAILURE( "Couldn't initialize SDL:\n\t\t" );
S_LOG_FAILURE( SDL_GetError( ) );
}
// if width = 0 and height = 0, the window is fullscreen
// This is necessary to allow the window to move1
// on WIN32 systems. Without this, the window resets
// to the smallest possible size after moving.
SDL_SetVideoMode( mRenderWindow->getWidth( ), mRenderWindow->getHeight( ), 0, 0 ); // first 0: BitPerPixel,
// second 0: flags ( fullscreen/... )
// neither are needed as Ogre sets these
static SDL_SysWMinfo pInfo;
SDL_VERSION( &pInfo.version );
SDL_GetWMInfo( &pInfo );
// Also, SDL keeps an internal record of the window size
// and position. Because SDL does not own the window, it
// missed the WM_POSCHANGED message and has no record of
// either size or position. It defaults to {0, 0, 0, 0},
// which is then used to trap the mouse "inside the
// window". We have to fake a window-move to allow SDL
// to catch up, after which we can safely grab input.
RECT r;
GetWindowRect( pInfo.window, &r );
SetWindowPos( pInfo.window, 0, r.left, r.top, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
///do some FPU fiddling, since we need the correct settings for stuff like mercator ( which uses fractals etc. ) to work
_fpreset( );
_controlfp( _PC_64, _MCW_PC );
_controlfp( _RC_NEAR , _MCW_RC );
#else
///On *NIX, Ogre can have either a SDL or an GLX backend ( or "platform", it's selected at compile time by the --with-platform=[GLX|SDL] option ). Ogre 1.2+ uses GLX by default.
///However, we use SDL for our input systems. If the SDL backend then is used, everything is already set up for us.
///If on the other hand the GLX backend is used, we need to do some fiddling to get SDL to play nice with the GLX render system.
///Check if SDL already has been initalized. If it has, we know that Ogre uses the SDL backend ( the call to SDL_Init happens at mRoot->restoreConfig( ) )
if( SDL_WasInit( SDL_INIT_VIDEO )==0 ) {
///SDL hasn't been initilized, we thus know that we're using the GLX platform, and need to initialize SDL ourselves
/// we start by trying to figure out what kind of resolution the user has selected, and whether full screen should be used or not
unsigned int height = 768, width = 1024;
bool fullscreen;
parseWindowGeometry( mRoot->getRenderSystem( )->getConfigOptions( ), width, height, fullscreen );
SDL_Init( SDL_INIT_VIDEO );
///this is a failsafe which guarantees that SDL is correctly shut down ( returning the screen to correct resolution, releasing mouse etc. ) if there's a crash.
atexit( SDL_Quit );
signal( SIGSEGV, shutdownHandler );
signal( SIGABRT, shutdownHandler );
signal( SIGBUS, shutdownHandler );
signal( SIGILL, shutdownHandler );
///set the window size
// int flags = SDL_OPENGL | SDL_HWPALETTE | SDL_RESIZABLE | SDL_HWSURFACE;
int flags = SDL_HWPALETTE | SDL_HWSURFACE;
// SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
// request good stencil size if 32-bit colour
/* if ( colourDepth == 32 )
{
SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 8 );
}*/
if ( fullscreen )
flags |= SDL_FULLSCREEN;
SDL_SetVideoMode( width, height, 0, flags ); // create an SDL window
SDL_WM_SetCaption( "Ember", "ember" );
SDL_SysWMinfo info;
SDL_VERSION( &info.version );
SDL_GetWMInfo( &info );
std::string dsp( &( DisplayString( info.info.x11.display )[1] ) );
std::vector<Ogre::String> tokens = Ogre::StringUtil::split( dsp, "." );
Ogre::NameValuePairList misc;
std::string s = Ogre::StringConverter::toString( ( long )info.info.x11.display );
s += ":" + tokens[1] +":";
s += ":" + Ogre::StringConverter::toString( ( long )info.info.x11.window );
misc["parentWindowHandle"] = s;
//misc["externalGLControl"] = "true";
/* GLXContext glxContext( glXGetCurrentContext( ) );
GLXDrawable glxDrawable( glXGetCurrentDrawable( ) );
std::string glxContextString = Ogre::StringConverter::toString( ( long )glxContext );
glxContextString += ":" + Ogre::StringConverter::toString( ( long )glxDrawable );
misc["glxcontext"] = glxContextString;*/
/// initialise root, without creating a window
mRoot->initialise( false );
mRenderWindow = mRoot->createRenderWindow( "MainWindow", width, height, true, &misc );
///we need to set the window to be active by ourselves, since GLX by default sets it to false, but then activates it upon receiving some X event ( which it will never recieve since we'll use SDL ).
///see OgreGLXWindow.cpp
mRenderWindow->setActive( true );
mRenderWindow->setAutoUpdated( true );
} else {
mRenderWindow = mRoot->initialise( true, "Ember" );
}
///set the icon of the window
Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif
/**
An bitmap of the ember icon, to be used for setting the window icon for SDL.
*/
static struct {
unsigned int width;
unsigned int height;
unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */
unsigned char pixel_data[64 * 64 * 3 + 1];
} emberIcon = {
64, 64, 3,
"C+\37B )\36?&\31?'\32C+\36D-\40@( \34='\33>( \33C, \40O8+YC7[F8U>1M6&F.\36E, "
"\35M3!R8&Q7&N3#J/\37F, \35G*\34K.\40Q2$V7*\\<0^=2_>4_?5\\<1R2 )R2( ]<5hIAjL"
"BdHA_D;ZB8W@7V?7[F>bOFkYNsaUo^T`OFN>4I8.G5*?, !7$\31:%\33D-$L2*M3*K1( J.&N"
"/( U7/[<5Z<5R80N5+K1'E-\40B*\37C-\37B.\40@*\35? )\34B, \37H1$N:-T?4M9+B, \40"
"<%\35>'\36C, \37I2\"O5%R8( S7( R6'N3$N1#O3$S5'W8+X8.Y8.W6-T5*O/$B\"\31?\37\27"
"F&\37Q4+S8/U;3X@7_E=aI@_I@^JB]KBaQHjZQn^UhYO_PFXI?PC8D7+:.!;-\40C2'H4*F1"
"'A*!:#\32:#\33E, $Q70X?7\\D<R:0U=3T<1bLCbMC_KBYE;UC8TC7SD9VE;[LCSC:I92E53"
"G75K95L9/P;/YD9_J@^H=aI>bJ>bG<_D8aD9`C7aC8^@5Z:/Y8/Y:1_?6dF<gJ@dI@`G>^F>"
"_G?_JAcMDdPGeTKhWNp_Wrd\\l`WeYQaWN]UJZRGZRFe]Qpf[vi`ug^jZQ\\IAP<4M:0J7.I"
"4, I4, ZB7cMAzf[ye[wf\\wf[q`VhZQ[MESF=WI@VIAUHAPD;OA8SF=UG=VG<WH=ZH;fRFhRF"
"rYLmTGfK>a@2`?0a=/f@1f<, f=.c:, ]3$c7+oOByXL{[NyZOwZOoRGt\\SnVL\\D:V@6R<1]"
"I?saX\210xn\211|rwmaZSFSL@UPD_[Orm_|vi\177uj\202vk\201sj\201pg\200qfyi_h"
"XNWG=P8-V?4r^UmZOveZxk_tg\\naXXLDI<5F:3J@9KA:MC;E:2L@9SG@PC9A1'Q<0Y?3fH;"
"nOBrPBrOBnI8zVEuK7uH2wB+wB*u8!\243\32\24\240!\23\235\30\23r@-pI9g?1hB5lH"
";}_T\177cXeF:U8*K/#H.\"L5 )XB7`LBTH>D;2=7-<8.=9/EB6HB7KB8UJAbTLqd\\\177rh"
"\203umzmdpcZF3 )@-$aQJUE=`QHl`Ti\\S_RIF:3;/( LB;\\TMaZStngNG@D;4G<7>1, 7\"\32"
"D*\36X:, mOB{\\OsPArL;qJ7pD/o?'v@%u7\32u0\20\1772\22\262\17\4\260\30\3\200"
"'\11z/\20s/\23m3\35d.\31d5\40mF4\177cSxYLiL@M0$C'\32;!\26@*!A, \";*\":, #<"
"1( 3+\"/%\34:0&5+$, $\37 )#\40'\36\32 )\35\25:.%I=6H<4MA8\36\21\15\27\14\12A"
"857-%8.%K@8PC<:*&'\31\25\33\22\17\34\24\20""61*65-64.'$\37C<53&\40*\32\24"
"= )\"F1'O5%X;*`?.iA.r@+|G.\205K1\217P2\226O/\226H\"\225?\21\232A\21\316\5"
"\1\316\14\1\243C\26\240M\"\230B\30\220>\27\206>\34\202H+\204V;\204^G\177"
"YHxSEkG:Y9+J, \40P5*H.&@ )\";'!7%\35""4#\33, \35\27#\27\22!\24\17\30\17\15\25"
"\20\17\22\14\13\31\17\11+!\31;3+1 )\40*#\33\30\20\16\23\15\12<74+%\40\34\26"
"\21\34\23\20( \33\30""6%\".\36\33*\37\34""92, _\\SLLBGF<DB63 )\37C3*ZB:sZR\220"
"~uiJ:iC/nB-wE0\206Q:\233fL\243eF\242Q, \250M\36\251C\17\261G\17\276=\21\351"
"%\5\3475\10\301G$\260`9\255fC\237U3\220G&\206D&\210Q9\204S>\200UBvL;]3!X"
"2#]=0eF:X:/U<3R;5S>7J73@/*T>9N:4<+#.\40\31!\31\23%\37\33( $!-( %\33\27\24\17"
"\14\12\"\35\30\35\27\22C>972. )$\40, %#4+( 5-+60-72/KFBRMH@93<5-:0'8'\34<'\35"
"I1%I*\33T0\37U+\30i8!{F.\212V=\236iO\251lN\246Z4\245H\27\262O\31\276T\35"
"\305R\31\3378\24\376O\0\376m\0\355=\"\332\205Y\323\203]\302lB\263_:\245X"
"5\226N.\213L.\211ZB\204[FpI5c= )eA1`@0O1!G, !J1 )='\40""0\37\31""6\"\34B+$D"
", &;'!/\37\27, #\36.'#1+( /, *\31\27\25\15\13\10\10\4\3\13\10\10""6/-6/, FA<]"
"WQ]VRQLIMKFIFBNGBJ?:?/ )A/( I1( M2%V</P6%cD/fA )l@%uC( \212W9\222Y:\234Z7\240"
"P'\245H\30\262M\27\277U\35\314b+\325g/\354?\37\376_\0\376\261\0\376\5\0\342"
"s5\331n5\322p>\317\200Z\304zR\271rK\255kD\244kL\250\200j\240ze\205_G\204"
"cNyXCkL7oTEs^PcPEWG<UD;L;0R@3O=1K;3XJA^QHvh`}tl^VN>7/2. )-*&D?<@:5TNIVOI0"
"( #'\40\32;/&WI=bN@P9+O6( Q6&Q5'U?3fQC\\D4t[IoK4{O6\214_F\217Y=\244mO\244^"
";\256^7\270_4\306g8\323uD\334vC\346\200L\364=\40\376k\0\376\326\0\376D\0"
"\364E\40\346s9\336uB\320f2\313sG\301qC\262c9\247a@\225R4\214P5\204Q6\200"
"S:jA*^:#G*\30C.\37G8*H?5JF=<8-A=.C?/A;1LF=G?7WNFhaXQLBFA8841 )%!:53=74^XT"
"mfaQIC<2+A4 )WF8U<*U: )W:*]>._@1cJ>ycWhQAfJ9nG3tB )\217[>\214K )\236X5\245Q )"
"\264Z.\307nB\323wI\333q>\345r;\357s3\3720\22\376y\0\376\326\0\376\263\0\376"
"\22\0\365o<\353{E\341zH\325qA\306b, \277k=\261gB\252nP\225Y:\234lO\225jL\200"
"U9mC+a<%cC0`E5WA3RA6YL>J?1RG7WK>RE9UIAZOG^TM>4-2+$\37\34\30\34\31\25=:65"
"2/D?;UOIXQKXNFXNCVH;XE6R9, S;/gK?^D7[C6aI:pVF\225\200p\207cN\217_F\217S3\232"
"V3\253a=\270f=\301a2\321n?\332m7\344p8\360v:\365u7\3720\23\376z\0\376\326"
"\0\376\326\0\376y\0\3726\32\365z=\356\203R\344\204W\326r=\310h5\267d:\254"
"fC\225Q-\220X6\211V8\206X:yL0rJ7dA1X9+P7+S?6mYL_K=UC5M:1_MCTD;]PGcYQG<49"
"/'\22\16\14\22\16\13=9640-1, '60*80+7/ )1, '80 )NA6N;2P=5ZE:^E:cH:iN@oO>wR=\177"
"M4\211N0\234[;\264tU\271jE\276^0\316g6\332k7\347vA\363\203P\365~F\364w<\371"
"@\36\376c\0\376\326\0\376\326\0\376\320\0\3767\0\370I!\365z?\355w@\341t="
"\321g1\300^0\263\\4\240Q+\230R+\227\\;\226fF\213_AxR9{]IxdTeUHK;0]J<gUEe"
"SFaPDZJ?RB:^QHl_XSF?F<4\24\21\16\11\7\6""421*'%\40\34\27#\36\31*$\36'\40"
"\35!\33\27""4*$=0'L:/Q<0Y>.sSBqP>yUB\203YB\211Y>\226^?\242b?\257hB\271g;"
"\311sF\325zJ\337yD\351v:\364\202G\365~C\364s5\364s4\366`-\376$\0\376\311"
"\0\376\326\0\376\326\0\376\247\0\376\4\0\366e-\366\202J\357\205P\342|F\330"
"|J\307l:\262X'\246U )\234X.\231c=\221b@\200S6\206bI\204eO\200eSiTFq_Sxg[f"
"VIhXM]PFVJAdUNvh`cRKZMD\15\13\11\4\4\4-, *%\"\40#\35\32""0 )$<50C<8:2, @4, K"
"=4TB7[C5lN:tP9uL4{J/\200I*\216Q-\246f@\251]2\266`1\306k8\322o:\341}G\354"
"\200E\366\210L\366\210L\367\212Q\366\212P\367\220X\367\221[\373-\32\376\215"
"\0\376\326\0\376\326\0\376\326\0\376t\0\3736\36\365\200G\365|@\352m0\335"
"k2\317f-\302e1\271i:\255i<\241g>\230eA\220aB\202U:yO7jG5fK;r\\Ls_QiWJbPD"
"aOCM=3P@7[MEI8/I8/\6\5\5\1\1\1.++#\37\36\34\27\24\33\23\20$\33\31""1'$ )\""
"\35*\36\26:&\32I1%Q5( eB-\200V<\216aD\223aA\227[6\236Z2\257h>\277rF\305k7"
"\323q;\337v<\353y;\365y<\365~B\365z9\365z6\365u.\365x6\365|=\371E\"\376^"
"\0\376\326\0\376\326\0\376\326\0\376\326\0\376Q\0\371>\34\365u5\364p/\347"
"g( \332j0\307Z!\275a.\262f7\245c6\234c;\215V4\200L/tF, oG-qQ<cG4L3\"\\F8XC"
"5RA5K:2: )!C4-, \32\22:( \37\26\26\25\10\10\11""965, '%\"\31\26\"\27\22( \33\26"
"""6 )#4( \40""8 )\37F0!X<( aB.wP8\213_A\215X6\230^:\242`8\250\\/\267d3\307p="
"\324u?\337t6\353t2\366p0\376\2\0\365v4\366\177=\365{7\365x3\366~<\365t1\370"
"M\40\376G\0\376\326\0\376\326\0\376\326\0\376\326\0\376\272\0\376\17\0\366"
"p4\365|<\364z6\347x;\327o7\306`+\272d4\260h;\235Y/\221T1\206O/\203T7yN5m"
"I5oP=cF2W<*^F6cOAeRDcPDcSJVC9lYO\23\23\22\25\26\26PLLE?=0%!&\31\24 )\32\24"
"""4%\36""5'\35""5$\32F, \33Z:%kG/\177S7\225bA\220R+\234X-\261l?\275qC\306"
"o;\323t<\335q2\352u0\370d0\376\22\0\376\7\0\366x1\366}5\365p( \364i\36\365"
"y6\365|=\370U%\376=\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376"
"?\0\370T&\365q, \365x3\361s0\342o1\323k2\304g4\264b0\241T'\227U2\207H'y@\37"
"r@\"qF+gA'bA+Y=-Z?.dK:r\\Lp\\P\\JA.\31\20""3\36\25\10\12\11\3\4\4?<=D>=9"
"/.7-+>3/@3/D4-F0&R8 )W4!`4\34p9\36\212M-\231V1\242U, \253S%\301i:\322{I\332"
"o5\347s6\370d5\3762\0\376\36\0\366`\"\365p )\364o'\364l$\364l$\364j!\364l"
"$\370H\32\376K\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376^\0"
"\370=\25\364d\33\364l%\365v3\354e\40\332^\36\312`&\266S\37\237F\30\237X/"
"\221R, \200I'tD&c7\33`8\37U2\35V9'J/\40K3%fPC{f[\200meR;0:\"\31%''003[Y]M"
"LN.-/\35\35\36\"\40\40/*( 8- )?0'D-#C$\26L\"\17^ )\21p.\17\1770\14\226@\30\246"
"B\24\270G\24\313Q\31\336Y\33\365B\26\376 )\0\376|\0\376\3\0\362X\23\362V\20"
"\362V\17\362W\20\362W\21\362U\15\362S\10\370 )\5\376n\0\376\326\0\376\326"
"\0\376\326\0\376\326\0\376\326\0\376[\0\3672\11\362T\13\362T\13\362W\21\363"
"\\\25\343S\20\314H\13\266E\20\242>\17\221>\26\200:\27r8\31a1\25P$\14F#\17"
"""5\27\10$\17\3\32\13\3\31\13\5\"\24\15K;4o^WM5-'\17\6\25\25\26\26\26\30"
"GFJA@A122( ( &( &$-( %0( \37""3#\31""9\"\25G%\23X+\23i3\25{5\20\214=\23\235?\20"
"\257B\16\306Q\30\333^!\357i, \373\33\12\376\236\0\376\210\0\372\"\10\362^"
"\30\362\\\27\362^\33\363b\40\363b\40\363`\37\366?\22\376\24\0\376\270\0\376"
"\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376E\0\367A\24\363_\34\362"
"^\32\363]\34\364b$\363m-\340f-\314]*\271Y-\244L%\222D\40\207C#y>$n=( `;( V"
":, P7, G2 )6%\35, \34\25F4, iWMS8.B&\35\12\11\14\1\1\1, '( )##0( %9-&:-&?.$J4%Z;"
"( Z5\37g:!zA$\221Q-\243W*\261]+\272T\34\314]\40\335e#\354e!\371E\35\376;\0"
"\376\326\0\376\221\0\373\40\11\365j%\365j$\364h$\364l*\364j'\366U\35\376"
"\17\0\376\235\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376\317"
"\0\376#\0\366^%\364h\37\364c\32\376\11\0\376\17\0\366f%\360m*\336_\40\317"
"]%\274S\37\247@\24\237A\30\224?\33\211?\40\204F, w@, i3\35f8%W0\40D#\26D( \37"
"P943\33\30""0\33\30\25\26\30\10\12\12""3-++\40\35 )\32\25""4\"\33@ )\40J-\40"
"T1\37i<%\200L1\212N.\231W0\246[6\257Z1\303f3\321o7\335s8\353w6\366o, \376"
"\11\0\376\254\0\376\326\0\376\270\0\376\13\0\365k, \365o )\365o-\365r0\365"
"h!\372( \11\376\200\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376"
"\326\0\376\256\0\376\10\0\365d\40\366o( \371A\24\376E\0\376\30\0\366X\27\365"
"g!\354f\40\333\\\32\311V\36\274R!\254H\34\236C\31\223C!\212?\37\207A$\177"
">%f, \33T#\21M#\25H( \37D*&\25\1\1\16\0\0\17\21\20\25\26\25""941/$\37'\31\23"
"/\36\26""8\37\25?\40\25M( \33h:$tB+\203E%\222L&\243R )\264Z, \312n:\325o7\341"
"i )\362r1\371F!\376X\0\376\326\0\376\326\0\376\323\0\3763\0\367[, \365s2\365"
"w9\365u7\367Z$\376+\0\376\320\0\376\326\0\376\326\0\376\326\0\376\326\0\376"
"\326\0\376\326\0\376t\0\3725\25\365p )\366]\31\376\27\0\376\256\0\376!\0\366"
"^&\365q/\365m'\342b!\322`'\301\\( \252L\37\231B\32\217C\34\207A\37w6\32n4"
"\34h7#Y1!_>0eL@^I@5\36\23""0\31\14\0\0\0\1\1\1+&$( \35\30/#\31> )\36E )\31I"
"+\32^8$sA'\177D$\215P.\235R( \255Z*\277d0\315h/\337w;\360\203G\366{<\376\10"
"\0\376\257\0\376\326\0\376\326\0\376\326\0\376d\0\371@\36\365p.\366z<\366"
"\200E\3736\35\376}\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376"
"\326\0\376\322\0\376-\0\370^( \366w3\372@\35\376g\0\376\326\0\376u\0\3735"
"\33\366z:\365l&\354h$\337t<\317l;\273[, \255W.\224D\33\204@\31\200F#xF )wN"
"7vT@~cS~k`qbZPC9N?7\2\2\0\1\1\1*&&$\32\27\36\21\15( \26\17""7\34\23E%\27e"
"8\37xB%\203K*\220I\"\240N\40\257R\37\274R\33\320[\37\343g#\364k#\367A\15"
"\376H\0\376\326\0\376\326\0\376\326\0\376\326\0\376\207\0\372#\12\364`\32"
"\364c\34\366_\37\376\23\0\376\300\0\376\326\0\376\326\0\376\326\0\376\326"
"\0\376\326\0\376\326\0\376\214\0\376\1\0\365j\"\365`\35\376\15\0\376\270"
"\0\376\326\0\376\322\0\376U\0\371-\14\365i\"\364h\36\344a\34\322Z\35\273"
"H\20\255L\34\231B\27\207=\24u2\15e*\13h8\35c>'\\A0|i\\\236\222\207\222\205"
"}dWM\4\3\0\1\1\1.* )!\32\27\33\20\15%\25\17>'\36R7*oI5rA( }=\37\231P-\253X"
".\271[+\306[%\332i )\353g\40\365s.\3731\30\376\203\0\376\326\0\376\326\0\376"
"\326\0\376\326\0\376\223\0\373!\12\364j#\365l'\367G\30\376F\0\376\326\0\376"
"\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376\317\0\376+\0\366I\21\365"
"j\37\370T\35\3768\0\376\326\0\376\326\0\376\326\0\376\316\0\3763\0\371>\30"
"\365k$\356b\31\333]\34\312\\#\266O\35\245M\40\226N&\206G$}G+pB( M( \23A%\25"
"XE6seY`REL<.\26\22\12\5\4\2""2-+'\34\31-\33\23""5!\26J+\36Y8 )jC.u<!\211D"
"!\237X2\262b9\303l>\317e/\341m0\363o*\364a\27\376\3\0\376\241\0\376\326\0"
"\376\326\0\376\326\0\376\326\0\376\244\0\374\31\10\367Z\37\367h*\3728\30"
"\376n\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376\233"
"\0\374\36\14\376\3\0\366T\30\370F\27\376L\0\376\326\0\376\326\0\376\326\0"
"\376\326\0\376\266\0\376\26\0\367U\40\366w3\345i( \324c )\301\\ )\261[0\241"
"Z3\222T1\206Q1\201V=rR>mSBfRCN=2\31\11\5\20\6\5\21\16\7\26\20\12C;6:, $<'"
"\35C+\37P/\37a6#n?'\203C!\225M$\244S )\262W( \305c/\324b'\345]\25\365i\34\364"
"^\23\376\3\0\376\247\0\376\326\0\376\326\0\376\326\0\376\326\0\376\316\0"
"\376S\0\376+\0\376\24\0\373, \21\376\203\0\376\326\0\376\326\0\376\326\0\376"
"\326\0\376\326\0\376\322\0\376:\0\371N\37\376#\0\376'\0\370O\35\376>\0\376"
"\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376\211\0\376\1\0\366u3\355"
"h#\332b$\314g3\263V'\245\\4\214H$}@\40|K3uR?nRCiSDbOC6$\32\"\22\12\2\1\1"
"\25\15\11E837%\35-\34\24""4\37\26<\35\21N\37\14d*\16{5\23\215>\24\233?\23"
"\261J\27\300K\20\330[\33\355`\27\363U\11\363[\17\373!\10\376\214\0\376\326"
"\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376\303\0\376\35\0\373"
"!\13\376\224\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376s\0\372"
" )\10\365c\40\376\13\0\376\203\0\376\23\0\376\15\0\376\267\0\376\326\0\376"
"\326\0\376\326\0\376\326\0\376\326\0\376E\0\371D\31\365x5\337a!\313^%\260"
"I\26\240H\33\222F\36}8\25t9\33U.\33U7'mWI\213yl\205p_nVD\0\0\0\2\2\2""0+"
"*#\30\24$\25\20""1\35\25>!\26V*\30o3\27\200;\30\220C\34\242G\33\267P\36\314"
"[$\335[\31\362Z\16\364g\36\364f\36\367@\14\376E\0\376\326\0\376\326\0\376"
"\326\0\376\326\0\376\326\0\376\326\0\376\272\0\376\13\0\373\35\11\376\231"
"\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376P\0\373#\10\372 )"
"\10\376\5\0\376\266\0\376p\0\3712\21\376C\0\376\322\0\376\326\0\376\326\0"
"\376\326\0\376\326\0\376\257\0\376\13\0\366w9\350t8\325k2\301a-\260\\/\237"
"S+\217L*\177C'h;$aA-v^O\213zm\217|n\213uf\22\15\12\15\13\14;65-#!'\27\21"
"+\23\13""7\30\13S&\22v9\32\206?\33\222>\27\244D\31\273O\32\322`&\345d\37"
"\364f\35\364d\34\364h\40\364f\40\373\"\12\376\217\0\376\326\0\376\326\0\376"
"\326\0\376\326\0\376\326\0\376\306\0\376\24\0\373!\14\376\224\0\376\326\0"
"\376\326\0\376\326\0\376\326\0\376\326\0\376\312\0\376\210\0\376x\0\376\241"
"\0\376\326\0\376\270\0\376\14\0\373*\22\376\210\0\376\326\0\376\326\0\376"
"\326\0\376\326\0\376\326\0\376?\0\370Q\"\360\177E\331d )\311g4\274lB\245^"
"7\215K( \211Q2yL4kL9YE7`QFYJ<lZLF;6XMH\207{vsaZC.&2\32\20""8\33\15H\37\15"
"a$\11\204:\24\227E\33\260S#\302W\34\321Q\23\350^\30\365p( \365q-\370L\33\376"
"\7\0\376\23\0\376\23\0\376\245\0\376\326\0\376\326\0\376\326\0\376\326\0"
"\376\325\0\376J\0\371+\12\376u\0\376\326\0\376\326\0\376\326\0\376\326\0"
"\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376\303\0\376"
"\23\0\371B\32\376Z\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376"
"a\0\3719\21\363j&\337g, \316i9\274e:\245V0\223P.\177B%h:$M0#0$\36""3, ( .\""
"\30UF;\27\17\13""8+$od_hWP]H>^E:hI9`7#`( \17\2004\21\2178\17\250C\23\301O"
"\30\327X\31\354Z\17\364^\21\367E\21\376\15\0\376\230\0\376c\0\3719\22\376"
"\31\0\376\303\0\376\326\0\376\326\0\376\326\0\376\326\0\376\273\0\376\27"
"\0\376\24\0\376\276\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376"
"\326\0\376\326\0\376\326\0\376\313\0\376H\0\371;\32\373.\26\376\206\0\376"
"\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376C\0\367L\33\365s.\341d"
"$\311Z$\273b6\250Z4\234Z:\221]C{Q<cE5;, &*&$%\33\25aUL\0\0\0\7\6\5:42/#\37"
", \34\25""0\33\23D%\31O )\30X&\17\1773\15\226@\23\253C\21\302K\24\331X\30\360"
"]\24\366L\14\376\10\0\376\226\0\376\326\0\376\214\0\373#\11\372\"\10\376"
"\211\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376\250\0\376\27"
"\0\375v\0\373\324\1\373\323\1\372\323\1\374\324\0\375\325\0\376\326\0\376"
"\326\0\376\316\0\376A\0\3728\31\372, \16\376P\0\376\322\0\376\326\0\376\326"
"\0\376\326\0\376\326\0\376\263\0\376\15\0\365i&\365};\351z=\325o7\300d5\253"
"Z0\234U0\213P2vI1eF5K9/:1+\33\24\16@94%\40\35\32\26\23?620!\34*\26\17""3"
"\31\17H%\27U, \31[ )\16y.\11\2238\12\253C\16\303L\21\334W\30\363b\32\372*\13"
"\376z\0\376\326\0\376\326\0\376\270\0\376\13\0\3709\16\376Z\0\376\326\0\376"
"\326\0\376\326\0\376\326\0\376\326\0\375\326\1\375\303\1\375\300\3\355\312"
"\17\245\215!\237\200\15\334\267\3\367\317\0\373\323\0\375\325\0\376\310\0"
"\3762\0\376-\0\376|\0\376\322\0\376\326\0\376\326\0\376\326\0\376\326\0\376"
"\323\0\376?\0\371H$\365s/\366~>\355y:\331p6\307h3\262Z*\240Q%\214H!\200S"
"6qN:cM@XMG\30\25\22\23\21\17;3, -%\37F:45#\34""4\35\23I-\40Y7( d7%j1\27{/\16"
"\2268\15\253C\20\310M\20\336U\20\367C\17\376>\0\376\324\0\376\326\0\376\326"
"\0\376\321\0\376*\0\370D\26\376L\0\376\326\0\376\326\0\376\326\0\375\325"
"\0\376\326\1\376\326\0\375\326\6\352\314.\263\246l569#\40\40; )\1\224v\1\333"
"\266\0\366\317\0\373\323\0\375\317\0\376\322\0\376\326\0\376\326\0\376\326"
"\0\376\326\0\376\326\0\376\326\0\376g\0\3724\30\366\200B\365s/\365w3\357"
"s/\330c$\312j3\267`-\245W*\223P*\201Q5nH1r]Opf_\"\37\33\0\0\0\36\31\23\33"
"\25\17=502\"\33, \30\17>'\34T7 )f?-u>'\212F )\250Q, \265U*\312X\"\336W\26\373"
"\40\12\376\223\0\376\326\0\376\326\0\376\326\0\376\326\0\376=\0\3729\32\376"
"n\0\376\326\0\375\325\0\375\326\0\376\326\0\376\326\0\370\323\17\347\316"
"H\341\327\250mkd\3\3\0'( *\0\1\3\5\2\0<+\0\224v\0\332\265\0\366\317\0\372"
"\323\0\375\325\0\376\326\0\376\326\0\376\326\0\376\326\0\376\207\0\376\1"
"\0\365_\34\366z7\366~=\366z6\361u2\336j*\312b'\273b.\254].\226R+\200N0yU"
"?\202l_\211~wQMI\"!\37\2\1\0\11\7\2.*&\40\27\21\37\20\11, \27\15""8\35\20"
"C\40\21` )\20v1\21\2319\16\260F\24\304Y!\340e&\374\25\10\376\256\0\376\326"
"\0\376\326\0\376\326\0\376\326\0\376\200\0\376K\0\375\302\0\375\325\0\376"
"\326\0\376\326\0\373\324\5\356\314\33\347\317Y\357\342\251\263\255\226\25"
"\23\12\1\1\0!!#\21\22\22\0\0\0\0\0\0\6\2\0<*\0\230z\0\335\270\0\370\320\0"
"\373\323\0\375\325\0\376\326\0\376\271\0\376\20\0\370['\365l\"\365d\36\366"
"p.\366s+\363u.\341o.\316h, \276b.\254Z )\227P%}H )wS;\210qa\227\213\202uniP"
"NJ\26\24\13\30\30\20""62+&\35\26\"\26\14( \30\14-\27\12""7\27\10V!\10p.\16"
"\2165\13\2479\10\272C\16\330P\20\371#\7\376\206\0\376\326\0\376\326\0\376"
"\326\0\376\326\0\376\326\0\375\325\0\376\326\0\376\326\0\367\321\7\347\305"
"\26\337\3039\352\325s\355\337\246\220\204yGD9\4\3\0\0\0\0\16\16\16##%\0\0"
"\0\0\0\0\0\0\0\0\0\0\5\2\0>-\0\230{\0\336\271\0\371\321\0\373\324\0\375\211"
"\0\373%\14\365j#\371M\36\376\14\0\376\15\0\366s1\365{6\343u5\321n2\301h0"
"\261b0\234X+xG&kF.u^N{mdME>1+%CC934+C@:3+$2'\35""6( \35<( \32D )\33]2\35t;\37"
"\206<\31\251D\24\277N\30\322V\32\361K\22\376\34\0\376\262\0\376\326\0\376"
"\326\0\376\326\0\376\326\0\375\325\0\366\316\4\335\272\21\312\260;\332\307"
"y\346\327\236\343\327\265\32\22\21\203\200\177\6\5\0\1\1\0\0\0\0\2\2\2''"
" )\6\6\7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0<-\0\246\210\7\360\312\3\375\300"
"\0\3765\0\376\7\0\376I\0\376\203\0\376A\0\370R\35\364u )\341l&\317f'\272U"
"\32\257Z'\235W+o;\35_9\"[B1VF<\37\25\14\22\7\1KKA[[Snmea[QRF<A1&6\"\25""7"
"\36\20Q+\30o:!\204A\40\240A\23\273G\20\313M\20\351^\27\3707\13\376\36\0\376"
"\231\0\376\326\0\376\326\0\376\326\0\374\324\1\307\245\21\221\201:\245\233"
"o\264\253\222\302\274\263\252\244\252\253\251\270\36\34\34\1\1\0\0\0\0\0"
"\0\0\0\0\0\34\34\35\30\30\31\0\0\0\0\0\0\0\0\0\0\0\0\5\5\5\13\14\15\34\34"
"\36ME/\342\277\10\376\326\0\376\315\0\376\271\0\376\311\0\376>\0\376I\0\371"
"L\32\362o\"\336`\30\314]\36\275Z\"\252L\30\231M#xD*\\2\35K/\37E5+\"\32\20"
"/&\36\33\34\23\32\32\25""52/4/'?5 )O?2J4%J0!eB0s?&~<\35\217:\21\262D\20\311"
"U\35\342_\35\364`\24\367>\10\376\2\0\376C\0\376\246\0\376\326\0\374\324\0"
"\305\245\10""91\10""0, \30;8.GEDfenPPY\17\17\17\6\6\7\2\2\2\0\0\0\0\0\0\12"
"\12\13, , .\17\17\20\26\26\27\33\33\35\35\36\37\35\35\37\34\34\36\22\22\24"
"i[\13\362\315\2\375\325\0\376\326\0\376\257\0\376, \0\373:\27\376c\0\372="
"\23\361p#\337j&\320e, \300\\'\266^/\235S.\206W>\201ZDfM@N?80( \"PGB87*47.:"
"83+&\35.$\31""7( \35= )\36""8!\23N.\36e8\"t8\32\2007\24\251K\34\304O\24\327"
"V\25\362k#\365b\27\365h\35\370A\21\376\12\0\376\237\0\373\324\0\346\302\2"
"O@\1\2\2\0\4\3\0\2\2\1\4\4\4\33\33\34++.( ( *$$%\40\40!\36\36\40'' )DDH//1\40"
"\40\"\16\16\17\7\7\7\1\1\1\0\0\0\1\1\0\245\213\4\371\322\0\375\325\0\376"
"\314\0\376#\0\371E\31\376\11\0\376\201\0\373, \15\356q&\335m+\313^$\272V!"
"\263\\.\231T1o?'iE2H2( 9.*\14\11\10\34\33\31( %\35""53( B<53*!1%\35/\40\27""8"
"#\32@( \33P1#]1\36u:!\205A\"\243L#\300Q\31\321\\\36\350d\37\365k\"\365k\36"
"\365o$\371<\21\376c\0\374\324\4\334\274\26w_\6\10\4\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\2\2\2\4\4\5\6\6\6\7\7\10\20\20\20**-\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0( \40\0\327\265\0\373\323\0\376\326\0\376\316\0\376<\0\373'\15\376"
"C\0\376\222\0\373%\15\352p( \333p0\312h/\275e3\263e6\227X3h>%]<( R?4QGB\35"
"\33\32\17\17\16\25\16\13\33\22\13""8.( 6+#B3, Q@7cNDoSFrQAoC0|F.\212M0\237"
"R-\272S!\315a*\340f%\364z6\365n$\365k\40\365<\24\355|3\350\323g\213|*?7\13"
"\22\13\0\17\6\0\6\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\27\27\30"
"\34\34\35\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0v`\0\363\315\0\375\325\0\376"
"\326\0\376\326\0\376\311\0\376\215\0\376\303\0\376s\0\3728\25\346r.\324j"
"*\306g0\265^+\260d9\217P-kB )`@.\\I?VNI$!\37\23\21\20I>7C82MD>F:4D7/SB8r\\"
"R|_S}ZLqD2l6\37w8\33\211E%\245F\30\311f2\330p9\350n0\356l*\320zP\304\207"
"\220qg_\227\221z'!\0, ( \26\7\7\4\0\0\0\10\3\0\13\3\0\3\1\1\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0$$%\14\14\14\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\34\22\4\275\233"
"\1\372\323\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0"
"\376, \0\363b+\341x:\323r9\307o?\270e9\253_8\213N/a:%O0!<, $4., \17\17\16\16"
"\16\15RD>WICgZUXHC?.':&\35P7.hK@zWJ\200VFzE0\177B( \204C%\226B\30\271U%\311"
"e3\331d )\224Z:\200\177\217\277\277\337\265\263\313\40\37\32\11\10\0\22\21"
"\17\17\17\16\2\2\2\4\5\5\11\11\12\37\32\31\7\6\6\0\0\0\0\0\0\0\0\0\5\5\5"
"( ( )\3\3\3\0\0\0\1\1\1\7\6\6\34\33\36VV[\217\210xK>\30\261\217\1\376\326\0"
"\376\326\0\376\326\0\376\326\0\376\307\0\376d\0\3730\21\347t0\332r5\312h"
"/\273_.\255Z-\237S )\211O1X0\33B&\26J8/`WRROLIFC\32\12\7( \31\23L<:J82:%\37"
"""5\37\30A&\37S4 )c@4pE7vD/zA'\201@\40\220E\40\252G\26\301R\35\326d, \177A"
"!\16\16\17$$( ) )/\17\17\20\21\21\22\27\27\31'' )\21\21\22\22\22\22\16\16\17"
"\12\12\12\1\1\1\0\0\0\0\0\0\0\0\0\20\20\21\"\"#\0\0\0\0\0\0\10\6\5%#'st\205"
"\273\272\323769\0\1\2\14\14\14jP\0\366\203\0\376r\0\376U\0\376\35\0\3727"
"\23\356i#\337n-\320j.\302c, \265]-\240N\"\225K#\207K+^5!;\37\22/\40\30""9"
"0+#\37\32\40\36\31\35\14\10\26\6\2<, ( F2.E/*K4, V:0X7+\\:-f=, j<'q:!\205E&\231"
"V2\251U )\275X$\311Q\27\305X\35\40\13\2\0\0\0\0\0\0\4\4\4\5\5\5\16\17\17\31"
"\31\32\1\1\1\0\0\0\0\0\0\10\3\0\4\1\0\4\1\0\0\0\0\0\0\0$$&\22\22\24\0\0\0"
"\5\1\0\11\1\0\22\12\2, ( !PLJ\25\24\20\11\11\10\23\24\25\5\5\5I\16\5\3232\24"
"\371?\16\366\\\27\361p$\342f\37\323a\37\305_$\262O\31\260\\/\234Q'\210?\32"
"\200G )pF1W<0\\KCjb\\he_mlfE6/>0*UEAQ>:@*$3\34\24""7\33\23@!\26R1#a: )c7#h"
"7\40w?\"\216Q0\242\\3\270b0\307b*\324a\"\1779\21\1\1\0\0\0\0\0\0\0\0\0\0"
"\23\23\24\11\11\11\0\0\0\0\0\0\35\22\0\241\201\0\234}\0\207j\1oY\2fR\3j["
"\20iU\10sZ\3\216l\1\251\204\0\233|\0&\40\0\15\13\0\6\6\4\11\11\12\36\37\40"
"\21\21\22\11\12\13\222E\30\365q$\362g\32\343_\26\322R\14\302L\11\272W\36"
"\252M\33\234D\27\216C\32}8\23t;\36rJ7\202h\\\211zq\213\202~{wszxr;, %:-'I"
";6B2+B-&@( !9\33\23<\33\20L, \37c?.g=+f7!l6\33\200B\"\222L'\247R&\272T\37\305"
"O\26\277R\31*\21\3\1\0\0\0\0\0\1\1\2\30\31\32\2\3\3\1\0\0\3\1\0\205d\0\373"
"\323\0\372\322\0\370\320\0\365\316\0\362\314\1\361\313\1\362\314\1\365\316"
"\0\370\320\0\373\323\0\363\313\0XB\0\0\0\0\0\0\0\0\0\0\21\21\22\1\2\2\0\0"
"\0\255E\17\362b\27\346h%\326X\25\307Q\21\272P\25\256M\31\235E\30\232N#\217"
"J( q3\30l3\34`8 )jNAkZQ`WP51+( %\40>/*D72L@9M>7bNFpZQmSHpSG{]R}[LsL:j>*s@( \200"
"D%\207E#\235P'\267^/\275S\32\314[\36\263R\35\212<\21y5\21e\32\14g\36\17o"
"I\2\220n\0\266\224\0\361\312\0\376\326\0\376\326\0\376\326\0\376\326\0\376"
"\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\314\246"
"\0WF\0-!\0\25\20\4\33\25\24\20\5\2""6\23\3\332V\21\345a\33\326U\22\313V\26"
"\272H\14\263O\33\243F\24\224>\21\2068\16\177;\30n1\26c-\27I$\24K0%ZI?jbY"
"LHA;81OD=ND=LA<G95TE=cQJgSHkSGqYLtTDqM<g<( p>&}F )\206J*\224O )\256[/\264S\40"
"\301Y!\315\\\35\332a\34\347i\40\363p%\371?\24\376\31\0\376\210\0\376\316"
"\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0"
"\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376\326\0\376\316\0\361"
"\236\0\337D\1\317%\13\324W\25\342Y\21\341V\16\327\\\32\310R\22\275P\26\261"
"K\25\243C\20\233E\27\234P( \213B\36w6\27g, \23`-\31I$\26C( \34ZI?ypgqoehg]1"
" )!%\35\26/#\37&\32\30+\37\32&\33\25""0\"\32A, #>( \37O0#c=+mE0xG/\200H*\211"
"N.\224Q-\243T, \256V )\271Y'\301V\34\320b&\331a\40\345j&\357l#\370Q\24\373"
"( \14\376%\0\376Y\0\376}\0\376\225\0\376\246\0\376\257\0\376\263\0\376\263"
"\0\376\260\0\376\251\0\376\231\0\376\206\0\376o\0\376N\0\376#\0\376\4\0\370"
">\16\364`\25\352^\24\337X\23\320K\15\310O\23\275L\26\262G\25\251H\32\234"
"A\27\235J( \221C\"\1778\34u4\32g-\27U%\24A\36\22""4\30\16""4!\32:1, &$\34&"
"%\32\10\3\1\26\11\4""7, %?3, L<4?0 )0\40\26""3\34\20/\26\13<\37\22U.\34Y/\33"
"k9\"v<!~>\37\205?\35\217A\34\231D\31\250M\37\255E\22\271G\21\306O\26\321"
"W\31\336b\36\346e\40\355^\21\363I\12\366<\17\370-\14\372!\11\372\27\6\372"
"\23\5\373\21\4\373\22\6\372\26\11\372\31\11\371\37\11\370*\20\3673\20\366"
"I\35\364Z\40\363g\37\353a\34\337U\20\327U\20\312O\20\300V\40\261H\26\242"
"9\14\234;\16\2126\16\2047\25\2014\25\2007\26l( \15X\33\7T!\17D\33\20""0\22"
"\13$\16\11\"\24\20#\36\34\3\2\2\0\0\0 )\36\31*\33\25""3$\36 )\27\24, \31\25"
".\35\25.\34\22""1\34\21/\31\20""4\36\23<\37\21U1\40T, \27`0\27g1\25m2\24z"
"9\32\2009\31\215A\34\224@\21\242H\25\261V%\265Q\35\301Y\37\313`*\320[\36"
"\324U\20\331]\26\337d\36\340d\34\341f\36\341[\21\337X\20\340i$\341f!\340"
"e\36\341`\30\341e\36\340^\33\333[\31\326X\31\317Z\35\311V\32\303P\26\271"
"J\25\253@\20\250F\27\235?\22\223:\23\215;\24\2020\13~5\31o+\22f+\23h.\33"
"a*\27M\"\25@\33\22H+\40VA6fVMng_MMC79/B0, <*&6%\"\40\16\12\31\6\3!\15\6""0"
"\36\27""8$\33""3\40\27, \30\17+\25\13""5\33\17""4\30\14?\37\20I%\23U-\32c"
"6\36d2\30n6\31p1\16s.\12|3\21\2037\21\226J\36\250U'\257X )\254N\33\253J\30"
"\260N\33\260L\31\262I\23\266I\17\275N\23\300W\36\277Y\"\274T\35\275X$\275"
"^/\275c5\267O\34\261P\40\256X.\240G\35\233E\35\216;\21\2066\17\1772\20\200"
"7\30\206>\37\203=\35{8\35j.\26a+\26^, \30i4\"m=, g=0W6*Z@6oZO\215\200u\242"
"\234\222\220\216\203mmaC.+H30R<:C, *7\40\33""8\40\33E/*P93W@8T<2N5*P1'K-#"
"F( \34T2\40oL6\202\\D\200YAyM5~L.|D${@\40y<\32\202>\32\222N( \232M#\241P&\253"
"Y/\260X+\261\\.\250O\40\247I\30\263V%\274e7\270c3\261Z+\261^1\262_4\260c"
";\247T*\240P( \232P, \226M+\216I*\207J/~A'w:#p3\37~C.\210P=\213XI\200OBuE7"
"l>1rH;rL@mKBlOCgODn[P\201uh\231\223\211\243\242\226\231\231\214L40M40[@<"
"T84G+( D )%M3-P92S=6Q>8[G?[D=Q:3R;/YA5eK>lP?sS@uR<zT={S:wJ0sC'wB%\204Q3\207"
"P3\207L/\220T7\225S4\223Q2\212J*\203B\"\212K+\223Y;\216V7\217[;\225cC\222"
"]@\214\\AxJ1qE-j@*h>*mA/pC1j=, ^2#V*\36W-\"[9/[=5]A8Z=5P4, D, %>( !@, %<+$0\""
"\34+\37\31""6-%IE?IJDPQJ, \36\34%\27\25""3$!, \34\31%\26\25'\31\27""3$\40:"
"+ );20C96SGBZNH\\OIXKFbUOcTL\\MG`NFfRFmWKoXJv_RpUGoPBsTCtTEoN@pPBnM?gH;bF"
"9]A4X?1W=0S9+V@3\\E7ZC4O:.B1&<-%7*\"2$\35""7%\36=&\37:$\36""3!\33""1\35\30"
"/\36\31( \35\31#\33\27#\32\27#\33\30%\35\32( !\35&!\35%\40\35-'%3., 3/, *&%\""
"\36\34\5\4\2\7\6\5\6\4\3\7\5\4\5\3\2\10\6\5\22\20\17\34\32\31\23\22\20\23"
"\22\22""20/0.-*'%, )'#!\40 )'%@<:\31\26\25?<:732_XW.**D?>'%$\21\21\22 )%$:5"
"3\31\30\27+'%\34\32\30\27\25\24\30\26\25\32\25\24\34\25\23\33\30\27\34\33"
"\33\27\26\26\27\25\25\30\25\24\27\24\21\22\16\15\24\21\17\20\16\14\30\23"
"\20\35\26\23\"\31\27*!\37\37\34\32\25\23\21\36\33\31#\34\30'\40\33""40-3"
"30>?=TUSddaffbYXUgec\215\211\207\230\225\221zuqQIE>6292.( \40\31""2 )\"3*#"
"90*B:3G?8C:3<1+4+#1'\40;1*F;4>6/2 )\"90 )OFA\\UO[TOUOJNJEOIEVQN_[Vic^mgcle"
"`d\\W]VPYQKWPHYOG]SMf[Th^XcYRWMGNC;F;2;1 )2 )!2'\36""9.$G9/SD;WJ@RE;K>4H=4"
"I@6IC<MLHUXT`ebqus\200\201\200wxu__[`a\\\203\201\177\232\224\221\213\204"
"\201sjig]\\\\SO",
};
///We'll use the emberIcon struct
SDL_Surface * iconSurface = SDL_CreateRGBSurfaceFrom( emberIcon.pixel_data, 64, 64, 24, 64*3,
rmask, gmask, bmask, 0 );
if ( iconSurface ) {
SDL_WM_SetIcon( iconSurface, 0 );
}
#endif
setStandardValues( );
return true;
}
else
{
return false;
}
}
713 void OgreSetup::setStandardValues( )
{
/// Set default mipmap level ( NB some APIs ignore this )
Ogre::TextureManager::getSingleton( ).setDefaultNumMipmaps( 5 );
/// Set default animation mode
Ogre::Animation::setDefaultInterpolationMode( Ogre::Animation::IM_SPLINE );
///remove padding for bounding boxes
Ogre::MeshManager::getSingletonPtr( )->setBoundsPaddingFactor( 0 );
///all new movable objects shall by default be unpickable; it's up to the objects themselved to make themselves pickable
Ogre::MovableObject::setDefaultQueryFlags( 0 );
}
729 EmberPagingSceneManager* OgreSetup::chooseSceneManager( )
{
/// Create new scene manager factory
EmberPagingSceneManagerFactory* sceneManagerFactory = new EmberPagingSceneManagerFactory( );
/// Register our factory
Ogre::Root::getSingleton( ).addSceneManagerFactory( sceneManagerFactory );
EmberPagingSceneManager* sceneMgr = static_cast<EmberPagingSceneManager*>( mRoot->createSceneManager( Ogre::ST_EXTERIOR_REAL_FAR, "EmberPagingSceneManager" ) );
///We need to call init scene since a lot of components used by the scene manager are thus created
sceneMgr->InitScene( );
return sceneMgr;
}
745 void OgreSetup::parseWindowGeometry( Ogre::ConfigOptionMap& config, unsigned int& width, unsigned int& height, bool& fullscreen )
{
Ogre::ConfigOptionMap::iterator opt = config.find( "Video Mode" );
if ( opt != config.end( ) ) {
Ogre::String val = opt->second.currentValue;
Ogre::String::size_type pos = val.find( 'x' );
if ( pos != Ogre::String::npos ) {
width = Ogre::StringConverter::parseUnsignedInt( val.substr( 0, pos ) );
height = Ogre::StringConverter::parseUnsignedInt( val.substr( pos + 1 ) );
}
}
///now on to whether we should use fullscreen
opt = config.find( "Full Screen" );
if ( opt != config.end( ) ) {
fullscreen = ( opt->second.currentValue == "Yes" );
}
}
}
1 //
// C++ Interface: OgreSetup
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGREOGRESETUP_H
#define EMBEROGREOGRESETUP_H
#include "EmberOgrePrerequisites.h"
namespace EmberOgre {
30 class EmberPagingSceneManager;
/**
A class used for setting up Ogre. Instead of creating the Ogre root object and the main render window direclty, use this to guarantee that everything is set up correctly.
@author Erik Hjortsberg <erik@katastrof.nu>
*/
36 class OgreSetup{
public:
38 OgreSetup( );
40 ~OgreSetup( );
/**
* Creates the ogre base system.
* @return
*/
46 Ogre::Root* createOgreSystem( );
/**
* Configures the application - returns false if the user chooses to abandon configuration.
* @param
* @return
*/
53 bool configure( void );
/**
* Gets the main render window.
* @return
*/
59 inline Ogre::RenderWindow* getRenderWindow( ) const;
/**
* Gets the Ogre root object.
* @return
*/
65 inline Ogre::Root* getRoot( ) const;
/**
* chooses and sets up the correct scene manager
* @param
*/
71 EmberPagingSceneManager* chooseSceneManager( );
/**
* Shuts down the ogre system.
*/
76 void shutdown( );
private:
/**
Holds the Ogre root object.
*/
83 Ogre::Root* mRoot;
/**
Holds the main render window.
*/
88 Ogre::RenderWindow* mRenderWindow;
/**
* Attempts to parse out the user selected geometry options for ogre.
* @param config The option map, usually found inside the currently selected RenderSystem.
* @param width The width of the window in pixels.
* @param height The height of the window in pixels.
* @param fullscreen Whether fullscreen should be used or not.
*/
98 void parseWindowGeometry( Ogre::ConfigOptionMap& config, unsigned int& width, unsigned int& height, bool& fullscreen );
/**
Sets standard values in the ogre environment.
*/
103 void setStandardValues( );
};
107 Ogre::Root* OgreSetup::getRoot( ) const { return mRoot;}
108 Ogre::RenderWindow* OgreSetup::getRenderWindow( ) const { return mRenderWindow;}
}
#endif
1 //
// C++ Implementation: OpcodeCollisionDetector
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "OpcodeCollisionDetector.h"
#include "ogreopcode/include/OgreCollisionManager.h"
#include "ogreopcode/include/OgreEntityCollisionShape.h"
#include "ogreopcode/include/OgreCollisionObject.h"
#include "EmberOgrePrerequisites.h"
#include "EmberEntityUserObject.h"
#include "OpcodeCollisionDetectorVisualizer.h"
#include "model/Model.h"
#include "model/SubModel.h"
namespace EmberOgre {
37 OpcodeCollisionDetector::OpcodeCollisionDetector( Model::Model* model ) : mModel( model ), mVisualizer( 0 )
{
buildCollisionObjects( );
}
42 OpcodeCollisionDetector::~OpcodeCollisionDetector( )
{
destroyCollisionObjects( );
}
47 void OpcodeCollisionDetector::reload( )
{
destroyCollisionObjects( );
buildCollisionObjects( );
}
54 void OpcodeCollisionDetector::destroyCollisionObjects( )
{
OgreOpcode::CollisionContext* collideContext = OgreOpcode::CollisionManager::getSingletonPtr( )->getDefaultContext( );
for ( OpcodeCollisionDetector::CollisionObjectStore::iterator I = mCollisionObjects.begin( ); I != mCollisionObjects.end( ); ++I )
{
OgreOpcode::ICollisionShape* shape = ( *I )->getShape( );
collideContext->destroyObject( *I );
OgreOpcode::CollisionManager::getSingleton( ).destroyShape( shape );
}
mCollisionObjects.clear( );
}
67 void OpcodeCollisionDetector::buildCollisionObjects( )
{
OgreOpcode::CollisionContext* collideContext = OgreOpcode::CollisionManager::getSingletonPtr( )->getDefaultContext( );
const Model::Model::SubModelSet& submodels = mModel->getSubmodels( );
for ( Model::Model::SubModelSet::const_iterator I = submodels.begin( ); I != submodels.end( ); ++I )
{
Ogre::Entity* entity = ( *I )->getEntity( );
// if ( entity->isVisible( ) ) {
std::string collideShapeName( std::string( "entity_" ) + entity->getName( ) );
OgreOpcode::EntityCollisionShape *collideShape = OgreOpcode::CollisionManager::getSingletonPtr( )->createEntityCollisionShape( collideShapeName.c_str( ) );
// if ( !collideShape->isInitialized( ) ) {
collideShape->load( entity );
// }
OgreOpcode::CollisionObject* collideObject = collideContext->createObject( collideShapeName );
collideObject->setShape( collideShape );
collideContext->addObject( collideObject );
mCollisionObjects.push_back( collideObject );
// }
// collideObject->setDebug( true, false, false, false );
/* collideShape->setDebug( true );
collideShape->visualize( );*/
/*
EmberEntityUserObject* userObject = new EmberEntityUserObject( this, getModel( ), ( *I )->getEntity( ), 0 );
( *I )->getEntity( )->setUserObject( userObject );*/
}
}
97 void OpcodeCollisionDetector::refit( )
{
for ( OpcodeCollisionDetector::CollisionObjectStore::iterator I = mCollisionObjects.begin( ); I != mCollisionObjects.end( ); ++I )
{
( *I )->refit( );
}
}
106 void OpcodeCollisionDetector::testCollision( Ogre::Ray& ray, CollisionResult& result )
{
for ( OpcodeCollisionDetector::CollisionObjectStore::iterator I = mCollisionObjects.begin( ); I != mCollisionObjects.end( ); ++I ) {
OgreOpcode::ICollisionShape* collisionShape = ( *I )->getShape( );
OgreOpcode::CollisionPair pick_result;
if ( collisionShape->rayCheck( OgreOpcode::COLLTYPE_QUICK, mModel->_getParentNodeFullTransform( ), ray, 1000.0f, pick_result, false ) ) {
result.collided = true;
result.distance = pick_result.distance;
result.position = pick_result.contact;
return;
}
}
}
122 void OpcodeCollisionDetector::setVisualize( bool visualize )
{
if ( visualize ) {
if ( !mVisualizer ) {
mVisualizer = new OpcodeCollisionDetectorVisualizerInstance( *this );
}
} else {
delete mVisualizer;
mVisualizer = 0;
}
}
134 bool OpcodeCollisionDetector::getVisualize( ) const
{
return mVisualizer != 0;
}
}
1 //
// C++ Interface: OpcodeCollisionDetector
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGREOPCODECOLLISIONDETECTOR_H
#define EMBEROGREOPCODECOLLISIONDETECTOR_H
#include "EmberEntityUserObject.h"
namespace OgreOpcode
{
30 class CollisionObject;
namespace Details
{
33 class OgreOpcodeDebugger;
}
};
namespace EmberOgre {
39 class OpcodeCollisionDetector;
40 class OpcodeCollisionDetectorVisualizerInstance;
namespace Model
{
44 class Model;
}
/**
@author Erik Hjortsberg <erik@katastrof.nu>
*/
50 class OpcodeCollisionDetector
: public ICollisionDetector
{
public:
friend class OpcodeCollisionDetectorVisualizerInstance;
OpcodeCollisionDetector( Model::Model* model );
virtual ~OpcodeCollisionDetector( );
virtual void testCollision( Ogre::Ray& ray, CollisionResult& result );
virtual void refit( );
/**
* Called when the entity changes, such as a subentity being hidden or shown. Implementations must reload the collision data.
*/
virtual void reload( );
virtual void setVisualize( bool visualize );
virtual bool getVisualize( ) const;
private:
typedef std::vector<OgreOpcode::CollisionObject*> CollisionObjectStore;
void buildCollisionObjects( );
void destroyCollisionObjects( );
CollisionObjectStore mCollisionObjects;
Model::Model* mModel;
OpcodeCollisionDetectorVisualizerInstance* mVisualizer;
};
}
#endif
1 //
// C++ Implementation: OpcodeCollisionDetectorVisualizer
//
// Description:
//
//
// Author: Erik Hjortsberg <erik.hjortsberg@iteam.se>, ( C ) 2007
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "OpcodeCollisionDetectorVisualizer.h"
#include "ogreopcode/include/OgreOpcodeDebugObject.h"
#include "ogreopcode/include/OgreCollisionManager.h"
#include "ogreopcode/include/OgreEntityCollisionShape.h"
#include "ogreopcode/include/OgreCollisionObject.h"
#include "OpcodeCollisionDetector.h"
namespace EmberOgre {
template<> EmberOgre::OpcodeCollisionDetectorVisualizer* Ember::Singleton<EmberOgre::OpcodeCollisionDetectorVisualizer>::ms_Singleton = 0;
34 OpcodeCollisionDetectorVisualizer::OpcodeCollisionDetectorVisualizer( )
{
mOpcodeDebugger = new OgreOpcode::Details::OgreOpcodeDebugger( "OpcodeCollisionDetectorVisualizer", OgreOpcode::CollisionManager::getSingletonPtr( )->getSceneManager( ) );
}
40 OpcodeCollisionDetectorVisualizer::~OpcodeCollisionDetectorVisualizer( )
{
Ogre::Root::getSingleton( ).removeFrameListener( this );
mOpcodeDebugger->clearAll( );
delete mOpcodeDebugger;
}
47 bool OpcodeCollisionDetectorVisualizer::frameStarted( const Ogre::FrameEvent& event )
{
mOpcodeDebugger->clearAll( );
for ( VisualizerInstanceStore::iterator I = mInstances.begin( ); I != mInstances.end( ); ++I ) {
( *I )->visualize( mOpcodeDebugger );
}
return true;
}
56 void OpcodeCollisionDetectorVisualizer::addInstance( OpcodeCollisionDetectorVisualizerInstance* instance )
{
if ( !mInstances.size( ) ) {
Ogre::Root::getSingleton( ).addFrameListener( this );
}
mInstances.push_back( instance );
}
64 void OpcodeCollisionDetectorVisualizer::removeInstance( OpcodeCollisionDetectorVisualizerInstance* instance )
{
VisualizerInstanceStore::iterator I = std::find( mInstances.begin( ), mInstances.end( ), instance );
if ( I != mInstances.end( ) ) {
mInstances.erase( I );
}
if ( !mInstances.size( ) ) {
mOpcodeDebugger->clearAll( );
Ogre::Root::getSingleton( ).removeFrameListener( this );
}
}
78 OpcodeCollisionDetectorVisualizerInstance::OpcodeCollisionDetectorVisualizerInstance( OpcodeCollisionDetector& detector ) : mDetector( detector )
{
OpcodeCollisionDetectorVisualizer::getSingleton( ).addInstance( this );
}
83 OpcodeCollisionDetectorVisualizerInstance::~OpcodeCollisionDetectorVisualizerInstance( )
{
for ( OpcodeCollisionDetector::CollisionObjectStore::iterator I = mDetector.mCollisionObjects.begin( ); I != mDetector.mCollisionObjects.end( ); ++I )
{
( *I )->getShape( )->clearViz( );
}
OpcodeCollisionDetectorVisualizer::getSingleton( ).removeInstance( this );
}
92 void OpcodeCollisionDetectorVisualizerInstance::visualize( OgreOpcode::Details::OgreOpcodeDebugger* debugger )
{
for ( OpcodeCollisionDetector::CollisionObjectStore::iterator I = mDetector.mCollisionObjects.begin( ); I != mDetector.mCollisionObjects.end( ); ++I )
{
( *I )->getShape( )->clearViz( );
( *I )->getShape( )->visualize( debugger );
}
}
}
1 //
// C++ Interface: OpcodeCollisionDetectorVisualizer
//
// Description:
//
//
// Author: Erik Hjortsberg <erik.hjortsberg@iteam.se>, ( C ) 2007
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBEROGREOPCODECOLLISIONDETECTORVISUALIZER_H
#define EMBEROGREOPCODECOLLISIONDETECTORVISUALIZER_H
#include "framework/Singleton.h"
#include <Ogre.h>
namespace OgreOpcode
{
31 class CollisionObject;
namespace Details
{
34 class OgreOpcodeDebugger;
}
};
namespace EmberOgre {
40 class OpcodeCollisionDetector;
41 class OpcodeCollisionDetectorVisualizerInstance;
/**
Helps with visualizing the collision objects. Create and register instances of OpcodeCollisionDetectorVisualizerInstance to visualize entities.
@see OpcodeCollisionDetectorVisualizerInstance
*/
47 class OpcodeCollisionDetectorVisualizer : public Ember::Singleton<OpcodeCollisionDetectorVisualizer>, public Ogre::FrameListener
{
public:
50 friend class OpcodeCollisionDetectorVisualizerInstance;
/**
* Default ctor.
*/
54 OpcodeCollisionDetectorVisualizer( );
55 virtual ~OpcodeCollisionDetectorVisualizer( );
/**
* Methods from Ogre::FrameListener
*/
59 virtual bool frameStarted( const Ogre::FrameEvent& event );
/**
* Registers an instance of OpcodeCollisionDetectorVisualizerInstance to be rendered each frame.
* @param instance An instance of OpcodeCollisionDetectorVisualizerInstance which in turn points to an instance of EmberPhysicalEntity.
*/
65 void addInstance( OpcodeCollisionDetectorVisualizerInstance* instance );
/**
* Removes an instance of OpcodeCollisionDetectorVisualizerInstance which will no longer be rendered each frame.
* @param instance An instance of OpcodeCollisionDetectorVisualizerInstance which in turn points to an instance of EmberPhysicalEntity.
*/
70 void removeInstance( OpcodeCollisionDetectorVisualizerInstance* instance );
protected:
typedef std::vector<OpcodeCollisionDetectorVisualizerInstance*> VisualizerInstanceStore;
/**
* The debugger object responsible for rendering.
*/
77 OgreOpcode::Details::OgreOpcodeDebugger* mOpcodeDebugger;
/**
* All the registered instances which will be rendered each frame.
*/
82 VisualizerInstanceStore mInstances;
};
85 class OpcodeCollisionDetectorVisualizerInstance
{
public:
88 OpcodeCollisionDetectorVisualizerInstance( OpcodeCollisionDetector& detector );
89 virtual ~OpcodeCollisionDetectorVisualizerInstance( );
/**
* Called each frame by OpcodeCollisionDetectorVisualizer to let the object tell the debugger how to render this instance.
* @param debugger
*/
95 void visualize( OgreOpcode::Details::OgreOpcodeDebugger* debugger );
protected:
98 OpcodeCollisionDetector& mDetector;
};
}
#endif
1 /*
Copyright ( C ) 2004 Erik Hjortsberg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "EmberEntity.h"
#include "EmberPhysicalEntity.h"
#include "model/Model.h"
// #include "PersonEmberEntity.h"
namespace EmberOgre {
26 PersonEmberEntity::PersonEmberEntity( const std::string& id, Eris::TypeInfo* ty, Eris::View* vw, Ogre::SceneManager* sceneManager, Ogre::SceneNode* nodeWithModel ) :
EmberPhysicalEntity( id, ty, vw, sceneManager, nodeWithModel )
{
}
32 PersonEmberEntity::~PersonEmberEntity( )
{}
35 void PersonEmberEntity::init( const Atlas::Objects::Entity::RootEntity &ge )
{
EmberPhysicalEntity::init( ge );
// mModel->setQueryFlags( EmberEntity::CM_PERSONS );
}
41 bool PersonEmberEntity::allowVisibilityOfMember( EmberEntity* entity )
{
return false;
}
}
1 /*
Copyright ( C ) 2004 Erik Hjortsberg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
( at your option ) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef PERSONDIMEENTITY_H
#define PERSONDIMEENTITY_H
#include "EmberOgrePrerequisites.h"
namespace EmberOgre {
25 class EmberPhysicalEntity;
26 class PersonEmberEntity : public EmberPhysicalEntity {
public:
29 PersonEmberEntity( const std::string& id, Eris::TypeInfo* ty, Eris::View* vw, Ogre::SceneManager* sceneManager, Ogre::SceneNode* nodeWithModel );
30 virtual ~PersonEmberEntity( );
32 virtual bool allowVisibilityOfMember( EmberEntity* entity );
protected:
35 virtual void init( const Atlas::Objects::Entity::RootEntity &ge );
};
}
#endif // PERSONDIMEENTITY_H
1 // DRGNURBSSurface.h: interface for the CDRGNURBSSurface class.
// ------------------------------------------------------------------------------------
// Copyright © 1999 Intel Corporation
// All Rights Reserved
//
// Permission is granted to use, copy, distribute and prepare derivative works of this
// software for any purpose and without fee, provided, that the above copyright notice
// and this statement appear in all copies. Intel makes no representations about the
// suitability of this software for any purpose. This software is provided "AS IS."
//
// Intel specifically disclaims all warranties, express or implied, and all liability,
// including consequential and other indirect damages, for the use of this software,
// including liability for infringement of any proprietary rights, and including the
// warranties of merchantability and fitness for a particular purpose. Intel does not
// assume any responsibility for any errors which may appear in this software nor any
// responsibility to update it.
// ------------------------------------------------------------------------------------
//
// PURPOSE:
//
// Declaration of the CDRGNURBSSurface class for rendering NURBS surfaces.
// Accompanies the article "Rendering NURBS Surfaces in Real-Time". Please refer
// to the article for an understanding of the methods in this class.
// ------------------------------------------------------------------------------------
//
// Author: Dean Macri - Intel Developer Relations Divison -- Tools and Technology Group
//
////////////////////////////////////////////////////////////////////////////////////////
//
// Yoinked from http://www.gamasutra.com/features/19991117/macri_pfv.htm
// Hacked into an unholy mess for use with OGRE by Chris "Antiarc" Heald ( antiarc@captionthis.com )
// Date: 11/9/2003
//
////////////////////////////////////////////////////////////////////////////////////////
#if !defined( AFX_DRGNURBSSURFACE_H__0D6D594B_6F3B_11D3_BE36_00902752C5DF__INCLUDED_ )
#define AFX_DRGNURBSSURFACE_H__0D6D594B_6F3B_11D3_BE36_00902752C5DF__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif
#define SIMD_SIZE 1
#define ALIGNED_NEW( s, t ) new t[s];
#define ALIGNED_DELETE( x ) do { if( ( x ) ) { delete x; x = NULL; } } while ( 0 )
#define SAFE_RELEASE( x ) do { if( ( x ) ) { x->Release( ); x = NULL; } } while ( 0 )
#define SAFE_DELETE( x ) do { if( ( x ) ) { delete x; x = NULL;} } while ( 0 )
// Some handy-dandy macros
//
#define CLAMP_UPPER( x ) if ( x>1.0f ) { x = 1.0f; }
#define CLAMP_LOWER( x ) if ( x<0.0f ) { x = 0.0f; }
struct Point4D
{
float x;
float y;
float z;
float w;
};
struct splinePoint
{
float x;
float y;
float z;
};
71 class CDRGNURBSSurface
{
private:
Point4D* m_pControlPoints;
float* m_UBasisCoefficients;
float* m_VBasisCoefficients;
float* m_UKnots;
float* m_VKnots;
float* m_UBasis;
float* m_dUBasis;
float* m_VBasis;
float* m_dVBasis;
Point4D* m_UTemp;
Point4D* m_dUTemp;
int* m_TessUKnotSpan;
int* m_TessVKnotSpan;
int m_iUDegree, m_iVDegree;
int m_iUOrder, m_iVOrder;
int m_iUKnots, m_iVKnots;
int m_iUControlPoints, m_iVControlPoints;
int m_iUBasisSpans, m_iVBasisSpans;
int m_iUTessellations, m_iVTessellations;
splinePoint* m_pVertices;
99 void Cleanup( void );
100 float ComputeCoefficient( float* fKnots, int iInterval, int i, int p, int k );
101 void ComputeBasisCoefficients( void );
102 void EvaluateBasisFunctions( void );
public:
105 CDRGNURBSSurface( void );
106 virtual ~CDRGNURBSSurface( void );
108 bool Init( int uDegree, int vDegree, int uControlPoints, int vControlPoints,
Point4D* pControlPoints, float* pUKnots, float* pVKnots,
int iDefaultUTessellations = 10, int iDefaultVTessellations = 10 );
112 void UpdateControlPoints( Point4D* pControlPoints );
114 splinePoint getData( int index );
115 virtual void SetTessellations( int iUTessellations, int iVTessellations );
116 virtual void TessellateSurface( void );
117 virtual int GetTriangleCount( void );
};
#endif // !defined( AFX_DRGNURBSSURFACE_H__0D6D594B_6F3B_11D3_BE36_00902752C5DF__INCLUDED_ )
1 //
// C++ Interface: EmberPagingLandScapeData2D_HeightField
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2005
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBERPAGINGLANDSCAPEDATA2D_HEIGHTFIELD_H
#define EMBERPAGINGLANDSCAPEDATA2D_HEIGHTFIELD_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeData2D.h"
namespace EmberOgre
{
namespace Terrain {
34 class TerrainPage;
}
/**
* A specialized class for loading 2D Data from Mercator, through an EmberOgre::TerrainPage class..
*/
40 class EmberPagingLandScapeData2D_HeightField: public Ogre::PagingLandScapeData2D
{
public:
43 EmberPagingLandScapeData2D_HeightField( Ogre::PagingLandScapeData2DManager *pageMgr );
44 virtual Ogre::String getName( ) const {return Ogre::String( "EmberHeightField" );}
45 virtual ~EmberPagingLandScapeData2D_HeightField( void ) {};
47 virtual const Ogre::Vector3 getNormal( const Ogre::Real mX, const Ogre::Real mZ );
48 virtual const Ogre::ColourValue getBase( const Ogre::Real mX, const Ogre::Real mZ );
49 virtual const Ogre::ColourValue getCoverage( const Ogre::Real mX, const Ogre::Real mZ );
50 virtual const Ogre::Real getShadow( const Ogre::Real mX, const Ogre::Real mZ, const bool& positive );
52 virtual Ogre::PagingLandScapeData2D* newPage( );
54 virtual const Ogre::Real getMaxAbsoluteHeight( void ) const;
protected:
57 virtual void _save( void );
58 virtual bool _load( const uint x, const uint z );
59 virtual void _load( void );
60 virtual void _unload( void );
private:
63 Terrain::TerrainPage* mTerrainPage;
};
}
#endif
1 //
// C++ Interface: EmberPagingLandScapeTexture
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2005
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBERPAGINGLANDSCAPETEXTURE_H
#define EMBERPAGINGLANDSCAPETEXTURE_H
#include "../../../EmberOgrePrerequisites.h"
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeTexture.h"
namespace EmberOgre
{
34 class EmberPagingLandScapeTexture : public Ogre::PagingLandScapeTexture
{
public:
38 EmberPagingLandScapeTexture( Ogre::PagingLandScapeTextureManager *pageMgr );
39 virtual ~EmberPagingLandScapeTexture( void );
41 virtual Ogre::String getName( ) const {return Ogre::String( "EmberTexture" );}
43 virtual Ogre::PagingLandScapeTexture* newTexture( );
44 virtual bool isMaterialSupported( bool recursive = true );
45 void setOptions( void );
protected:
48 virtual void _loadMaterial( void );
50 virtual void _unloadMaterial( void );
};
}
#endif
1 //
// C++ Interface: EmberPagingSceneManager
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2005
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#ifndef EMBERPAGINGSCENEMANAGER_H
#define EMBERPAGINGSCENEMANAGER_H
#include "../../../EmberOgrePrerequisites.h"
#include "OgrePagingLandScapeSceneManager.h"
// #include "OgrePagingLandScapeOptions.h"
namespace EmberOgre {
namespace Terrain {
34 class TerrainGenerator;
}
36 class EmberPagingSceneManager;
namespace Model {
39 class Model;
}
42 class IPageData
{
void createHeightData( Ogre::Real* heightData );
Ogre::MaterialPtr getMaterial( );
};
49 class IPageDataProvider
{
51 IPageData* getPageData( Ogre::Vector2 position );
};
/// Factory for OctreeSceneManager
56 class EmberPagingSceneManagerFactory : public Ogre::SceneManagerFactory
{
protected:
59 void initMetaData( void ) const;
public:
61 EmberPagingSceneManagerFactory( ) {}
62 ~EmberPagingSceneManagerFactory( ) {}
/// Factory type name
64 static const Ogre::String FACTORY_TYPE_NAME;
65 Ogre::SceneManager* createInstance( const Ogre::String& instanceName );
66 void destroyInstance( Ogre::SceneManager* instance );
};
/**
* This is a specialization of Ogre::PagingLandScapeSceneManager.
*
* @see Ogre::PagingLandScapeSceneManager
*/
74 class EmberPagingSceneManager : public Ogre::PagingLandScapeSceneManager {
public:
/** Things that need to be allocated once
*/
81 void InitScene( void );
83 EmberPagingSceneManager( const Ogre::String &name );
// EmberTerrainSceneManager( );
// virtual ~EmberTerrainSceneManager( );
// void attachPage( Ogre::ushort pageX, Ogre::ushort pageZ, Ogre::TerrainPage* page, float maxY, float minY );
// Ogre::TerrainPage* getTerrainPage( const Ogre::Vector3 & pt );
/*
* Resizes the octree. Do this after adding pages.
*/
// void doResize( );
/*
* The scenemanager stores the pages in vectors. This does not allow
* for pages with negative indices.
* But WF uses negative terrain coordinates.
* Thus we need to offset the indices.
*/
/* int getPageOffset( );
void setWorldGeometry( const Ogre::String& filename );
void setWorldGeometry( Ogre::TerrainOptions& options );*/
/* const Ogre::PagingLandScapeOptions * getOptions( ) const
{
assert( mOptions );
return mOptions;
}*/
/**
* Utility method for creating a new Model.
* @param modelName the id of the model
* @param modelDefinitionName the name of the model defition from which the model should be created
* @return
*/
121 Model::Model* createModel(
122 const Ogre::String& modelName,
123 const Ogre::String& modelDefinitionName );
125 void registerProvider( IPageDataProvider* provider );
protected:
/*
* @see EmberOgre::EmberTerrainSceneManager::getPageOffset( )
*/
132 Ogre::ushort mPageOffset;
// /*
// * Stitches the neighbours, preventing gaps
// */
// void setupPageNeighbors( Ogre::ushort pageX, Ogre::ushort pageZ, Ogre::TerrainPage* page );
/*
* Max and min values for the world. Used to resize the octree.
*/
float mMaxX;
float mMaxY;
float mMaxZ;
float mMinX;
float mMinY;
float mMinZ;
149 IPageDataProvider* mProvider;
private:
};
}
#endif // EMBERPAGINGSCENEMANAGER_H
1 //
// C++ Interface: EmberPagingSceneManagerAdapter
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "../../../EmberOgrePrerequisites.h"
#include "../../../terrain/ISceneManagerAdapter.h"
namespace Ogre
{
30 class PagingLandScapeOptions;
31 class SceneManager;
}
namespace EmberOgre {
36 class EmberPagingSceneManager;
38 class EmberPagingSceneManagerAdapter : public Terrain::ISceneManagerAdapter
{
public:
43 EmberPagingSceneManagerAdapter( EmberPagingSceneManager* scenemanager );
46 virtual int getPageSize( );
47 virtual Ogre::Real getHeightAt( const Ogre::Real x, const Ogre::Real z );
49 virtual void setWorldPagesDimensions( int numberOfPagesHeight, int numberOfPagesWidth, int heightOffsetInPages, int widthOffsetInPages );
51 virtual void setCamera( Ogre::Camera* camera );
52 virtual void setResourceGroupName( const std::string& groupName );
53 virtual void loadOptions( const std::string& filePath );
54 virtual void resize( Ogre::AxisAlignedBox newSize, int levels );
55 virtual void loadScene( );
57 virtual void setOption( const std::string& strKey, const void* pValue );
58 virtual void getOption( const std::string& strKey, void* pDestValue );
60 virtual Ogre::SceneManager* getSceneManager( ) const;
61 virtual void reloadAllPages( );
62 virtual void reloadPage( unsigned int x, unsigned int z );
private:
65 EmberPagingSceneManager* mSceneManager;
66 Ogre::PagingLandScapeOptions* getOptions( );
};
}
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright ( c ) 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
#ifndef _DebugRectangle2D_H__
#define _DebugRectangle2D_H__
#include "OgrePagingLandScapePrerequisites.h"
#ifdef _VISIBILITYDEBUG
#include "OgreSimpleRenderable.h"
namespace Ogre
{
/** Allows the rendering of a simple 2D rectangle
This class renders a simple 2D rectangle; this rectangle has no depth and
therefore is best used with specific render queue and depth settings,
like RENDER_QUEUE_BACKGROUND and 'depth_write off' for backdrops, and
RENDER_QUEUE_OVERLAY and 'depth_check off' for fullscreen quads.
*/
44 class DebugRectangle2D : public SimpleRenderable
{
protected:
/** Override this method to prevent parent transforms ( rotation, translation, scale )
*/
49 void getWorldTransforms( Matrix4* xform ) const;
/** @copydoc Renderable::getWorldOrientation */
51 const Quaternion& getWorldOrientation( void ) const;
/** @copydoc Renderable::getWorldPosition */
53 const Vector3& getWorldPosition( void ) const;
public:
57 DebugRectangle2D( );
58 ~DebugRectangle2D( );
/** Sets the corners of the rectangle, in relative coordinates.
@param
left Left position in screen relative coordinates, -1 = left edge, 1.0 = right edge
top Top position in screen relative coordinates, 1 = top edge, -1 = bottom edge
right Right position in screen relative coordinates
bottom Bottom position in screen relative coordinates
*/
67 void setCorners( Real left, Real top, Real right, Real bottom );
69 Real getSquaredViewDepth( const Camera* cam ) const { return 0; }
71 Real getBoundingRadius( void ) const { return 0; }
/// Identity view and projection
#ifdef PLSM2_EIHORT
74 bool getUseIdentityProjection( void ) const { return mUseIdentityProjection; }
#else
76 bool useIdentityProjection( void ) const { return true; }
#endif
/// Identity view and projection
#ifdef PLSM2_EIHORT
80 bool getUseIdentityView( void ) const { return mUseIdentityView; }
#else
82 bool useIdentityView( void ) const { return true; }
#endif
};
}// namespace
#endif //_VISIBILITYDEBUG
#endif // _DebugRectangle2D_H__
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright ( c ) 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
#ifndef _OcclusionBoundingBox_H__
#define _OcclusionBoundingBox_H__
#include "OgrePrerequisites.h"
#include "OgreSimpleRenderable.h"
namespace Ogre
{
/** Allows the rendering of an opaque bounding box.
@remarks
This class builds a opaque renderable from a given aabb. A pointer to this class can be
added to a render queue to display the bounding box of an object.
*/
40 class OcclusionBoundingBox : public SimpleRenderable
{
protected:
/** Override this method to prevent parent transforms ( rotation, translation, scale )
*/
45 void getWorldTransforms( Matrix4* xform ) const;
/** @copydoc Renderable::getWorldOrientation */
47 const Quaternion& getWorldOrientation( void ) const;
/** @copydoc Renderable::getWorldPosition */
49 const Vector3& getWorldPosition( void ) const;
/** Builds the wireframe line list.
*/
53 void setupBoundingBoxVertices( const AxisAlignedBox& aab );
55 Real mRadius;
public:
59 OcclusionBoundingBox( );
60 ~OcclusionBoundingBox( );
62 virtual PolygonMode getRenderDetail( ) const;
/** Builds the wireframe line list.
@param
aabb bounding box to build a wireframe from.
*/
68 void setupBoundingBox( const AxisAlignedBox& aabb );
70 Real getSquaredViewDepth( const Camera* cam ) const;
72 Real getBoundingRadius( void ) const { return mRadius; }
};
}// namespace
#endif
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
OgrePagingLandScapeOctreeAxisAlignedBoxSceneQuery.h - description
-------------------
begin : Tues July 20, 2004
copyright : ( C ) 2004 by Jon Anderson
email : janders@users.sf.net
***************************************************************************/
#ifndef PagingLandScapeAxisAlignedBoxSCENEQUERY_H
#define PagingLandScapeAxisAlignedBoxSCENEQUERY_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgreSceneManager.h"
namespace Ogre
{
/** PagingLandScape implementation of AxisAlignedBoxSceneQuery. */
class _OgrePagingLandScapeExport PagingLandScapeAxisAlignedBoxSceneQuery : public DefaultAxisAlignedBoxSceneQuery
{
public:
46 PagingLandScapeAxisAlignedBoxSceneQuery( SceneManager* creator );
virtual ~PagingLandScapeAxisAlignedBoxSceneQuery( void );
/** See RayScenQuery. */
/** Finds any entities that intersect the AAB for the query. */
void execute( SceneQueryListener* listener );
// Structure returned in the geometry field of the worldFragment for this
// query. Cut'n'paste this into your client w/out the setters if using
// this query from a client.
struct CustomQueryResult
{
enum CustomQueryResultTypes { QUERY_EXTENTS_TYPE, SUBSECTION_EXTENTS_TYPE, VERTEX_TYPE };
void SetQueryExtents( int width, int height )
{
type_ = QUERY_EXTENTS_TYPE;
data_.queryExtents_.width_ = width;
data_.queryExtents_.height_ = height;
}
void SetSubsectionExtents( int width, int height, short renderLevel, int subX, int subZ )
{
type_ = SUBSECTION_EXTENTS_TYPE;
data_.subExtents_.width_ = width;
data_.subExtents_.height_ = height;
data_.subExtents_.renderLevel_ = renderLevel;
data_.subExtents_.subX_ = subX;
data_.subExtents_.subZ_ = subZ;
}
void SetVertex( const Vector3& vertex, bool included )
{
type_ = VERTEX_TYPE;
// Can't use a Vector3 in a union, so we'll break it up.
data_.vertexData_.x_ = vertex.x;
data_.vertexData_.y_ = vertex.y;
data_.vertexData_.z_ = vertex.z;
data_.vertexData_.included_ = included;
}
CustomQueryResultTypes type_;
union
{
struct
{
int width_;
int height_;
} queryExtents_;
struct
{
int width_;
int height_;
short renderLevel_;
int subX_;
int subZ_;
} subExtents_;
struct
{
Real x_;
Real y_;
Real z_;
bool included_;
} vertexData_;
} data_;
};
};
}
#endif
1 #ifndef __PagingLandScapeCallBackEvent_H__
#define __PagingLandScapeCallBackEvent_H__
#include "Ogre.h"
#include "OgrePagingLandScapeCallback.h"
namespace Ogre
{
//---------------------------------------------------------------------
10 class PagingLandscapeEvent
{
public:
13 PagingLandscapeEvent( const size_t pagex, const size_t pagez,
14 const size_t tilex, const size_t tilez,
15 const Real* heightData, const AxisAlignedBox &Bbox ) :
mPagex( pagex ),
mPagez( pagez ),
mTilex( tilex ),
mTilez( tilez ),
mHeightData( heightData ),
mBbox( Bbox )
{
};
25 ~PagingLandscapeEvent( ){};
27 const size_t mPagex;
28 const size_t mPagez;
29 const size_t mTilex;
30 const size_t mTilez;
31 const Real* mHeightData;
32 const AxisAlignedBox &mBbox;
};
typedef fastdelegate::FastDelegate1<PagingLandscapeEvent *> PagingLandscapeDelegate;
}
#endif //__PagingLandScapeCallBackEvent_H__
// FastDelegate.h
// Efficient delegates in C++ that generate only two lines of asm code!
// Documentation is found at http://www.codeproject.com/cpp/FastDelegate.asp
//
// - Don Clugston, Mar 2004.
// Major contributions were made by Jody Hagins.
// History:
// 24-Apr-04 1.0 * Submitted to CodeProject.
// 28-Apr-04 1.1 * Prevent most unsafe uses of evil static function hack.
// * Improved syntax for horrible_cast ( thanks Paul Bludov ).
// * Tested on Metrowerks MWCC and Intel ICL ( IA32 )
// * Compiled, but not run, on Comeau C++ and Intel Itanium ICL.
// 27-Jun-04 1.2 * Now works on Borland C++ Builder 5.5
// * Now works on /clr "managed C++" code on VC7, VC7.1
// * Comeau C++ now compiles without warnings.
// * Prevent the virtual inheritance case from being used on
// VC6 and earlier, which generate incorrect code.
// * Improved warning and error messages. Non-standard hacks
// now have compile-time checks to make them safer.
// * implicit_cast used instead of static_cast in many cases.
// * If calling a const member function, a const class pointer can be used.
// * MakeDelegate( ) global helper function added to simplify pass-by-value.
// * Added fastdelegate.clear( )
// 16-Jul-04 1.2.1* Workaround for gcc bug ( const member function pointers in templates )
// 30-Oct-04 1.3 * Support for ( non-void ) return values.
// * No more workarounds in client code!
// MSVC and Intel now use a clever hack invented by John Dlugosz:
// - The FASTDELEGATEDECLARE workaround is no longer necessary.
// - No more warning messages for VC6
// * Less use of macros. Error messages should be more comprehensible.
// * Added include guards
// * Added FastDelegate::empty( ) to test if invocation is safe ( Thanks Neville Franks ).
// * Now tested on VS 2006 Express Beta, PGI C++
// 24-Dec-04 1.4 * Added DelegateMemento, to allow collections of disparate delegates.
// * <, >, <=, >= comparison operators to allow storage in ordered containers.
// * Substantial reduction of code size, especially the 'Closure' class.
// * Standardised all the compiler-specific workarounds.
// * MFP conversion now works for CodePlay ( but not yet supported in the full code ).
// * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1
// * New syntax: FastDelegate< int ( char *, double ) >.
// 14-Feb-05 1.4.1* Now treats =0 as equivalent to .clear( ), ==0 as equivalent to .empty( ). ( Thanks elfric ).
// * Now tested on Intel ICL for AMD64, VS2006 Beta for AMD64 and Itanium.
// 30-Mar-05 1.5 * Safebool idiom: "if ( dg )" is now equivalent to "if ( !dg.empty( ) )"
// * Fully supported by CodePlay VectorC
// * Bugfix for Metrowerks: empty( ) was buggy because a valid MFP can be 0 on MWCC!
// * More optimal assignment, == and != operators for static function pointers.
#ifndef FASTDELEGATE_H
#define FASTDELEGATE_H
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <memory.h> // to allow <, > comparisons
////////////////////////////////////////////////////////////////////////////////
// Configuration options
//
////////////////////////////////////////////////////////////////////////////////
// Uncomment the following #define for optimally-sized delegates.
// In this case, the generated asm code is almost identical to the code you'd get
// if the compiler had native support for delegates.
// It will not work on systems where sizeof( dataptr ) < sizeof( codeptr ).
// Thus, it will not work for DOS compilers using the medium model.
// It will also probably fail on some DSP systems.
#define FASTDELEGATE_USESTATICFUNCTIONHACK
// Uncomment the next line to allow function declarator syntax.
// It is automatically enabled for those compilers where it is known to work.
//#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
////////////////////////////////////////////////////////////////////////////////
// Compiler identification for workarounds
//
////////////////////////////////////////////////////////////////////////////////
// Compiler identification. It's not easy to identify Visual C++ because
// many vendors fraudulently define Microsoft's identifiers.
#if defined( _MSC_VER ) && !defined( __MWERKS__ ) && !defined( __VECTOR_C ) && !defined( __ICL ) && !defined( __BORLANDC__ )
#define FASTDLGT_ISMSVC
#if ( _MSC_VER <1300 ) // Many workarounds are required for VC6.
#define FASTDLGT_VC6
#pragma warning( disable:4786 ) // disable this ridiculous warning
#endif
#endif
// Does the compiler uses Microsoft's member function pointer structure?
// If so, it needs special treatment.
// Metrowerks CodeWarrior, Intel, and CodePlay fraudulently define Microsoft's
// identifier, _MSC_VER. We need to filter Metrowerks out.
#if defined( _MSC_VER ) && !defined( __MWERKS__ )
#define FASTDLGT_MICROSOFT_MFP
#if !defined( __VECTOR_C )
// CodePlay doesn't have the __single/multi/virtual_inheritance keywords
#define FASTDLGT_HASINHERITANCE_KEYWORDS
#endif
#endif
// Does it allow function declarator syntax? The following compilers are known to work:
#if defined( FASTDLGT_ISMSVC ) && ( _MSC_VER >=1310 ) // VC 7.1
#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
#endif
// Gcc( 2.95+ ), and versions of Digital Mars, Intel and Comeau in common use.
#if defined ( __DMC__ ) || defined( __GNUC__ ) || defined( __ICL ) || defined( __COMO__ )
#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
#endif
// It works on Metrowerks MWCC 3.2.2. From boost.Config it should work on earlier ones too.
#if defined ( __MWERKS__ )
#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
#endif
#ifdef __GNUC__ // Workaround GCC bug #8271
// At present, GCC doesn't recognize constness of MFPs in templates
#define FASTDELEGATE_GCC_BUG_8271
#endif
////////////////////////////////////////////////////////////////////////////////
// General tricks used in this code
//
// ( a ) Error messages are generated by typdefing an array of negative size to
// generate compile-time errors.
// ( b ) Warning messages on MSVC are generated by declaring unused variables, and
// enabling the "variable XXX is never used" warning.
// ( c ) Unions are used in a few compiler-specific cases to perform illegal casts.
// ( d ) For Microsoft and Intel, when adjusting the 'this' pointer, it's cast to
// ( char * ) first to ensure that the correct number of *bytes* are added.
//
////////////////////////////////////////////////////////////////////////////////
// Helper templates
//
////////////////////////////////////////////////////////////////////////////////
namespace fastdelegate {
namespace detail { // we'll hide the implementation details in a nested namespace.
// implicit_cast< >
// I believe this was originally going to be in the C++ standard but
// was left out by accident. It's even milder than static_cast.
// I use it instead of static_cast<> to emphasize that I'm not doing
// anything nasty.
// Usage is identical to static_cast<>
template <class OutputClass, class InputClass>
152 inline OutputClass implicit_cast( InputClass input ){
return input;
}
// horrible_cast< >
// This is truly evil. It completely subverts C++'s type system, allowing you
// to cast from any class to any other class. Technically, using a union
// to perform the cast is undefined behaviour ( even in C ). But we can see if
// it is OK by checking that the union is the same size as each of its members.
// horrible_cast<> should only be used for compiler-specific workarounds.
// Usage is identical to reinterpret_cast<>.
// This union is declared outside the horrible_cast because BCC 5.5.1
// can't inline a function with a nested class, and gives a warning.
template <class OutputClass, class InputClass>
167 union horrible_union{
OutputClass out;
InputClass in;
};
template <class OutputClass, class InputClass>
173 inline OutputClass horrible_cast( const InputClass input ){
horrible_union<OutputClass, InputClass> u;
// Cause a compile-time error if in, out and u are not the same size.
// If the compile fails here, it means the compiler has peculiar
// unions which would prevent the cast from working.
typedef int ERROR_CantUseHorrible_cast[sizeof( InputClass )==sizeof( u )
&& sizeof( InputClass )==sizeof( OutputClass ) ? 1 : -1];
u.in = input;
return u.out;
}
////////////////////////////////////////////////////////////////////////////////
// Workarounds
//
////////////////////////////////////////////////////////////////////////////////
// Backwards compatibility: This macro used to be necessary in the virtual inheritance
// case for Intel and Microsoft. Now it just forward-declares the class.
#define FASTDELEGATEDECLARE( CLASSNAME ) class CLASSNAME;
// Prevent use of the static function hack with the DOS medium model.
#ifdef __MEDIUM__
#undef FASTDELEGATE_USESTATICFUNCTIONHACK
#endif
// DefaultVoid - a workaround for 'void' templates in VC6.
//
// ( 1 ) VC6 and earlier do not allow 'void' as a default template argument.
// ( 2 ) They also doesn't allow you to return 'void' from a function.
//
// Workaround for ( 1 ): Declare a dummy type 'DefaultVoid' which we use
// when we'd like to use 'void'. We convert it into 'void' and back
// using the templates DefaultVoidToVoid<> and VoidToDefaultVoid<>.
// Workaround for ( 2 ): On VC6, the code for calling a void function is
// identical to the code for calling a non-void function in which the
// return value is never used, provided the return value is returned
// in the EAX register, rather than on the stack.
// This is true for most fundamental types such as int, enum, void *.
// Const void * is the safest option since it doesn't participate
// in any automatic conversions. But on a 16-bit compiler it might
// cause extra code to be generated, so we disable it for all compilers
// except for VC6 ( and VC5 ).
#ifdef FASTDLGT_VC6
// VC6 workaround
typedef const void * DefaultVoid;
#else
// On any other compiler, just use a normal void.
typedef void DefaultVoid;
#endif
// Translate from 'DefaultVoid' to 'void'.
// Everything else is unchanged
template <class T>
struct DefaultVoidToVoid { typedef T type; };
template <>
struct DefaultVoidToVoid<DefaultVoid> { typedef void type; };
// Translate from 'void' into 'DefaultVoid'
// Everything else is unchanged
template <class T>
struct VoidToDefaultVoid { typedef T type; };
template <>
struct VoidToDefaultVoid<void> { typedef DefaultVoid type; };
////////////////////////////////////////////////////////////////////////////////
// Fast Delegates, part 1:
//
// Conversion of member function pointer to a standard form
//
////////////////////////////////////////////////////////////////////////////////
// GenericClass is a fake class, ONLY used to provide a type.
// It is vitally important that it is never defined, so that the compiler doesn't
// think it can optimize the invocation. For example, Borland generates simpler
// code if it knows the class only uses single inheritance.
// Compilers using Microsoft's structure need to be treated as a special case.
#ifdef FASTDLGT_MICROSOFT_MFP
#ifdef FASTDLGT_HASINHERITANCE_KEYWORDS
// For Microsoft and Intel, we want to ensure that it's the most efficient type of MFP
// ( 4 bytes ), even when the /vmg option is used. Declaring an empty class
// would give 16 byte pointers in this case....
class __single_inheritance GenericClass;
#endif
// ...but for Codeplay, an empty class *always* gives 4 byte pointers.
// If compiled with the /clr option ( "managed C++" ), the JIT compiler thinks
// it needs to load GenericClass before it can call any of its functions,
// ( compiles OK but crashes at runtime! ), so we need to declare an
// empty class to make it happy.
// Codeplay and VC4 can't cope with the unknown_inheritance case either.
268 class GenericClass {};
#else
270 class GenericClass;
#endif
// The size of a single inheritance member function pointer.
const int SINGLE_MEMFUNCPTR_SIZE = sizeof( void ( GenericClass::* )( ) );
// SimplifyMemFunc< >::Convert( )
//
// A template function that converts an arbitrary member function pointer into the
// simplest possible form of member function pointer, using a supplied 'this' pointer.
// According to the standard, this can be done legally with reinterpret_cast<>.
// For ( non-standard ) compilers which use member function pointers which vary in size
// depending on the class, we need to use knowledge of the internal structure of a
// member function pointer, as used by the compiler. Template specialization is used
// to distinguish between the sizes. Because some compilers don't support partial
// template specialisation, I use full specialisation of a wrapper struct.
// general case -- don't know how to convert it. Force a compile failure
template <int N>
struct SimplifyMemFunc {
template <class X, class XFuncType, class GenericMemFuncType>
inline static GenericClass *Convert( X *pthis, XFuncType function_to_bind,
GenericMemFuncType &bound_func ) {
// Unsupported member function type -- force a compile failure.
// ( it's illegal to have a array with negative size ).
typedef char ERROR_Unsupported_member_function_pointer_on_this_compiler[N-100];
return 0;
}
};
// For compilers where all member func ptrs are the same size, everything goes here.
// For non-standard compilers, only single_inheritance classes go here.
template <>
struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE> {
template <class X, class XFuncType, class GenericMemFuncType>
inline static GenericClass *Convert( X *pthis, XFuncType function_to_bind,
GenericMemFuncType &bound_func ) {
#if defined __DMC__
// Digital Mars doesn't allow you to cast between abitrary PMF's,
// even though the standard says you can. The 32-bit compiler lets you
// static_cast through an int, but the DOS compiler doesn't.
bound_func = horrible_cast<GenericMemFuncType>( function_to_bind );
#else
bound_func = reinterpret_cast<GenericMemFuncType>( function_to_bind );
#endif
return reinterpret_cast<GenericClass *>( pthis );
}
};
////////////////////////////////////////////////////////////////////////////////
// Fast Delegates, part 1b:
//
// Workarounds for Microsoft and Intel
//
////////////////////////////////////////////////////////////////////////////////
// Compilers with member function pointers which violate the standard ( MSVC, Intel, Codeplay ),
// need to be treated as a special case.
#ifdef FASTDLGT_MICROSOFT_MFP
// We use unions to perform horrible_casts. I would like to use #pragma pack( push, 1 )
// at the start of each function for extra safety, but VC6 seems to ICE
// intermittently if you do this inside a template.
// __multiple_inheritance classes go here
// Nasty hack for Microsoft and Intel ( IA32 and Itanium )
template<>
struct SimplifyMemFunc< SINGLE_MEMFUNCPTR_SIZE + sizeof( int ) > {
template <class X, class XFuncType, class GenericMemFuncType>
inline static GenericClass *Convert( X *pthis, XFuncType function_to_bind,
GenericMemFuncType &bound_func ) {
// We need to use a horrible_cast to do this conversion.
// In MSVC, a multiple inheritance member pointer is internally defined as:
union {
XFuncType func;
struct {
GenericMemFuncType funcaddress; // points to the actual member function
int delta; // #BYTES to be added to the 'this' pointer
}s;
} u;
// Check that the horrible_cast will work
typedef int ERROR_CantUsehorrible_cast[sizeof( function_to_bind )==sizeof( u.s )? 1 : -1];
u.func = function_to_bind;
bound_func = u.s.funcaddress;
return reinterpret_cast<GenericClass *>( reinterpret_cast<char *>( pthis ) + u.s.delta );
}
};
// virtual inheritance is a real nuisance. It's inefficient and complicated.
// On MSVC and Intel, there isn't enough information in the pointer itself to
// enable conversion to a closure pointer. Earlier versions of this code didn't
// work for all cases, and generated a compile-time error instead.
// But a very clever hack invented by John M. Dlugosz solves this problem.
// My code is somewhat different to his: I have no asm code, and I make no
// assumptions about the calling convention that is used.
// In VC++ and ICL, a virtual_inheritance member pointer
// is internally defined as:
struct MicrosoftVirtualMFP {
void ( GenericClass::*codeptr )( ); // points to the actual member function
int delta; // #bytes to be added to the 'this' pointer
int vtable_index; // or 0 if no virtual inheritance
};
// The CRUCIAL feature of Microsoft/Intel MFPs which we exploit is that the
// m_codeptr member is *always* called, regardless of the values of the other
// members. ( This is *not* true for other compilers, eg GCC, which obtain the
// function address from the vtable if a virtual function is being called ).
// Dlugosz's trick is to make the codeptr point to a probe function which
// returns the 'this' pointer that was used.
// Define a generic class that uses virtual inheritance.
// It has a trival member function that returns the value of the 'this' pointer.
struct GenericVirtualClass : virtual public GenericClass
{
typedef GenericVirtualClass * ( GenericVirtualClass::*ProbePtrType )( );
GenericVirtualClass * GetThis( ) { return this; }
};
// __virtual_inheritance classes go here
template <>
struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE + 2*sizeof( int ) >
{
template <class X, class XFuncType, class GenericMemFuncType>
inline static GenericClass *Convert( X *pthis, XFuncType function_to_bind,
GenericMemFuncType &bound_func ) {
union {
XFuncType func;
GenericClass* ( X::*ProbeFunc )( );
MicrosoftVirtualMFP s;
} u;
u.func = function_to_bind;
bound_func = reinterpret_cast<GenericMemFuncType>( u.s.codeptr );
union {
GenericVirtualClass::ProbePtrType virtfunc;
MicrosoftVirtualMFP s;
} u2;
// Check that the horrible_cast<>s will work
typedef int ERROR_CantUsehorrible_cast[sizeof( function_to_bind )==sizeof( u.s )
&& sizeof( function_to_bind )==sizeof( u.ProbeFunc )
&& sizeof( u2.virtfunc )==sizeof( u2.s ) ? 1 : -1];
// Unfortunately, taking the address of a MF prevents it from being inlined, so
// this next line can't be completely optimised away by the compiler.
u2.virtfunc = &GenericVirtualClass::GetThis;
u.s.codeptr = u2.s.codeptr;
return ( pthis->*u.ProbeFunc )( );
}
};
#if ( _MSC_VER <1300 )
// Nasty hack for Microsoft Visual C++ 6.0
// unknown_inheritance classes go here
// There is a compiler bug in MSVC6 which generates incorrect code in this case!!
template <>
struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE + 3*sizeof( int ) >
{
template <class X, class XFuncType, class GenericMemFuncType>
inline static GenericClass *Convert( X *pthis, XFuncType function_to_bind,
GenericMemFuncType &bound_func ) {
// There is an apalling but obscure compiler bug in MSVC6 and earlier:
// vtable_index and 'vtordisp' are always set to 0 in the
// unknown_inheritance case!
// This means that an incorrect function could be called!!!
// Compiling with the /vmg option leads to potentially incorrect code.
// This is probably the reason that the IDE has a user interface for specifying
// the /vmg option, but it is disabled - you can only specify /vmg on
// the command line. In VC1.5 and earlier, the compiler would ICE if it ever
// encountered this situation.
// It is OK to use the /vmg option if /vmm or /vms is specified.
// Fortunately, the wrong function is only called in very obscure cases.
// It only occurs when a derived class overrides a virtual function declared
// in a virtual base class, and the member function
// points to the *Derived* version of that function. The problem can be
// completely averted in 100% of cases by using the *Base class* for the
// member fpointer. Ie, if you use the base class as an interface, you'll
// stay out of trouble.
// Occasionally, you might want to point directly to a derived class function
// that isn't an override of a base class. In this case, both vtable_index
// and 'vtordisp' are zero, but a virtual_inheritance pointer will be generated.
// We can generate correct code in this case. To prevent an incorrect call from
// ever being made, on MSVC6 we generate a warning, and call a function to
// make the program crash instantly.
typedef char ERROR_VC6CompilerBug[-100];
return 0;
}
};
#else
// Nasty hack for Microsoft and Intel ( IA32 and Itanium )
// unknown_inheritance classes go here
// This is probably the ugliest bit of code I've ever written. Look at the casts!
// There is a compiler bug in MSVC6 which prevents it from using this code.
template <>
struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE + 3*sizeof( int ) >
{
template <class X, class XFuncType, class GenericMemFuncType>
inline static GenericClass *Convert( X *pthis, XFuncType function_to_bind,
GenericMemFuncType &bound_func ) {
// The member function pointer is 16 bytes long. We can't use a normal cast, but
// we can use a union to do the conversion.
union {
XFuncType func;
// In VC++ and ICL, an unknown_inheritance member pointer
// is internally defined as:
struct {
GenericMemFuncType m_funcaddress; // points to the actual member function
int delta; // #bytes to be added to the 'this' pointer
int vtordisp; // #bytes to add to 'this' to find the vtable
int vtable_index; // or 0 if no virtual inheritance
} s;
} u;
// Check that the horrible_cast will work
typedef int ERROR_CantUsehorrible_cast[sizeof( XFuncType )==sizeof( u.s )? 1 : -1];
u.func = function_to_bind;
bound_func = u.s.funcaddress;
int virtual_delta = 0;
if ( u.s.vtable_index ) { // Virtual inheritance is used
// First, get to the vtable.
// It is 'vtordisp' bytes from the start of the class.
const int * vtable = *reinterpret_cast<const int *const*>(
reinterpret_cast<const char *>( pthis ) + u.s.vtordisp );
// 'vtable_index' tells us where in the table we should be looking.
virtual_delta = u.s.vtordisp + *reinterpret_cast<const int *>(
reinterpret_cast<const char *>( vtable ) + u.s.vtable_index );
}
// The int at 'virtual_delta' gives us the amount to add to 'this'.
// Finally we can add the three components together. Phew!
return reinterpret_cast<GenericClass *>(
reinterpret_cast<char *>( pthis ) + u.s.delta + virtual_delta );
};
};
#endif // MSVC 7 and greater
#endif // MS/Intel hacks
} // namespace detail
////////////////////////////////////////////////////////////////////////////////
// Fast Delegates, part 2:
//
// Define the delegate storage, and cope with static functions
//
////////////////////////////////////////////////////////////////////////////////
// DelegateMemento -- an opaque structure which can hold an arbitary delegate.
// It knows nothing about the calling convention or number of arguments used by
// the function pointed to.
// It supplies comparison operators so that it can be stored in STL collections.
// It cannot be set to anything other than null, nor invoked directly:
// it must be converted to a specific delegate.
// Implementation:
// There are two possible implementations: the Safe method and the Evil method.
// DelegateMemento - Safe version
//
// This implementation is standard-compliant, but a bit tricky.
// A static function pointer is stored inside the class.
// Here are the valid values:
// +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+
// | 0 | 0 | 0 | Empty |
// | !=0 |( dontcare )| Invoker | Static function|
// | 0 | !=0 | !=0* | Method call |
// +--------------------+----------+------------+----------------+
// * For Metrowerks, this can be 0. ( first virtual function in a
// single_inheritance class ).
// When stored stored inside a specific delegate, the 'dontcare' entries are replaced
// with a reference to the delegate itself. This complicates the = and == operators
// for the delegate class.
// DelegateMemento - Evil version
//
// For compilers where data pointers are at least as big as code pointers, it is
// possible to store the function pointer in the this pointer, using another
// horrible_cast. In this case the DelegateMemento implementation is simple:
// +--pThis --+-- pMemFunc-+-- Meaning---------------------+
// | 0 | 0 | Empty |
// | !=0 | !=0* | Static function or method call|
// +----------+------------+-------------------------------+
// * For Metrowerks, this can be 0. ( first virtual function in a
// single_inheritance class ).
// Note that the Sun C++ and MSVC documentation explicitly state that they
// support static_cast between void * and function pointers.
class DelegateMemento {
protected:
// the data is protected, not private, because many
// compilers have problems with template friends.
typedef void ( detail::GenericClass::*GenericMemFuncType )( ); // arbitrary MFP.
detail::GenericClass *m_pthis;
GenericMemFuncType m_pFunction;
#if !defined( FASTDELEGATE_USESTATICFUNCTIONHACK )
typedef void ( *GenericFuncPtr )( ); // arbitrary code pointer
GenericFuncPtr m_pStaticFunction;
#endif
public:
#if !defined( FASTDELEGATE_USESTATICFUNCTIONHACK )
DelegateMemento( ) : m_pthis( 0 ), m_pFunction( 0 ), m_pStaticFunction( 0 ) {};
void clear( ) {
m_pthis=0; m_pFunction=0; m_pStaticFunction=0;
}
#else
DelegateMemento( ) : m_pthis( 0 ), m_pFunction( 0 ) {};
void clear( ) { m_pthis=0; m_pFunction=0; }
#endif
public:
#if !defined( FASTDELEGATE_USESTATICFUNCTIONHACK )
inline bool IsEqual ( const DelegateMemento &x ) const{
// We have to cope with the static function pointers as a special case
if ( m_pFunction!=x.m_pFunction ) return false;
// the static function ptrs must either both be equal, or both be 0.
if ( m_pStaticFunction!=x.m_pStaticFunction ) return false;
if ( m_pStaticFunction!=0 ) return m_pthis==x.m_pthis;
else return true;
}
#else // Evil Method
inline bool IsEqual ( const DelegateMemento &x ) const{
return m_pthis==x.m_pthis && m_pFunction==x.m_pFunction;
}
#endif
// Provide a strict weak ordering for DelegateMementos.
inline bool IsLess( const DelegateMemento &right ) const {
// deal with static function pointers first
#if !defined( FASTDELEGATE_USESTATICFUNCTIONHACK )
if ( m_pStaticFunction !=0 || right.m_pStaticFunction!=0 )
return m_pStaticFunction < right.m_pStaticFunction;
#endif
if ( m_pthis !=right.m_pthis ) return m_pthis < right.m_pthis;
// There are no ordering operators for member function pointers,
// but we can fake one by comparing each byte. The resulting ordering is
// arbitrary ( and compiler-dependent ), but it permits storage in ordered STL containers.
return memcmp( &m_pFunction, &right.m_pFunction, sizeof( m_pFunction ) ) < 0;
}
// BUGFIX ( Mar 2006 ):
// We can't just compare m_pFunction because on Metrowerks,
// m_pFunction can be zero even if the delegate is not empty!
inline bool operator ! ( ) const // Is it bound to anything?
{ return m_pthis==0 && m_pFunction==0; }
inline bool empty( ) const // Is it bound to anything?
{ return m_pthis==0 && m_pFunction==0; }
public:
DelegateMemento & operator = ( const DelegateMemento &right ) {
SetMementoFrom( right );
return *this;
}
inline bool operator <( const DelegateMemento &right ) {
return IsLess( right );
}
inline bool operator >( const DelegateMemento &right ) {
return right.IsLess( *this );
}
DelegateMemento ( const DelegateMemento &right ) :
m_pFunction( right.m_pFunction ), m_pthis( right.m_pthis )
#if !defined( FASTDELEGATE_USESTATICFUNCTIONHACK )
, m_pStaticFunction ( right.m_pStaticFunction )
#endif
{}
protected:
void SetMementoFrom( const DelegateMemento &right ) {
m_pFunction = right.m_pFunction;
m_pthis = right.m_pthis;
#if !defined( FASTDELEGATE_USESTATICFUNCTIONHACK )
m_pStaticFunction = right.m_pStaticFunction;
#endif
}
};
// ClosurePtr<>
//
// A private wrapper class that adds function signatures to DelegateMemento.
// It's the class that does most of the actual work.
// The signatures are specified by:
// GenericMemFunc: must be a type of GenericClass member function pointer.
// StaticFuncPtr: must be a type of function pointer with the same signature
// as GenericMemFunc.
// UnvoidStaticFuncPtr: is the same as StaticFuncPtr, except on VC6
// where it never returns void ( returns DefaultVoid instead ).
// An outer class, FastDelegateN<>, handles the invoking and creates the
// necessary typedefs.
// This class does everything else.
namespace detail {
template < class GenericMemFunc, class StaticFuncPtr, class UnvoidStaticFuncPtr>
class ClosurePtr : public DelegateMemento {
public:
// These functions are for setting the delegate to a member function.
// Here's the clever bit: we convert an arbitrary member function into a
// standard form. XMemFunc should be a member function of class X, but I can't
// enforce that here. It needs to be enforced by the wrapper class.
template < class X, class XMemFunc >
inline void bindmemfunc( X *pthis, XMemFunc function_to_bind ) {
m_pthis = SimplifyMemFunc< sizeof( function_to_bind ) >
::Convert( pthis, function_to_bind, m_pFunction );
#if !defined( FASTDELEGATE_USESTATICFUNCTIONHACK )
m_pStaticFunction = 0;
#endif
}
// For const member functions, we only need a const class pointer.
// Since we know that the member function is const, it's safe to
// remove the const qualifier from the 'this' pointer with a const_cast.
// VC6 has problems if we just overload 'bindmemfunc', so we give it a different name.
template < class X, class XMemFunc>
inline void bindconstmemfunc( const X *pthis, XMemFunc function_to_bind ) {
m_pthis= SimplifyMemFunc< sizeof( function_to_bind ) >
::Convert( const_cast<X*>( pthis ), function_to_bind, m_pFunction );
#if !defined( FASTDELEGATE_USESTATICFUNCTIONHACK )
m_pStaticFunction = 0;
#endif
}
#ifdef FASTDELEGATE_GCC_BUG_8271 // At present, GCC doesn't recognize constness of MFPs in templates
template < class X, class XMemFunc>
inline void bindmemfunc( const X *pthis, XMemFunc function_to_bind ) {
bindconstmemfunc( pthis, function_to_bind );
#if !defined( FASTDELEGATE_USESTATICFUNCTIONHACK )
m_pStaticFunction = 0;
#endif
}
#endif
// These functions are required for invoking the stored function
inline GenericClass *GetClosureThis( ) const { return m_pthis; }
inline GenericMemFunc GetClosureMemPtr( ) const { return reinterpret_cast<GenericMemFunc>( m_pFunction ); }
// There are a few ways of dealing with static function pointers.
// There's a standard-compliant, but tricky method.
// There's also a straightforward hack, that won't work on DOS compilers using the
// medium memory model. It's so evil that I can't recommend it, but I've
// implemented it anyway because it produces very nice asm code.
#if !defined( FASTDELEGATE_USESTATICFUNCTIONHACK )
// ClosurePtr<> - Safe version
//
// This implementation is standard-compliant, but a bit tricky.
// I store the function pointer inside the class, and the delegate then
// points to itself. Whenever the delegate is copied, these self-references
// must be transformed, and this complicates the = and == operators.
public:
// The next two functions are for operator ==, =, and the copy constructor.
// We may need to convert the m_pthis pointers, so that
// they remain as self-references.
template< class DerivedClass >
inline void CopyFrom ( DerivedClass *pParent, const DelegateMemento &x ) {
SetMementoFrom( x );
if ( m_pStaticFunction!=0 ) {
// transform self references...
m_pthis=reinterpret_cast<GenericClass *>( pParent );
}
}
// For static functions, the 'static_function_invoker' class in the parent
// will be called. The parent then needs to call GetStaticFunction( ) to find out
// the actual function to invoke.
template < class DerivedClass, class ParentInvokerSig >
inline void bindstaticfunc( DerivedClass *pParent, ParentInvokerSig static_function_invoker,
StaticFuncPtr function_to_bind ) {
if ( function_to_bind==0 ) { // cope with assignment to 0
m_pFunction=0;
} else {
bindmemfunc( pParent, static_function_invoker );
}
m_pStaticFunction=reinterpret_cast<GenericFuncPtr>( function_to_bind );
}
inline UnvoidStaticFuncPtr GetStaticFunction( ) const {
return reinterpret_cast<UnvoidStaticFuncPtr>( m_pStaticFunction );
}
#else
// ClosurePtr<> - Evil version
//
// For compilers where data pointers are at least as big as code pointers, it is
// possible to store the function pointer in the this pointer, using another
// horrible_cast. Invocation isn't any faster, but it saves 4 bytes, and
// speeds up comparison and assignment. If C++ provided direct language support
// for delegates, they would produce asm code that was almost identical to this.
// Note that the Sun C++ and MSVC documentation explicitly state that they
// support static_cast between void * and function pointers.
template< class DerivedClass >
inline void CopyFrom ( DerivedClass *pParent, const DelegateMemento &right ) {
SetMementoFrom( right );
}
// For static functions, the 'static_function_invoker' class in the parent
// will be called. The parent then needs to call GetStaticFunction( ) to find out
// the actual function to invoke.
// ******** EVIL, EVIL CODE! *******
template < class DerivedClass, class ParentInvokerSig>
inline void bindstaticfunc( DerivedClass *pParent, ParentInvokerSig static_function_invoker,
StaticFuncPtr function_to_bind ) {
if ( function_to_bind==0 ) { // cope with assignment to 0
m_pFunction=0;
} else {
// We'll be ignoring the 'this' pointer, but we need to make sure we pass
// a valid value to bindmemfunc( ).
bindmemfunc( pParent, static_function_invoker );
}
// WARNING! Evil hack. We store the function in the 'this' pointer!
// Ensure that there's a compilation failure if function pointers
// and data pointers have different sizes.
// If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK.
typedef int ERROR_CantUseEvilMethod[sizeof( GenericClass * )==sizeof( function_to_bind ) ? 1 : -1];
m_pthis = horrible_cast<GenericClass *>( function_to_bind );
// MSVC, SunC++ and DMC accept the following ( non-standard ) code:
// m_pthis = static_cast<GenericClass *>( static_cast<void *>( function_to_bind ) );
// BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long
// m_pthis = reinterpret_cast<GenericClass *>( reinterpret_cast<long>( function_to_bind ) );
}
// ******** EVIL, EVIL CODE! *******
// This function will be called with an invalid 'this' pointer!!
// We're just returning the 'this' pointer, converted into
// a function pointer!
inline UnvoidStaticFuncPtr GetStaticFunction( ) const {
// Ensure that there's a compilation failure if function pointers
// and data pointers have different sizes.
// If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK.
typedef int ERROR_CantUseEvilMethod[sizeof( UnvoidStaticFuncPtr )==sizeof( this ) ? 1 : -1];
return horrible_cast<UnvoidStaticFuncPtr>( this );
}
#endif // !defined( FASTDELEGATE_USESTATICFUNCTIONHACK )
// Does the closure contain this static function?
inline bool IsEqualToStaticFuncPtr( StaticFuncPtr funcptr ){
if ( funcptr==0 ) return empty( );
// For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary
// value that is not equal to any valid function pointer.
else return funcptr==reinterpret_cast<StaticFuncPtr>( GetStaticFunction( ) );
}
};
} // namespace detail
////////////////////////////////////////////////////////////////////////////////
// Fast Delegates, part 3:
//
// Wrapper classes to ensure type safety
//
////////////////////////////////////////////////////////////////////////////////
// Once we have the member function conversion templates, it's easy to make the
// wrapper classes. So that they will work with as many compilers as possible,
// the classes are of the form
// FastDelegate3<int, char *, double>
// They can cope with any combination of parameters. The max number of parameters
// allowed is 8, but it is trivial to increase this limit.
// Note that we need to treat const member functions seperately.
// All this class does is to enforce type safety, and invoke the delegate with
// the correct list of parameters.
// Because of the weird rule about the class of derived member function pointers,
// you sometimes need to apply a downcast to the 'this' pointer.
// This is the reason for the use of "implicit_cast<X*>( pthis )" in the code below.
// If CDerivedClass is derived from CBaseClass, but doesn't override SimpleVirtualFunction,
// without this trick you'd need to write:
// MyDelegate( static_cast<CBaseClass *>( &d ), &CDerivedClass::SimpleVirtualFunction );
// but with the trick you can write
// MyDelegate( &d, &CDerivedClass::SimpleVirtualFunction );
// RetType is the type the compiler uses in compiling the template. For VC6,
// it cannot be void. DesiredRetType is the real type which is returned from
// all of the functions. It can be void.
// Implicit conversion to "bool" is achieved using the safe_bool idiom,
// using member data pointers ( MDP ). This allows "if ( dg )..." syntax
// Because some compilers ( eg codeplay ) don't have a unique value for a zero
// MDP, an extra padding member is added to the SafeBool struct.
// Some compilers ( eg VC6 ) won't implicitly convert from 0 to an MDP, so
// in that case the static function constructor is not made explicit; this
// allows "if ( dg==0 ) ..." to compile.
//N=0
template<class RetType=detail::DefaultVoid>
class FastDelegate0 {
private:
typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
typedef DesiredRetType ( *StaticFunctionPtr )( );
typedef RetType ( *UnvoidStaticFunctionPtr )( );
typedef RetType ( detail::GenericClass::*GenericMemFn )( );
typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
ClosureType m_Closure;
public:
// Typedefs to aid generic programming
typedef FastDelegate0 type;
// Construction and comparison functions
FastDelegate0( ) { clear( ); }
FastDelegate0( const FastDelegate0 &x ) {
m_Closure.CopyFrom( this, x.m_Closure ); }
void operator = ( const FastDelegate0 &x ) {
m_Closure.CopyFrom( this, x.m_Closure ); }
bool operator ==( const FastDelegate0 &x ) const {
return m_Closure.IsEqual( x.m_Closure ); }
bool operator !=( const FastDelegate0 &x ) const {
return !m_Closure.IsEqual( x.m_Closure ); }
bool operator <( const FastDelegate0 &x ) const {
return m_Closure.IsLess( x.m_Closure ); }
bool operator >( const FastDelegate0 &x ) const {
return x.m_Closure.IsLess( m_Closure ); }
// Binding to non-const member functions
template < class X, class Y >
FastDelegate0( Y *pthis, DesiredRetType ( X::* function_to_bind )( ) ) {
m_Closure.bindmemfunc( detail::implicit_cast<X*>( pthis ), function_to_bind ); }
template < class X, class Y >
inline void bind( Y *pthis, DesiredRetType ( X::* function_to_bind )( ) ) {
m_Closure.bindmemfunc( detail::implicit_cast<X*>( pthis ), function_to_bind ); }
// Binding to const member functions.
template < class X, class Y >
FastDelegate0( const Y *pthis, DesiredRetType ( X::* function_to_bind )( ) const ) {
m_Closure.bindconstmemfunc( detail::implicit_cast<const X*>( pthis ), function_to_bind ); }
template < class X, class Y >
inline void bind( const Y *pthis, DesiredRetType ( X::* function_to_bind )( ) const ) {
m_Closure.bindconstmemfunc( detail::implicit_cast<const X *>( pthis ), function_to_bind ); }
// Static functions. We convert them into a member function call.
// This constructor also provides implicit conversion
FastDelegate0( DesiredRetType ( *function_to_bind )( ) ) {
bind( function_to_bind ); }
// for efficiency, prevent creation of a temporary
void operator = ( DesiredRetType ( *function_to_bind )( ) ) {
bind( function_to_bind ); }
inline void bind( DesiredRetType ( *function_to_bind )( ) ) {
m_Closure.bindstaticfunc( this, &FastDelegate0::InvokeStaticFunction,
function_to_bind ); }
// Invoke the delegate
RetType operator( ) ( ) const {
return ( m_Closure.GetClosureThis( )->*( m_Closure.GetClosureMemPtr( ) ) )( ); }
// Implicit conversion to "bool" using the safe_bool idiom
private:
typedef struct SafeBoolStruct {
int a_data_pointer_to_this_is_0_on_buggy_compilers;
StaticFunctionPtr m_nonzero;
} UselessTypedef;
typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
public:
operator unspecified_bool_type( ) const {
return empty( )? 0: &SafeBoolStruct::m_nonzero;
}
// necessary to allow ==0 to work despite the safe_bool idiom
inline bool operator==( StaticFunctionPtr funcptr ) {
return m_Closure.IsEqualToStaticFuncPtr( funcptr ); }
inline bool operator!=( StaticFunctionPtr funcptr ) {
return !m_Closure.IsEqualToStaticFuncPtr( funcptr ); }
inline bool operator ! ( ) const { // Is it bound to anything?
return !m_Closure; }
inline bool empty( ) const {
return !m_Closure; }
void clear( ) { m_Closure.clear( );}
// Conversion to and from the DelegateMemento storage class
const DelegateMemento & GetMemento( ) { return m_Closure; }
void SetMemento( const DelegateMemento &any ) { m_Closure.CopyFrom( this, any ); }
private: // Invoker for static functions
RetType InvokeStaticFunction( ) const {
return ( *( m_Closure.GetStaticFunction( ) ) )( ); }
};
//N=1
template<class Param1, class RetType=detail::DefaultVoid>
class FastDelegate1 {
private:
typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
typedef DesiredRetType ( *StaticFunctionPtr )( Param1 p1 );
typedef RetType ( *UnvoidStaticFunctionPtr )( Param1 p1 );
typedef RetType ( detail::GenericClass::*GenericMemFn )( Param1 p1 );
typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
ClosureType m_Closure;
public:
// Typedefs to aid generic programming
typedef FastDelegate1 type;
// Construction and comparison functions
FastDelegate1( ) { clear( ); }
FastDelegate1( const FastDelegate1 &x ) {
m_Closure.CopyFrom( this, x.m_Closure ); }
void operator = ( const FastDelegate1 &x ) {
m_Closure.CopyFrom( this, x.m_Closure ); }
bool operator ==( const FastDelegate1 &x ) const {
return m_Closure.IsEqual( x.m_Closure ); }
bool operator !=( const FastDelegate1 &x ) const {
return !m_Closure.IsEqual( x.m_Closure ); }
bool operator <( const FastDelegate1 &x ) const {
return m_Closure.IsLess( x.m_Closure ); }
bool operator >( const FastDelegate1 &x ) const {
return x.m_Closure.IsLess( m_Closure ); }
// Binding to non-const member functions
template < class X, class Y >
FastDelegate1( Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1 ) ) {
m_Closure.bindmemfunc( detail::implicit_cast<X*>( pthis ), function_to_bind ); }
template < class X, class Y >
inline void bind( Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1 ) ) {
m_Closure.bindmemfunc( detail::implicit_cast<X*>( pthis ), function_to_bind ); }
// Binding to const member functions.
template < class X, class Y >
FastDelegate1( const Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1 ) const ) {
m_Closure.bindconstmemfunc( detail::implicit_cast<const X*>( pthis ), function_to_bind ); }
template < class X, class Y >
inline void bind( const Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1 ) const ) {
m_Closure.bindconstmemfunc( detail::implicit_cast<const X *>( pthis ), function_to_bind ); }
// Static functions. We convert them into a member function call.
// This constructor also provides implicit conversion
FastDelegate1( DesiredRetType ( *function_to_bind )( Param1 p1 ) ) {
bind( function_to_bind ); }
// for efficiency, prevent creation of a temporary
void operator = ( DesiredRetType ( *function_to_bind )( Param1 p1 ) ) {
bind( function_to_bind ); }
inline void bind( DesiredRetType ( *function_to_bind )( Param1 p1 ) ) {
m_Closure.bindstaticfunc( this, &FastDelegate1::InvokeStaticFunction,
function_to_bind ); }
// Invoke the delegate
RetType operator( ) ( Param1 p1 ) const {
return ( m_Closure.GetClosureThis( )->*( m_Closure.GetClosureMemPtr( ) ) )( p1 ); }
// Implicit conversion to "bool" using the safe_bool idiom
private:
typedef struct SafeBoolStruct {
int a_data_pointer_to_this_is_0_on_buggy_compilers;
StaticFunctionPtr m_nonzero;
} UselessTypedef;
typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
public:
operator unspecified_bool_type( ) const {
return empty( )? 0: &SafeBoolStruct::m_nonzero;
}
// necessary to allow ==0 to work despite the safe_bool idiom
inline bool operator==( StaticFunctionPtr funcptr ) {
return m_Closure.IsEqualToStaticFuncPtr( funcptr ); }
inline bool operator!=( StaticFunctionPtr funcptr ) {
return !m_Closure.IsEqualToStaticFuncPtr( funcptr ); }
inline bool operator ! ( ) const { // Is it bound to anything?
return !m_Closure; }
inline bool empty( ) const {
return !m_Closure; }
void clear( ) { m_Closure.clear( );}
// Conversion to and from the DelegateMemento storage class
const DelegateMemento & GetMemento( ) { return m_Closure; }
void SetMemento( const DelegateMemento &any ) { m_Closure.CopyFrom( this, any ); }
private: // Invoker for static functions
RetType InvokeStaticFunction( Param1 p1 ) const {
return ( *( m_Closure.GetStaticFunction( ) ) )( p1 ); }
};
//N=2
template<class Param1, class Param2, class RetType=detail::DefaultVoid>
class FastDelegate2 {
private:
typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
typedef DesiredRetType ( *StaticFunctionPtr )( Param1 p1, Param2 p2 );
typedef RetType ( *UnvoidStaticFunctionPtr )( Param1 p1, Param2 p2 );
typedef RetType ( detail::GenericClass::*GenericMemFn )( Param1 p1, Param2 p2 );
typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
ClosureType m_Closure;
public:
// Typedefs to aid generic programming
typedef FastDelegate2 type;
// Construction and comparison functions
FastDelegate2( ) { clear( ); }
FastDelegate2( const FastDelegate2 &x ) {
m_Closure.CopyFrom( this, x.m_Closure ); }
void operator = ( const FastDelegate2 &x ) {
m_Closure.CopyFrom( this, x.m_Closure ); }
bool operator ==( const FastDelegate2 &x ) const {
return m_Closure.IsEqual( x.m_Closure ); }
bool operator !=( const FastDelegate2 &x ) const {
return !m_Closure.IsEqual( x.m_Closure ); }
bool operator <( const FastDelegate2 &x ) const {
return m_Closure.IsLess( x.m_Closure ); }
bool operator >( const FastDelegate2 &x ) const {
return x.m_Closure.IsLess( m_Closure ); }
// Binding to non-const member functions
template < class X, class Y >
FastDelegate2( Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2 ) ) {
m_Closure.bindmemfunc( detail::implicit_cast<X*>( pthis ), function_to_bind ); }
template < class X, class Y >
inline void bind( Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2 ) ) {
m_Closure.bindmemfunc( detail::implicit_cast<X*>( pthis ), function_to_bind ); }
// Binding to const member functions.
template < class X, class Y >
FastDelegate2( const Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2 ) const ) {
m_Closure.bindconstmemfunc( detail::implicit_cast<const X*>( pthis ), function_to_bind ); }
template < class X, class Y >
inline void bind( const Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2 ) const ) {
m_Closure.bindconstmemfunc( detail::implicit_cast<const X *>( pthis ), function_to_bind ); }
// Static functions. We convert them into a member function call.
// This constructor also provides implicit conversion
FastDelegate2( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2 ) ) {
bind( function_to_bind ); }
// for efficiency, prevent creation of a temporary
void operator = ( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2 ) ) {
bind( function_to_bind ); }
inline void bind( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2 ) ) {
m_Closure.bindstaticfunc( this, &FastDelegate2::InvokeStaticFunction,
function_to_bind ); }
// Invoke the delegate
RetType operator( ) ( Param1 p1, Param2 p2 ) const {
return ( m_Closure.GetClosureThis( )->*( m_Closure.GetClosureMemPtr( ) ) )( p1, p2 ); }
// Implicit conversion to "bool" using the safe_bool idiom
private:
typedef struct SafeBoolStruct {
int a_data_pointer_to_this_is_0_on_buggy_compilers;
StaticFunctionPtr m_nonzero;
} UselessTypedef;
typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
public:
operator unspecified_bool_type( ) const {
return empty( )? 0: &SafeBoolStruct::m_nonzero;
}
// necessary to allow ==0 to work despite the safe_bool idiom
inline bool operator==( StaticFunctionPtr funcptr ) {
return m_Closure.IsEqualToStaticFuncPtr( funcptr ); }
inline bool operator!=( StaticFunctionPtr funcptr ) {
return !m_Closure.IsEqualToStaticFuncPtr( funcptr ); }
inline bool operator ! ( ) const { // Is it bound to anything?
return !m_Closure; }
inline bool empty( ) const {
return !m_Closure; }
void clear( ) { m_Closure.clear( );}
// Conversion to and from the DelegateMemento storage class
const DelegateMemento & GetMemento( ) { return m_Closure; }
void SetMemento( const DelegateMemento &any ) { m_Closure.CopyFrom( this, any ); }
private: // Invoker for static functions
RetType InvokeStaticFunction( Param1 p1, Param2 p2 ) const {
return ( *( m_Closure.GetStaticFunction( ) ) )( p1, p2 ); }
};
//N=3
template<class Param1, class Param2, class Param3, class RetType=detail::DefaultVoid>
class FastDelegate3 {
private:
typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
typedef DesiredRetType ( *StaticFunctionPtr )( Param1 p1, Param2 p2, Param3 p3 );
typedef RetType ( *UnvoidStaticFunctionPtr )( Param1 p1, Param2 p2, Param3 p3 );
typedef RetType ( detail::GenericClass::*GenericMemFn )( Param1 p1, Param2 p2, Param3 p3 );
typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
ClosureType m_Closure;
public:
// Typedefs to aid generic programming
typedef FastDelegate3 type;
// Construction and comparison functions
FastDelegate3( ) { clear( ); }
FastDelegate3( const FastDelegate3 &x ) {
m_Closure.CopyFrom( this, x.m_Closure ); }
void operator = ( const FastDelegate3 &x ) {
m_Closure.CopyFrom( this, x.m_Closure ); }
bool operator ==( const FastDelegate3 &x ) const {
return m_Closure.IsEqual( x.m_Closure ); }
bool operator !=( const FastDelegate3 &x ) const {
return !m_Closure.IsEqual( x.m_Closure ); }
bool operator <( const FastDelegate3 &x ) const {
return m_Closure.IsLess( x.m_Closure ); }
bool operator >( const FastDelegate3 &x ) const {
return x.m_Closure.IsLess( m_Closure ); }
// Binding to non-const member functions
template < class X, class Y >
FastDelegate3( Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3 ) ) {
m_Closure.bindmemfunc( detail::implicit_cast<X*>( pthis ), function_to_bind ); }
template < class X, class Y >
inline void bind( Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3 ) ) {
m_Closure.bindmemfunc( detail::implicit_cast<X*>( pthis ), function_to_bind ); }
// Binding to const member functions.
template < class X, class Y >
FastDelegate3( const Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3 ) const ) {
m_Closure.bindconstmemfunc( detail::implicit_cast<const X*>( pthis ), function_to_bind ); }
template < class X, class Y >
inline void bind( const Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3 ) const ) {
m_Closure.bindconstmemfunc( detail::implicit_cast<const X *>( pthis ), function_to_bind ); }
// Static functions. We convert them into a member function call.
// This constructor also provides implicit conversion
FastDelegate3( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3 ) ) {
bind( function_to_bind ); }
// for efficiency, prevent creation of a temporary
void operator = ( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3 ) ) {
bind( function_to_bind ); }
inline void bind( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3 ) ) {
m_Closure.bindstaticfunc( this, &FastDelegate3::InvokeStaticFunction,
function_to_bind ); }
// Invoke the delegate
RetType operator( ) ( Param1 p1, Param2 p2, Param3 p3 ) const {
return ( m_Closure.GetClosureThis( )->*( m_Closure.GetClosureMemPtr( ) ) )( p1, p2, p3 ); }
// Implicit conversion to "bool" using the safe_bool idiom
private:
typedef struct SafeBoolStruct {
int a_data_pointer_to_this_is_0_on_buggy_compilers;
StaticFunctionPtr m_nonzero;
} UselessTypedef;
typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
public:
operator unspecified_bool_type( ) const {
return empty( )? 0: &SafeBoolStruct::m_nonzero;
}
// necessary to allow ==0 to work despite the safe_bool idiom
inline bool operator==( StaticFunctionPtr funcptr ) {
return m_Closure.IsEqualToStaticFuncPtr( funcptr ); }
inline bool operator!=( StaticFunctionPtr funcptr ) {
return !m_Closure.IsEqualToStaticFuncPtr( funcptr ); }
inline bool operator ! ( ) const { // Is it bound to anything?
return !m_Closure; }
inline bool empty( ) const {
return !m_Closure; }
void clear( ) { m_Closure.clear( );}
// Conversion to and from the DelegateMemento storage class
const DelegateMemento & GetMemento( ) { return m_Closure; }
void SetMemento( const DelegateMemento &any ) { m_Closure.CopyFrom( this, any ); }
private: // Invoker for static functions
RetType InvokeStaticFunction( Param1 p1, Param2 p2, Param3 p3 ) const {
return ( *( m_Closure.GetStaticFunction( ) ) )( p1, p2, p3 ); }
};
//N=4
template<class Param1, class Param2, class Param3, class Param4, class RetType=detail::DefaultVoid>
class FastDelegate4 {
private:
typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
typedef DesiredRetType ( *StaticFunctionPtr )( Param1 p1, Param2 p2, Param3 p3, Param4 p4 );
typedef RetType ( *UnvoidStaticFunctionPtr )( Param1 p1, Param2 p2, Param3 p3, Param4 p4 );
typedef RetType ( detail::GenericClass::*GenericMemFn )( Param1 p1, Param2 p2, Param3 p3, Param4 p4 );
typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
ClosureType m_Closure;
public:
// Typedefs to aid generic programming
typedef FastDelegate4 type;
// Construction and comparison functions
FastDelegate4( ) { clear( ); }
FastDelegate4( const FastDelegate4 &x ) {
m_Closure.CopyFrom( this, x.m_Closure ); }
void operator = ( const FastDelegate4 &x ) {
m_Closure.CopyFrom( this, x.m_Closure ); }
bool operator ==( const FastDelegate4 &x ) const {
return m_Closure.IsEqual( x.m_Closure ); }
bool operator !=( const FastDelegate4 &x ) const {
return !m_Closure.IsEqual( x.m_Closure ); }
bool operator <( const FastDelegate4 &x ) const {
return m_Closure.IsLess( x.m_Closure ); }
bool operator >( const FastDelegate4 &x ) const {
return x.m_Closure.IsLess( m_Closure ); }
// Binding to non-const member functions
template < class X, class Y >
FastDelegate4( Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) ) {
m_Closure.bindmemfunc( detail::implicit_cast<X*>( pthis ), function_to_bind ); }
template < class X, class Y >
inline void bind( Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) ) {
m_Closure.bindmemfunc( detail::implicit_cast<X*>( pthis ), function_to_bind ); }
// Binding to const member functions.
template < class X, class Y >
FastDelegate4( const Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const ) {
m_Closure.bindconstmemfunc( detail::implicit_cast<const X*>( pthis ), function_to_bind ); }
template < class X, class Y >
inline void bind( const Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const ) {
m_Closure.bindconstmemfunc( detail::implicit_cast<const X *>( pthis ), function_to_bind ); }
// Static functions. We convert them into a member function call.
// This constructor also provides implicit conversion
FastDelegate4( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) ) {
bind( function_to_bind ); }
// for efficiency, prevent creation of a temporary
void operator = ( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) ) {
bind( function_to_bind ); }
inline void bind( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) ) {
m_Closure.bindstaticfunc( this, &FastDelegate4::InvokeStaticFunction,
function_to_bind ); }
// Invoke the delegate
RetType operator( ) ( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const {
return ( m_Closure.GetClosureThis( )->*( m_Closure.GetClosureMemPtr( ) ) )( p1, p2, p3, p4 ); }
// Implicit conversion to "bool" using the safe_bool idiom
private:
typedef struct SafeBoolStruct {
int a_data_pointer_to_this_is_0_on_buggy_compilers;
StaticFunctionPtr m_nonzero;
} UselessTypedef;
typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
public:
operator unspecified_bool_type( ) const {
return empty( )? 0: &SafeBoolStruct::m_nonzero;
}
// necessary to allow ==0 to work despite the safe_bool idiom
inline bool operator==( StaticFunctionPtr funcptr ) {
return m_Closure.IsEqualToStaticFuncPtr( funcptr ); }
inline bool operator!=( StaticFunctionPtr funcptr ) {
return !m_Closure.IsEqualToStaticFuncPtr( funcptr ); }
inline bool operator ! ( ) const { // Is it bound to anything?
return !m_Closure; }
inline bool empty( ) const {
return !m_Closure; }
void clear( ) { m_Closure.clear( );}
// Conversion to and from the DelegateMemento storage class
const DelegateMemento & GetMemento( ) { return m_Closure; }
void SetMemento( const DelegateMemento &any ) { m_Closure.CopyFrom( this, any ); }
private: // Invoker for static functions
RetType InvokeStaticFunction( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const {
return ( *( m_Closure.GetStaticFunction( ) ) )( p1, p2, p3, p4 ); }
};
//N=5
template<class Param1, class Param2, class Param3, class Param4, class Param5, class RetType=detail::DefaultVoid>
class FastDelegate5 {
private:
typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
typedef DesiredRetType ( *StaticFunctionPtr )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 );
typedef RetType ( *UnvoidStaticFunctionPtr )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 );
typedef RetType ( detail::GenericClass::*GenericMemFn )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 );
typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
ClosureType m_Closure;
public:
// Typedefs to aid generic programming
typedef FastDelegate5 type;
// Construction and comparison functions
FastDelegate5( ) { clear( ); }
FastDelegate5( const FastDelegate5 &x ) {
m_Closure.CopyFrom( this, x.m_Closure ); }
void operator = ( const FastDelegate5 &x ) {
m_Closure.CopyFrom( this, x.m_Closure ); }
bool operator ==( const FastDelegate5 &x ) const {
return m_Closure.IsEqual( x.m_Closure ); }
bool operator !=( const FastDelegate5 &x ) const {
return !m_Closure.IsEqual( x.m_Closure ); }
bool operator <( const FastDelegate5 &x ) const {
return m_Closure.IsLess( x.m_Closure ); }
bool operator >( const FastDelegate5 &x ) const {
return x.m_Closure.IsLess( m_Closure ); }
// Binding to non-const member functions
template < class X, class Y >
FastDelegate5( Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) ) {
m_Closure.bindmemfunc( detail::implicit_cast<X*>( pthis ), function_to_bind ); }
template < class X, class Y >
inline void bind( Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) ) {
m_Closure.bindmemfunc( detail::implicit_cast<X*>( pthis ), function_to_bind ); }
// Binding to const member functions.
template < class X, class Y >
FastDelegate5( const Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const ) {
m_Closure.bindconstmemfunc( detail::implicit_cast<const X*>( pthis ), function_to_bind ); }
template < class X, class Y >
inline void bind( const Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const ) {
m_Closure.bindconstmemfunc( detail::implicit_cast<const X *>( pthis ), function_to_bind ); }
// Static functions. We convert them into a member function call.
// This constructor also provides implicit conversion
FastDelegate5( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) ) {
bind( function_to_bind ); }
// for efficiency, prevent creation of a temporary
void operator = ( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) ) {
bind( function_to_bind ); }
inline void bind( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) ) {
m_Closure.bindstaticfunc( this, &FastDelegate5::InvokeStaticFunction,
function_to_bind ); }
// Invoke the delegate
RetType operator( ) ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const {
return ( m_Closure.GetClosureThis( )->*( m_Closure.GetClosureMemPtr( ) ) )( p1, p2, p3, p4, p5 ); }
// Implicit conversion to "bool" using the safe_bool idiom
private:
typedef struct SafeBoolStruct {
int a_data_pointer_to_this_is_0_on_buggy_compilers;
StaticFunctionPtr m_nonzero;
} UselessTypedef;
typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
public:
operator unspecified_bool_type( ) const {
return empty( )? 0: &SafeBoolStruct::m_nonzero;
}
// necessary to allow ==0 to work despite the safe_bool idiom
inline bool operator==( StaticFunctionPtr funcptr ) {
return m_Closure.IsEqualToStaticFuncPtr( funcptr ); }
inline bool operator!=( StaticFunctionPtr funcptr ) {
return !m_Closure.IsEqualToStaticFuncPtr( funcptr ); }
inline bool operator ! ( ) const { // Is it bound to anything?
return !m_Closure; }
inline bool empty( ) const {
return !m_Closure; }
void clear( ) { m_Closure.clear( );}
// Conversion to and from the DelegateMemento storage class
const DelegateMemento & GetMemento( ) { return m_Closure; }
void SetMemento( const DelegateMemento &any ) { m_Closure.CopyFrom( this, any ); }
private: // Invoker for static functions
RetType InvokeStaticFunction( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const {
return ( *( m_Closure.GetStaticFunction( ) ) )( p1, p2, p3, p4, p5 ); }
};
//N=6
template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType=detail::DefaultVoid>
class FastDelegate6 {
private:
typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
typedef DesiredRetType ( *StaticFunctionPtr )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 );
typedef RetType ( *UnvoidStaticFunctionPtr )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 );
typedef RetType ( detail::GenericClass::*GenericMemFn )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 );
typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
ClosureType m_Closure;
public:
// Typedefs to aid generic programming
typedef FastDelegate6 type;
// Construction and comparison functions
FastDelegate6( ) { clear( ); }
FastDelegate6( const FastDelegate6 &x ) {
m_Closure.CopyFrom( this, x.m_Closure ); }
void operator = ( const FastDelegate6 &x ) {
m_Closure.CopyFrom( this, x.m_Closure ); }
bool operator ==( const FastDelegate6 &x ) const {
return m_Closure.IsEqual( x.m_Closure ); }
bool operator !=( const FastDelegate6 &x ) const {
return !m_Closure.IsEqual( x.m_Closure ); }
bool operator <( const FastDelegate6 &x ) const {
return m_Closure.IsLess( x.m_Closure ); }
bool operator >( const FastDelegate6 &x ) const {
return x.m_Closure.IsLess( m_Closure ); }
// Binding to non-const member functions
template < class X, class Y >
FastDelegate6( Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) ) {
m_Closure.bindmemfunc( detail::implicit_cast<X*>( pthis ), function_to_bind ); }
template < class X, class Y >
inline void bind( Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) ) {
m_Closure.bindmemfunc( detail::implicit_cast<X*>( pthis ), function_to_bind ); }
// Binding to const member functions.
template < class X, class Y >
FastDelegate6( const Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const ) {
m_Closure.bindconstmemfunc( detail::implicit_cast<const X*>( pthis ), function_to_bind ); }
template < class X, class Y >
inline void bind( const Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const ) {
m_Closure.bindconstmemfunc( detail::implicit_cast<const X *>( pthis ), function_to_bind ); }
// Static functions. We convert them into a member function call.
// This constructor also provides implicit conversion
FastDelegate6( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) ) {
bind( function_to_bind ); }
// for efficiency, prevent creation of a temporary
void operator = ( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) ) {
bind( function_to_bind ); }
inline void bind( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) ) {
m_Closure.bindstaticfunc( this, &FastDelegate6::InvokeStaticFunction,
function_to_bind ); }
// Invoke the delegate
RetType operator( ) ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const {
return ( m_Closure.GetClosureThis( )->*( m_Closure.GetClosureMemPtr( ) ) )( p1, p2, p3, p4, p5, p6 ); }
// Implicit conversion to "bool" using the safe_bool idiom
private:
typedef struct SafeBoolStruct {
int a_data_pointer_to_this_is_0_on_buggy_compilers;
StaticFunctionPtr m_nonzero;
} UselessTypedef;
typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
public:
operator unspecified_bool_type( ) const {
return empty( )? 0: &SafeBoolStruct::m_nonzero;
}
// necessary to allow ==0 to work despite the safe_bool idiom
inline bool operator==( StaticFunctionPtr funcptr ) {
return m_Closure.IsEqualToStaticFuncPtr( funcptr ); }
inline bool operator!=( StaticFunctionPtr funcptr ) {
return !m_Closure.IsEqualToStaticFuncPtr( funcptr ); }
inline bool operator ! ( ) const { // Is it bound to anything?
return !m_Closure; }
inline bool empty( ) const {
return !m_Closure; }
void clear( ) { m_Closure.clear( );}
// Conversion to and from the DelegateMemento storage class
const DelegateMemento & GetMemento( ) { return m_Closure; }
void SetMemento( const DelegateMemento &any ) { m_Closure.CopyFrom( this, any ); }
private: // Invoker for static functions
RetType InvokeStaticFunction( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const {
return ( *( m_Closure.GetStaticFunction( ) ) )( p1, p2, p3, p4, p5, p6 ); }
};
//N=7
template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType=detail::DefaultVoid>
class FastDelegate7 {
private:
typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
typedef DesiredRetType ( *StaticFunctionPtr )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 );
typedef RetType ( *UnvoidStaticFunctionPtr )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 );
typedef RetType ( detail::GenericClass::*GenericMemFn )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 );
typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
ClosureType m_Closure;
public:
// Typedefs to aid generic programming
typedef FastDelegate7 type;
// Construction and comparison functions
FastDelegate7( ) { clear( ); }
FastDelegate7( const FastDelegate7 &x ) {
m_Closure.CopyFrom( this, x.m_Closure ); }
void operator = ( const FastDelegate7 &x ) {
m_Closure.CopyFrom( this, x.m_Closure ); }
bool operator ==( const FastDelegate7 &x ) const {
return m_Closure.IsEqual( x.m_Closure ); }
bool operator !=( const FastDelegate7 &x ) const {
return !m_Closure.IsEqual( x.m_Closure ); }
bool operator <( const FastDelegate7 &x ) const {
return m_Closure.IsLess( x.m_Closure ); }
bool operator >( const FastDelegate7 &x ) const {
return x.m_Closure.IsLess( m_Closure ); }
// Binding to non-const member functions
template < class X, class Y >
FastDelegate7( Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) ) {
m_Closure.bindmemfunc( detail::implicit_cast<X*>( pthis ), function_to_bind ); }
template < class X, class Y >
inline void bind( Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) ) {
m_Closure.bindmemfunc( detail::implicit_cast<X*>( pthis ), function_to_bind ); }
// Binding to const member functions.
template < class X, class Y >
FastDelegate7( const Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const ) {
m_Closure.bindconstmemfunc( detail::implicit_cast<const X*>( pthis ), function_to_bind ); }
template < class X, class Y >
inline void bind( const Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const ) {
m_Closure.bindconstmemfunc( detail::implicit_cast<const X *>( pthis ), function_to_bind ); }
// Static functions. We convert them into a member function call.
// This constructor also provides implicit conversion
FastDelegate7( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) ) {
bind( function_to_bind ); }
// for efficiency, prevent creation of a temporary
void operator = ( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) ) {
bind( function_to_bind ); }
inline void bind( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) ) {
m_Closure.bindstaticfunc( this, &FastDelegate7::InvokeStaticFunction,
function_to_bind ); }
// Invoke the delegate
RetType operator( ) ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const {
return ( m_Closure.GetClosureThis( )->*( m_Closure.GetClosureMemPtr( ) ) )( p1, p2, p3, p4, p5, p6, p7 ); }
// Implicit conversion to "bool" using the safe_bool idiom
private:
typedef struct SafeBoolStruct {
int a_data_pointer_to_this_is_0_on_buggy_compilers;
StaticFunctionPtr m_nonzero;
} UselessTypedef;
typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
public:
operator unspecified_bool_type( ) const {
return empty( )? 0: &SafeBoolStruct::m_nonzero;
}
// necessary to allow ==0 to work despite the safe_bool idiom
inline bool operator==( StaticFunctionPtr funcptr ) {
return m_Closure.IsEqualToStaticFuncPtr( funcptr ); }
inline bool operator!=( StaticFunctionPtr funcptr ) {
return !m_Closure.IsEqualToStaticFuncPtr( funcptr ); }
inline bool operator ! ( ) const { // Is it bound to anything?
return !m_Closure; }
inline bool empty( ) const {
return !m_Closure; }
void clear( ) { m_Closure.clear( );}
// Conversion to and from the DelegateMemento storage class
const DelegateMemento & GetMemento( ) { return m_Closure; }
void SetMemento( const DelegateMemento &any ) { m_Closure.CopyFrom( this, any ); }
private: // Invoker for static functions
RetType InvokeStaticFunction( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const {
return ( *( m_Closure.GetStaticFunction( ) ) )( p1, p2, p3, p4, p5, p6, p7 ); }
};
//N=8
template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType=detail::DefaultVoid>
class FastDelegate8 {
private:
typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
typedef DesiredRetType ( *StaticFunctionPtr )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 );
typedef RetType ( *UnvoidStaticFunctionPtr )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 );
typedef RetType ( detail::GenericClass::*GenericMemFn )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 );
typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
ClosureType m_Closure;
public:
// Typedefs to aid generic programming
typedef FastDelegate8 type;
// Construction and comparison functions
FastDelegate8( ) { clear( ); }
FastDelegate8( const FastDelegate8 &x ) {
m_Closure.CopyFrom( this, x.m_Closure ); }
void operator = ( const FastDelegate8 &x ) {
m_Closure.CopyFrom( this, x.m_Closure ); }
bool operator ==( const FastDelegate8 &x ) const {
return m_Closure.IsEqual( x.m_Closure ); }
bool operator !=( const FastDelegate8 &x ) const {
return !m_Closure.IsEqual( x.m_Closure ); }
bool operator <( const FastDelegate8 &x ) const {
return m_Closure.IsLess( x.m_Closure ); }
bool operator >( const FastDelegate8 &x ) const {
return x.m_Closure.IsLess( m_Closure ); }
// Binding to non-const member functions
template < class X, class Y >
FastDelegate8( Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) ) {
m_Closure.bindmemfunc( detail::implicit_cast<X*>( pthis ), function_to_bind ); }
template < class X, class Y >
inline void bind( Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) ) {
m_Closure.bindmemfunc( detail::implicit_cast<X*>( pthis ), function_to_bind ); }
// Binding to const member functions.
template < class X, class Y >
FastDelegate8( const Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const ) {
m_Closure.bindconstmemfunc( detail::implicit_cast<const X*>( pthis ), function_to_bind ); }
template < class X, class Y >
inline void bind( const Y *pthis, DesiredRetType ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const ) {
m_Closure.bindconstmemfunc( detail::implicit_cast<const X *>( pthis ), function_to_bind ); }
// Static functions. We convert them into a member function call.
// This constructor also provides implicit conversion
FastDelegate8( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) ) {
bind( function_to_bind ); }
// for efficiency, prevent creation of a temporary
void operator = ( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) ) {
bind( function_to_bind ); }
inline void bind( DesiredRetType ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) ) {
m_Closure.bindstaticfunc( this, &FastDelegate8::InvokeStaticFunction,
function_to_bind ); }
// Invoke the delegate
RetType operator( ) ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const {
return ( m_Closure.GetClosureThis( )->*( m_Closure.GetClosureMemPtr( ) ) )( p1, p2, p3, p4, p5, p6, p7, p8 ); }
// Implicit conversion to "bool" using the safe_bool idiom
private:
typedef struct SafeBoolStruct {
int a_data_pointer_to_this_is_0_on_buggy_compilers;
StaticFunctionPtr m_nonzero;
} UselessTypedef;
typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
public:
operator unspecified_bool_type( ) const {
return empty( )? 0: &SafeBoolStruct::m_nonzero;
}
// necessary to allow ==0 to work despite the safe_bool idiom
inline bool operator==( StaticFunctionPtr funcptr ) {
return m_Closure.IsEqualToStaticFuncPtr( funcptr ); }
inline bool operator!=( StaticFunctionPtr funcptr ) {
return !m_Closure.IsEqualToStaticFuncPtr( funcptr ); }
inline bool operator ! ( ) const { // Is it bound to anything?
return !m_Closure; }
inline bool empty( ) const {
return !m_Closure; }
void clear( ) { m_Closure.clear( );}
// Conversion to and from the DelegateMemento storage class
const DelegateMemento & GetMemento( ) { return m_Closure; }
void SetMemento( const DelegateMemento &any ) { m_Closure.CopyFrom( this, any ); }
private: // Invoker for static functions
RetType InvokeStaticFunction( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const {
return ( *( m_Closure.GetStaticFunction( ) ) )( p1, p2, p3, p4, p5, p6, p7, p8 ); }
};
////////////////////////////////////////////////////////////////////////////////
// Fast Delegates, part 4:
//
// FastDelegate<> class ( Original author: Jody Hagins )
// Allows boost::function style syntax like:
// FastDelegate< double ( int, long ) >
// instead of:
// FastDelegate2< int, long, double >
//
////////////////////////////////////////////////////////////////////////////////
#ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
// Declare FastDelegate as a class template. It will be specialized
// later for all number of arguments.
template <typename Signature>
class FastDelegate;
//N=0
// Specialization to allow use of
// FastDelegate< R ( ) >
// instead of
// FastDelegate0 < R >
template<typename R>
class FastDelegate< R ( ) >
// Inherit from FastDelegate0 so that it can be treated just like a FastDelegate0
: public FastDelegate0 < R >
{
public:
// Make using the base type a bit easier via typedef.
typedef FastDelegate0 < R > BaseType;
// Allow users access to the specific type of this delegate.
typedef FastDelegate SelfType;
// Mimic the base class constructors.
FastDelegate( ) : BaseType( ) { }
template < class X, class Y >
FastDelegate( Y * pthis,
R ( X::* function_to_bind )( ) )
: BaseType( pthis, function_to_bind ) { }
template < class X, class Y >
FastDelegate( const Y *pthis,
R ( X::* function_to_bind )( ) const )
: BaseType( pthis, function_to_bind )
{ }
FastDelegate( R ( *function_to_bind )( ) )
: BaseType( function_to_bind ) { }
void operator = ( const BaseType &x ) {
*static_cast<BaseType*>( this ) = x; }
};
//N=1
// Specialization to allow use of
// FastDelegate< R ( Param1 ) >
// instead of
// FastDelegate1 < Param1, R >
template<typename R, class Param1>
class FastDelegate< R ( Param1 ) >
// Inherit from FastDelegate1 so that it can be treated just like a FastDelegate1
: public FastDelegate1 < Param1, R >
{
public:
// Make using the base type a bit easier via typedef.
typedef FastDelegate1 < Param1, R > BaseType;
// Allow users access to the specific type of this delegate.
typedef FastDelegate SelfType;
// Mimic the base class constructors.
FastDelegate( ) : BaseType( ) { }
template < class X, class Y >
FastDelegate( Y * pthis,
R ( X::* function_to_bind )( Param1 p1 ) )
: BaseType( pthis, function_to_bind ) { }
template < class X, class Y >
FastDelegate( const Y *pthis,
R ( X::* function_to_bind )( Param1 p1 ) const )
: BaseType( pthis, function_to_bind )
{ }
FastDelegate( R ( *function_to_bind )( Param1 p1 ) )
: BaseType( function_to_bind ) { }
void operator = ( const BaseType &x ) {
*static_cast<BaseType*>( this ) = x; }
};
//N=2
// Specialization to allow use of
// FastDelegate< R ( Param1, Param2 ) >
// instead of
// FastDelegate2 < Param1, Param2, R >
template<typename R, class Param1, class Param2>
class FastDelegate< R ( Param1, Param2 ) >
// Inherit from FastDelegate2 so that it can be treated just like a FastDelegate2
: public FastDelegate2 < Param1, Param2, R >
{
public:
// Make using the base type a bit easier via typedef.
typedef FastDelegate2 < Param1, Param2, R > BaseType;
// Allow users access to the specific type of this delegate.
typedef FastDelegate SelfType;
// Mimic the base class constructors.
FastDelegate( ) : BaseType( ) { }
template < class X, class Y >
FastDelegate( Y * pthis,
R ( X::* function_to_bind )( Param1 p1, Param2 p2 ) )
: BaseType( pthis, function_to_bind ) { }
template < class X, class Y >
FastDelegate( const Y *pthis,
R ( X::* function_to_bind )( Param1 p1, Param2 p2 ) const )
: BaseType( pthis, function_to_bind )
{ }
FastDelegate( R ( *function_to_bind )( Param1 p1, Param2 p2 ) )
: BaseType( function_to_bind ) { }
void operator = ( const BaseType &x ) {
*static_cast<BaseType*>( this ) = x; }
};
//N=3
// Specialization to allow use of
// FastDelegate< R ( Param1, Param2, Param3 ) >
// instead of
// FastDelegate3 < Param1, Param2, Param3, R >
template<typename R, class Param1, class Param2, class Param3>
class FastDelegate< R ( Param1, Param2, Param3 ) >
// Inherit from FastDelegate3 so that it can be treated just like a FastDelegate3
: public FastDelegate3 < Param1, Param2, Param3, R >
{
public:
// Make using the base type a bit easier via typedef.
typedef FastDelegate3 < Param1, Param2, Param3, R > BaseType;
// Allow users access to the specific type of this delegate.
typedef FastDelegate SelfType;
// Mimic the base class constructors.
FastDelegate( ) : BaseType( ) { }
template < class X, class Y >
FastDelegate( Y * pthis,
R ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3 ) )
: BaseType( pthis, function_to_bind ) { }
template < class X, class Y >
FastDelegate( const Y *pthis,
R ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3 ) const )
: BaseType( pthis, function_to_bind )
{ }
FastDelegate( R ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3 ) )
: BaseType( function_to_bind ) { }
void operator = ( const BaseType &x ) {
*static_cast<BaseType*>( this ) = x; }
};
//N=4
// Specialization to allow use of
// FastDelegate< R ( Param1, Param2, Param3, Param4 ) >
// instead of
// FastDelegate4 < Param1, Param2, Param3, Param4, R >
template<typename R, class Param1, class Param2, class Param3, class Param4>
class FastDelegate< R ( Param1, Param2, Param3, Param4 ) >
// Inherit from FastDelegate4 so that it can be treated just like a FastDelegate4
: public FastDelegate4 < Param1, Param2, Param3, Param4, R >
{
public:
// Make using the base type a bit easier via typedef.
typedef FastDelegate4 < Param1, Param2, Param3, Param4, R > BaseType;
// Allow users access to the specific type of this delegate.
typedef FastDelegate SelfType;
// Mimic the base class constructors.
FastDelegate( ) : BaseType( ) { }
template < class X, class Y >
FastDelegate( Y * pthis,
R ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) )
: BaseType( pthis, function_to_bind ) { }
template < class X, class Y >
FastDelegate( const Y *pthis,
R ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const )
: BaseType( pthis, function_to_bind )
{ }
FastDelegate( R ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) )
: BaseType( function_to_bind ) { }
void operator = ( const BaseType &x ) {
*static_cast<BaseType*>( this ) = x; }
};
//N=5
// Specialization to allow use of
// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) >
// instead of
// FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R >
template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5>
class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) >
// Inherit from FastDelegate5 so that it can be treated just like a FastDelegate5
: public FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R >
{
public:
// Make using the base type a bit easier via typedef.
typedef FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > BaseType;
// Allow users access to the specific type of this delegate.
typedef FastDelegate SelfType;
// Mimic the base class constructors.
FastDelegate( ) : BaseType( ) { }
template < class X, class Y >
FastDelegate( Y * pthis,
R ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) )
: BaseType( pthis, function_to_bind ) { }
template < class X, class Y >
FastDelegate( const Y *pthis,
R ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const )
: BaseType( pthis, function_to_bind )
{ }
FastDelegate( R ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) )
: BaseType( function_to_bind ) { }
void operator = ( const BaseType &x ) {
*static_cast<BaseType*>( this ) = x; }
};
//N=6
// Specialization to allow use of
// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) >
// instead of
// FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R >
template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) >
// Inherit from FastDelegate6 so that it can be treated just like a FastDelegate6
: public FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R >
{
public:
// Make using the base type a bit easier via typedef.
typedef FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > BaseType;
// Allow users access to the specific type of this delegate.
typedef FastDelegate SelfType;
// Mimic the base class constructors.
FastDelegate( ) : BaseType( ) { }
template < class X, class Y >
FastDelegate( Y * pthis,
R ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) )
: BaseType( pthis, function_to_bind ) { }
template < class X, class Y >
FastDelegate( const Y *pthis,
R ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const )
: BaseType( pthis, function_to_bind )
{ }
FastDelegate( R ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) )
: BaseType( function_to_bind ) { }
void operator = ( const BaseType &x ) {
*static_cast<BaseType*>( this ) = x; }
};
//N=7
// Specialization to allow use of
// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >
// instead of
// FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R >
template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >
// Inherit from FastDelegate7 so that it can be treated just like a FastDelegate7
: public FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R >
{
public:
// Make using the base type a bit easier via typedef.
typedef FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > BaseType;
// Allow users access to the specific type of this delegate.
typedef FastDelegate SelfType;
// Mimic the base class constructors.
FastDelegate( ) : BaseType( ) { }
template < class X, class Y >
FastDelegate( Y * pthis,
R ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) )
: BaseType( pthis, function_to_bind ) { }
template < class X, class Y >
FastDelegate( const Y *pthis,
R ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const )
: BaseType( pthis, function_to_bind )
{ }
FastDelegate( R ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) )
: BaseType( function_to_bind ) { }
void operator = ( const BaseType &x ) {
*static_cast<BaseType*>( this ) = x; }
};
//N=8
// Specialization to allow use of
// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >
// instead of
// FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R >
template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >
// Inherit from FastDelegate8 so that it can be treated just like a FastDelegate8
: public FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R >
{
public:
// Make using the base type a bit easier via typedef.
typedef FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > BaseType;
// Allow users access to the specific type of this delegate.
typedef FastDelegate SelfType;
// Mimic the base class constructors.
FastDelegate( ) : BaseType( ) { }
template < class X, class Y >
FastDelegate( Y * pthis,
R ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) )
: BaseType( pthis, function_to_bind ) { }
template < class X, class Y >
FastDelegate( const Y *pthis,
R ( X::* function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const )
: BaseType( pthis, function_to_bind )
{ }
FastDelegate( R ( *function_to_bind )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) )
: BaseType( function_to_bind ) { }
void operator = ( const BaseType &x ) {
*static_cast<BaseType*>( this ) = x; }
};
#endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
////////////////////////////////////////////////////////////////////////////////
// Fast Delegates, part 5:
//
// MakeDelegate( ) helper function
//
// MakeDelegate( &x, &X::func ) returns a fastdelegate of the type
// necessary for calling x.func( ) with the correct number of arguments.
// This makes it possible to eliminate many typedefs from user code.
//
////////////////////////////////////////////////////////////////////////////////
// Also declare overloads of a MakeDelegate( ) global function to
// reduce the need for typedefs.
// We need seperate overloads for const and non-const member functions.
// Also, because of the weird rule about the class of derived member function pointers,
// implicit downcasts may need to be applied later to the 'this' pointer.
// That's why two classes ( X and Y ) appear in the definitions. Y must be implicitly
// castable to X.
// Workaround for VC6. VC6 needs void return types converted into DefaultVoid.
// GCC 3.2 and later won't compile this unless it's preceded by 'typename',
// but VC6 doesn't allow 'typename' in this context.
// So, I have to use a macro.
#ifdef FASTDLGT_VC6
#define FASTDLGT_RETTYPE detail::VoidToDefaultVoid<RetType>::type
#else
#define FASTDLGT_RETTYPE RetType
#endif
//N=0
template <class X, class Y, class RetType>
FastDelegate0<FASTDLGT_RETTYPE> MakeDelegate( Y* x, RetType ( X::*func )( ) ) {
return FastDelegate0<FASTDLGT_RETTYPE>( x, func );
}
template <class X, class Y, class RetType>
FastDelegate0<FASTDLGT_RETTYPE> MakeDelegate( Y* x, RetType ( X::*func )( ) const ) {
return FastDelegate0<FASTDLGT_RETTYPE>( x, func );
}
//N=1
template <class X, class Y, class Param1, class RetType>
FastDelegate1<Param1, FASTDLGT_RETTYPE> MakeDelegate( Y* x, RetType ( X::*func )( Param1 p1 ) ) {
return FastDelegate1<Param1, FASTDLGT_RETTYPE>( x, func );
}
template <class X, class Y, class Param1, class RetType>
FastDelegate1<Param1, FASTDLGT_RETTYPE> MakeDelegate( Y* x, RetType ( X::*func )( Param1 p1 ) const ) {
return FastDelegate1<Param1, FASTDLGT_RETTYPE>( x, func );
}
//N=2
template <class X, class Y, class Param1, class Param2, class RetType>
FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE> MakeDelegate( Y* x, RetType ( X::*func )( Param1 p1, Param2 p2 ) ) {
return FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE>( x, func );
}
template <class X, class Y, class Param1, class Param2, class RetType>
FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE> MakeDelegate( Y* x, RetType ( X::*func )( Param1 p1, Param2 p2 ) const ) {
return FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE>( x, func );
}
//N=3
template <class X, class Y, class Param1, class Param2, class Param3, class RetType>
FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE> MakeDelegate( Y* x, RetType ( X::*func )( Param1 p1, Param2 p2, Param3 p3 ) ) {
return FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE>( x, func );
}
template <class X, class Y, class Param1, class Param2, class Param3, class RetType>
FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE> MakeDelegate( Y* x, RetType ( X::*func )( Param1 p1, Param2 p2, Param3 p3 ) const ) {
return FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE>( x, func );
}
//N=4
template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class RetType>
FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE> MakeDelegate( Y* x, RetType ( X::*func )( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) ) {
return FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE>( x, func );
}
template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class RetType>
FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE> MakeDelegate( Y* x, RetType ( X::*func )( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const ) {
return FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE>( x, func );
}
//N=5
template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class RetType>
FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE> MakeDelegate( Y* x, RetType ( X::*func )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) ) {
return FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE>( x, func );
}
template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class RetType>
FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE> MakeDelegate( Y* x, RetType ( X::*func )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const ) {
return FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE>( x, func );
}
//N=6
template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType>
FastDelegate6<Param1, Param2, Param3, Param4, Param5, Param6, FASTDLGT_RETTYPE> MakeDelegate( Y* x, RetType ( X::*func )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) ) {
return FastDelegate6<Param1, Param2, Param3, Param4, Param5, Param6, FASTDLGT_RETTYPE>( x, func );
}
template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType>
FastDelegate6<Param1, Param2, Param3, Param4, Param5, Param6, FASTDLGT_RETTYPE> MakeDelegate( Y* x, RetType ( X::*func )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const ) {
return FastDelegate6<Param1, Param2, Param3, Param4, Param5, Param6, FASTDLGT_RETTYPE>( x, func );
}
//N=7
template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType>
FastDelegate7<Param1, Param2, Param3, Param4, Param5, Param6, Param7, FASTDLGT_RETTYPE> MakeDelegate( Y* x, RetType ( X::*func )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) ) {
return FastDelegate7<Param1, Param2, Param3, Param4, Param5, Param6, Param7, FASTDLGT_RETTYPE>( x, func );
}
template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType>
FastDelegate7<Param1, Param2, Param3, Param4, Param5, Param6, Param7, FASTDLGT_RETTYPE> MakeDelegate( Y* x, RetType ( X::*func )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const ) {
return FastDelegate7<Param1, Param2, Param3, Param4, Param5, Param6, Param7, FASTDLGT_RETTYPE>( x, func );
}
//N=8
template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType>
FastDelegate8<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, FASTDLGT_RETTYPE> MakeDelegate( Y* x, RetType ( X::*func )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) ) {
return FastDelegate8<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, FASTDLGT_RETTYPE>( x, func );
}
template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType>
FastDelegate8<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, FASTDLGT_RETTYPE> MakeDelegate( Y* x, RetType ( X::*func )( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const ) {
return FastDelegate8<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, FASTDLGT_RETTYPE>( x, func );
}
// clean up after ourselves...
#undef FASTDLGT_RETTYPE
} // namespace fastdelegate
#endif // !defined( FASTDELEGATE_H )
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright © 2000-2004 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
PagingLandScapeCamera.h - description
-------------------
begin : Fri Sep 27 2004
copyright : ( C ) 2006 by Tuan Kuranes
email : tuan.kuranes@free.fr
***************************************************************************/
#ifndef PagingLandScapeCamera_H
#define PagingLandScapeCamera_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeOctreeCamera.h"
namespace Ogre
{
/** Specialized viewpoint from which an part of LandScape can be rendered.
@remarks
This class contains several specializations of the Ogre::Camera class. It
implements the getRenderOperation method in order to return displayable geometry
for debugging purposes. It also implements a visibility function that is more granular
than the default.
*/
49 class PagingLandScapeCamera : public PagingLandScapeOctreeCamera
{
51 friend class PagingLandScapePageManager;
public:
/* Standard Constructor */
56 PagingLandScapeCamera( const String& name, SceneManager* sm );
/* Standard destructor */
58 ~PagingLandScapeCamera( void );
/** Returns the visibility of the box
*/
62 bool isVisible( const AxisAlignedBox &bounds ) const;
64 void updatePaging( const unsigned int x, const unsigned int z );
66 void resetPaging( void );
unsigned int mCurrentCameraPageX;
unsigned int mCurrentCameraPageZ;
unsigned int mCurrentCameraTileX;
unsigned int mCurrentCameraTileZ;
private:
unsigned int mIniX;
unsigned int mFinX;
unsigned int mIniZ;
unsigned int mFinZ;
unsigned int mPreIniX;
unsigned int mPreFinX;
unsigned int mPreIniZ;
unsigned int mPreFinZ;
87 Vector3 mLastCameraPos;
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeData2D.h - description
-------------------
begin : Wen Mar 5 2003
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeDATA2D_H
#define PAGINGLandScapeDATA2D_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeOptions.h"
namespace Ogre
{
/**
* Encapsulating 2D Data reading.
*/
31 class PagingLandScapeData2D
{
public:
34 PagingLandScapeData2D( PagingLandScapeData2DManager *pageMgr );
36 virtual ~PagingLandScapeData2D( void );
38 virtual PagingLandScapeData2D* newPage( ) = 0;
40 virtual String getName( ) const= 0;
41 virtual bool load( const unsigned int mX, const unsigned int mZ );
43 virtual void load( void );
45 virtual void init( void );
46 virtual void uninit( void );
48 virtual void unload( void );
#ifndef _MAPSPLITTER
/**
* deform Height Data of the terrain.
* \param &deformationPoint
* Where modification is, in world coordinates
* \param &modificationHeight
* What modification do to terrain
* \param info
* Give some info on tile to
* help coordinate system change
*/
61 const bool deformHeight( const Vector3& deformationPoint, Real &modificationHeight );
/**
*
* deform Height Data of the terrain.
* \param &x
* x Position on 2d height grid
* \param &z
* z Position on 2d height grid
* \param &modificationHeight
* What modification do to terrain
*/
73 const bool deformHeight( const unsigned int x, const unsigned int z, Real &modificationHeight );
76 bool setHeight( const unsigned int x, const unsigned int z, const Real h );
77 bool setHeight( const unsigned int x, const unsigned int z, const unsigned int Pos, const Real h );
/**
*
* get smallest rectangle containing all deformation
* done before an update. ( where rectangle is reseted. )
*
* \return Box struct describing rectangle
*
*/
86 Image::Box getDeformationRectangle( void );
/**
*
* Adjust smallest rectangle to make it contain the point
* \param &x
* x Position on 2d height grid
* \param &z
* z Position on 2d height grid
*/
96 void adjustDeformationRectangle( const unsigned int x, const unsigned int z );
/**
*
* Reset Deformation rectangle
*/
102 void resetDeformationRectangle( void );
#endif // _MAPSPLITTER
105 virtual const Vector3 getNormal( const Real mX, const Real mZ );
106 virtual const ColourValue getBase( const Real mX, const Real mZ ) const
{
return ColourValue::White;
};
111 virtual const ColourValue getCoverage( const Real mX, const Real mZ ) const
{
return ColourValue::White;
};
116 virtual const Real getShadow( const Real mX, const Real mZ, const bool& positive ) const
{
return 0.0f;
};
//-----------------------------------------------------------------------
121 const Real getShiftX( ) const
{
return mShiftX;
}
//-----------------------------------------------------------------------
126 const Real getShiftZ( ) const
{
return mShiftZ;
}
//-----------------------------------------------------------------------
131 inline const Real getHeightAbsolute( const Real x, const Real z ) const
{
const Vector3 &invScale = mParent->getOptions( )->invScale;
// adjust x and z to be local to page
int i_x = static_cast<int> ( x * invScale.x - mShiftX );
int i_z = static_cast<int> ( z * invScale.z - mShiftZ );
// due to Real imprecision on Reals, we have to use boundaries here
// otherwise we'll hit asserts.
int size = static_cast<int> ( mSize-1 );
if ( i_x > size )
i_x = size;
else if ( i_x < 0 )
i_x = 0;
if ( i_z > size )
i_z = size;
else if ( i_z < 0 )
i_z = 0;
const unsigned int u_x = static_cast<unsigned int> ( i_x );
const unsigned int u_z = static_cast<unsigned int> ( i_z );
const size_t arraypos = u_z * mSize + u_x;
assert ( mHeightData && arraypos < mMaxArrayPos );
return mHeightData[arraypos];
}
161 inline const Real getHeight( const Real x, const Real z ) const
{
assert ( z < mSize && x < mSize );
assert ( mHeightData );
const unsigned int Pos = static_cast< unsigned int > ( z * mSize + x );
assert ( mMaxArrayPos > Pos );
return mHeightData[ Pos ];
};
170 inline const Real getHeight( const unsigned int x, const unsigned int z ) const
{
assert ( mHeightData );
assert ( z < mSize && x < mSize );
const unsigned int Pos = static_cast <unsigned int> ( z * mSize + x );
assert ( mMaxArrayPos > Pos );
return mHeightData[ Pos ];
};
179 inline const Real getHeight( const int x, const int z ) const
{
assert ( mHeightData );
assert ( static_cast< unsigned int >( z ) < mSize && static_cast< unsigned int >( x ) < mSize );
const unsigned int Pos = static_cast< unsigned int >( z * mSize + x );
assert ( mMaxArrayPos > Pos );
return mHeightData[ Pos ];
};
188 inline const Real getHeight( const unsigned int pos ) const
{
assert ( mHeightData );
assert ( mMaxArrayPos > pos );
return mHeightData[ pos ];
};
194 inline const Real getMaxHeight( void ) const
{
return mMaxheight;
};
// useful to know max height before data is loaded.
199 virtual const Real getMaxAbsoluteHeight( void ) const = 0;
201 Real* getHeightData( void )
{
return mHeightData;
};
206 bool isLoaded( void ) const {return mIsLoaded;};
208 void computePowerof2PlusOneSize( void );
210 virtual size_t getXDimension( void ) const
{
return mXDimension;
};
215 virtual size_t getZDimension( void ) const
{
return mZDimension;
};
220 virtual size_t getSize( void ) const
{
return mSize;
};
225 void getCoordinates( unsigned int& X, unsigned int& Z ) const
{
X = mPageX;
Z = mPageZ;
};
230 inline bool isCoord( const unsigned int x, const unsigned int z ) const {return ( mPageX == x && mPageZ == z );};
protected:
234 virtual void _save( void ) = 0;
235 virtual bool _load( const unsigned int x, const unsigned int z ) = 0;
236 virtual void _load( void ) = 0;
237 virtual void _unload( void ) = 0;
238 bool _checkSize( const size_t s );
// computed Height Data ( scaled )
241 Real *mHeightData;
// maximum position in Array
unsigned int mMaxArrayPos;
// data side maximum size
245 size_t mSize;
// data source width
247 size_t mXDimension;;
// data source height
249 size_t mZDimension;
// image data maximum size
unsigned int mMax;
// maximum page/data2d height. ( scaled )
253 Real mMaxheight;
// if data loaded or not
255 bool mIsLoaded;
// if data modified or not
258 bool mIsModified;
// if data modified but not yet
// readied by other objects ( texture or renderable )
// to get modification to rect only once per frame.
262 bool mIsRectModified;
// page number
unsigned int mPageX;
// page number
unsigned int mPageZ;
// coordinate shift based on page number
270 Real mShiftX;
// coordinate shift based on page number
272 Real mShiftZ;
273 PagingLandScapeData2DManager *mParent;
private :
276 Image::Box mRect;
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeData2DManager.h - description
-------------------
begin : Mon Jun 16 2003
copyright : ( C ) 2003-2006 by Jose A. Milan and Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeDATA2DMANAGER_H
#define PAGINGLandScapeDATA2DMANAGER_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
26 class PagingLandScapeData2DManager
{
public:
29 PagingLandScapeData2DManager( PagingLandScapeSceneManager * scnMgr,
30 PagingLandScapeOptions * opt );
32 ~PagingLandScapeData2DManager( void );
34 void load( void );
35 void clear( void );
36 void WorldDimensionChange( void );
37 void reset( void );
39 PagingLandScapeData2D* allocateData2D( ) const;
41 bool load( const unsigned int dataX, const unsigned int dataZ );
43 bool reload( const unsigned int dataX, const unsigned int dataZ );
45 void unload( const unsigned int dataX, const unsigned int dataZ );
47 bool isLoaded( const unsigned int dataX, const unsigned int dataZ );
49 const Real getHeight( const unsigned int dataX, const unsigned int dataZ, const Real x, const Real z );
51 const Real getHeight( const unsigned int dataX, const unsigned int dataZ, const unsigned int x, const unsigned int z );
53 const Real getHeightAtPage( const unsigned int dataX, const unsigned int dataZ, const Real x, const Real z );
55 const Real getHeightAtPage( const unsigned int dataX, const unsigned int dataZ, const int x, const int z );
57 bool setHeight( const Vector3& deformationPoint, const Real modificationHeight, const PagingLandScapeTileInfo* info );
58 bool deformHeight( const Vector3& deformationPoint, const Real modificationHeight, const PagingLandScapeTileInfo* info );
// bool addNewHeight( const Sphere newSphere );
//
// bool removeNewHeight( const Sphere oldSphere );
//This function will return the max possible value of height base on the current 2D Data implementation
65 const Real getMaxHeight( const unsigned int x, const unsigned int z );
67 const Real getMaxHeight( void ) const;
/** Get the real world height at a particular position
@remarks
Method is used to get the terrain height at a world position based on x and z.
This method just figures out what page the position is on and then asks the page node
to do the dirty work of getting the height.
@par
the Real returned is the real world height based on the scale of the world. If the height could
not be determined then -1 is returned and this would only occur if the page was not preloaded or loaded
@param x x world position
@param z z world position
*/
82 const Real getInterpolatedWorldHeight( const Real x, const Real z, Real *slope = NULL );
83 const Real getWorldHeight( const Real x, const Real z );
85 const ColourValue getCoverageAt( const unsigned int dataX, const unsigned int dataZ, const Real x, const Real z );
87 const ColourValue getBaseAt( const unsigned int dataX, const unsigned int dataZ, const Real x, const Real z );
89 const Real getShadowAt( const unsigned int dataX, const unsigned int dataZ, const unsigned int x, const unsigned int z, const bool& positive );
91 const Vector3 getNormalAt( const unsigned int pageX, const unsigned int pageZ, const unsigned int x, const unsigned int z );
92 const Real getRealWorldSlope( const Real x, const Real z );
93 const Vector3 getNormalAt( const unsigned int pageX, const unsigned int pageZ, const unsigned int x, const unsigned int z, const unsigned int Lod );
95 void setPageManager( PagingLandScapeSceneManager *scnMgr );
98 void registerDataType( PagingLandScapeData2D* source )
{
mData2DTypeMap.push_back( source );
// LogManager::getSingleton( ).logMessage( LML_CRITICAL,
// "PagingLandScape: Registered a new Data2DType for "
// "type " + typeName );
}
// Walk the heightfield from location1 to location2 and find the max slope.
// If maxSlope > 0 and a slope of greater than maxSlopeIn is found, maxSlope is returned.
// This is an expensive operation, so use sparingly.
108 Real getMaxSlope( Vector3 location1, Vector3 location2, Real maxSlopeIn );
110 PagingLandScapeData2D* getData2D( const unsigned int i , const unsigned int j,
111 const bool alwaysReturn = true );
112 PagingLandScapeData2D* getNewData2D( const unsigned int i , const unsigned int j );
113 void releaseData2D ( PagingLandScapeData2D*p );
115 PagingLandScapeOptions* getOptions( ){return mOptions;}
116 PagingLandScapeSceneManager *getSceneManager( ){return mScnMgr;}
protected:
118 PagingLandScapeSceneManager * mScnMgr;
119 PagingLandScapeOptions* mOptions;
unsigned int mData2DType;
123 String mData2DFormat;
unsigned int mWidth;
unsigned int mHeight;
129 Real mMaxHeight;
//PagingLandScapeData2DPages mData2D;
131 PagingLandScapePageManager* mPageManager;
/// Map of Data2d source type
134 PagingLandScapeData2DMap mData2DTypeMap;
/// The currently active page Data2d source
136 PagingLandScapeData2D* mActiveData2DType;
138 PagingLandScapeData2DList mActiveData2Ds;
139 PagingLandScapeData2DList mFreeData2Ds;
140 PagingLandScapeData2DArray mData2DPool;
};
} //namespace
#endif
1 /***************************************************************************
OgrePagingLandScapeData2D_HeightField.h - description
-------------------
begin : Mon Oct 13 2003
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeDATA2D_HEIGHTFIELD_H
#define PAGINGLandScapeDATA2D_HEIGHTFIELD_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
/**
* A specialized class for loading 2D Data from a HeightField file.
*/
31 class PagingLandScapeData2D_HeightField: public PagingLandScapeData2D
{
public:
34 PagingLandScapeData2D_HeightField( PagingLandScapeData2DManager *dataMgr );
35 virtual String getName( ) const{return String( "HeightField" );}
36 virtual ~PagingLandScapeData2D_HeightField( void );
38 virtual const Vector3 getNormal( const Real mX, const Real mZ );
39 virtual const ColourValue getBase( const Real mX, const Real mZ );
40 virtual const ColourValue getCoverage( const Real mX, const Real mZ );
41 virtual const Real getShadow( const Real mX, const Real mZ, const bool& positive );
43 const Real getMaxAbsoluteHeight( void ) const;
44 virtual PagingLandScapeData2D* newPage( );
protected:
47 virtual void _save( void );
48 virtual bool _load( const unsigned int x, const unsigned int z );
49 virtual void _load( void );
50 virtual void _unload( void );
private:
53 Real getScale( ) const;
54 Real getInvScale( ) const;
56 Image* mImage;
57 Image* mBase;
58 Image* mShadow;
59 Image* mCoverage;
/// should be 4 bytes ( mImage is RGBA )
62 size_t mBpp;
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeData2D_HeightFieldBlendNeighbor.h - description
-------------------
begin : Mon Oct 13 2003
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PagingLandScapeData2D_HeightFieldBlendNeighbor_H
#define PagingLandScapeData2D_HeightFieldBlendNeighbor_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
/**
* A specialized class for loading 2D Data from a HeightField file.
*/
29 class PagingLandScapeData2D_HeightFieldBlendNeighbor: public PagingLandScapeData2D
{
public:
32 PagingLandScapeData2D_HeightFieldBlendNeighbor( PagingLandScapeData2DManager *dataMgr );
33 virtual String getName( ) const{return String( "HeightFieldBlendNeighbor" );}
34 virtual ~PagingLandScapeData2D_HeightFieldBlendNeighbor( void );
36 virtual const Real getShadow( const Real mX, const Real mZ, const bool& positive );
38 virtual PagingLandScapeData2D* newPage( );
39 const Real getMaxAbsoluteHeight( void ) const;
protected:
42 virtual void _save( void );
43 virtual bool _load( const unsigned int x, const unsigned int z );
44 virtual void _load( void );
45 virtual void _unload( void );
private:
48 Image * mShadow;
unsigned int mBpp;// should be 2 bytes ( mImage is 16 bits )
};
}
#endif //PagingLandScapeData2D_HeightFieldBlendNeighbor_H
1 /***************************************************************************
OgrePagingLandScapeData2D_HeightFieldN.h - description
-------------------
begin : Mon Oct 13 2003
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PagingLandScapeData2D_HeightFieldN_H
#define PagingLandScapeData2D_HeightFieldN_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
/**
* A specialized class for loading 2D Data from a HeightField file.
*/
31 class PagingLandScapeData2D_HeightFieldN: public PagingLandScapeData2D
{
public:
34 PagingLandScapeData2D_HeightFieldN( PagingLandScapeData2DManager *dataMgr );
35 virtual String getName( ) const{return String( "HeightFieldN" );}
36 virtual ~PagingLandScapeData2D_HeightFieldN( void );
38 virtual const Vector3 getNormal( const Real mX, const Real mZ );
39 virtual const ColourValue getBase( const Real mX, const Real mZ );
40 virtual const ColourValue getCoverage( const Real mX, const Real mZ );
41 virtual const Real getShadow( const Real mX, const Real mZ, const bool& positive );
43 virtual PagingLandScapeData2D* newPage( );
44 const Real getMaxAbsoluteHeight( void ) const;
protected:
47 virtual void _save( void );
48 virtual bool _load( const unsigned int x, const unsigned int z );
49 virtual void _load( void );
50 virtual void _unload( void );
private:
53 Image* mImage;
54 Image* mBase;
55 Image* mShadow;
56 Image* mCoverage;
58 size_t mBpp;// should be 4 bytes ( mImage is RGBA )
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeData2D_HeightFieldNTC.h - description
-------------------
begin : Mon Oct 13 2003
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeDATA2D_HEIGHTFIELDNTC_H
#define PAGINGLandScapeDATA2D_HEIGHTFIELDNTC_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
/**
* A specialized class for loading 2D Data from a compressed HeightField file.
*/
30 class PagingLandScapeData2D_HeightFieldNTC: public PagingLandScapeData2D
{
public:
33 PagingLandScapeData2D_HeightFieldNTC( PagingLandScapeData2DManager *dataMgr );
34 virtual String getName( ) const{return String( "HeightFieldNTC" );}
36 ~PagingLandScapeData2D_HeightFieldNTC( void );
39 virtual const Vector3 getNormalAt( const Real mX, const Real mZ );
40 virtual const ColourValue getBase( const Real mX, const Real mZ );
41 virtual const ColourValue getCoverage( const Real mX, const Real mZ );
43 virtual PagingLandScapeData2D* newPage( );;
44 const Real getMaxAbsoluteHeight( void ) const;
protected:
47 virtual void _save( void );
49 virtual bool _load( const unsigned int x, const unsigned int z );
51 virtual void _load( void );
53 virtual void _unload( void );
private:
56 inline Real _decodeTC( const Real encoded ) const;
57 inline uchar _encodeTC( const Real decoded ) const;
59 Real input_max, input_min;
61 Image* mImage;
62 size_t mBpp;// should be 4 bytes ( mImage is RGBA )
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeData2D_HeightFieldRaw.h - description
-------------------
begin : Mon Oct 13 2003
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PagingLandScapeData2D_HeightFieldRaw_H
#define PagingLandScapeData2D_HeightFieldRaw_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
/**
* A specialized class for loading 2D Data from a HeightField file.
*/
29 class PagingLandScapeData2D_HeightFieldRaw: public PagingLandScapeData2D
{
public:
32 PagingLandScapeData2D_HeightFieldRaw( PagingLandScapeData2DManager *dataMgr );
33 virtual String getName( ) const{return String( "HeightFieldRaw" );}
34 virtual ~PagingLandScapeData2D_HeightFieldRaw( void );
36 virtual const Real getShadow( const Real mX, const Real mZ, const bool& positive );
38 virtual PagingLandScapeData2D* newPage( );
39 const Real getMaxAbsoluteHeight( void ) const;
protected:
42 virtual void _save( void );
43 virtual bool _load( const unsigned int x, const unsigned int z );
44 virtual void _load( void );
45 virtual void _unload( void );
private:
48 Image * mShadow;
unsigned int mBpp;// should be 2 bytes ( mImage is 16 bits )
};
}
#endif //PagingLandScapeData2D_HeightFieldRaw_H
1 /***************************************************************************
OgrePagingLandScapeData2D_HeightFieldRawTC.h - description
-------------------
begin : Mon Oct 13 2003
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeDATA2D_HEIGHTFIELDRawTC_H
#define PAGINGLandScapeDATA2D_HEIGHTFIELDRawTC_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
/**
* A specialized class for loading 2D Data from a compressed HeightField file.
*/
28 class PagingLandScapeData2D_HeightFieldRawTC: public PagingLandScapeData2D
{
public:
31 PagingLandScapeData2D_HeightFieldRawTC( PagingLandScapeData2DManager *dataMgr );
32 virtual String getName( ) const{return String( "HeightFieldRawTC" );}
34 virtual ~PagingLandScapeData2D_HeightFieldRawTC( void );
36 virtual const Vector3 getNormalAt( const Real mX, const Real mZ );
37 virtual const ColourValue getBase( const Real mX, const Real mZ );
38 virtual const ColourValue getCoverage( const Real mX, const Real mZ );
39 virtual PagingLandScapeData2D* newPage( );;
40 const Real getMaxAbsoluteHeight( void ) const;
protected:
44 virtual void _save( void );
45 virtual bool _load( const unsigned int x, const unsigned int z );
46 virtual void _load( void );
47 virtual void _unload( void );
private:
50 inline Real _decodeRawTC( const Real encoded ) const;
51 inline ushort _encodeRawTC( const Real decoded ) const;
53 Real input_max, input_min;
54 Image* mImage;
unsigned int mBpp;// should be 4 bytes ( mImage is RGBA )
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeData2D_HeightFieldTC.h - description
-------------------
begin : Mon Oct 13 2003
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeDATA2D_HEIGHTFIELDTC_H
#define PAGINGLandScapeDATA2D_HEIGHTFIELDTC_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
/**
* A specialized class for loading 2D Data from a compressed HeightField file.
*/
31 class PagingLandScapeData2D_HeightFieldTC: public PagingLandScapeData2D
{
public:
34 PagingLandScapeData2D_HeightFieldTC( PagingLandScapeData2DManager *dataMgr );
36 virtual ~PagingLandScapeData2D_HeightFieldTC( void );
37 virtual String getName( ) const{return String( "HeightFieldTC" );}
39 virtual const ColourValue getBase( const Real mX, const Real mZ );
40 virtual const ColourValue getCoverage( const Real mX, const Real mZ );
42 virtual PagingLandScapeData2D* newPage( );
43 const Real getMaxAbsoluteHeight( void ) const;
protected:
46 virtual void _save( void );
47 virtual bool _load( const unsigned int x, const unsigned int z );
48 virtual void _load( void );
49 virtual void _unload( void );
private:
52 inline Real _decodeTC( const Real encoded ) const;
53 inline uchar _encodeTC( const Real decoded ) const;
55 Real input_max, input_min;
57 Image* mImage;
58 size_t mBpp;// should be 4 bytes ( mImage is RGBA )
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeData2D_Spline.h
Header for a NURBS-based heightfield generator
-------------------
begin : Sat Nov 9 2003
copyright : ( C ) 2003 Chris "Antiarc" Heald
email : antiarc@captionthis.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeDATA2D_SPLINE_H
#define PAGINGLandScapeDATA2D_SPLINE_H
#include "OgrePagingLandScapePrerequisites.h"
#include "DRGNURBSSurface.h"
namespace Ogre
{
/**
* A specialized class for loading 2D Data from a Spline file.
*/
33 class PagingLandScapeData2D_Spline: public PagingLandScapeData2D
{
public:
36 PagingLandScapeData2D_Spline( PagingLandScapeData2DManager *dataMgr );
38 ~PagingLandScapeData2D_Spline( void );
40 virtual PagingLandScapeData2D* newPage( );
41 virtual String getName( ) const{return String( "Spline" );}
42 const Real getMaxAbsoluteHeight( void ) const;
protected:
45 virtual void _save( void );
47 virtual bool _load( const unsigned int x, const unsigned int z );
49 virtual void _load( void );
51 virtual void _unload( void );
private:
int degree;
56 CDRGNURBSSurface* mSurface;
Point4D* mPoints;
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeHorizon.h - description
-------------------
begin : Sat Mar 08 2003
copyright : ( C ) 2003-2006 by Jose A. Milan and Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PagingLandScapeHorizon_H
#define PagingLandScapeHorizon_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
25 class PagingLandScapeHorizon
{
public:
28 PagingLandScapeHorizon( const PagingLandScapeOptions * const options );
29 ~PagingLandScapeHorizon( void );
31 void registerMinMaxHeightPage( const unsigned int pageX, const unsigned int pageZ, const Real minHeight, const Real maxHeight );
33 void registerMinMaxHeightTile( const PagingLandScapeTileInfo* info, const Real minHeight, const Real maxHeight );
35 bool IsPageVisible( const PagingLandScapeCamera* cam, const unsigned int destpageX, const unsigned int destpageZ );
/**
*
* \param cam Give info on current tile and camera height
* \param *destinfo info on the tile we want to test visibility on,
* \return
*/
43 bool IsTileVisible( const PagingLandScapeCamera* cam, const PagingLandScapeTileInfo* destinfo );
46 MaterialPtr getVisibilityMaterial( void );
48 void AddVisibleTile( const unsigned int Tilex, const unsigned int Tilez, const bool visible );
49 void AddVisibleTile( const PagingLandScapeTileInfo* info, const bool visible );
51 void update( void );
52 void prepare( const PagingLandScapeCamera* cam );
private :
const PagingLandScapeOptions * const mOptions;
bool calcVis( const Vector3& src, const Vector3& dest, const Real* const heightMap, const unsigned int mapWidth, const unsigned int mapHeight );
Real* mMaxPageHeights;
Real* mMinPageHeights;
unsigned int mPageWidth;
unsigned int mPageHeight;
unsigned int mNumTilesPage;
Real* mMaxTileHeights;
Real* mMinTileHeights;
unsigned int mTileWidth;
unsigned int mTileHeight;
MaterialPtr mVisibilityMaterial;
uchar* mVisData;
Image mVisImage;
TexturePtr mVisTex;
bool material_enabled;
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeIndexBufferManager.h - description
-------------------
begin : Fri Feb 28 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeINDEXBUFFER_H
#define PAGINGLandScapeINDEXBUFFER_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
26 class PagingLandScapeIndexBufferManager
{
public:
31 PagingLandScapeIndexBufferManager( PagingLandScapeSceneManager * scnMgr );
33 ~PagingLandScapeIndexBufferManager( void );
35 IndexData *getIndex( const int LOD );
37 void load( );
38 void clear( );
/** Utility method to generate stitching indexes on the edge of a tile
@param neighbor The neighbor direction to stitch
@param hiLOD The LOD of this tile
@param loLOD The LOD of the neighbor
@param omitFirstTri Whether the first triangle of the stitch ( always clockwise
relative to the center of this tile ) is to be omitted because an
adjoining edge is also being stitched
@param omitLastTri Whether the last triangle of the stitch ( always clockwise
relative to the center of this tile ) is to be omitted because an
adjoining edge is also being stitched
@param pIdx Pointer to a pointer to the index buffer to push the results
into ( this pointer will be updated )
@returns The number of indexes added
*/
55 unsigned int stitchEdge( const Neighbor neighbor, const int hiLOD, const int loLOD, const bool omitFirstTri, const bool omitLastTri, void** ppIdx, const bool is32bits ) const;
/// Gets the index data for this tile based on current settings
58 IndexData* getIndexData( const int RenderLevel, PagingLandScapeRenderable** Neighbors );
/// Internal method for generating triangle list terrain indexes
61 IndexData* generateTriListIndexes( const bool northStitch, const bool southStitch, const bool eastStitch, const bool westStitch, const int RenderLevel, PagingLandScapeRenderable** Neighbors ) const;
//*******************
//Added by Fiesch adapted from a post by tonyhnz
65 IndexData* getRawIndexes( int renderLevel );
67 PagingLandScapeSceneManager *getSceneManager( ){return mScnMgr;}
protected:
70 PagingLandScapeSceneManager *mScnMgr;
/** Returns the index into the height array for the given coordinates. */
73 inline ushort _index16( int x, int z ) const
{
return ( x + z * mTileSize );
};
/** Returns the index into the height array for the given coordinates. */
78 inline unsigned int _index32( int x, int z ) const
{
return ( x + z * mTileSize );
};
unsigned int mTileSize;
85 IndexArray mCache;
/// Shared array of IndexData ( reuse indexes across tiles )
87 LevelArray mLevelIndex;
// Store the indexes for every combination
unsigned int mNumIndexes;
};
}
#endif
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
OgrePagingLandScapeIntersectionSceneQuery.h - description
-------------------
begin : Tues July 20, 2004
copyright : ( C ) 2004 by Jon Anderson
email : janders@users.sf.net
***************************************************************************/
#ifndef PagingLandScapeIntersectionSCENEQUERY_H
#define PagingLandScapeIntersectionSCENEQUERY_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeOctreeIntersectionSceneQuery.h"
#include "OgreSceneManager.h"
namespace Ogre
{
/** PagingLandScapeOctree implementation of IntersectionSceneQuery. */
class _OgrePagingLandScapeExport PagingLandScapeIntersectionSceneQuery :
public PagingLandScapeOctreeIntersectionSceneQuery
{
public:
48 PagingLandScapeIntersectionSceneQuery( SceneManager* creator );
virtual ~PagingLandScapeIntersectionSceneQuery( void );
/** See IntersectionSceneQuery. */
void execute( IntersectionSceneQueryListener* listener );
};
}
#endif
/*-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright � 2000-2004 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------*/
#ifndef __PagingLandScapePageSourceListener_H__
#define __PagingLandScapePageSourceListener_H__
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
/** Abstract class which classes can override to receive notifications
when a page is ready to be added to the terrain manager.
*/
class _OgrePagingLandScapeExport PagingLandScapeListener
{
public:
37 PagingLandScapeListener( ){};
virtual ~PagingLandScapeListener( ){};
/** Listener method called when a new page is about to be constructed.
@param pagex, pagez The index of the page being constructed
@param heightData Array of normalised height data ( 0..1 ). The size of
this buffer will conform to the scene manager page size. The listener
may modify the data if it wishes.
*/
virtual void pagePreloaded( const size_t pagex, const size_t pagez, const Real* heightData, const AxisAlignedBox &Bbox ){};
virtual void pageLoaded( const size_t pagex, const size_t pagez, const Real* heightData, const AxisAlignedBox &Bbox ){};
virtual void pageUnloaded( const size_t pagex, const size_t pagez, const Real* heightData, const AxisAlignedBox &Bbox ){};
virtual void pagePostunloaded( const size_t pagex, const size_t pagez ){};
virtual void pageShow( const size_t pagex, const size_t pagez, const Real* heightData, const AxisAlignedBox &Bbox ){};
virtual void pageHide( const size_t pagex, const size_t pagez, const Real* heightData, const AxisAlignedBox &Bbox ) {};
virtual void tileLoaded( const size_t pagex, const size_t pagez, const size_t tilex, const size_t tilez, const AxisAlignedBox &Bbox ){};
virtual void tileUnloaded( const size_t pagex, const size_t pagez, const size_t tilex, const size_t tilez, const AxisAlignedBox &Bbox ){};
virtual void tileDeformed( const size_t pagex, const size_t pagez, const size_t tilex, const size_t tilez, const AxisAlignedBox &Bbox ){};
virtual void tileShow( const size_t pagex, const size_t pagez, const size_t tilex, const size_t tilez, const AxisAlignedBox &Bbox ){};
virtual void tileHide( const size_t pagex, const size_t pagez, const size_t tilex, const size_t tilez, const AxisAlignedBox &Bbox ){};
virtual void terrainReady( void ) {};
};
}
#endif //__PagingLandScapePageSourceListener_H__
/*-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright � 2000-2004 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------*/
#ifndef __PagingLandScapePageSourceListenerManager_H__
#define __PagingLandScapePageSourceListenerManager_H__
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeListener.h"
#include "OgreSingleton.h"
#include "OgrePagingLandScapeCallBackEvent.h"
namespace Ogre
{
/** Simple manager class to hold onto a list of page source listeners
across all sources.
*/
class _OgrePagingLandScapeExport PagingLandScapeListenerManager
{
public:
40 PagingLandScapeListenerManager( PagingLandScapeSceneManager * scnMgr );
41 ~PagingLandScapeListenerManager( void );
/** Register a class which will be called back whenever a new page is
available.
@remarks
Since this method is static, it applies to any page source which
is in active use; there is no need to register one per source.
*/
49 void addListener( PagingLandScapeListener* pl );
/** Unregister a class which will be called back whenever a new page is
available.
*/
54 void removeListener( PagingLandScapeListener* pl );
/// Fire event when Heightmap page Loaded Event
57 void firePagePreloaded( const size_t pagex, const size_t pagez, const Real* heightData, const AxisAlignedBox &Bbox );
/// Fire event when Loaded is when page is textured and loaded in GPU.
60 void firePageLoaded( const size_t pagex, const size_t pagez, const Real* heightData, const AxisAlignedBox &Bbox );
/// Fire event when Loaded is when page is untextured and unloaded in GPU.
63 void firePageUnloaded( const size_t pagex, const size_t pagez, const Real* heightData, const AxisAlignedBox &Bbox );
/// Fire event when Heightmap page is unloaded
66 void firePagePostunloaded( const size_t pagex, const size_t pagez );
/// Fire event when page is visible
69 void firePageShow( const size_t pagex, const size_t pagez, const Real* heightData, const AxisAlignedBox &Bbox );
/// Fire event when page is no more visible
72 void firePageHide( const size_t pagex, const size_t pagez, const Real* heightData, const AxisAlignedBox &Bbox );
/// Fire event when tile is Loaded in GPU
75 void fireTileLoaded( const size_t pagex, const size_t pagez, const size_t tilex, const size_t tilez, const AxisAlignedBox &Bbox );
/// Fire event when tile is unLoaded in GPU
78 void fireTileUnloaded( const size_t pagex, const size_t pagez, const size_t tilex, const size_t tilez, const AxisAlignedBox &Bbox );
/// Fire event when tile is deformed
81 void fireTileDeformed( const size_t pagex, const size_t pagez, const size_t tilex, const size_t tilez, const AxisAlignedBox &Bbox );
/// Fire event when tile is visible
84 void fireTileShow( const size_t pagex, const size_t pagez, const size_t tilex, const size_t tilez, const AxisAlignedBox &Bbox );
/// Fire event when tile is invisible
87 void fireTileHide( const size_t pagex, const size_t pagez, const size_t tilex, const size_t tilez, const AxisAlignedBox &Bbox );
/// Fire event when all tiles and page needed are loaded
90 void fireTerrainReady( void );
93 bool setOption( const String& strKey, const void* pValue );
/** Register a delegate method which will be called back whenever terrain is ready ( no more queued objects. )
*/
97 void addTerrainListener( PagingLandscapeDelegate* pl );
98 void removeTerrainListener( PagingLandscapeDelegate* pl );
/** Register a delegate method which will be called back whenever terrain is ready ( no more queued objects. )
*/
103 void addPreloadPageListener( PagingLandscapeDelegate* pl );
104 void removePreloadPageListener( PagingLandscapeDelegate* pl );
/** Register a delegate method which will be called back whenever terrain is ready ( no more queued objects. )
*/
107 void addShowPageListener( PagingLandscapeDelegate* pl );
108 void removeShowPageListener( PagingLandscapeDelegate* pl );
/** Register a delegate method which will be called back whenever terrain is ready ( no more queued objects. )
*/
111 void addHidePageListener( PagingLandscapeDelegate* pl );
112 void removeHidePageListener( PagingLandscapeDelegate* pl );
/** Register a delegate method which will be called back whenever terrain is ready ( no more queued objects. )
*/
115 void addLoadPageListener( PagingLandscapeDelegate* pl );
116 void removeLoadPageListener( PagingLandscapeDelegate* pl );
/** Register a delegate method which will be called back whenever terrain is ready ( no more queued objects. )
*/
119 void addModifyPageListener( PagingLandscapeDelegate* pl );
120 void removeModifyPageListener( PagingLandscapeDelegate* pl );
/** Register a delegate method which will be called back whenever terrain is ready ( no more queued objects. )
*/
123 void addPostunloadPageListener( PagingLandscapeDelegate* pl );
124 void removePostunloadPageListener( PagingLandscapeDelegate* pl );
/** Register a delegate method which will be called back whenever terrain is ready ( no more queued objects. )
*/
127 void addUnloadPageListener( PagingLandscapeDelegate* pl );
128 void removeUnloadPageListener( PagingLandscapeDelegate* pl );
/** Register a delegate method which will be called back whenever terrain is ready ( no more queued objects. )
*/
133 void addShowTileListener( PagingLandscapeDelegate* pl );
134 void removeShowTileListener( PagingLandscapeDelegate* pl );
/** Register a delegate method which will be called back whenever terrain is ready ( no more queued objects. )
*/
137 void addHideTileListener( PagingLandscapeDelegate* pl );
138 void removeHideTileListener( PagingLandscapeDelegate* pl );
/** Register a delegate method which will be called back whenever terrain is ready ( no more queued objects. )
*/
141 void addLoadTileListener( PagingLandscapeDelegate* pl );
142 void removeLoadTileListener( PagingLandscapeDelegate* pl );
/** Register a delegate method which will be called back whenever terrain is ready ( no more queued objects. )
*/
145 void addModifyTileListener( PagingLandscapeDelegate* pl );
146 void removeModifyTileListener( PagingLandscapeDelegate* pl );
/** Register a delegate method which will be called back whenever terrain is ready ( no more queued objects. )
*/
149 void addUnloadTileListener( PagingLandscapeDelegate* pl );
150 void removeUnloadTileListener( PagingLandscapeDelegate* pl );
protected:
std::list<PagingLandscapeDelegate *> mTerrainReadyListeners;
std::list<PagingLandscapeDelegate *> mShowPageListeners;
std::list<PagingLandscapeDelegate *> mHidePageListeners;
std::list<PagingLandscapeDelegate *> mPreloadPageListeners;
std::list<PagingLandscapeDelegate *> mLoadPageListeners;
std::list<PagingLandscapeDelegate *> mUnloadPageListeners;
std::list<PagingLandscapeDelegate *> mPostunloadPageListeners;
std::list<PagingLandscapeDelegate *> mModifyPageListeners;
std::list<PagingLandscapeDelegate *> mShowTileListeners;
std::list<PagingLandscapeDelegate *> mHideTileListeners;
std::list<PagingLandscapeDelegate *> mLoadTileListeners;
std::list<PagingLandscapeDelegate *> mUnloadTileListeners;
std::list<PagingLandscapeDelegate *> mModifyTileListeners;
};
}
#endif //__PagingLandScapePageSourceListener_H__
/*-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright � 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------*/
#ifndef __PagingLandScapeMeshDecal_H__
#define __PagingLandScapeMeshDecal_H__
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
/** Factory object for creating PagingLandScapeMeshDecal instances */
31 class PagingLandScapeMeshDecalFactory : public MovableObjectFactory
{
protected:
34 MovableObject* createInstanceImpl( const String& name, const NameValuePairList* params );
public:
36 PagingLandScapeMeshDecalFactory( ) {}
37 ~PagingLandScapeMeshDecalFactory( ) {}
39 static String FACTORY_TYPE_NAME;
41 const String& getType( void ) const;
42 void destroyInstance( MovableObject* obj );
};
45 class PagingLandScapeMeshDecal : public Renderable, public MovableObject, public SceneQueryListener
{
private:
48 SceneManager* sceneMgr_;
49 Vector3 position_;
50 Quaternion orientation_;
51 Vector2 size_;
52 MaterialPtr material_;
54 AxisAlignedBox AABB_;
55 Real radius_;
57 LightList lightList_;
59 RenderOperation renderOp_;
60 RaySceneQuery* rayQuery_;
61 AxisAlignedBoxSceneQuery* AABBquery_;
63 size_t declSize_;
struct Vertex
{
Vertex( Real x, Real y, Real z, bool included )
: vertex_( x, y, z )
, included_( included ) {}
Vector3 vertex_;
bool included_;
};
typedef std::vector<Vertex> VertexContainer;
typedef std::vector<VertexContainer> SubSectionContainer;
76 SubSectionContainer subSections_;
struct SubExtent
{
int width_;
int height_;
int renderLevel_;
};
typedef std::vector<SubExtent> SubExtentContainer;
86 SubExtentContainer subExtents_;
unsigned int currentSubX_;
unsigned int currentSubZ_;
int width_;
int height_;
/**
We'll use this flag to prevent rebuilding of the geometry every frame, instead only rebuilding when the LOD has changed.
*/
97 bool mDirty;
/**
A copy of the subextents from the last geometry generation, to allow for dirty checks.
*/
102 SubExtentContainer mOldSubExtents;
public:
105 PagingLandScapeMeshDecal( const String& name,
106 const String& materialName,
107 const Vector2& size,
108 const String& sceneMgrInstanceName );
109 virtual ~PagingLandScapeMeshDecal( );
// Main public interface
112 void SetSize( const Vector2& size );
114 virtual void _notifyAttached( Node* parent, bool isTagPoint = false );
private:
116 void CreateGeometry( );
117 size_t GetNumVertices( ) const;
118 size_t GetNumIndices( ) const;
119 int GetRenderLevel( int x, int z ) const
{
assert( x >= 0 && x < width_ );
assert( z >= 0 && z < height_ );
return subExtents_[z * width_ + x].renderLevel_;
}
template<class T> int CreateIndices( HardwareIndexBufferSharedPtr ibuf );
template<class T> int MeshSubSection( int x, int z, T*& indices, int& indexOffset );
template<class T> int StitchEdge( T*& indices,
const SubExtent& extents,
const int hiLOD,
const int loLOD,
const bool horizontal,
const bool forward,
const bool omitFirstTri,
const bool omitLastTri,
const int indexOffset );
// From MovableObject
const String& getMovableType( ) const
{
return PagingLandScapeMeshDecalFactory::FACTORY_TYPE_NAME;
}
const AxisAlignedBox& getBoundingBox( ) const
{
return AABB_;
}
145 Real getBoundingRadius( ) const
{
return radius_;
}
149 void _updateRenderQueue( RenderQueue* queue );
// From Renderable
152 const MaterialPtr& getMaterial( ) const
{
return material_;
}
virtual void getRenderOperation( RenderOperation& op );
virtual void getWorldTransforms( Matrix4* xform ) const;
const Quaternion& getWorldOrientation( ) const;
const Vector3& getWorldPosition( ) const;
Real getSquaredViewDepth( const Camera* cam ) const;
const LightList& getLights( ) const
{
return lightList_;
}
// From SceneQueryListener
bool queryResult( MovableObject* object )
{
return false;
}
bool queryResult( SceneQuery::WorldFragment* fragment );
};
}
#endif
1 #ifndef __PagingLandScapeOcclusion_H
#define __PagingLandScapeOcclusion_H
#include "OgrePagingLandScapePrerequisites.h"
#include <stack>
#include <list>
#include "OgrePagingLandScapeOcclusionQuerySet.h"
#include "OgrePagingLandScapeOcclusionElement.h"
#include "OgrePagingLandScapeOctree.h"
#include "OgrePagingLandScapeOctreeNode.h"
namespace Ogre
{
19 class Occlusion
{
public:
23 Occlusion( unsigned int visibilityThsd = 0 );
24 ~Occlusion( )
{
mQueryPool.deletePool ( );
}
//this is the algorithm from the paper
29 void CHCtraversal( PagingLandScapeOctree *octree, VisibleObjectsBoundsInfo * const visibleBounds );
30 void CHCtraversalConservative ( PagingLandScapeOctree *octree, VisibleObjectsBoundsInfo * const visibleBounds );
32 bool insideViewFrustum ( OcclusionElement& node );
33 void pullUpVisibility( OcclusionElement& n );
34 bool isQueryResultIsVisible( OcclusionElement& node );
35 bool issueDrawQuery( PagingLandScapeOctreeNode& n );
36 void issueBboxQuery( OcclusionElement& n );
37 void queueDraw( PagingLandScapeOctreeNode& n );
39 const unsigned int getNodeCount( ) const { return nodeCount; }
40 unsigned int getFrame( ) const {return mFrameId;};
41 PagingLandScapeOctreeCamera *getCamera( ) const {return mCurrentCam;};
#ifdef _VISIBILITYDEBUG
unsigned int object_cnt;
unsigned int triangle_cnt;
unsigned int traversed_nodes_cnt;
unsigned int frustum_culled_nodes_cnt;
unsigned int query_cnt;
#endif //_VISIBILITYDEBUG
52 bool nextFrame ( PagingLandScapeOctreeCamera *cam,
53 MovableObjectList *camInProgressVisibles,
54 bool onlyshadowcaster,
55 RenderQueue *q );
57 void init ( PagingLandScapeOctreeSceneManager *scnMngr )
{
mScnMngr = scnMngr;
};
62 void initQueryPool( )
{
if ( mIsQueryPoolNotInitiated )
{
mQueryPool.setRenderSystem ( );
mQueryPool.setAutoextend ( true );
mQueryPool.setPoolSize ( 300 );
mIsQueryPoolNotInitiated = false;
}
};
#ifdef _VISIBILITYDEBUG
74 void TreeOverlayDebugView( PagingLandScapeOctree *octree,
75 PagingLandScapeOctreeSceneManager *mScnMgr );
#endif //_VISIBILITYDEBUG
78 PagingLandScapeOctreeSceneManager *mScnMngr;
80 PagingLandScapeOctreeCamera *mCurrentCam;
81 RenderQueue *mCurrentRenderQueue;
82 bool mOnlyShadowCaster;
unsigned int mFrameId;
85 void setIfNotSolidScene( const bool isNotSolid ) {mIsNotSolidScene = isNotSolid;};
86 bool isNotSolidScene ( ) const {return mIsNotSolidScene;};
87 void setNumberOfConservativeFrames ( const unsigned int frames ){mFrameConservativeVisibility = frames;}
88 unsigned int getNumberOfConservativeFrames ( ) const {return mFrameConservativeVisibility;}
private:
91 bool mIsNotSolidScene;
///Keep a set of pre-allocated HW queries
93 QuerySet mQueryPool;
/// As it's initiated on first HW query use
95 bool mIsQueryPoolNotInitiated;
///culling mode from frustum culling to coherent hierarchical Occlusion
unsigned int mode;
/// number of frame we consider a node visible after a query set it visible once.
unsigned int mFrameConservativeVisibility;
/// Number of pixel upon which a node is considered as visible
unsigned int mVisibilityTreshold;
/// store number of nodes in Tree
unsigned int nodeCount;
/// store queried elements that didn't return results
108 QueriedOcclusionElement m_queryQueue;
};
}
#endif //__PagingLandScapeOcclusion_H
1 #ifndef __PagingLandScapeOcclusionCHCTraversal_H
#define __PagingLandScapeOcclusionCHCTraversal_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeOctreeCamera.h"
#include "OgrePagingLandScapeOcclusionTraversal.h"
namespace Ogre
{
//-----------------------------------------------------------------------
// TREE TRAVERSAL classes
// a OctreeNode with Geometry objects in the leaves
// and a TreeNodeData struct at every node
15 class CHCTraversal : public TraversalConst
{
public:
18 virtual void onTree( PagingLandScapeOctree& n, VisibleObjectsBoundsInfo * const visibleBounds ) const;
19 virtual void onLeaf( PagingLandScapeOctreeNode& n, VisibleObjectsBoundsInfo * const visibleBounds ) const ;
21 CHCTraversal( FrontToBackNodeSorterPriorityQueue& vStack, Occlusion& o );
private:
24 FrontToBackNodeSorterPriorityQueue& stack;
25 Occlusion& occlusion;
const unsigned int frameId;
27 const bool mIsNotSolidScene;
};
}
#endif //PagingLandScapeOcclusionCHCTraversal
1 #ifndef __PagingLandScapeOcclusionCameraTraversal_H
#define __PagingLandScapeOcclusionCameraTraversal_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeOctreeCamera.h"
namespace Ogre
{
//-----------------------------------------------------------------------
//
11 class RegisterCameraTraversal : public TraversalConst
{
private:
14 PagingLandScapeOctreeCamera *cam;
public:
17 RegisterCameraTraversal( PagingLandScapeOctreeCamera *c ) : cam ( c ) {};
18 virtual void onTree( PagingLandScapeOctree& n, VisibleObjectsBoundsInfo * const visibleBounds ) const ;
19 virtual void onLeaf( PagingLandScapeOctreeNode& n, VisibleObjectsBoundsInfo * const visibleBounds ) const ;
};
//-----------------------------------------------------------------------
//
23 class UnregisterCameraTraversal : public TraversalConst
{
private:
26 PagingLandScapeOctreeCamera *cam;
public:
29 UnregisterCameraTraversal( PagingLandScapeOctreeCamera *c ) : cam ( c ) {};
30 virtual void onTree( PagingLandScapeOctree& n, VisibleObjectsBoundsInfo * const visibleBounds ) const ;
31 virtual void onLeaf( PagingLandScapeOctreeNode& n, VisibleObjectsBoundsInfo * const visibleBounds ) const ;
};
}
#endif //PagingLandScapeOcclusionCameraTraversal
1 #ifndef __PagingLandScapeOcclusionTreeOverlayDebugTraversal_H
#define __PagingLandScapeOcclusionTreeOverlayDebugTraversal_H
#include "OgrePagingLandScapePrerequisites.h"
#ifdef _VISIBILITYDEBUG
#include "OgrePagingLandScapeOctreeCamera.h"
#include "OgrePagingLandScapeOcclusionTraversal.h"
namespace Ogre
{
//------------------------------------------------------
//
18 class TreeOverlayDebug : public TraversalConst
{
public:
21 TreeOverlayDebug( Occlusion& o, PagingLandScapeOctreeSceneManager *scnMgr );
22 virtual void onTree( PagingLandScapeOctree& n, VisibleObjectsBoundsInfo * const visibleBounds ) const ;
23 virtual void onLeaf( PagingLandScapeOctreeNode& n, VisibleObjectsBoundsInfo * const visibleBounds ) const ;
private:
26 Occlusion& occlusion;
27 PagingLandScapeOctreeSceneManager *mScnMrg;
};
}
#endif //_VISIBILITYDEBUG
#endif //__PagingLandScapeOcclusionTreeOverlayDebugTraversal_H
1 #ifndef __PagingLandScapeOcclusionElement_H
#define __PagingLandScapeOcclusionElement_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
struct VisibleObjectsBoundsInfo;
10 class OcclusionElement
{
public :
13 OcclusionElement( );
14 virtual ~OcclusionElement( );
16 VisibilityData *getNodeData( PagingLandScapeOctreeCamera *cam );
17 void addCamNodeData ( PagingLandScapeOctreeCamera *cam );
18 void removeCamNodeData ( PagingLandScapeOctreeCamera *cam );
20 virtual OcclusionElement* getParent ( ) = 0;
21 virtual OcclusionBoundingBox* getOcclusionBoundingBox( ) = 0;
22 virtual bool isLeaf( ) const = 0;
//virtual void _addToRenderQueue( Camera* cam, RenderQueue* const q, const bool onlyShadowCasters ) = 0;
//virtual void _addAlreadyNotifiedToVisibles( Camera* cam, RenderQueue* const q, const bool onlyShadowCasters ) = 0;
//virtual void notifyNodeObjects( Camera* cam ) = 0;
28 virtual void traversal( Traversal&, VisibleObjectsBoundsInfo * const visibleBounds ) = 0;
29 virtual void traversal( const TraversalConst&, VisibleObjectsBoundsInfo * const visibleBounds ) = 0;
30 virtual void traversal( const ConstTraversalConst&, VisibleObjectsBoundsInfo * const visibleBounds ) const = 0;
32 virtual const AxisAlignedBox &getCullBoundingBox( ) const = 0;
33 virtual const Vector3 &getHalfSize( ) const = 0;
#ifdef _VISIBILITYDEBUG
36 DebugRectangle2D *getRectangle2d( SceneManager *scnMgr );
#endif //_VISIBILITYDEBUG
39 void setRegisteredtoCam( const bool flag )
{
mIsRegisteredToCam = flag;
};
45 virtual bool isOccluder ( ) const = 0;
protected :
/// if node has all camera information about occlusion
49 bool mIsRegisteredToCam;
private :
typedef std::map<unsigned int, VisibilityData* > NodeDataPerCamMap;
typedef NodeDataPerCamMap::iterator NodeDataPerCamMapiterator;
56 NodeDataPerCamMap nodeDataPerCam;
#ifdef _VISIBILITYDEBUG
58 DebugRectangle2D *mDebugRectangle2d;
#endif //_VISIBILITYDEBUG
};
}//namespace Ogre
#endif //__PagingLandScapeOcclusionElement_H
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright ( c ) 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
#ifndef __OgrePagingLandScapeOcclusionQuerySet_H__
#define __OgrePagingLandScapeOcclusionQuerySet_H__
#include "OgrePrerequisites.h"
#include "OgreRenderSystem.h"
#include "OgreRoot.h"
#include "OgrePagingLandScapePoolSet.h"
namespace Ogre
{
/** A collection of pre-allocated queries
*/
40 class QuerySet : public PoolSet<HardwareOcclusionQuery>
{
protected:
44 HardwareOcclusionQuery* allocate ( )
{
return mRenderSystem->createHardwareOcclusionQuery( );
}
48 void deallocate ( HardwareOcclusionQuery *p )
{
mRenderSystem->destroyHardwareOcclusionQuery ( p );
}
public:
55 void setRenderSystem ( )
{
mRenderSystem = Root::getSingleton ( ).getRenderSystem ( );
}
private:
61 RenderSystem *mRenderSystem;
};
}
#endif//__OgrePagingLandScapeOcclusionQuerySet_H__
1 #ifndef __PagingLandScapeOcclusionSWTraversal_H
#define __PagingLandScapeOcclusionSWTraversal_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeOctreeCamera.h"
#include "OgrePagingLandScapeOcclusionTraversal.h"
namespace Ogre
{
//-----------------------------------------------------------------------
// TREE TRAVERSAL classes
// a OctreeNode with Geometry objects in the leaves
// and a TreeNodeData struct at every node
//-----------------------------------------------------------------------
// Basic Occlusion query use : stop and wait query result Culling
17 class SWTraversal : public Traversal
{
private:
21 Occlusion& occlusion;
PagingLandScapeOctreeCamera::Visibility mCurrentVisibility;
23 Vector3 camPos;
public:
27 SWTraversal ( Occlusion& o );
29 virtual void onTree( PagingLandScapeOctree&, VisibleObjectsBoundsInfo * const visibleBounds );
30 virtual void onLeaf( PagingLandScapeOctreeNode&, VisibleObjectsBoundsInfo * const visibleBounds );
31 bool isVisible( OcclusionElement & n );
32 void traverseChildren( PagingLandScapeOctree & n, VisibleObjectsBoundsInfo * const visibleBounds );
};
}
#endif //PagingLandScapeOcclusionSWTraversal
1 #ifndef _PagingLandScapeOcclusionSorterH
#define _PagingLandScapeOcclusionSorterH
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeOcclusionElement.h"
namespace Ogre
{
//comparator for priority queue
11 class FrontToBackNodeSorterOperator
{
public:
15 FrontToBackNodeSorterOperator( const Vector3& position ) : pos( position ) {};
//-----------------------------------------------------------------------
17 inline bool operator( )( OcclusionElement*& a, OcclusionElement*& b ) const
{
// could check if both distance == 0 then order visible first// ?
return vectorToBoxDistance ( *a, pos ) > vectorToBoxDistance ( *b, pos );
}
//-----------------------------------------------------------------------
23 inline bool operator( )( const OcclusionElement*& a, const OcclusionElement*& b ) const
{
// could check if both distance == 0 then order visible first ?
return vectorToBoxDistance ( *a, pos ) > vectorToBoxDistance ( *b, pos );
}
//-----------------------------------------------------------------------
29 Real vectorToBoxDistance( const OcclusionElement &a, const Vector3& point ) const
{
const Vector3 &boxMin = a.getCullBoundingBox ( ).getMinimum ( );
const Vector3 halfSize ( ( a.getCullBoundingBox ( ).getMaximum ( ) - boxMin ) * 0.5 );
// work in the box's coordinate system
const Vector3 kDiff ( point - ( halfSize + boxMin ) );
// compute squared distance and closest point on box
Real fSqrDistance ( 0.0 );
for ( unsigned int i = 0; i < 3; i++ )
{
const Real kClosest = kDiff[i];
const Real khalfSize = halfSize[i];
if ( kClosest < -khalfSize )
{
const Real fDelta = kClosest + khalfSize;
fSqrDistance += fDelta * fDelta;
}
else if ( kClosest > khalfSize )
{
const Real fDelta = kClosest - khalfSize;
fSqrDistance += fDelta * fDelta;
}
}
return fSqrDistance;
}
private:
56 const Vector3 pos;
};
}//namespace Ogre
#endif //_PagingLandScapeOcclusionSorterH
1 #ifndef __PagingLandScapeOcclusionTraversal_H
#define __PagingLandScapeOcclusionTraversal_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeOctreeCamera.h"
#include <OgreSceneManager.h>
namespace Ogre
{
//-----------------------------------------------------------------------
11 class ConstTraversalConst
{
public:
15 virtual ~ConstTraversalConst( ) {}
16 virtual void onTree( const PagingLandScapeOctree& n, VisibleObjectsBoundsInfo * const visibleBounds ) const = 0;
17 virtual void onLeaf( const PagingLandScapeOctreeNode&, VisibleObjectsBoundsInfo * const visibleBounds ) const = 0;
protected:
20 virtual void traverseChildren( const PagingLandScapeOctree& n, VisibleObjectsBoundsInfo * const visibleBounds ) const;
};
//-----------------------------------------------------------------------
23 class TraversalConst
{
public:
27 virtual ~TraversalConst( ) {}
28 virtual void onTree( PagingLandScapeOctree& n, VisibleObjectsBoundsInfo * const visibleBounds ) const = 0;
29 virtual void onLeaf( PagingLandScapeOctreeNode&, VisibleObjectsBoundsInfo * const visibleBounds ) const = 0;
protected:
32 virtual void traverseChildren( PagingLandScapeOctree& n, VisibleObjectsBoundsInfo * const visibleBounds ) const ;
};
//-----------------------------------------------------------------------
35 class Traversal
{
public:
39 virtual ~Traversal( ) {}
40 virtual void onTree( PagingLandScapeOctree& n, VisibleObjectsBoundsInfo * const visibleBounds ) = 0;
41 virtual void onLeaf( PagingLandScapeOctreeNode&, VisibleObjectsBoundsInfo * const visibleBounds ) = 0;
protected:
44 virtual void traverseChildren( PagingLandScapeOctree& n, VisibleObjectsBoundsInfo * const visibleBounds );
};
}
#endif //PagingLandScapeOcclusionTraversal
1 #ifndef __PagingLandScapeOcclusionViewFrustumCullingTraversal_H
#define __PagingLandScapeOcclusionViewFrustumCullingTraversal_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeOctreeCamera.h"
#include "OgrePagingLandScapeOcclusionTraversal.h"
namespace Ogre
{
//-----------------------------------------------------------------------
// Basic View Frustum Culling using hierarchy info
// as if an octree is fully in frustum, all children are for sure visible
14 class ViewFrustumCullingTraversal : public Traversal
{
public:
18 ViewFrustumCullingTraversal ( Occlusion& o );
20 virtual void onTree( PagingLandScapeOctree&, VisibleObjectsBoundsInfo * const visibleBounds );
21 virtual void onLeaf( PagingLandScapeOctreeNode&, VisibleObjectsBoundsInfo * const visibleBounds );
private:
24 Occlusion& occlusion;
PagingLandScapeOctreeCamera::Visibility mCurrentVisibility;
};
//-----------------------------------------------------------------------
// Basic View Frustum Culling
31 class ViewFrustumCullingTraversalDirect : public Traversal
{
public:
36 ViewFrustumCullingTraversalDirect ( Occlusion& o );
38 virtual void onTree( PagingLandScapeOctree&, VisibleObjectsBoundsInfo * const visibleBounds );
39 virtual void onLeaf( PagingLandScapeOctreeNode&, VisibleObjectsBoundsInfo * const visibleBounds );
private:
42 Occlusion& occlusion;
};
}
#endif //__PagingLandScapeOcclusionViewFrustumCullingTraversal_H
1 #ifndef __VisibilityData_H
#define __VisibilityData_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
//contains the additional data needed for the
// Coherent Hierarchical Culling
10 class VisibilityData
{
public:
// ctor
14 VisibilityData( ):
#ifdef _VISIBILITYDEBUG
viewFrustumVisible ( false ),
#endif //_VISIBILITYDEBUG
queryVisible ( true ),
lastQueryFrameId ( 0 ),
frameID ( 0 ),
query ( 0 ),
notified ( false )
{};
//dtor
25 ~VisibilityData( ){assert ( query == 0 );};
#ifdef _VISIBILITYDEBUG
// frustum culled
29 bool viewFrustumVisible;
#endif //_VISIBILITYDEBUG
// Visible on screen, as certified by query result
33 bool queryVisible;
//last query result
unsigned int lastQueryFrameId;
//last render
unsigned int frameID;
// query associated to node
39 HardwareOcclusionQuery *query;
// Has been checked against renderer
// ( if not too far, or outside this render like shadows... )
42 bool notified;
};
}
#endif //__VisibilityData_H
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright ( c ) 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
PagingLandScapeOctree.h - description
-------------------
begin : Mon Sep 30 2002
copyright : ( C ) 2002 by Jon Anderson
email : janders@users.sf.net
Enhancements 2003 - 2004 ( C ) The OGRE Team
***************************************************************************/
#ifndef __PagingLandScapeOctree_H
#define __PagingLandScapeOctree_H
#include "OgreAxisAlignedBox.h"
#include "OgrePagingLandScapeOcclusionElement.h"
#include "OgrePagingLandScapeOcclusionTraversal.h"
#include <list>
namespace Ogre
{
48 class PagingLandScapeOctreeNode;
typedef std::list < PagingLandScapeOctreeNode* > NodeList;
/** PagingLandScapeOctree data structure for managing scene nodes.
@remarks
This is a loose PagingLandScapeOctree implementation, meaning that each
octant child of the PagingLandScapeOctree actually overlaps it's siblings by a factor
of .5. This guarantees that any thing that is half the size of the parent will
fit completely into a child, with no splitting necessary.
*/
61 class PagingLandScapeOctree : public OcclusionElement
{
public:
65 PagingLandScapeOctree( );
66 ~PagingLandScapeOctree( void );
68 void reset( );
70 void setParent( PagingLandScapeOctree * parent );
71 void setSceneManager( PagingLandScapeOctreeSceneManager * scn );
/** Adds an PagingLandScapeOctree scene node to this PagingLandScapeOctree level.
@remarks
This is called by the PagingLandScapeOctreeSceneManager after
it has determined the correct PagingLandScapeOctree to insert the node into.
*/
78 void _addNode( PagingLandScapeOctreeNode* nod );
/** Removes an PagingLandScapeOctree scene node to this PagingLandScapeOctree level.
*/
82 void _removeNode( PagingLandScapeOctreeNode* nod );
/** Returns the number of scene nodes attached to this PagingLandScapeOctree
*/
86 inline size_t numNodes( void ) const
{
return mNumNodes;
};
/** creates the wire frame bounding box for this octant
*/
95 WireBoundingBox* getWireBoundingBox( void );
/** creates the opaque Cull bounding box ( bbox*2 ) for this octant
*/
99 OcclusionBoundingBox* getOcclusionBoundingBox( );
/** 3D array of children of this PagingLandScapeOctree.
@remarks
Children are dynamically created as needed when nodes are inserted in the PagingLandScapeOctree.
If, later, the all the nodes are removed from the child, it is still kept around.
*/
PagingLandScapeOctree* mChildren[ 2 ][ 2 ][ 2 ];
/** Determines if this PagingLandScapeOctree is twice as big as the given box.
@remarks
This method is used by the PagingLandScapeOctreeSceneManager to determine if the given
box will fit into a child of this PagingLandScapeOctree.
*/
114 bool _isTwiceSize( const AxisAlignedBox& box ) const;
/** Determines if this PagingLandScapeOctree is twice as big as the given box.
@remarks
This method is used by the PagingLandScapeOctreeSceneManager to determine if the given
box will fit into a child of this PagingLandScapeOctree.
*/
121 bool _isTwiceCullSize( const AxisAlignedBox& box ) const;
123 bool _isNotCrossingAxes( const AxisAlignedBox& box ) const;
/** Returns the appropriate indexes for the child of this PagingLandScapeOctree into which the box will fit.
@remarks
This is used by the PagingLandScapeOctreeSceneManager to determine which child to traverse next when
finding the appropriate PagingLandScapeOctree to insert the box. Since it is a loose PagingLandScapeOctree, only the
center of the box is checked to determine the octant.
*/
131 PagingLandScapeOctree* _getChildWhereBoxFits( const AxisAlignedBox& bx, PagingLandScapeOctreeSceneManager *scn );
/** Returns the appropriate indexes for the child of this PagingLandScapeOctree into which the box will fit.
@remarks
This is used by the PagingLandScapeOctreeSceneManager to determine which child to traverse next when
finding the appropriate PagingLandScapeOctree to insert the box. Since it is a loose PagingLandScapeOctree, only the
center of the box is checked to determine the octant.
*/
138 PagingLandScapeOctree *_getCullChildWhereBoxFits( const AxisAlignedBox& bx, PagingLandScapeOctreeSceneManager *scn );
/** Creates the AxisAlignedBox used for culling this PagingLandScapeOctree.
@remarks
Since it's a loose PagingLandScapeOctree, the culling bounds can be different than the actual bounds of the PagingLandScapeOctree.
*/
143 void _getCullBounds( AxisAlignedBox* bound ) const;
/** Public list of SceneNodes attached to this particular PagingLandScapeOctree
*/
147 NodeList mNodes;
148 NodeList mMovingNodes;
149 NodeList mStaticNodes;
151 inline OcclusionElement* getParent ( ) {return mParent;};
153 inline bool isLeaf( ) const {return false;};
155 inline void traversal( Traversal &tr, VisibleObjectsBoundsInfo * const visibleBounds )
{
tr.onTree ( *this, visibleBounds );
};
159 inline void traversal( const TraversalConst &tr, VisibleObjectsBoundsInfo * const visibleBounds )
{
tr.onTree( *this, visibleBounds );
};
163 inline void traversal( const ConstTraversalConst &tr, VisibleObjectsBoundsInfo * const visibleBounds ) const
{
tr.onTree ( *this, visibleBounds );
};
// check if need to traverse it.
169 inline bool hasChildren( ) const
{
return ( mNumNodes != 0 );
};
174 void setBoundingBox( const Vector3 &min, const Vector3 &max );
#ifdef _VISIBILITYDEBUG
177 void setDebugCorners( PagingLandScapeOctreeSceneManager *scnMgr );
#endif //_VISIBILITYDEBUG
180 inline const AxisAlignedBox &getCullBoundingBox( ) const {return mCullBox;};
181 inline const AxisAlignedBox &getBoundingBox( ) const {return mBox;};
182 inline const Vector3 &getHalfSize( ) const {return mHalfSize;};
183 inline const Vector3 &getCullHalfSize( ) const {return mCullHalfSize;};
185 inline bool isOccluder ( ) const { return true; }
protected:
/** The bounding box of the PagingLandScapeOctree
@remarks
This is used for octant index determination and rendering, but not culling
*/
193 AxisAlignedBox mBox;
/// Octree double size bounding box
195 AxisAlignedBox mCullBox;
196 WireBoundingBox* mWireBoundingBox;
/** Vector containing the dimensions of this PagingLandScapeOctree
*/
199 Vector3 mHalfSize;
/** Vector containing the dimensions of this PagingLandScapeOctree / 2
*/
202 Vector3 mCullHalfSize;
/** Increments the overall node count of this PagingLandScapeOctree and all it's parents
*/
207 inline void _ref( void )
{
++mNumNodes;
if ( mParent != 0 )
{
mParent->_ref( );
}
};
/** Decrements the overall node count of this PagingLandScapeOctree and all it's parents
*/
218 void _unref( const bool removeChildren );
///number of SceneNodes in this PagingLandScapeOctree and all it's children.
221 size_t mNumNodes;
///parent PagingLandScapeOctree
PagingLandScapeOctree* mParent;
224 PagingLandScapeOctreeSceneManager *mSceneMgr;
225 OcclusionBoundingBox* mOcclusionBoundingBox;
};
}
#endif
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
OgrePagingLandScapeOctreeAxisAlignedBoxSceneQuery.h - description
-------------------
begin : Tues July 20, 2004
copyright : ( C ) 2004 by Jon Anderson
email : janders@users.sf.net
***************************************************************************/
#ifndef PagingLandScapeOctreeAxisAlignedBoxSCENEQUERY_H
#define PagingLandScapeOctreeAxisAlignedBoxSCENEQUERY_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgreSceneManager.h"
namespace Ogre
{
/** PagingLandScapeOctree implementation of AxisAlignedBoxSceneQuery. */
class _OgrePagingLandScapeExport PagingLandScapeOctreeAxisAlignedBoxSceneQuery : public DefaultAxisAlignedBoxSceneQuery
{
public:
46 PagingLandScapeOctreeAxisAlignedBoxSceneQuery( SceneManager* creator );
virtual ~PagingLandScapeOctreeAxisAlignedBoxSceneQuery( void );
/** See RayScenQuery. */
/** Finds any entities that intersect the AAB for the query. */
void execute( SceneQueryListener* listener );
};
}
#endif
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright ( c ) 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
PagingLandScapeOctreecamera.h - description
-------------------
begin : Fri Sep 27 2002
copyright : ( C ) 2002 by Jon Anderson
email : janders@users.sf.net
Enhancements 2003 - 2004 ( C ) The OGRE Team
***************************************************************************/
#ifndef PagingLandScapeOctreeCAMERA_H
#define PagingLandScapeOctreeCAMERA_H
#include "OgreCamera.h"
#include "OgreHardwareBufferManager.h"
#include "OgreSimpleRenderable.h"
#include "OgrePagingLandScapePrerequisites.h"
/**
*@author Jon Anderson
*/
namespace Ogre
{
51 class PagingLandScapeOctree;
/** Specialized viewpoint from which an PagingLandScapeOctree can be rendered.
@remarks
This class contains several specializations of the Ogre::Camera class. It
implements the getRenderOperation method in order to return displayable geometry
for debugging purposes. It also implements a visibility function that is more granular
than the default.
*/
62 class PagingLandScapeOctreeCamera : public Camera
{
public:
/** Visibility types */
enum Visibility
{
NONE,
PARTIAL,
FULL
};
/* Standard Constructor */
76 PagingLandScapeOctreeCamera( const String& name, SceneManager* sm );
/* Standard destructor */
78 virtual ~PagingLandScapeOctreeCamera( void );
/** Returns the visibility of the box
*/
82 Visibility getVisibility( const AxisAlignedBox& bound ) const;
84 bool isRegisteredInOcclusionSystem( ) const;
85 void setRegisteredInOcclusionSystem( const bool registered );
87 void updateRegistrationInOcclusionSystem( );
89 void setNextOcclusionMode( );
90 culling_modes getOcclusionMode( ) const {return mOcclusionMode;};
91 bool needRegistrationInOcclusionSystem( ) const;
92 void setOcclusionMode( culling_modes occlusionMode );
94 void setOcclusionModeAsString( const String &cullingModeAsString );
95 String getOcclusionModeAsString( ) const;
97 unsigned int getId( )const {return mUniqueIdentification;}
98 unsigned int getFrameId( )const {return mFrameId;}
99 bool nextFrame( const unsigned int framesSceneId );
101 void _addCHCRenderedFaces( unsigned int numfaces )
{
mVisFacesLastCHCRender = numfaces;
}
private:
107 void changeOcclusionMode( culling_modes nextOcclusionMode );
unsigned int mVisFacesLastCHCRender;
110 bool isOcclusionSystemRegistered;
unsigned int mUniqueIdentification;
culling_modes mOcclusionMode;
/// last rendered frame
unsigned int mFrameId;
unsigned int mFrameSceneId;
static unsigned int s_camId;
};
}
#endif
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
OgrePagingLandScapeOctreeIntersectionSceneQuery.h - description
-------------------
begin : Tues July 20, 2004
copyright : ( C ) 2004 by Jon Anderson
email : janders@users.sf.net
***************************************************************************/
#ifndef PagingLandScapeOctreeIntersectionSCENEQUERY_H
#define PagingLandScapeOctreeIntersectionSCENEQUERY_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgreSceneManager.h"
namespace Ogre
{
/** PagingLandScapeOctree implementation of IntersectionSceneQuery. */
class _OgrePagingLandScapeExport PagingLandScapeOctreeIntersectionSceneQuery :
public DefaultIntersectionSceneQuery
{
public:
47 PagingLandScapeOctreeIntersectionSceneQuery( SceneManager* creator );
virtual ~PagingLandScapeOctreeIntersectionSceneQuery( void );
/** See IntersectionSceneQuery. */
void execute( IntersectionSceneQueryListener* listener );
};
}
#endif
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright ( c ) 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
PagingLandScapeOctreenode.h - description
-------------------
begin : Fri Sep 27 2002
copyright : ( C ) 2002 by Jon Anderson
email : janders@users.sf.net
Enhancements 2003 - 2004 ( C ) The OGRE Team
***************************************************************************/
#ifndef __PagingLandScapeOctreeNODE_H
#define __PagingLandScapeOctreeNODE_H
#include "OgreSceneNode.h"
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeOctreeSceneManager.h"
#include "OgrePagingLandScapeOctree.h"
#include "OgrePagingLandScapeOcclusionElement.h"
namespace Ogre
{
/** Specialized SceneNode that is customized for working within an PagingLandScapeOctree. Each node
* maintains it's own bounding box, rather than merging it with all the children.
*
*/
51 class PagingLandScapeOctreeNode : public SceneNode, public OcclusionElement
{
public:
/** Standard constructor */
55 PagingLandScapeOctreeNode( SceneManager* creator );
/** Standard constructor */
57 PagingLandScapeOctreeNode( SceneManager* creator, const String& name );
/** Standard destructor */
59 ~PagingLandScapeOctreeNode( void );
/** Returns the PagingLandScapeOctree in which this PagingLandScapeOctreeNode resides
*/
63 PagingLandScapeOctree* getOctant( void )
{
return mOctant;
};
/** Sets the PagingLandScapeOctree in which this PagingLandScapeOctreeNode resides
*/
70 void setOctant( PagingLandScapeOctree* o )
{
mOctant = o;
};
/** Determines if the center of this node is within the given box
*/
77 bool _isIn( const AxisAlignedBox& box ) const;
/** Adds all the attached scene nodes to the render queue
*/
81 virtual void _addToRenderQueue( Camera* cam, RenderQueue* const q, const bool onlyShadowCasters, VisibleObjectsBoundsInfo * const visibleBounds );
83 MovableObjectList *getVisibleNotifiedNodeObjects( Camera* cam,
84 const bool onlyShadowCasters );
86 bool notifyNodeObjects( Camera* cam,
87 const bool onlyShadowCasters );
/** Adds all the attached scene nodes to the render queue
* with the particularity that it has already been notified by camera.
*/
91 void _addAlreadyNotifiedToVisibles( );
92 void _addToVisibles( Camera* cam, const bool onlyShadowCasters );
/** Sets up the LegacyRenderOperation for rendering this scene node as geometry.
@remarks
This will render the scene node as a bounding box.
*/
//virtual void getRenderOperation( RenderOperation& op );
/** Returns the local bounding box of this PagingLandScapeOctreeNode.
@remarks
This is used to render the bounding box, rather then the global.
*/
103 AxisAlignedBox& _getLocalAABB( void )
{
return mLocalAABB;
};
/** Adds a ( pre-created ) child scene node to this node. If it is attached to another node,
it must be detached first.
@param child The Node which is to become a child node of this one
*/
111 virtual void addChild( Node* child );
/** Drops the specified child from this node.
@remarks
Does not delete the node, just detaches it from
this parent, potentially to be reattached elsewhere.
There is also an alternate version which drops a named
child from this node.
*/
119 virtual Node* removeChild( unsigned short index );
/** Drops the specified child from this node.
@remarks
Does not delete the node, just detaches it from
this parent, potentially to be reattached elsewhere.
There is also an alternate version which drops a named
child from this node.
*/
127 virtual Node* removeChild( Node* child );
/** Drops the named child from this node.
@remarks
Does not delete the node, just detaches it from
this parent, potentially to be reattached elsewhere.
*/
134 virtual Node* removeChild( const String& name );
/** Removes all child Nodes attached to this node. Does not delete the nodes, just detaches them from
this parent, potentially to be reattached elsewhere.
*/
138 virtual void removeAllChildren( void );
142 virtual OcclusionElement* getParent ( ) {return mOctant;};
145 inline const AxisAlignedBox &getCullBoundingBox( ) const
{
return _getWorldAABB( );
};
151 virtual const Vector3 &getHalfSize( ) const
{
return mHalfSize;
};
156 virtual bool isLeaf( ) const {return true;};
158 virtual void traversal( Traversal&tr, VisibleObjectsBoundsInfo * const visibleBounds )
{
tr.onLeaf ( *this, visibleBounds );
};
162 virtual void traversal( const TraversalConst &tr, VisibleObjectsBoundsInfo * const visibleBounds )
{
tr.onLeaf( *this, visibleBounds );
};
166 virtual void traversal( const ConstTraversalConst &tr, VisibleObjectsBoundsInfo * const visibleBounds ) const
{
tr.onLeaf ( *this, visibleBounds );
};
/** creates the opaque bounding box for this octant
*/
172 OcclusionBoundingBox* getOcclusionBoundingBox( );
#ifdef _VISIBILITYDEBUG
175 void setDebugCorners( PagingLandScapeOctreeSceneManager *scnMgr );
#endif //_VISIBILITYDEBUG
/** Adds an instance of a scene object to this node.
@remarks
Scene objects can include Entity objects, Camera objects, Light objects,
ParticleSystem objects etc. Anything that subclasses from MovableObject.
*/
183 virtual void attachObject( MovableObject* obj );
/** Detaches the indexed object from this scene node.
@remarks
Detaches by index, see the alternate version to detach by name. Object indexes
may change as other objects are added / removed.
*/
189 virtual MovableObject* detachObject( unsigned short index );
/** Detaches an object by pointer. */
191 virtual void detachObject( MovableObject* obj );
/** Detaches the named object from this node and returns a pointer to it. */
194 virtual MovableObject* detachObject( const String& name );
/** Detaches all objects attached to this node.
*/
198 virtual void detachAllObjects( void );
200 virtual bool isOccluder ( ) const { return mIsOccluder; }
202 bool isStaticNode( ) const { return mIsStaticNode; }
204 void setStaticCulling ( const bool staticNode ) { mIsStaticNode = staticNode; };
protected:
/** Internal method for updating the bounds for this PagingLandScapeOctreeNode.
@remarks
This method determines the bounds solely from the attached objects, not
any children. If the node has changed it's bounds, it is removed from its
current PagingLandScapeOctree, and reinserted into the tree.
*/
214 void _updateBounds( void );
216 void _removeNodeAndChildren( void );
///local bounding box
219 AxisAlignedBox mLocalAABB;
///PagingLandScapeOctree this node is attached to.
222 PagingLandScapeOctree* mOctant;
223 OcclusionBoundingBox* mOcclusionBoundingBox;
224 Vector3 mHalfSize;
/// if node need to in loose octree or normal octree
226 bool mIsStaticNode;
/// if node need to be drawn during query phase
228 bool mIsOccluder;
// if a pre-notified object is visible.
230 MovableObjectList mNotifiedVisibles;
};
}
#endif //__PagingLandScapeOctreeNODE_H
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
OgrePagingLandScapeOctreePlaneBoundedVolumeListSceneQuery.h - description
-------------------
begin : Tues July 20, 2004
copyright : ( C ) 2004 by Jon Anderson
email : janders@users.sf.net
***************************************************************************/
#ifndef PagingLandScapeOctreePlaneBoundedVolumeListSCENEQUERY_H
#define PagingLandScapeOctreePlaneBoundedVolumeListSCENEQUERY_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgreSceneManager.h"
namespace Ogre
{
/** PagingLandScapeOctree implementation of PlaneBoundedVolumeListSceneQuery. */
class _OgrePagingLandScapeExport PagingLandScapeOctreePlaneBoundedVolumeListSceneQuery : public DefaultPlaneBoundedVolumeListSceneQuery
{
public:
46 PagingLandScapeOctreePlaneBoundedVolumeListSceneQuery( SceneManager* creator );
virtual ~PagingLandScapeOctreePlaneBoundedVolumeListSceneQuery( void );
/** See SceneQuery. */
void execute( SceneQueryListener* listener );
};
}
#endif
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
OgrePagingLandScapeOctreeRaySceneQuery.h - description
-------------------
begin : Tues July 20, 2004
copyright : ( C ) 2004 by Jon Anderson
email : janders@users.sf.net
***************************************************************************/
#ifndef PagingLandScapeOctreeRaySCENEQUERY_H
#define PagingLandScapeOctreeRaySCENEQUERY_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgreSceneManager.h"
namespace Ogre
{
/** PagingLandScapeOctree implementation of RaySceneQuery. */
class _OgrePagingLandScapeExport PagingLandScapeOctreeRaySceneQuery : public DefaultRaySceneQuery
{
public:
46 PagingLandScapeOctreeRaySceneQuery( SceneManager* creator );
virtual ~PagingLandScapeOctreeRaySceneQuery( void );
/** See RayScenQuery. */
void execute( RaySceneQueryListener* listener );
};
}
#endif
1 /***************************************************************************
PagingLandScapeOctreescenemanager.h - description
-------------------
begin : Fri Sep 27 2002
copyright : ( C ) 2002 by Jon Anderson
email : janders@users.sf.net
***************************************************************************/
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright ( c ) 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
#ifndef PagingLandScapeOctreeSCENEMANAGER_H
#define PagingLandScapeOctreeSCENEMANAGER_H
#include "OgreSceneManager.h"
#include "OgreRenderOperation.h"
#include "OgreSphere.h"
#include <list>
#include <algorithm>
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeOctree.h"
#include "OgrePagingLandScapeOcclusion.h"
#include "OgreRenderable.h"
#include "OgrePagingLandScapePoolSet.h"
namespace Ogre
{
/// Factory for OctreeSceneManager
56 class PagingLandScapeOctreeSceneManagerFactory : public SceneManagerFactory
{
protected:
59 void initMetaData( void ) const;
public:
61 PagingLandScapeOctreeSceneManagerFactory( ) {}
62 ~PagingLandScapeOctreeSceneManagerFactory( ) {}
/// Factory type name
64 static const String FACTORY_TYPE_NAME;
65 SceneManager* createInstance( const String& instanceName );
66 void destroyInstance( SceneManager* instance );
};
69 class PagingLandScapeOctreeNode;
71 class PagingLandScapeOctreeCamera;
72 class PagingLandScapeOctreeIntersectionSceneQuery;
73 class PagingLandScapeOctreeRaySceneQuery;
74 class PagingLandScapeOctreeSphereSceneQuery;
75 class PagingLandScapeOctreeAxisAlignedBoxSceneQuery;
76 class PagingLandScapeOctreePlaneBoundedVolumeListSceneQuery;
/** A collection of pre-allocated octrees
*/
80 class OctreeSet : public PoolSet<PagingLandScapeOctree>
{
protected:
83 virtual PagingLandScapeOctree* allocate ( )
{
return new PagingLandScapeOctree( );
}
87 virtual void deallocate ( PagingLandScapeOctree *p )
{
delete p;
}
};
//typedef std::list < WireBoundingBox* > BoxList;
//typedef std::list < OcclusionBoundingBox* > BoxList;
//typedef std::list < unsigned long > ColorList;
//typedef std::list < SceneNode* > SceneNodeList;
/** Specialized SceneManager that divides the geometry into an PagingLandScapeOctree in order to facilitate spatial queries.
@remarks
For debugging purposes, a special "CullCamera" can be defined. To use it, call setUseCallCamera( true ),
and create a camera named "CullCamera". All culling will be performed using that camera, instead of the viewport
camera, allowing you to fly around and examine culling.
*/
108 class PagingLandScapeOctreeSceneManager : public SceneManager
{
110 friend class PagingLandScapeOctreeIntersectionSceneQuery;
111 friend class PagingLandScapeOctreeRaySceneQuery;
112 friend class PagingLandScapeOctreeSphereSceneQuery;
113 friend class PagingLandScapeOctreeAxisAlignedBoxSceneQuery;
114 friend class PagingLandScapeOctreePlaneBoundedVolumeListSceneQuery;
public:
static int intersect_call;
/** Standard Constructor. Initializes the PagingLandScapeOctree to -500, -500, -500 to 500, 500, 500 with unlimited depth. */
119 PagingLandScapeOctreeSceneManager( const String &name );
/** Standard Constructor */
121 PagingLandScapeOctreeSceneManager( const String &name, AxisAlignedBox& box, int max_depth );
/** Standard destructor */
123 virtual ~PagingLandScapeOctreeSceneManager( void );
125 inline PagingLandScapeOctree * getNewOctree( )
{
return mOctreeSet.getPoolable( );
}
129 inline void deleteOctree( PagingLandScapeOctree * p )
{
p->reset ( );
mOctreeSet.removePoolable ( p );
}
135 void shutdown( );
/// @copydoc SceneManager::getTypeName
137 const String& getTypeName( void ) const;
/** Initializes the manager to the given box and depth.
*/
141 void init( const AxisAlignedBox& box, int d );
/** Creates a specialized PagingLandScapeOctreeNode */
144 virtual SceneNode* createSceneNode( void );
/** Creates a specialized PagingLandScapeOctreeNode */
146 virtual SceneNode* createSceneNode( const String& name );
/** Creates a specialized PagingLandScapeOctreeCamera */
148 virtual Camera* createCamera( const String& name );
149 virtual void destroyCamera( Camera *cam );
150 virtual void destroyCamera( const String& name );
151 virtual void destroyAllCameras( void );
153 void addCamera( Camera *cam );
/** Deletes a scene node */
156 virtual void destroySceneNode( const String& name );
/** Does nothing more */
159 virtual void _updateSceneGraph( Camera* cam );
/** Recurses through the PagingLandScapeOctree determining which nodes are visible. */
#ifdef PLSM2_EIHORT
163 virtual void _findVisibleObjects( Camera* cam, VisibleObjectsBoundsInfo *visibleBounds, bool onlyShadowCasters );
#else
165 virtual void _findVisibleObjects( Camera* cam, bool onlyShadowCasters );
#endif
/** Alerts each un-culled object, notifying it that it will be drawn.
* Useful for doing calculations only on nodes that will be drawn, prior
* to drawing them...
*/
//virtual void _alertVisibleObjects( void );
/** Walks through the PagingLandScapeOctree, adding any visible objects to the render queue.
@remarks
If any octant in the PagingLandScapeOctree if completely within the the view frustum,
all sub-children are automatically added with no visibility tests.
*/
179 void walkPagingLandScapeOctree( PagingLandScapeOctreeCamera * camera, RenderQueue * const queue,
PagingLandScapeOctree * const octant, const bool foundvisible, const bool onlyShadowCasters );
/** Checks the given PagingLandScapeOctreeNode, and determines if it needs to be moved
* to a different octant.
*/
185 void _updatePagingLandScapeOctreeNode( PagingLandScapeOctreeNode* nod );
/** Removes the given PagingLandScapeOctree node */
188 void _removePagingLandScapeOctreeNode( PagingLandScapeOctreeNode* nod );
/** Adds the PagingLandScapeOctree Node, starting at the given PagingLandScapeOctree, and recursing at max to the specified depth.
*/
192 void _addPagingLandScapeOctreeNode( PagingLandScapeOctreeNode* ocnod, PagingLandScapeOctree* PagingLandScapeOctree, int depth = 0 );
/** Adds the PagingLandScapeOctree Node, starting at the given PagingLandScapeOctree, and recursing at max to the specified depth.
*/
196 void _addPagingLandScapeOctreeMovableNode( PagingLandScapeOctreeNode* ocnod, PagingLandScapeOctree* PagingLandScapeOctree, int depth = 0 );
/** Adds the PagingLandScapeOctree Node, starting at the given PagingLandScapeOctree, and recursing at max to the specified depth.
*/
200 void _addPagingLandScapeOctreeStaticNode( PagingLandScapeOctreeNode* ocnod, PagingLandScapeOctree* PagingLandScapeOctree, int depth = 0 );
/** Recurses the PagingLandScapeOctree, adding any nodes intersecting with the box into the given list.
It ignores the exclude scene node.
*/
205 void findNodesIn( const AxisAlignedBox& box, std::list < SceneNode* > &list,
const SceneNode* const exclude = 0 );
/** Recurses the PagingLandScapeOctree, adding any nodes intersecting with the sphere into the given list.
It ignores the exclude scene node.
*/
211 void findNodesIn( const Sphere& sphere, std::list < SceneNode* > &list,
const SceneNode* const exclude = 0 );
/** Recurses the PagingLandScapeOctree, adding any nodes intersecting with the volume into the given list.
It ignores the exclude scene node.
*/
217 void findNodesIn( const PlaneBoundedVolume& volume, std::list < SceneNode* > &list,
const SceneNode* const exclude=0 );
/** Recurses the PagingLandScapeOctree, adding any nodes intersecting with the ray into the given list.
It ignores the exclude scene node.
*/
223 void findNodesIn( const Ray& ray, std::list < SceneNode* > &list,
const SceneNode* const exclude=0 );
/** Sets the box visibility flag */
227 void setShowBoxes( bool b )
{
#ifdef _VISIBILITYDEBUG
mShowBoxes = b;
#endif //_VISIBILITYDEBUG
};
/** Sets the cull camera flag */
235 void setUseCullCamera( bool b )
{
#ifdef _VISIBILITYDEBUG
mCullCamera = b;
#endif //_VISIBILITYDEBUG
};
/** Resizes the PagingLandScapeOctree to the given size */
243 void resize( const AxisAlignedBox& box );
244 void resize( const AxisAlignedBox &box, const int depth );
/** Sets the given option for the SceneManager
@remarks
Options are:
"Size", AxisAlignedBox *;
"CullCamera", bool *;
"Depth", int *;
"ShowPagingLandScapeOctree", bool *;
*/
255 virtual bool setOption( const String& key, const void* value );
/** Gets the given option for the Scene Manager.
@remarks
See setOption
*/
261 virtual bool getOption( const String& key, void* value );
263 bool getOptionValues( const String& key, StringVector& refValueList );
264 bool getOptionKeys( StringVector& refKeys );
/** Overridden from SceneManager */
266 void clearScene( void );
268 AxisAlignedBoxSceneQuery* createAABBQuery( const AxisAlignedBox& box, unsigned long mask );
269 SphereSceneQuery* createSphereQuery( const Sphere& sphere, unsigned long mask );
270 PlaneBoundedVolumeListSceneQuery* createPlaneBoundedVolumeQuery( const PlaneBoundedVolumeList& volumes, unsigned long mask );
271 RaySceneQuery* createRayQuery( const Ray& ray, unsigned long mask );
272 IntersectionSceneQuery* createIntersectionQuery( unsigned long mask );
274 void directRenderSingleQueue( RenderQueue *queue );
275 void directRenderSingleObject( Renderable *mo );
277 void addVisible( MovableObject *mo );
279 const AxisAlignedBox &getBoundingBox( )const {return mBox;};
281 void registeredNodeInCamera( OcclusionElement *on );
282 void unregisteredNodeInCamera( OcclusionElement *on );
284 void registerCamera ( PagingLandScapeOctreeCamera *c );
285 void unregisterCamera( PagingLandScapeOctreeCamera *c );
protected:
/// The root PagingLandScapeOctree
290 PagingLandScapeOctree* mPagingLandScapeOctree;
typedef std::map<unsigned int, MovableObjectList * > VisiblesPerCam;
293 VisiblesPerCam mVisibles;
294 MovableObjectList * mCamInProgressVisibles;
295 PolygonMode mCamDetail;
296 bool mCamClear;
/// number of rendered objects
int mNumObjects;
/// max depth for the tree.
int mMaxDepth;
/// Size of the PagingLandScapeOctree
305 AxisAlignedBox mBox;
// OCCLUSION
309 Occlusion mOcclusion;
//DEBUG INFO
#ifdef _VISIBILITYDEBUG
/// box visibility flag
314 bool mShowBoxes;
/// list of boxes to be rendered
316 MovableObjectList mBoxes;
/// cull camera flag
318 bool mCullCamera;
/// cull camera flag
320 bool mCullDebug;
322 String mDebugText;
#endif //_VISIBILITYDEBUG
326 PagingLandScapeOctreeCamera *mCurrentOptionCamera;
328 RenderTexture *mOcclusionDepth;
329 Camera *mOcclusionCamera;
331 void enableHardwareOcclusionTests( );
332 void disableHardwareOcclusionTests( );
334 OctreeSet mOctreeSet;
};
}
#endif
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
OgrePagingLandScapeOctreeSphereSceneQuery.h - description
-------------------
begin : Tues July 20, 2004
copyright : ( C ) 2004 by Jon Anderson
email : janders@users.sf.net
***************************************************************************/
#ifndef PagingLandScapeOctreeSphereSCENEQUERY_H
#define PagingLandScapeOctreeSphereSCENEQUERY_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgreSceneManager.h"
namespace Ogre
{
/** PagingLandScapeOctree implementation of SphereSceneQuery. */
class _OgrePagingLandScapeExport PagingLandScapeOctreeSphereSceneQuery : public DefaultSphereSceneQuery
{
public:
46 PagingLandScapeOctreeSphereSceneQuery( SceneManager* creator );
virtual ~PagingLandScapeOctreeSphereSceneQuery( void );
/** See SceneQuery. */
void execute( SceneQueryListener* listener );
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeOptions.h - description
-------------------
begin : Sun Mar 02 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeOPTIONS_H
#define PAGINGLandScapeOPTIONS_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgreStringVector.h"
#include "OgreConfigFile.h"
#include "OgreMaterial.h"
namespace Ogre
{
/**
* A simple class for encapsulating parameters passed in when initializing *
* a LandScapeRenderable
*/
32 class PagingLandScapeOptions
{
public:
35 PagingLandScapeOptions( PagingLandScapeSceneManager * scnMgr );
37 ~PagingLandScapeOptions( void );
39 void init( );
40 void setDefault( );
42 bool load( DataStreamPtr& stream );
43 bool load( const String &filename, ConfigFile& config );
44 bool load( const String &filename );
46 void loadMap( const String& mapName );
47 void loadMapOptions( const String& mapName );
48 void insertMap( const String& mapName );
50 LandScapeFileNames* getLandScapeFileNames( void )
{
return &mMapList;
};
55 bool setOption( const String& strKey, const void* pValue );
56 bool getOption( const String& strKey, void* pDestValue );
58 bool hasOption( const String& strKey ) const ;
60 bool getOptionValues( const String & key, StringVector &refValueList );
61 bool getOptionKeys( StringVector &refKeys );
63 void getAvgColors( void );
65 LandScapeFileNames& getMapList( void );
67 const String& getMapFilename( const String &currMapName ) const;
68 const String& getPreviousMapName( void ) const;
69 const String& getNextMapName( void ) const;
70 const String& getCurrentMapName( void ) const;
72 void setCurrentMapName( const String& mapName );
74 const String& getCurrentTextureFormat( void ) const;
75 void setTextureFormat( const String& format );
76 void insertTextureFormat ( const String &format ) ;
78 void setPrimaryCamera( PagingLandScapeCamera* cam );
79 void calculateCFactor( void );
81 String data2DFormat;
82 String textureFormat;
84 String TerrainName;
86 String LandScape_filename;
87 String LandScape_extension;
88 String LandScape_export_filename;
89 String LandScape_export_extension;
91 String image_filename;
92 bool ImageNameLoad;
// MAP TOOL OPTIONS
96 String OutDirectory;
97 String TextureExtension;
98 String TextureExportExtension;
100 bool Paged;
101 bool BaseMap;
102 bool MiniMap;
103 bool ColorMapSplit;
104 bool ColorMapGenerate;
105 bool LightMap;
106 bool NormalMap;
107 bool HeightMap;
108 bool AlphaMaps;
109 bool LitBaseMap;
110 bool LitColorMapSplit;
111 bool LitColorMapGenerate;
112 bool InfiniteMap;
113 bool CoverageMap;
114 bool HeightNormalMap;
116 Real HeightMapBlurFactor;
118 String ColorMapName;
120 bool lightmoved;
121 Vector3 Sun;
122 Real SunAngle;
123 Real Amb;
124 Real Diff;
126 bool mUseLodMapCache;
unsigned int Blur;
// end of MAP TOOL OPTIONS
unsigned int maxValue; //Compression range for the TC height field
unsigned int minValue;
unsigned int TileSize;
unsigned int PageSize; //size of the page.
136 Real invTileSizeMinusOne;
137 Real invPageSizeMinusOne;
unsigned int NumTiles;
unsigned int NumPages;
unsigned int world_height; //world page height, from 0 to height, in page number
unsigned int world_width; //world page width, from 0 to width, in page number
144 Real maxScaledZ; //world page height, scaled
145 Real maxScaledX; //world page width, scaled
147 Real maxUnScaledZ; //world page height, scaled
148 Real maxUnScaledX; //world page width, scaled
151 Real change_factor; //Determines the value of the change factor for loading/unloading LandScape Pages
unsigned int max_adjacent_pages;
unsigned int max_preload_pages;
154 Real visible_renderables; //Numbers of visible renderables surrounding the camera
155 Real renderable_factor; //Determines the distance of loading and unloading of renderables in renderable numbers
157 Vector3 position; //Startup position of the terrain surface
158 Vector3 scale;
159 Vector3 invScale;
161 Material::LodDistanceList lodMaterialDistanceList; //Distance for the material LOD change
162 Real distanceLOD; //Distance for the LOD change
163 Real LOD_factor;
164 bool roughnessLod;
unsigned int num_renderables; //Max number of renderables to use.
unsigned int num_renderables_increment; //Number of renderables to add in case we run out of renderables
unsigned int num_tiles; //Max number of tiles to use.
unsigned int num_tiles_increment; //Number of renderables to add in case we run out of renderables
171 Real cameraThreshold; //If the last camera position is >= the the scene is transverse again.
unsigned int num_renderables_loading; //Max number of renderable to load in a single Frame.
unsigned int maxRenderLevel;
unsigned int NumMatHeightSplat;
177 std::vector <ColourValue> matColor;
178 std::vector <Real> matHeight;
179 std::vector<String> SplatDetailMapNames;
181 bool VertexCompression;
183 bool hasVertexShader;
184 bool hasFragmentShader;
185 bool hasFragmentShader2;
unsigned int numTextureUnits;
187 bool isRenderGL;
189 Real ScaledPageSizeX;
190 Real ScaledPageSizeZ;
191 Real ScaledHeightY;
/// used to test all texture format without
/// restrictions ( renderer or capabilities )
196 bool TextureFormatDebug;
/// Can terrain be deformed real-time
198 bool Deformable;
/// are deformation saved?
200 bool saveDeformation;
//used to get screen height...
// should find another way...
205 PagingLandScapeCamera* primaryCamera;
/// At what point ( parametric ) should LOD morphing start
208 Real lodMorphStart;
209 bool lodMorph;
unsigned int maxPixelError;
211 Real CFactor;
// MapSplitter Tool
unsigned int RawHeight;
unsigned int RawWidth;
217 bool isRaw;
218 bool Equalize;
219 bool ZHorizon;
220 bool SRTM_water;
unsigned int MiniMapHeight;
unsigned int MiniMapWidth;
// Generate one or all maps ?
226 bool mBatchMode;
// Both
/// ResourceGroupName
231 String groupName;
232 String cfgGroupName;
234 bool lit;
235 bool normals;
236 bool colored;
238 bool coverage_vertex_color;
239 bool base_vertex_color;
240 bool vertex_shadowed;
241 bool vertex_instant_colored;
243 bool BigImage;
244 bool VisMap;
245 bool MaxLodUnderCam;
247 Real TextureStretchFactor;
unsigned int RenderableLoadInterval;
unsigned int PageLoadInterval;
unsigned int TileInvisibleUnloadFrames;
unsigned int PageInvisibleUnloadFrames;
unsigned int NumSplatMapToSplit;
256 std::vector<String> SplatMapNames;
unsigned int NumTextureFormatSupported;
259 std::vector<String> TextureFormatSupported;
261 bool queryNoInterpolation;
262 Real queryResolutionFactor;
264 bool materialPerPage;
265 bool textureModifiable;
267 Vector3 BaseCameraViewpoint;
268 Vector3 Baselookat;
270 bool setUint ( unsigned int &u, const String &ValuetoGet );
271 bool setBool ( bool &b, const String &ValuetoGet );
272 bool setReal ( Real &r, const String &ValuetoGet );
273 bool setColourValue( ColourValue &r, const String &ValuetoGet );
274 bool setString ( String &s, const String &ValuetoGet );
276 StringVector mResourceFilesystem;
277 StringVector mResourceZip;
279 PagingLandScapeSceneManager *mScnMgr;
281 void setTileInfo( PagingLandScapeTileInfo *t );
282 PagingLandScapeTileInfo *getTileInfo( const uint pageX, const uint pageZ,
283 const uint tileX, const uint tileZ );
284 void loadMapInfo( );
285 void clearTileInfo( );
286 void saveMapInfo( );
private:
290 void loadcfg ( const String &filename, ConfigFile& config );
291 ColourValue _getAvgColor( const String& tex ) const;
292 String mCurrentMap;
293 LandScapeFileNames mMapList;
294 StringVector mTextureFormats;
295 bool isInit;
296 ConfigFile *mConfig;
298 std::deque<PagingLandScapeTileInfo*> mTileInfoCache;
};
}
#endif
/***************************************************************************
OgrePagingLandScapePage.h - description
-------------------
begin : Sat Mar 08 2003
copyright : ( C ) 2003-2006 by Jose A. Milan and Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapePAGE_H
#define PAGINGLandScapePAGE_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
class _OgrePagingLandScapeExport PagingLandScapePage
{
public:
/** Sets the appropriate neighbor for this TerrainRenderable. Neighbors are necessary
to know when to bridge between LODs.
*/
33 void _setNeighbor( const Neighbor& n, PagingLandScapePage* p );
/** Returns the page's scene node
*/
37 SceneNode* getPageNode( ) const { return mPageNode; }
/** Returns the neighbor TerrainRenderable.
*/
41 PagingLandScapePage* _getNeighbor( const Neighbor& n ) const
{
return mNeighbors[ n ];
};
46 PagingLandScapeTile* getTile( const unsigned int i , const unsigned int j ) const;
48 PagingLandScapeTile* getTile( const Vector3& pos );
49 PagingLandScapePage( PagingLandScapePageManager *pageMgr );
virtual ~PagingLandScapePage( void );
/** Whole Map changes */
void init( const unsigned int tableX, const unsigned int tableZ );
/** Release the page, but keep it reusable if Whole Map changes */
void uninit( void );
/** Pre-loads the LandScape data using parameters int he given in the constructor. */
void preload( void );
/** Loads the LandScape tiles using parameters int he given in the constructor. */
void load( void );
/** Unloads the LandScape data, then reloads it */
void reload( void );
/** Loads the LandScape texture using parameters int he given in the constructor. */
void loadTexture( void );
/** Unloads the LandScape texture, but doesn't destroy the LandScape data. */
void unloadTexture( void );
/** Unloads the LandScape data, but doesn't destroy the LandScape page. */
void unload( void );
/** Post Unloads the LandScape data, but doesn't destroy the LandScape page. */
void postUnload( void );
void unsetLoading( void )
{
mIsLoading = false;
};
void unsetPreLoading( void )
{
mIsPreLoading = false;
};
void unsetTextureLoading( void )
{
mIsTextureLoading = false;
};
void unsetUnloading( void )
{
mIsUnloading = false;
};
void unsetPostUnloading( void )
{
mIsPostUnloading = false;
};
void unsetTextureunloading( void )
{
mIsTextureunloading = false;
};
const bool isLoaded( void ) const
{
return mIsLoaded;
};
const bool isPreLoaded( void ) const
{
return mIsPreLoaded;
};
const bool isTextureLoaded( void ) const
{
return mIsTextureLoaded;
};
const bool isLoadable( void ) const
{
return mIsLoadable;
};
const bool unloadUntouched( void );
void touch( void );
bool isVisible( void ) const
{
return mVisible;
}
/** Returns if the camera is over this LandScape page.
*/
int isCameraIn( const Vector3& pos ) const;
bool _Notify( const Vector3 &pos, const PagingLandScapeCamera * const Cam );
void _Show( const bool do_show );
void getCoordinates( unsigned int& X, unsigned int& Z ) const
{
X = mTableX;
Z = mTableZ;
};
bool mIsLoading;
bool mIsPreLoading;
bool mIsTextureLoading;
bool mIsUnloading;
bool mIsPostUnloading;
bool mIsTextureunloading;
/** Sets the render queue group which the tiles should be rendered in. */
void setRenderQueue( uint8 qid );
void _updateLod( void );
void setMapMaterial( void );
inline bool isCoord( const unsigned int x, const unsigned int z ){return ( mTableZ == z && mTableX == x );};
SceneNode *getSceneNode( ){return mPageNode;};
const AxisAlignedBox &getWorldBbox( ) const {return mBounds;};
const Vector3 &getCenter( void ) const {return mWorldPosition;};
protected:
SceneNode* mPageNode;
PagingLandScapeTiles mTiles;
bool mIsLoaded;
bool mIsPreLoaded;
bool mIsTextureLoaded;
// if data needed for this page doesn't exists
bool mIsLoadable;
bool mVisible;
// ensure page is not flickering due to shadow passes
// as it unload instantly
// but loading is queued
// if not page not showed until mVisibletouch==0 it becomes invisible
//size_t mVisibletouch;
// Position of this Terrain Page in the Terrain Page Array
unsigned int mTableX;
unsigned int mTableZ;
unsigned int mNumTiles;
Real mIniX; //, mEndX; // Max and Min values of the terrain
Real mIniZ; //, mEndZ;
PagingLandScapePage* mNeighbors[4];
// Change Zone values
AxisAlignedBox mBounds;
AxisAlignedBox mBoundsInt;
AxisAlignedBox mBoundsExt;
Vector3 mWorldPosition;
PagingLandScapePageRenderable* mRenderable;
unsigned int mTimeUntouched;
PageState pageState;
PageQueuingState pageQueingState;
PagingLandScapePageManager *mParent;
};
}
#endif
/***************************************************************************
OgrePagingLandScapePageManager.h - description
-------------------
begin : Sat May 01 2004
copyright : ( C ) 2003-2006 by Jose A. Milan and Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapePAGEMANAGER_H
#define PAGINGLandScapePAGEMANAGER_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgreSingleton.h"
#include "OgreFrameListener.h"
#include "OgrePagingLandScapeQueue.h"
#include "OgrePagingLandScapePage.h"
namespace Ogre
{
class _OgrePagingLandScapeExport PagingLandScapePageManager : public FrameListener
{
public:
///ctor
35 PagingLandScapePageManager( PagingLandScapeSceneManager * scnMgr );
///dtor
37 ~PagingLandScapePageManager( void );
/// upon new landscape
40 void load( void );
/// empty before loading a landscape or final deletion
42 void clear( void );
/// reset paging but keep page pool in memory
44 void reset( void );
/// used to load first page earlier than first updatePaging( ) call
/// say like just after scene manager setWorldGeom( )
48 void LoadFirstPage( PagingLandScapeCamera* cam );
/// Make sure page under camera is loaded,
/// that neighbor pages are preLoaded, preLoading
/// and process queues accordingly
52 void updatePaging( PagingLandScapeCamera* cam );
// recursively call LOD update on all page and tiles
55 void _updateLod( void );
// load everything around camera just now.
58 void loadNow( PagingLandScapeCamera *cam );
// Make sure page gets into loaded page list when loaded from outside
// ie "LoadNow" getOption
61 void addLoadedPage( PagingLandScapePage *p );
/// if page is already instantiated get page at this pos,
/// otherwise allocate one, if alwaysReturn is set true.
65 PagingLandScapePage* getPage( const unsigned int i , const unsigned int j,
const bool alwaysReturn = true );
/// Instantiate a new page from pool.
68 PagingLandScapePage* getNewPage( const unsigned int i , const unsigned int j );
/// Return a page to the pool.
70 void releasePage ( PagingLandScapePage*p );
/// get Tile at absolute position in space, return answer even when position is outside landscape
/// when alwaysAnswer is true
74 PagingLandScapeTile* getTile( const Real posx, const Real posz, bool alwaysAnswer );
/// get Tile at absolute position but unscaled by landscape scale in space,
/// return answer even when position is outside landscape
/// when alwaysAnswer is true
78 PagingLandScapeTile* getTileUnscaled( const Real posx, const Real posz, bool alwaysAnswer );
// get Tile at relative position ( in the page containing the tile page coordinate system ) in space,
/// return answer even when position is outside landscape
/// when alwaysAnswer is true
82 PagingLandScapeTile* getTile( const Real posx, const Real posz,
const unsigned int pagex, const unsigned int pagez,
bool alwaysAnswer );
// get Tile at relative position but unscaled by landscape scale ( in the page containing the tile page coordinate system ) in space,
/// return answer even when position is outside landscape
/// when alwaysAnswer is true
88 PagingLandScapeTile* getTileUnscaled( const Real posx, const Real posz,
const unsigned int pagex, const unsigned int pagez,
bool alwaysAnswer );
// get Tile at relative position but unscaled by landscape scale ( in the page containing the tile page coordinate system ) in space,
/// return answer even when position is outside landscape
/// when alwaysAnswer is true
94 PagingLandScapeTile* getTilePage ( unsigned int &posx, unsigned int &posz, const unsigned int pagex, const unsigned int pagez );
96 void getGlobalToPage( Real& x, Real& z ) const;
/** Get the Page indices from a position
@param posx the world position vector.
@param posz the world position vector.
@param x result placed in reference to the x index of the page
@param z result placed in reference to the z index of the page
*/
103 inline bool getPageIndices( const Real posx, const Real posz, unsigned int& x, unsigned int& z, bool alwaysAnswer ) const
{
if ( alwaysAnswer )
{
getNearestPageIndicesUnscaled( posx * mOptions->invScale.x, posz* mOptions->invScale.z, x, z );
return true;
}
else
{
return getRealPageIndicesUnscaled( posx * mOptions->invScale.x, posz* mOptions->invScale.z, x, z );
}
}
/** Get the Page indices from a position, returning page only if position is in.
@param posx the world position vector but unscaled.
@param posz the world position vector but unscaled.
@param x result placed in reference to the x index of the page
@param z result placed in reference to the z index of the page
*/
121 inline bool getRealPageIndicesUnscaled( const Real posx, const Real posz,
unsigned int& x, unsigned int& z )
const
{
const Real lx = ( ( posx + mOptions->maxUnScaledX ) * mOptions->invPageSizeMinusOne );
const Real lz = ( ( posz + mOptions->maxUnScaledZ ) * mOptions->invPageSizeMinusOne );
// make sure indices are not negative or outside range of number of pages
if ( lx >= mOptions->world_width || lx < static_cast <Real> ( 0.0 ) ||
lz >= mOptions->world_height || lz < static_cast <Real> ( 0.0 ) )
{
return false;
}
else
{
x = static_cast< unsigned int > ( lx );
z = static_cast< unsigned int > ( lz );
return true;
}
}
/** Get the Page indices from a position, always returning a page.
@param posx the world position vector but unscaled.
@param posz the world position vector but unscaled.
@param x result placed in reference to the x index of the page
@param z result placed in reference to the z index of the page
*/
147 void getNearestPageIndicesUnscaled( const Real posx, const Real posz, unsigned int& x, unsigned int& z ) const;
/** Get the Tile indices from a position
@param posx the world position vector.
@param posz the world position vector.
@param pagex the world position page number.
@param pagez the world position page number.
@param x result placed in reference to the x index of the page
@param z result placed in reference to the z index of the page
*/
157 bool getTileIndices( const Real posx, const Real posz, const unsigned int pagex, const unsigned int pagez, unsigned int& x, unsigned int& z, bool alwaysAnswer ) const;
/** Get the Tile indices from a position, returning tile only if position is in.
@param posx the world position vector but unscaled.
@param posz the world position vector but unscaled.
@param x result placed in reference to the x index of the page
@param z result placed in reference to the z index of the page
*/
165 inline bool getRealTileIndicesUnscaled( const Real posx, const Real posz,
const unsigned int pagex, const unsigned int pagez,
unsigned int& x, unsigned int& z ) const
{
// adjust x and z to be local to page
const int pSize = mOptions->PageSize - 1;
const int tilex = static_cast< int >( ( posx - ( ( pagex * pSize ) - mOptions->maxUnScaledX ) ) * mOptions->invTileSizeMinusOne );
const int tilez = static_cast< int >( ( posz - ( ( pagez * pSize ) - mOptions->maxUnScaledZ ) ) * mOptions->invTileSizeMinusOne );
const int tilesPerPage = static_cast< int >( mOptions->NumTiles );
//const int tilesPerPage = static_cast< int >( mOptions->NumTiles( pSize * inv_tSize ) - 1 );
if ( tilex > tilesPerPage || tilex < 0 ||
tilez > tilesPerPage || tilez < 0 )
{
return false;
}
else
{
x = static_cast< unsigned int >( tilex );
z = static_cast< unsigned int >( tilez );
return true;
}
}
/** Get the Tile indices from a position, returning tile only if position is in.
@param posx the world position vector but unscaled.
@param posz the world position vector but unscaled.
@param x result placed in reference to the x index of the page
@param z result placed in reference to the z index of the page
*/
197 void getNearestTileIndicesUnscaled( const Real posx, const Real posz, const unsigned int pagex, const unsigned int pagez, unsigned int& x, unsigned int& z ) const;
199 void setTerrainReady( bool isready )
{
mTerrainReady = isready;
};
205 void removeFromQueues( PagingLandScapePage* p );
207 bool frameStarted( const FrameEvent& evt );
208 bool frameEnded( const FrameEvent& evt );
210 void setWorldGeometryRenderQueue( uint8 qid );
211 RenderQueueGroupID getRenderQueueGroupID( void )
{
return mRenderQueueGroupID;
};
216 void setMapMaterial( void );
217 void WorldDimensionChange( void );
/// getter
222 unsigned int getCurrentCameraPageX( void ) const;
/// getter
224 unsigned int getCurrentCameraPageZ( void ) const;
/// getter
226 unsigned int getCurrentCameraTileX( void ) const;
/// getter
228 unsigned int getCurrentCameraTileZ( void ) const;
/// getter
230 int getPagePreloadQueueSize( void ) const;
/// getter
232 int getPageLoadQueueSize( void ) const;
/// getter
234 int getPageTextureloadQueueSize( void ) const;
/// getter
236 int getLoadedPageSize( void ) const;
/// getter
238 int getPreLoadedPageSize( void ) const;
/// getter
240 int getTextureLoadedPageSize( void ) const;
/// getter
242 int getUnloadedPagesSize( void ) const;
244 RenderQueueGroupID getPageRenderQueue( ){return mRenderQueueGroupID;};
246 PagingLandScapeOptions* getOptions( ){return mOptions;}
247 PagingLandScapeSceneManager* getSceneManager( ){return mSceneManager;}
249 bool isEnabled ( )const {return mEnabled;}
250 void setEnabled ( const bool enabled ){mEnabled = enabled;}
protected:
PagingLandScapeOptions* mOptions;
PagingLandScapeSceneManager *mSceneManager;
void processUnloadQueues( );
void processLoadQueues( );
void updateLoadedPages( );
void queuePageNeighbors ( );
void makePageLoadedNow( PagingLandScapePage* p );
PagingLandScapePage* find_nearest( const Vector3& pos, const unsigned int x, const unsigned int z, PagingLandScapePageList& mQueue ) const;
PagingLandScapeData2DManager* mData2d;
PagingLandScapeTextureManager* mTexture;
PagingLandScapeRenderableManager* mRenderablesMgr;
/** LandScape pages for the terrain.
*/
//PagingLandScapePages mPages;
PagingLandScapeQueue <PagingLandScapePage> mPageLoadQueue;
PagingLandScapeQueue <PagingLandScapePage> mPagePreloadQueue;
PagingLandScapeQueue <PagingLandScapePage> mPageTextureloadQueue;
PagingLandScapePageList mLoadedPages;
PagingLandScapePageList mPreLoadedPages;
PagingLandScapePageList mTextureLoadedPages;
PagingLandScapePageList mActivePages;
PagingLandScapePageList mFreePages;
PagingLandScapePageArray mPagePool;
unsigned int mWidth;
unsigned int mHeight;
int mNextQueueFrameCount;
int mTimePreLoaded;
int mPause;
PagingLandScapeCamera* mCurrentcam;
bool mTerrainReady;
bool mOnFrame;
unsigned int mRenderableLoadInterval;
unsigned int mPageLoadInterval;
RenderQueueGroupID mRenderQueueGroupID;
//if not queued to be removed from frame listener
//or SM is in paused State
bool mEnabled;
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapePageRenderable.h - description
-------------------
begin : Thu Feb 27 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PagingLandScapePageRenderable_H
#define PagingLandScapePageRenderable_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
/** Represents a LandScape page in terms of vertexes.
@remarks
A LandScapeRenderable represents a Page used to render a
block of LandScape using the procedural terrain approach for LOD.
*/
33 class PagingLandScapePageRenderable : public Renderable, public MovableObject
{
public:
/** Initializes the LandScapeRenderable with the given options and the starting coordinates of this block.
*/
39 PagingLandScapePageRenderable( PagingLandScapePageManager *pageMgr, const String& name, const unsigned int pageX, const unsigned int pageZ, const AxisAlignedBox& bounds );
41 virtual ~PagingLandScapePageRenderable( void );
43 void load( void );
45 void setMaterial( const MaterialPtr& mat );
47 const Real getMaxHeight( void )
{
return ( mBounds.getMaximum( ) ).y;
};
52 static PagingLandScapeOptions* mOpt;
/////////Movable overridden object methods
/** Updates the level of detail to be used for rendering this TerrainRenderable based on the passed in Camera */
57 inline void _notifyCurrentCamera( Camera* cam )
{
//if ( static_cast<PagingLandScapeCamera*> ( cam )->isVisible ( mBounds.getAllCorners( ) ) )
//{
mVisible = true;
// MovableObject::_notifyCurrentCamera( cam );
//}
//else
// mVisible = false;
}
67 void _updateRenderQueue( RenderQueue* queue );
/** Returns the type of the movable. */
70 virtual const String& getMovableType( void ) const
{
return mType;
};
/** Returns the bounding box of this TerrainRenderable */
76 const AxisAlignedBox& getBoundingBox( void ) const
{
return mBounds;
};
/////////Renderable object methods
/**
Constructs a RenderOperation to render the TerrainRenderable.
@remarks
Each TerrainRenderable has a block of vertices that represent the terrain. Index arrays are dynamically
created for mipmap level, and then cached.
*/
88 virtual void getRenderOperation( RenderOperation& rend );
90 virtual const MaterialPtr& getMaterial( void ) const
{
return mMaterial;
};
95 virtual void getWorldTransforms( Matrix4* xform ) const;
97 virtual const Quaternion& getWorldOrientation( void ) const;
98 virtual const Vector3& getWorldPosition( void ) const;
/** @copydoc Renderable::getLights */
101 const LightList& getLights( void ) const;
103 virtual Technique* getTechnique( void ) const;
105 virtual Real getSquaredViewDepth( const Camera* cam ) const;
107 virtual Real getBoundingRadius( void ) const;
/// @see MovableObject
110 uint32 getTypeFlags( void ) const;
protected:
114 PagingLandScapePageManager *mParent;
116 VertexData* mCurrVertexes;
117 IndexData* mCurrIndexes;
/// Bounding box of this tile
120 AxisAlignedBox mBounds;
/// The center point of this tile
122 Vector3 mCenter;
/// The MovableObject type
124 static String mType;
/// Current material used by this tile
126 MaterialPtr mMaterial;
unsigned int mX;
unsigned int mZ;
};
}
#endif
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright ( c ) 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
#ifndef __OgrePagingLandScapePoolSet_H__
#define __OgrePagingLandScapePoolSet_H__
#include <list>
#include <vector>
namespace Ogre
{
/** A collection of pre-allocated object instance of a same base class
*/
37 template <class T> class PoolSet
{
protected:
typedef std::list<T*> ActivePoolableList;
typedef std::list<T*> FreePoolableList;
typedef std::vector<T*> PoolablePool;
public:
/** Usual constructor
@param
poolSize The initial size of the object pool. Estimate of the number of objects
which will be required, and pass it using this parameter. The set will
preallocate this number to avoid memory fragmentation. The default behaviour
once this pool has run out is to double it.
@see
PoolSet::setAutoextend
*/
PoolSet( unsigned int poolSize = 0, bool autoExtendPool = true ):
mAutoExtendPool( autoExtendPool ),
mAutoExtendFactor( 2.0f ),
mPoolSize( poolSize )
{
assert ( mFreePoolables.empty( ) );
assert ( mActivePoolables.empty( ) );
assert ( mPoolablePool.empty( ) );
setPoolSize( poolSize );
}
/**
dtor
*/
virtual ~PoolSet( )
{
assert ( mPoolSize == 0 && mPoolablePool.empty( ) );
}
/**
empty totally the pool.
*/
77 void deletePool( )
{
// Free pool items
for ( typename PoolablePool::iterator i = mPoolablePool.begin( );
i != mPoolablePool.end( ); ++i )
{
deallocate ( *i );
}
mPoolablePool.clear( );
mFreePoolables.clear( );
mActivePoolables.clear( );
mPoolSize = 0;
}
/** Creates a new pooled object and adds it to this set.
@remarks
Behavior once the query pool has been exhausted depends on the
PoolSet::setAutoextendPool option.
@returns
On success, a pointer to a newly created Poolable is
returned.
@par
On failure ( i.e. no more space and can't autoextend ),
<b>NULL</b> is returned.
@see
PoolSet::setAutoextend
*/
103 T* getPoolable( )
{
if ( mFreePoolables.empty( ) )
{
if ( mAutoExtendPool )
{
autoExtend ( );
}
else
{
return 0;
}
}
// Get a new Object
T* newPoolable = mFreePoolables.front( );
mFreePoolables.pop_front( );
mActivePoolables.push_back( newPoolable );
return newPoolable;
}
/*
Extend the pool Size by a mAutoExtendFactor factor ( default 2.0f )
*/
126 void autoExtend( )
{
unsigned int newSize = ( unsigned int )( mPoolSize * mAutoExtendFactor );
if ( newSize <= mPoolSize )
newSize = mPoolSize + 1;
setPoolSize ( newSize );
}
/*
Extend the pool Size by this factor ( default is 2.0f )
*/
136 void setExtendFactor( const float factor )
{
assert( factor >= 1.0f );// otherwise you'll make it smaller
mAutoExtendFactor = factor;
}
/** Removes a pooled object from the set.
@note
This version is more efficient than removing by index.
*/
145 void removePoolable( T * const pPoolable )
{
mActivePoolables.remove ( pPoolable );
mFreePoolables.push_back ( pPoolable );
}
/** Returns the number of active object which currently make up this set.
*/
152 size_t getActivePoolablesSize( void ) const
{
return static_cast< size_t >( mActivePoolables.size( ) );
}
156 ActivePoolableList &getActivePoolables( void )
{
return mActivePoolables;
}
/** Tells the set whether to allow automatic extension of the pool of objects.
@remarks
A PoolSet stores a pool of pre-constructed queries which are used as needed when
a new object is requested. This allows applications to create / remove objects efficiently
without incurring construction / destruction costs. This method allows you to configure
the behavior when a new object is requested but the object pool has been exhausted.
@par
The default behavior is to allow the pool to extend ( typically this allocates double the current
pool of queries when the pool is expended ), equivalent to calling this method with
autoExtend = true. If you set the parameter to false however, any attempt to create a new pooled object
when the pool has expired will simply fail silently, returning a null pointer.
@param autoextend true to double the pool every time it runs out, false to fail silently.
*/
173 void setAutoextend( bool autoextend )
{
mAutoExtendPool = autoextend;
}
/** Returns true if the object pool automatically extends.
@see
PoolSet::setAutoextend
*/
181 bool getAutoextend( void ) const
{
return mAutoExtendPool;
}
/** Adjusts the size of the pool of object available in this set.
@remarks
See the PoolSet::setAutoextend method for full details of the query pool. This method adjusts
the preallocated size of the pool. If you try to reduce the size of the pool, the set has the option
of ignoring you if too many objects are already in use. Bear in mind that calling this method will
incur significant construction / destruction calls so should be avoided in time-critical code. The same
goes for auto-extension, try to avoid it by estimating the pool size correctly up-front.
@param
size The new size for the pool.
*/
195 void setPoolSize( const unsigned int size )
{
// Never shrink below size( )
const size_t currSize = mPoolablePool.size( );
if( currSize < size )
{
increasePool( size );
for ( size_t i = currSize; i < size; ++i )
{
// Add new items to the queue
mFreePoolables.push_back ( mPoolablePool[i] );
}
mPoolSize = size;
}
}
/** Returns the current size of the object pool.
@returns
The current size of the object pool.
@see
PoolSet::setAutoextend
*/
217 unsigned int getPoolSize( void ) const
{
return static_cast< unsigned int >( mPoolablePool.size( ) );
}
/** Empties this set of all Actives object ( but do not delete them ).
*/
223 void clear( )
{
// Insert actives into free list
mFreePoolables.insert( mFreePoolables.end( ), mActivePoolables.begin( ), mActivePoolables.end( ) );
// Remove all active instances
mActivePoolables.clear( );
}
protected:
/** Active object list.
@remarks
This is a linked list of pointers to objects in the object pool.
@par
This allows very fast insertions and deletions from anywhere in the list to activate / deactivate objects
( required for particle systems etc ) as well as reuse of Poolable instances in the pool
without construction & destruction which avoids memory thrashing.
*/
ActivePoolableList mActivePoolables;
/** Free object queue.
@remarks
This contains a list of the objects free for use as new instances
as required by the set. Poolable instances are pre-constructed up to the estimated size in the
mPoolablePool vector and are referenced on this deque at startup. As they get used this deque
reduces, as they get released back to to the set they get added back to the deque.
*/
FreePoolableList mFreePoolables;
/** Pool of objects instances for use and reuse in the active query list.
@remarks
This vector will be preallocated with the estimated size of the set, and will extend as required.
*/
PoolablePool mPoolablePool;
/// The number of query in the pool.
unsigned int mPoolSize;
/// Flag indicating whether to auto extend pool
bool mAutoExtendPool;
// by how much we will auto extend current pool
Real mAutoExtendFactor;
/// method for increasing pool size
void increasePool( unsigned int size )
{
assert ( size > 0 );
const size_t oldSize = mPoolablePool.size( );
// Increase size
mPoolablePool.reserve( size );
mPoolablePool.resize( size );
// Create new queries
for ( size_t i = oldSize; i < size; ++i )
mPoolablePool[i] = allocate( );
}
protected :
virtual T* allocate( ) = 0;
virtual void deallocate( T* p ) = 0;
};
}
#endif//__OgrePagingLandScapePoolSet_H__
1 /***************************************************************************
OgrePagingLandScapePrecompiledHeaders.cpp - description
-------------------
copyright : ( C ) 2006 Tuan Kuranes
email : tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef _PRECOMP_HEADERS
#define _PRECOMP_HEADERS
#ifdef _PRECOMPILED_HEADERS
#include "OgrePagingLandScapePrerequisites.h"
// -------------------------------------------------------
// Octree Scene Manager ( occlusion management inside )
// -------------------------------------------------------
#include "OgrePagingLandScapeOctreeSceneManager.h"
#include "OgrePagingLandScapeOctreeNode.h"
#include "OgrePagingLandScapeOctree.h"
#include "OgrePagingLandScapeOctreeCamera.h"
#include "OgrePagingLandScapeOctreeAxisAlignedBoxSceneQuery.h"
#include "OgrePagingLandScapeOctreeIntersectionSceneQuery.h"
#include "OgrePagingLandScapeOctreePlaneBoundedVolumeListSceneQuery.h"
#include "OgrePagingLandScapeOctreeRaySceneQuery.h"
#include "OgrePagingLandScapeOctreeSphereSceneQuery.h"
//hardware occlusion management
#include "OgreOcclusionBoundingBox.h"
#include "OgrePagingLandScapeOcclusionQuerySet.h"
#include "OgrePagingLandScapeOcclusionSorter.h"
#include "OgrePagingLandScapeOcclusionTraversal.h"
#include "OgrePagingLandScapeOcclusionCameraTraversal.h"
#include "OgrePagingLandScapeOcclusionDebugTraversal.h"
#include "OgrePagingLandScapeOcclusionCHCTraversal.h"
#include "OgrePagingLandScapeOcclusionSWTraversal.h"
#include "OgrePagingLandScapeOcclusionVFTraversal.h"
#include "OgrePagingLandScapeOcclusion.h"
#include "OgrePagingLandScapeOcclusionElement.h"
#include "OgrePagingLandScapeOcclusionVisibilityData.h"
// -------------------------------------------------------
// Paging Scene Manager
// -------------------------------------------------------
#include "OgrePagingLandScapeSceneManager.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeCamera.h"
#include "OgrePagingLandScapeRaySceneQuery.h"
#include "OgrePagingLandScapeIntersectionSceneQuery.h"
#include "OgrePagingLandScapeAxisAlignedBoxSceneQuery.h"
// Horizon Culling
#include "OgrePagingLandScapeHorizon.h"
// Queues
// pages
#include "OgrePagingLandScapePage.h"
#include "OgrePagingLandScapePageRenderable.h"
#include "OgrePagingLandScapePageManager.h"
// Tile Management ( page is constituted of tiles. )
#include "OgrePagingLandScapeTile.h"
#include "OgrePagingLandScapeTileInfo.h"
#include "OgrePagingLandScapeTileManager.h"
// IndexBuffer Caching to share it across tiles and LOD
#include "OgrePagingLandScapeIndexBuffer.h"
// Texture coordinates buffer cache to share it across pages
#include "OgrePagingLandScapeTextureCoordinatesManager.h"
// Renderable that constitutes tiles
#include "OgrePagingLandScapeRenderable.h"
#include "OgrePagingLandScapeRenderableManager.h"
// Terrain Data Source management
#include "OgrePagingLandScapeData2D.h"
#include "OgrePagingLandScapeData2D_HeightField.h"
#include "OgrePagingLandScapeData2D_HeightFieldTC.h"
#include "OgrePagingLandScapeData2D_HeightFieldN.h"
#include "OgrePagingLandScapeData2D_HeightFieldNTC.h"
#include "OgrePagingLandScapeData2D_HeightFieldRaw.h"
#include "OgrePagingLandScapeData2D_HeightFieldRawTC.h"
#include "OgrePagingLandScapeData2D_Spline.h"
#include "OgrePagingLandScapeData2DManager.h"
// Terrain Texture Source management
#include "OgrePagingLandScapeTexture.h"
#include "OgrePagingLandScapeTexture_Splatting.h"
#include "OgrePagingLandScapeTexture_BaseTexture.h"
#include "OgrePagingLandScapeTextureManager.h"
// User Call back system using listener pattern
#include "OgrePagingLandScapeListenerManager.h"
#include "OgrePagingLandScapeListener.h"
#include "OgrePagingLandScapeCallback.h"
#include "OgrePagingLandScapeCallbackEvent.h"
//decals
#include "OgrePagingLandScapeMeshDecal.h"
//utils
#include "OgrePagingLandscapePoolSet.h"
#include "OgrePagingLandscapeQueue.h"
#include "OgreDebugRectangle2D.h"
#include "fileutils.h"
#endif
#endif //_PRECOMP_HEADERS
1 /***************************************************************************
OgrePagingLandScapePrerequisites.h - description
-------------------
begin : Sun Oct 26 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef __PagingLandScapePrerequisites_H__
#define __PagingLandScapePrerequisites_H__
#include <OgrePrerequisites.h>
#include <OgreHardwareBufferManager.h>
#include <OgreTextureManager.h>
#include <OgreHardwarePixelBuffer.h>
#include <OgreAxisAlignedBox.h>
//-----------------------------------------------------------------------
// Options
//-----------------------------------------------------------------------
//#define _VISIBILITYDEBUG
#if !( OGRE_VERSION < ( ( 1 << 16 ) | ( 3 << 8 ) | 0 ) )
#define PLSM2_EIHORT 1
#endif
//-----------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------
#include <vector>
#include <map>
#include <queue>
#include <list>
#include <stack>
#include <limits>
namespace Ogre
{
// Octree Scene management
typedef std::list < MovableObject* > MovableObjectList;
typedef std::list < Renderable* > RenderableList;
60 class PagingLandScapeOctreeSceneManager;
61 class PagingLandScapeOctreeNode;
typedef std::list<PagingLandScapeOctreeNode*> NodeList;
63 class PagingLandScapeOctree;
64 class PagingLandScapeOctreeCamera;
#ifdef _VISIBILITYDEBUG
67 class DebugRectangle2D;
#endif //_VISIBILITYDEBUG
// hardware occlusion management
71 class QuerySet;
72 class Occlusion;
73 class VisibilityData;
74 class OcclusionElement;
75 class Between;
76 class Leaf;
typedef enum culling_modes
{
// STANDARD_WALK = 0,
// VIEW_FRUSTUM,
VIEW_FRUSTUM_DIRECT,
//STOP_AND_WAIT,
CHC,
CHC_CONSERVATIVE,
NUM_CULLING_MODE
};
89 class OcclusionBoundingBox;
typedef std::list<OcclusionElement*> OcclusionElementList;
typedef std::list<PagingLandScapeOctreeNode*> PagingLandScapeOctreeNodeList;
93 class FrontToBackNodeSorterOperator;
//priority queue for the nodes to traversal
typedef std::priority_queue<OcclusionElement*, std::vector<OcclusionElement*>, FrontToBackNodeSorterOperator> FrontToBackNodeSorterPriorityQueue;
//queue for the nodes with running occlusion queries
typedef std::queue<OcclusionElement*> QueriedOcclusionElement; //queue for the nodes with running occlusion queries
100 class Traversal;
101 class TraversalConst;
102 class ConstTraversalConst;
104 class CHCTraversal;
105 class SWTraversal;
106 class ViewFrustumCullingTraversal;
107 class ViewFrustumCullingTraversalDirect;
108 class TreeOverlayDebug;
// Paging Scene Management
116 class PagingLandScapeSceneManager;
117 class PagingLandScapeOptions;
118 class PagingLandScapeCamera;
typedef std::list< PagingLandScapeCamera* > PagingLandScapeCameraList;
121 class PagingLandScapeRaySceneQuery;
// Basic Horizon Culling ( based on tile max and min height )
124 class PagingLandScapeHorizon;
// Page Scene Management
127 class PagingLandScapePage;
128 class PagingLandScapePageRenderable;
129 class PagingLandScapePageManager;
#define PAGE_INSIDE 0x00000001
#define PAGE_CHANGE 0x00000002
#define PAGE_OUTSIDE 0x00000004
typedef enum PageState
{
inited,
Preloaded,
Textureloaded,
Loaded
};
typedef enum PageQueuingState
{
queuednone,
queuedPreload,
queuedTextureLoad,
queuedLoad
};
typedef std::list< PagingLandScapePage* > PagingLandScapePageList;
typedef std::vector< PagingLandScapePage* > PagingLandScapePageArray;
typedef PagingLandScapePageArray PagingLandScapePageRow;
typedef std::vector< PagingLandScapePageRow > PagingLandScapePages;
// Tile Management ( page is constituted of tiles. )
158 class PagingLandScapeTile;
159 class PagingLandScapeTileInfo;
160 class PagingLandScapeTileManager;
typedef std::list< PagingLandScapeTile* > PagingLandScapeTileList;
typedef std::vector< PagingLandScapeTile* > PagingLandScapeTileRow;
typedef std::vector< PagingLandScapeTileRow > PagingLandScapeTiles;
// IndexBuffer Caching to share it across tiles and LOD
167 class PagingLandScapeIndexBufferManager;
typedef std::map< unsigned int, IndexData* > IndexMap;
typedef std::vector< IndexData* > IndexArray;
typedef std::vector< IndexMap* > LevelArray;
// Renderable that constitutes tiles
173 class PagingLandScapeRenderable;
174 class PagingLandScapeRenderableSet;
175 class PagingLandScapeRenderableManager;
typedef std::vector< PagingLandScapeRenderable* > PagingLandScapeRenderableVector;
// Texture coordinates buffer cache
179 class PagingLandScapeTextureCoordinatesManager;
// Terrain Data Source management
182 class PagingLandScapeData2D;
183 class PagingLandScapeData2DManager;
typedef std::vector< PagingLandScapeData2D* > PagingLandScapeData2DArray;
typedef std::list< PagingLandScapeData2D* > PagingLandScapeData2DList;
typedef std::vector< PagingLandScapeData2D* > PagingLandScapeData2DRow;
typedef std::vector< PagingLandScapeData2DRow > PagingLandScapeData2DPages;
typedef std::vector<PagingLandScapeData2D*> PagingLandScapeData2DMap;
// Terrain Texture Source management
193 class PagingLandScapeTexture;
194 class PagingLandScapeTextureManager;
typedef std::vector< PagingLandScapeTexture* > PagingLandScapeTextureArray;
typedef std::list< PagingLandScapeTexture* > PagingLandScapeTextureList;
typedef std::vector< PagingLandScapeTexture* > PagingLandScapeTextureRow;
typedef std::vector< PagingLandScapeTextureRow > PagingLandScapeTexturePages;
typedef std::vector<PagingLandScapeTexture*> PagingLandScapeTextureMap;
typedef std::vector< HardwareVertexBufferSharedPtr> HardwareTextureBuffersRow;
typedef std::vector< HardwareTextureBuffersRow> HardwareTextureBuffersCol;
// User Call back system using listener pattern
209 class PagingLandScapeListenerManager;
210 class PagingLandScapeListener;
211 class PagingLandscapeEvent;
// Multi-map management
typedef std::map< String, String > LandScapeFileNames;
// Vertex Shader Hardware Morphing
#define MORPH_CUSTOM_PARAM_ID 77
// LOD
enum Neighbor
{
NORTH = 0,
SOUTH,
EAST,
WEST
};
#define STITCH_NORTH_SHIFT 0
#define STITCH_SOUTH_SHIFT 8
#define STITCH_WEST_SHIFT 16
#define STITCH_EAST_SHIFT 24
#define STITCH_NORTH 128 << STITCH_NORTH_SHIFT
#define STITCH_SOUTH 128 << STITCH_SOUTH_SHIFT
#define STITCH_WEST 128 << STITCH_WEST_SHIFT
#define STITCH_EAST 128 << STITCH_EAST_SHIFT
}
//-----------------------------------------------------------------------
// Windows Settings
//-----------------------------------------------------------------------
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
# ifdef PLUGIN_PAGINGLANDSCAPE2_EXPORTS
# define _OgrePagingLandScapeExport __declspec( dllexport )
# else
# define _OgrePagingLandScapeExport __declspec( dllimport )
# endif
#else
# define _OgrePagingLandScapeExport
#endif
//STL trick to call delete in a for_each
struct delete_object
{
256 template <typename T>
void operator( )( T *ptr ){ delete ptr; ptr = 0;}
};
#ifndef ogre_restrict
#ifdef __INTEL_COMPILER
#define ogre_restrict restrict
#elif _MSC_VER >= 1400
#define ogre_restrict __restrict
#else
#define ogre_restrict
#endif
#endif
// DEBUGGING
#ifdef _PLSM2_RELEASE_ASSERT
#undef assert
extern "C"
{
278 _CRTIMP void __cdecl _assert( const char*, const char*, unsigned );
}
#define assert( exp ) ( void )( ( exp ) || ( _assert( #exp, __FILE__, __LINE__ ), 0 ) )
#endif //_PLSM2_RELEASE_ASSERT
#endif //__PagingLandScapePrerequisites_H__
/***************************************************************************
OgrePagingLandScapeQueue.h - description
-------------------
begin : Mon Aug 04 2003
copyright : ( C ) 2003 by Jose A. Milan
email : spoke2@supercable.es
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLANDSCAPEQUEUE_H
#define PAGINGLANDSCAPEQUEUE_H
#include <queue>
#include <list>
#include "Ogre.h"
#include "OgreSceneNode.h"
#include "OgreVector3.h"
namespace Ogre
{
//-----------------------------------------------------------------------
32 inline Real vectorToBoxDistance( const AxisAlignedBox &bbox, const Vector3& point )
{
const Vector3 &boxMin = bbox.getMinimum ( );
const Vector3 halfSize ( ( bbox.getMaximum ( ) - boxMin ) * 0.5 );
// work in the box's coordinate system
const Vector3 kDiff ( point - ( halfSize + boxMin ) );
// compute squared distance and closest point on box
Real fSqrDistance ( 0.0 );
for ( unsigned int i = 0; i < 3; i++ )
{
const Real kClosest = kDiff[i];
const Real khalfSize = halfSize[i];
if ( kClosest < -khalfSize )
{
const Real fDelta = kClosest + khalfSize;
fSqrDistance += fDelta * fDelta;
}
else if ( kClosest > khalfSize )
{
const Real fDelta = kClosest - khalfSize;
fSqrDistance += fDelta * fDelta;
}
}
return fSqrDistance;
}
//-----------------------------------------------------------------------
template <class T>
59 class distanceToBoxSort
{
public:
//-----------------------------------------------------------------------
63 distanceToBoxSort( const Vector3 &camPos ) : mCamPos( camPos )
{};
//-----------------------------------------------------------------------
66 bool operator( )( T* x, T* y )
{
return ( x->getCenter( ) - mCamPos ).squaredLength( ) <
( y->getCenter( ) - mCamPos ).squaredLength( );
//return vectorToBoxDistance ( x->getWorldBbox( ), mCamPos ) <
// vectorToBoxDistance ( y->getWorldBbox( ), mCamPos );
}
private:
76 const Vector3 mCamPos;
};
//-----------------------------------------------------------------------
/** This class holds classes T given to it by the plugin in a FIFO queue. */
template<class T>
81 class PagingLandScapeQueue
{
public:
//typedef std::queue<T *, std::list<T *> > MsgQueType;
typedef std::list<T *> MsgQueType;
//-----------------------------------------------------------------------
90 PagingLandScapeQueue( )
{
};
//-----------------------------------------------------------------------
94 virtual ~PagingLandScapeQueue( )
{
mQueue.clear ( );
};
//-----------------------------------------------------------------------
99 void clear ( )
{
mQueue.clear ( );
};
//-----------------------------------------------------------------------
104 void push( T* e )
{
assert ( std::find( mQueue.begin( ), mQueue.end( ), e ) == mQueue.end( ) );
// Insert the element at the end of the queue
mQueue.push_back ( e );
};
//-----------------------------------------------------------------------
typename MsgQueType::iterator begin( )
{
return mQueue.begin ( );
};
//-----------------------------------------------------------------------
typename MsgQueType::iterator end( )
{
118 return mQueue.end ( );
};
//-----------------------------------------------------------------------
typename MsgQueType::iterator erase( typename MsgQueType::iterator it )
{
123 return mQueue.erase ( it );
};
//-----------------------------------------------------------------------
void remove ( T* e )
{
mQueue.remove ( e );
};
//-----------------------------------------------------------------------
void sortNearest( const Vector3 &pos )
{
mQueue.sort ( distanceToBoxSort <T>( pos ) );
};
//-----------------------------------------------------------------------
T *find_nearest( const Vector3 &pos )
{
T *p = 0;
Real mindist = std::numeric_limits<Real>::max ( );
typename MsgQueType::iterator q, qend = mQueue.end ( );
for ( q = mQueue.begin ( );
q != qend;
++q )
{
const Real res = ( pos - ( *q )->getCenter( ) ).squaredLength( );
//const Real res = vectorToBoxDistance ( ( *q )->getSceneNode( )->_getWorldAABB( ), pos );
if ( res < mindist )
{
mindist = res;
p = ( *q );
}
}
if ( p )
mQueue.remove ( p );
return p;
};
//-----------------------------------------------------------------------
T *find_nearest( const unsigned int x, const unsigned int z )
{
T *p = 0;
unsigned int mindist = 0;
typename MsgQueType::iterator q, qend = mQueue.end ( );
for ( q = mQueue.begin ( );
q != qend;
++q )
{
unsigned int lx, lz;
( *q )->getCoordinates( lx, lz );
const unsigned int res = abs ( static_cast <int> ( lx - x ) ) + abs ( static_cast <int> ( lz - z ) );
if ( res < mindist )
{
mindist = res;
p = ( *q );
}
}
if ( p )
mQueue.remove ( p );
return p;
};
//-----------------------------------------------------------------------
T *find_farest( const unsigned int x, const unsigned int z )
{
T *p = 0;
unsigned int maxdist = -1;
typename MsgQueType::iterator q, qend = mQueue.end ( );
for ( q = mQueue.begin ( );
q != qend;
++q )
{
unsigned int lx, lz;
( *q )->getCoordinates( lx, lz );
const unsigned int res = abs ( ( int )( lx - x ) ) + abs ( ( int )( lz - z ) );
if ( res > maxdist )
{
maxdist = res;
p = ( *q );
}
}
if ( p )
mQueue.remove ( p );
return p;
};
//-----------------------------------------------------------------------
T* pop( )
{
T* tmp = 0;
if ( !mQueue.empty ( ) )
{
// Queue is not empty so get a pointer to the
// first message in the queue
tmp = mQueue.front( );
// Now remove the pointer from the message queue
mQueue.pop_front( );
}
return tmp;
};
//-----------------------------------------------------------------------
size_t getSize( ) const
{
return mQueue.size ( );
};
//-----------------------------------------------------------------------
bool empty( ) const
{
return mQueue.empty( );
};
//-----------------------------------------------------------------------
MsgQueType *getQueue( )
{
return &mQueue;
}
protected:
MsgQueType mQueue;
};
} //namespace
#endif //PAGINGLANDSCAPEQUEUE_H
1 /***************************************************************************
OgrePagingLandScapeRaySceneQuery.h - description
-------------------
begin : Fri Sep 10 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeRAYSCENEQUERY_H
#define PAGINGLandScapeRAYSCENEQUERY_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeOctreeRaySceneQuery.h"
namespace Ogre
{
/** PagingLandScape's specialisation of RaySceneQuery.
if RSQ_Height bit mask is set, RSQ_Terrain and RSQ_Entity bits will be ignored
Otherwise data will be returned based on the mask
*/
32 class PagingLandScapeRaySceneQuery : public PagingLandScapeOctreeRaySceneQuery
{
public:
36 PagingLandScapeRaySceneQuery( SceneManager* creator ) : PagingLandScapeOctreeRaySceneQuery( creator )
{
mSupportedWorldFragments.insert( SceneQuery::WFT_SINGLE_INTERSECTION );
//mLastResult = new RaySceneQueryResult( );
}
// virtual ~PagingLandScapeRaySceneQuery( void )
// {
// clearFragmentList( );
// //delete mLastResult;
// //mLastResult = 0;
// }
/** See RaySceneQuery. */
50 void execute( RaySceneQueryListener * listener );
/** Executes the query, returning the results back in one list.
@remarks
This method executes the scene query as configured, gathers the results
into one structure and returns a reference to that structure. These
results will also persist in this query object until the next query is
executed, or clearResults( ) is called. An more lightweight version of
this method that returns results through a listener is also available.
*/
//virtual RaySceneQueryResult& execute( void );
//void clearResults( void );
protected:
//JEFF
//PagingLandScapeTile* getNonDividedTile( PagingLandScapeTile* tile, const Vector3& origin );
66 inline Vector3 getHeightAt( const Vector3& origin ) const;
//std::vector< SceneQuery::WorldFragment* > fragmentList;
// void clearFragmentList( void )
// {
// std::vector< SceneQuery::WorldFragment* >::iterator cur, end = fragmentList.end( );
// for ( cur = fragmentList.begin( ); cur < end; ++cur )
// {
// SceneQuery::WorldFragment* frag = ( *cur );
// if ( frag )
// {
// delete frag;
// frag = 0;
// }
// }
// fragmentList.clear( );
// }
private:
86 WorldFragment mWorldFrag;
};
} // namespace Ogre
#endif
1 /***************************************************************************
OgrePagingLandScapeRenderable.h - description
-------------------
begin : Thu Feb 27 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeRENDERABLE_H
#define PAGINGLandScapeRENDERABLE_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
/** Represents a LandScape tile in terms of vertexes.
@remarks
A LandScapeRenderable represents a tile used to render a
block of LandScape using the procedural terrain approach for LOD.
*/
33 class PagingLandScapeRenderable : public Renderable, public MovableObject
{
public:
/** Sets the appropriate neighbor for this TerrainRenderable. Neighbors are necessary
to know when to bridge between LODs.
*/
40 void _setNeighbor( Neighbor n, PagingLandScapeRenderable* t )
{
mNeighbors[ n ] = t;
};
/** Returns the neighbor TerrainRenderable.
*/
47 PagingLandScapeRenderable* _getNeighbor( Neighbor n ) const
{
return mNeighbors[ n ];
}
/** Returns RenderLevel of current TerrainRenderable.
*/
54 int getRenderLevel( ) const
{
return mRenderLevel < 0 ? 0 : mRenderLevel;
}
/// The current LOD level
int mRenderLevel;
// if a neighbour changes its RenderLevel.
// get a new Index buffer.
64 void update( );
/** Initializes the LandScapeRenderable with the given options and the starting coordinates of this block.
*/
68 PagingLandScapeRenderable( PagingLandScapeRenderableManager *renderableMgr );
70 ~PagingLandScapeRenderable( void );
72 void init( PagingLandScapeTileInfo* info );
73 void uninit( void );
75 bool load( void );
77 void setNeedUpdate( void )
{
mNeedReload = true;
};
81 void adjustDeformationRectangle( unsigned int x, unsigned int z );
83 void unload( void );
85 void setMaterial( const MaterialPtr& mat );
87 const bool isLoaded( void )
{
assert ( ( mIsLoaded && mParentNode ) || ( !mIsLoaded && mParentNode == 0 ) );
return mIsLoaded;
};
93 const Real getMaxHeight( void )
{
return ( mBounds.getMaximum( ) ).y;
};
98 inline void setInUse ( bool InUse )
{
mInUse = InUse;
}
/////////Movable overridden object methods
/** Updates the level of detail to be used for rendering this TerrainRenderable based on the passed in Camera */
106 virtual void _notifyCurrentCamera( Camera* cam );
108 virtual void _updateRenderQueue( RenderQueue* queue );
/** Returns the type of the movable. */
111 virtual const String& getMovableType( void ) const
{
return mType;
};
/** Returns the bounding box of this TerrainRenderable */
117 const AxisAlignedBox& getBoundingBox( void ) const
{
return mBounds;
};
/////////Renderable object methods
/**
Constructs a RenderOperation to render the TerrainRenderable.
@remarks
Each TerrainRenderable has a block of vertices that represent the terrain. Index arrays are dynamically
created for mipmap level, and then cached.
*/
129 virtual void getRenderOperation( RenderOperation& rend );
131 virtual const MaterialPtr& getMaterial( void ) const
{
return mMaterial;
};
136 virtual void getWorldTransforms( Matrix4* xform ) const;
138 virtual const Quaternion& getWorldOrientation( void ) const;
139 virtual const Vector3& getWorldPosition( void ) const;
/** @copydoc Renderable::getLights */
142 const LightList& getLights( void ) const;
144 virtual Technique* getTechnique( void ) const;
146 virtual Real getSquaredViewDepth( const Camera* cam ) const;
/** Overridden from MovableObject */
149 Real getBoundingRadius( void ) const { return mBoundingRadius; }
/// Overridden from Renderable to allow the morph LOD entry to be set
152 void _updateCustomGpuParameter( const GpuProgramParameters::AutoConstantEntry& constantEntry, GpuProgramParameters* params ) const;
154 void setMaxLod ( const bool setmaxlod ) {mForcedMaxLod = setmaxlod;};
/// @see MovableObject
157 uint32 getTypeFlags( void ) const;
/** Internal method called to notify the object that it has been attached to a node.
*/
161 virtual void _notifyAttached( Node* parent, bool isTagPoint = false );
163 bool isInUse( ) const {return mInUse;};
165 IndexData* getRawIndexData( const int renderlevel );
166 void getRawVertexData( Vector3* pVerts );
167 const unsigned int getVertexCount( );
169 bool mQueued;
170 PagingLandScapeTile *mParentTile;
protected:
175 VertexData* mCurrVertexes;
176 IndexData* mCurrIndexes;
/// Bounding box of this tile
179 AxisAlignedBox mBounds;
/// The center point of this tile
181 Vector3 mCenter;
/// The MovableObject type
183 static String mType;
/// Current material used by this tile
185 MaterialPtr mMaterial;
/// Connection to tiles four neighbors
PagingLandScapeRenderable* mNeighbors [ 4 ];
190 IndexData*mIndex;
unsigned int mNumIndex;
193 bool mInUse;
194 bool mIsLoaded;
195 bool mNeedReload;
197 ushort mMaterialLODIndex;
// for loading
200 PagingLandScapeTileInfo* mInfo;
// Morph
/** Returns the vertex coord for the given coordinates */
204 inline Real _vertex( const int x, const int z, const int n ) const;
205 Real* mHeightfield;
/// The previous 'next' LOD level down, for frame coherency
int mLastNextLevel;
/// The morph factor between this and the next LOD level down
209 Real mLODMorphFactor;
/// List of squared distances at which LODs change
212 std::vector<Real>* mMinLevelDistSqr;
/// Optional set of delta buffers, used to morph from one LOD to the next
215 HardwareVertexBufferSharedPtr* mDeltaBuffers;
/// Array of LOD indexes specifying which LOD is the next one down
/// ( deals with clustered error metrics which cause LODs to be skipped )
int mNextLevelDown[10];
// distance between center renderable and camera.
222 Real mDistanceToCam;
224 void fillNextLevelDown( );
225 void _calculateMinLevelDist2( const Real C );
/// Create a blank delta buffer for use in morphing
227 HardwareVertexBufferSharedPtr createDeltaBuffer( void ) const;
// did LOD level changes this frame
230 bool mChangedRenderLevel;
232 Vector3 _getvertex( const int x, const int z ) const;
234 PagingLandScapeRenderableManager *mParent;
/// The bounding radius of this renderable
237 Real mBoundingRadius;
private :
241 Image::Box mRect;
242 bool mIsRectModified;
243 bool mForcedMaxLod;
244 Vector4 mCustomGpuParameters;
/// Whether light list need to re-calculate
mutable bool mLightListDirty;
/// Cached light list
mutable LightList mLightList;
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeRenderableManager.h - description
-------------------
begin : Mon Jun 16 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeRENDERABLEMANAGER_H
#define PAGINGLandScapeRENDERABLEMANAGER_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeQueue.h"
#include "OgrePagingLandScapeIndexBuffer.h"
#include "OgrePagingLandScapeTileInfo.h"
#include "OgrePagingLandScapePoolSet.h"
namespace Ogre
{
/** Class to manage A collection of pre-allocated PagingLandScapeRenderable
*/
36 class PagingLandScapeRenderableSet : public PoolSet<PagingLandScapeRenderable>
{
public:
40 PagingLandScapeRenderableSet( );
41 void setRenderableManager ( PagingLandScapeRenderableManager *rMgr )
{
mRenderableManager = rMgr;
}
protected:
47 PagingLandScapeRenderable* allocate ( );
48 void deallocate ( PagingLandScapeRenderable *r );
private:
52 PagingLandScapeRenderableManager *mRenderableManager;
};
/** Class to manage the PagingLandScapeRenderables ( Pool and Loading Queue )
@remarks
This class is used as a store of PagingLandScapeRenderables and the are reference and dereference in order to not being created and
destroyed every time the plug-in need to change the LOD.
*/
60 class PagingLandScapeRenderableManager
{
public:
/** Initializes the PagingLandScapeRenderableManager with the
* given options and allocate the necessary memory.
*/
66 PagingLandScapeRenderableManager ( PagingLandScapeSceneManager * scnMgr );
68 virtual ~PagingLandScapeRenderableManager( void );
/** Retrieve a free renderable.
*/
72 PagingLandScapeRenderable* getRenderable( void );
/** Make a renderable free.
*/
76 void freeRenderable( PagingLandScapeRenderable* rend );
/** Set this renderable to be loaded
*/
80 void queueRenderableLoading( PagingLandScapeTile* tile );
/** Set this renderable to be unloaded
*/
84 void unqueueRenderable( PagingLandScapeTile* tile );
/** Load a set of renderables
*/
88 bool executeRenderableLoading( const Vector3 &Cameraposition );
90 size_t numRenderables( void ) const;
91 size_t numFree( void ) const;
92 size_t numLoading( void ) const;
94 void InitTextureCoordinatesBuffers( void );
95 void freeTextureCoordinatesBuffers( void );
96 HardwareVertexBufferSharedPtr getTextureCoordinatesBuffers( const unsigned int tilex, const unsigned int tilez );
97 void setTextureCoordinatesBuffers( const unsigned int tilex, const unsigned int tilez, const HardwareVertexBufferSharedPtr& data );
99 unsigned int numVisibles( void ) const
{
return mLastRenderablesVisibles;
};
103 void resetVisibles( void )
{
mLastRenderablesVisibles = mRenderablesVisibles;
mRenderablesVisibles = 0;
};
108 void addVisible( void )
{
mRenderablesVisibles++;
};
114 void load( void );
115 void clear( void );
/// unload some Tiles/renderables if no more in use
118 void processTileUnload( );
120 inline PagingLandScapeOptions* getOptions( ){return mOptions;}
121 inline PagingLandScapeSceneManager* getSceneManager( ){return mSceneManager;}
protected:
124 PagingLandScapeOptions* mOptions;
125 PagingLandScapeSceneManager *mSceneManager;
128 void _addBatch( const unsigned int num );
///Keep a set of pre-allocated PagingLandscapeRenderables.
132 PagingLandScapeRenderableSet mRenderablePool;
/** Queue to batch the process of loading the Renderables.
This avoid the plug-in to load a lot of renderables in a single Frame,
dropping the FPS.
*/
138 PagingLandScapeQueue< PagingLandScapeTile > mTilesLoadRenderableQueue;
unsigned int mRenderablesVisibles;
unsigned int mLastRenderablesVisibles;
unsigned int mNumRenderablesIncrement;
unsigned int mNumRenderableLoading;
unsigned int mRenderableLoadInterval;
int mLoadInterval;
};
}
#endif
/***************************************************************************
OgrePagingLandScapeSceneManager.h - description
-------------------
begin : Mon May 12 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeSCENEMANAGER_H
#define PAGINGLandScapeSCENEMANAGER_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeOctreeSceneManager.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgreStringVector.h"
#include "OgrePagingLandScapeData2DManager.h"
namespace Ogre
{
/// Factory for OctreeSceneManager
32 class PagingLandScapeSceneManagerFactory : public SceneManagerFactory
{
protected:
35 void initMetaData( void ) const;
public:
37 PagingLandScapeSceneManagerFactory( ) {}
38 ~PagingLandScapeSceneManagerFactory( ) {}
/// Factory type name
40 static const String FACTORY_TYPE_NAME;
41 SceneManager* createInstance( const String& instanceName );
42 void destroyInstance( SceneManager* instance );
};
/** This is a basic SceneManager for organizing PagingLandScapeRenderables into a total LandScape.
It loads a LandScape from a .cfg file that specifies what textures/scale/mipmaps/etc to use.
*/
50 class PagingLandScapeSceneManager : public PagingLandScapeOctreeSceneManager
{
52 friend class PagingLandScapeRaySceneQuery;
public:
54 PagingLandScapeSceneManager( const String &name );
55 ~PagingLandScapeSceneManager( void );
57 void shutdown( );
/// @copydoc SceneManager::getTypeName
59 const String& getTypeName( void ) const;
/** Creates a specialized Camera */
62 virtual Camera * createCamera( const String &name );
63 virtual void destroyCamera( Camera *cam );
64 virtual void destroyCamera( const String& name );
65 virtual void destroyAllCameras( void );
/** Sets the source of the 'world' geometry, i.e. the large, mainly static geometry
making up the world e.g. rooms, LandScape etc.
@remarks
Depending on the type of SceneManager ( subclasses will be specialised
for particular world geometry types ) you have requested via the Root or
SceneManagerEnumerator classes, you can pass a filename to this method and it
will attempt to load the world-level geometry for use. If you try to load
an inappropriate type of world data an exception will be thrown. The default
SceneManager cannot handle any sort of world geometry and so will always
throw an exception. However subclasses like BspSceneManager can load
particular types of world geometry e.g. "q3dm1.bsp".
*/
79 virtual void setWorldGeometry( const String& filename );
/** Sets the source of the 'world' geometry, i.e. the large, mainly
static geometry making up the world e.g. rooms, LandScape etc.
@remarks
Depending on the type of SceneManager ( subclasses will be
specialised for particular world geometry types ) you have
requested via the Root or SceneManagerEnumerator classes, you
can pass a stream to this method and it will attempt to load
the world-level geometry for use. If the manager can only
handle one input format the typeName parameter is not required.
The stream passed will be read ( and it's state updated ).
@param stream Data stream containing data to load
@param typeName String identifying the type of world geometry
contained in the stream - not required if this manager only
supports one type of world geometry.
*/
96 virtual void setWorldGeometry( DataStreamPtr& stream,
const String& typeName = StringUtil::BLANK );
/** Things that need to be allocated once
*/
102 void InitScene( void );
/** Empties the entire scene, including all SceneNodes, Cameras, Entities and Lights etc.
*/
106 void clearScene( void );
/** Empties only the Terrain Scene pages, tiles, textures and so on
*/
110 void resetScene( void );
/** Loads the LandScape using current parameters
*/
114 void loadScene( void );
/** Method for setting a specific option of the Scene Manager. These options are usually
specific for a certain implementation of the Scene Manager class, and may ( and probably
will ) not exist across different implementations.
@param
strKey The name of the option to set
@param
pValue A pointer to the value - the size should be calculated by the scene manager
based on the key
@return
On success, true is returned.
@par
On failure, false is returned.
*/
129 bool setOption( const String& strKey, const void* pValue );
/** Method for getting the value of an implementation-specific Scene Manager option.
@param
strKey The name of the option
@param
pDestValue A pointer to a memory location where the value will
be copied. Currently, the memory will be allocated by the
scene manager, but this may change
@return
On success, true is returned and pDestValue points to the value of the given
option.
@par
On failiure, false is returned and pDestValue is set to NULL.
*/
144 bool getOption( const String& strKey, void* pDestValue );
/** Method for verifying wether the scene manager has an implementation-specific
option.
@param
strKey The name of the option to check for.
@return
If the scene manager contains the given option, true is returned.
@remarks
If it does not, false is returned.
*/
155 bool hasOption( const String& strKey ) const;
/** Method for getting all possible values for a specific option. When this list is too large
( i.e. the option expects, for example, aOgre::Real ), the return value will be true, but the
list will contain just one element whose size will be set to 0.
Otherwise, the list will be filled with all the possible values the option can
accept.
@param
strKey The name of the option to get the values for.
@param
refValueList A reference to a list that will be filled with the available values.
@return
On success ( the option exists ), true is returned.
@par
On failiure, false is returned.
*/
171 bool getOptionValues( const String& key, StringVector& refValueList );
/** Method for getting all the implementation-specific options of the scene manager.
@param
refKeys A reference to a list that will be filled with all the available options.
@return
On success, true is returned.
On failiure, false is returned.
*/
180 bool getOptionKeys( StringVector &refKeys );
/** Internal method for updating the scene graph ie the tree of SceneNode instances managed by this class.
@remarks
This must be done before issuing objects to the rendering pipeline, since derived transformations from
parent nodes are not updated until required. This SceneManager is a basic implementation which simply
updates all nodes from the root. This ensures the scene is up to date but requires all the nodes
to be updated even if they are not visible. Subclasses could trim this such that only potentially visible
nodes are updated.
*/
190 void _updateSceneGraph( Camera* cam );
/** Sends visible objects found in _findVisibleObjects to the rendering engine.
*/
//void _renderVisibleObjects( void );
/** Internal method which parses the scene to find visible objects to render.
@remarks
If you're implementing a custom scene manager, this is the most important method to
override since it's here you can apply your custom world partitioning scheme. Once you
have added the appropriate objects to the render queue, you can let the default
SceneManager objects _renderVisibleObjects handle the actual rendering of the objects
you pick.
@par
Any visible objects will be added to a rendering queue, which is indexed by material in order
to ensure objects with the same material are rendered together to minimise render state changes.
*/
//void _findVisibleObjects( Camera * cam, bool onlyShadowCasters );
/** Creates an AxisAlignedBoxSceneQuery for this scene manager.
@remarks
This method creates a new instance of a query object for this scene manager,
for an axis aligned box region. See SceneQuery and AxisAlignedBoxSceneQuery
for full details.
Currently this only supports custom geometry results. It ignores the y
coords of the AABB.
@par
The instance returned from this method must be destroyed by calling
SceneManager::destroyQuery when it is no longer required.
@param box Details of the box which describes the region for this query.
@param mask The query mask to apply to this query; can be used to filter out
certain objects; see SceneQuery for details.
*/
223 AxisAlignedBoxSceneQuery* createAABBQuery( const AxisAlignedBox& box, unsigned long mask = 0xFFFFFFFF );
/** Creates a RaySceneQuery for this scene manager.
@remarks
This method creates a new instance of a query object for this scene manager,
looking for objects which fall along a ray. See SceneQuery and RaySceneQuery
for full details.
@par
The instance returned from this method must be destroyed by calling
SceneManager::destroyQuery when it is no longer required.
@param ray Details of the ray which describes the region for this query.
@param mask The query mask to apply to this query; can be used to filter out
certain objects; see SceneQuery for details.
*/
238 RaySceneQuery* createRayQuery( const Ray& ray, unsigned long mask = 0xFFFFFFFF );
/** Creates an IntersectionSceneQuery for this scene manager.
@remarks
This method creates a new instance of a query object for locating
intersecting objects. See SceneQuery and IntersectionSceneQuery
for full details.
@par
The instance returned from this method must be destroyed by calling
SceneManager::destroyQuery when it is no longer required.
@param mask The query mask to apply to this query; can be used to filter out
certain objects; see SceneQuery for details.
*/
//IntersectionSceneQuery* createIntersectionQuery( unsigned long mask );
/** intersectSegment
@remarks
Intersect mainly with LandScape
@param start
begining of the segment
@param end
where it ends
@param result
where it intersects with terrain
*/
263 bool intersectSegment( const Ogre::Vector3& start, const Ogre::Vector3& end, Ogre::Vector3* result );
/** intersectSegment
@remarks
Intersect mainly with LandScape
@param start
begining of the segment
@param dir
direction of the ray
@param result
where it intersects with terrain
*/
275 bool intersectSegmentTerrain( const Ogre::Vector3& begin, const Ogre::Vector3& dir, Ogre::Vector3* result );
/** load
* @remarks load heights only LandScape, need brush and brush scale to be set before
* @param &impact where load take place, where BrushArray is centered
*/
280 void setHeight ( const Ogre::Vector3 &impact );
/** deform
* @remarks deform only LandScape, need brush and brush scale to be set before
* @param &impact where deformation take place, where BrushArray is centered
*/
285 void deformHeight( const Ogre::Vector3& impact );
/** paint
* @remarks paint only LandScape, need channel, brush and brush scale to be set before
* @param impact where painting take place
* @param isAlpha if we want to paint alpha or color
*/
291 void paint ( const Ogre::Vector3 &impact );
/** getAreaHeight
* @remarks used to fill user allocated array with values.
* @param impact where array is centered
*/
296 void getAreaHeight( const Ogre::Vector3& impact );
/** renderBaseTextures( )
* @remarks Performs render to texture for all pages to create base textures from
* splatting shader. If alternate material is specified, will use it instead of
* the actual material assigned to the page. This is necessary when terrain is lit
* and/or compressed.
*/
304 void renderBaseTextures( const String& alternateMatName );
/** Overridden from SceneManager */
307 void setWorldGeometryRenderQueue( uint8 qid );
309 void PagingLandScapeOctreeResize( void );
311 void WorldDimensionChange( void );
//-----------------------------------------------------------------------
inline Ogre::Real _OgrePagingLandScapeExport getHeightAt( const Ogre::Real x, const Ogre::Real z )
{
return mData2DManager->getInterpolatedWorldHeight( x, z );
}
//-----------------------------------------------------------------------
inline Ogre::Real _OgrePagingLandScapeExport getSlopeAt( const Ogre::Real x, const Ogre::Real z )
{
Ogre::Real slope;
// return mData2DManager->getRealWorldSlope( x, z );
323 mData2DManager->getInterpolatedWorldHeight( x, z, &slope );
return slope;
}
327 _OgrePagingLandScapeExport void getWorldSize( Real *worldSizeX, Ogre::Real *worldSizeZ );
328 _OgrePagingLandScapeExport float getMaxSlope( Vector3 location1, Ogre::Vector3 location2, float maxSlopeIn );
330 inline PagingLandScapeOptions * getOptions( )
{
assert( mOptions );
return mOptions;
}
336 inline PagingLandScapeHorizon * getHorizon( )
{
assert( mHorizon );
return mHorizon;
}
341 inline PagingLandScapeTileManager * getTileManager( )
{
assert( mTileManager );
return mTileManager;
}
346 inline PagingLandScapePageManager * getPageManager( )
{
assert( mPageManager );
return mPageManager;
}
351 inline PagingLandScapeData2DManager * getData2DManager( )
{
assert( mData2DManager );
return mData2DManager;
}
356 inline PagingLandScapeListenerManager * getListenerManager( )
{
assert( mListenerManager );
return mListenerManager;
}
361 inline PagingLandScapeTextureManager * getTextureManager( )
{
assert( mTextureManager );
return mTextureManager;
}
366 inline PagingLandScapeIndexBufferManager * getIndexesManager( )
{
assert( mIndexesManager );
return mIndexesManager;
}
371 inline PagingLandScapeRenderableManager * getRenderableManager( )
{
assert( mRenderableManager );
return mRenderableManager;
}
376 inline PagingLandScapeTextureCoordinatesManager* getTextureCoordinatesManager( )
{
assert( mTexCoordManager );
return mTexCoordManager;
}
381 inline PagingLandScapeIndexBufferManager* getIndexBufferManager( )
{
assert( mIndexesManager );
return mIndexesManager;
}
protected:
// EntityList& getEntities( void )
// {
// return mEntities;
// }
/** All the plugin options are handle here.
*/
PagingLandScapeOptions* mOptions;
/** LandScape 2D Data manager.
This class encapsulate the 2d data loading and unloading
*/
PagingLandScapeData2DManager* mData2DManager;
/** LandScape Texture manager.
This class encapsulate the texture loading and unloading
*/
PagingLandScapeTextureManager* mTextureManager;
/** LandScape tiles manager to avoid creating a deleting terrain tiles.
They are created at the plugin start and destroyed at the plugin unload.
*/
PagingLandScapeTileManager* mTileManager;
/** LandScape Renderable manager to avoid creating a deleting renderables.
They are created at the plugin start and destroyed at the plug in unload.
*/
PagingLandScapeRenderableManager* mRenderableManager;
/** LandScape pages Index Buffer sharing across pages for the terrain.
*/
PagingLandScapeIndexBufferManager* mIndexesManager;
/** LandScape pages texture coordinates sharing across pages for the terrain.
*/
PagingLandScapeTextureCoordinatesManager* mTexCoordManager;
/** LandScape pages for the terrain.
*/
PagingLandScapePageManager* mPageManager;
/** Horizon visibility testing.
*/
PagingLandScapeHorizon* mHorizon;
/** Dispatch scene manager events.
*/
PagingLandScapeListenerManager* mListenerManager;
bool mNeedOptionsUpdate;
//JEFF - flag to indicate if the world geometry was setup
bool mWorldGeomIsSetup;
bool mWorldGeomIsInit;
PagingLandScapeTileInfo* mImpactInfo;
Ogre::Vector3 mImpact;
Ogre::Vector3 mBrushCenter;
unsigned int mBrushSize;
Ogre::Real mBrushScale;
Ogre::Real* mCraterArray;
Ogre::Real* mBrushArray;
unsigned int mBrushArrayHeight;
unsigned int mBrushArrayWidth;
bool textureFormatChanged;
MovableObjectFactory* mMeshDecalFactory;
// re-create the default Crater brush.
void resizeCrater ( );
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture.h - description
-------------------
begin : Fri Apr 16 2004
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeTEXTURE_H
#define PAGINGLandScapeTEXTURE_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
# define SAND 0
# define GRASS 1
# define ROCK 2
# define SNOW 3
/**
* A simple class for encapsulating Texture generation.
*/
34 class PagingLandScapeTexture
{
public:
37 PagingLandScapeTexture( PagingLandScapeTextureManager *pageMgr,
38 const String materialName,
const unsigned int numTexture = 0,
40 bool isSplatMode = false );
// Method that must be overridden
43 virtual String getName ( void ) const {return mMaterialBaseName;};
44 virtual PagingLandScapeTexture *newTexture( )
{
return new PagingLandScapeTexture( mParent, mMaterialBaseName );
};
// Method that can be overridden
50 virtual ~PagingLandScapeTexture( void );
52 virtual void bindCompressionSettings( GpuProgramParametersSharedPtr params );
53 virtual void bindCompressionSettings( );
55 virtual void load( unsigned int mX, unsigned int mZ );
56 virtual void update( void );
57 virtual void unload( void );
59 virtual bool isMaterialSupported( bool recursive = true );
60 virtual void setOptions( void );
63 virtual const unsigned int getNumChannels ( void ) const
{
return mNumTexture;
};
67 virtual const unsigned int getNumChannelsperTexture ( const size_t i ) const
{
return static_cast<unsigned int>( mNumChannelperTexture[i] );
};
// Real Method
73 bool getCastsShadows( void ) const {return false;}
75 bool isLoaded( void ) const;
77 void setNeedUpdate( void );
78 void updated( void );
79 bool needUpdate( void ) const;
81 const MaterialPtr& getMaterial( void ) const;
83 void paint ( const unsigned int x,
const unsigned int z,
85 const Real paintForce );
88 void adjustDeformationRectangle( unsigned int x, unsigned int z );
89 void adjustPaintRectangle( unsigned int x, unsigned int z );
91 virtual void lightUpdate( );
93 void getCoordinates( unsigned int& X, unsigned int& Z )
{
X = mDataX;
Z = mDataZ;
};
98 inline bool isCoord( const unsigned int x, const unsigned int z )
{
return ( mDataX == x && mDataZ == z );
};
103 const String &getMaterialName( );
protected:
107 void compute( PagingLandScapeData2D* data,
108 const Image::Box& dataRect,
109 const Image::Box& textureRect );
112 void computePointAlpha( const unsigned int imagePos,
113 const Real height,
114 const Real slope ) ;
116 void computePointColor( const unsigned int imagePos,
117 const Real height,
118 const Real slope ) ;
120 void paintPoint ( const unsigned int imagePos,
121 const Real paintForce );
123 void upload( const Image::Box& textureRect );
125 void setNumTexture( );
// Method that can be overridden
128 virtual void _loadMaterial( void );
// Method that can be overridden
130 virtual void _unloadMaterial( void );
// Method that can be overridden
132 virtual void _save( void );
// properties that can be accessed from children
138 bool mIsSplatMode;
139 bool mIsBaseMode;
142 bool mIsLoaded;
143 bool mIsModified;
//! Pointer to ogre material
145 MaterialPtr mMaterial;
//! what page it correspond to
unsigned int mDataX, mDataZ;
149 Image::Box mPaintRect;
150 bool mIsPaintRectModified;
151 Image::Box mDeformRect;
152 bool mIsDeformRectModified;
153 PagingLandScapeTextureManager *mParent;
// Edit, deform and update
unsigned int mNumTexture;
157 std::vector<unsigned int> mNumChannelperTexture;
158 std::vector<Image> mImages;
159 std::vector<TexturePtr> mTextures;
160 std::vector<HardwarePixelBufferSharedPtr> mBuffers;
161 std::vector<bool> doTextureNeedUpdate;
162 std::vector<bool> isTextureModified;
// special case alpha loading Image as A8 only.
165 void loadAlphaTexture( const String& filename, const unsigned int channel );
// loading Image, buffer and texture in channels
167 void loadColorTexture( const String& TexName, const unsigned int channel );
// loading Image, buffer and texture.
169 void loadTexture( const String &filename, Image &img );
// Dynamic Lighting
171 void computeLightMap ( ) const;
172 Image mShadow;
173 Image mLightImage;
174 TexturePtr mLightTexture;
175 HardwarePixelBufferSharedPtr mLightBuffer;
176 bool mPositiveShadow;
177 bool mIsShaderShadowed;
178 bool mIsShadowed;
// Name that helps building textures names on each page
181 String mMaterialBaseName;
private :
184 void loadTexturesToModify( );
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeRenderableManager.h - description
-------------------
begin : Mon Jun 16 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeTextureCoordinatesMANAGER_H
#define PAGINGLandScapeTextureCoordinatesMANAGER_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
/** Class to manage the creation, destruction and use of PagingLandScapeRenderables.
@remarks
This class is used as a store of PagingLandScapeTexturecoordinatesBuffer shared between Page
*/
29 class PagingLandScapeTextureCoordinatesManager
{
public:
/** Initializes the PagingLandScapeTextureCoordinatesManager with the
* given options and allocate the necessary memory.
*/
35 PagingLandScapeTextureCoordinatesManager( PagingLandScapeSceneManager * scnMgr );
36 virtual ~PagingLandScapeTextureCoordinatesManager( void );
37 void load( void );
38 void clear( void );
40 HardwareVertexBufferSharedPtr getBuffer( const unsigned int tilex, const unsigned int tilez );
42 PagingLandScapeOptions* getOptions( ){return mOptions;}
protected:
45 PagingLandScapeOptions* mOptions;
unsigned int mPageSize;
unsigned int mTileSize;
50 HardwareTextureBuffersCol mTexBuffs;
};
}
#endif //PAGINGLandScapeTextureCoordinatesMANAGER_H
1 /***************************************************************************
OgrePagingLandScapeTextureManager.h - description
-------------------
begin : Fri Apr 16 2004
copyright : ( C ) 2003-2006 by Jose A. Milan and Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeTEXTUREMANAGER_H
#define PAGINGLandScapeTEXTUREMANAGER_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
26 class PagingLandScapeTextureManager
{
public:
30 PagingLandScapeTextureManager( PagingLandScapeSceneManager * scnMgr );
32 virtual ~PagingLandScapeTextureManager( void );
34 void load( void );
35 void clear( void );
36 void WorldDimensionChange( void );
37 PagingLandScapeTexture* allocateTexture( ) const;
38 void reset( void );
40 void load( const unsigned int texX, const unsigned int texZ );
41 void reload( const unsigned int dataX, const unsigned int dataZ );
42 void unload( const unsigned int texX, const unsigned int texZ );
44 bool isLoaded( const unsigned int texX, const unsigned int texZ );
47 const MaterialPtr& getMaterial( const unsigned int texX, const unsigned int texZ );
50 MaterialPtr getMapMaterial( void );
51 void setMapMaterial( void );
53 void setPaintChannelValues ( const std::vector<Real> *theChannelModifList )
{
channelModifList = theChannelModifList;
};
57 void paint ( const Vector3 &currpoint,
58 const Real paintForce,
59 const PagingLandScapeTileInfo *info );
61 void deformHeight ( const Vector3 &currpoint,
62 const PagingLandScapeTileInfo *info );
64 String getNextTextureFormat( );
65 String getCurrentTextureFormat( );
67 void registerTextureFormats( );
68 void clearTextureFormats ( );
69 void registerTextureType( PagingLandScapeTexture* source )
{
mTextureTypeMap.push_back( source );
}
74 PagingLandScapeTexture* getTexture( const unsigned int i, const unsigned int j,
75 const bool alwaysReturn = true );
76 PagingLandScapeTexture* getNewTexture( const unsigned int i, const unsigned int j );
77 void releaseTexture ( PagingLandScapeTexture*p );
79 unsigned int getNumChannels( );
80 unsigned int getNumChannelsperTexture( const size_t i );
83 inline PagingLandScapeSceneManager *getSceneManager( ){return mSceneManager;}
84 inline PagingLandScapeOptions* getOptions( ){return mOptions;}
unsigned int mPageSize;
88 Image mImage;
89 std::vector<Real> heights;
90 std::vector<Real> dividers;
91 std::vector<ColourValue> colors;
93 const std::vector<Real> *channelModifList;
protected:
// Common var for all textures
97 void setPageSize( );
98 void clearData ( );
//
102 PagingLandScapeSceneManager *mSceneManager;
103 PagingLandScapeOptions* mOptions;
unsigned int mTextureType;
107 String mTextureFormat;
unsigned int mWidth;
unsigned int mHeight;
unsigned int mTexturePageSize;
//PagingLandScapeTexturePages mTexture;
116 MaterialPtr mMapMaterial;
unsigned int mPaintChannel;
119 ColourValue mPaintColor;
123 PagingLandScapeTextureMap mTextureTypeMap;
/// The currently active page Data2d source
125 PagingLandScapeTexture* mActiveTextureType;
127 PagingLandScapeTextureList mActiveTextures;
128 PagingLandScapeTextureList mFreeTextures;
129 PagingLandScapeTextureArray mTexturePool;
};
} //namespace
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture_BaseTexture.h - description
-------------------
begin : Mon Apr 26 2004
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeTEXTURE_BASETEXTURE_H
#define PAGINGLandScapeTEXTURE_BASETEXTURE_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
25 class PagingLandScapeTexture_BaseTexture : public PagingLandScapeTexture
{
public:
28 PagingLandScapeTexture_BaseTexture( PagingLandScapeTextureManager *textureMgr );
29 String getName( ) const{return String( "BaseTexture" );}
30 void setOptions( void );
31 ~PagingLandScapeTexture_BaseTexture( void );
33 PagingLandScapeTexture* newTexture( );
34 bool isMaterialSupported( );
protected:
37 void _loadMaterial( void );
private:
40 Image BaseImage;
41 uchar *_BuildBaseTexture( ) const;
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture_BaseTexture2.h - description
-------------------
begin : Mon Apr 26 2004
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PagingLandScapeTexture_BaseTexture2_H
#define PagingLandScapeTexture_BaseTexture2_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
25 class PagingLandScapeTexture_BaseTexture2 : public PagingLandScapeTexture
{
public:
28 PagingLandScapeTexture_BaseTexture2( PagingLandScapeTextureManager *textureMgr );
29 String getName( ) const{return String( "BaseTexture2" );}
30 void setOptions( void );
31 ~PagingLandScapeTexture_BaseTexture2( void );
33 PagingLandScapeTexture* newTexture( );
34 bool isMaterialSupported( );
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture_Image.h - description
-------------------
begin : Fri Apr 16 2004
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeTEXTURE_IMAGE_H
#define PAGINGLandScapeTEXTURE_IMAGE_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
25 class PagingLandScapeTexture_Image : public PagingLandScapeTexture
{
public:
28 PagingLandScapeTexture_Image( PagingLandScapeTextureManager *textureMgr );
29 ~PagingLandScapeTexture_Image( void );
31 String getName( ) const
{
return String( "ImagePaging" );
}
36 PagingLandScapeTexture* newTexture( );
37 bool isMaterialSupported( );
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture_InstantBaseTexture.h - description
-------------------
begin : Mon Apr 26 2004
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PagingLandScapeTexture_InstantBaseTexture_H
#define PagingLandScapeTexture_InstantBaseTexture_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
26 class PagingLandScapeTexture_InstantBaseTexture : public PagingLandScapeTexture
{
public:
30 PagingLandScapeTexture_InstantBaseTexture( PagingLandScapeTextureManager *textureMgr );
31 ~PagingLandScapeTexture_InstantBaseTexture( void );
33 String getName( ) const{return String( "InstantBaseTexture" );}
36 void paint ( const unsigned int x, const unsigned int z,
37 const Real paintForce, const ColourValue &mPaintColor );
39 PagingLandScapeTexture* newTexture( );
40 bool isMaterialSupported( );
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture_InstantBaseTextureEdit.h - description
-------------------
begin : Mon Apr 26 2004
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PagingLandScapeTexture_InstantBaseTextureEdit_H
#define PagingLandScapeTexture_InstantBaseTextureEdit_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
27 class PagingLandScapeTexture_InstantBaseTextureEdit : public PagingLandScapeTexture
{
public:
31 PagingLandScapeTexture_InstantBaseTextureEdit( PagingLandScapeTextureManager *textureMgr );
32 virtual ~PagingLandScapeTexture_InstantBaseTextureEdit( void );
34 virtual String getName( ) const{return String( "InstantBaseTextureEdit" );}
36 virtual PagingLandScapeTexture* newTexture( );
37 virtual bool isMaterialSupported( );
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture_InstantBaseTexture.h - description
-------------------
begin : Mon Apr 26 2004
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PagingLandScapeTexture_InstantBaseTextureShadowed_H
#define PagingLandScapeTexture_InstantBaseTextureShadowed_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
26 class PagingLandScapeTexture_InstantBaseTextureShadowed : public PagingLandScapeTexture
{
public:
30 PagingLandScapeTexture_InstantBaseTextureShadowed( PagingLandScapeTextureManager *textureMgr );
31 ~PagingLandScapeTexture_InstantBaseTextureShadowed( void );
33 String getName( ) const{return String( "InstantBaseTextureShadowed" );}
35 void paint ( const unsigned int x, const unsigned int z,
36 const Real paintForce, const ColourValue &mPaintColor );
39 PagingLandScapeTexture* newTexture( );
40 bool isMaterialSupported( );
protected:
43 void _loadMaterial( void );
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture_SplattingShader.h - description
-------------------
begin : Mon Apr 16 2004
copyright : ( C ) 2002-2005 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeTEXTURE_NONE_H
#define PAGINGLandScapeTEXTURE_NONE_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeTexture.h"
namespace Ogre
{
27 class PagingLandScapeTexture_None : public PagingLandScapeTexture
{
public:
30 PagingLandScapeTexture_None( PagingLandScapeTextureManager *textureMgr ) :
PagingLandScapeTexture( textureMgr, "None", 0, false )
{
mIsLoaded = true;
mIsModified = false;
};
36 ~PagingLandScapeTexture_None( void )
{
};
40 String getName( ) const
{
return String( "None" );
}
44 PagingLandScapeTexture* newTexture( )
{
return new PagingLandScapeTexture_None( mParent );
};
48 void load( uint mX, uint mZ )
{
mDataX = mX;
mDataZ = mZ;
mIsLoaded = true;
mIsModified = false;
};
55 void unload( void ) { };
protected:
58 void _loadMaterial( void ) { };
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture_Splatting.h - description
-------------------
begin : Mon Apr 16 2004
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeTEXTURE_SPLATTING_H
#define PAGINGLandScapeTEXTURE_SPLATTING_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
25 class PagingLandScapeTexture_Splatting : public PagingLandScapeTexture
{
public:
28 PagingLandScapeTexture_Splatting( PagingLandScapeTextureManager *textureMgr );
29 String getName( ) const{return String( "Splatting" );}
31 void setOptions( void );
32 ~PagingLandScapeTexture_Splatting( void );
34 PagingLandScapeTexture* newTexture( );
35 bool isMaterialSupported( );
protected:
39 void _loadMaterial( void );
private:
43 void _BuildPoint( const unsigned int i, const int j,
44 ColourValue& out, std::vector<Real> &alpha );
46 inline void _InterpolateAlpha( std::vector<Real> &alpha, const Real percentaje,
const int index1, const int index2 );
49 bool bAlpha1NotUsed, bAlpha2NotUsed, bAlpha3NotUsed, bAlpha4NotUsed;
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture_Splatting.h - description
-------------------
begin : Mon Apr 16 2004
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeTEXTURE_SPLATTING2_H
#define PAGINGLandScapeTEXTURE_SPLATTING2_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
25 class PagingLandScapeTexture_Splatting2 : public PagingLandScapeTexture
{
public:
28 PagingLandScapeTexture_Splatting2( PagingLandScapeTextureManager *textureMgr );
29 String getName( ) const{return String( "Splatting2" );}
31 ~PagingLandScapeTexture_Splatting2( void );
33 void setOptions( void );
35 PagingLandScapeTexture* newTexture( );
36 bool isMaterialSupported( );
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture_Splatting.h - description
-------------------
begin : Mon Apr 16 2004
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PagingLandScapeTexture_Splatting2Edit_H
#define PagingLandScapeTexture_Splatting2Edit_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
25 class PagingLandScapeTexture_Splatting2Edit : public PagingLandScapeTexture
{
public:
28 PagingLandScapeTexture_Splatting2Edit( PagingLandScapeTextureManager *textureMgr );
30 String getName( ) const{return String( "Splatting2Edit" );}
31 ~PagingLandScapeTexture_Splatting2Edit( void );
32 void setOptions( void );
34 PagingLandScapeTexture* newTexture( );
35 bool isMaterialSupported( );
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture_Splatting.h - description
-------------------
begin : Mon Apr 16 2004
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PagingLandScapeTexture_Splatting3_H
#define PagingLandScapeTexture_Splatting3_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
25 class PagingLandScapeTexture_Splatting3 : public PagingLandScapeTexture
{
public:
28 PagingLandScapeTexture_Splatting3( PagingLandScapeTextureManager *textureMgr );
29 String getName( ) const{return String( "Splatting3" );}
31 void setOptions( void );
33 ~PagingLandScapeTexture_Splatting3( );
35 PagingLandScapeTexture* newTexture( );
36 bool isMaterialSupported( );
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture_Splatting4.h - description
-------------------
begin : Mon Apr 16 2004
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeTEXTURE4_SPLATTING_H
#define PAGINGLandScapeTEXTURE4_SPLATTING_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
25 class PagingLandScapeTexture_Splatting4 : public PagingLandScapeTexture
{
public:
28 PagingLandScapeTexture_Splatting4( PagingLandScapeTextureManager *textureMgr );
29 String getName( ) const{return String( "Splatting4" );}
30 void setOptions( void );
31 ~PagingLandScapeTexture_Splatting4( void );
33 PagingLandScapeTexture* newTexture( );
34 bool isMaterialSupported( );
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture_Splatting5.h - description
-------------------
begin : Mon Apr 16 2004
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeTEXTURE5_SPLATTING_H
#define PAGINGLandScapeTEXTURE5_SPLATTING_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeTexture.h"
namespace Ogre
{
27 class PagingLandScapeTexture_Splatting5 : public PagingLandScapeTexture
{
public:
30 PagingLandScapeTexture_Splatting5( PagingLandScapeTextureManager *textureMgr );
31 String getName( ) const{return String( "Splatting5" );}
32 void setOptions( void );
33 ~PagingLandScapeTexture_Splatting5( void );
35 PagingLandScapeTexture* newTexture( );
36 bool isMaterialSupported( );
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture_Splatting4.h - description
-------------------
begin : Mon Apr 16 2004
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeTEXTURE6_SPLATTING_H
#define PAGINGLandScapeTEXTURE6_SPLATTING_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
25 class PagingLandScapeTexture_Splatting6 : public PagingLandScapeTexture
{
public:
28 PagingLandScapeTexture_Splatting6( PagingLandScapeTextureManager *textureMgr );
29 String getName( ) const{return String( "Splatting6" );}
30 void setOptions( void );
31 ~PagingLandScapeTexture_Splatting6( void );
33 PagingLandScapeTexture* newTexture( );
34 bool isMaterialSupported( );
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture_Splatting7.h - description
-------------------
begin : Mon Apr 16 2004
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeTEXTURE7_SPLATTING_H
#define PAGINGLandScapeTEXTURE7_SPLATTING_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
25 class PagingLandScapeTexture_Splatting7 : public PagingLandScapeTexture
{
public:
28 PagingLandScapeTexture_Splatting7( PagingLandScapeTextureManager *textureMgr );
30 ~PagingLandScapeTexture_Splatting7( void );
31 String getName( ) const{return String( "Splatting7" );}
32 PagingLandScapeTexture* newTexture( );
33 bool isMaterialSupported( );
35 void setOptions( void );
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture_Splatting7Edit.h - description
-------------------
begin : Mon Apr 16 2004
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeTEXTURE7Edit_SPLATTING_H
#define PAGINGLandScapeTEXTURE7Edit_SPLATTING_H
#include "OgrePagingLandScapePrerequisites.h"
namespace Ogre
{
25 class PagingLandScapeTexture_Splatting7Edit : public PagingLandScapeTexture
{
public:
28 PagingLandScapeTexture_Splatting7Edit( PagingLandScapeTextureManager *textureMgr );
30 String getName( ) const{return String ( "Splatting7Edit" );};
32 void setOptions( void );
34 ~PagingLandScapeTexture_Splatting7Edit( void );
36 PagingLandScapeTexture* newTexture( );
37 bool isMaterialSupported( );
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture_SplattingShader.h - description
-------------------
begin : Mon Apr 16 2004
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeTEXTURE_SPLATTINGSHADER_H
#define PAGINGLandScapeTEXTURE_SPLATTINGSHADER_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeTexture.h"
namespace Ogre
{
27 class PagingLandScapeTexture_SplattingShader : public PagingLandScapeTexture
{
public:
30 PagingLandScapeTexture_SplattingShader( PagingLandScapeTextureManager *textureMgr );
31 String getName( ) const{return String( "SplattingShader" );}
33 ~PagingLandScapeTexture_SplattingShader( void );
35 PagingLandScapeTexture* newTexture( );
36 bool isMaterialSupported( );
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTexture_SplattingShader.h - description
-------------------
begin : Mon Apr 16 2004
copyright : ( C ) 2002-2006 by Jose A Milan & Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeTEXTURE_SPLATTINGSHADEREDIT_H
#define PAGINGLandScapeTEXTURE_SPLATTINGSHADEREDIT_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeTexture.h"
namespace Ogre
{
27 class PagingLandScapeTexture_SplattingShaderEdit : public PagingLandScapeTexture
{
public:
30 PagingLandScapeTexture_SplattingShaderEdit( PagingLandScapeTextureManager *textureMgr );
31 String getName( ) const{return String( "SplattingShaderEdit" );}
33 ~PagingLandScapeTexture_SplattingShaderEdit( void );
34 PagingLandScapeTexture* newTexture( );
35 bool isMaterialSupported( );
};
}
#endif //PAGINGLandScapeTEXTURE_SPLATTINGSHADEREDIT_H
/***************************************************************************
OgrePagingLandScapeTile.h - description
-------------------
begin : Sun Jun 08 2003
copyright : ( C ) 2003-2006 by Jose A. Milan and Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeTILE_H
#define PAGINGLandScapeTILE_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeTileInfo.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeTileManager.h"
#include "OgrePagingLandScapeRenderable.h"
namespace Ogre
{
class _OgrePagingLandScapeExport PagingLandScapeTile
{
public:
34 inline PagingLandScapeTileInfo* getInfo( void )
{
return mInfo;
};
/** Sets the appropriate neighbor for this TerrainRenderable. Neighbors are necessary
to know when to bridge between LODs.
*/
42 void _setNeighbor( Neighbor n, PagingLandScapeTile* t );
/** Returns the neighbor TerrainRenderable.
*/
46 inline PagingLandScapeTile* _getNeighbor( Neighbor n )
{
return mNeighbors[ n ];
};
/** intersectSegment
@remarks
Intersect mainly with LandScape
@param start
beginning of the segment
@param end
where it ends
@param result
where it intersects with terrain
*/
61 bool intersectSegmentFromAbove( const Vector3& start, const Vector3& dir, Vector3* result );
62 bool intersectSegmentFromBelow( const Vector3& start, const Vector3& dir, Vector3* result );
/** updateTerrain
@remarks
Make the Tile reload its vertices and normals
( upon a modification of the height data )
*/
69 void updateTerrain( void );
71 inline PagingLandScapeRenderable* getRenderable( void )
{
return mRenderable;
}
76 void _linkRenderableNeighbor( void );
77 void _updateLod( void );
79 PagingLandScapeTile( PagingLandScapeTileManager *pageMgr );
81 ~PagingLandScapeTile( void );
83 void init( SceneNode* PageNode, const int tableX, const int tableZ, const int tileX, const int tileZ );
84 void load( void );
85 void unload( void );
86 void uninit( void );
88 void _Notify( const Vector3 &pos, const PagingLandScapeCamera * const Cam );
90 inline bool isLoaded( void )
{
return mLoaded;
};
94 inline bool isLoading( void )
{
return mLoading;
};
98 inline void setLoading( bool value )
{
mLoading = value;
};
103 void setInUse ( bool InUse )
{
assert ( mInit );
if ( mRenderable )
mRenderable->setInUse ( InUse );
}
110 inline bool isVisible( void )
{
return mVisible;
}
/// make tile visible not being unload or invisible until a certain time.
116 inline void touch ( )
{
mTimeUntouched = mParent->getOptions( )->TileInvisibleUnloadFrames;
}
121 void setRenderQueueGroup( uint8 qid );
123 SceneNode *getSceneNode( )
{
return mTileSceneNode;
};
127 const AxisAlignedBox &getWorldBbox( ) const
{
return mWorldBounds;
};
131 inline const AxisAlignedBox &getCullWorldBbox( ) const
{
return mWorldBoundsExt;
};
135 inline const Vector3 &getCenter( void ) const
{
return mWorldPosition;
};
140 const bool unloadUntouched ( );
protected:
//movable object variables
AxisAlignedBox mWorldBounds;
AxisAlignedBox mWorldBoundsExt;
Vector3 mWorldPosition;
// if the tile is initialized
bool mInit;
// if the renderable is loaded
bool mLoaded;
// if the renderable is loading
bool mLoading;
PagingLandScapeRenderable* mRenderable;
SceneNode* mTileSceneNode;
SceneNode* mParentSceneNode;
PagingLandScapeTile* mNeighbors[4];
PagingLandScapeTileInfo *mInfo;
bool mVisible;
unsigned int mTimeUntouched;
PagingLandScapeTileManager *mParent;
};
} //namespace
#endif
1 /***************************************************************************
OgrePagingLandScapeTileInfo.h - description
-------------------
begin : Sat Jan 31 2004
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeTILEINFO_H
#define PAGINGLandScapeTILEINFO_H
namespace Ogre
{
/** This class holds the Tile info
@remarks
This will avoid to pass a lot of data to the Renderable class.
*/
27 class
PagingLandScapeTileInfo
{
public:
31 PagingLandScapeTileInfo( const uint pageX, const uint pageZ,
32 const uint tileX, const uint tileZ )
:
mMinLevelDistSqr( 0 ),
mPageX ( pageX ),
mPageZ ( pageZ ),
mTileX ( tileX ),
mTileZ ( tileZ )
{
}
41 ~PagingLandScapeTileInfo( )
{
delete mMinLevelDistSqr;
}
//This is the Page Index in the Page Array
unsigned short int mPageX;
unsigned short int mPageZ;
//This is the tile Index in the Tile Array
unsigned short int mTileX;
unsigned short int mTileZ;
/// List of squared distances at which LODs change
// costly to compute, so we cache it there.
56 std::vector<Real>* mMinLevelDistSqr;
};
}
#endif
1 /***************************************************************************
OgrePagingLandScapeTileManager.h - description
-------------------
begin : Mon Jun 16 2003
copyright : ( C ) 2003-2006 by Jose A. Milan and Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#ifndef PAGINGLandScapeTILEMANAGER_H
#define PAGINGLandScapeTILEMANAGER_H
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeQueue.h"
namespace Ogre
{
28 class PagingLandScapeTileManager
{
public:
32 PagingLandScapeTileManager( PagingLandScapeSceneManager * scnMgr );
34 virtual ~PagingLandScapeTileManager( void );
/** Retrieve a free tile.
*/
38 PagingLandScapeTile* getTile( void );
/** Make a tile free.
*/
42 void freeTile( PagingLandScapeTile* tile );
44 void reset( void );
46 unsigned int numTiles( void ) const;
48 size_t numFree( void ) const;
51 void load( void );
52 void clear( void );
// unload invisible tiles after option::mTileInvisibleUnloadFrames tick
// without being visible.
56 void unloadUntouched( );
58 inline PagingLandScapeOptions* getOptions( )
{
return mOptions;
}
63 inline PagingLandScapeSceneManager* getSceneManager( )
{
return mSceneManager;
}
protected:
70 PagingLandScapeOptions* mOptions;
71 PagingLandScapeSceneManager *mSceneManager;
73 void _addBatch( const unsigned int num );
75 PagingLandScapeTileRow mTiles;
77 PagingLandScapeQueue< PagingLandScapeTile > mQueue;
unsigned int mNumTiles;
};
} //namespace
#endif
1 /***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
/**
@file
fileutils.h
@brief
Utility function to manage directories
*/
#ifndef fileutils_H
#define fileutils_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* check if directory exists or not*
* \param *Dirname name of the directory
* \return true if exists
*/
26 bool DirExists( const char *Dirname );
/**
* change the current directory and return old one
* as a MALLOC'ED by system ONE
* \param *Dirname
* \return
*/
33 char* ChangeToDir( const char* Dirname );
/**
* Reestablish directory to current one before changing
* and free the char* MALLOC'ED by system when changing.
* \param *oldDirname
*/
39 void RetablishDir( char* oldDirname );
#ifdef __cplusplus
}/* end extern C definitions */
#endif
#endif //fileutils_H
1 // DRGNURBSSurface.cpp: implementation of the CDRGNURBSSurface class.
// ------------------------------------------------------------------------------------
// Copyright © 1999 Intel Corporation
// All Rights Reserved
//
// Permission is granted to use, copy, distribute and prepare derivative works of this
// software for any purpose and without fee, provided, that the above copyright notice
// and this statement appear in all copies. Intel makes no representations about the
// suitability of this software for any purpose. This software is provided "AS IS."
//
// Intel specifically disclaims all warranties, express or implied, and all liability,
// including consequential and other indirect damages, for the use of this software,
// including liability for infringement of any proprietary rights, and including the
// warranties of merchantability and fitness for a particular purpose. Intel does not
// assume any responsibility for any errors which may appear in this software nor any
// responsibility to update it.
// ------------------------------------------------------------------------------------
//
// PURPOSE:
//
// Implementation of the CDRGNURBSSurface class for rendering NURBS surfaces.
// Accompanies the article "Rendering NURBS Surfaces in float-Time". Please refer
// to the article for an understanding of the methods in this class.
// ------------------------------------------------------------------------------------
//
// Author: Dean Macri - Intel Developer Relations Divison -- Tools and Technology Group
// Please contact me at dean.p.macri@intel.com with questions, suggestions, etc.
//
////////////////////////////////////////////////////////////////////////////////////////
//
// Yoinked from http://www.gamasutra.com/features/19991117/macri_pfv.htm
// Hacked into an unholy mess for use with OGRE by Chris "Antiarc" Heald ( antiarc@captionthis.com )
// Date: 11/9/2003
//
////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "DRGNURBSSurface.h"
#include <stdlib.h>
#include <math.h>
#include <string.h>
48 CDRGNURBSSurface::CDRGNURBSSurface( )
{
m_pControlPoints = NULL;
m_UKnots = NULL;
m_VKnots = NULL;
m_UBasisCoefficients = NULL;
m_VBasisCoefficients = NULL;
m_UBasis = NULL;
m_dUBasis = NULL;
m_VBasis = NULL;
m_dVBasis = NULL;
m_UTemp = NULL;
m_dUTemp = NULL;
m_TessUKnotSpan = NULL;
m_TessVKnotSpan = NULL;
m_iUTessellations = 0;
m_iVTessellations = 0;
m_pVertices = NULL;
}
// -----------------------------------------------------------------------
//
// Free up anything we've allocated
//
// -----------------------------------------------------------------------
76 void CDRGNURBSSurface::Cleanup( void )
{
ALIGNED_DELETE( m_pControlPoints );
ALIGNED_DELETE( m_UKnots );
ALIGNED_DELETE( m_VKnots );
ALIGNED_DELETE( m_UBasisCoefficients );
ALIGNED_DELETE( m_VBasisCoefficients );
ALIGNED_DELETE( m_UBasis );
ALIGNED_DELETE( m_dUBasis );
ALIGNED_DELETE( m_VBasis );
ALIGNED_DELETE( m_dVBasis );
ALIGNED_DELETE( m_UTemp );
ALIGNED_DELETE( m_dUTemp );
ALIGNED_DELETE( m_pVertices );
SAFE_DELETE( m_TessUKnotSpan );
SAFE_DELETE( m_TessVKnotSpan );
}
94 CDRGNURBSSurface::~CDRGNURBSSurface( )
{
Cleanup( ); // Free everything :- )
}
// -----------------------------------------------------------------------
//
// Initialize a CDRGNURBSSurface object. This will normally only be called
// once for a particular object but it's safe to call it more than once.
//
// -----------------------------------------------------------------------
105 bool CDRGNURBSSurface::Init( int uDegree,
int vDegree,
int uControlPoints,
int vControlPoints,
Point4D *pControlPoints,
float *pUKnots,
float *pVKnots,
int iDefaultUTessellations,
int iDefaultVTessellations
)
{
// In case we've already been initialized.
Cleanup( );
// Copy the stuff we're given
//
m_iUDegree = uDegree;
m_iVDegree = vDegree;
m_iUControlPoints = uControlPoints;
m_iVControlPoints = vControlPoints;
//
// Compute some other useful quantities
//
m_iUOrder = m_iUDegree + 1;
m_iVOrder = m_iVDegree + 1;
m_iUKnots = m_iUOrder + m_iUControlPoints;
m_iVKnots = m_iVOrder + m_iVControlPoints;
// Calculate how many valid spans exist in the Knot vectors
m_iUBasisSpans = m_iUKnots - 2 * m_iUDegree;
m_iVBasisSpans = m_iVKnots - 2 * m_iVDegree;
//
// Allocate some memory for the control points, knots, and basis stuff
//
m_pControlPoints = ALIGNED_NEW( m_iUControlPoints * m_iVControlPoints, Point4D );
m_UKnots = ALIGNED_NEW( m_iUKnots, float );
m_VKnots = ALIGNED_NEW( m_iVKnots, float );
// For each span in the knot vector, there will be m_iUOrder ( and m_iVOrder )
// Basis polynomials that are non-zero. Each of those polynomials will
// have m_iUOrder coefficients, hence m_iUBasisSpans * m_iUOrder * m_iUOrder
m_UBasisCoefficients = ALIGNED_NEW( m_iUOrder * m_iUOrder * m_iUBasisSpans, float );
m_VBasisCoefficients = ALIGNED_NEW( m_iVOrder * m_iVOrder * m_iVBasisSpans, float );
m_UTemp = ALIGNED_NEW( m_iVOrder, Point4D );
m_dUTemp = ALIGNED_NEW( m_iVOrder, Point4D );
//
// Copy the incoming data to the internal structures. If the incoming control
// points are NOT stored as pre-weighted points, then you'll need to loop over
// the points and multiply x, y, and z by the w value ( so that the actual,
// stored control point is {x*w, y*w, z*w, w} )
//
memcpy( m_pControlPoints, pControlPoints, m_iUControlPoints * m_iVControlPoints * sizeof( Point4D ) );
memcpy( m_UKnots, pUKnots, m_iUKnots * sizeof( float ) );
memcpy( m_VKnots, pVKnots, m_iVKnots * sizeof( float ) );
ComputeBasisCoefficients( );
SetTessellations( iDefaultUTessellations, iDefaultVTessellations );
return true;
}
// -----------------------------------------------------------------------
//
// Change the number of tessellations used to render the object
//
// -----------------------------------------------------------------------
176 void CDRGNURBSSurface::SetTessellations( int iUTessellations, int iVTessellations )
{
if( ( iUTessellations != m_iUTessellations ) ||
( iVTessellations != m_iVTessellations ) )
{
m_iUTessellations = iUTessellations;
m_iVTessellations = iVTessellations;
//
// Free anything we've already allocated
//
ALIGNED_DELETE( m_UBasis );
ALIGNED_DELETE( m_VBasis );
ALIGNED_DELETE( m_dUBasis );
ALIGNED_DELETE( m_dVBasis );
SAFE_DELETE( m_TessUKnotSpan );
SAFE_DELETE( m_TessVKnotSpan );
//
// Allocate memory for the basis functions, etc
//
m_UBasis = ALIGNED_NEW( m_iUOrder * SIMD_SIZE * ( m_iUTessellations+1 ), float );
m_VBasis = ALIGNED_NEW( m_iVOrder * SIMD_SIZE * ( m_iVTessellations+1 ), float );
m_dUBasis = ALIGNED_NEW( m_iUOrder * SIMD_SIZE * ( m_iUTessellations+1 ), float );
m_dVBasis = ALIGNED_NEW( m_iVOrder * SIMD_SIZE * ( m_iVTessellations+1 ), float );
m_TessUKnotSpan = new int[ m_iUTessellations+1 ];
m_TessVKnotSpan = new int[ m_iVTessellations+1 ];
ALIGNED_DELETE( m_pVertices );
int iVertices = ( ( iUTessellations+1 ) * ( iVTessellations+1 ) ); //2 * ( iVTessellations + 1 );
m_pVertices = ALIGNED_NEW( iVertices, splinePoint );
//
// Re-evaluate the basis functions
//
EvaluateBasisFunctions( );
}
}
// -----------------------------------------------------------------------
// float CDRGNURBSSurface::ComputeCoefficient( float *fKnots, int iInterval, int i, int p, int k )
//
//
// Determines the polynomial coefficients from the knot vector
//
// Remember that the b-spline basis functions of degree p on knot interval
// i = ( Bi, p ) defined on a knot vector u = {U0, U1, ..., Um} are defined:
//
// Bi, 0( u ) = 1 if Ui <= u < Ui+1
// 0 otherwise
//
// u - Ui Ui+p+1 - u
// Bi, p( u ) = ---------- * Bi, p-1( u ) + ------------- * Bi+1, p-1( u )
// Ui+p - Ui Ui+p+1 - Ui+1
//
//
// For some degree p on interval i, there exist p+1 polynomials of
// degree p of the form:
//
// Ci, p, 0 + Ci, p, 1 * u^1 + Ci, p, 2 * u^2 + ... + Ci, p, p * u^p
//
// I derived a recursive formula for these constant coefficients as
//
// Ci, 0, 0 = Bi, 0( u ) ( i.e. Ci, 0, 0 will be either 0 or 1 )
//
// For p > 0
// Ui+p+1 * Ci+1, p-1, 0 UiCi, p-1, 0
// Ci, p, 0 = --------------------- - ------------
// Ui+p+1 - Ui+1 Ui+p - Ui
//
// Ci, p-1, p-1 Ci+1, p-1, p-1
// Ci, p, p = ------------ - ---------------
// Ui+p - Ui Ui+p+1 - Ui+1
//
// For 0<k<p
// Ci, p-1, k-1 - Ui * Ci, p-1, k Ci+1, p-1, k-1 - Ui+p+1 * Ci+1, p-1, k
// Ci, p, k = ---------------------------- - ------------------------------------
// Ui+p - Ui Ui+p+1 - Ui+1
//
//
// From this, for a pth degree b-spline, for each interval i, there are
// p+1 b-spline basis functions that are non-zero and each one has p+1
// coefficients. Note that Ci, p, k is dependent on u only for determining the
// knot span, i, that we're computing the coefficients for.
// The next two functions compute those coefficients for the various intervals
// -----------------------------------------------------------------------
264 float CDRGNURBSSurface::ComputeCoefficient( float *fKnots, int iInterval, int i, int p, int k )
{
float fResult = 0.0f;
if( p == 0 )
{
if( i == iInterval )
fResult = 1.0f;
}
else if( k == 0 )
{
if( fKnots[i+p] != fKnots[i] )
fResult -= fKnots[i] * ComputeCoefficient( fKnots, iInterval, i, p-1, 0 ) / ( fKnots[i+p] - fKnots[i] );
if( fKnots[i+p+1] != fKnots[i+1] )
fResult += fKnots[i+p+1] * ComputeCoefficient( fKnots, iInterval, i+1, p-1, 0 ) / ( fKnots[i+p+1] - fKnots[i+1] );
}
else if( k == p )
{
if( fKnots[i+p] != fKnots[i] )
fResult += ComputeCoefficient( fKnots, iInterval, i, p-1, p-1 ) / ( fKnots[i+p] - fKnots[i] );
if( fKnots[i+p+1] != fKnots[i+1] )
fResult -= ComputeCoefficient( fKnots, iInterval, i+1, p-1, p-1 ) / ( fKnots[i+p+1] - fKnots[i+1] );
}
else if( k > p )
{
fResult = 0.0f;
}
else
{
float C1, C2;
if( fKnots[i+p] != fKnots[i] )
{
C1 = ComputeCoefficient( fKnots, iInterval, i, p-1, k-1 );
C2 = ComputeCoefficient( fKnots, iInterval, i, p-1, k );
fResult += ( C1 - fKnots[i] * C2 ) / ( fKnots[i+p] - fKnots[i] );
}
if( fKnots[i+p+1] != fKnots[i+1] )
{
C1 = ComputeCoefficient( fKnots, iInterval, i+1, p-1, k-1 );
C2 = ComputeCoefficient( fKnots, iInterval, i+1, p-1, k );
fResult -= ( C1 - fKnots[i+p+1] * C2 ) / ( fKnots[i+p+1] - fKnots[i+1] );
}
}
return fResult;
}
// -----------------------------------------------------------------------
// void CDRGNURBSSurface::ComputeBasisCoefficients( void )
//
// See the comment from the function above, ComputeCoefficient( )
// -----------------------------------------------------------------------
318 void CDRGNURBSSurface::ComputeBasisCoefficients( void )
{
int i, j, k;
//
// Start with U. For each Basis span calculate coefficients
// for m_iUOrder polynomials each having m_iUOrder coefficients
//
for( i=0; i<m_iUBasisSpans; i++ )
{
for( j=0; j<m_iUOrder; j++ )
{
for( k=0; k<m_iUOrder; k++ )
{
m_UBasisCoefficients[ ( i * m_iUOrder + j ) * m_iUOrder + k ] =
ComputeCoefficient( m_UKnots, i + m_iUDegree, i + j, m_iUDegree, k );
}
}
}
for( i=0; i<m_iVBasisSpans; i++ )
{
for( j=0; j<m_iVOrder; j++ )
{
for( k=0; k<m_iVOrder; k++ )
{
m_VBasisCoefficients[ ( i * m_iVOrder + j ) * m_iVOrder + k ] =
ComputeCoefficient( m_VKnots, i + m_iVDegree, i + j, m_iVDegree, k );
}
}
}
}
// -----------------------------------------------------------------------
// void CDRGNURBSSurface::EvaluateBasisFunctions( void )
//
// Evaluate the polynomials for the basis functions and store the results.
// First derivatives are calculated as well.
// -----------------------------------------------------------------------
359 void CDRGNURBSSurface::EvaluateBasisFunctions( void )
{
int i, j, k, idx;
float u, uinc;
float v, vinc;
//
// First evaluate the U basis functions and derivitives at uniformly spaced u values
//
idx = 0;
u = m_UKnots[idx+m_iUDegree];
uinc = ( m_UKnots[m_iUKnots-m_iUOrder] - m_UKnots[m_iUDegree] )/( m_iUTessellations );
for( i=0; i<=m_iUTessellations; i++ )
{
while( ( idx < m_iUKnots - m_iUDegree*2 - 2 ) && ( u >= m_UKnots[idx+m_iUDegree+1] ) )
idx++;
m_TessUKnotSpan[i] = idx+m_iUDegree;
//
// Evaluate using Horner's method
//
for( j=0; j<m_iUOrder; j++ )
{
m_UBasis[( i*m_iUOrder+j ) * SIMD_SIZE] = m_UBasisCoefficients[ ( idx * m_iUOrder + j ) * m_iUOrder + m_iUDegree ];
m_dUBasis[( i*m_iUOrder+j ) * SIMD_SIZE] = m_UBasis[( i*m_iUOrder+j ) * SIMD_SIZE] * m_iUDegree;
for( k=m_iUDegree-1; k>=0; k-- )
{
m_UBasis[( i*m_iUOrder+j )*SIMD_SIZE] = m_UBasis[ ( i*m_iUOrder+j )*SIMD_SIZE ] * u +
m_UBasisCoefficients[ ( idx * m_iUOrder + j ) * m_iUOrder + k ];
if( k>0 )
{
m_dUBasis[( i*m_iUOrder+j )*SIMD_SIZE] = m_dUBasis[( i * m_iUOrder+j )*SIMD_SIZE] * u +
m_UBasisCoefficients[ ( idx * m_iUOrder + j ) * m_iUOrder + k ] * k;
}
}
//
// Make three copies. This isn't necessary if we're using straight C
// code but for the Pentium III optimizations, it is.
//
}
u += uinc;
}
//
// Finally evaluate the V basis functions at uniformly spaced v values
//
idx = 0;
v = m_VKnots[idx+m_iVDegree];
vinc = ( m_VKnots[m_iVKnots-m_iVOrder] - m_VKnots[m_iVDegree] )/( m_iVTessellations );
for( i=0; i<=m_iVTessellations; i++ )
{
while( ( idx < m_iVKnots - m_iVDegree*2 - 2 ) && ( v >= m_VKnots[idx+m_iVDegree+1] ) )
idx++;
m_TessVKnotSpan[i] = idx+m_iVDegree;
//
// Evaluate using Horner's method
//
for( j=0; j<m_iVOrder; j++ )
{
m_VBasis[( i*m_iVOrder+j )*SIMD_SIZE] = m_VBasisCoefficients[ ( idx * m_iVOrder + j ) * m_iVOrder + m_iVDegree ];
m_dVBasis[( i*m_iVOrder+j )*SIMD_SIZE] = m_VBasis[( i*m_iVOrder+j )*SIMD_SIZE] * m_iVDegree;
for( k=m_iVDegree-1; k>=0; k-- )
{
m_VBasis[( i*m_iVOrder+j )*SIMD_SIZE] = m_VBasis[ ( i*m_iVOrder+j )*SIMD_SIZE ] * v +
m_VBasisCoefficients[ ( idx * m_iVOrder + j ) * m_iVOrder + k ];
if( k>0 )
{
m_dVBasis[( i*m_iVOrder+j )*SIMD_SIZE] = m_dVBasis[( i * m_iVOrder+j )*SIMD_SIZE] * v +
m_VBasisCoefficients[ ( idx * m_iVOrder + j ) * m_iVOrder + k ] * k;
}
}
}
v += vinc;
}
}
// -----------------------------------------------------------------------
//
// Tessellate the surface into triangles and submit them as a triangle
// strip to Direct3D.
//
// -----------------------------------------------------------------------
447 void CDRGNURBSSurface::TessellateSurface( )
{
int u, v;
int k, l;
int uKnot, vKnot;
Point4D *UTemp = m_UTemp, *dUTemp = m_dUTemp;
Point4D Pw;
float rhw;
int iVertices;
Point4D *pControlPoints = m_pControlPoints;
int iCPOffset;
float VBasis, dVBasis;
int idx, uidx;
if( ( m_iUTessellations == 0 ) || ( m_iVTessellations == 0 ) )
return;
iVertices = 2 * ( m_iVTessellations + 1 );
// Step over the U and V coordinates and generate triangle strips to render
//
for( u=0; u<=m_iUTessellations; u++ )
{
// What's the current knot span in the U direction?
uKnot = m_TessUKnotSpan[u];
// Calculate the offset into the pre-calculated basis functions array
uidx = u * m_iUOrder * SIMD_SIZE;
vKnot = -1;
// Create one row of vertices
for( v=0; v<=m_iVTessellations; v++ )
{
idx = u * m_iUTessellations + v;
if( vKnot != m_TessVKnotSpan[v] )
{
vKnot = m_TessVKnotSpan[v];
//
// If our knot span in the V direction has changed, then calculate some
// temporary variables. These are the sum of the U-basis functions times
// the control points ( times the weights because the control points have
// the weights factored in ).
//
for( k=0; k<=m_iVDegree; k++ )
{
iCPOffset = ( uKnot - m_iUDegree ) * m_iVControlPoints + ( vKnot - m_iVDegree );
UTemp[k].x = m_UBasis[uidx] * pControlPoints[ iCPOffset + k ].x;
UTemp[k].y = m_UBasis[uidx] * pControlPoints[ iCPOffset + k ].y;
UTemp[k].z = m_UBasis[uidx] * pControlPoints[ iCPOffset + k ].z;
UTemp[k].w = m_UBasis[uidx] * pControlPoints[ iCPOffset + k ].w;
dUTemp[k].x = m_dUBasis[uidx] * pControlPoints[ iCPOffset + k ].x;
dUTemp[k].y = m_dUBasis[uidx] * pControlPoints[ iCPOffset + k ].y;
dUTemp[k].z = m_dUBasis[uidx] * pControlPoints[ iCPOffset + k ].z;
dUTemp[k].w = m_dUBasis[uidx] * pControlPoints[ iCPOffset + k ].w;
for( l=1; l<=m_iUDegree; l++ )
{
iCPOffset += m_iVControlPoints;
UTemp[k].x += m_UBasis[uidx+l * SIMD_SIZE] * pControlPoints[ iCPOffset + k].x;
UTemp[k].y += m_UBasis[uidx+l * SIMD_SIZE] * pControlPoints[ iCPOffset + k].y;
UTemp[k].z += m_UBasis[uidx+l * SIMD_SIZE] * pControlPoints[ iCPOffset + k].z;
UTemp[k].w += m_UBasis[uidx+l * SIMD_SIZE] * pControlPoints[ iCPOffset + k].w;
dUTemp[k].x += m_dUBasis[uidx+l * SIMD_SIZE] * pControlPoints[ iCPOffset + k ].x;
dUTemp[k].y += m_dUBasis[uidx+l * SIMD_SIZE] * pControlPoints[ iCPOffset + k ].y;
dUTemp[k].z += m_dUBasis[uidx+l * SIMD_SIZE] * pControlPoints[ iCPOffset + k ].z;
dUTemp[k].w += m_dUBasis[uidx+l * SIMD_SIZE] * pControlPoints[ iCPOffset + k ].w;
}
}
}
// Compute the point in the U and V directions
VBasis = m_VBasis[ ( v * m_iVOrder )*SIMD_SIZE ];
dVBasis = m_dVBasis[ ( v * m_iVOrder )*SIMD_SIZE ];
Pw.x = VBasis * UTemp[0].x;
Pw.y = VBasis * UTemp[0].y;
Pw.z = VBasis * UTemp[0].z;
Pw.w = VBasis * UTemp[0].w;
for( k=1; k<=m_iVDegree; k++ )
{
VBasis = m_VBasis[ ( v * m_iVOrder + k )*SIMD_SIZE ];
dVBasis = m_dVBasis[ ( v * m_iVOrder + k )*SIMD_SIZE ];
Pw.x += VBasis * UTemp[k].x;
Pw.y += VBasis * UTemp[k].y;
Pw.z += VBasis * UTemp[k].z;
Pw.w += VBasis * UTemp[k].w;
}
// rhw is the factor to multiply by inorder to bring the 4-D points back into 3-D
rhw = 1.0f / Pw.w;
Pw.x = Pw.x * rhw;
Pw.y = Pw.y * rhw;
Pw.z = Pw.z * rhw;
// Store the vertex position.
m_pVertices[idx].x = Pw.x;
m_pVertices[idx].y = Pw.y;
m_pVertices[idx].z = Pw.z;
}
}
}
// -----------------------------------------------------------------------
550 splinePoint CDRGNURBSSurface::getData( int index )
{
return m_pVertices[index];
}
// -----------------------------------------------------------------------
//
// Implementation of the base class method.
//
// -----------------------------------------------------------------------
559 int CDRGNURBSSurface::GetTriangleCount( )
{
return 2 * m_iUTessellations * m_iVTessellations;
}
// -----------------------------------------------------------------------
//
// Change the control points of the surface. This method doesn't do any
// error checking, so it assumes the array passed in contains as many
// control points as where used when the surface was initialized.
//
// -----------------------------------------------------------------------
571 void CDRGNURBSSurface::UpdateControlPoints( Point4D *pControlPoints )
{
memcpy( m_pControlPoints, pControlPoints, m_iUControlPoints * m_iVControlPoints * sizeof( Point4D ) );
}
1 //
// C++ Implementation: EmberPagingLandScapeData2D_HeightField
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2005
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "EmberOgrePrerequisites.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "EmberPagingLandScapeData2D_HeightField.h"
#include "EmberPagingSceneManager.h"
#include "EmberOgre.h"
#include "terrain/TerrainPage.h"
#include "terrain/TerrainGenerator.h"
using namespace Ogre;
namespace EmberOgre
{
41 EmberPagingLandScapeData2D_HeightField::EmberPagingLandScapeData2D_HeightField( Ogre::PagingLandScapeData2DManager *pageMgr )
: Ogre::PagingLandScapeData2D( pageMgr ), mTerrainPage( 0 )
{
///set it to something, so it doesn't default to a crazy number ( like 5.79555e+022 ) since that will break stuff later on
///in regards to calculating the distance to the tile ( especially in PagingLandScapeTile::_Notify )
mMaxheight = 1;
}
49 bool EmberPagingLandScapeData2D_HeightField::_load( const Ogre::uint x, const Ogre::uint z )
{
assert( !mTerrainPage );
Terrain::TerrainGenerator* terrainGenerator = EmberOgre::getSingleton( ).getTerrainGenerator( );
mXDimension = mZDimension = terrainGenerator->getPageSize( );
mMaxArrayPos = mSize * mSize;
mHeightData = new Real[mMaxArrayPos];
mTerrainPage = terrainGenerator->getTerrainPage( Ogre::Vector2( x, z ) );
//should always return a TerrainPage*
assert( mTerrainPage );
mTerrainPage->createHeightData( mHeightData );
///make sure it's not 0
mMaxheight = std::max<float>( mTerrainPage->getMaxHeight( ), 1.0f );
mMax = static_cast <unsigned int> ( mSize * mTerrainPage->getMaxHeight( ) );
return true;
}
70 PagingLandScapeData2D* EmberPagingLandScapeData2D_HeightField::newPage( )
{
return new EmberPagingLandScapeData2D_HeightField( mParent );
}
76 const ColourValue EmberPagingLandScapeData2D_HeightField::getBase ( const Real mX, const Real mZ )
{
return ColourValue::White;
}
//-----------------------------------------------------------------------
84 const ColourValue EmberPagingLandScapeData2D_HeightField::getCoverage ( const Real mX, const Real mZ )
{
return ColourValue::Blue;
}
//-----------------------------------------------------------------------
91 const Real EmberPagingLandScapeData2D_HeightField::getShadow ( const Real mX, const Real mZ,
92 const bool &positive )
{
return 0.0f;
}
//-----------------------------------------------------------------------
100 const Vector3 EmberPagingLandScapeData2D_HeightField::getNormal ( const Real x, const Real z )
{
float height;
WFMath::Vector<3> normal;
EmberOgre::getSingleton( ).getTerrainGenerator( )->getTerrain( ).getHeightAndNormal( x, -z, height, normal );
return Atlas2Ogre( normal );
// return Ogre::PagingLandScapeData2D::getNormal( x, z );
}
//-----------------------------------------------------------------------
109 void EmberPagingLandScapeData2D_HeightField::_save( )
{
S_LOG_VERBOSE( "Saving terrain page at x: " << mPageX << " z:" << mPageZ << "." );
}
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
115 void EmberPagingLandScapeData2D_HeightField::_load( )
{
S_LOG_VERBOSE( "Loading ( _load( ) ) terrain page at x: " << mPageX << " z:" << mPageZ << "." );
}
//-----------------------------------------------------------------------
120 void EmberPagingLandScapeData2D_HeightField::_unload( )
{
S_LOG_VERBOSE( "Unloading terrain page at x: " << mPageX << " z:" << mPageZ << "." );
mTerrainPage = 0;
}
126 const Ogre::Real EmberPagingLandScapeData2D_HeightField::getMaxAbsoluteHeight( void ) const
{
///return a totally arbitrary high enough value
return 250.0f;
//return mMaxheight;
}
};
1 //
// C++ Implementation: EmberPagingLandScapeTexture
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2005
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "EmberPagingLandScapeTexture.h"
#include "EmberOgre.h"
#include "terrain/TerrainPage.h"
#include "terrain/TerrainGenerator.h"
namespace EmberOgre
{
32 EmberPagingLandScapeTexture::EmberPagingLandScapeTexture( Ogre::PagingLandScapeTextureManager *pageMgr )
: Ogre::PagingLandScapeTexture( pageMgr, "EmberTexture", 1, false )
{
}
37 EmberPagingLandScapeTexture::~EmberPagingLandScapeTexture( void )
{
}
41 Ogre::PagingLandScapeTexture* EmberPagingLandScapeTexture::newTexture( )
{
return new EmberPagingLandScapeTexture( mParent );
}
46 bool EmberPagingLandScapeTexture::isMaterialSupported( bool recursive )
{
//TODO: check for stuff here
return true;
}
52 void EmberPagingLandScapeTexture::setOptions( void )
{
}
56 void EmberPagingLandScapeTexture::_loadMaterial( )
{
Terrain::TerrainGenerator* terrainGenerator = EmberOgre::getSingleton( ).getTerrainGenerator( );
Terrain::TerrainPage* page = terrainGenerator->getTerrainPage( Ogre::Vector2( mDataX, mDataZ ) );
assert( page );
if ( page ) {
mMaterial = page->getMaterial( );
}
}
67 void EmberPagingLandScapeTexture::_unloadMaterial( )
{
S_LOG_VERBOSE( "Unloading terrain material." );
}
}
1 //
// C++ Implementation: EmberPagingSceneManager
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2005
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "EmberPagingSceneManager.h"
#include "EmberOgrePrerequisites.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeTextureManager.h"
#include "OgrePagingLandScapeOptions.h"
#include "EmberPagingLandScapeData2D_HeightField.h"
#include "EmberPagingLandScapeTexture.h"
#include "model/Model.h"
namespace EmberOgre {
const Ogre::String EmberPagingSceneManagerFactory::FACTORY_TYPE_NAME = "EmberPagingSceneManager";
//-----------------------------------------------------------------------
38 void EmberPagingSceneManagerFactory::initMetaData( void ) const
{
mMetaData.typeName = FACTORY_TYPE_NAME;
mMetaData.description = "Uses the PagingLandscapeSceneManager.";
mMetaData.sceneTypeMask = Ogre::ST_EXTERIOR_REAL_FAR; // support all types
mMetaData.worldGeometrySupported = false;
}
//-----------------------------------------------------------------------
46 Ogre::SceneManager* EmberPagingSceneManagerFactory::createInstance(
47 const Ogre::String& instanceName )
{
return new EmberPagingSceneManager( instanceName );
}
//-----------------------------------------------------------------------
52 void EmberPagingSceneManagerFactory::destroyInstance( Ogre::SceneManager* instance )
{
delete instance;
}
58 EmberPagingSceneManager::EmberPagingSceneManager( const Ogre::String &name ): PagingLandScapeSceneManager( name )
{
if ( !mOptions )
mOptions = new Ogre::PagingLandScapeOptions( this );
}
//-----------------------------------------------------------------------
66 void EmberPagingSceneManager::InitScene ( )
{
PagingLandScapeSceneManager::InitScene ( );
getData2DManager( )->registerDataType ( new EmberPagingLandScapeData2D_HeightField ( getData2DManager( ) ) );
getTextureManager( )->registerTextureType ( new EmberPagingLandScapeTexture ( getTextureManager( ) ) );
}
75 void EmberPagingSceneManager::registerProvider( IPageDataProvider* provider )
{
mProvider = provider;
}
80 Model::Model* EmberPagingSceneManager::createModel(
81 const Ogre::String& modelName,
82 const Ogre::String& modelDefinitionName )
{
// delegate to factory implementation
Ogre::NameValuePairList params;
params["modeldefinition"] = modelDefinitionName;
return static_cast<Model::Model*>(
createMovableObject( modelName, Model::ModelFactory::FACTORY_TYPE_NAME,
¶ms ) );
}
}
1 //
// C++ Implementation: EmberPagingSceneManagerAdapter
//
// Description:
//
//
// Author: Erik Hjortsberg <erik@katastrof.nu>, ( C ) 2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// ( at your option ) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
//
#include "EmberPagingSceneManagerAdapter.h"
#include "EmberPagingSceneManager.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapePageManager.h"
#include "OgrePagingLandScapePage.h"
namespace EmberOgre {
33 Ogre::PagingLandScapeOptions* EmberPagingSceneManagerAdapter::getOptions( )
{
return mSceneManager->getOptions( );
}
38 EmberPagingSceneManagerAdapter::EmberPagingSceneManagerAdapter( EmberPagingSceneManager* scenemanager ) : mSceneManager( scenemanager )
{
}
42 int EmberPagingSceneManagerAdapter::getPageSize( )
{
return getOptions( )->PageSize;
}
47 Ogre::Real EmberPagingSceneManagerAdapter::getHeightAt( const Ogre::Real x, const Ogre::Real z )
{
return mSceneManager->getHeightAt( x, z );
}
53 void EmberPagingSceneManagerAdapter::setWorldPagesDimensions( int numberOfPagesHeight, int numberOfPagesWidth, int heightOffsetInPages, int widthOffsetInPages )
{
///in order position ( 0, 0 ) to be aligned to the centre of the terrain we must offset the position of the terrain a bit
getOptions( )->position.z = ( ( numberOfPagesHeight * 0.5f ) - heightOffsetInPages ) * getOptions( )->PageSize;
getOptions( )->position.x = ( ( numberOfPagesWidth * 0.5f ) - widthOffsetInPages ) * getOptions( )->PageSize;
getOptions( )->world_height = numberOfPagesHeight;
getOptions( )->world_width = numberOfPagesWidth;
///update the options
getOptions( )->NumPages = getOptions( )->world_height * getOptions( )->world_width;
getOptions( )->maxUnScaledZ = getOptions( )->world_height * ( getOptions( )->PageSize - 1 ) * 0.5f;
getOptions( )->maxUnScaledX = getOptions( )->world_width * ( getOptions( )->PageSize - 1 ) * 0.5f;
getOptions( )->maxScaledZ = getOptions( )->scale.z * getOptions( )->maxUnScaledZ;
getOptions( )->maxScaledX = getOptions( )->scale.x * getOptions( )->maxUnScaledX;
}
72 void EmberPagingSceneManagerAdapter::resize( Ogre::AxisAlignedBox newSize, int levels )
{
mSceneManager->resize( newSize, levels );
}
77 void EmberPagingSceneManagerAdapter::setCamera( Ogre::Camera* camera )
{
mSceneManager->setOption( "primaryCamera", camera );
}
82 void EmberPagingSceneManagerAdapter::setResourceGroupName( const std::string& groupName )
{
mSceneManager->setOption( "GroupName", &groupName );
mSceneManager->getOptions( )->groupName = groupName;
mSceneManager->getOptions( )->cfgGroupName = groupName;
}
89 void EmberPagingSceneManagerAdapter::loadOptions( const std::string& filePath )
{
mSceneManager->getOptions( )->loadMapOptions( filePath );
mSceneManager->getOptions( )->setTextureFormat( "EmberTexture" );
}
96 void EmberPagingSceneManagerAdapter::loadScene( )
{
mSceneManager->loadScene( );
mSceneManager->getOptions( )->setOption( "LoadNow", 0 );
}
102 void EmberPagingSceneManagerAdapter::setOption( const std::string& strKey, const void* pValue )
{
mSceneManager->setOption( strKey, pValue );
}
107 void EmberPagingSceneManagerAdapter::getOption( const std::string& strKey, void* pDestValue )
{
mSceneManager->getOption( strKey, pDestValue );
}
112 Ogre::SceneManager* EmberPagingSceneManagerAdapter::getSceneManager( ) const
{
return mSceneManager;
}
117 void EmberPagingSceneManagerAdapter::reloadAllPages( )
{
mSceneManager->getPageManager( )->load( );
}
122 void EmberPagingSceneManagerAdapter::reloadPage( unsigned int x, unsigned int z )
{
Ogre::Vector2 position( x, z );
setOption( "PageUpdate", &position );
Ogre::PagingLandScapePage* page= mSceneManager->getPageManager( )->getPage( x, z, false );
if ( page ) {
// page->reload( );
page->unload( );
page->load( );
}
}
}
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright ( c ) 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreDebugRectangle2D.h"
#ifdef _VISIBILITYDEBUG
#include "OgreHardwareBufferManager.h"
#include "OgreCamera.h"
#include "OgreRoot.h"
namespace Ogre {
#define POSITION_BINDING 0
39 DebugRectangle2D::DebugRectangle2D( ) : SimpleRenderable ( )
{
#ifdef PLSM2_EIHORT
mUseIdentityProjection = true;
mUseIdentityView = true;
#endif
mRenderOp.indexData = new IndexData( );
mRenderOp.vertexData = new VertexData( );
mRenderOp.operationType = RenderOperation::OT_LINE_LIST;
mRenderOp.indexData->indexCount = 8;
mRenderOp.vertexData->vertexCount = 4;
mRenderOp.vertexData->vertexStart = 0;
mRenderOp.useIndexes = true;
VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration;
VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding;
decl->addElement( POSITION_BINDING, 0, VET_FLOAT3, VES_POSITION );
const size_t offset = VertexElement::getTypeSize( VET_FLOAT3 );
decl->addElement ( POSITION_BINDING, offset, VET_COLOUR, VES_DIFFUSE );
mRenderOp.indexData->indexBuffer = HardwareBufferManager::getSingleton( ).createIndexBuffer(
HardwareIndexBuffer::IT_16BIT,
mRenderOp.indexData->indexCount,
HardwareBuffer::HBU_STATIC_WRITE_ONLY );
HardwareVertexBufferSharedPtr vbuf =
HardwareBufferManager::getSingleton( ).createVertexBuffer(
decl->getVertexSize( POSITION_BINDING ),
mRenderOp.vertexData->vertexCount,
HardwareBuffer::HBU_STATIC_WRITE_ONLY );
// Bind buffer
bind->setBinding( POSITION_BINDING, vbuf );
SimpleRenderable::setBoundingBox( AxisAlignedBox( -1000 * Vector3::UNIT_SCALE,
1000 * Vector3::UNIT_SCALE ) );
SimpleRenderable::setRenderQueueGroup ( RENDER_QUEUE_OVERLAY );
// set basic white material
SimpleRenderable::setMaterial( "BaseWhiteNoLighting" );
}
85 DebugRectangle2D::~DebugRectangle2D( )
{
delete mRenderOp.vertexData;
delete mRenderOp.indexData;
}
91 void DebugRectangle2D::setCorners( Real left, Real top, Real right, Real bottom )
{
VertexDeclaration * const decl = mRenderOp.vertexData->vertexDeclaration;
const VertexElement* poselem = decl->findElementBySemantic( VES_POSITION );
const VertexElement* colorelem = decl->findElementBySemantic( VES_DIFFUSE );
HardwareVertexBufferSharedPtr vbuf =
mRenderOp.vertexData->vertexBufferBinding->getBuffer( POSITION_BINDING );
const size_t vertexSize = vbuf->getVertexSize ( );
float *pPos;
RGBA *pColor;
Root * const root = Root::getSingletonPtr( );
uchar* pMain = static_cast<uchar *>(
vbuf->lock( HardwareBuffer::HBL_DISCARD ) );
// #define V3( AX, AY, AZ, ACOLOR ) poselem->baseVertexPointerToElement( pMain, &pPos ); \
// *pPos++ = AX; *pPos++ = AY; *pPos++ = AZ; \
// pMain += vertexSize;
#define V3( A_X, A_Y, A_Z, ACOLOR ) poselem->baseVertexPointerToElement( pMain, &pPos ); \
*pPos++ = static_cast <float> ( A_X ); \
*pPos++ = static_cast <float> ( A_Y ); \
*pPos++ = static_cast <float> ( A_Z ); \
colorelem->baseVertexPointerToElement( pMain, &pColor ); \
root->convertColourValue ( ACOLOR, pColor ); \
pMain += vertexSize;
V3( left, top, -1.0f, ColourValue::White )
V3( left, bottom, -1.0f, ColourValue::White )
V3( right, bottom, -1.0f, ColourValue::White )
V3( right, top, -1.0f, ColourValue::White )
vbuf->unlock( );
HardwareIndexBufferSharedPtr iBuf = mRenderOp.indexData->indexBuffer;
ushort* pIdx = static_cast<ushort*>(
iBuf->lock( 0, iBuf->getSizeInBytes( ), HardwareBuffer::HBL_DISCARD ) );
*pIdx++ = static_cast<ushort> ( 0 ); *pIdx++ = static_cast<ushort> ( 1 ); // line 1
*pIdx++ = static_cast<ushort> ( 1 ); *pIdx++ = static_cast<ushort> ( 2 ); // line 2
*pIdx++ = static_cast<ushort> ( 2 ); *pIdx++ = static_cast<ushort> ( 3 ); // line 3
140 *pIdx++ = static_cast<ushort> ( 3 ); *pIdx++ = static_cast<ushort> ( 0 ); // line 4
iBuf->unlock( );
}
// Override this method to prevent parent transforms ( rotation, translation, scale )
146 void DebugRectangle2D::getWorldTransforms( Matrix4* xform ) const
{
// return identity matrix to prevent parent transforms
*xform = Matrix4::IDENTITY;
}
151 //-----------------------------------------------------------------------
const Quaternion& DebugRectangle2D::getWorldOrientation( void ) const
{
return Quaternion::IDENTITY;
}
//-----------------------------------------------------------------------
const Vector3& DebugRectangle2D::getWorldPosition( void ) const
{
return Vector3::ZERO;
}
}
#endif //_VISIBILITYDEBUG
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright ( c ) 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "Ogre.h"
#include "OgreOcclusionBoundingBox.h"
#include "OgreSimpleRenderable.h"
#include "OgreHardwareBufferManager.h"
#include "OgreCamera.h"
namespace Ogre {
#define POSITION_BINDING 0
//-----------------------------------------------------------------------
39 OcclusionBoundingBox::OcclusionBoundingBox( )
{
mRenderOp.indexData = new IndexData( );
mRenderOp.vertexData = new VertexData( );
mRenderOp.operationType = RenderOperation::OT_TRIANGLE_LIST;
mRenderOp.indexData->indexCount = 36;
mRenderOp.vertexData->vertexCount = 24;
mRenderOp.vertexData->vertexStart = 0;
mRenderOp.useIndexes = true;
VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration;
VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding;
decl->addElement( POSITION_BINDING, 0, VET_FLOAT3, VES_POSITION );
//const size_t offset = VertexElement::getTypeSize( VET_FLOAT3 );
//decl->addElement ( POSITION_BINDING, offset, VET_COLOUR, VES_DIFFUSE );
mRenderOp.indexData->indexBuffer = HardwareBufferManager::getSingleton( ).createIndexBuffer(
HardwareIndexBuffer::IT_16BIT,
mRenderOp.indexData->indexCount,
HardwareBuffer::HBU_STATIC_WRITE_ONLY );
HardwareVertexBufferSharedPtr vbuf =
HardwareBufferManager::getSingleton( ).createVertexBuffer(
decl->getVertexSize( POSITION_BINDING ),
mRenderOp.vertexData->vertexCount,
HardwareBuffer::HBU_STATIC_WRITE_ONLY );
// Bind buffer
bind->setBinding( POSITION_BINDING, vbuf );
this->setPolygonModeOverrideable ( false );
//Renderable::getPolygonMode ( );
// set basic white material
this->setMaterial( "BaseWhiteNoLightNoDepthCheckWrite" );
}
//-----------------------------------------------------------------------
78 PolygonMode OcclusionBoundingBox:: getRenderDetail( ) const
{
//return PM_WIREFRAME;
return PM_SOLID;
}
//-----------------------------------------------------------------------
85 OcclusionBoundingBox::~OcclusionBoundingBox( )
{
delete mRenderOp.indexData;
delete mRenderOp.vertexData;
}
//-----------------------------------------------------------------------
91 void OcclusionBoundingBox::setupBoundingBox( const AxisAlignedBox& aabb )
{
// init the vertices to the aabb
setupBoundingBoxVertices( aabb );
// setup the bounding box of this SimpleRenderable
setBoundingBox( aabb );
}
//-----------------------------------------------------------------------
// Override this method to prevent parent transforms ( rotation, translation, scale )
102 void OcclusionBoundingBox::getWorldTransforms( Matrix4* xform ) const
{
// return identity matrix to prevent parent transforms
*xform = Matrix4::IDENTITY;
}
//-----------------------------------------------------------------------
108 const Quaternion& OcclusionBoundingBox::getWorldOrientation( void ) const
{
return Quaternion::IDENTITY;
}
//-----------------------------------------------------------------------
113 const Vector3& OcclusionBoundingBox::getWorldPosition( void ) const
{
return Vector3::ZERO;
}
//-----------------------------------------------------------------------
118 void OcclusionBoundingBox::setupBoundingBoxVertices( const AxisAlignedBox& aab )
{
const Vector3 &max = aab.getMaximum( );
const Vector3 &min = aab.getMinimum( );
const Real sqLen = std::max( max.squaredLength( ),
min.squaredLength( ) );
mRadius = Math::Sqrt( sqLen );
VertexDeclaration * const decl = mRenderOp.vertexData->vertexDeclaration;
const VertexElement* poselem = decl->findElementBySemantic( VES_POSITION );
//const VertexElement* colorelem = decl->findElementBySemantic( VES_DIFFUSE );
HardwareVertexBufferSharedPtr vbuf =
mRenderOp.vertexData->vertexBufferBinding->getBuffer( POSITION_BINDING );
const size_t vertexSize = vbuf->getVertexSize ( );
float *pPos;
//RGBA *pColor;
//Root * const root = Root::getSingletonPtr( );
uchar* pMain = static_cast<uchar *>(
vbuf->lock( HardwareBuffer::HBL_DISCARD ) );
//generate 8 corners of the bbox
// RightHanded
#define V3( A_X, A_Y, A_Z, ACOLOR ) poselem->baseVertexPointerToElement( pMain, &pPos ); \
*pPos++ = static_cast <float> ( A_X ); \
*pPos++ = static_cast <float> ( A_Y ); \
*pPos++ = static_cast <float> ( A_Z ); \
pMain += vertexSize;
// #define V3( AX, AY, AZ, ACOLOR ) poselem->baseVertexPointerToElement( pMain, &pPos ); \
// *pPos++ = AX; *pPos++ = AY; *pPos++ = AZ; \
// colorelem->baseVertexPointerToElement( pMain, &pColor ); \
// root->convertColourValue ( ACOLOR, pColor ); \
// pMain += vertexSize;
V3( min.x, max.y, max.z, ColourValue::White ) // 1
V3( min.x, min.y, max.z, ColourValue::White ) // 2
V3( max.x, max.y, max.z, ColourValue::White ) // 3
V3( max.x, min.y, max.z, ColourValue::White ) // 4
V3( max.x, max.y, min.z, ColourValue::White ) // 5
V3( max.x, min.y, min.z, ColourValue::White ) // 6
V3( min.x, max.y, min.z, ColourValue::White ) // 7
V3( min.x, min.y, min.z, ColourValue::White ) // 8
vbuf->unlock( );
HardwareIndexBufferSharedPtr iBuf = mRenderOp.indexData->indexBuffer;
ushort* pIdx = static_cast<ushort*>(
iBuf->lock( 0, iBuf->getSizeInBytes( ), HardwareBuffer::HBL_DISCARD ) );
*pIdx++ = static_cast<ushort> ( 0 ); *pIdx++ = static_cast<ushort> ( 1 ); *pIdx++ = static_cast<ushort> ( 2 );
*pIdx++ = static_cast<ushort> ( 1 ); *pIdx++ = static_cast<ushort> ( 3 ); *pIdx++ = static_cast<ushort> ( 2 );
*pIdx++ = static_cast<ushort> ( 2 ); *pIdx++ = static_cast<ushort> ( 3 ); *pIdx++ = static_cast<ushort> ( 4 );
*pIdx++ = static_cast<ushort> ( 3 ); *pIdx++ = static_cast<ushort> ( 5 ); *pIdx++ = static_cast<ushort> ( 4 );
*pIdx++ = static_cast<ushort> ( 6 ); *pIdx++ = static_cast<ushort> ( 5 ); *pIdx++ = static_cast<ushort> ( 7 );
*pIdx++ = static_cast<ushort> ( 5 ); *pIdx++ = static_cast<ushort> ( 7 ); *pIdx++ = static_cast<ushort> ( 6 );
*pIdx++ = static_cast<ushort> ( 6 ); *pIdx++ = static_cast<ushort> ( 7 ); *pIdx++ = static_cast<ushort> ( 0 );
*pIdx++ = static_cast<ushort> ( 7 ); *pIdx++ = static_cast<ushort> ( 1 ); *pIdx++ = static_cast<ushort> ( 0 );
*pIdx++ = static_cast<ushort> ( 4 ); *pIdx++ = static_cast<ushort> ( 6 ); *pIdx++ = static_cast<ushort> ( 0 );
*pIdx++ = static_cast<ushort> ( 4 ); *pIdx++ = static_cast<ushort> ( 0 ); *pIdx++ = static_cast<ushort> ( 2 );
*pIdx++ = static_cast<ushort> ( 1 ); *pIdx++ = static_cast<ushort> ( 7 ); *pIdx++ = static_cast<ushort> ( 3 );
*pIdx++ = static_cast<ushort> ( 7 ); *pIdx++ = static_cast<ushort> ( 5 ); *pIdx++ = static_cast<ushort> ( 3 );
189
iBuf->unlock( );
}
//-----------------------------------------------------------------------
Real OcclusionBoundingBox::getSquaredViewDepth( const Camera* cam ) const
{
const Vector3 &min = mBox.getMinimum( );
const Vector3 &max = mBox.getMaximum( );
const Vector3 mid = ( ( max - min ) * 0.5f ) + min;
const Vector3 dist = cam->getDerivedPosition( ) - mid;
return dist.squaredLength( );
}
}
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
OgrePagingLandScapeAxisAlignedBoxSceneQuery.cpp - description
-------------------
begin : Sat Oct 15, 2006
copyright : ( C ) 2006 by Steven Klug
email : stevenklug@san.rr.com
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgrePagingLandScapeData2D.h"
#include "OgrePagingLandScapeAxisAlignedBoxSceneQuery.h"
#include "OgrePagingLandScapeSceneManager.h"
#include "OgreEntity.h"
#include "OgrePagingLandScapeTile.h"
#include "OgrePagingLandScapePage.h"
#include "OgrePagingLandScapePageManager.h"
using namespace Ogre;
namespace Ogre
{
// NOTE: Creating some of my own conversion functions here even though
// these are somewhat duplicating code in the page manager. It was
// more for the exercise of getting clear in my head the differences
// between world coords, page local coords, page numbers, tiles, etc.
// May convert back to the ones in the page manager eventually, though
// these may offer some speed advantages as some redundant calculations
// ( invPageSize, etc. ) are only done once in the main query.
//-----------------------------------------------------------------------
// Scale a coordinate from world space to page number and coord for local
// unscaled page space.
inline
63 bool WorldToPage( Real coord, Real scale, Real maxUnScaled, uint pageSize, Real invPageSize, uint worldExtent,
uint& pageNumber, Real& localPageCoord )
{
// scale position from world to page scale
Real unscaled = ( coord / scale ) + maxUnScaled;
// get Page
Real value = unscaled * invPageSize;
uint maxPage = static_cast<int>( worldExtent );
// Set output params.
pageNumber = static_cast<int>( value );
if( value < 0.0 )
{
pageNumber = 0;
localPageCoord = 0.0;
return false;
}
else if( pageNumber >= maxPage )
{
pageNumber = maxPage - 1;
localPageCoord = pageNumber * pageSize + pageSize - 1;
return false;
}
else
{
localPageCoord = unscaled - ( pageNumber * pageSize );
return true;
}
}
//-----------------------------------------------------------------------
inline
95 Real PageToWorld( uint pageNumber, Real localPageCoord, Real scale, Real maxUnScaled, uint pageSize )
{
Real unscaled = localPageCoord + pageNumber * pageSize;
return ( unscaled - maxUnScaled ) * scale;
}
//-----------------------------------------------------------------------
// Scale a coordinate from local page space to tile number.
inline
104 uint PageToTile( int localPageCoord, Real invTileSize, uint maxNumTiles )
{
// get Tile
uint value = static_cast< uint > ( localPageCoord * invTileSize );
return ( value < 0 ) ? 0 : ( value >= maxNumTiles ? maxNumTiles - 1: value );
}
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// Operations and data for render levels ( lod levels ).
115 class RenderLevel
{
int renderLevel_;
int lodStep_;
119 uint lodMask_;
public:
//-----------------------------------------------------------------------
122 RenderLevel( )
{
SetRenderLevel( 0 );
}
//-----------------------------------------------------------------------
127 RenderLevel( int renderLevel )
{
SetRenderLevel( renderLevel );
}
//-----------------------------------------------------------------------
132 void SetRenderLevel( int renderLevel )
{
renderLevel_ = renderLevel;
lodStep_ = 1 << renderLevel;
lodMask_ = ~( lodStep_ - 1 );
}
//-----------------------------------------------------------------------
139 int GetRenderLevel( ) const
{
return renderLevel_;
}
//-----------------------------------------------------------------------
144 int GetLodStep( ) const
{
return lodStep_;
}
//-----------------------------------------------------------------------
149 uint GetLodMask( ) const
{
return lodMask_;
}
//-----------------------------------------------------------------------
154 bool operator < ( const RenderLevel& rhs ) const
{
return renderLevel_ < rhs.renderLevel_;
}
//-----------------------------------------------------------------------
// Step the input coordinate by the lodStep.
160 int LodStep( int localPageCoord ) const
{
return localPageCoord + lodStep_;
}
//-----------------------------------------------------------------------
// Return the floor of the passed in coord based on valid LOD.
166 int Floor( int localPageCoord ) const
{
return localPageCoord & lodMask_;
}
//-----------------------------------------------------------------------
// Return the ceiling of the passed in coord based on valid LOD.
172 int Ceil( int localPageCoord ) const
{
if( Floor( localPageCoord ) == localPageCoord )
return localPageCoord; // Already at ceiling.
else
return Floor( localPageCoord + lodStep_ );
}
//-----------------------------------------------------------------------
180 int GetLodLevel( ) const
{
return lodStep_;
}
};
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// Object responsible for caching tile changes specific to lod stepping.
190 class LodTracker
{
192 const Vector3 scale_;
193 const Real maxUnScaledX_;
194 const Real maxUnScaledZ_;
195 const uint pageSize_;
196 const Real invPageSize_;
197 const uint tileSize_;
198 const Real invTileSize_;
199 const uint maxNumTiles_;
200 PagingLandScapePageManager* pageMgr_;
201 PagingLandScapeData2DManager* dataMgr_;
203 const PagingLandScapePage* page_;
204 const PagingLandScapeData2D* pageData_;
205 PagingLandScapeTile* tile_;
206 RenderLevel renderLevel_;
207 uint pageX_;
208 uint pageZ_;
public:
//-----------------------------------------------------------------------
LodTracker( Vector3 scale,
Real maxUnScaledX,
Real maxUnScaledZ,
uint pageSize,
uint tileSize,
uint maxNumTiles,
PagingLandScapePageManager* pageMgr,
PagingLandScapeData2DManager* dataMgr )
: scale_( scale )
, maxUnScaledX_( maxUnScaledX )
, maxUnScaledZ_( maxUnScaledZ )
, pageSize_( pageSize )
, invPageSize_( 1.0f / pageSize )
, tileSize_( tileSize )
, invTileSize_( 1.0f / tileSize )
, maxNumTiles_( maxNumTiles )
, pageMgr_( pageMgr )
, dataMgr_( dataMgr )
, page_( 0 )
, pageData_( 0 )
, tile_( 0 )
, pageX_( 0 )
, pageZ_( 0 ) {}
//-----------------------------------------------------------------------
236 uint GetTileSize( ) const
{
return tileSize_;
}
//-----------------------------------------------------------------------
241 Real GetInvTileSize( ) const
{
return invTileSize_;
}
//-----------------------------------------------------------------------
246 uint GetMaxNumTiles( ) const
{
return maxNumTiles_;
}
//-----------------------------------------------------------------------
251 const RenderLevel& GetRenderLevel( ) const
{
return renderLevel_;
}
//-----------------------------------------------------------------------
256 const PagingLandScapePage* GetPage( ) const
{
return page_;
}
//-----------------------------------------------------------------------
261 uint GetPageX( ) const
{
return pageX_;
}
//-----------------------------------------------------------------------
266 uint GetPageZ( ) const
{
return pageZ_;
}
//-----------------------------------------------------------------------
// Returns true if the vertex is included, or false if it is removed
// by LOD. Requires local page coordinates.
273 bool GetWorldVertex( int localPageX, int localPageZ, Vector3& vertex )
{
UpdateWithLocalPage( localPageX, localPageZ );
bool included = ( renderLevel_.Floor( localPageX ) == localPageX &&
renderLevel_.Floor( localPageZ ) == localPageZ );
if( page_ && page_->isLoaded( ) && pageData_ )
{
// TODO: Do we really need to include the real data when the vertex
// has been removed by lod? Or can we just stuff a dummy result in
// here to fill out the array?
vertex.y = pageData_->getHeight( localPageX, localPageZ );
page_->getCoordinates( pageX_, pageZ_ );
vertex.x = PageToWorld( pageX_, localPageX, scale_.x, maxUnScaledX_, pageSize_ );
vertex.z = PageToWorld( pageZ_, localPageZ, scale_.z, maxUnScaledZ_, pageSize_ );
}
return included;
}
//-----------------------------------------------------------------------
// Set the current page. Must be called before Update( ).
292 void SetPage( const PagingLandScapePage* page )
{
page_ = page;
if( page_ && page_->isLoaded( ) )
{
page_->getCoordinates( pageX_, pageZ_ );
pageData_ = dataMgr_->getData2D( pageX_, pageZ_, false );
}
}
//-----------------------------------------------------------------------
// Sets the page using the page coordinates.
303 void SetPage( int pageX, int pageZ )
{
const PagingLandScapePage* page = pageMgr_->getPage( pageX, pageZ, false );
if( !page || !page->isLoaded( ) )
{
assert( false );
return; // TODO: Currently the AABB must be on the currently loaded landscape.
}
SetPage( page );
}
//-----------------------------------------------------------------------
// Update using page local tile coordinates.
315 void UpdateTile( int tileX, int tileZ )
{
PagingLandScapeTile* tile = page_->getTile( tileX, tileZ );
if( tile != tile_ )
{
tile_ = tile;
bool tileLoaded = tile_ && tile_->isLoaded( ) && tile_->getRenderable( );
renderLevel_.SetRenderLevel( ( tileLoaded ) ? tile_->getRenderable( )->getRenderLevel( ) : 0 );
}
}
//-----------------------------------------------------------------------
// Update our lodStep and lodMask for the current tile, given the page
// local coordinates of a vertex.
328 void UpdateWithLocalPage( int localPageX, int localPageZ )
{
int tileX = PageToTile( localPageX, invTileSize_, maxNumTiles_ );
int tileZ = PageToTile( localPageZ, invTileSize_, maxNumTiles_ );
UpdateTile( tileX, tileZ );
}
};
//-----------------------------------------------------------------------
// Loop over every edge tile. Determine which the lowest lod on each edge
// and use that to adjust the extents.
// TODO: This routine is expensive, and is only needed when LOD is involved.
// Optimize? Ironic since LOD is supposed to make things faster.
342 void AdjustEdgesForLod( LodTracker& lodTracker,
int minPageX, int minPageZ, int maxPageX, int maxPageZ,
int& localPageMinX, int& localPageMinZ, int& localPageMaxX, int& localPageMaxZ )
{
int minTileZ = PageToTile( localPageMinZ,
lodTracker.GetInvTileSize( ),
lodTracker.GetMaxNumTiles( ) );
int maxTileZ = PageToTile( localPageMaxZ,
lodTracker.GetInvTileSize( ),
lodTracker.GetMaxNumTiles( ) );
int minTileX = PageToTile( localPageMinX,
lodTracker.GetInvTileSize( ),
lodTracker.GetMaxNumTiles( ) );
int maxTileX = PageToTile( localPageMaxX,
lodTracker.GetInvTileSize( ),
lodTracker.GetMaxNumTiles( ) );
int westRenderLevel = 0;
int eastRenderLevel = 0;
for( int pageZ = minPageZ; pageZ <= maxPageZ; ++pageZ )
{
int endTileZ = ( pageZ == maxPageZ ) ? maxTileZ : lodTracker.GetMaxNumTiles( ) - 1;
for( int tileZ = ( pageZ == minPageZ ) ? minTileZ : 0;
tileZ <= endTileZ;
++tileZ )
{
// West edge
lodTracker.SetPage( minPageX, pageZ );
lodTracker.UpdateTile( minTileX, tileZ );
int renderLevel = lodTracker.GetRenderLevel( ).GetRenderLevel( );
if( renderLevel > westRenderLevel )
westRenderLevel = renderLevel;
// East edge
lodTracker.SetPage( maxPageX, pageZ );
lodTracker.UpdateTile( maxTileX, tileZ );
renderLevel = lodTracker.GetRenderLevel( ).GetRenderLevel( );
if( renderLevel > eastRenderLevel )
eastRenderLevel = renderLevel;
}
}
int northRenderLevel = 0;
int southRenderLevel = 0;
for( int pageX = minPageX; pageX <= maxPageX; ++pageX )
{
int endTileX = ( pageX == maxPageX ) ? maxTileX : lodTracker.GetMaxNumTiles( ) - 1;
for( int tileX = ( pageX == minPageX ) ? minTileX : 0;
tileX <= endTileX;
++tileX )
{
// North edge
lodTracker.SetPage( pageX, minPageZ );
lodTracker.UpdateTile( tileX, minTileZ );
int renderLevel = lodTracker.GetRenderLevel( ).GetRenderLevel( );
if( renderLevel > northRenderLevel )
northRenderLevel = renderLevel;
// South edge
lodTracker.SetPage( pageX, maxPageZ );
lodTracker.UpdateTile( tileX, maxTileZ );
renderLevel = lodTracker.GetRenderLevel( ).GetRenderLevel( );
if( renderLevel > southRenderLevel )
southRenderLevel = renderLevel;
}
}
// Use the lods we found to adjust the min and max local coords.
RenderLevel renderLevel( westRenderLevel );
localPageMinX = renderLevel.Floor( localPageMinX );
renderLevel.SetRenderLevel( eastRenderLevel );
localPageMaxX = renderLevel.Ceil( localPageMaxX );
renderLevel.SetRenderLevel( northRenderLevel );
localPageMinZ = renderLevel.Floor( localPageMinZ );
renderLevel.SetRenderLevel( southRenderLevel );
localPageMaxZ = renderLevel.Ceil( localPageMaxZ );
}
//-----------------------------------------------------------------------
417 void DoTileSubSection( LodTracker& lodTracker,
SceneQuery::WorldFragment& worldFragment,
PagingLandScapeAxisAlignedBoxSceneQuery::CustomQueryResult& queryResult,
SceneQueryListener* listener,
int localPageMinX, int localPageMinZ, int localPageMaxX, int localPageMaxZ,
uint subX, uint subZ )
{
lodTracker.UpdateWithLocalPage( localPageMinX, localPageMinZ );
// Send the width and height of this sub-section.
queryResult.SetSubsectionExtents( localPageMaxX - localPageMinX + 1,
localPageMaxZ - localPageMinZ + 1,
lodTracker.GetRenderLevel( ).GetRenderLevel( ),
subX, subZ );
listener->queryResult( &worldFragment );
for( int z = localPageMinZ; z <= localPageMaxZ; ++z )
{
for( int x = localPageMinX; x <= localPageMaxX; ++x )
{
Vector3 vertex;
bool included = lodTracker.GetWorldVertex( x, z, vertex );
queryResult.SetVertex( vertex, included );
listener->queryResult( &worldFragment );
}
}
}
}
namespace Ogre
{
//---------------------------------------------------------------------
PagingLandScapeAxisAlignedBoxSceneQuery::PagingLandScapeAxisAlignedBoxSceneQuery( SceneManager* creator )
: DefaultAxisAlignedBoxSceneQuery( creator )
{
}
//---------------------------------------------------------------------
PagingLandScapeAxisAlignedBoxSceneQuery::~PagingLandScapeAxisAlignedBoxSceneQuery( void )
{
}
//---------------------------------------------------------------------
// Well return via callbacks a set of rectangular tile sub-sections.
// All fragments returned via callback use a WFT_CUSTOM_GEOMETRY type.
// The CustomQueryResult structure defined above is what is passed
// in the void* geometry field. The type_ field of the CustomQuery
// result determins what is being sent in the fragment as follows:
//
// QUERY_EXTENTS_TYPE: Sent as the first result, this gives the width
// and height ( in tile subsections ) of the entire query result. The
// render level in this case is not defined.
//
// SUBSECTION_EXTENTS_TYPE: Sent before each sub-section's vertex
// data. This contains the height, width, and render level of the
// subsequent vertex data.
//
// VERTEX_TYPE: This is the actual vertex data, and whether the vertex
// is included when displayed at the tile's current render level.
//
// The seemingly complex way of returning the data is so that the same
// stitching algorithm used by PLSM can be used by the client in
// creating a mesh out of the data.
//---------------------------------------------------------------------
void PagingLandScapeAxisAlignedBoxSceneQuery::execute( SceneQueryListener* listener )
{
if( !( getQueryTypeMask( ) & SceneManager::WORLD_GEOMETRY_TYPE_MASK ) )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
"PagingLandScapeSceneManager only supports WORLD_GEOMETRY_TYPE_MASK for AxisAlignedBoxSceneQueries",
"PagingLandScapeAxisAlignedBoxSceneQuery::execute" );
}
PagingLandScapeSceneManager* mgr = static_cast< PagingLandScapeSceneManager* >( mParentSceneMgr );
// Currently we ignore the y coords of the bounding box and assume they
// want all the vertices in the xz square.
// Determine page that each corner of AABB is on.
Vector3 min = mAABB.getMinimum( );
Vector3 max = mAABB.getMaximum( );
// Pre-gather some constants.
const PagingLandScapeOptions* options = mgr->getOptions( );
const Vector3& scale = options->scale;
const Real maxUnScaledX = options->maxUnScaledX;
const Real maxUnScaledZ = options->maxUnScaledZ;
const uint pageSize = options->PageSize - 1;
const Real invPageSize = 1.0f / pageSize;
const uint tileSize = options->TileSize - 1;
const Real invTileSize = 1.0f / tileSize;
const uint maxNumTiles = options->NumTiles;
const uint worldWidth = options->world_width;
const uint worldHeight = options->world_height;
// Note that for efficiency here, I'm not allocating a new WorldFragment
// every time, so clients will have to use the subscribtion mechanism to
// get the results, as the execute( ) that returns the SceneQueryResult
// will contain a collection of only the last result. TODO: The ogre
// RegionSceneQuery could be modified to only do heap allocation when
// the subscription mechanism isn't being used by the client.
WorldFragment worldFragment;
worldFragment.fragmentType = SceneQuery::WFT_CUSTOM_GEOMETRY;
CustomQueryResult result;
worldFragment.geometry = &result;
// Calculate page min/max.
uint minPageX;
Real localPageMinXReal;
bool minXInWorld;
uint minPageZ;
Real localPageMinZReal;
bool minZInWorld;
uint maxPageX;
Real localPageMaxXReal;
bool maxXInWorld;
uint maxPageZ;
Real localPageMaxZReal;
bool maxZInWorld;
minXInWorld = WorldToPage( min.x, scale.x, maxUnScaledX, pageSize, invPageSize, worldWidth, minPageX, localPageMinXReal );
minZInWorld = WorldToPage( min.z, scale.z, maxUnScaledZ, pageSize, invPageSize, worldHeight, minPageZ, localPageMinZReal );
maxXInWorld = WorldToPage( max.x, scale.x, maxUnScaledX, pageSize, invPageSize, worldWidth, maxPageX, localPageMaxXReal );
maxZInWorld = WorldToPage( max.z, scale.z, maxUnScaledZ, pageSize, invPageSize, worldHeight, maxPageZ, localPageMaxZReal );
// At least one corner of the bounding box must be inside the world, or
// we return no results.
if( !( minXInWorld && minZInWorld ) || !( maxXInWorld && maxZInWorld ) ||
!( minXInWorld && maxZInWorld ) || !( maxXInWorld && minZInWorld ) )
return;
// Determine the width and height of the query in terms of tile sub-sections.
// We need to make sure we return enough vertices so the entire bounding box
// fits within. That means for lodded tiles we may need to move to the
// next valid vertex, however, satisfying this requirement should never change
// the query extents because every tile has valid vertices at its edges.
int localPageMinX = static_cast<int>( localPageMinXReal );
int localPageMinZ = static_cast<int>( localPageMinZReal );
int localPageMaxX = static_cast<int>( Math::Ceil( localPageMaxXReal ) );
int localPageMaxZ = static_cast<int>( Math::Ceil( localPageMaxZReal ) );
LodTracker lodTracker( scale,
maxUnScaledX,
maxUnScaledZ,
pageSize,
tileSize,
maxNumTiles,
mgr->getPageManager( ),
mgr->getData2DManager( ) );
// TODO: Expensive routine. Can we do away with it or optimze it somehow?
AdjustEdgesForLod( lodTracker,
minPageX, minPageZ, maxPageX, maxPageZ,
localPageMinX, localPageMinZ, localPageMaxX, localPageMaxZ );
// Pre-calculate the width and height of the whole query in terms of how many
// tile sub-sections we'll have.
int middleTiles = ( static_cast<int>( maxPageX ) - static_cast<int>( minPageX ) - 1 ) *
( pageSize / tileSize ); // Get the contribution from the middle pages.
int leftTiles = ( maxNumTiles - PageToTile( localPageMinX,
invTileSize,
maxNumTiles ) ); // Get contribution from the left side.
int rightTiles = PageToTile( localPageMaxX - 1,
invTileSize,
maxNumTiles ) + 1; // Get contribution from the right side.
int calcWidth = leftTiles + middleTiles + rightTiles;
middleTiles = ( static_cast<int>( maxPageZ ) - static_cast<int>( minPageZ ) - 1 ) *
( pageSize / tileSize ); // Get the contribution from the middle pages.
leftTiles = ( maxNumTiles - PageToTile( localPageMinZ,
invTileSize,
maxNumTiles ) ); // Get contribution from the left side.
rightTiles = PageToTile( localPageMaxZ - 1,
invTileSize,
maxNumTiles ) + 1; // Get contribution from the right side.
int calcHeight = leftTiles + middleTiles + rightTiles;
//Real calcWidth = ( maxPageX == minPageX ) ? localPageMaxX - localPageMinX + 1 :
// ( pageSize - localPageMinX ) + localPageMaxX + 1 +
// ( maxPageX - minPageX - 1 ) * pageSize;
//Real calcHeight = ( maxPageZ == minPageZ ) ? localPageMaxZ - localPageMinZ + 1 :
// ( pageSize - localPageMinZ ) + localPageMaxZ + 1 +
// ( maxPageZ - minPageZ - 1 ) * pageSize;
// Notify our caller about the width and height, using custom geometry type.
result.SetQueryExtents( calcWidth, calcHeight );
listener->queryResult( &worldFragment );
uint subZ = 0;
for( uint pageZ = minPageZ; pageZ <= maxPageZ; ++pageZ )
{
// Determine Z tile range on this page.
uint tileBeginZ = ( pageZ == minPageZ ) ?
PageToTile( localPageMinZ, invTileSize, maxNumTiles ) : 0;
uint tileEndZ = ( pageZ == maxPageZ ) ?
PageToTile( localPageMaxZ - 1, invTileSize, maxNumTiles ) : maxNumTiles - 1;
for( uint tileZ = tileBeginZ; tileZ <= tileEndZ; ++tileZ, ++subZ )
{
uint subX = 0;
for( uint pageX = minPageX; pageX <= maxPageX; ++pageX )
{
lodTracker.SetPage( pageX, pageZ );
// Determine X tile range on this page.
uint tileBeginX = ( pageX == minPageX ) ? PageToTile( localPageMinX, invTileSize, maxNumTiles ) : 0;
uint tileEndX = ( pageX == maxPageX ) ? PageToTile( localPageMaxX - 1, invTileSize, maxNumTiles ) : maxNumTiles - 1;
for( uint tileX = tileBeginX; tileX <= tileEndX; ++tileX, ++subX )
{
// Determine the Z local page coord range for this tile.
uint localPageBeginZ = ( pageZ == minPageZ ) && ( tileZ == tileBeginZ ) ?
localPageMinZ : tileZ * tileSize;
uint localPageEndZ = ( pageZ == maxPageZ ) && ( tileZ == tileEndZ ) ?
localPageMaxZ : ( tileZ + 1 ) * tileSize;
// Determine the X local page coord range for this tile.
uint localPageBeginX = ( pageX == minPageX ) && ( tileX == tileBeginX ) ?
localPageMinX : tileX * tileSize;
uint localPageEndX = ( pageX == maxPageX ) && ( tileX == tileEndX ) ?
localPageMaxX : ( tileX + 1 ) * tileSize;
DoTileSubSection( lodTracker, worldFragment, result, listener,
localPageBeginX, localPageBeginZ, localPageEndX, localPageEndZ,
subX, subZ );
}
}
}
}
}
}
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright © 2000-2004 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
PagingLandScapeCamera.cpp - description
-------------------
begin : Fri Sep 27 2002
copyright : ( C ) 2002 by Jon Anderson
email : janders@users.sf.net
Enhancements 2003 - 2004 ( C ) The OGRE Team
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreCamera.h"
#include "OgrePagingLandScapeCamera.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeSceneManager.h"
namespace Ogre
{
//-----------------------------------------------------------------------
49 PagingLandScapeCamera::PagingLandScapeCamera( const String& name, SceneManager* sm ) :
PagingLandScapeOctreeCamera( name, sm ),
mCurrentCameraPageX( 0 ),
mCurrentCameraPageZ( 0 ),
mCurrentCameraTileX( 0 ),
mCurrentCameraTileZ( 0 ),
mIniX( 0 ),
mFinX( 0 ),
mIniZ( 0 ),
mFinZ( 0 ),
mPreIniX( 0 ),
mPreFinX( 0 ),
mPreIniZ( 0 ),
mPreFinZ( 0 ),
mLastCameraPos ( Vector3( std::numeric_limits<Real>::max ( ),
0.0f,
std::numeric_limits<Real>::max ( ) ) )
{
// initialized after the Camera::Camera( ).
mLastViewport = 0;
}
//-----------------------------------------------------------------------
72 PagingLandScapeCamera::~PagingLandScapeCamera( )
{
}
//-----------------------------------------------------------------------
77 void PagingLandScapeCamera::resetPaging( )
{
mCurrentCameraPageX = 0;
mCurrentCameraPageZ = 0;
mCurrentCameraTileX = 0;
mCurrentCameraTileZ = 0;
mIniX = 0;
mFinX = 0;
mIniZ = 0;
mFinZ = 0;
mPreIniX = 0;
mPreFinX = 0;
mPreIniZ = 0;
mPreFinZ = 0;
mLastCameraPos = Vector3 ( std::numeric_limits<Real>::max ( ),
0.0f,
std::numeric_limits<Real>::max ( ) );
updatePaging ( 0, 0 );
// Real dist = Camera::getDerivedPosition( ).squaredLength( )
// + mParent->getOptions( )->cameraThreshold
// mLastCameraPos.x = dist;
// mLastCameraPos.y = dist;
// mLastCameraPos.z = dist;
}
//-----------------------------------------------------------------------
102 void PagingLandScapeCamera::updatePaging ( const unsigned int x, const unsigned int z )
{
// We must load the next visible LandScape pages,
// check the LandScape boundaries
mCurrentCameraPageX = x;
mCurrentCameraPageZ = z;
const PagingLandScapeOptions * const opt =
static_cast <PagingLandScapeSceneManager*> ( mSceneMgr )->getOptions ( );
const unsigned int w = opt->world_width;
const unsigned int h = opt->world_height;
const unsigned int adjpages = opt->max_adjacent_pages;
const unsigned int prepages = opt->max_preload_pages;
// Load Windowing
unsigned int lx = x;
if ( static_cast<int> ( x - adjpages ) >= 0 )
{
mIniX = x - adjpages;
}
else
{
mIniX = 0;
lx -= x - adjpages;
}
if ( lx + adjpages < w )
{
mFinX = lx + adjpages;
}
else
{
mFinX = w - 1;
mIniX = ( static_cast <int> ( mIniX + ( w - ( lx + adjpages ) ) ) > 0 )? mIniX + ( w - ( lx + adjpages ) ):0;
}
unsigned int lz = z;
if ( static_cast<int> ( z - adjpages ) >= 0 )
{
mIniZ = z - adjpages;
}
else
{
mIniZ = 0;
lz -= z - adjpages;
}
if ( lz + adjpages < h )
{
mFinZ = lz + adjpages;
}
else
{
mFinZ = h - 1;
mIniZ = ( static_cast <int> ( mIniZ + ( h - ( lz + adjpages ) ) ) > 0 )? mIniZ + ( h - ( lz + adjpages ) ):0;
}
// Pre-load Windowing
lx = x;
if ( static_cast<int> ( x - prepages ) > 0 )
{
mPreIniX = x - prepages;
}
else
{
mPreIniX = 0;
lx -= x - prepages;
}
if ( x + prepages < w )
{
mPreFinX = x + prepages;
}
else
{
mPreFinX = w - 1;
mPreIniX = ( static_cast <int> ( mPreIniX + ( w - ( lx + prepages ) ) ) > 0 )? mPreIniX + ( w - ( lx + prepages ) ):0;
}
lz = z;
if ( static_cast<int> ( z - prepages ) > 0 )
{
mPreIniZ = z - prepages;
}
else
{
mPreIniZ = 0;
lz -= z - prepages;
}
if ( lz + prepages < h )
{
mPreFinZ = lz + prepages;
}
else
{
mPreFinZ = h - 1;
mPreIniZ = ( static_cast <int> ( mPreIniZ + ( h - ( lz + prepages ) ) ) > 0 )? mPreIniZ + ( h - ( lz + prepages ) ):0;
}
//( static_cast <PagingLandScapeSceneManager*> ( getSceneManager( ) )->resize( ) );
}
//-----------------------------------------------------------------------
201 bool PagingLandScapeCamera::isVisible( const AxisAlignedBox &bound ) const
{
// Null boxes always invisible
assert ( !bound.isNull( ) );
// Infinite boxes always visible
assert ( !bound.isInfinite( ) );
// Get centre of the box
const Vector3 ¢re ( bound.getCenter( ) );
// Get the half-size of the box
const Vector3 &halfSize =( bound.getHalfSize( ) );
// For each plane, see if all points are on the negative side
// If so, object is not visible
const bool infinite_far_clip = ( mFarDist == 0 );
for ( unsigned int plane = 0; plane < 6; ++plane )
{
// Skip far plane if infinite view frustum
if ( plane == FRUSTUM_PLANE_FAR && infinite_far_clip )
continue;
const Plane::Side side = mFrustumPlanes[plane].getSide( centre, halfSize );
if ( side == Plane::NEGATIVE_SIDE )
{
// ALL corners on negative side therefore out of view
return false;
}
}
return true;
}
}
1 /***************************************************************************
OgrePagingLandScapeData2D.cpp - description
-------------------
begin : Wen Mar 06 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreSphere.h"
#include "OgrePagingLandScapeSceneManager.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeData2D.h"
#include "OgrePagingLandScapeOptions.h"
#ifndef _MAPSPLITTER
#include "OgreAxisAlignedBox.h"
#include "OgreMovableObject.h"
#include "OgreSimpleRenderable.h"
#include "OgrePagingLandScapePageManager.h"
#include "OgrePagingLandScapeTile.h"
#include "OgrePagingLandScapeRenderable.h"
#endif// _MAPSPLITTER
namespace Ogre
{
47 PagingLandScapeData2D::PagingLandScapeData2D( PagingLandScapeData2DManager *pageMgr ):
mParent( pageMgr ),
mHeightData ( 0 ),
mIsLoaded ( false ),
mIsModified ( false ),
mIsRectModified ( false ),
mRect ( 0, 0, 0, 0, 0, 1 )
{
}
//-----------------------------------------------------------------------
57 PagingLandScapeData2D::~PagingLandScapeData2D( )
{
unload ( );
}
//-----------------------------------------------------------------------
62 void PagingLandScapeData2D::init( )
{
//
}
//-----------------------------------------------------------------------
67 void PagingLandScapeData2D::uninit( )
{
PagingLandScapeData2D::unload ( );
}
//-----------------------------------------------------------------------
72 bool PagingLandScapeData2D::load( const unsigned int x, const unsigned int z )
{
if ( !mIsLoaded )
{
mIsModified = false;
mIsRectModified = false;
mRect = Image::Box ( 0, 0, 0, 0, 0, 1 );
mPageX = x;
mPageZ = z;
mSize = mParent->getOptions( )->PageSize;
mShiftX = ( mPageX * ( mSize - 1 ) ) - mParent->getOptions( )->maxUnScaledX;
mShiftZ = ( mPageZ * ( mSize - 1 ) ) - mParent->getOptions( )->maxUnScaledZ;
const bool isLoadable = _load ( x, z );
mIsLoaded = true;
return isLoadable;
}
return true;
}
//-----------------------------------------------------------------------
95 void PagingLandScapeData2D::load( )
{
if ( !mIsLoaded )
{
_load( );
mIsLoaded = true;
}
}
//-----------------------------------------------------------------------
104 void PagingLandScapeData2D::unload( )
{
if ( mIsLoaded )
{
if ( mIsModified && mParent->getOptions( )->saveDeformation )
_save ( );
delete[] mHeightData;
mHeightData = 0;
_unload( );
mIsLoaded = false;
#ifndef _MAPSPLITTER
resetDeformationRectangle ( );
#endif
}
}
//-----------------------------------------------------------------------
120 void PagingLandScapeData2D::computePowerof2PlusOneSize( )
{
mSize = mParent->getOptions( )->PageSize;
const size_t p2size = mSize - 1;
size_t pagex = mXDimension / p2size;
if ( mXDimension - ( pagex * p2size ) > 1 )
pagex++;
mXDimension = pagex * p2size + 1;
size_t pagez = mZDimension / p2size;
if ( mZDimension - ( pagez * p2size ) > 1 )
pagez++;
mZDimension = pagez * p2size + 1;
}
//-----------------------------------------------------------------------
136 bool PagingLandScapeData2D::_checkSize( const size_t s )
{
// ispow2 - 1
const int p = static_cast <unsigned int> ( s - 1 );
// ispow2
return ( ( p & ( p - 1 ) ) == 0 );
}
#ifndef _MAPSPLITTER
//-----------------------------------------------------------------------
146 void PagingLandScapeData2D::resetDeformationRectangle ( )
{
mRect.left = 0;
mRect.right = 0;
mRect.top = 0;
mRect.bottom = 0;
mIsRectModified = false;
}
//-----------------------------------------------------------------------
155 Image::Box PagingLandScapeData2D::getDeformationRectangle ( )
{
return mRect;
}
//-----------------------------------------------------------------------
160 void PagingLandScapeData2D::adjustDeformationRectangle( const unsigned int x, const unsigned int z )
{
if ( mIsRectModified )
{
if ( mRect.left > x )
mRect.left = x;
if ( mRect.right < x )
mRect.right = x;
if ( mRect.top > z )
mRect.top = z;
if ( mRect.bottom < z )
mRect.bottom = z;
}
else
{
// first modification :
// deformation rectangle is the point
mRect.left = x;
mRect.right = x;
mRect.top = z;
mRect.bottom = z;
mIsRectModified = true;
mIsModified = true;
}
unsigned int tileposx = x;
unsigned int tileposz = z;
PagingLandScapeTile *t =
mParent->getSceneManager( )->getPageManager( )->getTilePage( tileposx, tileposz,
mPageX, mPageZ );
if ( t && t->isLoaded ( ) )
{
// tells what tile portion needs to be updated.
PagingLandScapeRenderable * const r = t->getRenderable ( );
r->adjustDeformationRectangle ( tileposx, tileposz );
}
}
//-----------------------------------------------------------------------
198 const bool PagingLandScapeData2D::deformHeight( const Vector3 &deformationPoint,
199 Real &modificationHeight )
{
// adjust x and z to be local to page
const int x = static_cast<int> ( deformationPoint.x - mShiftX );
const int z = static_cast<int> ( deformationPoint.z - mShiftZ );
// due to Real imprecision on Reals, we have to use boundaries here
// otherwise we'll hit asserts.
const int size = static_cast<int> ( mSize-1 );
const unsigned int ux = static_cast<unsigned int> ( std::max( std::min ( x, size ), 0 ) );
const unsigned int uz = static_cast<unsigned int> ( std::max( std::min ( z, size ), 0 ) );
return deformHeight( ux, uz, modificationHeight );
}
//-----------------------------------------------------------------------
212 const bool PagingLandScapeData2D::deformHeight( const unsigned int x,
const unsigned int z,
214 Real &modificationHeight )
{
const unsigned int arraypos = static_cast <unsigned int> ( z * mSize + x );
assert ( mHeightData && arraypos < mMaxArrayPos );
const Real maxH = mParent->getMaxHeight( );
const Real newH = mHeightData[arraypos] - modificationHeight;
bool did_modif = false;
if ( newH <= 0.0f )
{
if ( mHeightData[arraypos] != 0.0f )
did_modif = setHeight( x, z, arraypos, 0.0f );
modificationHeight = 0.0f;
}
else if ( newH >= maxH )
{
if ( mHeightData[arraypos] != maxH )
did_modif = setHeight( x, z, arraypos, maxH );
modificationHeight = maxH;
}
else
{
did_modif = setHeight( x, z, arraypos, newH );
modificationHeight = newH;
}
return did_modif;
}
//-----------------------------------------------------------------------
244 bool PagingLandScapeData2D::setHeight( const unsigned int x, const unsigned int z,
245 const unsigned int Pos, const Real h )
{
if ( mHeightData[Pos] != h )
{
mHeightData[ Pos ] = h;
unsigned int tileposx = x;
unsigned int tileposz = z;
// Make position local to tiles.
// and return a Tile.
PagingLandScapeTile *t =
mParent->getSceneManager( )->getPageManager( )->getTilePage ( tileposx, tileposz,
mPageX, mPageZ );
if ( t && t->isLoaded ( ) )
{
// tells what tile portion needs to be updated.
PagingLandScapeRenderable * const r = t->getRenderable ( );
r->adjustDeformationRectangle ( tileposx, tileposz );
const unsigned int tSize = mParent->getOptions( )->TileSize - 1;
const unsigned int NumTiles = mParent->getOptions( )->NumTiles;
const PagingLandScapeTileInfo * const info = t->getInfo( );
const unsigned int tX = info->mTileX;
const unsigned int tZ = info->mTileZ;
// If we're on a page edge, we must duplicate the change on the
// neighbour tile ( if it has one... )
// could be a direct neighbour or a diagonal one ( in a corner. )
const bool left = ( tileposx == 0 && tX != 0 );
const bool right = ( tileposx == tSize && tX != NumTiles - 1 );
const bool down = ( tileposz == 0 && tZ != 0 );
const bool up = ( tileposz == tSize && tZ != NumTiles - 1 );
if ( left )
{
PagingLandScapeRenderable * const rn = r->_getNeighbor( WEST );
if ( rn )
{
if ( down )
{
PagingLandScapeRenderable * const rnUp = rn->_getNeighbor( NORTH );
if ( rnUp && rnUp->isLoaded ( ) )
{
rnUp->adjustDeformationRectangle ( tSize, tSize );
}
}
else if ( up )
{
PagingLandScapeRenderable * const rnDown = rn->_getNeighbor( SOUTH );
if ( rnDown && rnDown->isLoaded ( ) )
{
rnDown->adjustDeformationRectangle ( tSize, 0 );
}
}
if ( rn->isLoaded ( ) )
{
rn->adjustDeformationRectangle ( tSize, tileposz );
}
}
}
else if ( right )
{
PagingLandScapeRenderable * const rn = r->_getNeighbor( EAST );
if ( rn )
{
if ( down )
{
PagingLandScapeRenderable * const rnUp = rn->_getNeighbor( NORTH );
if ( rnUp && rnUp->isLoaded ( ) )
{
rnUp->adjustDeformationRectangle ( 0, tSize );
}
}
else if ( up )
{
PagingLandScapeRenderable * const rnDown = rn->_getNeighbor( SOUTH );
if ( rnDown && rnDown->isLoaded ( ) )
{
rnDown->adjustDeformationRectangle ( 0, 0 );
}
}
if ( rn )
{
rn->adjustDeformationRectangle ( 0, tileposz );
}
}
}
if ( down )
{
PagingLandScapeRenderable * const rn = r->_getNeighbor( NORTH );
if ( rn && rn->isLoaded ( ) )
{
rn->adjustDeformationRectangle ( tileposx, tSize );
}
}
else if ( up )
{
PagingLandScapeRenderable * const rn = r->_getNeighbor( SOUTH );
if ( rn && rn->isLoaded ( ) )
{
rn->adjustDeformationRectangle ( tileposx, 0 );
}
}
}
adjustDeformationRectangle ( x, z );
return true;
}
return false;
}
//-----------------------------------------------------------------------
358 bool PagingLandScapeData2D::setHeight( const unsigned int x, const unsigned int z,
359 const Real h )
{
const unsigned int Pos = static_cast <unsigned int> ( ( z * mSize )+ x );
assert ( mHeightData && mMaxArrayPos > Pos );
return setHeight( x, z, Pos, h );
}
#endif //_MAPSPLITTER
//-----------------------------------------------------------------------
367 const Vector3 PagingLandScapeData2D::getNormal ( const Real mX, const Real mZ )
{
// First General method : ( 9 adds and 6 muls + a normalization )
// *---v3--*
// | | |
// | | |
// v1--X--v2
// | | |
// | | |
// *---v4--*
//
// U = v2 - v1;
// V = v4 - v3;
// N = Cross( U, V );
// N.normalise;
//
// BUT IN CASE OF A HEIGHTMAP :
//
// if you do some math by hand before you code,
// you can see that N is immediately given by
// Approximation ( 2 adds and a normalization )
//
// N = Vector3( z[x-1][y] - z[x+1][y], z[x][y-1] - z[x][y+1], 2 );
// N.normalise( );
//
// or even using SOBEL operator VERY accurate!
// ( 14 adds and a normalization )
//
// N = Vector3 ( z[x-1][y-1] + z[x-1][y] + z[x-1][y] + z[x-1][y+1] - z[x+1][y-1] - z[x+1][y] - z[x+1][y] - z[x+1][y+1],
// z[x-1][y-1] + z[x][y-1] + z[x][y-1] + z[x+1][y-1] - z[x-1][y+1] - z[x][y+1] - z[x][y+1] - z[x+1][y+1],
// 8 );
// N.normalize( );
// Fast SOBEL filter
const size_t pageSize = mSize - 1;
// the divider make sure we do respect proportion ( height and width proportional to y )
const Real Divider = static_cast <Real> ( pageSize ) / mParent->getOptions( )->scale.y;
assert ( mHeightData );
#define getisIn( a, b ) ( mHeightData[static_cast<unsigned int> ( a ) + static_cast<unsigned int> ( b ) * mSize] )
if ( mX > 0 && mZ > 0 &&
mX < pageSize && mZ < pageSize )
{
// Vector3 result ( getisIn( x-1, z-1 ) + getisIn ( x-1, z ) + getisIn ( x-1, z ) + getisIn ( x-1, z+1 ) - getisIn ( x+1, z-1 ) - getisIn ( x+1, z ) - getisIn ( x+1, z ) - getisIn ( x+1, z+1 ),
// 8.0f,
// getisIn ( x-1, z-1 ) + getisIn ( x, z-1 ) + getisIn ( x, z-1 ) + getisIn ( x+1, z-1 ) - getisIn ( x-1, z+1 ) - getisIn ( x, z+1 ) - getisIn ( x, z+1 ) - getisIn ( x+1, z+1 ) );
Vector3 result( ( getisIn ( mX - 1 , mZ ) - getisIn ( mX + 1 , mZ ) ) * Divider,
2.0f,
( getisIn ( mX, mZ - 1 ) - getisIn ( mX , mZ + 1 ) ) * Divider );
result.normalise ( );
return result;
}
else
{
unsigned int x = static_cast <unsigned int> ( mX );
unsigned int z = static_cast <unsigned int> ( mZ );
Real a, b, c, d;
if ( x == 0 )
{
a = getisIn ( x , z );
b = getisIn ( x + 1, z );
}
else if ( x == pageSize )
{
a = getisIn ( x - 1 , z );
b = getisIn ( x , z );
}
else
{
a = getisIn ( x - 1 , z );
b = getisIn ( x + 1, z );
}
if ( z == 0 )
{
c = getisIn ( x , z );
d = getisIn ( x , z + 1 );
}
else if ( z == pageSize )
{
c = getisIn ( x , z - 1 );
d = getisIn ( x , z );
}
else
{
c = getisIn ( x , z - 1 );
d = getisIn ( x , z + 1 );
}
Vector3 result( ( a - b ) * Divider,
2.0f,
( c - d ) * Divider );
result.normalise ( );
return result;
#ifdef _NOWAY
#ifndef _MAPSPLITTER
#define getisOut( a, b ) ( PagingLandScapeData2DManager::getSingleton ( ).getHeightAtPage ( mPageX, mPageZ, static_cast<int> ( a ), static_cast<int> ( b ) ) )
// Vector3 result ( getisOut( x-1, z-1 ) + getisOut ( x-1, z ) + getisOut ( x-1, z ) + getisOut ( x-1, z+1 ) - getisOut ( x+1, z-1 ) - getisOut ( x+1, z ) - getisOut ( x+1, z ) - getisOut ( x+1, z+1 ),
// 8.0f,
// getisOut ( x-1, z-1 ) + getisOut ( x, z-1 ) + getisOut ( x, z-1 ) + getisOut ( x+1, z-1 ) - getisOut ( x-1, z+1 ) - getisOut ( x, z+1 ) - getisOut ( x, z+1 ) - getisOut ( x+1, z+1 ) );
Vector3 result( ( getisOut ( mX - 1 , mZ ) - getisOut ( mX + 1 , mZ ) ) * Divider,
2.0f,
( getisOut ( mX, mZ - 1 ) - getisOut ( mX , mZ + 1 ) ) * Divider );
result.normalise ( );
return result;
#endif //_MAPSPLITTER
#endif //
}
}
} //namespace
1 /***************************************************************************
OgrePagingLandScapeData2DManager.cpp - description
-------------------
begin : Mon Jun 16 2003
copyright : ( C ) 2003-2006 by Jose A. Milan and Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreMath.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreMovableObject.h"
#include "OgreAxisAlignedBox.h"
#include "OgrePlane.h"
#include "OgreCamera.h"
#include "OgreSimpleRenderable.h"
#include "OgreException.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeCamera.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeData2D.h"
// Data loaders implementations
// #include "OgrePagingLandScapeData2D_HeightField.h"
// #include "OgrePagingLandScapeData2D_HeightFieldTC.h"
//
// #include "OgrePagingLandScapeData2D_HeightFieldN.h"
// #include "OgrePagingLandScapeData2D_HeightFieldNTC.h"
//
// #include "OgrePagingLandScapeData2D_HeightFieldRaw.h"
// #include "OgrePagingLandScapeData2D_HeightFieldRawTC.h"
//
// #include "OgrePagingLandScapeData2D_Spline.h"
//
// // load heights from texture.
// #include "OgrePagingLandScapeData2D_HeightFieldBlendNeighbor.h"
// needed to get RenderLevel for RealHeight
#include "OgrePagingLandScapeRenderable.h"
#include "OgrePagingLandScapeTile.h"
#include "OgrePagingLandScapeTileInfo.h"
#include "OgrePagingLandScapePage.h"
#include "OgrePagingLandScapePageManager.h"
#include "OgrePagingLandScapeSceneManager.h"
namespace Ogre
{
//-----------------------------------------------------------------------
69 PagingLandScapeData2DManager::PagingLandScapeData2DManager( PagingLandScapeSceneManager * scnMgr,
70 PagingLandScapeOptions * opt ) :
mScnMgr( scnMgr ),
mOptions ( opt ),
mData2DType ( 0 ),
mData2DFormat ( "" ),
mWidth ( 0 ),
mHeight ( 0 ),
mMaxHeight ( 0 ),
mPageManager ( 0 )
{
// // Add default texture Types.
// registerDataType ( new PagingLandScapeData2D_HeightField ( this ) );
// registerDataType ( new PagingLandScapeData2D_HeightFieldRaw( this ) );
// registerDataType ( new PagingLandScapeData2D_HeightFieldTC( this ) );
// #ifndef _MAPSPLITTER
// registerDataType ( new PagingLandScapeData2D_HeightFieldN( this ) );
// registerDataType ( new PagingLandScapeData2D_HeightFieldRawTC( this ) );
// registerDataType ( new PagingLandScapeData2D_HeightFieldNTC( this ) );
// registerDataType ( new PagingLandScapeData2D_HeightFieldBlendNeighbor( this ) );
// #endif //_MAPSPLITTER
// registerDataType ( new PagingLandScapeData2D_Spline( this ) );
}
//-----------------------------------------------------------------------
93 PagingLandScapeData2D *PagingLandScapeData2DManager::allocateData2D( ) const
{
assert ( !mData2DTypeMap.empty( ) && mData2DTypeMap[mData2DType] );
return mData2DTypeMap[mData2DType]->newPage( );
}
//-----------------------------------------------------------------------
99 PagingLandScapeData2DManager::~PagingLandScapeData2DManager( )
{
reset( );
// for all in map delete.
PagingLandScapeData2DMap::iterator i = mData2DTypeMap.begin( );
while ( i != mData2DTypeMap.end( ) )
{
delete ( *i );
++i;
}
}
//-----------------------------------------------------------------------
111 void PagingLandScapeData2DManager::reset( )
{
if ( !mActiveData2Ds.empty( ) )
{
std::for_each( mActiveData2Ds.begin( ), mActiveData2Ds.end( ),
std::mem_fun( &PagingLandScapeData2D::unload ) );
// Insert actives into free list
mFreeData2Ds.insert( mFreeData2Ds.end( ), mActiveData2Ds.begin( ), mActiveData2Ds.end( ) );
// Remove all active instances
mActiveData2Ds.clear( );
}
// could save a delete if data type is the same... ?
if ( !mData2DPool.empty( ) )
{
std::for_each( mData2DPool.begin( ), mData2DPool.end( ), delete_object( ) );
mData2DPool.clear( );
mFreeData2Ds.clear( );
}
mWidth = 0;
mHeight = 0;
}
//-----------------------------------------------------------------------
136 void PagingLandScapeData2DManager::load ( )
{
if ( mOptions->data2DFormat != mData2DFormat )
{
reset ( );
mData2DFormat = mOptions->data2DFormat;
unsigned int i = 0;
for ( ; i != mData2DTypeMap.size( ); ++i )
{
if ( StringUtil::endsWith ( mData2DTypeMap[i]->getName ( ), mData2DFormat, false ) )
{
mData2DType = i;
break;
}
}
if ( i == mData2DTypeMap.size( ) )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
"PageData2D not supplied or wrong ( check case ) !",
" PagingLandScapeData2DManager::load" );
}
}
WorldDimensionChange( );
mMaxHeight = mData2DTypeMap[mData2DType]->getMaxAbsoluteHeight ( );
}
//-----------------------------------------------------------------------
162 bool PagingLandScapeData2DManager::reload( const unsigned int dataX, const unsigned int dataZ )
{
#ifndef _MAPSPLITTER
PagingLandScapeData2D* data = getData2D ( dataX, dataZ );
data->unload( );
const bool ret = data->load( dataX, dataZ );
const unsigned int tsize = mOptions->TileSize;
const unsigned int psize = mOptions->PageSize;
for ( unsigned int z = 0; z <= psize ; z += tsize )
{
for ( unsigned int x = 0; x <= psize ; x += tsize )
{
data->adjustDeformationRectangle ( x, z );
}
}
return ret;
#else //_MAPSPLITTER
return true;
#endif //_MAPSPLITTER
}
//-----------------------------------------------------------------------
184 PagingLandScapeData2D *PagingLandScapeData2DManager::getNewData2D( const unsigned int x, const unsigned int z )
{
PagingLandScapeData2D *newData2D;
if ( mFreeData2Ds.empty( ) )
{
const size_t pool_size = mData2DPool.size ( );
const size_t new_pool_size = ( pool_size == 0 ) ? 9 : pool_size * 2;
mData2DPool.reserve( new_pool_size );
mData2DPool.resize( new_pool_size );
// Create new pages
for ( size_t i = pool_size; i < new_pool_size; ++i )
{
newData2D = allocateData2D( );
mData2DPool[i] = newData2D;
mFreeData2Ds.push_back ( newData2D );
}
}
newData2D = mFreeData2Ds.front ( );
mFreeData2Ds.pop_front ( );
mActiveData2Ds.push_back ( newData2D );
newData2D->load ( x, z );
return newData2D;
}
//-----------------------------------------------------------------------
212 void PagingLandScapeData2DManager::releaseData2D( PagingLandScapeData2D *p )
{
mActiveData2Ds.remove( p );
mFreeData2Ds.push_back( p );
}
//-----------------------------------------------------------------------
218 PagingLandScapeData2D *PagingLandScapeData2DManager::getData2D( const unsigned int x, const unsigned int z,
219 const bool alwaysReturn )
{
if ( x < mWidth && z < mHeight )
{
PagingLandScapeData2DList::iterator l, lend = mActiveData2Ds.end( );
for ( l = mActiveData2Ds.begin( ); l != lend; ++l )
{
if ( ( *l )->isCoord( x, z ) )
return ( *l );
}
if ( alwaysReturn )
return getNewData2D( x, z );
}
assert ( !alwaysReturn );
return 0;
}
//-----------------------------------------------------------------------
236 void PagingLandScapeData2DManager::clear ( )
{
}
//-----------------------------------------------------------------------
240 void PagingLandScapeData2DManager::WorldDimensionChange( )
{
const unsigned int newWidth = mOptions->world_width;
const unsigned int newHeight = mOptions->world_height;
reset( );
mWidth = newWidth;
mHeight = newHeight;
}
//-----------------------------------------------------------------------
251 void PagingLandScapeData2DManager::setPageManager ( PagingLandScapeSceneManager *scnMgr )
{
mPageManager = scnMgr->getPageManager( );
}
//-----------------------------------------------------------------------
256 bool PagingLandScapeData2DManager::load( const unsigned int dataX, const unsigned int dataZ )
{
PagingLandScapeData2D* data = getData2D ( dataX , dataZ );
if ( !data->isLoaded ( ) )
{
return data->load ( dataX, dataZ );
}
return true;
}
//-----------------------------------------------------------------------
266 void PagingLandScapeData2DManager::unload( const unsigned int dataX, const unsigned int dataZ )
{
PagingLandScapeData2D* data = getData2D ( dataX , dataZ, false );
if ( data && data->isLoaded ( ) )
{
data->unload ( );
releaseData2D ( data );
}
}
//-----------------------------------------------------------------------
277 bool PagingLandScapeData2DManager::isLoaded( const unsigned int dataX, const unsigned int dataZ )
{
PagingLandScapeData2D * const data = getData2D ( dataX , dataZ, false );
return data && data->isLoaded( );
}
//-----------------------------------------------------------------------
283 const ColourValue PagingLandScapeData2DManager::getCoverageAt( const unsigned int dataX,
const unsigned int dataZ,
285 const Real x,
286 const Real z )
{
PagingLandScapeData2D* data = getData2D ( dataX , dataZ, false );
if ( data && data->isLoaded( ) )
{
// TODO check it the terrain height is modified
return data->getCoverage( x, z );
}
return ColourValue::White;
}
//-----------------------------------------------------------------------
297 const ColourValue PagingLandScapeData2DManager::getBaseAt( const unsigned int dataX,
const unsigned int dataZ,
299 const Real x,
300 const Real z )
{
PagingLandScapeData2D* data = getData2D ( dataX , dataZ, false );
if ( data && data->isLoaded( ) )
{
// TODO check it the terrain height is modified
return data->getBase( x, z );
}
return ColourValue::White;
}
//-----------------------------------------------------------------------
311 const Real PagingLandScapeData2DManager::getShadowAt( const unsigned int dataX,
const unsigned int dataZ,
const unsigned int x,
const unsigned int z,
315 const bool &positive )
{
PagingLandScapeData2D* data = getData2D ( dataX , dataZ, false );
if ( data && data->isLoaded( ) )
{
// TODO check it the terrain height is modified
return data->getShadow( x, z, positive );
}
return 0.0f;
}
//-----------------------------------------------------------------------
326 const Real PagingLandScapeData2DManager::getHeight( const unsigned int dataX,
const unsigned int dataZ,
328 const Real x,
329 const Real z )
{
PagingLandScapeData2D* data = getData2D ( dataX , dataZ, false );
if ( data && data->isLoaded( ) )
{
// TODO check it the terrain height is modified
return data->getHeight( x, z );
}
return 0.0f;
}
//-----------------------------------------------------------------------
341 const Real PagingLandScapeData2DManager::getHeight( const unsigned int dataX,
const unsigned int dataZ,
const unsigned int x,
const unsigned int z )
{
PagingLandScapeData2D* data = getData2D ( dataX , dataZ, false );
if ( data && data->isLoaded( ) )
{
return data->getHeight( x, z );
}
return 0.0f;
}
//-----------------------------------------------------------------------
// bool PagingLandScapeData2DManager::addNewHeight( const Sphere newSphere )
// {
// unsigned int x, z;
//
// Vector3 s = newSphere.getCenter( );
// // Calculate where is going to be placed the new height
// PagingLandScapePageManager::getSingleton ( ).getPageIndices( s.x, s.z, x, z, true );
// // TODO: DeScale and add the sphere to all the necessary pages
//
// //place it there
// return mData2D[ x ][ z ]->addNewHeight( newSphere );
// }
//-----------------------------------------------------------------------
// bool PagingLandScapeData2DManager::removeNewHeight( const Sphere oldSphere )
// {
// unsigned int x, z;
// Vector3 s = oldSphere.getCenter( );
// // Calculate where is going to be placed the new height
// PagingLandScapePageManager::getSingleton ( ).getPageIndices( s.x, s.z, x, z, true );
// // TODO: DeScale and add the sphere to all the necessary pages
//
// //remove it
// return mData2D[ x ][ z ]->removeNewHeight( oldSphere );
// }
//-----------------------------------------------------------------------
382 const Real PagingLandScapeData2DManager::getMaxHeight( const unsigned int x,
const unsigned int z )
{
PagingLandScapeData2D* data = getData2D ( x, z, false );
if ( data && data->isLoaded( ) )
{
return data->getMaxHeight( );
}
return mMaxHeight;
}
//-----------------------------------------------------------------------
393 const Real PagingLandScapeData2DManager::getMaxHeight( ) const
{
return mMaxHeight;
}
//-----------------------------------------------------------------------
398 bool PagingLandScapeData2DManager::setHeight( const Vector3 &deformationPoint,
399 const Real modificationHeight,
400 const PagingLandScapeTileInfo* info )
{
#ifndef _MAPSPLITTER
const unsigned int pX = info->mPageX;
const unsigned int pZ = info->mPageZ;
const unsigned int pSize = mOptions->PageSize - 1;
// adjust x and z to be local to page
const unsigned int x = static_cast<unsigned int> ( deformationPoint.x
- pX * pSize
+ mOptions->maxUnScaledX );
const unsigned int z = static_cast<unsigned int> ( deformationPoint.z
- pZ * pSize
+ mOptions->maxUnScaledZ );
PagingLandScapeData2D* data = getData2D ( pX , pZ, false );
if ( data && data->isLoaded( ) )
{
Real heightResult = modificationHeight;
if ( data->setHeight ( x, z, heightResult ) )
{
const unsigned int wL = mOptions->world_width;
const unsigned int hL = mOptions->world_height;
// If we're on a page edge, we must duplicate the change on the
// neighbour page ( if it has one... )
const bool left = ( x == 0 && pX != 0 );
const bool right = ( x == pSize && pX < wL - 1 );
const bool down = ( z == 0 && pZ != 0 );
const bool up = ( z == pSize && pZ < hL - 1 );
assert ( z <= pSize && x <= pSize );
if ( left )
{
if ( down )
{
// lower left corner
data = getData2D ( pX - 1, pZ - 1 , false );
if ( data && data->isLoaded( ) )
{
data->setHeight ( pSize, pSize, heightResult );
}
}
else if ( up )
{
// upper left corner
data = getData2D ( pX - 1, pZ + 1 , false );
if ( data && data->isLoaded( ) )
{
data->setHeight ( pSize, 0, heightResult );
}
}
// left
data = getData2D ( pX - 1, pZ, false );
if ( data && data->isLoaded( ) )
{
data->setHeight ( pSize, z, heightResult );
}
}
else if ( right )
{
if ( up )
{
// upper right corner
data = getData2D ( pX + 1, pZ + 1 , false );
if ( data && data->isLoaded( ) )
{
data->setHeight ( 0, 0, heightResult );
}
}
else if ( down )
{
// lower right corner
data = getData2D ( pX + 1, pZ - 1 , false );
if ( data && data->isLoaded( ) )
{
data->setHeight ( 0, pSize, heightResult );
}
}
// right
data = getData2D ( pX + 1, pZ, false );
if ( data && data->isLoaded( ) )
{
data->setHeight ( 0, z, heightResult );
}
}
if ( down )
{
// lower ( down only )
data = getData2D ( pX, pZ - 1 , false );
if ( data && data->isLoaded( ) )
{
data->setHeight ( x, pSize, heightResult );
}
}
else if ( up )
{
// upper ( up only )
data = getData2D ( pX, pZ + 1 , false );
if ( data && data->isLoaded( ) )
{
data->setHeight ( x, 0, heightResult );
}
}
return true;
} // if ( data->deformHeight ( x, z, heightResult ) )
} // if ( data->isLoaded( ) )
#endif
return false;
}
//-----------------------------------------------------------------------
512 bool PagingLandScapeData2DManager::deformHeight( const Vector3 &deformationPoint,
513 const Real modificationHeight,
514 const PagingLandScapeTileInfo* info )
{
#ifndef _MAPSPLITTER
const unsigned int pX = info->mPageX;
const unsigned int pZ = info->mPageZ;
const unsigned int pSize = mOptions->PageSize - 1;
// adjust x and z to be local to page
const unsigned int x = static_cast<unsigned int> ( deformationPoint.x
- pX * pSize
+ mOptions->maxUnScaledX );
const unsigned int z = static_cast<unsigned int> ( deformationPoint.z
- pZ * pSize
+ mOptions->maxUnScaledZ );
PagingLandScapeData2D* data = getData2D ( pX , pZ, false );
if ( data && data->isLoaded( ) )
{
Real heightResult = modificationHeight;
if ( data->deformHeight ( x, z, heightResult ) )
{
const unsigned int wL = mOptions->world_width;
const unsigned int hL = mOptions->world_height;
// If we're on a page edge, we must duplicate the change on the
// neighbour page ( if it has one... )
const bool left = ( x == 0 && pX != 0 );
const bool right = ( x == pSize && pX < wL - 1 );
const bool down = ( z == 0 && pZ != 0 );
const bool up = ( z == pSize && pZ < hL - 1 );
assert ( z <= pSize && x <= pSize );
if ( left )
{
if ( down )
{
// lower left corner
data = getData2D ( pX - 1, pZ - 1 , false );
if ( data && data->isLoaded( ) )
{
data->setHeight ( pSize, pSize, heightResult );
}
}
else if ( up )
{
// upper left corner
data = getData2D ( pX - 1, pZ + 1 , false );
if ( data && data->isLoaded( ) )
{
data->setHeight ( pSize, 0, heightResult );
}
}
// left
data = getData2D ( pX - 1, pZ, false );
if ( data && data->isLoaded( ) )
{
data->setHeight ( pSize, z, heightResult );
}
}
else if ( right )
{
if ( up )
{
// upper right corner
data = getData2D ( pX + 1, pZ + 1 , false );
if ( data && data->isLoaded( ) )
{
data->setHeight ( 0, 0, heightResult );
}
}
else if ( down )
{
// lower right corner
data = getData2D ( pX + 1, pZ - 1 , false );
if ( data && data->isLoaded( ) )
{
data->setHeight ( 0, pSize, heightResult );
}
}
// right
data = getData2D ( pX + 1, pZ, false );
if ( data && data->isLoaded( ) )
{
data->setHeight ( 0, z, heightResult );
}
}
if ( down )
{
// lower ( down only )
data = getData2D ( pX, pZ - 1 , false );
if ( data && data->isLoaded( ) )
{
data->setHeight ( x, pSize, heightResult );
}
}
else if ( up )
{
// upper ( up only )
data = getData2D ( pX, pZ + 1 , false );
if ( data && data->isLoaded( ) )
{
data->setHeight ( x, 0, heightResult );
}
}
return true;
} // if ( data->deformHeight ( x, z, heightResult ) )
} // if ( data->isLoaded( ) )
return false;
#else //_MAPSPLITTER
return true;
#endif //_MAPSPLITTER
}
//-----------------------------------------------------------------------
629 const Real PagingLandScapeData2DManager::getInterpolatedWorldHeight ( const Real x, const Real z, Real *getSlopeAt )
{
#ifndef _MAPSPLITTER
Real heightValue;
//#define _DEBUGPOS
//#define _DEBUGPOSHEIGHTSTICH
// scale position from world to page scale
const Real unscaledX = ( x * mOptions->invScale.x ) + mOptions->maxUnScaledX;
const Real unscaledZ = ( z * mOptions->invScale.z ) + mOptions->maxUnScaledZ;
const Real pSize = mOptions->PageSize - 1;
const Real inv_pSize = 1.0f / pSize;
//get Page
int value = static_cast< int > ( unscaledX * inv_pSize );
const int maxPageX = static_cast< int > ( mOptions->world_width );
const int pageNumberX = ( value < 0 ) ? 0 : ( value >= maxPageX ? maxPageX - 1: value );
const int maxPageZ = static_cast< int > ( mOptions->world_height );
value = static_cast< int > ( unscaledZ * inv_pSize );
const int pageNumberZ = ( value < 0 ) ? 0 : ( value >= maxPageZ ? maxPageZ - 1: value );
const PagingLandScapePage * const page = mScnMgr->getPageManager( )->getPage ( pageNumberX, pageNumberZ, false );
if ( ! ( page && page->isPreLoaded( ) ) )
return 0.0f;
// adjust x and z to be local to page
const Real localPageX = unscaledX - ( pageNumberX*pSize );
const Real localPageZ = unscaledZ - ( pageNumberZ*pSize );
const unsigned int tSize = mOptions->TileSize - 1;
const Real inv_tSize = 1.0f / tSize;
//get Tile
value = static_cast< int > ( localPageX * inv_tSize );
const int maxNumTiles = static_cast< int > ( mOptions->NumTiles );
const int tileNumberX = ( value < 0 ) ? 0 : ( value >= maxNumTiles? maxNumTiles - 1: value );
value = static_cast< int > ( localPageZ * inv_tSize );
const int tileNumberZ = ( value < 0 ) ? 0 : ( value >= maxNumTiles? maxNumTiles - 1: value );
// adjust x and z to be local to tile
const int localTileX = Math::ICeil ( localPageX - tileNumberX * tSize );
const int localTileZ = Math::ICeil ( localPageZ - tileNumberZ * tSize );
#ifdef _DEBUGPOSHEIGHT
{
RenderTarget *t = mOptions->primaryCamera->getViewport( )->getTarget ( );
const String debugPos ( " px: " + StringConverter::toString( pageNumberX ) +
" pz: " + StringConverter::toString( pageNumberZ ) +
" lpx: " + StringConverter::toString( localPageX ) +
" lpz: " + StringConverter::toString( localPageZ ) +
" tx: " + StringConverter::toString( tileNumberX ) +
" tz: " + StringConverter::toString( tileNumberZ ) +
" ltx: " + StringConverter::toString( localTileX ) +
" ltz: " + StringConverter::toString( localTileZ )
);
t->setDebugText( debugPos );
}
#endif // _DEBUG
PagingLandScapeTile * const tile = page->getTile ( tileNumberX, tileNumberZ );
bool tileLoaded = tile && tile->isLoaded( ) && tile->getRenderable( );
const int currentRenderLevel = ( tileLoaded ) ?
tile->getRenderable( )->getRenderLevel( )
:
0;
#ifdef _DEBUGPOSHEIGHTSTICH
String debugStich ( "( " + StringConverter::toString( pageNumberX ) +
", " + StringConverter::toString( pageNumberZ ) +
" )( " + StringConverter::toString( tileNumberX ) +
", " + StringConverter::toString( tileNumberZ ) +
" )( " + StringConverter::toString( localPageX ) +
", " + StringConverter::toString( localPageZ ) +
" )( " + StringConverter::toString( localTileX ) +
", " + StringConverter::toString( localTileZ ) +
" ) rdl:" + StringConverter::toString( currentRenderLevel )
);
#endif // _DEBUGPOSHEIGHTSTICH
// find the 4 vertices that surround the point
// use LOD info to determine vertex data spacing - this is passed into the method
// determine vertices on left and right of point and top and bottom
// don't access VBO since a big performance hit when only 4 vertices are needed
// Step from one vertex to another in the level detail algorithm
const int currentLodStep = 1 << currentRenderLevel;
//const int currentLodStep = 1;
const Real inv_currentLodStep = 1.0f / currentLodStep;
// check if can be on a stitched part of tile
const int tileSizeMinuscurrentLodStep = tSize + 1 - currentLodStep;
if ( tileLoaded &&
( localTileX <= currentLodStep ||
localTileX >= tileSizeMinuscurrentLodStep ||
localTileZ <= currentLodStep ||
localTileZ >= tileSizeMinuscurrentLodStep ) )
{
// get stitching configuration
PagingLandScapeRenderable * const r = tile->getRenderable( );
PagingLandScapeRenderable * neighbour;
// get each tile LOD and if stitching occurs in this direction.
neighbour = r->_getNeighbor( NORTH );
const bool north = ( neighbour && neighbour->isLoaded( )
&& neighbour->getRenderLevel( ) > currentRenderLevel
&& localTileZ <= currentLodStep );//z-1
neighbour = r->_getNeighbor( SOUTH );
const bool south = ( neighbour && neighbour->isLoaded( )
&& neighbour->getRenderLevel( ) > currentRenderLevel
&& localTileZ >= tileSizeMinuscurrentLodStep );//z+1
assert ( north != south || ( south == false && north == false ) );
neighbour = r->_getNeighbor( EAST );
const bool east = ( neighbour && neighbour->isLoaded( )
&& neighbour->getRenderLevel( ) > currentRenderLevel
&& localTileX >= tileSizeMinuscurrentLodStep );//x+1
neighbour = r->_getNeighbor( WEST );
const bool west = ( neighbour && neighbour->isLoaded( )
&& neighbour->getRenderLevel( ) > currentRenderLevel
&& localTileX <= currentLodStep );//x-1
assert ( east != west || ( east == false && west == false ) );
if ( north || south || east || west )
{
// Interpolate at LOD that uses stitching between tiles if needed.
//
// lower LOD
// *-----------*
// |\ \ 3 / /|
// |1\2 \ / 4/5|
// *--*--*--*--*
// higher LOD
//
// we iterate over triangle to find which contains the points.
// then we launch a ray to triangle intersection query.
//
// any simpler suggestion welcome. ( gladly, this is hell long full of repetition code. )
//
const Vector2 pos ( localPageX, localPageZ );
int bottom_right_x, bottom_right_z;
Vector2 a2d, b2d , c2d;
if ( north )
{
bool not_found = true;
if ( east )//northeast
{
#ifdef _DEBUGPOSHEIGHTSTICH
debugStich += " north: " + StringConverter::toString( r->_getNeighbor( NORTH )->getRenderLevel( ) ) +
" east: " + StringConverter::toString( r->_getNeighbor( EAST )->getRenderLevel( ) );
#endif //_DEBUGPOSHEIGHTSTICH
// neighbour lod spread
const int neighbour_currentLodStep = 1 << r->_getNeighbor( EAST )->getRenderLevel( );
// Step half way between low detail steps
const int halfsuperstep = neighbour_currentLodStep >> 1;
const unsigned long neighbour_lod_mask = ~( neighbour_currentLodStep - 1 );
bottom_right_z = static_cast<int>( localPageZ ) & neighbour_lod_mask;
const unsigned long lod_mask = ~( currentLodStep - 1 );
bottom_right_x = static_cast<int>( localPageX ) & lod_mask;
a2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z );
b2d = Vector2 ( bottom_right_x, bottom_right_z + halfsuperstep );
c2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z + neighbour_currentLodStep );
// biggest Middle tri
if ( !Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
// all other smalls tri up to middle
// but omit first triangle
// omit first tri
a2d = Vector2 ( bottom_right_x, bottom_right_z );
b2d = Vector2 ( bottom_right_x, bottom_right_z + currentLodStep );
c2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z );
int step = 1;
while ( step < halfsuperstep &&
!Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
step += currentLodStep;
a2d.y += currentLodStep;
b2d.y += currentLodStep;
}
// stops here, not looking after middle of higher lod.
// middle point
if ( step < halfsuperstep )
not_found = false;
}
else
{
not_found = false;
}
}
else if ( west )//northwest
{
#ifdef _DEBUGPOSHEIGHTSTICH
debugStich += " north: " + StringConverter::toString( r->_getNeighbor( NORTH )->getRenderLevel( ) ) +
" west: " + StringConverter::toString( r->_getNeighbor( WEST )->getRenderLevel( ) );
#endif //_DEBUGPOSHEIGHTSTICH
// neighbour lod spread
const int neighbour_currentLodStep = 1 << r->_getNeighbor( WEST )->getRenderLevel( );
// Step half way between low detail steps
const int halfsuperstep = neighbour_currentLodStep >> 1;
const unsigned long neighbour_lod_mask = ~( neighbour_currentLodStep - 1 );
bottom_right_z = static_cast<int>( localPageZ ) & neighbour_lod_mask;
const unsigned long lod_mask = ~( currentLodStep - 1 );
bottom_right_x = static_cast<int>( localPageX ) & lod_mask;
a2d = Vector2 ( bottom_right_x, bottom_right_z );
b2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z + halfsuperstep );
c2d = Vector2 ( bottom_right_x, bottom_right_z + neighbour_currentLodStep );
// biggest Middle tri
if ( !Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
//all other small tri
a2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z );
b2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z + currentLodStep );
c2d = Vector2 ( bottom_right_x, bottom_right_z );
int step = halfsuperstep;
// begins at middle point
a2d.y += halfsuperstep;
b2d.y += halfsuperstep;
c2d.y += neighbour_currentLodStep;
while ( step < neighbour_currentLodStep &&
!Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
step += currentLodStep;
a2d.y += currentLodStep;
b2d.y += currentLodStep;
}
// stops here
if ( step < neighbour_currentLodStep )
not_found = false;
}
else
{
not_found = false;
}
}
if ( not_found )
{
// in north stitching
#ifdef _DEBUGPOSHEIGHTSTICH
debugStich += " north: " + StringConverter::toString( r->_getNeighbor( NORTH )->getRenderLevel( ) );
#endif //_DEBUGPOSHEIGHTSTICH
// neighbour lod spread
const int neighbour_currentLodStep = 1 << r->_getNeighbor( NORTH )->getRenderLevel( );
// Step half way between low detail steps
const int halfsuperstep = neighbour_currentLodStep >> 1;
const unsigned long neighbour_lod_mask = ~( neighbour_currentLodStep - 1 );
bottom_right_x = static_cast<int>( localPageX ) & neighbour_lod_mask;
const unsigned long lod_mask = ~( currentLodStep - 1 );
bottom_right_z = static_cast<int>( localPageZ ) & lod_mask;
a2d = Vector2 ( bottom_right_x, bottom_right_z );
b2d = Vector2 ( bottom_right_x + halfsuperstep, bottom_right_z + currentLodStep );
c2d = Vector2 ( bottom_right_x + neighbour_currentLodStep, bottom_right_z );
// biggest Middle tri
if ( !Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
//all other small tri
// could omit first and last tri ?
int step = 0;
a2d = Vector2 ( bottom_right_x, bottom_right_z + currentLodStep );
b2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z + currentLodStep );
c2d = Vector2 ( bottom_right_x, bottom_right_z );
while ( step < halfsuperstep &&
!Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
step += currentLodStep;
a2d.x += currentLodStep;
b2d.x += currentLodStep;
}
// middle point
if ( step >= halfsuperstep )
{
c2d.x += neighbour_currentLodStep;
while ( step < neighbour_currentLodStep &&
!Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
step += currentLodStep;
a2d.x += currentLodStep;
b2d.x += currentLodStep;
}
}
}
}
}
else if ( south )
{
bool not_found = true;
if ( east )//northeast
{
#ifdef _DEBUGPOSHEIGHTSTICH
debugStich += " south: " + StringConverter::toString( r->_getNeighbor( SOUTH )->getRenderLevel( ) ) +
" east: " + StringConverter::toString( r->_getNeighbor( EAST )->getRenderLevel( ) );
#endif //_DEBUGPOSHEIGHTSTICH
// neighbour lod spread
const int neighbour_currentLodStep = 1 << r->_getNeighbor( EAST )->getRenderLevel( );
// Step half way between low detail steps
const int halfsuperstep = neighbour_currentLodStep >> 1;
const unsigned long neighbour_lod_mask = ~( neighbour_currentLodStep - 1 );
bottom_right_z = static_cast<int>( localPageZ ) & neighbour_lod_mask;
const unsigned long lod_mask = ~( currentLodStep - 1 );
bottom_right_x = static_cast<int>( localPageX ) & lod_mask;
a2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z );
b2d = Vector2 ( bottom_right_x, bottom_right_z + halfsuperstep );
c2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z + neighbour_currentLodStep );
// biggest Middle tri
if ( !Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
// all other smalls tri up to middle
// but omit first triangle
// omit first tri
a2d = Vector2 ( bottom_right_x, bottom_right_z );
b2d = Vector2 ( bottom_right_x, bottom_right_z + currentLodStep );
c2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z );
int step = 1;
while ( step < halfsuperstep &&
!Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
step += currentLodStep;
a2d.y += currentLodStep;
b2d.y += currentLodStep;
}
// stops here, not looking after middle of higher lod.
// middle point
if ( step < halfsuperstep )
not_found = false;
}
else
{
not_found = false;
}
}
else if ( west )//northwest
{
#ifdef _DEBUGPOSHEIGHTSTICH
debugStich += " south: " + StringConverter::toString( r->_getNeighbor( SOUTH )->getRenderLevel( ) ) +
" west: " + StringConverter::toString( r->_getNeighbor( WEST )->getRenderLevel( ) );
#endif //_DEBUGPOSHEIGHTSTICH
// neighbour lod spread
const int neighbour_currentLodStep = 1 << r->_getNeighbor( WEST )->getRenderLevel( );
// Step half way between low detail steps
const int halfsuperstep = neighbour_currentLodStep >> 1;
const unsigned long neighbour_lod_mask = ~( neighbour_currentLodStep - 1 );
bottom_right_z = static_cast<int>( localPageZ ) & neighbour_lod_mask;
const unsigned long lod_mask = ~( currentLodStep - 1 );
bottom_right_x = static_cast<int>( localPageX ) & lod_mask;
a2d = Vector2 ( bottom_right_x, bottom_right_z );
b2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z + halfsuperstep );
c2d = Vector2 ( bottom_right_x, bottom_right_z + neighbour_currentLodStep );
// biggest Middle tri
if ( !Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
//all other small tri
a2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z );
b2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z + currentLodStep );
c2d = Vector2 ( bottom_right_x, bottom_right_z );
int step = halfsuperstep;
// begins at middle point
a2d.y += halfsuperstep;
b2d.y += halfsuperstep;
c2d.y += neighbour_currentLodStep;
while ( step < neighbour_currentLodStep &&
!Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
step += currentLodStep;
a2d.y += currentLodStep;
b2d.y += currentLodStep;
}
// stops here
if ( step < neighbour_currentLodStep )
not_found = false;
}
else
{
not_found = false;
}
}
if ( not_found )
{
// south
#ifdef _DEBUGPOSHEIGHTSTICH
debugStich += " south: " + StringConverter::toString( r->_getNeighbor( SOUTH )->getRenderLevel( ) );
#endif //_DEBUGPOSHEIGHTSTICH
// neighbour lod spread
const int neighbour_currentLodStep = 1 << r->_getNeighbor( SOUTH )->getRenderLevel( );
// Step half way between low detail steps
const int halfsuperstep = neighbour_currentLodStep >> 1;
const unsigned long neighbour_lod_mask = ~( neighbour_currentLodStep - 1 );
bottom_right_x = static_cast<int>( localPageX ) & neighbour_lod_mask;
const unsigned long lod_mask = ~( currentLodStep - 1 );
bottom_right_z = static_cast<int>( localPageZ ) & lod_mask;
a2d = Vector2 ( bottom_right_x, bottom_right_z + currentLodStep );
b2d = Vector2 ( bottom_right_x + halfsuperstep, bottom_right_z );
c2d = Vector2 ( bottom_right_x + neighbour_currentLodStep, bottom_right_z + currentLodStep );
// biggest Middle tri
if ( !Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
//all other small tri
// could omit first and last tri ?
int step = 0;
a2d = Vector2 ( bottom_right_x, bottom_right_z );
b2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z );
c2d = Vector2 ( bottom_right_x, bottom_right_z + currentLodStep );
while ( step < halfsuperstep &&
!Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
step += currentLodStep;
a2d.x += currentLodStep;
b2d.x += currentLodStep;
}
// middle point
if ( step >= halfsuperstep )
{
c2d.x += neighbour_currentLodStep;
while ( step < neighbour_currentLodStep &&
!Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
step += currentLodStep;
a2d.x += currentLodStep;
b2d.x += currentLodStep;
}
}
}
}
}
else if ( east ) // just east
{
#ifdef _DEBUGPOSHEIGHTSTICH
debugStich += " east: " + StringConverter::toString( r->_getNeighbor( EAST )->getRenderLevel( ) );
#endif //_DEBUGPOSHEIGHTSTICH
// neighbour lod spread
const int neighbour_currentLodStep = 1 << r->_getNeighbor( EAST )->getRenderLevel( );
// Step half way between low detail steps
const int halfsuperstep = neighbour_currentLodStep >> 1;
const unsigned long neighbour_lod_mask = ~( neighbour_currentLodStep - 1 );
bottom_right_z = static_cast<int>( localPageZ ) & neighbour_lod_mask;
const unsigned long lod_mask = ~( currentLodStep - 1 );
bottom_right_x = static_cast<int>( localPageX ) & lod_mask;
a2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z );
b2d = Vector2 ( bottom_right_x, bottom_right_z + halfsuperstep );
c2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z + neighbour_currentLodStep );
// biggest Middle tri
if ( !Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
//all other small tri
a2d = Vector2 ( bottom_right_x, bottom_right_z );
b2d = Vector2 ( bottom_right_x, bottom_right_z + currentLodStep );
c2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z );
int step = 0;
while ( step < halfsuperstep &&
!Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
step += currentLodStep;
a2d.y += currentLodStep;
b2d.y += currentLodStep;
}
// middle point
if ( step >= halfsuperstep )
{
c2d.y += neighbour_currentLodStep;
while ( step < neighbour_currentLodStep &&
!Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
step += currentLodStep;
a2d.y += currentLodStep;
b2d.y += currentLodStep;
}
}
}
}
else if ( west ) // just west
{
#ifdef _DEBUGPOSHEIGHTSTICH
debugStich += " west: " + StringConverter::toString( r->_getNeighbor( WEST )->getRenderLevel( ) );
#endif //_DEBUGPOSHEIGHTSTICH
// neighbour lod spread
const int neighbour_currentLodStep = 1 << r->_getNeighbor( WEST )->getRenderLevel( );
// Step half way between low detail steps
const int halfsuperstep = neighbour_currentLodStep >> 1;
const unsigned long neighbour_lod_mask = ~( neighbour_currentLodStep - 1 );
bottom_right_z = static_cast<int>( localPageZ ) & neighbour_lod_mask;
const unsigned long lod_mask = ~( currentLodStep - 1 );
bottom_right_x = static_cast<int>( localPageX ) & lod_mask;
a2d = Vector2 ( bottom_right_x, bottom_right_z );
b2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z + halfsuperstep );
c2d = Vector2 ( bottom_right_x, bottom_right_z + neighbour_currentLodStep );
// biggest Middle tri
if ( !Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
//all other small tri
a2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z );
b2d = Vector2 ( bottom_right_x + currentLodStep, bottom_right_z + currentLodStep );
c2d = Vector2 ( bottom_right_x, bottom_right_z );
int step = 0;
while ( step < halfsuperstep &&
!Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
step += currentLodStep;
a2d.y += currentLodStep;
b2d.y += currentLodStep;
}
// middle point
if ( step >= halfsuperstep )
{
c2d.y += neighbour_currentLodStep;
while ( step < neighbour_currentLodStep &&
!Math::pointInTri2D ( pos, a2d, b2d, c2d ) )
{
step += currentLodStep;
a2d.y += currentLodStep;
b2d.y += currentLodStep;
}
}
}
}
const Vector3 a ( a2d.x, getHeightAtPage ( pageNumberX, pageNumberZ, a2d.x, a2d.y ), a2d.y );
const Vector3 b ( b2d.x, getHeightAtPage ( pageNumberX, pageNumberZ, b2d.x, b2d.y ), b2d.y );
const Vector3 c ( c2d.x, getHeightAtPage ( pageNumberX, pageNumberZ, c2d.x, c2d.y ), c2d.y );
#ifdef _DEBUGPOSHEIGHTSTICH
const Real shiftx = pageNumberX*pSize - mOptions->maxUnScaledX;
const Real shiftz = pageNumberZ*pSize - mOptions->maxUnScaledZ;
const Vector3 A ( ( a.x + shiftx ) * mOptions->scale.x,
a.y,
( a.z + shiftz ) * mOptions->scale.z );
const Vector3 B ( ( b.x + shiftx ) * mOptions->scale.x,
b.y,
( b.z + shiftz ) * mOptions->scale.z );
const Vector3 C ( ( c.x + shiftx ) * mOptions->scale.x,
c.y,
( c.z + shiftz ) * mOptions->scale.z );
static bool debugged_stitch_none = true;
static SceneNode* Anode = 0;
static SceneNode* Bnode = 0;
static SceneNode* Cnode = 0;
if ( debugged_stitch_none )
{
const String name( "TriDebugSphere" );
Entity* entity = PagingLandScapeSceneManager::getSingleton( ).createEntity( name, "sphere.mesh" );
SceneNode* Rootnode = PagingLandScapeSceneManager::getSingleton( ).getRootSceneNode( );
Entity *e;
Anode = Rootnode->createChildSceneNode( name + "A" );
e = entity->clone( name + "A" );
Anode->attachObject( e );
Anode->setScale( 0.1f, 0.1f, 0.1f );
Anode->showBoundingBox( true );
e->getMesh( )->getSubMesh( 0 )->setMaterialName( "BaseRedNoLightNoDepthCheck" );
Bnode = Rootnode->createChildSceneNode( name + "B" );
e = entity->clone( name + "B" );
Bnode->attachObject( e );
Bnode->setScale( 0.1f, 0.1f, 0.1f );
Bnode->showBoundingBox( true );
e->getMesh( )->getSubMesh( 0 )->setMaterialName ( "BaseRedNoLightNoDepthCheck" );
Cnode = Rootnode->createChildSceneNode( name + "C" );
e = entity->clone( name + "C" );
Cnode->attachObject( e );
Cnode->setScale( 0.1f, 0.1f, 0.1f );
Cnode->showBoundingBox( true );
e->getMesh( )->getSubMesh( 0 )->setMaterialName ( "BaseRedNoLightNoDepthCheck" );
debugged_stitch_none = false;
}
Anode->setPosition( A );
Bnode->setPosition( B );
Cnode->setPosition( C );
#endif //_DEBUGPOSHEIGHTSTICH
const Ray triIntersect ( Vector3( localPageX, getMaxHeight( ), localPageZ ), Vector3::NEGATIVE_UNIT_Y );
std::pair<bool, Real> res = Math::intersects( triIntersect, a, b, c, true, true );
if ( res.first )
heightValue = getMaxHeight( ) - res.second;
else
heightValue = 0.0f;
if ( getSlopeAt )
{
Vector3 result;
Vector3 vector1;
Vector3 vector2;
vector1 = a - b;
vector2 = b - c;
result.x = ( vector1.y * vector2.z ) - ( vector1.z * vector2.y );
result.y = ( vector1.z * vector2.x ) - ( vector1.x * vector2.z );
result.z = ( vector1.x * vector2.y ) - ( vector1.y * vector2.x );
// result.x = ( ( top_right_y - top_left_y ) * ( -mOptions->scale.z ) );
// result.y = mOptions->scale.x * ( -mOptions->scale.z );
// result.z = -mOptions->scale.x * ( bottom_left_y - top_left_y );
result.normalise( );
*getSlopeAt = 1.0 + result.y;
if ( fabs( *getSlopeAt ) < 0.001f )
*getSlopeAt = 0.0f;
}
return heightValue;
}
}
// no stitching, easy life...
//
// TL-----TR 1.0
// | / |
// | / | .
// | / | .
// | / | . ^
// | / | |
// BL-----BR 0.0 z
// 1.0 ... 0.0
//
// < - x
//
// Where 1.0 is currentLodStep
//
const unsigned long lod_mask = ~( currentLodStep - 1 );
const int bottom_right_x = static_cast<int>( localPageX ) & lod_mask;
const int bottom_right_z = static_cast<int>( localPageZ ) & lod_mask;
const int top_right_x = bottom_right_x + currentLodStep;
const int top_right_z = bottom_right_z + currentLodStep;
#ifdef _DEBUGPOSHEIGHTSTICH
if ( 1 )
{
RenderTarget *t = mOptions->primaryCamera->getViewport( )->getTarget ( );
const String Debugtext ( debugStich );
t->setDebugText ( debugStich );
}
#endif //_DEBUGPOSHEIGHTSTICH
// find the 4 heights around the point
const Real bottom_right_y = getHeightAtPage ( pageNumberX, pageNumberZ, bottom_right_x , bottom_right_z );
const Real bottom_left_y = getHeightAtPage ( pageNumberX, pageNumberZ, top_right_x, bottom_right_z );
const Real top_right_y = getHeightAtPage ( pageNumberX, pageNumberZ, bottom_right_x, top_right_z );
const Real top_left_y = getHeightAtPage ( pageNumberX, pageNumberZ, top_right_x, top_right_z );
#ifdef _DEBUGPOSHEIGHTSTICH
const Real shiftx = pageNumberX*pSize - mOptions->maxUnScaledX;
const Real shiftz = pageNumberZ*pSize - mOptions->maxUnScaledZ;
const Vector3 BR( ( bottom_right_x + shiftx ) * mOptions->scale.x,
bottom_right_y,
( bottom_right_z + shiftz ) * mOptions->scale.z );
const Vector3 BL( ( top_right_x + shiftx ) * mOptions->scale.x,
bottom_left_y,
( bottom_right_z + shiftz ) * mOptions->scale.z );
const Vector3 TR( ( bottom_right_x + shiftx ) * mOptions->scale.x,
top_right_y,
( top_right_z + shiftz ) * mOptions->scale.z );
const Vector3 TL( ( top_right_x + shiftx ) * mOptions->scale.x,
top_left_y,
( top_right_z + shiftz ) * mOptions->scale.z );
static bool debugged_none = true;
static SceneNode* BRnode = 0;
static SceneNode* BLnode = 0;
static SceneNode* TRnode = 0;
static SceneNode* TLnode = 0;
if ( debugged_none )
{
const String name( "DebugSphere" );
Entity* entity = PagingLandScapeSceneManager::getSingleton( ).createEntity( name, "sphere.mesh" );
SceneNode* Rootnode = PagingLandScapeSceneManager::getSingleton( ).getRootSceneNode( );
BRnode = Rootnode->createChildSceneNode( name + "BR" );
BRnode->attachObject( entity->clone( name + "BR" ) );
BRnode->setScale( 0.1f, 0.1f, 0.1f );
BRnode->showBoundingBox( true );
BLnode = Rootnode->createChildSceneNode( name + "BL" );
BLnode->attachObject( entity->clone( name + "BL" ) );
BLnode->setScale( 0.1f, 0.1f, 0.1f );
BLnode->showBoundingBox( true );
TRnode = Rootnode->createChildSceneNode( name + "TR" );
TRnode->attachObject( entity->clone( name + "TR" ) );
TRnode->setScale( 0.1f, 0.1f, 0.1f );
TRnode->showBoundingBox( true );
TLnode = Rootnode->createChildSceneNode( name + "TL" );
TLnode->attachObject( entity->clone( name + "TL" ) );
TLnode->setScale( 0.1f, 0.1f, 0.1f );
TLnode->showBoundingBox( true );
debugged_none = false;
}
BRnode->setPosition( BR );
BLnode->setPosition( BL );
TRnode->setPosition( TR );
TLnode->setPosition( TL );
if ( 0 )
{
RenderTarget *t = mOptions->primaryCamera->getViewport( )->getTarget ( );
const String Debugtext ( "( X= " + StringConverter::toString( localPageX ) + " Z=" +
StringConverter::toString( localPageZ ) + " ), ( br_x=" +
StringConverter::toString( bottom_right_x ) + ", br_z=" +
StringConverter::toString( bottom_right_z ) + " ) & spread=" +
StringConverter::toString( currentLodStep )+ " ) & lod=" +
StringConverter::toString( currentRenderLevel ) );
t->setDebugText( Debugtext );
}
#endif //_DEBUGPOSHEIGHTSTICH
const Real z_pct = ( localPageZ - bottom_right_z ) * inv_currentLodStep;
Real x_pct = ( localPageX - bottom_right_x ) * inv_currentLodStep;
if ( x_pct > 1 - z_pct )
{
// This point is on the upper-left tri
const Real y1 = bottom_left_y * ( 1-z_pct ) + top_left_y * z_pct;
const Real y2 = bottom_left_y * ( 1-z_pct ) + top_right_y * z_pct;
if ( z_pct > 0.0f )
x_pct = ( x_pct - ( 1-z_pct ) ) / z_pct;
if ( getSlopeAt )
{
Vector3 result( ( ( top_right_y - top_left_y ) * ( -mOptions->scale.z ) ),
mOptions->scale.x * ( -mOptions->scale.z ),
-mOptions->scale.x * ( bottom_left_y - top_left_y ) );
result.normalise( );
*getSlopeAt = 1.0 + result.y;
if ( fabs( *getSlopeAt ) < 0.001f )
*getSlopeAt = 0.0f;
}
return y1 * x_pct + y2 * ( 1-x_pct );
} // if ( x_pct > 1 - z_pct )
else
{
// This point is on the lower-right tri
const Real y1 = bottom_left_y * ( 1-z_pct ) + top_right_y * z_pct;
const Real y2 = bottom_right_y * ( 1-z_pct ) + top_right_y * z_pct;
if ( z_pct < 1.0f )
x_pct = x_pct / ( 1-z_pct );
if ( getSlopeAt )
{
Vector3 result( ( bottom_left_y - bottom_right_y ) * mOptions->scale.z,
-mOptions->scale.x * mOptions->scale.z,
mOptions->scale.x * ( top_right_y - bottom_right_y ) );
result.normalise( );
*getSlopeAt = 1.0 + result.y;
if ( fabs( *getSlopeAt ) < 0.001f )
*getSlopeAt = 0.0f;
}
return y1 * x_pct + y2 * ( 1-x_pct );
}
#else //_MAPSPLITTER
return 0.0f;
#endif //_MAPSPLITTER
}
//-----------------------------------------------------------------------
1491 const Real PagingLandScapeData2DManager::getWorldHeight( const Real x, const Real z )
{
#ifndef _MAPSPLITTER
// figure out which page the point is on
unsigned int pageX, pageZ;
if ( mPageManager->getPageIndices( x, z, pageX, pageZ, false ) )
{
PagingLandScapeData2D * const data = getData2D ( pageX, pageZ, false );
if ( data && data->isLoaded( ) )
{
// scale position from world to page scale
Real localX = x * mOptions->invScale.x;
Real localZ = z * mOptions->invScale.z;
// adjust x and z to be local to page
const Real pSize = mOptions->PageSize - 1;
localX -= pageX*pSize - mOptions->maxUnScaledX;
localZ -= pageZ*pSize - mOptions->maxUnScaledZ;
return getHeightAtPage ( pageX, pageZ, static_cast<int> ( localX ), static_cast<int> ( localZ ) );
}
}
#endif //_MAPSPLITTER
return 0.0f;
}
//-----------------------------------------------------------------------
1519 const Real PagingLandScapeData2DManager::getHeightAtPage( const unsigned int dataX, const unsigned int dataZ,
1520 const Real x, const Real z )
{
PagingLandScapeData2D* data = getData2D ( dataX, dataZ, false );
if ( data && data->isLoaded( ) )
{
Real lX = x;
Real lZ = z;
const Real pSize = mOptions->PageSize - 1;
PagingLandScapeData2D* srcdata = data;
//check if we have to change current page
if ( lX < 0.0f )
{
if ( dataX == 0 )
lX = 0.0f;
else
{
data = getData2D ( dataX - 1 , dataZ, false );
if ( data && data->isLoaded( ) )
{
lX = static_cast<Real> ( pSize );
}
else
{
lX = 0.0f;
data = srcdata;
}
}
}
else if ( lX > pSize )
{
if ( dataX == mOptions->world_width - 1 )
lX = static_cast<Real> ( pSize );
else
{
data = getData2D ( dataX + 1 , dataZ, false );
if ( data && data->isLoaded( ) )
{
lX = 0.0f;
}
else
{
lX = static_cast<Real> ( pSize );
data = srcdata;
}
}
}
if ( lZ < 0.0f )
{
if ( dataZ == 0 )
lZ = 0.0f;
else
{
data = getData2D ( dataX, dataZ - 1, false );
if ( data && data->isLoaded( ) )
{
lZ = static_cast<Real> ( pSize );
}
else
{
lZ = 0.0f;
data = srcdata;
}
}
}
else if ( lZ > pSize )
{
if ( dataZ == mOptions->world_height - 1 )
lZ = static_cast<Real> ( pSize );
else
{
data = getData2D ( dataX, dataZ + 1, false );
if ( data && data->isLoaded( ) )
{
lZ = 0.0f;
}
else
{
lZ = static_cast<Real> ( pSize );
data = srcdata;
}
}
}
assert ( data );
return data->getHeight ( lX, lZ );
}
return 0.0f;
}
//-----------------------------------------------------------------------
1610 const Real PagingLandScapeData2DManager::getHeightAtPage( const unsigned int dataX, const unsigned int dataZ,
const int x, const int z )
{
PagingLandScapeData2D * data = getData2D ( dataX, dataZ, false );
if ( data && data->isLoaded( ) )
{
int lX = x;
int lZ = z;
const int pSize = mOptions->PageSize - 1;
PagingLandScapeData2D* srcdata = data;
//check if we have to change current page
if ( lX < 0 )
{
if ( dataX == 0 )
lX = 0;
else
{
data = getData2D ( dataX - 1, dataZ, false );
if ( data && data->isLoaded( ) )
{
lX = pSize;
}
else
{
lX = 0;
data = srcdata;
}
}
}
else if ( lX > pSize )
{
if ( dataX == mOptions->world_width - 1 )
lX = pSize;
else
{
data = getData2D ( dataX + 1, dataZ, false );
if ( data && data->isLoaded( ) )
{
lX = 0;
}
else
{
lX = pSize;
data = srcdata;
}
}
}
if ( lZ < 0 )
{
if ( dataZ == 0 )
lZ = 0;
else
{
data = getData2D ( dataX, dataZ - 1, false );
if ( data && data->isLoaded( ) )
{
lZ = pSize;
}
else
{
lZ = 0;
data = srcdata;
}
}
}
else if ( lZ > pSize )
{
if ( dataZ == mOptions->world_height - 1 )
lZ = pSize;
else
{
data = getData2D ( dataX, dataZ + 1, false );
if ( data && data->isLoaded( ) )
{
lZ = 0;
}
else
{
lZ = pSize;
data = srcdata;
}
}
}
assert ( data );
return data->getHeight ( lX, lZ );
}
else
{
// not a border demand and we do not have the data.
return 0.0f;
}
}
//-----------------------------------------------------------------------
1707 const Vector3 PagingLandScapeData2DManager::getNormalAt( const unsigned int dataX, const unsigned int dataZ,
const unsigned int x, const unsigned int z )
{
PagingLandScapeData2D* data = getData2D ( dataX, dataZ, false );
if ( data && data->isLoaded( ) )
{
#ifdef _LOADEDNORM
// not as precise ( rgb normals gives 8 bits precision Real )
// and finally nearly as fast.
return data->getNormalAt ( x, z );
#else /*_LOADEDNORM*/
{
// First General method : ( 9 adds and 6 muls + a normalization )
// *---v3--*
// | | |
// | | |
// v1--X--v2
// | | |
// | | |
// *---v4--*
//
// U = v2 - v1;
// V = v4 - v3;
// N = Cross( U, V );
// N.normalise;
//
// BUT IN CASE OF A HEIGHTMAP :
//
// if you do some math by hand before you code,
// you can see that N is immediately given by
// Approximation ( 2 adds and a normalization )
//
// N = Vector3( z[x-1][y] - z[x+1][y], z[x][y-1] - z[x][y+1], 2 );
// N.normalise( );
//
// or even using SOBEL operator VERY accurate!
// ( 14 adds and a normalization )
//
// N = Vector3 ( z[x-1][y-1] + z[x-1][y] + z[x-1][y] + z[x-1][y+1] - z[x+1][y-1] - z[x+1][y] - z[x+1][y] - z[x+1][y+1],
// z[x-1][y-1] + z[x][y-1] + z[x][y-1] + z[x+1][y-1] - z[x-1][y+1] - z[x][y+1] - z[x][y+1] - z[x+1][y+1],
// 8 );
// N.normalize( );
// Fast SOBEL filter
// the divider make sure we do respect proportion ( height and width proportional to y )
const Real Divider = static_cast <Real> ( mOptions->PageSize - 1 ) / mOptions->scale.y;
#define gH( a, b ) ( getHeightAtPage( dataX, dataZ, static_cast<int> ( a ), static_cast<int> ( b ) ) )
// Vector3 result ( ( gH( x-1, z-1 ) + gH ( x-1, z ) + gH ( x-1, z ) + gH ( x-1, z+1 ) - gH ( x+1, z-1 ) - gH ( x+1, z ) - gH ( x+1, z ) - gH ( x+1, z+1 ) ) * Divider,
// 8.0f,
// ( gH ( x-1, z-1 ) + gH ( x, z-1 ) + gH ( x, z-1 ) + gH ( x+1, z-1 ) - gH ( x-1, z+1 ) - gH ( x, z+1 ) - gH ( x, z+1 ) - gH ( x+1, z+1 ) ) * Divider );
Vector3 result( ( gH ( x - 1 , z ) - gH ( x + 1 , z ) ) * Divider,
2.0f,
( gH ( x, z - 1 ) - gH ( x , z + 1 ) ) * Divider );
result.normalise ( );
return result;
}
#endif //_NOLOAD
}
return Vector3::UNIT_Y;
}
//----------------------------------------------------------------------------
1775 const Real PagingLandScapeData2DManager::getRealWorldSlope( const Real x, const Real z )
{
#ifndef _MAPSPLITTER
// figure out which page the point is on
const Vector3 pos( x, 0, z );
unsigned int pageX, pageZ;
if ( mPageManager->getPageIndices( pos.x, pos.z, pageX, pageZ, false ) )
{
PagingLandScapeData2D* data = getData2D ( pageX, pageZ, false );
if ( data && data->isLoaded( ) )
{
// figure out which tile the point is on
PagingLandScapeTile *t = mPageManager->getTile( pos.x, pos.z,
pageX, pageZ,
false );
unsigned int Lod = 0;
if ( t && t->isLoaded( ) )
Lod = t->getRenderable( )->getRenderLevel( );
const Vector3 normalVector = getNormalAt( pageX, pageZ, static_cast<unsigned int>( x ), static_cast<unsigned int>( z ), Lod );
const Real slope = 1.0f + normalVector.y;
if ( slope < 0.001f )
return 0.0f;
else
return slope;
}
}
#endif //_MAPSPLITTER
return 0.0f;
}
//-----------------------------------------------------------------------
1807 const Vector3 PagingLandScapeData2DManager::getNormalAt( const unsigned int pageX, const unsigned int pageZ, const unsigned int x, const unsigned int z, const unsigned int Lod )
{
Vector3 result;
// scale position from world to page scale
Real localX = x * mOptions->invScale.x;
Real localZ = z * mOptions->invScale.z;
// adjust x and z to be local to page
const Real pSize = mOptions->PageSize - 1;
localX -= pageX * pSize - mOptions->maxUnScaledX;
localZ -= pageZ * pSize - mOptions->maxUnScaledZ;
// make sure x and z do not go outside the world boundaries
if ( localX < 0 )
localX = 0;
else if ( localX >= pSize )
localX = pSize - 1;
if ( localZ < 0 )
localZ = 0;
else if ( localZ >= pSize )
localZ = pSize - 1;
// find the 4 vertices that surround the point
// use LOD info to determine vertex data spacing - this is passed into the method
// determine vertices on left and right of point and top and bottom
// don't access VBO since a big performance hit when only 4 vertices are needed
const int currentLodStep = 1 << Lod;
const Real inv_currentLodStep = 1.0f / currentLodStep;
// find the vertex to the 'bottom right' of the point
const unsigned long lod_mask = ~( currentLodStep - 1 );
const int bottom_right_x = static_cast<int>( localX ) & lod_mask;
const int bottom_right_z = static_cast<int>( localZ ) & lod_mask;
// find the 4 heights around the point
const Real bottom_right_y = getHeightAtPage( pageX, pageZ, bottom_right_x , bottom_right_z );
const Real bottom_left_y = getHeightAtPage( pageX, pageZ, bottom_right_x + currentLodStep, bottom_right_z );
const Real top_right_y = getHeightAtPage( pageX, pageZ, bottom_right_x, bottom_right_z + currentLodStep );
const Real top_left_y = getHeightAtPage( pageX, pageZ, bottom_right_x + currentLodStep, bottom_right_z + currentLodStep );
const Real z_pct = ( localZ - bottom_right_z ) * inv_currentLodStep;
Real x_pct = ( localX - bottom_right_x ) * inv_currentLodStep;
// TL-----TR 1.0
// | / |
// | / | .
// | / | .
// | / | . ^
// | / | |
// BL-----BR 0.0 z
// 1.0 ... 0.0
//
// < - x
if ( x_pct > 1 - z_pct )
{
// This point is on the upper-left tri
/*
Vector3 vector1;
Vector3 vector2;
vector1.x = -mOptions->scale.x;
vector1.y = top_right_y - top_left_y;
vector1.z = 0;
vector2.x = 0;
vector2.y = bottom_left_y - top_left_y;
vector2.z = -mOptions->scale.z;
result.x = ( vector1.y * vector2.z ) - ( vector1.z * vector2.y );
result.y = ( vector1.z * vector2.x ) - ( vector1.x * vector2.z );
result.z = ( vector1.x * vector2.y ) - ( vector1.y * vector2.x );
*/
// The formulas for calculating result are simplified from the above
// commented-out code for computing the cross product.
result.x = ( ( top_right_y - top_left_y ) * ( -mOptions->scale.z ) );
result.y = mOptions->scale.x * ( -mOptions->scale.z );
result.z = -mOptions->scale.x * ( bottom_left_y - top_left_y );
}
else
{
// This point is on the lower-right tri
/*
Vector3 vector1;
Vector3 vector2;
vector1.x = mOptions->scale.x;
vector1.y = bottom_left_y - bottom_right_y;
vector1.z = 0;
vector2.x = 0;
vector2.y = top_right_y - bottom_right_y;
vector2.z = mOptions->scale.z;
result.x = ( vector1.y * vector2.z ) - ( vector1.z * vector2.y );
result.y = ( vector1.z * vector2.x ) - ( vector1.x * vector2.z );
result.z = ( vector1.x * vector2.y ) - ( vector1.y * vector2.x );
*/
// The formulas for calculating result are simplified from the above
// commented-out code for computing the cross product.
result.x = ( bottom_left_y - bottom_right_y ) * mOptions->scale.z;
result.y = -mOptions->scale.x * mOptions->scale.z;
result.z = mOptions->scale.x * ( top_right_y - bottom_right_y );
}
result.normalise( );
return result;
}
//-----------------------------------------------------------------------
1916 Real PagingLandScapeData2DManager::getMaxSlope( Vector3 location1, Vector3 location2, Real maxSlopeIn )
{
int testCount;
int testIndex;
Real maxSlope;
Real nextSlope;
Vector3 unitVector;
Vector3 iterationOffset;
Vector3 nextLocation;
Real halfWorldSizeX;
Real halfWorldSizeZ;
Real distBetweenPoints;
// worldSizeX = ( float )mOptions->world_width * mOptions->scale.x;
// worldSizeZ = ( float )mOptions->world_height * mOptions->scale.z;
halfWorldSizeX = mOptions->maxScaledX;
halfWorldSizeZ = mOptions->maxScaledZ;
if ( ( location1[0] > halfWorldSizeX ) || ( location1[2] > halfWorldSizeZ ) ||
( location2[0] > halfWorldSizeX ) || ( location2[2] > halfWorldSizeZ ) ||
( location1[0] < -halfWorldSizeX ) || ( location1[2] < -halfWorldSizeZ ) ||
( location2[0] < -halfWorldSizeX ) || ( location2[2] < -halfWorldSizeZ ) )
{
// One or both endpoints is off the edge of the world. Return max slope.
return 1.0f;
}
getInterpolatedWorldHeight( location2.x, location2.z, &maxSlope );
// maxSlope = getRealWorldSlope( location2.x, location2.z );
if ( maxSlope > maxSlopeIn )
return maxSlope;
unitVector.x = location2.x - location1.x;
unitVector.y = 0.0f;
unitVector.z = location2.z - location1.z;
// before normalizing our unitVector, calculate the distance between the endpoints
distBetweenPoints = ( Real )sqrt( ( unitVector.x * unitVector.x ) + ( unitVector.z * unitVector.z ) );
// testCount = ( int )( distSquared / ( mOptions->scale.x * mOptions->scale.x ) / 16.0f );
testCount = ( int )( ( distBetweenPoints / mOptions->scale.x ) * 4.0f );
unitVector.normalise( );
iterationOffset.x = unitVector.x * ( mOptions->scale.x / 4.0f );
iterationOffset.z = unitVector.z * ( mOptions->scale.z / 4.0f );
nextLocation.x = location1.x;
nextLocation.y = location1.y;
nextLocation.z = location1.z;
for ( testIndex = 0; testIndex < testCount; testIndex++ )
{
getInterpolatedWorldHeight( nextLocation.x, nextLocation.z, &nextSlope );
// nextSlope = getRealWorldSlope( nextLocation.x, nextLocation.z );
if ( nextSlope > maxSlopeIn )
return nextSlope;
if ( nextSlope > maxSlope )
maxSlope = nextSlope;
nextLocation.x += iterationOffset.x;
nextLocation.z += iterationOffset.z;
}
return maxSlope;
}
} //namespace
1 /***************************************************************************
OgrePagingLandScapeData2D_HeightField.cpp - description
-------------------
begin : Mon Oct 13 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreLogManager.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreImage.h"
#include "OgreImageCodec.h"
#include "OgreArchiveManager.h"
#include "OgreStringConverter.h"
#include "OgreException.h"
#include "OgrePagingLandScapeData2D.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeData2D_HeightField.h"
#include "fileutils.h"
namespace Ogre
{
//-----------------------------------------------------------------------
45 PagingLandScapeData2D* PagingLandScapeData2D_HeightField::newPage( )
{
return new PagingLandScapeData2D_HeightField( mParent );
}
//-----------------------------------------------------------------------
50 PagingLandScapeData2D_HeightField::PagingLandScapeData2D_HeightField( PagingLandScapeData2DManager *dataMgr ):
PagingLandScapeData2D( dataMgr )
{
mImage = 0;
mCoverage = 0;
mBase = 0;
mShadow = 0;
mMaxheight = mParent->getOptions( )->scale.y;
}
//-------------------------------------------------------------------
60 const Real PagingLandScapeData2D_HeightField::getMaxAbsoluteHeight( void ) const
{
return mParent->getOptions( )->scale.y;
}
//-----------------------------------------------------------------------
65 PagingLandScapeData2D_HeightField::~PagingLandScapeData2D_HeightField( )
{
}
//-----------------------------------------------------------------------
69 const ColourValue PagingLandScapeData2D_HeightField::getBase ( const Real mX, const Real mZ )
{
if ( mBase != 0 )
{
unsigned int Pos = static_cast<unsigned int> ( ( mZ * mBase->getWidth( ) + mX ) * 4 );//4 bytes ( mImage is RGBA )
if ( mBase->getSize ( ) > Pos )
{
const Real divider = 1.0f / 255;
return ColourValue( ( Real ) mBase->getData( )[ Pos + 0] * divider,
( Real ) mBase->getData( )[ Pos + 1] * divider,
( Real ) mBase->getData( )[ Pos + 2] * divider,
( Real ) mBase->getData( )[ Pos + 3] * divider );
}
else
{
return ColourValue::White;
}
}
else
{
return ColourValue::White;
}
}
//-----------------------------------------------------------------------
94 const ColourValue PagingLandScapeData2D_HeightField::getCoverage ( const Real mX, const Real mZ )
{
if ( mCoverage != 0 )
{
unsigned int Pos = static_cast<unsigned int> ( ( mZ * mCoverage->getWidth( ) + mX ) * 4 );//4 bytes ( mImage is RGBA )
if ( mCoverage->getSize ( ) > Pos )
{
const Real divider = 1.0f / 255;
return ColourValue( ( Real ) mCoverage->getData( )[ Pos + 0] * divider,
( Real ) mCoverage->getData( )[ Pos + 1] * divider,
( Real ) mCoverage->getData( )[ Pos + 2] * divider,
( Real ) mCoverage->getData( )[ Pos + 3] * divider );
}
else
{
return ColourValue::White;
}
}
else
{
return ColourValue::White;
}
}
//-----------------------------------------------------------------------
119 const Real PagingLandScapeData2D_HeightField::getShadow ( const Real mX, const Real mZ,
120 const bool &positive )
{
if ( mShadow != 0 )
{
unsigned int Pos = static_cast<unsigned int> ( ( mZ * mShadow->getWidth( ) + mX ) * 3 );//3 bytes ( mImage is RGBA )
if ( mShadow->getSize ( ) > Pos )
{
if ( positive )
return static_cast<Real> ( mShadow->getData( )[ Pos + 0] ) / 255;
else
return static_cast<Real> ( mShadow->getData( )[ Pos + 1] ) / 255;
}
else
{
return 0.0f;
}
}
else
{
return 0.0f;
}
}
//-----------------------------------------------------------------------
144 const Vector3 PagingLandScapeData2D_HeightField::getNormal ( const Real x, const Real z )
{
#ifndef _LOADEDNORM
return PagingLandScapeData2D::getNormal( x, z );
#else
if ( mImage )
{
unsigned int Pos = static_cast<unsigned int> ( ( z * mSize + x ) * mBpp );//4 bytes ( mImage is RGBA )
if ( mMax > Pos )
{
const Real normalscale = 1.0f / 127.0f;
return Vector3 ( ( ( Real )( mImage->getData( )[Pos + 0] ) - 128.0f ) * normalscale,
( ( Real )( mImage->getData( )[Pos + 1] ) - 128.0f ) * normalscale,
( ( Real )( mImage->getData( )[Pos + 2] ) - 128.0f ) * normalscale );
}
else
{
return Vector3::UNIT_Y;
}
}
else
{
return Vector3::UNIT_Y;
}
#endif //_NOLOAD
}
//-----------------------------------------------------------------------
172 Real PagingLandScapeData2D_HeightField::getScale( ) const
{
Real prescale;
switch ( mBpp )
{
case 1:
prescale = mParent->getOptions( )->scale.y / 255;
break;
case 2:
prescale = mParent->getOptions( )->scale.y / 65535;
break;
case 3:
prescale = mParent->getOptions( )->scale.y / 16777215;
break;
case 4:
prescale = mParent->getOptions( )->scale.y / 16777215;
break;
default:
OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS,
"unrecongnized number of bpp for data src image.",
"PagingLandScapeData2D_HeightField::getScale" );
break;
}
return prescale;
}
//-----------------------------------------------------------------------
198 Real PagingLandScapeData2D_HeightField::getInvScale( ) const
{
Real prescale;
switch ( mBpp )
{
case 1:
prescale = 255.0 / mParent->getOptions( )->scale.y;
break;
case 2:
prescale = 65535.0 / mParent->getOptions( )->scale.y;
break;
case 3:
prescale = 16777215.0 / mParent->getOptions( )->scale.y;
break;
case 4:
prescale = 16777215.0 / mParent->getOptions( )->scale.y;
break;
default:
OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS,
"unrecongnized number of bpp for data src image.",
"PagingLandScapeData2D_HeightField::getScale" );
break;
}
return prescale;
}
//-----------------------------------------------------------------------
224 void PagingLandScapeData2D_HeightField::_save( )
{
const Real scale = getInvScale( );
const size_t bpp = mBpp;
size_t j = 0;
uchar * ogre_restrict data = mImage->getData( );
for ( unsigned int i = 0; i < mMaxArrayPos; i++ )
{
switch ( bpp )
{
case 1:
data[j] = uchar ( mHeightData[i] * scale );
break;
case 2:
case 3:
case 4:
{
const ushort syn = ushort ( mHeightData[i] * scale );
#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
data[j] = uchar ( ( syn >> 8 ) & 0xff );
data[j+ 1] = uchar ( syn & 0xff );
#else
data[j] = uchar ( syn & 0xff );
data[j+ 1] = uchar ( ( syn >> 8 ) & 0xff );
#endif
}
break;
default:
assert( 0 );
OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS,
"unrecognized bpp image.",
"PagingLandScapeData2D_HeightField::_save" );
break;
}
j += bpp;
}
const String fname = mParent->getOptions( )->LandScape_filename + "." +
StringConverter::toString( mPageZ ) + "." +
StringConverter::toString( mPageX ) + ".";
const String extname = mParent->getOptions( )->LandScape_extension;
FileInfoListPtr finfo = ResourceGroupManager::getSingleton( ).findResourceFileInfo (
mParent->getOptions( )->groupName,
fname + extname );
FileInfoList::iterator it = finfo->begin( );
if ( it != finfo->end( ) )
{
//FileInfo *inf = &( *it );
char *olddir = ChangeToDir ( const_cast< char * > ( ( ( it )->archive->getName( ) ).c_str( ) ) );
//FileSystemArchive::pushDirectory( )
mImage->save ( fname + "modif." + extname );
//FileSystemArchive::pushDirectory( );
RetablishDir ( olddir );
}
}
//-----------------------------------------------------------------------
283 bool PagingLandScapeData2D_HeightField::_load( const unsigned int mX, const unsigned int mZ )
{
const PagingLandScapeOptions * const opt = mParent->getOptions( );
const String pageName = "." + StringConverter::toString( mZ ) + "." +
StringConverter::toString( mX ) + ".";
const String &fileExt = opt->LandScape_extension;
const String &groupName = opt->groupName;
const String strFileName = opt->LandScape_filename + pageName;
mImage = new Image( );
if ( !( opt->Deformable &&
ResourceGroupManager::getSingleton( ).resourceExists( groupName, strFileName + "modif." + fileExt ) ) )
{
if ( !ResourceGroupManager::getSingleton( ).resourceExists( groupName, strFileName + fileExt ) )
{
LogManager::getSingleton( ).logMessage( LML_CRITICAL,
String( "PLSM2 : Cannot find map named " ) + strFileName + fileExt );
return false;
}
mImage->load ( strFileName + fileExt, groupName );
}
else
{
mImage->load ( strFileName + "modif." + fileExt, groupName );
}
//check to make sure it's 2^n + 1 size.
if ( mImage->getWidth( ) != mImage->getHeight( ) ||
!_checkSize( mImage->getWidth( ) ) )
{
String err = "Error: Invalid height map size : " +
StringConverter::toString( static_cast <unsigned int> ( mImage->getWidth( ) ) ) +
", " + StringConverter::toString( static_cast <unsigned int> ( mImage->getHeight( ) ) ) +
". Should be 2^n+1, 2^n+1";
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, err,
"PagingLandScapeData2D_HeightField::_load" );
}
mBpp = PixelUtil::getNumElemBytes ( mImage->getFormat ( ) );
const unsigned int bpp = static_cast <unsigned int> ( mBpp );
if ( mSize != mImage->getWidth( ) )
{
OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS,
"Error: Declared World size <> Height Map Size.",
"PagingLandScapeData2D_HeightField::_load" );
}
if ( opt->coverage_vertex_color )
{
mCoverage = new Image( );
mCoverage->load ( opt->LandScape_filename + ".Coverage" + pageName + fileExt,
groupName );
}
if ( opt->base_vertex_color )
{
mBase = new Image( );
mBase->load( opt->LandScape_filename + ".Base" + pageName + fileExt,
groupName );
}
if ( opt->vertex_shadowed )
{
mShadow = new Image( );
mShadow->load( opt->LandScape_filename + ".HS" + pageName + fileExt,
groupName );
}
mXDimension = mImage->getWidth( ) * bpp;
mZDimension = mImage->getHeight( ) * bpp;
mMax = static_cast <unsigned int> ( mSize * mSize * bpp );
mMaxArrayPos = static_cast <unsigned int> ( mSize * mSize );
mHeightData = new Real[mMaxArrayPos];
const Real scale = getScale( );
mMaxheight = 0.0f;
const uchar * const ogre_restrict imagedata = mImage->getData( );
const unsigned int maxminusone = mMax;
Real h;
unsigned int j = 0;
Real * const ogre_restrict heightField = mHeightData;
for ( unsigned int src_pos = 0; src_pos < maxminusone; src_pos += bpp )
{
switch ( bpp )
{
case 1:
h = imagedata[src_pos] * scale;
break;
case 2:
case 3:
case 4:
{
#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
ushort val = imagedata[src_pos] << 8;
val += imagedata[src_pos + 1];
#else
ushort val = imagedata[src_pos];
val += imagedata[src_pos + 1] << 8;
#endif
h = val * scale;
}
break;
default:
assert( 0 );
OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS,
"unrecongnized bpp image.",
"PagingLandScapeData2D_HeightField::_load" );
break;
}
mMaxheight = std::max ( h, mMaxheight );
heightField[j++] = h;
}
return true;
}
//-----------------------------------------------------------------------
401 void PagingLandScapeData2D_HeightField::_load( )
{
mImage = new Image( );
mImage->load ( mParent->getOptions( )->LandScape_filename +
"." + mParent->getOptions( )->LandScape_extension, mParent->getOptions( )->groupName );
mBpp = PixelUtil::getNumElemBytes ( mImage->getFormat ( ) );
mXDimension = mImage->getWidth( );
mZDimension = mImage->getHeight( );
const size_t sourceHeight = mZDimension;
const size_t sourceWidth = mXDimension;
computePowerof2PlusOneSize ( );
mSize = mXDimension;
mMaxArrayPos = static_cast <unsigned int> ( mXDimension * mZDimension );
mMax = static_cast <unsigned int> ( mMaxArrayPos * mBpp );
mHeightData = new Real[mMaxArrayPos];
const unsigned int bpp = static_cast <unsigned int> ( mBpp );
const Real scale = getScale( );
mMaxheight = 0.0f;
const uchar * ogre_restrict imagedata = mImage->getData( );
const unsigned int maxminusone = mMax;
const unsigned int shift_fill = static_cast <unsigned int> ( mXDimension - sourceWidth );
Real h;
unsigned int dest_pos = 0;
unsigned int src_pos = 0;
Real * const ogre_restrict heightField = mHeightData;
for ( unsigned int i = 0; i < sourceHeight; ++i )
{
for ( unsigned int j = 0; j < sourceWidth; ++j )
{
switch ( bpp )
{
case 1:
h = imagedata[src_pos] * scale;
break;
case 2:
case 3:
case 4:
{
#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
ushort val = imagedata[src_pos] << 8;
val += imagedata[src_pos + 1];
#else
ushort val = imagedata[src_pos];
val += imagedata[src_pos + 1] << 8;
#endif
h = val * scale;
}
break;
default:
assert( 0 );
OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS,
"unrecongnized bpp image.",
"PagingLandScapeData2D_HeightField::_load" );
break;
}
//DEBUG_OUTPUT ( " Bpp " << StringConverter::toString ( h ) << "\n";
mMaxheight = std::max ( h, mMaxheight );
heightField[dest_pos++] = h;
src_pos += bpp;
}
memset ( &heightField[dest_pos], 0, shift_fill );
dest_pos += shift_fill;
}
}
//-----------------------------------------------------------------------
474 void PagingLandScapeData2D_HeightField::_unload( )
{
delete mImage;
mImage = 0;
delete mCoverage;
mCoverage = 0;
delete mBase;
mBase = 0;
delete mShadow;
mShadow = 0;
}
} //namespace
1 /***************************************************************************
OgrePagingLandScapeData2D_HeightFieldBlendNeighbor.cpp - description
-------------------
begin : Mon Oct 13 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreLogManager.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreImage.h"
#include "OgreStringConverter.h"
#include "OgreResourceManager.h"
#include "OgreException.h"
#include "OgrePagingLandScapeData2D.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeData2D_HeightFieldBlendNeighbor.h"
#include "fileutils.h"
namespace Ogre
{
//-----------------------------------------------------------------------
44 PagingLandScapeData2D* PagingLandScapeData2D_HeightFieldBlendNeighbor::newPage( )
{
return new PagingLandScapeData2D_HeightFieldBlendNeighbor( mParent );
}
//-----------------------------------------------------------------------
49 PagingLandScapeData2D_HeightFieldBlendNeighbor::PagingLandScapeData2D_HeightFieldBlendNeighbor( PagingLandScapeData2DManager *dataMgr )
: PagingLandScapeData2D( dataMgr )
{
mShadow = 0;
mMaxheight = mParent->getOptions( )->scale.y;
}
//-------------------------------------------------------------------
57 const Real PagingLandScapeData2D_HeightFieldBlendNeighbor::getMaxAbsoluteHeight( void ) const
{
return mParent->getOptions( )->scale.y;
}
//-----------------------------------------------------------------------
62 PagingLandScapeData2D_HeightFieldBlendNeighbor::~PagingLandScapeData2D_HeightFieldBlendNeighbor( )
{
PagingLandScapeData2D::unload ( );
}
//-----------------------------------------------------------------------
68 const Real PagingLandScapeData2D_HeightFieldBlendNeighbor::getShadow ( const Real mX, const Real mZ,
69 const bool &positive )
{
if ( mShadow )
{
unsigned int Pos = static_cast<unsigned int> ( ( mZ * mShadow->getWidth( ) + mX ) * 3 );//3 bytes ( mImage is RGBA )
if ( mShadow->getSize ( ) > Pos )
{
if ( positive )
return static_cast<Real> ( mShadow->getData( )[ Pos + 0] ) / 255;
else
return static_cast<Real> ( mShadow->getData( )[ Pos + 1] ) / 255;
}
else
{
return 0.0f;
}
}
else
{
return 0.0f;
}
}
//-----------------------------------------------------------------------
92 void PagingLandScapeData2D_HeightFieldBlendNeighbor::_save( )
{
// Disabled for now
return;
uchar *data = new uchar[ mXDimension * mZDimension * 2 ];
const double divider = 65535.0 / mParent->getOptions( )->scale.y;
unsigned int j = 0;
for ( unsigned int i = 0; i < mMaxArrayPos; i++ )
{
const ushort syn = ushort ( mHeightData[i] * divider );
#if OGRE_ENDIAN == ENDIAN_BIG
data[j] = uchar ( ( syn >> 8 ) & 0xff );
data[j+ 1] = uchar ( syn & 0xff );
#else
data[j] = uchar ( syn & 0xff );
data[j+ 1] = uchar ( ( syn >> 8 ) & 0xff );
#endif
j += 2;
}
const String fname = mParent->getOptions( )->LandScape_filename + "." +
StringConverter::toString( mPageZ ) + "." +
StringConverter::toString( mPageX ) + ".";
const String extname = mParent->getOptions( )->LandScape_extension;
FileInfoListPtr finfo = ResourceGroupManager::getSingleton( ).findResourceFileInfo (
mParent->getOptions( )->groupName,
fname + extname );
FileInfoList::iterator it = finfo->begin( );
if ( it != finfo->end( ) )
{
//FileInfo *inf = &( *it );
char *olddir = ChangeToDir ( const_cast< char * > ( ( ( it )->archive->getName( ) ).c_str( ) ) );
//FileSystemArchive::pushDirectory( )
std::ofstream outfile;
String FileNameRaw;
DataStreamPtr image_chunk( new MemoryDataStream ( ( void* )data,
mXDimension * mZDimension * 2 * sizeof ( uchar ),
true ) );
outfile.open ( const_cast< char * > ( ( fname + "modif." + extname ).c_str( ) ),
std::ios::binary );
// Write out
outfile << image_chunk->getAsString ( );
outfile.close ( );
//FileSystemArchive::pushDirectory( );
RetablishDir ( olddir );
}
}
//-----------------------------------------------------------------------
149 bool PagingLandScapeData2D_HeightFieldBlendNeighbor::_load( const unsigned int mX, const unsigned int mZ )
{
const PagingLandScapeOptions *Options = mParent->getOptions( );
const String fileName = Options->LandScape_filename;
const String ext = Options->LandScape_extension;
const String extModif = "modif." + ext;
const String pageExtZ = "." + StringConverter::toString( mZ ) + ".";
const String pageExtX = StringConverter::toString( mX ) + ".";
const String pageExtZone = "." + StringConverter::toString( mZ + 1 ) + ".";
const String pageExtXone = StringConverter::toString( mX + 1 ) + ".";
// Load data
const String strFileName = fileName + pageExtZ + pageExtX;
const String strRightName = fileName + pageExtZ + pageExtXone;
const String strBottomName = fileName + pageExtZone + pageExtX;
const String strBRName = fileName + pageExtZone + pageExtXone;
Image *tex = new Image( );
Image *t_right = new Image( );
Image *t_bottom = new Image( );
Image *t_br = new Image( );
if ( Options->Deformable &&
ResourceGroupManager::getSingleton( ).resourceExists( Options->groupName, strFileName + extModif ) )
{
tex->load ( strFileName + extModif, Options->groupName );
if ( tex->getData( ) == 0 )
{
LogManager::getSingleton( ).logMessage( LML_CRITICAL, String( "PLSM2 : Cannot find map named " ) + strFileName + extModif );
delete tex;
delete t_right;
delete t_bottom;
delete t_br;
return false;
}
if ( ResourceGroupManager::getSingleton( ).resourceExists( Options->groupName, strRightName + extModif ) )
t_right->load ( strRightName + extModif, Options->groupName );
if ( ResourceGroupManager::getSingleton( ).resourceExists( Options->groupName, strBottomName + extModif ) )
t_bottom ->load ( strBottomName + extModif, Options->groupName );
if ( ResourceGroupManager::getSingleton( ).resourceExists( Options->groupName, strBRName + extModif ) )
t_br->load ( strBRName + extModif, Options->groupName );
}
else
{
tex->load ( strFileName + ext, Options->groupName );
if ( tex->getData( ) == 0 )
{
LogManager::getSingleton( ).logMessage( LML_CRITICAL, String( "PLSM2 : Cannot find map named " ) + strFileName + ext );
delete tex;
delete t_right;
delete t_bottom;
delete t_br;
return false;
}
if ( ResourceGroupManager::getSingleton( ).resourceExists( Options->groupName, strRightName + extModif ) )
t_right->load ( strRightName + ext, Options->groupName );
if ( ResourceGroupManager::getSingleton( ).resourceExists( Options->groupName, strBottomName + extModif ) )
t_bottom ->load ( strBottomName + ext, Options->groupName );
if ( ResourceGroupManager::getSingleton( ).resourceExists( Options->groupName, strBRName + extModif ) )
t_br->load ( strBRName + ext, Options->groupName );
}
//DataStreamPtr RawData;
//RawData = ResourceGroupManager::getSingleton( ).openResource( finalName,
//mParent->getOptions( )->groupName );
// Validate size
// Image size comes from setting ( since RAW is not self-describing )
// here 16 bits Raw file
mXDimension = mSize;
mZDimension = mXDimension;
mBpp = ( unsigned int )PixelUtil::getNumElemBytes ( tex->getFormat ( ) );;
mMaxArrayPos = static_cast <unsigned int> ( mSize * mSize );
const size_t numBytes = mMaxArrayPos * mBpp;
if ( tex->getWidth( ) != tex->getHeight( ) ||
tex->getWidth( ) != mSize - 1 )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
"Texture size ( " + StringConverter::toString( static_cast<unsigned int> ( tex->getSize( ) ) ) +
" ) does not agree with configuration settings.",
"PagingLandScapeData2D_HeightFieldBlendNeighbor::_load" );
}
uchar *pSrc = tex->getData( );
uchar *pRight = t_right->getData( );
uchar *pBottom = t_bottom->getData( );
uchar *pBr = t_br->getData( );
mMax = static_cast<unsigned int> ( numBytes ) + 1;
mHeightData = new Real[mMaxArrayPos];
const double scale = ( 1.0 / 255 ) * Options->scale.y;
mMaxheight = 0.0f;
unsigned int j = 0;
for ( unsigned int y = 0; y < tex->getHeight( ); y++ )
{
for ( unsigned int x = 0; x < tex->getWidth( ); x++ )
{
const uchar val = pSrc[ y * ( mSize-1 ) + x];
const Real h = val * scale;
mMaxheight = std::max ( h, mMaxheight );
mHeightData[j++] = h;
}
// grab the Right Column
if ( t_right->getData( ) == 0 )
{
// Copy the pixel if we have no right border
const uchar val = pSrc[ y * ( mSize-1 ) + ( mSize-2 )];
const Real h = val * scale;
mMaxheight = std::max ( h, mMaxheight );
mHeightData[j++] = h;
}
else
{
// Copy the right border
const uchar val = pRight[ y * ( mSize-1 )];
const Real h = val * scale;
mMaxheight = std::max ( h, mMaxheight );
mHeightData[j++] = h;
}
}
// Generate the bottom row
for ( unsigned int x = 0; x < tex->getWidth( ); x++ )
{
if ( t_bottom->getData( ) == 0 )
{
const uchar val = pSrc[ ( mSize-2 ) * ( mSize-1 ) + x];
const Real h = val * scale;
mMaxheight = std::max ( h, mMaxheight );
mHeightData[j++] = h;
} else
{
const uchar val = pBottom[ x];
const Real h = val * scale;
mMaxheight = std::max ( h, mMaxheight );
mHeightData[j++] = h;
}
}
// Corner Pixel
if ( t_br->getData( ) == 0 )
{
const uchar val = pSrc[ ( mSize-2 ) * ( mSize-1 ) + ( mSize-2 )];
const Real h = val * scale;
mMaxheight = std::max ( h, mMaxheight );
mHeightData[j++] = h;
}
else
{
const uchar val = pBr[0];
const Real h = val * scale;
mMaxheight = std::max ( h, mMaxheight );
mHeightData[j++] = h;
}
delete tex;
delete t_right;
delete t_bottom;
delete t_br;
if ( Options->vertex_shadowed )
{
mShadow = new Image( );
mShadow->load( fileName + ".HS" + pageExtZ + pageExtX + "png",
Options->groupName );
//mParent->getOptions( )->LandScape_extension );
}
return true;
}
//-----------------------------------------------------------------------
344 void PagingLandScapeData2D_HeightFieldBlendNeighbor::_load( )
{
// Load data
DataStreamPtr RawData = ResourceGroupManager::getSingleton( ).openResource( mParent->getOptions( )->LandScape_filename +
"." +
mParent->getOptions( )->LandScape_extension,
mParent->getOptions( )->groupName );
// Validate size
// Image size comes from setting ( since RAW is not self-describing )
// here 16 bits Raw file
mXDimension = mParent->getOptions( )->RawWidth;
mZDimension = mParent->getOptions( )->RawHeight;
mBpp = 2;
const size_t sourceHeight = mZDimension;
const size_t sourceWidth = mXDimension;
computePowerof2PlusOneSize ( );
mSize = mXDimension;
if ( RawData->size( ) != sourceHeight*sourceWidth*2 )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
"RAW size ( " + StringConverter::toString( static_cast<unsigned int> ( RawData->size( ) ) ) +
" ) does not agree with configuration settings.",
"PagingLandScapeData2D_HeightFieldBlendNeighbor::_load" );
}
mMaxArrayPos = static_cast <unsigned int> ( mXDimension * mZDimension );
const size_t numBytes = mMaxArrayPos * mBpp;
mMax = static_cast<unsigned int> ( numBytes ) + 1;
mHeightData = new Real[mMaxArrayPos];
const double scale = ( 1.0f / 65535.0f ) * mParent->getOptions( )->scale.y;
mMaxheight = 0.0f;
MemoryDataStream dc( RawData,
true );
const uchar *pSrc = dc.getPtr ( );
const unsigned int shift_fill = static_cast <unsigned int> ( mXDimension - sourceWidth );
unsigned int dest_pos = 0;
//for some reason water is 65035 in SRTM files...
const bool srtm_water = mParent->getOptions( )->SRTM_water;
for ( unsigned int i = 0; i < sourceHeight; ++i )
{
for ( unsigned int j = 0; j < sourceWidth; ++j )
{
#if OGRE_ENDIAN == ENDIAN_BIG
ushort val = *pSrc++ <<8;
val += *pSrc++;
#else
ushort val = *pSrc++;
val += *pSrc++ <<8;
#endif
if ( srtm_water && ( val - 65035 ) > 0 )
val = 0;
const Real h = val * scale;
mMaxheight = std::max ( h, mMaxheight );
mHeightData[dest_pos++] = h;
}
memset ( &mHeightData[dest_pos], 0, shift_fill );
dest_pos+= shift_fill;
}
}
//-----------------------------------------------------------------------
416 void PagingLandScapeData2D_HeightFieldBlendNeighbor::_unload( )
{
delete mShadow;
mShadow = 0;
}
} //namespace
1 /***************************************************************************
OgrePagingLandScapeData2D_HeightFieldN.cpp - description
-------------------
begin : Mon Oct 13 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreLogManager.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreImage.h"
#include "OgreImageCodec.h"
#include "OgreArchiveManager.h"
#include "OgreStringConverter.h"
#include "OgreException.h"
#include "OgrePagingLandScapeData2D.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeData2D_HeightFieldN.h"
#include "fileutils.h"
namespace Ogre
{
//-----------------------------------------------------------------------
45 PagingLandScapeData2D* PagingLandScapeData2D_HeightFieldN::newPage( )
{
return new PagingLandScapeData2D_HeightFieldN( mParent );
}
//-----------------------------------------------------------------------
50 PagingLandScapeData2D_HeightFieldN::PagingLandScapeData2D_HeightFieldN( PagingLandScapeData2DManager *dataMgr )
: PagingLandScapeData2D( dataMgr )
{
mImage = 0;
mCoverage = 0;
mBase = 0;
mShadow = 0;
mMaxheight = mParent->getOptions( )->scale.y;
}
//-----------------------------------------------------------------------
61 PagingLandScapeData2D_HeightFieldN::~PagingLandScapeData2D_HeightFieldN( )
{
PagingLandScapeData2D::unload ( );
}
//-------------------------------------------------------------------
67 const Real PagingLandScapeData2D_HeightFieldN::getMaxAbsoluteHeight( void ) const
{
return mParent->getOptions( )->scale.y;
}
//-----------------------------------------------------------------------
72 const ColourValue PagingLandScapeData2D_HeightFieldN::getBase ( const Real mX, const Real mZ )
{
if ( mBase != 0 )
{
unsigned int Pos = static_cast<unsigned int> ( ( mZ * mBase->getWidth( ) + mX ) * 4 );//4 bytes ( mImage is RGBA )
if ( mBase->getSize ( ) > Pos )
{
const Real divider = 1.0f / 255;
return ColourValue( ( Real ) mBase->getData( )[ Pos + 0] * divider,
( Real ) mBase->getData( )[ Pos + 1] * divider,
( Real ) mBase->getData( )[ Pos + 2] * divider,
( Real ) mBase->getData( )[ Pos + 3] * divider );
}
else
{
return ColourValue::White;
}
}
else
{
return ColourValue::White;
}
}
//-----------------------------------------------------------------------
97 const ColourValue PagingLandScapeData2D_HeightFieldN::getCoverage ( const Real mX, const Real mZ )
{
if ( mCoverage != 0 )
{
unsigned int Pos = static_cast<unsigned int> ( ( mZ * mCoverage->getWidth( ) + mX ) * 4 );//4 bytes ( mImage is RGBA )
if ( mCoverage->getSize ( ) > Pos )
{
const Real divider = 1.0f / 255;
return ColourValue( ( Real ) mCoverage->getData( )[ Pos + 0] * divider,
( Real ) mCoverage->getData( )[ Pos + 1] * divider,
( Real ) mCoverage->getData( )[ Pos + 2] * divider,
( Real ) mCoverage->getData( )[ Pos + 3] * divider );
}
else
{
return ColourValue::White;
}
}
else
{
return ColourValue::White;
}
}
//-----------------------------------------------------------------------
122 const Real PagingLandScapeData2D_HeightFieldN::getShadow ( const Real mX, const Real mZ,
123 const bool &positive )
{
if ( mShadow != 0 )
{
unsigned int Pos = static_cast<unsigned int> ( ( mZ * mShadow->getWidth( ) + mX ) * 3 );//3 bytes ( mImage is RGBA )
if ( mShadow->getSize ( ) > Pos )
{
if ( positive )
return static_cast<Real> ( mShadow->getData( )[ Pos + 0] ) / 255;
else
return static_cast<Real> ( mShadow->getData( )[ Pos + 1] ) / 255;
}
else
{
return 0.0f;
}
}
else
{
return 0.0f;
}
}
//-----------------------------------------------------------------------
147 const Vector3 PagingLandScapeData2D_HeightFieldN::getNormal ( const Real x, const Real z )
{
#ifndef _LOADEDNORM
return PagingLandScapeData2D::getNormal( x, z );
#else
if ( mImage )
{
unsigned int Pos = static_cast<unsigned int> ( ( z * mSize + x ) * mBpp );//4 bytes ( mImage is RGBA )
if ( mMax > Pos )
{
const Real normalscale = 1.0f / 127.0f;
return Vector3 ( ( ( Real )( mImage->getData( )[Pos + 0] ) - 128.0f ) * normalscale,
( ( Real )( mImage->getData( )[Pos + 1] ) - 128.0f ) * normalscale,
( ( Real )( mImage->getData( )[Pos + 2] ) - 128.0f ) * normalscale );
}
else
{
return Vector3::UNIT_Y;
}
}
else
{
return Vector3::UNIT_Y;
}
#endif //_NOLOAD
}
//-----------------------------------------------------------------------
175 void PagingLandScapeData2D_HeightFieldN::_save( )
{
const Real scale = 256.0 / mParent->getOptions( )->scale.y;
uchar *img = mImage->getData( );
unsigned int j = 0;
const unsigned int bpp = static_cast <unsigned int> ( mBpp );
for ( unsigned int i = 0; i < mMax - 1; i += bpp )
{
img[ i + ( mBpp - 1 )] = uchar ( mHeightData[j++] * scale );
}
const String fname = mParent->getOptions( )->LandScape_filename + ".HN." +
StringConverter::toString( mPageZ ) + "." +
StringConverter::toString( mPageX ) + ".";
const String extname = mParent->getOptions( )->LandScape_extension;
FileInfoListPtr finfo = ResourceGroupManager::getSingleton( ).findResourceFileInfo (
mParent->getOptions( )->groupName,
fname + extname );
FileInfoList::iterator it = finfo->begin( );
if ( it != finfo->end( ) )
{
//FileInfo *inf = &( *it );
char *olddir = ChangeToDir ( const_cast< char * > ( ( ( it )->archive->getName( ) ).c_str( ) ) );
//FileSystemArchive::pushDirectory( )
mImage->save ( fname + "modif." + extname );
//FileSystemArchive::pushDirectory( );
RetablishDir ( olddir );
}
}
//-----------------------------------------------------------------------
207 bool PagingLandScapeData2D_HeightFieldN::_load( const unsigned int mX, const unsigned int mZ )
{
const String strFileName = mParent->getOptions( )->LandScape_filename + ".HN." +
StringConverter::toString( mZ ) + "." +
StringConverter::toString( mX ) + ".";
String finalName = strFileName +
"modif." +
mParent->getOptions( )->LandScape_extension;
if ( !( mParent->getOptions( )->Deformable &&
ResourceGroupManager::getSingleton( ).resourceExists( mParent->getOptions( )->groupName,
finalName ) ) )
{
finalName = strFileName +
mParent->getOptions( )->LandScape_extension;
if ( !ResourceGroupManager::getSingleton( ).resourceExists( mParent->getOptions( )->groupName,
finalName ) )
{
LogManager::getSingleton( ).logMessage( LML_CRITICAL, String( "PLSM2 : Cannot find map named " ) + finalName );
return false;
}
}
mImage = new Image( );
mImage->load ( finalName, mParent->getOptions( )->groupName );
//check to make sure it's 2^n + 1 size.
if ( mImage->getWidth( ) != mImage->getHeight( ) || !_checkSize( mImage->getWidth( ) ) )
{
String err = "Error: Invalid heightmap size : " +
StringConverter::toString( static_cast <unsigned int> ( mImage->getWidth( ) ) ) +
", " + StringConverter::toString( static_cast <unsigned int> ( mImage->getHeight( ) ) ) +
". Should be 2^n+1, 2^n+1";
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, err, "PagingLandScapeData2D_HeightFieldN::_load" );
}
mBpp = PixelUtil::getNumElemBytes ( mImage->getFormat ( ) );
if ( mBpp != 4 )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, "Error: Image is not a RGBA image.( 4 bytes, 32 bits )",
"PagingLandScapeData2D_HeightFieldN::_load" );
}
if ( mSize != mImage->getWidth( ) )
{
OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS, "Error: Declared World size <> Height Map Size.", "PagingLandScapeData2D_HeightFieldN::_load" );
}
mMax = static_cast <unsigned int> ( mSize * mImage->getHeight( ) * mBpp + 1 );
if ( mParent->getOptions( )->coverage_vertex_color )
{
mCoverage = new Image( );
mCoverage->load( mParent->getOptions( )->LandScape_filename +
".Coverage." +
StringConverter::toString( mZ ) + "." +
StringConverter::toString( mX ) + "." +
mParent->getOptions( )->LandScape_extension, mParent->getOptions( )->groupName );
}
if ( mParent->getOptions( )->base_vertex_color )
{
mBase = new Image( );
mBase->load( mParent->getOptions( )->LandScape_filename +
".Base." +
StringConverter::toString( mZ ) + "." +
StringConverter::toString( mX ) + "." +
mParent->getOptions( )->LandScape_extension, mParent->getOptions( )->groupName );
}
if ( mParent->getOptions( )->vertex_shadowed )
{
mShadow = new Image( );
mShadow->load( mParent->getOptions( )->LandScape_filename +
".HS." +
StringConverter::toString( mZ ) + "." +
StringConverter::toString( mX ) + "." +
mParent->getOptions( )->LandScape_extension, mParent->getOptions( )->groupName );
}
mXDimension = mImage->getWidth( );
mZDimension = mImage->getHeight( );
mMaxArrayPos = static_cast <unsigned int> ( mSize * mImage->getHeight( ) );
mHeightData = new Real[mMaxArrayPos];
unsigned int j = 0;
const double scale = mParent->getOptions( )->scale.y / 256;
mMaxheight = 0.0f;
uchar *imagedata = mImage->getData( );
const unsigned int bpp = static_cast <unsigned int> ( mBpp );
for ( unsigned int i = 0; i < mMax - 1; i += bpp )
{
const Real h = imagedata[ i + ( bpp - 1 )] * scale;
mMaxheight = std::max ( h, mMaxheight );
mHeightData[j++] = h;
}
return true;
}
//-----------------------------------------------------------------------
306 void PagingLandScapeData2D_HeightFieldN::_load( )
{
mImage = new Image( );
mImage->load ( mParent->getOptions( )->LandScape_filename +
"." + mParent->getOptions( )->LandScape_extension, mParent->getOptions( )->groupName );
//check to make sure it's 2^n size.
if ( !_checkSize( mImage->getHeight( ) ) || !_checkSize( mImage->getWidth( ) ) )
{
String err = "Error: Invalid heightmap size : " +
StringConverter::toString( static_cast <unsigned int> ( mImage->getWidth( ) ) ) +
", " + StringConverter::toString( static_cast <unsigned int> ( mImage->getHeight( ) ) ) +
". Should be 2^n";
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, err, "PagingLandScapeData2D_HeightFieldN::_load" );
}
mBpp = static_cast <unsigned int> ( PixelUtil::getNumElemBytes ( mImage->getFormat ( ) ) );
if ( mBpp != 1 )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, "Error: Image is not a greyscale image.( 1 byte, 8 bits )",
"PagingLandScapeData2D_HeightFieldN::_load" );
}
mXDimension = mImage->getWidth( );
mZDimension = mImage->getHeight( );
mSize = mImage->getWidth( );
mMax = static_cast <unsigned int> ( mSize * mImage->getHeight( ) * mBpp );
mMaxArrayPos = static_cast <unsigned int> ( mSize * mImage->getHeight( ) );
mHeightData = new Real[mMaxArrayPos];
const double scale = mParent->getOptions( )->scale.y / 256;
mMaxheight = 0.0f;
uchar *imagedata = mImage->getData( );
for ( unsigned int i = 0; i < mMax; i ++ )
{
const Real h = imagedata[i] * scale;
mMaxheight = std::max ( h, mMaxheight );
mHeightData[i] = h;
}
}
//-----------------------------------------------------------------------
353 void PagingLandScapeData2D_HeightFieldN::_unload( )
{
delete mImage;
mImage = 0;
delete mCoverage;
mCoverage = 0;
delete mBase;
mBase = 0;
delete mShadow;
mShadow = 0;
}
} //namespace
1 /***************************************************************************
OgrePagingLandScapeData2D_HeightFieldNTC.cpp - description
-------------------
begin : Mon Oct 13 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreLogManager.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreImage.h"
#include "OgreStringConverter.h"
#include "OgreException.h"
#include "OgrePagingLandScapeData2D.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeData2D_HeightFieldNTC.h"
#include "fileutils.h"
namespace Ogre
{
//-----------------------------------------------------------------------
43 PagingLandScapeData2D* PagingLandScapeData2D_HeightFieldNTC::newPage( )
{
return new PagingLandScapeData2D_HeightFieldNTC( mParent );
}
//-----------------------------------------------------------------------
48 PagingLandScapeData2D_HeightFieldNTC::PagingLandScapeData2D_HeightFieldNTC( PagingLandScapeData2DManager *dataMgr )
: PagingLandScapeData2D( dataMgr )
{
mImage = 0;
input_max = 3000.0f;
input_min = 0.0f;
mMaxheight = _decodeTC ( 1.0f ) * mParent->getOptions( )->scale.y;
}
//-------------------------------------------------------------------
58 const Real PagingLandScapeData2D_HeightFieldNTC::getMaxAbsoluteHeight( void ) const
{
return _decodeTC ( 1.0f ) * mParent->getOptions( )->scale.y;
}
//-----------------------------------------------------------------------
63 PagingLandScapeData2D_HeightFieldNTC::~PagingLandScapeData2D_HeightFieldNTC( )
{
}
//-----------------------------------------------------------------------
67 const ColourValue PagingLandScapeData2D_HeightFieldNTC::getBase ( const Real mX, const Real mZ )
{
return ColourValue::White;
}
//-----------------------------------------------------------------------
73 const ColourValue PagingLandScapeData2D_HeightFieldNTC::getCoverage ( const Real mX, const Real mZ )
{
return ColourValue::White;
}
//-----------------------------------------------------------------------
78 const Vector3 PagingLandScapeData2D_HeightFieldNTC::getNormalAt ( const Real x, const Real z )
{
#ifndef _LOADEDNORM
return PagingLandScapeData2D::getNormal( x, z );
#else
if ( mImage )
{
unsigned int Pos = static_cast<unsigned int> ( ( z * mSize + x ) * mBpp );//4 bytes ( mImage is RGBA )
if ( mMax > Pos )
{
const Real normalscale = 1.0f / 127.0f;
return Vector3 ( ( ( Real )( mImage->getData( )[Pos + 0] ) - 128.0f ) * normalscale,
( ( Real )( mImage->getData( )[Pos + 1] ) - 128.0f ) * normalscale,
( ( Real )( mImage->getData( )[Pos + 2] ) - 128.0f ) * normalscale );
}
else
{
return Vector3::UNIT_Y;
}
}
else
{
return Vector3::UNIT_Y;
}
#endif //_NOLOAD
}
//-----------------------------------------------------------------------
107 void PagingLandScapeData2D_HeightFieldNTC::_save( )
{
const Real scale = 1.0f / mParent->getOptions( )->scale.y;
uchar *img = mImage->getData( );
unsigned int j = 0;
const unsigned int bpp = static_cast <unsigned int> ( mBpp );
for ( unsigned int i = 0; i < mMax - 1; i += bpp )
{
img[ i + ( mBpp - 1 )] = uchar ( _encodeTC( mHeightData[j++] ) * scale );
}
const String fname = mParent->getOptions( )->LandScape_filename + ".HN." +
StringConverter::toString( mPageZ ) + "." +
StringConverter::toString( mPageX ) + ".";
const String extname = mParent->getOptions( )->LandScape_extension;
FileInfoListPtr finfo = ResourceGroupManager::getSingleton( ).findResourceFileInfo (
mParent->getOptions( )->groupName,
fname + extname );
FileInfoList::iterator it = finfo->begin( );
if ( it != finfo->end( ) )
{
//FileInfo *inf = &( *it );
char *olddir = ChangeToDir ( const_cast< char * > ( ( ( it )->archive->getName( ) ).c_str( ) ) );
//FileSystemArchive::pushDirectory( )
mImage->save ( fname + "modif." + extname );
//FileSystemArchive::pushDirectory( );
RetablishDir ( olddir );
}
}
//-----------------------------------------------------------------------
141 bool PagingLandScapeData2D_HeightFieldNTC::_load( const unsigned int mX, const unsigned int mZ )
{
const String strFileName = mParent->getOptions( )->LandScape_filename + ".HN." +
StringConverter::toString( mZ ) + "." +
StringConverter::toString( mX ) + ".";
String finalName = strFileName +
"modif." +
mParent->getOptions( )->LandScape_extension;
if ( !( mParent->getOptions( )->Deformable &&
ResourceGroupManager::getSingleton( ).resourceExists( mParent->getOptions( )->groupName,
finalName ) ) )
{
finalName = strFileName +
mParent->getOptions( )->LandScape_extension;
if ( !ResourceGroupManager::getSingleton( ).resourceExists( mParent->getOptions( )->groupName,
finalName ) )
{
LogManager::getSingleton( ).logMessage( LML_CRITICAL, String( "PLSM2 : Cannot find map named " ) + finalName );
return false;
}
}
mImage = new Image( );
mImage->load ( finalName, mParent->getOptions( )->groupName );
//check to make sure it's 2^n + 1 size.
if ( mImage->getWidth( ) != mImage->getHeight( ) || !_checkSize( mImage->getWidth( ) ) )
{
String err = "Error: Invalid heightmap size : " +
StringConverter::toString( static_cast <unsigned int> ( mImage->getWidth( ) ) ) +
", " + StringConverter::toString( static_cast <unsigned int> ( mImage->getHeight( ) ) ) +
". Should be 2^n+1, 2^n+1";
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, err, "PagingLandScapeData2D_HeightField::_load" );
}
mBpp = PixelUtil::getNumElemBytes ( mImage->getFormat ( ) );
if ( mBpp != 4 )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, "Error: Image is not a RGBA image.( 4 bytes, 32 bits )",
"PagingLandScapeData2D_HeightField::_load" );
}
if ( mSize != mImage->getWidth( ) )
{
OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS, "Error: Declared World size <> Height Map Size.", "PagingLandScapeData2D_HeightField::_load" );
}
mXDimension = mImage->getWidth( );
mZDimension = mImage->getHeight( );
mMax = static_cast <unsigned int> ( mSize * mImage->getHeight( ) * mBpp + 1 );
mMaxArrayPos = static_cast <unsigned int> ( mSize * mImage->getHeight( ) );
mHeightData = new Real[mMaxArrayPos];
unsigned int j = 0;
const double divider = 1.0 / 255;
const Real scale = mParent->getOptions( )->scale.y;
uchar *data = mImage->getData( );
mMaxheight = 0.0f;
const unsigned int bpp = static_cast <unsigned int> ( mBpp );
for ( unsigned int i = 0; i < mMax - 1; i += bpp )
{
const Real h = _decodeTC( data[ i + ( mBpp - 1 )] * divider )* scale;
mMaxheight = std::max ( h, mMaxheight );
mHeightData[j++] = h;
}
return true;
}
//-----------------------------------------------------------------------
209 void PagingLandScapeData2D_HeightFieldNTC::_load( )
{
mImage = new Image( );
mImage->load( mParent->getOptions( )->LandScape_filename +
"." + mParent->getOptions( )->LandScape_extension,
mParent->getOptions( )->groupName );
//check to make sure it's 2^n size.
if ( !_checkSize( mImage->getHeight( ) ) || !_checkSize( mImage->getWidth( ) ) )
{
String err = "Error: Invalid heightmap size : " +
StringConverter::toString( static_cast <unsigned int> ( mImage->getWidth( ) ) ) +
", " + StringConverter::toString( static_cast <unsigned int> ( mImage->getHeight( ) ) ) +
". Should be 2^n, 2^n";
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, err, "PagingLandScapeData2D_HeightFieldNTC::_load" );
}
mBpp = PixelUtil::getNumElemBytes ( mImage->getFormat ( ) );
if ( mBpp != 1 )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, "Error: Image is not a grayscale image.( 1 byte, 8 bits )",
"PagingLandScapeData2D_HeightFieldNTC::_load" );
}
mSize = static_cast <unsigned int> ( mImage->getWidth( ) );
mMax = static_cast <unsigned int> ( mSize * mImage->getHeight( ) * mBpp + 1 );
mMaxArrayPos = static_cast <unsigned int> ( mSize * mImage->getHeight( ) );
mHeightData = new Real[mMaxArrayPos];
unsigned int j = 0;
const double divider = 1.0 / 255;
const Real scale = mParent->getOptions( )->scale.y;
uchar *data = mImage->getData( );
mMaxheight = 0.0f;
const unsigned int bpp = static_cast <unsigned int> ( mBpp );
for ( unsigned int i = 0; i < mMax - 1; i += bpp )
{
const Real h = _decodeTC( data[ i + ( mBpp - 1 )] * divider )* scale;
mMaxheight = std::max ( h, mMaxheight );
mHeightData[j++] = h;
}
}
//-----------------------------------------------------------------------
257 void PagingLandScapeData2D_HeightFieldNTC::_unload( )
{
delete mImage;
mImage = 0;
}
//-----------------------------------------------------------------------
264 inline Real PagingLandScapeData2D_HeightFieldNTC::_decodeTC( const Real encoded ) const
{
return ( ( Real ) ( encoded + 0.5f ) ) * ( input_max - input_min ) + input_min;
}
//-----------------------------------------------------------------------
270 inline uchar PagingLandScapeData2D_HeightFieldNTC::_encodeTC( const Real decoded ) const
{
return static_cast<uchar> ( ( decoded - input_min ) / ( input_max - input_min ) - 0.5f );
}
} //namespace
1 /***************************************************************************
OgrePagingLandScapeData2D_HeightFieldRaw.cpp - description
-------------------
begin : Mon Oct 13 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreLogManager.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreImage.h"
#include "OgreStringConverter.h"
#include "OgreResourceManager.h"
#include "OgreException.h"
#include "OgrePagingLandScapeData2D.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeData2D_HeightFieldRaw.h"
#include "fileutils.h"
namespace Ogre
{
//-----------------------------------------------------------------------
44 PagingLandScapeData2D* PagingLandScapeData2D_HeightFieldRaw::newPage( )
{
return new PagingLandScapeData2D_HeightFieldRaw( mParent );
}
//-----------------------------------------------------------------------
49 PagingLandScapeData2D_HeightFieldRaw::PagingLandScapeData2D_HeightFieldRaw( PagingLandScapeData2DManager *dataMgr )
: PagingLandScapeData2D( dataMgr )
{
mShadow = 0;
mMaxheight = mParent->getOptions( )->scale.y;
}
//-------------------------------------------------------------------
56 const Real PagingLandScapeData2D_HeightFieldRaw::getMaxAbsoluteHeight( void ) const
{
return mParent->getOptions( )->scale.y;
}
//-----------------------------------------------------------------------
61 PagingLandScapeData2D_HeightFieldRaw::~PagingLandScapeData2D_HeightFieldRaw( )
{
}
//-----------------------------------------------------------------------
66 const Real PagingLandScapeData2D_HeightFieldRaw::getShadow ( const Real mX, const Real mZ,
67 const bool &positive )
{
if ( mShadow )
{
unsigned int Pos = static_cast<unsigned int> ( ( mZ * mShadow->getWidth( ) + mX ) * 3 );//3 bytes ( mImage is RGBA )
if ( mShadow->getSize ( ) > Pos )
{
if ( positive )
return static_cast<Real> ( mShadow->getData( )[ Pos + 0] ) / 255;
else
return static_cast<Real> ( mShadow->getData( )[ Pos + 1] ) / 255;
}
else
{
return 0.0f;
}
}
else
{
return 0.0f;
}
}
//-----------------------------------------------------------------------
90 void PagingLandScapeData2D_HeightFieldRaw::_save( )
{
uchar *data = new uchar[ mXDimension * mZDimension * 2 ];
const double divider = 65535.0 / mParent->getOptions( )->scale.y;
unsigned int j = 0;
for ( unsigned int i = 0; i < mMaxArrayPos; i++ )
{
const ushort syn = ushort ( mHeightData[i] * divider );
#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
data[j] = uchar ( ( syn >> 8 ) & 0xff );
data[j+ 1] = uchar ( syn & 0xff );
#else
data[j] = uchar ( syn & 0xff );
data[j+ 1] = uchar ( ( syn >> 8 ) & 0xff );
#endif
j += 2;
}
const String fname = mParent->getOptions( )->LandScape_filename + "." +
StringConverter::toString( mPageZ ) + "." +
StringConverter::toString( mPageX ) + ".";
const String extname = mParent->getOptions( )->LandScape_extension;
FileInfoListPtr finfo = ResourceGroupManager::getSingleton( ).findResourceFileInfo (
mParent->getOptions( )->groupName,
fname + extname );
//ResourceGroupManager::getSingleton( ).openResource ( )
FileInfoList::iterator it = finfo->begin( );
if ( it != finfo->end( ) )
{
//FileInfo *inf = &( *it );
char *olddir = ChangeToDir ( const_cast< char * > ( ( ( it )->archive->getName( ) ).c_str( ) ) );
//FileSystemArchive::pushDirectory( )
std::ofstream outfile;
String FileNameRaw;
DataStreamPtr image_chunk( new MemoryDataStream ( ( void* )data,
mXDimension * mZDimension * 2 * sizeof ( uchar ),
true ) );
outfile.open ( const_cast< char * > ( ( fname + "modif." + extname ).c_str( ) ),
std::ios::binary );
// Write out
outfile << image_chunk->getAsString ( );
outfile.close ( );
//FileSystemArchive::pushDirectory( );
RetablishDir ( olddir );
}
}
//-----------------------------------------------------------------------
144 bool PagingLandScapeData2D_HeightFieldRaw::_load( const unsigned int mX, const unsigned int mZ )
{
// Load data
const String strFileName = mParent->getOptions( )->LandScape_filename + "." +
StringConverter::toString( mZ ) + "." +
StringConverter::toString( mX ) + ".";
String finalName = strFileName +
"modif." +
mParent->getOptions( )->LandScape_extension;
if ( !( mParent->getOptions( )->Deformable &&
ResourceGroupManager::getSingleton( ).resourceExists( mParent->getOptions( )->groupName, finalName ) ) )
{
finalName = strFileName + mParent->getOptions( )->LandScape_extension;
if ( !ResourceGroupManager::getSingleton( ).resourceExists( mParent->getOptions( )->groupName, finalName ) )
{
LogManager::getSingleton( ).logMessage( LML_CRITICAL, String( "PLSM2 : Cannot find map named " ) + finalName );
return false;
}
}
DataStreamPtr RawData;
RawData = ResourceGroupManager::getSingleton( ).openResource( finalName,
mParent->getOptions( )->groupName );
// Validate size
// Image size comes from setting ( since RAW is not self-describing )
// here 16 bits Raw file
mXDimension = mSize;
mZDimension = mXDimension;
mBpp = 2;
mMaxArrayPos = static_cast <unsigned int> ( mSize * mSize );
const size_t numBytes = mMaxArrayPos * mBpp;
if ( RawData->size( ) != numBytes )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
"RAW size ( " + StringConverter::toString( static_cast<unsigned int> ( RawData->size( ) ) ) +
" ) does not agree with configuration settings.",
"PagingLandScapeData2D_HeightFieldRaw::_load" );
}
mMax = static_cast<unsigned int> ( numBytes ) + 1;
mHeightData = new Real[mMaxArrayPos];
const double scale = ( double ) mParent->getOptions( )->scale.y / 65535;
mMaxheight = 0.0f;
MemoryDataStream dc ( RawData,
true );
const uchar *pSrc = dc.getPtr ( );
unsigned int j = 0;
for ( unsigned int i = 0; i < mMax - 1; i += mBpp )
{
#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
ushort val = *pSrc++ <<8;
val += *pSrc++;
#else
ushort val = *pSrc++;
val += *pSrc++ <<8;
#endif
const Real h = val * scale;
mMaxheight = std::max ( h, mMaxheight );
mHeightData[j++] = h;
}
if ( mParent->getOptions( )->vertex_shadowed )
{
mShadow = new Image( );
mShadow->load( mParent->getOptions( )->LandScape_filename +
".HS." +
StringConverter::toString( mZ ) + "." +
StringConverter::toString( mX ) + "." +
"png",
mParent->getOptions( )->groupName );
//mParent->getOptions( )->LandScape_extension );
}
return true;
}
//-----------------------------------------------------------------------
227 void PagingLandScapeData2D_HeightFieldRaw::_load( )
{
// Load data
const PagingLandScapeOptions * const opt = mParent->getOptions( );
const String mName( opt->LandScape_filename + "." + opt->LandScape_extension );
const String gName ( opt->groupName );
ResourceGroupManager *rsm = ResourceGroupManager::getSingletonPtr( );
DataStreamPtr RawData = rsm->openResource( mName, gName );
// Validate size
// Image size comes from setting ( since RAW is not self-describing )
// here 16 bits Raw file
mXDimension = opt->RawWidth;
mZDimension = opt->RawHeight;
mBpp = 2;
const size_t sourceHeight = mZDimension;
const size_t sourceWidth = mXDimension;
computePowerof2PlusOneSize ( );
mSize = mXDimension;
if ( RawData->size( ) != sourceHeight*sourceWidth*2 )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
"RAW size ( " + StringConverter::toString( static_cast<unsigned int> ( RawData->size( ) ) ) +
" ) does not agree with configuration settings.",
"PagingLandScapeData2D_HeightFieldRaw::_load" );
}
mMaxArrayPos = static_cast <unsigned int> ( mXDimension * mZDimension );
const size_t numBytes = mMaxArrayPos * mBpp;
mMax = static_cast<unsigned int> ( numBytes ) + 1;
mHeightData = new Real[mMaxArrayPos];
const Real scale = opt->ScaledHeightY;
mMaxheight = 0.0f;
MemoryDataStream dc( RawData,
true );
const uchar *pSrc = dc.getPtr ( );
const unsigned int shift_fill = static_cast <unsigned int> ( mXDimension - sourceWidth );
unsigned int dest_pos = 0;
//for some reason water is 65035 in SRTM files...
const bool srtm_water = opt->SRTM_water;
for ( unsigned int i = 0; i < sourceHeight; ++i )
{
for ( unsigned int j = 0; j < sourceWidth; ++j )
{
#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
ushort val = *pSrc++ << 8;
val += *pSrc++;
#else
ushort val = *pSrc++;
val += *pSrc++ << 8;
#endif
if ( srtm_water && ( val - 65035 ) > 0 )
val = 0;
const Real h = val * scale;
mMaxheight = std::max ( h, mMaxheight );
mHeightData[dest_pos++] = h;
}
memset ( &mHeightData[dest_pos], 0, shift_fill );
dest_pos+= shift_fill;
}
}
//-----------------------------------------------------------------------
300 void PagingLandScapeData2D_HeightFieldRaw::_unload( )
{
delete mShadow;
mShadow = 0;
}
} //namespace
1 /***************************************************************************
OgrePagingLandScapeData2D_HeightFieldRawTC.cpp - description
-------------------
begin : Mon Oct 13 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreLogManager.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreImage.h"
#include "OgreStringConverter.h"
#include "OgreResourceManager.h"
#include "OgreException.h"
#include "OgrePagingLandScapeData2D.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeData2D_HeightFieldRawTC.h"
#include "fileutils.h"
namespace Ogre
{
//-----------------------------------------------------------------------
44 PagingLandScapeData2D* PagingLandScapeData2D_HeightFieldRawTC::newPage( )
{
return new PagingLandScapeData2D_HeightFieldRawTC( mParent );
}
//-----------------------------------------------------------------------
49 PagingLandScapeData2D_HeightFieldRawTC::PagingLandScapeData2D_HeightFieldRawTC( PagingLandScapeData2DManager *dataMgr )
: PagingLandScapeData2D( dataMgr )
{
mImage = 0;
input_max = 3000.0f;
input_min = 0.0f;
mMaxheight = _decodeRawTC ( 1.0f ) * mParent->getOptions( )->scale.y;
}
//-------------------------------------------------------------------
58 const Real PagingLandScapeData2D_HeightFieldRawTC::getMaxAbsoluteHeight( void ) const
{
return _decodeRawTC ( 1.0f ) * mParent->getOptions( )->scale.y;
}
//-----------------------------------------------------------------------
64 PagingLandScapeData2D_HeightFieldRawTC::~PagingLandScapeData2D_HeightFieldRawTC( )
{
}
//-----------------------------------------------------------------------
68 const ColourValue PagingLandScapeData2D_HeightFieldRawTC::getBase ( const Real mX, const Real mZ )
{
return ColourValue::White;
}
//-----------------------------------------------------------------------
74 const ColourValue PagingLandScapeData2D_HeightFieldRawTC::getCoverage ( const Real mX, const Real mZ )
{
return ColourValue::White;
}
//-----------------------------------------------------------------------
79 const Vector3 PagingLandScapeData2D_HeightFieldRawTC::getNormalAt ( const Real x, const Real z )
{
#ifndef _LOADEDNORM
return PagingLandScapeData2D::getNormal( x, z );
#else
if ( mImage )
{
unsigned int Pos = static_cast<unsigned int> ( ( z * mSize + x ) * mBpp );//4 bytes ( mImage is RGBA )
if ( mMax > Pos )
{
const Real normalscale = 1.0f / 127.0f;
return Vector3 ( ( ( Real )( mImage->getData( )[Pos + 0] ) - 128.0f ) * normalscale,
( ( Real )( mImage->getData( )[Pos + 1] ) - 128.0f ) * normalscale,
( ( Real )( mImage->getData( )[Pos + 2] ) - 128.0f ) * normalscale );
}
else
{
return Vector3::UNIT_Y;
}
}
else
{
return Vector3::UNIT_Y;
}
#endif //_NOLOAD
}
//-----------------------------------------------------------------------
107 void PagingLandScapeData2D_HeightFieldRawTC::_save( )
{
uchar *data = new uchar[ mXDimension * mZDimension * 2 ];
const double divider = 65535.0 / mParent->getOptions( )->scale.y;
unsigned int j = 0;
for ( unsigned int i = 0; i < mXDimension*mZDimension; i++ )
{
ushort syn = static_cast <ushort> ( _encodeRawTC ( mHeightData[i] ) * divider );
#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
data[j] = uchar ( ( syn >> 8 ) & 0xff );
data[j+ 1] = uchar ( syn & 0xff );
#else
data[j] = uchar ( syn & 0xff );
data[j+ 1] = uchar ( ( syn >> 8 ) & 0xff );
#endif
j += 2;
}
const String fname = mParent->getOptions( )->LandScape_filename + "." +
StringConverter::toString( mPageZ ) + "." +
StringConverter::toString( mPageX ) + ".";
const String extname = mParent->getOptions( )->LandScape_extension;
FileInfoListPtr finfo = ResourceGroupManager::getSingleton( ).findResourceFileInfo (
mParent->getOptions( )->groupName,
fname + extname );
FileInfoList::iterator it = finfo->begin( );
if ( it != finfo->end( ) )
{
//FileInfo *inf = &( *it );
char *olddir = ChangeToDir ( const_cast< char * > ( ( ( it )->archive->getName( ) ).c_str( ) ) );
//FileSystemArchive::pushDirectory( )
std::ofstream outfile;
String FileNameRaw;
DataStreamPtr image_chunk( new MemoryDataStream ( ( void* )data,
mXDimension * mZDimension * 2 * sizeof ( uchar ),
true ) );
outfile.open ( const_cast< char * > ( ( fname + "modif." + extname ).c_str( ) ),
std::ios::binary );
// Write out
outfile << image_chunk->getAsString ( );
outfile.close ( );
//FileSystemArchive::pushDirectory( );
RetablishDir ( olddir );
}
}
//-----------------------------------------------------------------------
161 bool PagingLandScapeData2D_HeightFieldRawTC::_load( const unsigned int mX, const unsigned int mZ )
{
// Load data
//mRawData.clear( );
const String strFileName = mParent->getOptions( )->LandScape_filename + "." +
StringConverter::toString( mZ ) + "." +
StringConverter::toString( mX ) + ".";
String finalName = strFileName +
"modif." +
mParent->getOptions( )->LandScape_extension;
if ( !( mParent->getOptions( )->Deformable &&
ResourceGroupManager::getSingleton( ).resourceExists( mParent->getOptions( )->groupName, finalName ) ) )
{
finalName = strFileName +
mParent->getOptions( )->LandScape_extension;
if ( !ResourceGroupManager::getSingleton( ).resourceExists( mParent->getOptions( )->groupName, finalName ) )
{
LogManager::getSingleton( ).logMessage( LML_CRITICAL, String( "PLSM2 : Cannot find map named " ) + finalName );
return false;
}
}
DataStreamPtr RawData;
RawData = ResourceGroupManager::getSingleton( ).openResource( finalName,
mParent->getOptions( )->groupName );
// Validate size
// Image size comes from setting ( since RAW is not self-describing )
// here 16 bits Raw file
mXDimension = mSize;
mZDimension = mXDimension;
mBpp = 2;
size_t numBytes = mSize * mSize * mBpp;
if ( RawData->size( ) != numBytes )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
" ) does not agree with configuration settings.",
"PagingLandScapeData2D_HeightFieldRaw::_load" );
}
mMax = static_cast<unsigned int> ( numBytes ) + 1;
mMaxArrayPos = static_cast <unsigned int> ( mSize * mSize );
mHeightData = new Real[mMaxArrayPos];
const Real divider = 1.0f / 65535.0f;
const Real scale = mParent->getOptions( )->scale.y;
MemoryDataStream dc ( RawData,
true );
const uchar *pSrc = dc.getPtr ( );
mMaxheight = 0.0f;
unsigned int j = 0;
for ( unsigned int i = 0; i < mMax - 1; i += mBpp )
{
#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
ushort val = *pSrc++ <<8;
val += *pSrc++;
#else
ushort val = *pSrc++;
val += *pSrc++ <<8;
#endif
const Real h = _decodeRawTC ( val * divider )* scale;
mMaxheight = std::max ( h, mMaxheight );
mHeightData[j++] = h;
}
// if ( mParent->getOptions( )->vertex_shadowed )
// {
// mShadow = new Image( );
// mShadow->load( mParent->getOptions( )->LandScape_filename +
// ".HS." +
// StringConverter::toString( mZ ) + "." +
// StringConverter::toString( mX ) + "." +
// "png" );
// //mParent->getOptions( )->LandScape_extension );
// }
return true;
}
//-----------------------------------------------------------------------
244 void PagingLandScapeData2D_HeightFieldRawTC::_load( )
{
// Load data
DataStreamPtr RawData = ResourceGroupManager::getSingleton( ).openResource( mParent->getOptions( )->LandScape_filename +
"." +
mParent->getOptions( )->LandScape_extension,
mParent->getOptions( )->groupName );
// Validate size
// Image size comes from setting ( since RAW is not self-describing )
// here 16 bits Raw file
mXDimension = mParent->getOptions( )->RawWidth;
mZDimension = mParent->getOptions( )->RawHeight;
mBpp = 2;
const size_t sourceHeight = mZDimension;
const size_t sourceWidth = mXDimension;
computePowerof2PlusOneSize ( );
mSize = mXDimension;
if ( RawData->size( ) != sourceHeight*sourceWidth*2 )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
"RAW size ( " + StringConverter::toString( static_cast<unsigned int> ( RawData->size( ) ) ) +
" ) does not agree with configuration settings.",
"PagingLandScapeData2D_HeightFieldRaw::_load" );
}
mMaxArrayPos = static_cast <unsigned int> ( mXDimension * mZDimension );
const size_t numBytes = mMaxArrayPos * mBpp;
mMax = static_cast<unsigned int> ( numBytes ) + 1;
mHeightData = new Real[mMaxArrayPos];
mMaxheight = 0.0f;
MemoryDataStream dc( RawData,
true );
const uchar *pSrc = dc.getPtr ( );
const Real divider = 1.0f / 65535.0f;
const Real scale = mParent->getOptions( )->scale.y;
const unsigned int shift_fill = static_cast <unsigned int> ( mXDimension - sourceWidth );
unsigned int dest_pos = 0;
//for some reason water is 65035 in SRTM files...
const bool srtm_water = mParent->getOptions( )->SRTM_water;
for ( unsigned int i = 0; i < sourceHeight; ++i )
{
for ( unsigned int j = 0; j < sourceWidth; ++j )
{
#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
ushort val = *pSrc++ <<8;
val += *pSrc++;
#else
ushort val = *pSrc++;
val += *pSrc++ <<8;
#endif
if ( srtm_water && ( val - 65035 ) > 0 )
val = 0;
const Real h = _decodeRawTC ( val * divider ) * scale;
mMaxheight = std::max ( h, mMaxheight );
mHeightData[dest_pos++] = h;
}
memset ( &mHeightData[dest_pos], 0, shift_fill );
dest_pos+= shift_fill;
}
}
//-----------------------------------------------------------------------
320 void PagingLandScapeData2D_HeightFieldRawTC::_unload( )
{
delete mImage;
mImage = 0;
}
//-----------------------------------------------------------------------
327 inline Real PagingLandScapeData2D_HeightFieldRawTC::_decodeRawTC( const Real encoded ) const
{
return ( ( Real ) ( encoded + 0.5f ) ) * ( input_max - input_min ) + input_min;
}
//-----------------------------------------------------------------------
332 inline ushort PagingLandScapeData2D_HeightFieldRawTC::_encodeRawTC( const Real decoded ) const
{
return static_cast <short> ( ( decoded - input_min ) / ( input_max - input_min ) - 0.5f );
}
} //namespace
1 /***************************************************************************
OgrePagingLandScapeData2D_HeightFieldTC.cpp - description
-------------------
begin : Mon Oct 13 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreLogManager.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreImage.h"
#include "OgreStringConverter.h"
#include "OgreException.h"
#include "OgrePagingLandScapeData2D.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeData2D_HeightFieldTC.h"
#include "fileutils.h"
namespace Ogre
{
//-----------------------------------------------------------------------
44 PagingLandScapeData2D* PagingLandScapeData2D_HeightFieldTC::newPage( )
{
return new PagingLandScapeData2D_HeightFieldTC( mParent );
}
//-----------------------------------------------------------------------
49 PagingLandScapeData2D_HeightFieldTC::PagingLandScapeData2D_HeightFieldTC( PagingLandScapeData2DManager *dataMgr )
: PagingLandScapeData2D( dataMgr )
{
mImage = 0;
input_max = 3000.0f;
input_min = 0.0f;
mMaxheight = _decodeTC ( 1.0f ) * mParent->getOptions( )->scale.y;
}
//-------------------------------------------------------------------
58 const Real PagingLandScapeData2D_HeightFieldTC::getMaxAbsoluteHeight( void ) const
{
return _decodeTC ( 1.0f ) * mParent->getOptions( )->scale.y;
}
//-----------------------------------------------------------------------
64 PagingLandScapeData2D_HeightFieldTC::~PagingLandScapeData2D_HeightFieldTC( )
{
}
//-----------------------------------------------------------------------
68 const ColourValue PagingLandScapeData2D_HeightFieldTC::getBase ( const Real mX, const Real mZ )
{
return ColourValue::White;
}
//-----------------------------------------------------------------------
74 const ColourValue PagingLandScapeData2D_HeightFieldTC::getCoverage ( const Real mX, const Real mZ )
{
return ColourValue::White;
}
//-----------------------------------------------------------------------
79 void PagingLandScapeData2D_HeightFieldTC::_save( )
{
const Real scale = 1.0f / mParent->getOptions( )->scale.y;
uchar *img = mImage->getData( );
unsigned int j = 0;
for ( unsigned int i = 0; i < mMax - 1; i ++ )
{
img[ i ] = uchar ( _encodeTC( mHeightData[j++] ) * scale );
}
const String fname = mParent->getOptions( )->LandScape_filename + "." +
StringConverter::toString( mPageZ ) + "." +
StringConverter::toString( mPageX ) + ".";
const String extname = mParent->getOptions( )->LandScape_extension;
FileInfoListPtr finfo = ResourceGroupManager::getSingleton( ).findResourceFileInfo (
mParent->getOptions( )->groupName,
fname + extname );
FileInfoList::iterator it = finfo->begin( );
if ( it != finfo->end( ) )
{
//FileInfo *inf = &( *it );
char *olddir = ChangeToDir ( const_cast< char * > ( ( ( it )->archive->getName( ) ).c_str( ) ) );
//FileSystemArchive::pushDirectory( )
mImage->save ( fname + "modif." + extname );
//FileSystemArchive::pushDirectory( );
RetablishDir ( olddir );
}
}
//-----------------------------------------------------------------------
112 bool PagingLandScapeData2D_HeightFieldTC::_load( const unsigned int mX, const unsigned int mZ )
{
const String strFileName = mParent->getOptions( )->LandScape_filename + "." +
StringConverter::toString( mZ ) + "." +
StringConverter::toString( mX ) + ".";
String finalName = strFileName +
"modif." +
mParent->getOptions( )->LandScape_extension;
if ( !( mParent->getOptions( )->Deformable &&
ResourceGroupManager::getSingleton( ).resourceExists( mParent->getOptions( )->groupName,
finalName ) ) )
{
finalName = strFileName +
mParent->getOptions( )->LandScape_extension;
if ( !ResourceGroupManager::getSingleton( ).resourceExists( mParent->getOptions( )->groupName,
finalName ) )
{
LogManager::getSingleton( ).logMessage( LML_CRITICAL, String( "PLSM2 : Cannot find map named " ) + finalName );
return false;
}
}
mImage = new Image( );
mImage->load ( finalName, mParent->getOptions( )->groupName );
//check to make sure it's 2^n + 1 size.
if ( mImage->getWidth( ) != mImage->getHeight( ) ||
!_checkSize( mImage->getWidth( ) ) )
{
String err = "Error: Invalid heightmap size : " +
StringConverter::toString( static_cast<int>( mImage->getWidth( ) ) ) +
", " + StringConverter::toString( static_cast<int>( mImage->getHeight( ) ) ) +
". Should be 2^n+1, 2^n+1";
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, err, "PagingLandScapeData2D_HeightField::_load" );
}
mBpp = PixelUtil::getNumElemBytes ( mImage->getFormat ( ) );
if ( mBpp != 1 )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, "Error: Image is not a gray image.( 1 bytes, 8 bits )",
"PagingLandScapeData2D_HeightField::_load" );
}
if ( mSize != mImage->getWidth( ) )
{
OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS, "Error: Declared World size <> Height Map Size.", "PagingLandScapeData2D_HeightField::_load" );
}
mXDimension = mImage->getWidth( );
mZDimension = mImage->getHeight( );
mMax = static_cast <unsigned int> ( mSize * mImage->getHeight( ) + 1 );
mMaxArrayPos = mMax - 1;
mHeightData = new Real[mMaxArrayPos];
unsigned int j = 0;
const double divider = 1.0 / 255;
const Real scale = mParent->getOptions( )->scale.y;
uchar *data = mImage->getData( );
mMaxheight = 0.0f;
for ( unsigned int i = 0; i < mMax - 1; i++ )
{
const Real h = _decodeTC( data[ i ] * divider )* scale;
mMaxheight = std::max ( h, mMaxheight );
mHeightData[j++] = h;
}
return true;
}
//-----------------------------------------------------------------------
181 void PagingLandScapeData2D_HeightFieldTC::_load( )
{
mImage = new Image( );
mImage->load ( mParent->getOptions( )->LandScape_filename +
"." + mParent->getOptions( )->LandScape_extension, mParent->getOptions( )->groupName );
mBpp = PixelUtil::getNumElemBytes ( mImage->getFormat ( ) );
if ( mBpp != 1 )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, "Error: Image is not a greyscale image.( 1 byte, 8 bits )",
"PagingLandScapeData2D_HeightField::_load" );
}
mXDimension = mImage->getWidth( );
mZDimension = mImage->getHeight( );
const size_t sourceHeight = mZDimension;
const size_t sourceWidth = mXDimension;
computePowerof2PlusOneSize ( );
mSize = mXDimension;
mMaxArrayPos = static_cast <unsigned int> ( mXDimension * mZDimension );
mMax = static_cast <unsigned int> ( mMaxArrayPos * mBpp );
mHeightData = new Real[mMaxArrayPos];
const Real divider = 1.0f / 65535.0f;
const Real scale = mParent->getOptions( )->scale.y;
mMaxheight = 0.0f;
const unsigned int shift_fill = static_cast <unsigned int> ( mXDimension - sourceWidth );
uchar *imagedata = mImage->getData( );
unsigned int dest_pos = 0;
for ( unsigned int i = 0; i < sourceHeight; ++i )
{
for ( unsigned int j = 0; j < sourceWidth; ++j )
{
const Real h = _decodeTC( *imagedata++ * divider )* scale;
mMaxheight = std::max ( h, mMaxheight );
mHeightData[dest_pos++] = h;
}
memset ( &mHeightData[dest_pos], 0, shift_fill );
dest_pos += shift_fill;
}
}
//-----------------------------------------------------------------------
229 void PagingLandScapeData2D_HeightFieldTC::_unload( )
{
delete mImage;
mImage = 0;
}
//-----------------------------------------------------------------------
236 inline Real PagingLandScapeData2D_HeightFieldTC::_decodeTC( const Real encoded ) const
{
return ( ( Real ) ( encoded + 0.5f ) ) * ( input_max - input_min ) + input_min;
}
//-----------------------------------------------------------------------
242 inline uchar PagingLandScapeData2D_HeightFieldTC::_encodeTC( const Real decoded ) const
{
return static_cast<uchar> ( ( decoded - input_min ) / ( input_max - input_min ) - 0.5f );
}
} //namespace
1 /********************************************************************************
OgrePagingLandScapeData2D_Spline.cpp
*****************************************************************************
A NURBS-based heightfield generator for use with the pagingLandScapeplugin
Note that it could easily be adapted for use as a general NURBS surface
generator.
*****************************************************************************
begin : Sat Nov 9 2003
copyright : ( C ) 2003 Chris "Antiarc" Heald
email : antiarc@captionthis.com
********************************************************************************/
/********************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* ( at your option ) any later version. *
* *
********************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgrePagingLandScapeData2D.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeData2D_Spline.h"
namespace Ogre
{
//-----------------------------------------------------------------------
39 PagingLandScapeData2D* PagingLandScapeData2D_Spline::newPage( )
{
return new PagingLandScapeData2D_Spline( mParent );
}
//-----------------------------------------------------------------------
44 PagingLandScapeData2D_Spline::PagingLandScapeData2D_Spline( PagingLandScapeData2DManager *dataMgr )
: PagingLandScapeData2D( dataMgr ),
mSurface ( 0 ),
mPoints ( 0 )
{
mMaxheight = 256.0f * mParent->getOptions( )->scale.y;
}
//-----------------------------------------------------------------------
53 PagingLandScapeData2D_Spline::~PagingLandScapeData2D_Spline( )
{
delete mSurface;
delete[] mPoints;
}
//-------------------------------------------------------------------
59 void PagingLandScapeData2D_Spline::_save( )
{
}
//-------------------------------------------------------------------
64 const Real PagingLandScapeData2D_Spline::getMaxAbsoluteHeight( void ) const
{
return mParent->getOptions( )->scale.y;
}
//-----------------------------------------------------------------------
69 bool PagingLandScapeData2D_Spline::_load( const unsigned int mX, const unsigned int mZ )
{
int resolution = mParent->getOptions( )->PageSize;
mSize = resolution;
mMax = static_cast <unsigned int> ( mSize * mSize );
int pCount = 50;
int mDegree = 3;
Real MAX = 500;
int tessLevel = static_cast <unsigned int> ( mSize );
srand ( time( NULL ) );
mPoints = new Point4D[pCount * pCount];
const int knotVecSize = pCount + mDegree + 1;
float *knots = new float[knotVecSize];
int i;
for ( i = 0; i < knotVecSize; i++ )
{
if ( i < mDegree )
{
knots[i] = 0;
}
else if ( i > knotVecSize - mDegree )
{
knots[i] = knotVecSize - ( 2 * mDegree ) + 1;
}
else
{
knots[i] = i - mDegree + 1;
}
}
int dataSize = pCount * pCount;
for ( i = 0; i < dataSize; i++ )
{
mPoints[i].x = ( int ) ( i/pCount );
mPoints[i].y = double ( rand( ) ) / MAX;
mPoints[i].w = 1;
mPoints[i].z = 0;//i % pCount;
}
mSurface = new CDRGNURBSSurface( );
mSurface->Init( mDegree, mDegree,
pCount, pCount,
mPoints,
knots, knots,
tessLevel, tessLevel );
mSurface->TessellateSurface( );
delete[] knots;
delete[] mPoints;
mXDimension = mSize;
mZDimension = mSize;
mMaxArrayPos = resolution * resolution;
mHeightData = new Real[mMaxArrayPos];
Real scale = mParent->getOptions( )->scale.y;
mMaxheight = 0.0f;
unsigned int k;
for ( k = 0; k < mMaxArrayPos; k ++ )
{
Real h = static_cast<Real> ( mSurface->getData( k ).y * scale );
mHeightData[k] = h;
mMaxheight = std::max ( h, mMaxheight );
}
mIsLoaded = true;
return true;
}
//-----------------------------------------------------------------------
135 void PagingLandScapeData2D_Spline::_load( )
{
}
//-----------------------------------------------------------------------
140 void PagingLandScapeData2D_Spline::_unload( )
{
delete mSurface;
mSurface = 0;
mIsLoaded = false;
}
} //namespace
1 /***************************************************************************
OgrePagingLandScapeHorizon.cpp - description
-------------------
begin : Sat Mar 08 2003
copyright : ( C ) 2003-2006 by Jose A. Milan and Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreMovableObject.h"
#include "OgreAxisAlignedBox.h"
#include "OgreCamera.h"
#include "OgreMaterialManager.h"
#include "OgreTextureManager.h"
#include "OgreTechnique.h"
#include "OgrePass.h"
#include "OgreTextureUnitState.h"
#include "OgrePagingLandScapeTileInfo.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeHorizon.h"
#include "OgrePagingLandScapeCamera.h"
namespace Ogre
{
//-----------------------------------------------------------------------
47 PagingLandScapeHorizon::PagingLandScapeHorizon( const PagingLandScapeOptions * const options ):
mOptions( options )
{
mPageWidth = options->world_width;
mPageHeight = options->world_height;
mNumTilesPage = options->NumTiles;
mTileWidth = mPageWidth * mNumTilesPage;
mTileHeight = mPageHeight * mNumTilesPage;
size_t p_memssize = mPageWidth*mPageHeight;
mMinPageHeights = new Real[p_memssize];
memset ( mMinPageHeights, 0, p_memssize * sizeof( Real ) );
mMaxPageHeights = new Real[p_memssize];
memset ( mMaxPageHeights, 0, p_memssize * sizeof( Real ) );
size_t t_memssize = mTileWidth*mTileHeight;
mMinTileHeights = new Real[t_memssize];
memset ( mMinTileHeights, 0, t_memssize * sizeof( Real ) );
mMaxTileHeights = new Real[t_memssize];
memset ( mMaxTileHeights, 0, t_memssize * sizeof( Real ) );
material_enabled = false;
mVisData = 0;
}
//-----------------------------------------------------------------------
78 PagingLandScapeHorizon::~PagingLandScapeHorizon( )
{
delete [] mMinPageHeights;
delete [] mMaxPageHeights;
delete [] mMinTileHeights;
delete [] mMaxTileHeights;
mVisibilityMaterial.setNull( );
}
//-----------------------------------------------------------------------
89 void PagingLandScapeHorizon::prepare( const PagingLandScapeCamera* cam )
{
if ( material_enabled )
{
//reset.
memset ( mVisData, 0, mTileWidth * mTileHeight * 4 );
//add camera point
const Real tileX = cam->mCurrentCameraPageX * mNumTilesPage + cam->mCurrentCameraTileX;
const Real tileZ = cam->mCurrentCameraPageZ * mNumTilesPage + cam->mCurrentCameraTileZ;
const unsigned int tilePos = static_cast <unsigned int> ( ( tileX + tileZ * mTileWidth ) * 4 );
mVisData [ tilePos ] = 0;
mVisData [ tilePos + 1] = 0;
mVisData [ tilePos + 2] = 255;
mVisData [ tilePos + 3] = 255;
}
}
//-----------------------------------------------------------------------
107 void PagingLandScapeHorizon::update( )
{
if ( material_enabled )
{
const PixelBox srcBox = mVisImage.getPixelBox( );
HardwarePixelBufferSharedPtr Texbuffer = mVisTex->getBuffer ( 0, 0 );
const PixelBox lock = Texbuffer->lock ( srcBox, HardwareBuffer::HBL_DISCARD );
// lock.data can now be freely accessed
PixelUtil::bulkPixelConversion( srcBox, lock );
Texbuffer->unlock( );
}
}
//-----------------------------------------------------------------------
122 MaterialPtr PagingLandScapeHorizon::getVisibilityMaterial( )
{
if ( mVisibilityMaterial.isNull( ) )
{
const PagingLandScapeOptions * const opt = mOptions;
const String filename = opt->LandScape_filename;
const String name = filename +
"Visibility";
mVisibilityMaterial = MaterialManager::getSingleton( ).getByName ( name );
if ( mVisibilityMaterial.isNull( ) )
{
mVisibilityMaterial = MaterialManager::getSingleton( ).create ( name,
opt->groupName );
TextureUnitState *tu0 = mVisibilityMaterial->getTechnique ( 0 )->
getPass ( 0 )->createTextureUnitState ( );
tu0->setTextureName ( filename + ".Small." +
opt->TextureExtension );
tu0->setAlphaOperation ( LBX_BLEND_MANUAL, LBS_MANUAL, LBS_CURRENT, 0.7, 1, 1 );
//tu0->setTextureAddressingMode ( TextureUnitState::TextureAddressingMode::TAM_CLAMP );
tu0->setTextureAddressingMode ( TextureUnitState::TAM_CLAMP );
mVisibilityMaterial->setSceneBlending ( SBT_TRANSPARENT_ALPHA );
//mVisibilityMaterial->setDepthCheckEnabled ( false );
//mVisibilityMaterial->setDepthWriteEnabled ( false );
const size_t s = mTileWidth * mTileHeight * 4;
uchar *TexData = new uchar [s];
memset ( TexData, 0, s * sizeof( uchar ) );
// Assign the texture to the alpha map
mVisImage.loadDynamicImage( TexData, mTileWidth, mTileHeight, 1, PF_R8G8B8A8, true );
mVisData = mVisImage.getData( );
const String texname = filename + ".Visibility";
mVisTex = TextureManager::getSingleton( ).loadImage( texname,
opt->groupName,
mVisImage,
TEX_TYPE_2D, 0, 1.0f );
TextureUnitState *tu1 = mVisibilityMaterial->getTechnique ( 0 )->
getPass ( 0 )->createTextureUnitState( texname );
tu1->setTextureAddressingMode ( TextureUnitState::TAM_CLAMP );
}
else
{
const size_t s = mTileWidth * mTileHeight * 4;
uchar *TexData = new uchar [s];
memset ( TexData, 0, s * sizeof( uchar ) );
// Assign the texture to the alpha map
mVisImage.loadDynamicImage( TexData, mTileWidth, mTileHeight, 1, PF_R8G8B8A8, true );
mVisData = mVisImage.getData( );
mVisTex = TextureManager::getSingleton( ).getByName ( filename + ".Visibility" );
}
}
mVisibilityMaterial->load( );
material_enabled = true;
return mVisibilityMaterial;
}
//-----------------------------------------------------------------------
181 void PagingLandScapeHorizon::AddVisibleTile ( const unsigned int Tilex, const unsigned int Tilez,
182 const bool visible )
{
if ( material_enabled )
{
const unsigned int tilePos = ( Tilex + Tilez * mTileWidth ) * 4;
if ( visible )
{
mVisData [ tilePos ] = 0;
mVisData [ tilePos + 1] = 255;
mVisData [ tilePos + 2] = 0;
mVisData [ tilePos + 3] = 255;
}
else
{
mVisData [ tilePos ] = 255;
mVisData [ tilePos + 1] = 0;
mVisData [ tilePos + 2] = 0;
mVisData [ tilePos + 3] = 255;
}
}
}
//-----------------------------------------------------------------------
204 void PagingLandScapeHorizon::AddVisibleTile ( const PagingLandScapeTileInfo *info,
205 const bool visible )
{
if ( material_enabled )
{
const unsigned int TileX = info->mPageX*mNumTilesPage + info->mTileX;
const unsigned int TileZ = info->mPageZ*mNumTilesPage + info->mTileZ;
AddVisibleTile ( TileX, TileZ, visible );
}
}
//-----------------------------------------------------------------------
216 void PagingLandScapeHorizon::registerMinMaxHeightPage ( const unsigned int pageX, const unsigned int pageZ,
217 const Real minHeight, const Real maxHeight )
{
const size_t pos = mPageWidth*mPageHeight;
mMinPageHeights[pos] = minHeight;
mMaxPageHeights[pos] = maxHeight;
}
//-----------------------------------------------------------------------
224 void PagingLandScapeHorizon::registerMinMaxHeightTile ( const PagingLandScapeTileInfo *info,
225 const Real minHeight, const Real maxHeight )
{
const size_t tilePos = ( info->mPageX*mNumTilesPage + info->mTileX
+ ( ( info->mPageZ*mNumTilesPage ) + info->mTileZ ) * mTileWidth );
assert ( tilePos < mTileWidth*mTileHeight );
mMinTileHeights[tilePos] = minHeight;
mMaxTileHeights[tilePos] = maxHeight;
const size_t pagePos = info->mPageX + info->mPageZ * mPageWidth;
assert ( pagePos < mPageWidth*mPageHeight );
// if tile height is maximum or minimum height page
if ( mMaxPageHeights[pagePos] < maxHeight )
mMaxPageHeights[pagePos] = maxHeight;
if ( mMinPageHeights[pagePos] > minHeight )
mMinPageHeights[pagePos] = minHeight;
}
//-----------------------------------------------------------------------
246 bool PagingLandScapeHorizon::IsPageVisible( const PagingLandScapeCamera* cam,
const unsigned int destpageX, const unsigned int destpageZ )
{
const Real PageX = cam->mCurrentCameraPageX;
const Real PageZ = cam->mCurrentCameraPageZ;
// test if there is potential occluders
if ( fabs ( PageX - destpageX ) < 2 && fabs ( PageZ - destpageZ ) < 2 )
return true;
assert ( destpageX + destpageZ*mPageWidth < mPageWidth*mPageHeight );
return calcVis( Vector3 ( PageX, cam->getDerivedPosition ( ).y, PageZ ),
Vector3 ( destpageX, mMaxPageHeights[destpageX + destpageZ*mPageWidth], destpageZ ),
mMinPageHeights, mPageWidth, mPageHeight );
}
//-----------------------------------------------------------------------
263 bool PagingLandScapeHorizon::IsTileVisible( const PagingLandScapeCamera* cam,
264 const PagingLandScapeTileInfo *destinfo )
{
const Real RsrcTileX = cam->mCurrentCameraPageX * mNumTilesPage + cam->mCurrentCameraTileX;
const Real RsrcTileZ = cam->mCurrentCameraPageZ * mNumTilesPage + cam->mCurrentCameraTileZ;
const Real RdestTileX = destinfo->mPageX*mNumTilesPage + destinfo->mTileX;
const Real RdestTileZ = destinfo->mPageZ*mNumTilesPage + destinfo->mTileZ;
// test if there is potential occluders
if ( fabs ( RsrcTileX - RdestTileX ) < 2.0f && fabs ( RsrcTileZ - RdestTileZ ) < 2.0f )
return true;
const size_t pos = static_cast <size_t> ( RdestTileX + RdestTileZ*mTileWidth );
assert ( pos < mTileWidth*mTileHeight );
return calcVis( Vector3 ( RsrcTileX, cam->getDerivedPosition ( ).y, RsrcTileZ ),
Vector3 ( RdestTileX, mMaxTileHeights[pos], RdestTileZ ),
mMinTileHeights, mTileWidth, mTileHeight );
}
//-----------------------------------------------------------------------
287 bool PagingLandScapeHorizon::calcVis( const Vector3 &src, const Vector3 &dest,
const Real * const heightMap,
const unsigned int mapWidth, const unsigned int mapHeight )
{
/* Make sure the ray is normalised */
const Real x = dest.x - src.x;
const Real z = dest.z - src.z;
/*normalise only on x and z*/
const Real fLength = Math::Sqrt( x * x + z * z );
// Will also work for zero-sized vectors, but will change nothing
if ( fLength < 1e-08 )
return true;
const Real fInvLength = 1.0 / fLength;
const Vector3 direction ( x * fInvLength,
( dest.y - src.y ) * fInvLength,
z * fInvLength );
Real lasty = src.y;
Vector3 currpos ( src + direction ); // fetch new tile
/* For each heightmap location in the ray */
while ( currpos.x >= 0 &&
currpos.z >= 0 &&
currpos.x < mapWidth &&
currpos.z < mapHeight )
{
const size_t posx = static_cast <size_t> ( currpos.x + 0.5f );
const size_t posz = static_cast <size_t> ( currpos.z + 0.5f );
if ( posx == dest.x && posz == dest.z )
break;
const Real curry = currpos.y;
currpos = currpos + direction; // fetch new tile
const Real nexty = currpos.y; // fetch next tile height
const Real h = heightMap[posx + posz*mapWidth];
if ( h > nexty && h > lasty )
{
AddVisibleTile ( static_cast <unsigned int> ( dest.x ),
static_cast <unsigned int> ( dest.z ),
false );
return false; // line of sight is occluded
}
lasty = curry;
}
AddVisibleTile ( static_cast <unsigned int> ( dest.x ),
static_cast <unsigned int> ( dest.z ),
true );
return true;
}
} //namespace
1 /***************************************************************************
OgrePagingLandScapeIndexBufferManager.cpp - description
-------------------
begin : Fri Feb 28 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreHardwareBufferManager.h"
#include "OgreVertexIndexData.h"
#include "OgreVector3.h"
#include "OgreSimpleRenderable.h"
#include "OgrePagingLandScapeSceneManager.h"
#include "OgrePagingLandScapeRenderable.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeIndexBuffer.h"
namespace Ogre
{
//-----------------------------------------------------------------------
35 PagingLandScapeIndexBufferManager::PagingLandScapeIndexBufferManager( PagingLandScapeSceneManager * scnMgr ):
mScnMgr( scnMgr ),
mTileSize ( 0 ),
mNumIndexes ( 0 )
{
}
//-----------------------------------------------------------------------
43 PagingLandScapeIndexBufferManager::~PagingLandScapeIndexBufferManager( )
{
clear( );
}
//-----------------------------------------------------------------------
48 void PagingLandScapeIndexBufferManager::load( )
{
const unsigned int tileSize = mScnMgr->getOptions( )->TileSize;
const unsigned int numIndexes = mScnMgr->getOptions( )->maxRenderLevel + 1;
if ( tileSize != mTileSize || numIndexes != mNumIndexes )
{
// Clear
mLevelIndex.reserve ( numIndexes );
mLevelIndex.resize ( numIndexes );
for ( unsigned int k = 0; k < numIndexes; k++ )
{
mLevelIndex[k] = new IndexMap( );
}
mNumIndexes = numIndexes;
mTileSize = tileSize;
}
}
//-----------------------------------------------------------------------
68 void PagingLandScapeIndexBufferManager::clear( )
{
if ( !mLevelIndex.empty( ) )
{
for ( unsigned int i = 0; i < mNumIndexes; i++ )
{
delete mLevelIndex[i];
}
mLevelIndex.clear( );
}
if ( !mCache.empty( ) )
{
const size_t cachesize = mCache.size ( );
for( size_t j = 0; j < cachesize; j++ )
{
delete mCache[j];
}
mCache.clear( );
}
}
//-----------------------------------------------------------------------
89 IndexData *PagingLandScapeIndexBufferManager::getIndexData( const int renderLevel,
90 PagingLandScapeRenderable **Neighbors )
{
assert ( renderLevel < static_cast <int> ( mNumIndexes ) );
assert ( renderLevel >= 0 ) ;
unsigned int stitchFlags = 0;
bool eastStitch;
if ( Neighbors[ EAST ] &&
Neighbors[ EAST ]->isLoaded ( ) && Neighbors[ EAST ]->isVisible ( ) &&
Neighbors[ EAST ]->mRenderLevel > renderLevel )
{
assert ( Neighbors[ EAST ]->mRenderLevel < static_cast <int> ( mNumIndexes ) );
stitchFlags |= STITCH_EAST;
stitchFlags |=
( Neighbors[ EAST ]->mRenderLevel - renderLevel ) << STITCH_EAST_SHIFT;
eastStitch = true;
}
else
{
eastStitch = false;
}
bool westStitch;
if ( Neighbors[ WEST ] &&
Neighbors[ WEST ]->isLoaded ( ) && Neighbors[ WEST ]->isVisible ( ) &&
Neighbors[ WEST ]->mRenderLevel > renderLevel )
{
assert ( Neighbors[ WEST ]->mRenderLevel < static_cast <int> ( mNumIndexes ) );
stitchFlags |= STITCH_WEST;
stitchFlags |=
( Neighbors[ WEST ]->mRenderLevel - renderLevel ) << STITCH_WEST_SHIFT;
westStitch = true;
}
else
{
westStitch = false;
}
bool northStitch;
if ( Neighbors[ NORTH ] &&
Neighbors[ NORTH ]->isLoaded ( ) && Neighbors[ NORTH ]->isVisible ( ) &&
Neighbors[ NORTH ]->mRenderLevel > renderLevel )
{
assert ( Neighbors[ NORTH ]->mRenderLevel < static_cast <int> ( mNumIndexes ) );
stitchFlags |= STITCH_NORTH;
stitchFlags |=
( Neighbors[ NORTH ]->mRenderLevel - renderLevel ) << STITCH_NORTH_SHIFT;
northStitch = true;
}
else
{
northStitch = false;
}
bool southStitch;
if ( Neighbors[ SOUTH ] &&
Neighbors[ SOUTH ]->isLoaded ( ) && Neighbors[ SOUTH ]->isVisible ( ) &&
Neighbors[ SOUTH ]->mRenderLevel > renderLevel )
{
assert ( Neighbors[ SOUTH ]->mRenderLevel < static_cast <int> ( mNumIndexes ) );
stitchFlags |= STITCH_SOUTH;
stitchFlags |=
( Neighbors[ SOUTH ]->mRenderLevel - renderLevel ) << STITCH_SOUTH_SHIFT;
southStitch = true;
}
else
{
southStitch = false;
}
// Check preexisting
assert ( mLevelIndex.size( ) > ( unsigned int )renderLevel );
IndexMap::iterator ii = mLevelIndex[ renderLevel ]->find( stitchFlags );
if ( ii == mLevelIndex[ renderLevel ]->end( ) )
{
// Create
IndexData* indexData = generateTriListIndexes( northStitch,
southStitch,
eastStitch,
westStitch,
renderLevel,
Neighbors );
mCache.push_back( indexData );
mLevelIndex[ renderLevel ]->insert(
IndexMap::value_type( stitchFlags, indexData ) );
indexData->optimiseVertexCacheTriList( );
return indexData;
}
else
{
return ii->second;
}
}
//-----------------------------------------------------------------------
191 IndexData* PagingLandScapeIndexBufferManager::generateTriListIndexes( const bool northStitch,
192 const bool southStitch,
193 const bool eastStitch,
194 const bool westStitch,
const int RenderLevel,
196 PagingLandScapeRenderable **Neighbors ) const
{
const int step = 1 << RenderLevel;
assert ( step > 0 );
const unsigned int tileSize = mTileSize;
const unsigned int new_length = ( tileSize / step ) * ( tileSize / step ) * 2 * 2 * 2;
IndexData* indexData = new IndexData( );
assert ( indexData );
const bool is32bits = new_length > 65535 ? true : false;
indexData->indexBuffer =
HardwareBufferManager::getSingleton( ).createIndexBuffer(
( is32bits ) ? HardwareIndexBuffer::IT_32BIT : HardwareIndexBuffer::IT_16BIT,
new_length,
HardwareBuffer::HBU_STATIC_WRITE_ONLY );
const unsigned int north = northStitch ? step : 0;
const unsigned int south = southStitch ? step : 0;
const unsigned int east = eastStitch ? step : 0;
const unsigned int west = westStitch ? step : 0;
unsigned int numIndexes = 0;
const unsigned int step_offset = step * tileSize;
unsigned int height_count = north * tileSize;
void *idx;
if ( is32bits )
{
/** Returns the index into the height array for the given coordinates. */
unsigned int * ogre_restrict pIdx = static_cast<unsigned int*>( indexData->indexBuffer->lock( 0,
indexData->indexBuffer->getSizeInBytes( ),
HardwareBuffer::HBL_DISCARD ) );
assert ( pIdx );
for ( unsigned int j = north; j < tileSize - 1 - south; j += step )
{
for ( unsigned int i = west; i < tileSize - 1 - east; i += step )
{
//triangles
assert ( ( i + step + height_count + step_offset ) < ( tileSize * tileSize ) );
*pIdx++ = static_cast<unsigned int> ( i + height_count ); numIndexes++;
*pIdx++ = static_cast<unsigned int> ( i + height_count + step_offset ); numIndexes++;
*pIdx++ = static_cast<unsigned int> ( i + step + height_count ); numIndexes++;
*pIdx++ = static_cast<unsigned int> ( i + height_count + step_offset ); numIndexes++;
*pIdx++ = static_cast<unsigned int> ( i + step + height_count + step_offset ); numIndexes++;
*pIdx++ = static_cast<unsigned int> ( i + step + height_count ); numIndexes++;
}
height_count += step_offset;
}
idx = pIdx;
}
else
{
/** Returns the index into the height array for the given coordinates. */
ushort * ogre_restrict pIdx = static_cast<ushort*>( indexData->indexBuffer->lock( 0,
indexData->indexBuffer->getSizeInBytes( ),
HardwareBuffer::HBL_DISCARD ) );
assert ( pIdx );
for ( unsigned int j = north; j < tileSize - 1 - south; j += step )
{
for ( unsigned int i = west; i < tileSize - 1 - east; i += step )
{
//triangles
assert ( ( i + step + height_count + step_offset ) < ( ( tileSize ) * ( tileSize ) ) );
*pIdx++ = static_cast<ushort> ( i + height_count ); numIndexes++;
*pIdx++ = static_cast<ushort> ( i + height_count + step_offset ); numIndexes++;
*pIdx++ = static_cast<ushort> ( i + step + height_count ); numIndexes++;
*pIdx++ = static_cast<ushort> ( i + height_count + step_offset ); numIndexes++;
*pIdx++ = static_cast<ushort> ( i + step + height_count + step_offset ); numIndexes++;
*pIdx++ = static_cast<ushort> ( i + step + height_count ); numIndexes++;
}
height_count += step_offset;
}
idx = pIdx;
}
assert ( numIndexes < new_length );
// North stitching
assert ( RenderLevel < static_cast <int> ( mNumIndexes ) );
if ( northStitch )
{
assert ( Neighbors[ NORTH ] );
assert ( Neighbors[ NORTH ]->isLoaded ( ) );
assert ( Neighbors[ NORTH ]->isVisible ( ) );
assert ( Neighbors[ NORTH ]->mRenderLevel > RenderLevel );
assert ( Neighbors[ NORTH ]->mRenderLevel < static_cast <int> ( mNumIndexes ) );
numIndexes += stitchEdge( NORTH, RenderLevel, Neighbors[NORTH]->mRenderLevel,
westStitch , eastStitch , &idx, is32bits );
}
// East stitching
if ( eastStitch )
{
assert ( Neighbors[ EAST ] );
assert ( Neighbors[ EAST ]->isLoaded ( ) );
assert ( Neighbors[ EAST ]->isVisible ( ) );
assert ( Neighbors[ EAST ]->mRenderLevel > RenderLevel );
assert ( Neighbors[ EAST ]->mRenderLevel < static_cast <int> ( mNumIndexes ) );
numIndexes += stitchEdge( EAST, RenderLevel, Neighbors[EAST]->mRenderLevel,
northStitch, southStitch, &idx, is32bits );
}
// South stitching
if ( southStitch )
{
assert ( Neighbors[ SOUTH ] );
assert ( Neighbors[ SOUTH ]->isLoaded ( ) );
assert ( Neighbors[ SOUTH ]->isVisible ( ) );
assert ( Neighbors[ SOUTH ]->mRenderLevel > RenderLevel );
assert ( Neighbors[ SOUTH ]->mRenderLevel < static_cast <int> ( mNumIndexes ) );
numIndexes += stitchEdge( SOUTH, RenderLevel, Neighbors[SOUTH]->mRenderLevel,
eastStitch , westStitch, &idx, is32bits );
}
// West stitching
if ( westStitch )
{
assert ( Neighbors[ WEST ] );
assert ( Neighbors[ WEST ]->isLoaded ( ) );
assert ( Neighbors[ WEST ]->isVisible ( ) );
assert ( Neighbors[ WEST ]->mRenderLevel > RenderLevel );
assert ( Neighbors[ WEST ]->mRenderLevel < static_cast <int> ( mNumIndexes ) );
numIndexes += stitchEdge( WEST, RenderLevel, Neighbors[WEST]->mRenderLevel,
southStitch , northStitch, &idx, is32bits );
}
assert ( numIndexes < new_length );
indexData->indexBuffer->unlock( );
indexData->indexCount = numIndexes;
indexData->indexStart = 0;
return indexData;
}
//-----------------------------------------------------------------------
338 unsigned int PagingLandScapeIndexBufferManager::stitchEdge( const Neighbor neighbor,
const int hiLOD, const int loLOD,
340 const bool omitFirstTri, const bool omitLastTri,
void** ppIdx,
342 const bool is32bits ) const
{
assert( loLOD > hiLOD );
/*
Now do the stitching; we can stitch from any level to any level.
The stitch pattern is like this for each pair of vertices in the lower LOD
( excuse the poor ascii art ):
lower LOD
*-----------*
|\ \ 3 / /|
|1\2 \ / 4/5|
*--*--*--*--*
higher LOD
The algorithm is, for each pair of lower LOD vertices:
1. Iterate over the higher LOD vertices, generating tris connected to the
first lower LOD vertex, up to and including 1/2 the span of the lower LOD
over the higher LOD ( tris 1-2 ). Skip the first tri if it is on the edge
of the tile and that edge is to be stitched itself.
2. Generate a single tri for the middle using the 2 lower LOD vertices and
the middle vertex of the higher LOD ( tri 3 ).
3. Iterate over the higher LOD vertices from 1/2 the span of the lower LOD
to the end, generating tris connected to the second lower LOD vertex
( tris 4-5 ). Skip the last tri if it is on the edge of a tile and that
edge is to be stitched itself.
The same algorithm works for all edges of the patch; stitching is done
clockwise so that the origin and steps used change, but the general
approach does not.
*/
// Work out the steps ie how to increment indexes
// Step from one vertex to another in the high detail version
int step = 1 << hiLOD;
// Step from one vertex to another in the low detail version
int superstep = 1 << loLOD;
// Step half way between low detail steps
int halfsuperstep = superstep >> 1;
// Work out the starting points and sign of increments
// We always work the strip clockwise
int startx, starty, endx, rowstep;
bool horizontal;
const int tileSize = static_cast <int> ( mTileSize - 1 );
switch ( neighbor )
{
case NORTH:
startx = starty = 0;
endx = tileSize;
rowstep = step;
horizontal = true;
break;
case SOUTH:
// invert x AND y direction, helps to keep same winding
startx = starty = tileSize;
endx = 0;
rowstep = -step;
step = -step;
superstep = -superstep;
halfsuperstep = -halfsuperstep;
horizontal = true;
break;
case EAST:
startx = 0;
endx = tileSize;
starty = tileSize;
rowstep = -step;
horizontal = false;
break;
case WEST:
startx = tileSize;
endx = 0;
starty = 0;
rowstep = step;
step = -step;
superstep = -superstep;
halfsuperstep = -halfsuperstep;
horizontal = false;
break;
default:
startx = 0;
endx = 0;
starty = 0;
rowstep = 0;
step = 0;
superstep = 0;
halfsuperstep = 0;
horizontal = false;
assert ( 0 );
break;
};
assert ( *ppIdx );
unsigned int numIndexes = 0;
const bool isHorizontal = horizontal;
if ( is32bits )
{
// Get pointer to be updated
unsigned int* ogre_restrict pIdx = static_cast <unsigned int*> ( *ppIdx );
for ( int j = startx; j != endx; j += superstep )
{
int k;
for ( k = 0; k != halfsuperstep; k += step )
{
int jk = j + k;
//skip the first bit of the corner?
if ( j != startx || k != 0 || !omitFirstTri )
{
if ( isHorizontal )
{
*pIdx++ = _index32( j , starty ); numIndexes++;
*pIdx++ = _index32( jk, starty + rowstep ); numIndexes++;
*pIdx++ = _index32( jk + step, starty + rowstep ); numIndexes++;
}
else
{
*pIdx++ = _index32( starty, j ); numIndexes++;
*pIdx++ = _index32( starty + rowstep, jk ); numIndexes++;
*pIdx++ = _index32( starty + rowstep, jk + step ); numIndexes++;
}
}
}
// Middle tri
if ( isHorizontal )
{
*pIdx++ = _index32( j, starty ); numIndexes++;
*pIdx++ = _index32( j + halfsuperstep, starty + rowstep ); numIndexes++;
*pIdx++ = _index32( j + superstep, starty ); numIndexes++;
}
else
{
*pIdx++ = _index32( starty, j ); numIndexes++;
*pIdx++ = _index32( starty + rowstep, j + halfsuperstep ); numIndexes++;
*pIdx++ = _index32( starty, j + superstep ); numIndexes++;
}
for ( k = halfsuperstep; k != superstep; k += step )
{
int jk = j + k;
if ( j != endx - superstep || k != superstep - step || !omitLastTri )
{
if ( isHorizontal )
{
*pIdx++ = _index32( j + superstep, starty ); numIndexes++;
*pIdx++ = _index32( jk, starty + rowstep ); numIndexes++;
*pIdx++ = _index32( jk + step, starty + rowstep ); numIndexes++;
}
else
{
*pIdx++ = _index32( starty, j + superstep ); numIndexes++;
*pIdx++ = _index32( starty + rowstep, jk ); numIndexes++;
*pIdx++ = _index32( starty + rowstep, jk + step ); numIndexes++;
}
}
}
}
*ppIdx = pIdx;
}
else
{
// Get pointer to be updated
ushort* ogre_restrict pIdx = static_cast <ushort*> ( *ppIdx );
for ( int j = startx; j != endx; j += superstep )
{
int k;
for ( k = 0; k != halfsuperstep; k += step )
{
int jk = j + k;
//skip the first bit of the corner?
if ( j != startx || k != 0 || !omitFirstTri )
{
if ( isHorizontal )
{
*pIdx++ = _index16( j , starty ); numIndexes++;
*pIdx++ = _index16( jk, starty + rowstep ); numIndexes++;
*pIdx++ = _index16( jk + step, starty + rowstep ); numIndexes++;
}
else
{
*pIdx++ = _index16( starty, j ); numIndexes++;
*pIdx++ = _index16( starty + rowstep, jk ); numIndexes++;
*pIdx++ = _index16( starty + rowstep, jk + step ); numIndexes++;
}
}
}
// Middle tri
if ( isHorizontal )
{
*pIdx++ = _index16( j, starty ); numIndexes++;
*pIdx++ = _index16( j + halfsuperstep, starty + rowstep ); numIndexes++;
*pIdx++ = _index16( j + superstep, starty ); numIndexes++;
}
else
{
*pIdx++ = _index16( starty, j ); numIndexes++;
*pIdx++ = _index16( starty + rowstep, j + halfsuperstep ); numIndexes++;
*pIdx++ = _index16( starty, j + superstep ); numIndexes++;
}
for ( k = halfsuperstep; k != superstep; k += step )
{
int jk = j + k;
if ( j != endx - superstep || k != superstep - step || !omitLastTri )
{
if ( isHorizontal )
{
*pIdx++ = _index16( j + superstep, starty ); numIndexes++;
*pIdx++ = _index16( jk, starty + rowstep ); numIndexes++;
*pIdx++ = _index16( jk + step, starty + rowstep ); numIndexes++;
}
else
{
*pIdx++ = _index16( starty, j + superstep ); numIndexes++;
*pIdx++ = _index16( starty + rowstep, jk ); numIndexes++;
*pIdx++ = _index16( starty + rowstep, jk + step ); numIndexes++;
}
}
}
}
*ppIdx = pIdx;
}
return numIndexes;
}
//*******************
//Added by Fiesch adapted from a post by tonyhnz
572 IndexData *PagingLandScapeIndexBufferManager::getRawIndexes( int renderLevel )
{
// no stitching is done
// used to expose terrain vertex data
if ( renderLevel >= static_cast <int> ( mNumIndexes ) )
renderLevel = static_cast <int> ( mNumIndexes )-1;
if ( renderLevel < 0 )
renderLevel =0 ;
const unsigned int stitchFlags = 0;
assert ( mLevelIndex.size( ) > ( unsigned int )renderLevel );
IndexMap::iterator ii = mLevelIndex[ renderLevel ]->find( stitchFlags );
if ( ii == mLevelIndex[ renderLevel ]->end( ) )
{
// Create
IndexData* indexData = generateTriListIndexes( false,
false,
false,
false,
renderLevel,
0 );
mLevelIndex[ renderLevel ]->insert(
IndexMap::value_type( stitchFlags, indexData ) );
return indexData;
}
else
{
return ii->second;
}
}
} //namespace
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
OgrePagingLandScapeIntersectionSceneQuery.cpp - description
-------------------
begin : Tues July 20, 2004
copyright : ( C ) 2004by Jon Anderson
email : janders@users.sf.net
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgrePagingLandScapeSceneManager.h"
#include "OgrePagingLandScapeIntersectionSceneQuery.h"
#include "OgrePagingLandScapeOctreeSceneManager.h"
#include "OgrePagingLandScapeOctreeIntersectionSceneQuery.h"
#include "OgreEntity.h"
#include "OgreRoot.h"
namespace Ogre
{
//---------------------------------------------------------------------
51 PagingLandScapeIntersectionSceneQuery::PagingLandScapeIntersectionSceneQuery( SceneManager* creator )
: PagingLandScapeOctreeIntersectionSceneQuery( creator )
{
// Add bounds fragment type
mSupportedWorldFragments.insert( SceneQuery::WFT_SINGLE_INTERSECTION );
mSupportedWorldFragments.insert( SceneQuery::WFT_PLANE_BOUNDED_REGION );
}
//---------------------------------------------------------------------
60 PagingLandScapeIntersectionSceneQuery::~PagingLandScapeIntersectionSceneQuery( void )
{
}
//---------------------------------------------------------------------
65 void PagingLandScapeIntersectionSceneQuery::execute( IntersectionSceneQueryListener* listener )
{
if( mWorldFragmentType == SceneQuery::WFT_SINGLE_INTERSECTION )
{
PagingLandScapeOctreeIntersectionSceneQuery::execute( listener );
}
else if ( mWorldFragmentType == SceneQuery::WFT_PLANE_BOUNDED_REGION )
{
// We want the whole bounded volume
// assert( ( *bi )->fragment.fragmentType == SceneQuery::WFT_PLANE_BOUNDED_REGION );
// if ( !listener->queryResult( const_cast<WorldFragment*>( &( brush->fragment ) ),
// result.second + traceDistance ) )
// return false;
}
}
}
1 /*-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright � 2000-2004 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------*/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgrePagingLandScapeListenerManager.h"
#include "OgrePagingLandScapeSceneManager.h"
namespace Ogre
{
//-------------------------------------------------------------------------
33 PagingLandScapeListenerManager::PagingLandScapeListenerManager( PagingLandScapeSceneManager * scnMgr )
{
};
//-------------------------------------------------------------------------
37 PagingLandScapeListenerManager::~PagingLandScapeListenerManager( void )
{
std::for_each( mTerrainReadyListeners.begin( ), mTerrainReadyListeners.end( ), delete_object( ) );
std::for_each( mShowPageListeners.begin( ), mShowPageListeners.end( ), delete_object( ) );
std::for_each( mHidePageListeners.begin( ), mHidePageListeners.end( ), delete_object( ) );
std::for_each( mPreloadPageListeners.begin( ), mPreloadPageListeners.end( ), delete_object( ) );
std::for_each( mLoadPageListeners.begin( ), mLoadPageListeners.end( ), delete_object( ) );
std::for_each( mUnloadPageListeners.begin( ), mUnloadPageListeners.end( ), delete_object( ) );
std::for_each( mPostunloadPageListeners.begin( ), mPostunloadPageListeners.end( ), delete_object( ) );
std::for_each( mModifyPageListeners.begin( ), mModifyPageListeners.end( ), delete_object( ) );
std::for_each( mShowTileListeners.begin( ), mShowTileListeners.end( ), delete_object( ) );
std::for_each( mHideTileListeners.begin( ), mHideTileListeners.end( ), delete_object( ) );
std::for_each( mLoadTileListeners.begin( ), mLoadTileListeners.end( ), delete_object( ) );
std::for_each( mUnloadTileListeners.begin( ), mUnloadTileListeners.end( ), delete_object( ) );
std::for_each( mModifyTileListeners.begin( ), mModifyTileListeners.end( ), delete_object( ) );
};
//-------------------------------------------------------------------------
58 void PagingLandScapeListenerManager::firePagePreloaded( const size_t pagex,
59 const size_t pagez,
60 const Real* heightData,
61 const AxisAlignedBox &Bbox )
{
if ( mPreloadPageListeners.empty( ) )
return;
PagingLandscapeEvent e ( pagex, pagez, 0, 0, heightData, Bbox );
for ( std::list<PagingLandscapeDelegate *>::iterator it = mPreloadPageListeners.begin( );
it != mPreloadPageListeners.end( ); ++it )
( *( *it ) )( &e );
}
//-------------------------------------------------------------------------
72 void PagingLandScapeListenerManager::firePageLoaded( const size_t pagex, const size_t pagez,
73 const Real* heightData, const AxisAlignedBox &Bbox )
{
if ( mLoadPageListeners.empty( ) )
return;
PagingLandscapeEvent e ( pagex, pagez, 0, 0, heightData, Bbox );
for ( std::list<PagingLandscapeDelegate *>::iterator it = mLoadPageListeners.begin( );
it != mLoadPageListeners.end( ); ++it )
( *( *it ) )( &e );
}
//-------------------------------------------------------------------------
84 void PagingLandScapeListenerManager::firePageUnloaded( const size_t pagex, const size_t pagez,
85 const Real* heightData, const AxisAlignedBox &Bbox )
{
if ( mUnloadPageListeners.empty( ) )
return;
PagingLandscapeEvent e ( pagex, pagez, 0, 0, heightData, Bbox );
for ( std::list<PagingLandscapeDelegate *>::iterator it = mUnloadPageListeners.begin( );
it != mUnloadPageListeners.end( ); ++it )
( *( *it ) )( &e );
}
//-------------------------------------------------------------------------
97 void PagingLandScapeListenerManager::firePagePostunloaded( const size_t pagex, const size_t pagez )
{
if ( mPostunloadPageListeners.empty( ) )
return;
PagingLandscapeEvent e ( pagex, pagez, 0, 0, 0, AxisAlignedBox( ) );
for ( std::list<PagingLandscapeDelegate *>::iterator it = mPostunloadPageListeners.begin( );
it != mPostunloadPageListeners.end( ); ++it )
( *( *it ) )( &e );
}
//-------------------------------------------------------------------------
108 void PagingLandScapeListenerManager::firePageShow( const size_t pagex, const size_t pagez,
109 const Real* heightData, const AxisAlignedBox &Bbox )
{
if ( mShowPageListeners.empty( ) )
return;
PagingLandscapeEvent e ( pagex, pagez, 0, 0, heightData, Bbox );
for ( std::list<PagingLandscapeDelegate *>::iterator it = mShowPageListeners.begin( );
it != mShowPageListeners.end( ); ++it )
( *( *it ) )( &e );
}
//-------------------------------------------------------------------------
120 void PagingLandScapeListenerManager::firePageHide( const size_t pagex, const size_t pagez,
121 const Real* heightData, const AxisAlignedBox &Bbox )
{
if ( mHidePageListeners.empty( ) )
return;
PagingLandscapeEvent e ( pagex, pagez, 0, 0, heightData, Bbox );
for ( std::list<PagingLandscapeDelegate *>::iterator it = mHidePageListeners.begin( );
it != mHidePageListeners.end( ); ++it )
( *( *it ) )( &e );
}
//-------------------------------------------------------------------------
132 void PagingLandScapeListenerManager::fireTileLoaded ( const size_t pagex, const size_t pagez,
133 const size_t tilex, const size_t tilez, const AxisAlignedBox &Bbox )
{
if ( mLoadTileListeners.empty( ) )
return;
PagingLandscapeEvent e ( pagex, pagez, tilex, tilez, 0, Bbox );
for ( std::list<PagingLandscapeDelegate *>::iterator it = mLoadTileListeners.begin( );
it != mLoadTileListeners.end( ); ++it )
( *( *it ) )( &e );
}
//-------------------------------------------------------------------------
144 void PagingLandScapeListenerManager::fireTileUnloaded( const size_t pagex, const size_t pagez,
145 const size_t tilex, const size_t tilez, const AxisAlignedBox &Bbox )
{
if ( mUnloadTileListeners.empty( ) )
return;
PagingLandscapeEvent e ( pagex, pagez, tilex, tilez, 0, Bbox );
for ( std::list<PagingLandscapeDelegate *>::iterator it = mUnloadTileListeners.begin( );
it != mUnloadTileListeners.end( ); ++it )
( *( *it ) )( &e );
}
//-------------------------------------------------------------------------
156 void PagingLandScapeListenerManager::fireTileDeformed( const size_t pagex, const size_t pagez,
157 const size_t tilex, const size_t tilez, const AxisAlignedBox &Bbox )
{
if ( mModifyTileListeners.empty( ) )
return;
PagingLandscapeEvent e ( pagex, pagez, tilex, tilez, 0, Bbox );
for ( std::list<PagingLandscapeDelegate *>::iterator it = mModifyTileListeners.begin( );
it != mModifyTileListeners.end( ); ++it )
( *( *it ) )( &e );
}
//-------------------------------------------------------------------------
168 void PagingLandScapeListenerManager::fireTileShow( const size_t pagex, const size_t pagez,
169 const size_t tilex, const size_t tilez, const AxisAlignedBox &Bbox )
{
if ( mShowTileListeners.empty( ) )
return;
PagingLandscapeEvent e ( pagex, pagez, tilex, tilez, 0, Bbox );
for ( std::list<PagingLandscapeDelegate *>::iterator it = mShowTileListeners.begin( );
it != mShowTileListeners.end( ); ++it )
( *( *it ) )( &e );
}
//-------------------------------------------------------------------------
180 void PagingLandScapeListenerManager::fireTileHide( const size_t pagex, const size_t pagez,
181 const size_t tilex, const size_t tilez, const AxisAlignedBox &Bbox )
{
if ( mHideTileListeners.empty( ) )
return;
PagingLandscapeEvent e ( pagex, pagez, tilex, tilez, 0, Bbox );
for ( std::list<PagingLandscapeDelegate *>::iterator it = mHideTileListeners.begin( );
it != mHideTileListeners.end( ); ++it )
( *( *it ) )( &e );
}
//-------------------------------------------------------------------------
192 void PagingLandScapeListenerManager::fireTerrainReady( )
{
if ( mTerrainReadyListeners.empty( ) )
return;
PagingLandscapeEvent e ( 0, 0, 0, 0, 0, AxisAlignedBox ( ) );
for ( std::list<PagingLandscapeDelegate *>::iterator it = mTerrainReadyListeners.begin( );
it != mTerrainReadyListeners.end( ); ++it )
( *( *it ) )( &e );
}
//-------------------------------------------------------------------------
203 bool PagingLandScapeListenerManager::setOption( const String& strKey, const void* pValue )
{
PagingLandscapeDelegate *d = const_cast < PagingLandscapeDelegate * > ( static_cast < const PagingLandscapeDelegate * >( pValue ) );
if ( StringUtil::startsWith( strKey, "add", true ) )
{
if ( strKey == "addTerrainListener" )
{
addTerrainListener ( d );
return true;
}
if ( strKey == "addPreloadPageListener" )
{
addPreloadPageListener ( d );
return true;
}
if ( strKey == "addShowPageListener" )
{
addShowPageListener ( d );
return true;
}
if ( strKey == "addHidePageListener" )
{
addHidePageListener ( d );
return true;
}
if ( strKey == "addLoadPageListener" )
{
addLoadPageListener ( d );
return true;
}
if ( strKey == "addModifyPageListener" )
{
addModifyPageListener ( d );
return true;
}
if ( strKey == "addPostunloadPageListener" )
{
addPostunloadPageListener ( d );
return true;
}
if ( strKey == "addUnloadPageListener" )
{
addUnloadPageListener ( d );
return true;
}
if ( strKey == "addShowTileListener" )
{
addShowTileListener ( d );
return true;
}
if ( strKey == "addHideTileListener" )
{
addHideTileListener ( d );
return true;
}
if ( strKey == "addLoadTileListener" )
{
addLoadTileListener ( d );
return true;
}
if ( strKey == "addModifyTileListener" )
{
addModifyTileListener ( d );
return true;
}
if ( strKey == "addUnloadTileListener" )
{
addUnloadTileListener ( d );
return true;
}
}
if ( StringUtil::startsWith( strKey, "remove", true ) )
{
if ( strKey == "removeTerrainListener" )
{
removeTerrainListener ( d );
return true;
}
if ( strKey == "removePreloadPageListener" )
{
removePreloadPageListener ( d );
return true;
}
if ( strKey == "removeShowPageListener" )
{
removeShowPageListener ( d );
return true;
}
if ( strKey == "removeHidePageListener" )
{
removeHidePageListener ( d );
return true;
}
if ( strKey == "removeLoadPageListener" )
{
removeLoadPageListener ( d );
return true;
}
if ( strKey == "removeModifyPageListener" )
{
removeModifyPageListener ( d );
return true;
}
if ( strKey == "removePostunloadPageListener" )
{
removePostunloadPageListener ( d );
return true;
}
if ( strKey == "removeUnloadPageListener" )
{
removeUnloadPageListener ( d );
return true;
}
if ( strKey == "removeShowTileListener" )
{
removeShowTileListener ( d );
return true;
}
if ( strKey == "removeHideTileListener" )
{
removeHideTileListener ( d );
return true;
}
if ( strKey == "removeLoadTileListener" )
{
removeLoadTileListener ( d );
return true;
}
if ( strKey == "removeModifyTileListener" )
{
removeModifyTileListener ( d );
return true;
}
if ( strKey == "removeUnloadTileListener" )
{
removeUnloadTileListener ( d );
return true;
}
}
return false;
}
//-------------------------------------------------------------------------
352 void PagingLandScapeListenerManager::addTerrainListener( PagingLandscapeDelegate* pl )
{
mTerrainReadyListeners.push_back( pl );
}
//-------------------------------------------------------------------------
357 void PagingLandScapeListenerManager::removeTerrainListener( PagingLandscapeDelegate* pl )
{
mTerrainReadyListeners.remove ( pl );
}
//-------------------------------------------------------------------------
362 void PagingLandScapeListenerManager::addPreloadPageListener( PagingLandscapeDelegate* pl )
{
mPreloadPageListeners.push_back( pl );
};
//-------------------------------------------------------------------------
367 void PagingLandScapeListenerManager::removePreloadPageListener( PagingLandscapeDelegate* pl )
{
mPreloadPageListeners.remove ( pl );
};
//-------------------------------------------------------------------------
372 void PagingLandScapeListenerManager::addShowPageListener( PagingLandscapeDelegate* pl )
{
mShowPageListeners.push_back( pl );
};
//-------------------------------------------------------------------------
377 void PagingLandScapeListenerManager::removeShowPageListener( PagingLandscapeDelegate* pl )
{
mShowPageListeners.remove ( pl );
};
//-------------------------------------------------------------------------
382 void PagingLandScapeListenerManager::addHidePageListener( PagingLandscapeDelegate* pl )
{
mHidePageListeners.push_back( pl );
};
//-------------------------------------------------------------------------
387 void PagingLandScapeListenerManager::removeHidePageListener( PagingLandscapeDelegate* pl )
{
mHidePageListeners.remove ( pl );
};
//-------------------------------------------------------------------------
392 void PagingLandScapeListenerManager::addLoadPageListener( PagingLandscapeDelegate* pl )
{
mLoadPageListeners.push_back( pl );
};
//-------------------------------------------------------------------------
397 void PagingLandScapeListenerManager::removeLoadPageListener( PagingLandscapeDelegate* pl )
{
mLoadPageListeners.remove ( pl );
};
//-------------------------------------------------------------------------
402 void PagingLandScapeListenerManager::addModifyPageListener( PagingLandscapeDelegate* pl )
{
mModifyPageListeners.push_back( pl );
};
//-------------------------------------------------------------------------
407 void PagingLandScapeListenerManager::removeModifyPageListener( PagingLandscapeDelegate* pl )
{
mModifyPageListeners.remove ( pl );
};
//-------------------------------------------------------------------------
412 void PagingLandScapeListenerManager::addPostunloadPageListener( PagingLandscapeDelegate* pl )
{
mPostunloadPageListeners.push_back( pl );
};
//-------------------------------------------------------------------------
417 void PagingLandScapeListenerManager::removePostunloadPageListener( PagingLandscapeDelegate* pl )
{
mPostunloadPageListeners.remove ( pl );
};
//-------------------------------------------------------------------------
422 void PagingLandScapeListenerManager::addUnloadPageListener( PagingLandscapeDelegate* pl )
{
mUnloadPageListeners.push_back( pl );
};
//-------------------------------------------------------------------------
427 void PagingLandScapeListenerManager::removeUnloadPageListener( PagingLandscapeDelegate* pl )
{
mUnloadPageListeners.remove ( pl );
};
//-------------------------------------------------------------------------
432 void PagingLandScapeListenerManager::addShowTileListener( PagingLandscapeDelegate* pl )
{
mShowTileListeners.push_back( pl );
};
//-------------------------------------------------------------------------
437 void PagingLandScapeListenerManager::removeShowTileListener( PagingLandscapeDelegate* pl )
{
mShowTileListeners.remove ( pl );
};
//-------------------------------------------------------------------------
442 void PagingLandScapeListenerManager::addHideTileListener( PagingLandscapeDelegate* pl )
{
mHideTileListeners.push_back( pl );
};
//-------------------------------------------------------------------------
447 void PagingLandScapeListenerManager::removeHideTileListener( PagingLandscapeDelegate* pl )
{
mHideTileListeners.remove ( pl );
};
//-------------------------------------------------------------------------
452 void PagingLandScapeListenerManager::addLoadTileListener( PagingLandscapeDelegate* pl )
{
mLoadTileListeners.push_back( pl );
};
//-------------------------------------------------------------------------
457 void PagingLandScapeListenerManager::removeLoadTileListener( PagingLandscapeDelegate* pl )
{
mLoadTileListeners.remove ( pl );
};
//-------------------------------------------------------------------------
462 void PagingLandScapeListenerManager::addModifyTileListener( PagingLandscapeDelegate* pl )
{
mModifyTileListeners.push_back( pl );
};
//-------------------------------------------------------------------------
467 void PagingLandScapeListenerManager::removeModifyTileListener( PagingLandscapeDelegate* pl )
{
mModifyTileListeners.remove ( pl );
};
//-------------------------------------------------------------------------
472 void PagingLandScapeListenerManager::addUnloadTileListener( PagingLandscapeDelegate* pl )
{
mUnloadTileListeners.push_back( pl );
};
//-------------------------------------------------------------------------
477 void PagingLandScapeListenerManager::removeUnloadTileListener( PagingLandscapeDelegate* pl )
{
mUnloadTileListeners.remove ( pl );
};
}//namespace
1 /*-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright � 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------*/
/***************************************************************************
OgrePagingLandScapeMeshDecal.cpp - description
-------------------
begin : Sat Oct 15, 2006
copyright : ( C ) 2006 by Steven Klug
email : stevenklug@san.rr.com
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "Ogre.h"
#include "OgrePagingLandScapeMeshDecal.h"
#include "OgrePagingLandScapeAxisAlignedBoxSceneQuery.h"
#include <numeric>
using namespace Ogre;
using namespace std;
namespace
{
typedef PagingLandScapeAxisAlignedBoxSceneQuery::CustomQueryResult CustomQueryResult;
template<class T>
49 class IndexCalculator
{
int width_;
int offset_;
public:
54 IndexCalculator( int width, int offset )
: width_( width )
, offset_( offset ) {}
58 T GetIndex( int x, int z ) const
{
return offset_ + x + ( z * width_ );
}
};
}
65 PagingLandScapeMeshDecal::PagingLandScapeMeshDecal( const String& name,
66 const String& materialName,
67 const Vector2& size,
68 const String& sceneMgrInstanceName )
: MovableObject( name )
, material_( MaterialManager::getSingleton( ).getByName( materialName ) )
, size_( size )
, sceneMgr_( Root::getSingleton( ).getSceneManager( sceneMgrInstanceName ) )
, position_( Vector3::ZERO )
, mDirty( true )
{
if( material_.isNull( ) )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
"Invalid material name for mesh decal.",
"PagingLandScapeMeshDecal::PagingLandScapeMeshDecal" );
}
// Create a dummy rayQuery to avoid heap allocation every frame.
rayQuery_ = sceneMgr_->createRayQuery( Ray( Vector3::ZERO, Vector3::NEGATIVE_UNIT_Y ) );
rayQuery_->setQueryTypeMask( SceneManager::WORLD_GEOMETRY_TYPE_MASK );
rayQuery_->setWorldFragmentType( SceneQuery::WFT_SINGLE_INTERSECTION );
AABBquery_ = sceneMgr_->createAABBQuery( AxisAlignedBox( ) );
// Allocate objects for render op.
renderOp_.vertexData = new VertexData( );
renderOp_.indexData = new IndexData( );
// Create declaration ( memory format ) of vertex data
VertexDeclaration* decl = renderOp_.vertexData->vertexDeclaration;
decl->addElement( 0, 0, VET_FLOAT3, VES_POSITION );
declSize_ = sizeof( Vector3 );
decl->addElement( 0, declSize_, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0 );
declSize_ += sizeof( Vector2 );
// Set bounding information
AABB_.setMinimum( Vector3( -size_.x / 2, 1, -size_.y / 2 ) );
AABB_.setMaximum( Vector3( size_.x / 2, 1, size_.y / 2 ) );
// CreateGeometry( );
}
108 PagingLandScapeMeshDecal::~PagingLandScapeMeshDecal( )
{
sceneMgr_->destroyQuery( rayQuery_ );
sceneMgr_->destroyQuery( AABBquery_ );
delete renderOp_.vertexData;
delete renderOp_.indexData;
}
116 void PagingLandScapeMeshDecal::_notifyAttached( Node* parent, bool isTagPoint )
{
MovableObject::_notifyAttached( parent, isTagPoint );
CreateGeometry( );
}
123 void PagingLandScapeMeshDecal::CreateGeometry( )
{
Matrix4 xlate;
if( mParentNode )
getWorldTransforms( &xlate );
else
xlate = Matrix4::IDENTITY;
Matrix4 invXlate = xlate.inverse( );
// Deterimine approximate size of vertex data from query.
// Get the scale.
Real scaleX;
Real scaleZ;
sceneMgr_->getOption( "ScaleX", &scaleX );
sceneMgr_->getOption( "ScaleZ", &scaleZ );
const AxisAlignedBox& box = getWorldBoundingBox( true );
subSections_.clear( );
subExtents_.clear( );
height_ = 0;
width_ = 0;
AABBquery_->setBox( box );
AABBquery_->execute( this );
if( !height_ || !width_ )
return;
//only continue if it's dirty
if ( !mDirty ) {
return;
}
//make a copy of the subextends for lookup
mOldSubExtents = subExtents_;
mDirty = false;
Real xOffset = -size_.x / 2;
Real zOffset = -size_.y / 2;
// Create vertex data structure for 4 vertices shared between submeshes
VertexData* vertexData = renderOp_.vertexData;
// Allocate vertex buffer of the requested number of vertices ( vertexCount )
// and bytes per vertex ( offset )
HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton( ).
createVertexBuffer( declSize_,
GetNumVertices( ),
HardwareBuffer::HBU_STATIC_WRITE_ONLY );
// HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE );
// Set vertex buffer binding so buffer 0 is bound to our vertex buffer
vertexData->vertexBufferBinding->setBinding( 0, vbuf );
Real minY = Math::POS_INFINITY;
Real maxY = Math::NEG_INFINITY;
float* buffer = ( float* )vbuf->lock( HardwareBuffer::HBL_DISCARD );
int vertexCount = 0;
SubSectionContainer::const_iterator it = subSections_.begin( );
SubSectionContainer::const_iterator itEnd = subSections_.end( );
for( ; it != itEnd; ++it )
{
VertexContainer::const_iterator vertIt = it->begin( );
VertexContainer::const_iterator vertItEnd = it->end( );
for( ; vertIt != vertItEnd; ++vertIt )
{
// Copy our vertices into the hardware buffer and calculate
// texture coords.
// TODO: Don't transform vertices that aren't included due to LoD.
Vector3 localVertex = invXlate * vertIt->vertex_; // Convert back to local coordinates.
*buffer++ = localVertex.x;
*buffer++ = localVertex.y;
*buffer++ = localVertex.z;
// Keep track of height bounds for final AABB.
if( localVertex.y < minY )
minY = localVertex.y;
if( localVertex.y > maxY )
maxY = localVertex.y;
// Calculate texture coordinates based on distances from the
// edges of our rectangle.
*buffer++ = ( localVertex.x - xOffset ) / size_.x;
*buffer++ = 1.0 - ( ( localVertex.z - zOffset ) / size_.y );
++vertexCount;
}
}
vbuf->unlock( );
vertexData->vertexCount = vertexCount;
// Create index data.
IndexData* indexData = renderOp_.indexData;
indexData->indexStart = 0;
size_t maxNumIndices = GetNumIndices( );
bool is32bits = maxNumIndices >= 0x10000;
// Allocate index buffer of the requested number of vertices ( ibufCount )
HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton( ).
createIndexBuffer( ( is32bits ) ? HardwareIndexBuffer::IT_32BIT : HardwareIndexBuffer::IT_16BIT,
maxNumIndices,
HardwareBuffer::HBU_STATIC_WRITE_ONLY );
if( is32bits )
indexData->indexCount = CreateIndices<uint>( ibuf );
else
indexData->indexCount = CreateIndices<ushort>( ibuf );
// Put the hardware index buffer into our render operation object.
indexData->indexBuffer = ibuf;
indexData->optimiseVertexCacheTriList( );
subSections_.clear( );
subExtents_.clear( );
AABB_.setMinimum( Vector3( -size_.x / 2, minY, -size_.y / 2 ) );
AABB_.setMaximum( Vector3( size_.x / 2, maxY, size_.y / 2 ) );
radius_ = std::max( size_.x / 2, size_.y / 2 );
radius_ = std::max( radius_, maxY );
}
240 size_t PagingLandScapeMeshDecal::GetNumVertices( ) const
{
size_t vertices = 0;
SubSectionContainer::const_iterator it = subSections_.begin( );
for( ; it != subSections_.end( ); ++it )
vertices += it->size( );
return vertices;
}
249 size_t PagingLandScapeMeshDecal::GetNumIndices( ) const
{
size_t indices = 0;
SubExtentContainer::const_iterator it = subExtents_.begin( );
for( ; it != subExtents_.end( ); ++it )
{
int step = 1 << it->renderLevel_;
indices += ( it->width_ / step ) * ( it->height_ / step ) * 6;
}
return indices;
}
template<class T>
262 int PagingLandScapeMeshDecal::CreateIndices( Ogre::HardwareIndexBufferSharedPtr ibuf )
{
T* indices = ( T* )ibuf->lock( HardwareBuffer::HBL_DISCARD );
int indexCount = 0;
int indexOffset = 0;
for( int z = 0; z < height_; ++z )
{
for( int x = 0; x < width_; ++x )
{
indexCount += MeshSubSection<T>( x, z, indices, indexOffset );
}
}
ibuf->unlock( );
return indexCount;
}
template<class T>
279 int PagingLandScapeMeshDecal::MeshSubSection( int x, int z, T*& indices, int& indexOffset )
{
int indexCount = 0;
int offset = indexOffset;
const SubExtent& extents = subExtents_[z * width_ + x];
int rl = extents.renderLevel_;
// Get render levels of neighbors so we can stitch them properly.
int northRL = z > 0 ? GetRenderLevel( x, z - 1 ) : rl;
int westRL = x > 0 ? GetRenderLevel( x - 1, z ) : rl;
int southRL = z < height_ - 1 ? GetRenderLevel( x, z + 1 ) : rl;
int eastRL = x < width_ - 1 ? GetRenderLevel( x + 1, z ) : rl;
// We only stitch if the neighbor's render level is greater than ours.
bool northStitch = northRL > rl;
bool westStitch = westRL > rl;
bool southStitch = southRL > rl;
bool eastStitch = eastRL > rl;
// Get extents.
int height = extents.height_;
int width = extents.width_;
int step = 1 << rl;
int lineStepOffset = width * step;
int iEnd = height - 1 - ( southStitch ? step : 0 );
int i = 0;
if( northStitch )
{
i = step;
offset += lineStepOffset;
}
for( ; i < iEnd; i += step )
{
int nextLineOffset = offset + lineStepOffset;
int jEnd = width - 1 - ( eastStitch ? step : 0 );
for( int j = westStitch ? step : 0; j < jEnd; j += step )
{
*indices++ = j + offset; // up-left
*indices++ = j + nextLineOffset; // low-left
*indices++ = j + step + offset; // up-right
*indices++ = j + step + offset; // up-right
*indices++ = j + nextLineOffset; // low-left
*indices++ = j + step + nextLineOffset; // low-right
indexCount += 6;
}
offset = nextLineOffset;
}
// Stich any sides that need stiching.
if( northStitch )
indexCount += StitchEdge( indices, extents, rl, northRL, true, true, westStitch, eastStitch, indexOffset );
if( westStitch )
indexCount += StitchEdge( indices, extents, rl, westRL, false, false, southStitch, northStitch, indexOffset );
if( southStitch )
indexCount += StitchEdge( indices, extents, rl, southRL, true, false, eastStitch, westStitch, indexOffset );
if( eastStitch )
indexCount += StitchEdge( indices, extents, rl, eastRL, false, true, northStitch, southStitch, indexOffset );
indexOffset += ( width * height );
return indexCount;
}
// Use the same stiching algorithm the landscape renderer does or
// the decal won't look right. TODO: At some point it would be nice
// to just use the actual code from the renderer, but it's made to
// work specifically with tiles, not sub-sections of tiles.
template<class T>
344 int PagingLandScapeMeshDecal::StitchEdge( T*& indices,
const SubExtent& extents,
const int hiLOD,
const int loLOD,
348 const bool horizontal,
349 const bool forward,
350 const bool omitFirstTri,
351 const bool omitLastTri,
const int indexOffset )
{
// Work out the steps ie how to increment indexes
// Step from one vertex to another in the high detail version
int step = 1 << hiLOD;
// Step from one vertex to another in the low detail version
int superstep = 1 << loLOD;
// Step half way between low detail steps
int halfsuperstep = superstep >> 1;
// Work out the starting points and sign of increments
// We always work the strip clockwise
int startx, startz, endx, rowstep;
if( horizontal )
{
if( forward )
{
startx = startz = 0;
endx = extents.width_ - 1;
rowstep = step;
}
else
{
startx = extents.width_ - 1;
startz = extents.height_ - 1;
endx = 0;
rowstep = -step;
step = -step;
superstep = -superstep;
halfsuperstep = -halfsuperstep;
}
}
else
{
if( forward )
{
startx = 0;
endx = extents.height_ - 1;
startz = extents.width_ - 1;
rowstep = -step;
}
else
{
startx = extents.height_ - 1;
endx = 0;
startz = 0;
rowstep = step;
step = -step;
superstep = -superstep;
halfsuperstep = -halfsuperstep;
}
}
int indexCount = 0;
IndexCalculator<T> calc( extents.width_, indexOffset );
for( int j = startx; j != endx; j += superstep )
{
int k;
for( k = 0; k != halfsuperstep; k += step )
{
int jk = j + k;
//skip the first bit of the corner?
if( j != startx || k != 0 || !omitFirstTri )
{
if( horizontal )
{
*indices++ = calc.GetIndex( j , startz );
*indices++ = calc.GetIndex( jk, startz + rowstep );
*indices++ = calc.GetIndex( jk + step, startz + rowstep );
}
else
{
*indices++ = calc.GetIndex( startz, j );
*indices++ = calc.GetIndex( startz + rowstep, jk );
*indices++ = calc.GetIndex( startz + rowstep, jk + step );
}
indexCount += 3;
}
}
// Middle tri
if( horizontal )
{
*indices++ = calc.GetIndex( j, startz );
*indices++ = calc.GetIndex( j + halfsuperstep, startz + rowstep );
*indices++ = calc.GetIndex( j + superstep, startz );
}
else
{
*indices++ = calc.GetIndex( startz, j );
*indices++ = calc.GetIndex( startz + rowstep, j + halfsuperstep );
*indices++ = calc.GetIndex( startz, j + superstep );
}
indexCount += 3;
for( k = halfsuperstep; k != superstep; k += step )
{
int jk = j + k;
if( j != endx - superstep || k != superstep - step || !omitLastTri )
{
if( horizontal )
{
*indices++ = calc.GetIndex( j + superstep, startz );
*indices++ = calc.GetIndex( jk, startz + rowstep );
*indices++ = calc.GetIndex( jk + step, startz + rowstep );
}
else
{
*indices++ = calc.GetIndex( startz, j + superstep );
*indices++ = calc.GetIndex( startz + rowstep, jk );
*indices++ = calc.GetIndex( startz + rowstep, jk + step );
}
indexCount += 3;
}
}
}
return indexCount;
}
// From Ogre::MovableObject
472 void PagingLandScapeMeshDecal::_updateRenderQueue( RenderQueue* queue )
{
queue->addRenderable( this, mRenderQueueID, OGRE_RENDERABLE_DEFAULT_PRIORITY + 1 );
}
// From Ogre::Renderable
478 void PagingLandScapeMeshDecal::getRenderOperation( Ogre::RenderOperation& op )
{
// Update our RenderOperation if necessary.
const Vector3& position = mParentNode->getWorldPosition( );
const Quaternion& orientation = mParentNode->getOrientation( );
if( position != position_ ||
orientation != orientation_ )
{
position_ = position;
orientation_ = orientation;
//force a full geometry rebuild
mDirty = true;
}
//calling this every frame will only trigger a full rebuild when the LOD has changed
CreateGeometry( );
op = renderOp_;
}
496 void PagingLandScapeMeshDecal::getWorldTransforms( Ogre::Matrix4* xform ) const
{
*xform = mParentNode->_getFullTransform( );
}
501 const Quaternion& PagingLandScapeMeshDecal::getWorldOrientation( ) const
{
return mParentNode->_getDerivedOrientation( );
}
506 const Vector3& PagingLandScapeMeshDecal::getWorldPosition( ) const
{
return mParentNode->getWorldPosition( );
}
511 Real PagingLandScapeMeshDecal::getSquaredViewDepth( const Camera* cam ) const
{
return ( getWorldPosition( ) - cam->getDerivedPosition( ) ).squaredLength( );
}
// Receive terrain vertices from our query.
517 bool PagingLandScapeMeshDecal::queryResult( SceneQuery::WorldFragment* fragment )
{
if( fragment->fragmentType != SceneQuery::WFT_CUSTOM_GEOMETRY )
{
OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR,
"SceneQuery flags invalid.",
"PagingLandScapeMeshDecal::queryResult" );
}
CustomQueryResult* result = reinterpret_cast<CustomQueryResult*>( fragment->geometry );
switch( result->type_ )
{
case CustomQueryResult::QUERY_EXTENTS_TYPE:
{
// Reserve space for our sub-sections.
width_ = result->data_.queryExtents_.width_;
height_ = result->data_.queryExtents_.height_;
subSections_.resize( width_ * height_ );
subExtents_.resize( width_ * height_ );
break;
}
case CustomQueryResult::SUBSECTION_EXTENTS_TYPE:
{
currentSubX_ = result->data_.subExtents_.subX_;
currentSubZ_ = result->data_.subExtents_.subZ_;
int offset = currentSubX_ + currentSubZ_ * width_;
SubExtent& subExtent = subExtents_[offset];
subExtent.width_ = result->data_.subExtents_.width_;
subExtent.height_ = result->data_.subExtents_.height_;
subExtent.renderLevel_ = result->data_.subExtents_.renderLevel_;
// TODO: Optimize! We wouldn't need an intermediate array at all
// if the scene query gave us all the sub-section extents up front
// so we could allocate the correct size fo the vertex buffer. It's
// a bit tricky in the scene query, so leaving it this way for now.
// Another option could be to overallocate the vertex buffer assuming
// that each sub-section was the full tile size, but that's also
// pretty wasteful ( though possibly faster, since no heap allocation ).
subSections_[offset].reserve( subExtent.width_ * subExtent.height_ );
//compare with earlier result and see if any LOD has changed
if ( !mDirty ) {
if ( mOldSubExtents.size( ) >= offset ) {
SubExtent& oldSubExtent = mOldSubExtents[offset];
if ( oldSubExtent.renderLevel_ != subExtent.renderLevel_ ) {
mDirty = true;
}
} else {
mDirty = true;
}
}
break;
}
case CustomQueryResult::VERTEX_TYPE:
{
VertexContainer& subSection = subSections_[currentSubX_ + currentSubZ_ * width_];
Vertex vertex( result->data_.vertexData_.x_,
result->data_.vertexData_.y_,
result->data_.vertexData_.z_,
result->data_.vertexData_.included_ );
subSection.push_back( vertex );
break;
}
default:
OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR,
"Result type invalid.",
"PagingLandScapeMeshDecal::queryResult" );
}
return true;
}
//-----------------------------------------------------------------------
String PagingLandScapeMeshDecalFactory::FACTORY_TYPE_NAME = "PagingLandScapeMeshDecal";
#if 0
//-----------------------------------------------------------------------
595 PagingLandScapeMeshDecal* PagingLandScapeMeshDecalFactory::create( SceneManager& sceneMgr,
596 const String& name,
597 const String& materialName,
598 const Vector2& size,
599 const String& sceneMgrInstance )
{
NameValuePairList params;
params["materialName"] = materialName;
params["width"] = StringConverter::toString( size.x );
params["height"] = StringConverter::toString( size.y );
params["sceneMgrInstance"] = sceneMgrInstance;
return static_cast<PagingLandScapeMeshDecal*>(
sceneMgr.createMovableObject( name,
PagingLandScapeMeshDecalFactory::FACTORY_TYPE_NAME,
¶ms ) );
}
#endif
//-----------------------------------------------------------------------
614 const String& PagingLandScapeMeshDecalFactory::getType( void ) const
{
return FACTORY_TYPE_NAME;
}
//-----------------------------------------------------------------------
619 MovableObject* PagingLandScapeMeshDecalFactory::createInstanceImpl
(
621 const String& name,
622 const NameValuePairList* params
)
{
String materialName;
Real width = 0.0;
Real height = 0.0;
String sceneMgrInstance;
if( params != 0 )
{
NameValuePairList::const_iterator it = params->find( "materialName" );
if( it != params->end( ) )
{
materialName = it->second;
}
it = params->find( "width" );
if( it != params->end( ) )
{
width = StringConverter::parseReal( it->second );
}
it = params->find( "height" );
if( it != params->end( ) )
{
height = StringConverter::parseReal( it->second );
}
it = params->find( "sceneMgrInstance" );
if( it != params->end( ) )
{
sceneMgrInstance = it->second;
}
}
return new PagingLandScapeMeshDecal( name, materialName, Vector2( width, height ), sceneMgrInstance );
}
//-----------------------------------------------------------------------
656 void PagingLandScapeMeshDecalFactory::destroyInstance( MovableObject* obj )
{
delete obj;
}
1
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "Ogre.h"
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeOctreeCamera.h"
#include "OgrePagingLandScapeOctree.h"
#include "OgrePagingLandScapeOctreeNode.h"
#include "OgrePagingLandScapeOcclusion.h"
#include "OgrePagingLandScapeOcclusionElement.h"
#include "OgrePagingLandScapeOcclusionSorter.h"
#include "OgrePagingLandScapeOcclusionVisibilityData.h"
#include "OgrePagingLandScapeOcclusionTraversal.h"
#include "OgrePagingLandScapeOcclusionCHCTraversal.h"
#include "OgrePagingLandScapeOcclusionSWTraversal.h"
#include "OgrePagingLandScapeOcclusionVFTraversal.h"
#include "OgrePagingLandScapeOcclusionDebugTraversal.h"
#include "OgrePagingLandScapeOcclusionQuerySet.h"
#include "OgreOcclusionBoundingBox.h"
namespace Ogre
{
//-----------------------------------------------------------------------
31 Occlusion::Occlusion( unsigned int visibilityThsd ):
mCurrentCam( 0 ),
mVisibilityTreshold( visibilityThsd ),
mIsQueryPoolNotInitiated( true ),
mFrameConservativeVisibility ( 300 )
{
};
//-----------------------------------------------------------------------
39 bool Occlusion::nextFrame( PagingLandScapeOctreeCamera *cam,
40 MovableObjectList *camInProgressVisibles,
41 bool onlyshadowcaster,
42 RenderQueue *q )
{
bool newframe = true;
mCurrentRenderQueue = q;
mOnlyShadowCaster = onlyshadowcaster;
if ( cam != mCurrentCam )
{
mCurrentCam = cam;
}
if ( mCurrentCam->nextFrame( Root::getSingleton( ).getCurrentFrameNumber ( ) ) )
{
// change frame Id counter
//that identify current frame.
mFrameId = mCurrentCam->getFrameId( );
newframe = true;
}
if ( newframe )
{
camInProgressVisibles->clear( );
#ifdef _VISIBILITYDEBUG
// reset counters.
triangle_cnt = 0;
traversed_nodes_cnt = 0;
frustum_culled_nodes_cnt = 0;
query_cnt = 0;
object_cnt = 0;
#endif //_VISIBILITYDEBUG
return true;
}
return false;
}
//-----------------------------------------------------------------------
77 void Occlusion::queueDraw( PagingLandScapeOctreeNode& n )
{
#ifdef _VISIBILITYDEBUG
object_cnt++;
#endif //_VISIBILITYDEBUG
VisibilityData * const vis = n.getNodeData ( mCurrentCam );
if ( !vis->notified )
{
// notify objects handled by this node
n.notifyNodeObjects ( mCurrentCam, mOnlyShadowCaster );
}
// as it's visible add its attached objects to render queue.
// note that we know it already has been notified by camera,
// when we issued query.
n._addAlreadyNotifiedToVisibles ( );
// now it had been drawn, notified should be false.
vis->notified = false;
vis->frameID = mFrameId;
}
//-----------------------------------------------------------------------
99 bool Occlusion::issueDrawQuery( PagingLandScapeOctreeNode& n )
{
VisibilityData * const vis = n.getNodeData ( mCurrentCam );
#ifdef _VISIBILITYDEBUG
query_cnt++;
traversed_nodes_cnt++;
assert ( vis->viewFrustumVisible );
#endif //_VISIBILITYDEBUG
assert ( vis->frameID != mFrameId ) ;
assert ( vis->query == 0 );
assert ( n.isOccluder( ) );
MovableObjectList *moToRender = n.getVisibleNotifiedNodeObjects( mCurrentCam, mOnlyShadowCaster );
// Mark that Node already notified by this frame/cam combination
vis->frameID = mFrameId;
vis->notified = true;
if ( !moToRender->empty( ) )
{
HardwareOcclusionQuery *query = mQueryPool.getPoolable( );
vis->query = query;
// create the render Queue.
MovableObjectList::iterator it = moToRender->begin( ), itend = moToRender->end( );
while ( it != itend )
{
( *it )->_updateRenderQueue( &*mCurrentRenderQueue );
++it;
}
// draw and query.
query->beginOcclusionQuery ( );
mScnMngr->directRenderSingleQueue ( &*mCurrentRenderQueue );
query->endOcclusionQuery ( );
moToRender->clear( );
return true;
}
return false;
}
//-----------------------------------------------------------------------
144 void Occlusion::issueBboxQuery( OcclusionElement& n )
{
#ifdef _VISIBILITYDEBUG
query_cnt++;
#endif //_VISIBILITYDEBUG
VisibilityData * const vis = n.getNodeData ( mCurrentCam );
assert ( vis->query == 0 );
HardwareOcclusionQuery *query = mQueryPool.getPoolable( );
vis->query = query;
query->beginOcclusionQuery( );
// render bounding box for object
mScnMngr->directRenderSingleObject( n.getOcclusionBoundingBox( ) );
query->endOcclusionQuery( );
//mScnMngr->addVisible ( n.getOcclusionBoundingBox( ) );
}
//-----------------------------------------------------------------------
163 bool Occlusion::isQueryResultIsVisible( OcclusionElement& node )
{
// check visibility result
unsigned int visiblePixels = 0;
//this one wait if result not available
VisibilityData * const vis = node.getNodeData ( mCurrentCam );
vis->query->pullOcclusionQuery ( &visiblePixels );
mQueryPool.removePoolable ( vis->query );
vis->query = 0;
if ( visiblePixels > mVisibilityTreshold )
{
return true;
}
return false;
}
//-----------------------------------------------------------------------
181 void Occlusion::pullUpVisibility( OcclusionElement& node )
{
OcclusionElement* n = &node;
VisibilityData *vis = n->getNodeData ( mCurrentCam );
while ( !vis->queryVisible )
{
vis->queryVisible = true;
n = n->getParent( );
if ( 0 == n )
return;
vis = n->getNodeData ( mCurrentCam );
}
}
//-----------------------------------------------------------------------
196 bool Occlusion::insideViewFrustum( OcclusionElement& n )
{
const bool result = mCurrentCam->isVisible ( n.getCullBoundingBox ( ) );
#ifdef _VISIBILITYDEBUG
if ( result )
{
n.getNodeData ( mCurrentCam )->viewFrustumVisible = true;
}
else
{
n.getNodeData ( mCurrentCam )->viewFrustumVisible = false;
frustum_culled_nodes_cnt++;
}
#endif
return result;
}
//-----------------------------------------------------------------------
//this is the algorithm from the paper
216 void Occlusion::CHCtraversal( PagingLandScapeOctree *octree, VisibleObjectsBoundsInfo * const visibleBounds )
{
if ( mIsQueryPoolNotInitiated )
initQueryPool ( );
const unsigned int visibilityTreshold = mVisibilityTreshold;
const Vector3 &camPos = mCurrentCam->getDerivedPosition( );
FrontToBackNodeSorterPriorityQueue traversalStack = FrontToBackNodeSorterPriorityQueue( FrontToBackNodeSorterOperator ( camPos ) );
//draw leaves, stack otherwise
CHCTraversal toStackTraversal( traversalStack, *this );
const unsigned int frameId = mFrameId;
const unsigned int lastframeId = mFrameId - 1;
// first Octree
traversalStack.push ( octree );
while ( !traversalStack.empty( ) || !m_queryQueue.empty( ) )
{
//first part
// get previous frame occlusion results
while ( traversalStack.empty( ) &&
!m_queryQueue.empty( ) &&
!m_queryQueue.front( )->getNodeData ( mCurrentCam )->query->isStillOutstanding( ) )
{
OcclusionElement& node = *( m_queryQueue.front( ) );
m_queryQueue.pop( );
VisibilityData * const vis = node.getNodeData ( mCurrentCam );
// should be already frustum culled and flagged as not visible
assert ( vis->lastQueryFrameId == frameId );
assert ( !vis->queryVisible );
#ifdef _VISIBILITYDEBUG
assert ( vis->viewFrustumVisible );
#endif //_VISIBILITYDEBUG
// check visibility result
unsigned int visiblePixels = 0;
//this one wait if result not available
vis->query->pullOcclusionQuery( &visiblePixels );
mQueryPool.removePoolable( vis->query );
vis->query = 0;
if( visiblePixels > visibilityTreshold )
{
pullUpVisibility ( node );
// Traverse for sure this visible node
// And therefore check children
node.traversal ( toStackTraversal, visibleBounds );
//node.traversal ( toStackTraversal, 0 );
}
}
//2nd part
// query visible objects
while ( !traversalStack.empty( ) )
{
OcclusionElement& node = *traversalStack.top ( );
traversalStack.pop ( );
// make sure there's no loop of some sort.
// as we must query a node only once
assert ( frameId != node.getNodeData ( mCurrentCam )->lastQueryFrameId );
if ( insideViewFrustum ( node ) )
{
VisibilityData * const vis = node.getNodeData ( mCurrentCam );
// identify visible in the last frame nodes
const bool wasVisible = vis->queryVisible &&
lastframeId == vis->lastQueryFrameId;
if ( node.isLeaf( ) )
{
if ( wasVisible && node.isOccluder( ) )
{
// Draw & query at the same time previously visible nodes
if ( issueDrawQuery ( static_cast <PagingLandScapeOctreeNode &> ( node ) ) )
{
m_queryQueue.push ( &node );
}
else
{
// skip testing previously visible node
// that is not visible when notified.
// make next frame get here again,
// saving a box query
vis->queryVisible = true;
vis->lastQueryFrameId = frameId;
continue;
}
}
else
{
issueBboxQuery ( node );
m_queryQueue.push ( &node );
}
}
else
{
if ( wasVisible )
{
// skip testing previously visible node
// ( interior nodes in hierarchy )
node.traversal ( toStackTraversal, visibleBounds );
//node.traversal ( toStackTraversal, 0 );
}
else
{
// only query node that wasn't visible last frame
issueBboxQuery ( node );
m_queryQueue.push ( &node );
}
}
// reset this node's visibility to false
// Will be updated by results queries that will pull up results.
// by children that will be flagged visible and will transmit info
// to their parent nodes ( pullUpVisibility( ) )
vis->queryVisible = false;
// update node's visited flag to make sure we won't visit 2 times
// and to "tick" the visible info.
vis->lastQueryFrameId = frameId;
}
}
}
}
//-----------------------------------------------------------------------
//this is the algorithm from the paper, conservative way.
340 void Occlusion::CHCtraversalConservative( PagingLandScapeOctree *octree, VisibleObjectsBoundsInfo * const visibleBounds )
{
const unsigned int frameConservativeVisibility = mFrameConservativeVisibility;
const unsigned int visibilityTreshold = mVisibilityTreshold;
if ( mIsQueryPoolNotInitiated )
initQueryPool ( );
const Vector3 &camPos = mCurrentCam->getDerivedPosition( );
FrontToBackNodeSorterPriorityQueue traversalStack = FrontToBackNodeSorterPriorityQueue( FrontToBackNodeSorterOperator ( camPos ) );
//draw leaves, stack otherwise
CHCTraversal toStackTraversal( traversalStack, *this );
const unsigned int frameId = mFrameId;
const unsigned int lastframeId = mFrameId - 1;
// first Octree
traversalStack.push ( octree );
while ( !traversalStack.empty( ) || !m_queryQueue.empty( ) )
{
//first part
// get previous frame occlusion results
while ( traversalStack.empty( ) &&
!m_queryQueue.empty( ) &&
!m_queryQueue.front( )->getNodeData ( mCurrentCam )->query->isStillOutstanding( ) )
{
OcclusionElement& node = *( m_queryQueue.front( ) );
m_queryQueue.pop( );
VisibilityData * const vis = node.getNodeData ( mCurrentCam );
// should be already frustum culled and flagged as not visible
assert ( vis->lastQueryFrameId == frameId );
assert ( !vis->queryVisible );
#ifdef _VISIBILITYDEBUG
assert ( vis->viewFrustumVisible );
#endif //_VISIBILITYDEBUG
// check visibility result
unsigned int visiblePixels = 0;
//this one wait if result not available
vis->query->pullOcclusionQuery( &visiblePixels );
mQueryPool.removePoolable( vis->query );
vis->query = 0;
if( visiblePixels > visibilityTreshold )
{
pullUpVisibility ( node );
// Traverse for sure this visible node
// And therefore check children
node.traversal ( toStackTraversal, visibleBounds );
//node.traversal ( toStackTraversal, 0 );
}
}
//2nd part
// query visible objects
while ( !traversalStack.empty( ) )
{
OcclusionElement& node = *traversalStack.top ( );
traversalStack.pop ( );
// make sure there's no loop of some sort.
// as we must query a node only once
assert ( frameId != node.getNodeData ( mCurrentCam )->lastQueryFrameId );
if ( insideViewFrustum ( node ) )
{
VisibilityData * const vis = node.getNodeData ( mCurrentCam );
// identify visible in the last frame nodes
const bool wasVisible = vis->queryVisible;
const bool wasVisibleandQueriedBeforeLastNFrame = wasVisible
&& lastframeId - frameConservativeVisibility < vis->lastQueryFrameId;
if ( wasVisibleandQueriedBeforeLastNFrame )
{
if ( node.isLeaf( ) && node.isOccluder( ) )
{
MovableObjectList *moToRender = static_cast <PagingLandScapeOctreeNode *> ( &node )->getVisibleNotifiedNodeObjects( mCurrentCam, mOnlyShadowCaster );
// create the render Queue.
if ( !moToRender->empty( ) )
{
MovableObjectList::iterator it = moToRender->begin( ),
itend = moToRender->end( );
while ( it != itend )
{
( *it )->_updateRenderQueue ( &*mCurrentRenderQueue );
++it;
}
mScnMngr->directRenderSingleQueue ( &*mCurrentRenderQueue );
}
vis->notified = true;
}
pullUpVisibility ( node );
node.traversal ( toStackTraversal, visibleBounds );
//node.traversal ( toStackTraversal, 0 );
}
else
{
const bool wasVisibleandQueriedExacltyLastNFrame = wasVisible &&
lastframeId - frameConservativeVisibility == vis->lastQueryFrameId;
if ( node.isLeaf( ) )
{
if ( wasVisibleandQueriedExacltyLastNFrame && node.isOccluder( ) )
{
// Draw & query at the same time previously visible nodes
if ( issueDrawQuery ( static_cast <PagingLandScapeOctreeNode &> ( node ) ) )
{
m_queryQueue.push ( &node );
}
else
{
// skip testing previously visible node
// that is not visible when notified.
// make next frame get here again,
// saving a box query
vis->queryVisible = true;
vis->lastQueryFrameId = frameId;
continue;
}
}
else
{
issueBboxQuery ( node );
m_queryQueue.push ( &node );
}
}
else
{
if ( wasVisibleandQueriedExacltyLastNFrame )
{
// skip testing previously visible node
// ( interior nodes in hierarchy )
node.traversal ( toStackTraversal, visibleBounds );
//node.traversal ( toStackTraversal, 0 );
}
else
{
// only query node that wasn't visible last frame
issueBboxQuery ( node );
m_queryQueue.push ( &node );
}
}
// reset this node's visibility to false
// Will be updated by results queries that will pull up results.
// by children that will be flagged visible and will transmit info
// to their parent nodes ( pullUpVisibility( ) )
vis->queryVisible = false;
// update node's visited flag to make sure we won't visit 2 times
// and to "tick" the visible info.
vis->lastQueryFrameId = frameId;
}
}
}
}
}
}
1
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgrePagingLandScapeOctreeCamera.h"
#include "OgrePagingLandScapeOctree.h"
#include "OgrePagingLandScapeOctreeNode.h"
#include "OgrePagingLandScapeOcclusionElement.h"
#include "OgrePagingLandScapeOcclusion.h"
#include "OgrePagingLandScapeOcclusionSorter.h"
#include "OgrePagingLandScapeOcclusionTraversal.h"
#include "OgrePagingLandScapeOcclusionCHCTraversal.h"
#include "OgrePagingLandScapeOcclusionVisibilityData.h"
namespace Ogre
{
//-----------------------------------------------------------------------
19 void CHCTraversal::onTree( PagingLandScapeOctree& node, VisibleObjectsBoundsInfo * const visibleBounds ) const
{
#ifdef _VISIBILITYDEBUG
assert ( node.getNodeData ( occlusion.mCurrentCam )->viewFrustumVisible );
occlusion.traversed_nodes_cnt++;
#endif //_VISIBILITYDEBUG
if ( !node.mNodes.empty( ) )
{
PagingLandScapeOctreeNodeList::iterator it = node.mNodes.begin( );
while ( it != node.mNodes.end( ) )
{
stack.push ( *it );
++it;
}
}
PagingLandScapeOctree *n =
node.mChildren[ 0 ][ 0 ][ 0 ];
if ( n && n->hasChildren( ) )
stack.push( n );
n = node.mChildren[ 1 ][ 0 ][ 0 ];
if ( n && n->hasChildren( ) )
stack.push( n );
n = node.mChildren[ 0 ][ 1 ][ 0 ];
if ( n && n->hasChildren( ) )
stack.push( n );
n = node.mChildren[ 1 ][ 1 ][ 0 ];
if ( n && n->hasChildren( ) )
stack.push( n );
n = node.mChildren[ 0 ][ 0 ][ 1 ];
if ( n && n->hasChildren( ) )
stack.push( n );
n = node.mChildren[ 1 ][ 0 ][ 1 ];
if ( n && n->hasChildren( ) )
stack.push( n );
n = node.mChildren[ 0 ][ 1 ][ 1 ];
if ( n && n->hasChildren( ) )
stack.push( n );
n = node.mChildren[ 1 ][ 1 ][ 1 ];
if ( n && n->hasChildren( ) )
stack.push( n );
}
//-----------------------------------------------------------------------
63 void CHCTraversal::onLeaf( PagingLandScapeOctreeNode& n, VisibleObjectsBoundsInfo * const visibleBounds ) const
{
#ifdef _VISIBILITYDEBUG
assert ( n.getNodeData ( occlusion.mCurrentCam )->viewFrustumVisible );
assert ( n.getNodeData ( occlusion.mCurrentCam )->queryVisible );
occlusion.traversed_nodes_cnt++;
#endif //_VISIBILITYDEBUG
if ( !n.isOccluder( ) || mIsNotSolidScene )
occlusion.queueDraw ( n );
}
//-----------------------------------------------------------------------
74 CHCTraversal::CHCTraversal( FrontToBackNodeSorterPriorityQueue& vStack, Occlusion& o ):
stack( vStack ),
occlusion( o ),
frameId( o.getFrame( ) ),
mIsNotSolidScene( occlusion.isNotSolidScene( ) )
{
}
}
1
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgrePagingLandScapeOcclusionTraversal.h"
#include "OgrePagingLandScapeOctreeCamera.h"
#include "OgrePagingLandScapeOctree.h"
#include "OgrePagingLandScapeOctreeNode.h"
#include "OgrePagingLandScapeOcclusionElement.h"
#include "OgrePagingLandScapeOcclusion.h"
#include "OgrePagingLandScapeOcclusionTraversal.h"
#include "OgrePagingLandScapeOcclusionCameraTraversal.h"
namespace Ogre
{
//-----------------------------------------------------------------------
18 void RegisterCameraTraversal::onTree( PagingLandScapeOctree& n, VisibleObjectsBoundsInfo * const visibleBounds ) const
{
n.addCamNodeData ( cam );
traverseChildren ( n, visibleBounds );
}
//-----------------------------------------------------------------------
24 void RegisterCameraTraversal::onLeaf( PagingLandScapeOctreeNode& n, VisibleObjectsBoundsInfo * const visibleBounds ) const
{
n.addCamNodeData ( cam );
}
//-----------------------------------------------------------------------
29 void UnregisterCameraTraversal::onTree( PagingLandScapeOctree& n, VisibleObjectsBoundsInfo * const visibleBounds ) const
{
n.removeCamNodeData ( cam );
traverseChildren ( n, visibleBounds );
}
//-----------------------------------------------------------------------
35 void UnregisterCameraTraversal::onLeaf( PagingLandScapeOctreeNode& n, VisibleObjectsBoundsInfo * const visibleBounds ) const
{
n.removeCamNodeData ( cam );
}
}
1
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeOctreeCamera.h"
#include "OgrePagingLandScapeOctree.h"
#include "OgrePagingLandScapeOctreeNode.h"
#include "OgrePagingLandScapeOcclusionElement.h"
#include "OgrePagingLandScapeOcclusion.h"
#include "OgrePagingLandScapeOcclusionVisibilityData.h"
#include "OgrePagingLandScapeOcclusionTraversal.h"
#include "OgrePagingLandScapeOcclusionDebugTraversal.h"
#include "OgreDebugRectangle2D.h"
#ifdef _VISIBILITYDEBUG
namespace Ogre
{
// Debug Info
//
//-----------------------------------------------------------------------
24 TreeOverlayDebug::TreeOverlayDebug( Occlusion& o, PagingLandScapeOctreeSceneManager *scnMgr ):
occlusion( o ),
mScnMrg ( scnMgr )
{
}
//-----------------------------------------------------------------------
30 void TreeOverlayDebug::onTree( PagingLandScapeOctree& n, VisibleObjectsBoundsInfo * const visibleBounds ) const
{
SimpleRenderable * const s = n.getRectangle2d( mScnMrg );
if ( n.getNodeData ( occlusion.mCurrentCam )->viewFrustumVisible )
{
if ( n.getNodeData ( occlusion.mCurrentCam )->queryVisible )
{
s->setMaterial ( "BaseWhiteNoLightNoDepthCheck" );
occlusion.mCurrentRenderQueue->addRenderable ( s, s->getRenderQueueGroup ( ) );
traverseChildren ( n, visibleBounds );
}
else
{
s->setMaterial ( "BaseRedNoLightNoDepthCheck" );
occlusion.mCurrentRenderQueue->addRenderable ( s, s->getRenderQueueGroup ( ) );
}
}
else
{
s->setMaterial ( "BaseGreenNoLightNoDepthCheck" );
occlusion.mCurrentRenderQueue->addRenderable ( s, s->getRenderQueueGroup ( ) );
}
}
//-----------------------------------------------------------------------
55 void TreeOverlayDebug::onLeaf( PagingLandScapeOctreeNode& n, VisibleObjectsBoundsInfo * const visibleBounds ) const
{
SimpleRenderable * const s = n.getRectangle2d( mScnMrg );
if( n.getNodeData ( occlusion.mCurrentCam )->viewFrustumVisible )
{
if( n.getNodeData ( occlusion.mCurrentCam )->queryVisible )
{
s->setMaterial ( "BaseWhiteNoLightNoDepthCheck" );
occlusion.mCurrentRenderQueue->addRenderable( s, s->getRenderQueueGroup ( ) );
}
else
{
s->setMaterial ( "BaseRedNoLightNoDepthCheck" );
occlusion.mCurrentRenderQueue->addRenderable( s, s->getRenderQueueGroup ( ) );
}
}
else
{
s->setMaterial ( "BaseGreenNoLightNoDepthCheck" );
occlusion.mCurrentRenderQueue->addRenderable( s, s->getRenderQueueGroup ( ) );
}
}
}
#endif //_VISIBILITYDEBUG
1
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include <stack>
#include <queue>
#include "OgrePagingLandScapeOcclusionElement.h"
#include "OgrePagingLandScapePrerequisites.h"
#include "OgrePagingLandScapeOctreeCamera.h"
#include "OgrePagingLandScapeOcclusionVisibilityData.h"
#include "OgreDebugRectangle2D.h"
namespace Ogre
{
//---------------------------------------------------------------------
18 OcclusionElement::OcclusionElement( ) :
#ifdef _VISIBILITYDEBUG
mDebugRectangle2d( 0 ),
#endif //_VISIBILITYDEBUG
mIsRegisteredToCam ( false )
{
}
//---------------------------------------------------------------------
26 OcclusionElement::~OcclusionElement( )
{
#ifdef _VISIBILITYDEBUG
delete mDebugRectangle2d;
#endif //_VISIBILITYDEBUG
NodeDataPerCamMapiterator i = nodeDataPerCam.begin ( );
while ( i != nodeDataPerCam.end( ) )
{
delete i->second;
++i;
}
nodeDataPerCam.clear( );
}
//---------------------------------------------------------------------
41 VisibilityData *OcclusionElement::getNodeData( PagingLandScapeOctreeCamera *cam )
{
if ( nodeDataPerCam.find( cam->getId( ) ) == nodeDataPerCam.end( ) )
nodeDataPerCam[cam->getId( )] = new VisibilityData( );
//assert ( nodeDataPerCam.find( cam->getId( ) ) != nodeDataPerCam.end( ) );
return nodeDataPerCam[cam->getId( )];
}
//---------------------------------------------------------------------
49 void OcclusionElement::addCamNodeData ( PagingLandScapeOctreeCamera *cam )
{
if ( nodeDataPerCam.find( cam->getId( ) ) == nodeDataPerCam.end( ) )
nodeDataPerCam[cam->getId( )] = new VisibilityData( );
}
//---------------------------------------------------------------------
55 void OcclusionElement::removeCamNodeData ( PagingLandScapeOctreeCamera *cam )
{
NodeDataPerCamMapiterator i = nodeDataPerCam.find ( cam->getId( ) );
if ( i != nodeDataPerCam.end( ) )
{
delete i->second;
nodeDataPerCam.erase ( i );
}
}
#ifdef _VISIBILITYDEBUG
//---------------------------------------------------------------------
66 DebugRectangle2D *OcclusionElement::getRectangle2d( SceneManager *scnMgr )
{
if ( !mDebugRectangle2d )
{
mDebugRectangle2d = new DebugRectangle2D( );
//scnMgr->getRootSceneNode ( )->createChildSceneNode ( )->attachObject ( mDebugRectangle2d );
}
return mDebugRectangle2d;
}
#endif //_VISIBILITYDEBUG
}//namespace Ogre
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright ( c ) 2000-2005 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
#include "Ogre.h"
#include "OgrePagingLandScapeOcclusionQuerySet.h"
#include "OgreHardwareOcclusionQuery.h"
namespace Ogre
{
}
1
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgrePagingLandScapeOcclusionTraversal.h"
#include "OgrePagingLandScapeOcclusionSWTraversal.h"
#include "OgrePagingLandScapeOctreeCamera.h"
#include "OgrePagingLandScapeOctree.h"
#include "OgrePagingLandScapeOctreeNode.h"
#include "OgrePagingLandScapeOcclusionSorter.h"
#include "OgrePagingLandScapeOcclusionElement.h"
#include "OgrePagingLandScapeOcclusion.h"
#include "OgrePagingLandScapeOcclusionVisibilityData.h"
namespace Ogre
{
//-----------------------------------------------------------------------
19 SWTraversal::SWTraversal ( Occlusion& o ):
occlusion( o ),
mCurrentVisibility ( PagingLandScapeOctreeCamera::NONE ),
camPos( occlusion.mCurrentCam->getDerivedPosition ( ) )
{
}
//-----------------------------------------------------------------------
27 void SWTraversal::traverseChildren( PagingLandScapeOctree & node, VisibleObjectsBoundsInfo * const visibleBounds )
{
FrontToBackNodeSorterPriorityQueue myStack = FrontToBackNodeSorterPriorityQueue( FrontToBackNodeSorterOperator ( camPos ) );
//assert ( node.getNodeData ( occlusion.mCurrentCam )->viewFrustumVisible );
if ( !node.mNodes.empty( ) )
{
PagingLandScapeOctreeNodeList::const_iterator it = node.mNodes.begin( );
while ( it != node.mNodes.end( ) )
{
myStack.push( *it );
++it;
}
}
PagingLandScapeOctree *n =
node.mChildren[ 0 ][ 0 ][ 0 ];
if ( n && n->hasChildren( ) )
myStack.push ( n );
n = node.mChildren[ 1 ][ 0 ][ 0 ];
if ( n && n->hasChildren( ) )
myStack.push ( n );
n = node.mChildren[ 0 ][ 1 ][ 0 ];
if ( n && n->hasChildren( ) )
myStack.push ( n );
n = node.mChildren[ 1 ][ 1 ][ 0 ];
if ( n && n->hasChildren( ) )
myStack.push ( n );
n = node.mChildren[ 0 ][ 0 ][ 1 ];
if ( n && n->hasChildren( ) )
myStack.push ( n );
n = node.mChildren[ 1 ][ 0 ][ 1 ];
if ( n && n->hasChildren( ) )
myStack.push ( n );
n = node.mChildren[ 0 ][ 1 ][ 1 ];
if ( n && n->hasChildren( ) )
myStack.push ( n );
n = node.mChildren[ 1 ][ 1 ][ 1 ];
if ( n && n->hasChildren( ) )
myStack.push ( n );
//traverse nearer child first
while ( !myStack.empty ( ) )
{
OcclusionElement& nstacked = *myStack.top ( );
myStack.pop ( );
nstacked.traversal( *this, visibleBounds );
}
}
//-----------------------------------------------------------------------
77 bool SWTraversal::isVisible( OcclusionElement & n )
{
// issue query
if ( n.isLeaf ( ) && n.isOccluder( ) )
{
if ( occlusion.issueDrawQuery ( static_cast <PagingLandScapeOctreeNode &> ( n ) ) )
{
// we just wait for result
return occlusion.isQueryResultIsVisible ( n );
}
else
{
return false;
}
}
else
{
occlusion.issueBboxQuery ( n );
// we just wait for result
return occlusion.isQueryResultIsVisible ( n );
}
}
//-----------------------------------------------------------------------
101 void SWTraversal::onLeaf( PagingLandScapeOctreeNode &n, VisibleObjectsBoundsInfo * const visibleBounds )
{
if( occlusion.mCurrentCam->isVisible ( n.getCullBoundingBox ( ) ) )
{
#ifdef _VISIBILITYDEBUG
occlusion.traversed_nodes_cnt++;
n.getNodeData ( occlusion.mCurrentCam )->viewFrustumVisible = true;
#endif //_VISIBILITYDEBUG
const bool isitVisible = isVisible ( n );
if ( isitVisible )
{
#ifdef _VISIBILITYDEBUG
occlusion.object_cnt++;
#endif //_VISIBILITYDEBUG
occlusion.queueDraw ( n );
}
#ifdef _VISIBILITYDEBUG
n.getNodeData ( occlusion.mCurrentCam )->queryVisible = isitVisible;
#endif //_VISIBILITYDEBUG
}
#ifdef _VISIBILITYDEBUG
else
{
occlusion.traversed_nodes_cnt++;
n.getNodeData ( occlusion.mCurrentCam )->viewFrustumVisible = false;
occlusion.frustum_culled_nodes_cnt++;
}
#endif //_VISIBILITYDEBUG
}
//-----------------------------------------------------------------------
135 void SWTraversal::onTree( PagingLandScapeOctree & n, VisibleObjectsBoundsInfo * const visibleBounds )
{
if( occlusion.mCurrentCam->isVisible( n.getCullBoundingBox ( ) ) )
{
#ifdef _VISIBILITYDEBUG
occlusion.traversed_nodes_cnt++;
n.getNodeData ( occlusion.mCurrentCam )->viewFrustumVisible = true;
#endif //_VISIBILITYDEBUG
const bool isitVisible = isVisible( n );
if ( isitVisible )
{
traverseChildren ( n, visibleBounds );
}
#ifdef _VISIBILITYDEBUG
n.getNodeData ( occlusion.mCurrentCam )->queryVisible = isitVisible;
#endif //_VISIBILITYDEBUG
}
#ifdef _VISIBILITYDEBUG
else
{
occlusion.traversed_nodes_cnt++;
n.getNodeData ( occlusion.mCurrentCam )->viewFrustumVisible = false;
occlusion.frustum_culled_nodes_cnt++;
}
#endif //_VISIBILITYDEBUG
}
}
1
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgrePagingLandScapeOcclusionTraversal.h"
#include "OgrePagingLandScapeOctreeCamera.h"
#include "OgrePagingLandScapeOctree.h"
#include "OgrePagingLandScapeOctreeNode.h"
#include "OgrePagingLandScapeOcclusionElement.h"
#include "OgrePagingLandScapeOcclusion.h"
namespace Ogre
{
//-----------------------------------------------------------------------
15 void ConstTraversalConst::traverseChildren( const PagingLandScapeOctree& node, VisibleObjectsBoundsInfo * const visibleBounds ) const
{
if ( !node.mNodes.empty( ) )
{
//Add stuff to be rendered;
PagingLandScapeOctreeNodeList::const_iterator it = node.mNodes.begin( );
PagingLandScapeOctreeNodeList::const_iterator itEnd = node.mNodes.end( );
while ( it != itEnd )
{
( *it )->traversal ( *this, visibleBounds );
++it;
}
}
PagingLandScapeOctree *n =
node.mChildren[ 0 ][ 0 ][ 0 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 1 ][ 0 ][ 0 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 0 ][ 1 ][ 0 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 1 ][ 1 ][ 0 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 0 ][ 0 ][ 1 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 1 ][ 0 ][ 1 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 0 ][ 1 ][ 1 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 1 ][ 1 ][ 1 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
}
//-----------------------------------------------------------------------
57 void TraversalConst::traverseChildren( PagingLandScapeOctree& node, VisibleObjectsBoundsInfo * const visibleBounds ) const
{
if ( !node.mNodes.empty( ) )
{
//Add stuff to be rendered;
PagingLandScapeOctreeNodeList::iterator it = node.mNodes.begin( );
PagingLandScapeOctreeNodeList::iterator itEnd = node.mNodes.end( );
while ( it != itEnd )
{
( *it )->traversal( *this, visibleBounds );
++it;
}
}
PagingLandScapeOctree *n =
node.mChildren[ 0 ][ 0 ][ 0 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 1 ][ 0 ][ 0 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 0 ][ 1 ][ 0 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 1 ][ 1 ][ 0 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 0 ][ 0 ][ 1 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 1 ][ 0 ][ 1 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 0 ][ 1 ][ 1 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 1 ][ 1 ][ 1 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
}
//-----------------------------------------------------------------------
99 void Traversal::traverseChildren( PagingLandScapeOctree& node, VisibleObjectsBoundsInfo * const visibleBounds )
{
// hasLocalChildren
if ( !node.mNodes.empty( ) )
{
//Add stuff to be rendered;
PagingLandScapeOctreeNodeList::iterator it = node.mNodes.begin( );
PagingLandScapeOctreeNodeList::iterator itEnd = node.mNodes.end( );
while ( it != itEnd )
{
( *it )->traversal ( *this, visibleBounds );
++it;
}
}
PagingLandScapeOctree *n =
node.mChildren[ 0 ][ 0 ][ 0 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 1 ][ 0 ][ 0 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 0 ][ 1 ][ 0 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 1 ][ 1 ][ 0 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 0 ][ 0 ][ 1 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 1 ][ 0 ][ 1 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 0 ][ 1 ][ 1 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
n = node.mChildren[ 1 ][ 1 ][ 1 ];
if ( n && n->hasChildren( ) )
n->traversal ( *this, visibleBounds );
}
}
1
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgrePagingLandScapeOcclusionTraversal.h"
#include "OgrePagingLandScapeOcclusionVFTraversal.h"
#include "OgrePagingLandScapeOcclusionVisibilityData.h"
#include "OgrePagingLandScapeOctreeCamera.h"
#include "OgrePagingLandScapeOctree.h"
#include "OgrePagingLandScapeOctreeNode.h"
#include "OgrePagingLandScapeOcclusionElement.h"
#include "OgrePagingLandScapeOcclusion.h"
namespace Ogre
{
//-----------------------------------------------------------------------
18 ViewFrustumCullingTraversal::ViewFrustumCullingTraversal ( Occlusion& o ):
occlusion( o ),
mCurrentVisibility ( PagingLandScapeOctreeCamera::NONE )
{
}
//-----------------------------------------------------------------------
25 void ViewFrustumCullingTraversal::onTree( PagingLandScapeOctree& node, VisibleObjectsBoundsInfo * const visibleBounds )
{
PagingLandScapeOctreeCamera::Visibility newVis = mCurrentVisibility;
if ( newVis != PagingLandScapeOctreeCamera::FULL )
{
// box is not hierarchically culled as inside frustum box
// so we need to check it.
newVis = occlusion.mCurrentCam->getVisibility( node.getCullBoundingBox ( ) );
// if the octant is invisible
if ( newVis == PagingLandScapeOctreeCamera::NONE )
{
// Culled Octree.
// outside frustum
#ifdef _VISIBILITYDEBUG
node.getNodeData ( occlusion.mCurrentCam )->viewFrustumVisible = false;
node.getNodeData ( occlusion.mCurrentCam )->queryVisible = false;
occlusion.frustum_culled_nodes_cnt++;
occlusion.traversed_nodes_cnt++;
#endif //_VISIBILITYDEBUG
return;
}
}
#ifdef _VISIBILITYDEBUG
node.getNodeData ( occlusion.mCurrentCam )->viewFrustumVisible = true;
node.getNodeData ( occlusion.mCurrentCam )->queryVisible = true;
occlusion.traversed_nodes_cnt++;
#endif //_VISIBILITYDEBUG
// if we get there, then it's at least partially visible.
// Store parent Vis
PagingLandScapeOctreeCamera::Visibility oldVis = mCurrentVisibility;
mCurrentVisibility = newVis;
traverseChildren ( node, visibleBounds );
// Restore Parent Vis so that bothers can be pre-culled.
mCurrentVisibility = oldVis;
}
//-----------------------------------------------------------------------
68 void ViewFrustumCullingTraversal::onLeaf( PagingLandScapeOctreeNode &node, VisibleObjectsBoundsInfo * const visibleBounds )
{
// if this PagingLandScapeOctree is partially visible, manually cull all
// scene nodes attached directly to this level.
PagingLandScapeOctreeCamera::Visibility newVis = mCurrentVisibility;
if ( newVis != PagingLandScapeOctreeCamera::FULL )
{
newVis = occlusion.mCurrentCam->getVisibility( node.getCullBoundingBox ( ) );
// if the node is invisible
if ( newVis == PagingLandScapeOctreeCamera::NONE )
{
// Culled Node.
// outside frustum
#ifdef _VISIBILITYDEBUG
node.getNodeData ( occlusion.mCurrentCam )->viewFrustumVisible = false;
node.getNodeData ( occlusion.mCurrentCam )->queryVisible = false;
occlusion.frustum_culled_nodes_cnt++;
occlusion.traversed_nodes_cnt++;
#endif //_VISIBILITYDEBUG
return;
}
}
#ifdef _VISIBILITYDEBUG
node.getNodeData ( occlusion.mCurrentCam )->viewFrustumVisible = true;
node.getNodeData ( occlusion.mCurrentCam )->queryVisible = true;
occlusion.traversed_nodes_cnt++;
occlusion.object_cnt++;
#endif //_VISIBILITYDEBUG
// if we get there, then it's at least partially visible.
// Store parent Vis
PagingLandScapeOctreeCamera::Visibility oldVis = mCurrentVisibility;
mCurrentVisibility = newVis;
node._addToRenderQueue ( occlusion.mCurrentCam,
occlusion.mCurrentRenderQueue,
occlusion.mOnlyShadowCaster, visibleBounds );
// Restore Parent Vis so that bothers can be pre-culled.
mCurrentVisibility = oldVis;
}
//-----------------------------------------------------------------------
116 ViewFrustumCullingTraversalDirect::ViewFrustumCullingTraversalDirect ( Occlusion& o ):
occlusion( o )
{
}
//-----------------------------------------------------------------------
122 void ViewFrustumCullingTraversalDirect::onTree( PagingLandScapeOctree& node, VisibleObjectsBoundsInfo * const visibleBounds )
{
if ( occlusion.mCurrentCam->isVisible( node.getCullBoundingBox ( ) ) )
{
#ifdef _VISIBILITYDEBUG
occlusion.traversed_nodes_cnt++;
node.getNodeData ( occlusion.mCurrentCam )->viewFrustumVisible = true;
node.getNodeData ( occlusion.mCurrentCam )->queryVisible = true;
#endif //_VISIBILITYDEBUG
// if we get there, then it's at least partially visible.
traverseChildren ( node, visibleBounds );
}
#ifdef _VISIBILITYDEBUG
else
{
// Culled Octree.
// outside frustum
occlusion.traversed_nodes_cnt++;
occlusion.frustum_culled_nodes_cnt++;
node.getNodeData ( occlusion.mCurrentCam )->viewFrustumVisible = false;
node.getNodeData ( occlusion.mCurrentCam )->queryVisible = false;
}
#endif //_VISIBILITYDEBUG
}
//-----------------------------------------------------------------------
149 void ViewFrustumCullingTraversalDirect::onLeaf( PagingLandScapeOctreeNode &node, VisibleObjectsBoundsInfo * const visibleBounds )
{
// if this PagingLandScapeOctree is partially visible, manually cull all
// scene nodes attached directly to this level.
if ( occlusion.mCurrentCam->isVisible( node.getCullBoundingBox ( ) ) )
{
#ifdef _VISIBILITYDEBUG
occlusion.traversed_nodes_cnt++;
node.getNodeData ( occlusion.mCurrentCam )->viewFrustumVisible = true;
node.getNodeData ( occlusion.mCurrentCam )->queryVisible = true;
occlusion.object_cnt++;
#endif //_VISIBILITYDEBUG
// if we get there, then it's at least partially visible.
node._addToRenderQueue ( occlusion.mCurrentCam,
occlusion.mCurrentRenderQueue,
occlusion.mOnlyShadowCaster, visibleBounds );
}
#ifdef _VISIBILITYDEBUG
else
{
// Culled Octree.
// outside frustum
occlusion.traversed_nodes_cnt++;
occlusion.frustum_culled_nodes_cnt++;
node.getNodeData ( occlusion.mCurrentCam )->viewFrustumVisible = false;
node.getNodeData ( occlusion.mCurrentCam )->queryVisible = false;
}
#endif //_VISIBILITYDEBUG
}
}
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright ( c ) 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later__add
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
PagingLandScapeOctree.cpp - description
-------------------
begin : Mon Sep 30 2002
copyright : ( C ) 2002 by Jon Anderson
email : janders@users.sf.net
Enhancements 2003 - 2004 ( C ) The OGRE Team
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreWireBoundingBox.h"
#include "OgreOcclusionBoundingBox.h"
#include "OgrePagingLandScapeOctreeSceneManager.h"
#include "OgrePagingLandScapeOctree.h"
#include "OgrePagingLandScapeOctreeNode.h"
#include "OgreDebugRectangle2D.h"
namespace Ogre
{
//-----------------------------------------------------------------------
49 PagingLandScapeOctree::PagingLandScapeOctree( ) :
OcclusionElement( ),
mWireBoundingBox( 0 ),
mHalfSize( Vector3::ZERO ),
mNumNodes ( 0 ),
mParent ( 0 ),
mOcclusionBoundingBox( 0 )
{
//initialize all children to null.
for ( unsigned int i = 0; i < 2; i++ )
{
for ( unsigned int j = 0; j < 2; j++ )
{
for ( unsigned int k = 0; k < 2; k++ )
{
mChildren[ i ][ j ][ k ] = 0;
}
}
}
}
//-----------------------------------------------------------------------
71 void PagingLandScapeOctree::reset( )
{
//initialize all children to null.
PagingLandScapeOctree *o;
for ( unsigned int i = 0; i < 2; i++ )
{
for ( unsigned int j = 0; j < 2; j++ )
{
for ( unsigned int k = 0; k < 2; k++ )
{
o = mChildren[ i ][ j ][ k ];
if ( o )
{
mSceneMgr->deleteOctree ( mChildren[ i ][ j ][ k ] );
mChildren[ i ][ j ][ k ] = 0;
}
}
}
}
mSceneMgr = 0;
mParent = 0;
mNumNodes = 0;
}
//-----------------------------------------------------------------------
95 PagingLandScapeOctree::~PagingLandScapeOctree( )
{
//initialize all children to null.
#ifdef _DEBUG
for ( unsigned int i = 0; i < 2; i++ )
{
for ( unsigned int j = 0; j < 2; j++ )
{
for ( unsigned int k = 0; k < 2; k++ )
{
assert ( mChildren[ i ][ j ][ k ] == 0 );
}
}
}
#endif //_DEBUG
delete mWireBoundingBox;
delete mOcclusionBoundingBox;
mParent = 0;
}
//-----------------------------------------------------------------------
/** Returns true is the box will fit in a child.
*/
119 bool PagingLandScapeOctree::_isTwiceSize( const AxisAlignedBox &box ) const
{
// infinite boxes never fit in a child - always root node
if ( box.isInfinite( ) )
return false;
const Vector3 &halfMBoxSize = mBox.getHalfSize( );
const Vector3 &boxSize = box.getSize( );
return ( ( boxSize.x <= halfMBoxSize.x ) &&
( boxSize.y <= halfMBoxSize.y ) &&
( boxSize.z <= halfMBoxSize.z ) );
}
//-----------------------------------------------------------------------
/** Returns true is the box will fit in a child.
*/
134 bool PagingLandScapeOctree::_isTwiceCullSize( const AxisAlignedBox &box ) const
{
// infinite boxes never fit in a child - always root node
if ( box.isInfinite( ) )
return false;
const Vector3 &boxSize = box.getSize( );
return( boxSize.x <= mCullHalfSize.x ) &&
( boxSize.y <= mCullHalfSize.y ) &&
( boxSize.z <= mCullHalfSize.z ) ;
}
//-----------------------------------------------------------------------
/** Returns true is the box will fit in a child.
*/
149 bool PagingLandScapeOctree::_isNotCrossingAxes( const AxisAlignedBox &box ) const
{
const Vector3 &boxMin = box.getMinimum( );
const Vector3 &boxMax = box.getMaximum( );
const Vector3 octCullCenter = mCullBox.getMinimum( ) + mCullHalfSize;
return !( ( boxMin.x <= octCullCenter.x && octCullCenter.x <= boxMax.x ) ||
( boxMin.y <= octCullCenter.y && octCullCenter.y <= boxMax.y ) ||
( boxMin.z <= octCullCenter.z && octCullCenter.z <= boxMax.z ) );
}
//-----------------------------------------------------------------------
162 PagingLandScapeOctree *PagingLandScapeOctree::_getCullChildWhereBoxFits( const AxisAlignedBox &box,
163 PagingLandScapeOctreeSceneManager *scn )
{
/** It's assumed the the given box has already been proven to fit into
* a child. Since it's a loose PagingLandScapeOctree, only the centers need to be
* compared to find the appropriate node.
*/
const Vector3 octCenter = mCullBox.getMinimum( ) + mCullHalfSize;
const Vector3 ncenter = box.getMaximum( ).midPoint( box.getMinimum( ) );
unsigned int x;
if ( ncenter.x > octCenter.x )
x = 1;
else
x = 0;
unsigned int y;
if ( ncenter.y > octCenter.y )
y = 1;
else
y = 0;
unsigned int z;
if ( ncenter.z > octCenter.z )
z = 1;
else
z = 0;
if ( mChildren[ x ][ y ][ z ] == 0 )
{
const Vector3 &octantMax = mBox.getMaximum( );
const Vector3 &octantMin = mBox.getMinimum( );
Vector3 min, max;
if ( x == 0 )
{
min.x = octantMin.x;
max.x = octCenter.x;
}
else
{
min.x = octCenter.x;
max.x = octantMax.x;
}
if ( y == 0 )
{
min.y = octantMin.y;
max.y = octCenter.y;
}
else
{
min.y = octCenter.y;
max.y = octantMax.y;
}
if ( z == 0 )
{
min.z = octantMin.z;
max.z = octCenter.z;
}
else
{
min.z = octCenter.z;
max.z = octantMax.z;
}
PagingLandScapeOctree *newChild = scn->getNewOctree( );
newChild->setParent ( this );
newChild->setSceneManager( scn );
newChild ->setBoundingBox( min, max );
scn->registeredNodeInCamera ( newChild );
#ifdef _VISIBILITYDEBUG
newChild ->setDebugCorners( scn );
#endif //_VISIBILITYDEBUG
mChildren[x][y][z] = newChild;
}
return mChildren[x][y][z];
}
//-----------------------------------------------------------------------
244 PagingLandScapeOctree *PagingLandScapeOctree::_getChildWhereBoxFits( const AxisAlignedBox &box,
245 PagingLandScapeOctreeSceneManager *scn )
{
/** It's assumed the the given box has already been proven to fit into
* a child. Since it's a loose PagingLandScapeOctree, only the centers need to be
* compared to find the appropriate node.
*/
const Vector3 &octantMax = mBox.getMaximum( );
const Vector3 &octantMin = mBox.getMinimum( );
const Vector3 octCenter = octantMin + mHalfSize;
const Vector3 ncenter = box.getMaximum( ).midPoint( box.getMinimum( ) );
assert ( octantMax.x >= ncenter.x && octantMax.y >= ncenter.y && octantMax.z >= ncenter.z &&
octantMin.x <= ncenter.x && octantMin.y <= ncenter.y && octantMin.z <= ncenter.z );
unsigned int x;
if ( ncenter.x > octCenter.x )
x = 1;
else
x = 0;
unsigned int y;
if ( ncenter.y > octCenter.y )
y = 1;
else
y = 0;
unsigned int z;
if ( ncenter.z > octCenter.z )
z = 1;
else
z = 0;
if ( mChildren[ x ][ y ][ z ] == 0 )
{
Vector3 min, max;
if ( x == 0 )
{
min.x = octantMin.x;
max.x = octCenter.x;
}
else
{
min.x = octCenter.x;
max.x = octantMax.x;
}
if ( y == 0 )
{
min.y = octantMin.y;
max.y = octCenter.y;
}
else
{
min.y = octCenter.y;
max.y = octantMax.y;
}
if ( z == 0 )
{
min.z = octantMin.z;
max.z = octCenter.z;
}
else
{
min.z = octCenter.z;
max.z = octantMax.z;
}
#ifdef _DEBUG
std::cout << "new Child\n";
#endif
PagingLandScapeOctree *newChild = scn->getNewOctree( );
newChild->setParent ( this );
newChild->setSceneManager( scn );
newChild->setBoundingBox( min, max );
assert ( max.x >= ncenter.x && max.y >= ncenter.y && max.z >= ncenter.z &&
min.x <= ncenter.x && min.y <= ncenter.y && min.z <= ncenter.z );
scn->registeredNodeInCamera ( newChild );
#ifdef _VISIBILITYDEBUG
newChild ->setDebugCorners( scn );
#endif //_VISIBILITYDEBUG
mChildren[x][y][z] = newChild;
}
return mChildren[x][y][z];
}
//-----------------------------------------------------------------------
338 void PagingLandScapeOctree::setBoundingBox( const Vector3 &min,
339 const Vector3 &max )
{
mBox.setExtents( min, max );
mCullHalfSize = max - min;
const Vector3 halfSize = mCullHalfSize * 0.5f;
mHalfSize = halfSize;
mCullBox.setExtents( min - halfSize, max + halfSize );
if( mWireBoundingBox != 0 )
mWireBoundingBox->setupBoundingBox( mBox );
if( mOcclusionBoundingBox != 0 )
mOcclusionBoundingBox->setupBoundingBox( mBox );
}
//-----------------------------------------------------------------------
352 void PagingLandScapeOctree::_addNode( PagingLandScapeOctreeNode * n )
{
if ( n->isStaticNode ( ) )
mStaticNodes.push_back ( n );
else
mMovingNodes.push_back ( n );
mNodes.push_back ( n );
n->setOctant( this );
//update total counts.
_ref( );
}
//-----------------------------------------------------------------------
364 void PagingLandScapeOctree::_removeNode( PagingLandScapeOctreeNode * n )
{
assert ( !mNodes.empty( ) );
NodeList::iterator it;
it = std::find ( mNodes.begin ( ), mNodes.end ( ), n );
if ( it != mNodes.end ( ) )
mNodes.erase ( it );
if ( n->isStaticNode ( ) )
{
it = std::find( mStaticNodes.begin ( ), mStaticNodes.end ( ), n );
if ( it != mStaticNodes.end ( ) )
mStaticNodes.erase ( it );
}
else
{
it = std::find( mMovingNodes.begin ( ), mMovingNodes.end ( ), n );
if ( it != mMovingNodes.end ( ) )
mMovingNodes.erase ( it );
}
n->setOctant( 0 );
//update total counts.
_unref( mNumNodes == 1 );
}
//-----------------------------------------------------------------------
391 void PagingLandScapeOctree::_unref( const bool removeChildren )
{
--mNumNodes;
if ( removeChildren )
{
//remove null children
PagingLandScapeOctree *child;
for ( unsigned int i = 0; i < 2; i++ )
{
for ( unsigned int j = 0; j < 2; j++ )
{
for ( unsigned int k = 0; k < 2; k++ )
{
child = mChildren[ i ][ j ][ k ];
if ( child && !child->hasChildren( ) )
{
mSceneMgr->deleteOctree( child );
mChildren[ i ][ j ][ k ] = 0;
}
}
}
}
}
if ( mParent != 0 )
{
mParent->_unref( mNumNodes == 0 );
}
};
//-----------------------------------------------------------------------
420 void PagingLandScapeOctree::_getCullBounds( AxisAlignedBox *b ) const
{
// const Vector3 * const corners = mBox.getAllCorners( );
// b->setExtents( corners[ 0 ] - mHalfSize, corners[ 4 ] + mHalfSize );
*b = mCullBox;
}
//-----------------------------------------------------------------------
427 WireBoundingBox* PagingLandScapeOctree::getWireBoundingBox( )
{
// Create a WireBoundingBox if needed
if ( mWireBoundingBox == 0 )
{
mWireBoundingBox = new WireBoundingBox( );
//mWireBoundingBox->setRenderQueueGroup ( RENDER_QUEUE_WORLD_GEOMETRY_2 );
mWireBoundingBox->setupBoundingBox( mBox );
}
return mWireBoundingBox;
}
//-----------------------------------------------------------------------
440 OcclusionBoundingBox* PagingLandScapeOctree::getOcclusionBoundingBox( )
{
// Create an OcclusionBoundingBox only if needed
if ( mOcclusionBoundingBox == 0 )
{
mOcclusionBoundingBox = new OcclusionBoundingBox( );
//mOcclusionBoundingBox->setRenderQueueGroup ( RENDER_QUEUE_WORLD_GEOMETRY_2 );
mOcclusionBoundingBox->setupBoundingBox ( mBox );
}
return mOcclusionBoundingBox;
}
//-----------------------------------------------------------------------
452 void PagingLandScapeOctree::setParent( PagingLandScapeOctree * parent )
{
mParent = parent;
}
//-----------------------------------------------------------------------
457 void PagingLandScapeOctree::setSceneManager( PagingLandScapeOctreeSceneManager * scn )
{
mSceneMgr = scn;
}
#ifdef _VISIBILITYDEBUG
//-----------------------------------------------------------------------
463 void PagingLandScapeOctree::setDebugCorners( PagingLandScapeOctreeSceneManager *scnMgr )
{
// use the ratio ( OCtreeAAB / thisAAB ) / 8
const Vector3 &max = mBox.getMaximum ( );
const Vector3 &min = mBox.getMinimum ( );
const Vector3 &sceneMax = scnMgr->getBoundingBox ( ).getMaximum ( );
const Vector3 &sceneMin = scnMgr->getBoundingBox ( ).getMinimum ( );
const Real width = sceneMax.x - sceneMin.x;
const Real height = sceneMax.z - sceneMin.z;
if ( Math::Abs( width ) > 1e-08 && Math::Abs( height ) > 1e-08 )
{
Real left = 0.0f, top = 0.0f, right = 0.0f, bottom = 0.0f;
const Real toScreenDivider = 1.0f / 3;
const Real xleft = min.x - sceneMin.x;
if ( Math::Abs( xleft ) > 1e-08 )
left = ( xleft / width ) * toScreenDivider;
const Real ztop = min.z - sceneMin.z;
if ( Math::Abs( ztop ) > 1e-08 )
top = ( ztop / height ) * toScreenDivider;
const Real xright = max.x - sceneMin.x;
if ( Math::Abs( xright ) > 1e-08 )
right = ( xright / width ) * toScreenDivider;
const Real zbottom = max.z - sceneMin.z;
if ( Math::Abs( zbottom ) > 1e-08 )
bottom = ( zbottom / height ) * toScreenDivider;
getRectangle2d ( scnMgr )->setCorners ( ( 1.0f - toScreenDivider ) + left,
( 1.0f - toScreenDivider ) + top,
( 1.0f - toScreenDivider ) + right,
( 1.0f - toScreenDivider ) + bottom );
}
}
#endif //_VISIBILITYDEBUG
}
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
OgrePagingLandScapeOctreeAxisAlignedBoxSceneQuery.cpp - description
-------------------
begin : Tues July 20, 2004
copyright : ( C ) 2004by Jon Anderson
email : janders@users.sf.net
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgrePagingLandScapeOctreeAxisAlignedBoxSceneQuery.h"
#include "OgrePagingLandScapeOctreeSceneManager.h"
#include "OgreEntity.h"
namespace Ogre
{
//---------------------------------------------------------------------
46 PagingLandScapeOctreeAxisAlignedBoxSceneQuery::PagingLandScapeOctreeAxisAlignedBoxSceneQuery( SceneManager* creator )
: DefaultAxisAlignedBoxSceneQuery( creator )
{
}
//---------------------------------------------------------------------
52 PagingLandScapeOctreeAxisAlignedBoxSceneQuery::~PagingLandScapeOctreeAxisAlignedBoxSceneQuery( void )
{
}
//---------------------------------------------------------------------
57 void PagingLandScapeOctreeAxisAlignedBoxSceneQuery::execute( SceneQueryListener* listener )
{
std::list < SceneNode* > list;
//find the nodes that intersect the AAB
static_cast< PagingLandScapeOctreeSceneManager* >( mParentSceneMgr )->findNodesIn( mAABB, list, 0 );
//grab all moveables from the node that intersect...
std::list < SceneNode* >::iterator it = list.begin( );
while ( it != list.end( ) )
{
SceneNode::ObjectIterator oit = ( *it )->getAttachedObjectIterator( );
while ( oit.hasMoreElements( ) )
{
MovableObject* m = oit.getNext( );
if ( ( m->getQueryFlags( ) & mQueryMask ) && m->isInScene( ) && mAABB.intersects( m->getWorldBoundingBox( ) ) )
{
listener->queryResult( m );
}
}
++it;
}
}
}
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright ( c ) 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
PagingLandScapeOctreecamera.cpp - description
-------------------
begin : Fri Sep 27 2002
copyright : ( C ) 2002 by Jon Anderson
email : janders@users.sf.net
Enhancements 2003 - 2004 ( C ) The OGRE Team
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreMath.h"
#include "OgreAxisAlignedBox.h"
#include "OgreRoot.h"
#include "OgreViewport.h"
#include "OgreRenderSystem.h"
#include "OgrePagingLandScapeOctreeCamera.h"
#include "OgrePagingLandScapeOctreeSceneManager.h"
namespace Ogre
{
unsigned int PagingLandScapeOctreeCamera::s_camId = 0;
//-----------------------------------------------------------------------
51 PagingLandScapeOctreeCamera::PagingLandScapeOctreeCamera( const String& name, SceneManager* sm ) :
Camera( name, sm ),
mVisFacesLastCHCRender( 0 ),
isOcclusionSystemRegistered ( false ),
mOcclusionMode ( VIEW_FRUSTUM_DIRECT ),
mFrameId( 0 ),
mFrameSceneId( 0 )
{
mUniqueIdentification = s_camId++;
updateRegistrationInOcclusionSystem ( );
}
//-----------------------------------------------------------------------
63 PagingLandScapeOctreeCamera::~PagingLandScapeOctreeCamera( )
{
}
//-----------------------------------------------------------------------
67 bool PagingLandScapeOctreeCamera::nextFrame( const unsigned int framesSceneId )
{
if ( framesSceneId != mFrameSceneId )
{
// change frame Id counter
//that identify current frame.
mFrameSceneId = framesSceneId;
mFrameId += 1;
return true;
}
return false;
}
//-----------------------------------------------------------------------
80 bool PagingLandScapeOctreeCamera::isRegisteredInOcclusionSystem( ) const
{
return isOcclusionSystemRegistered;
}
//-----------------------------------------------------------------------
85 void PagingLandScapeOctreeCamera::setRegisteredInOcclusionSystem( const bool registered )
{
isOcclusionSystemRegistered = registered;
}
//-----------------------------------------------------------------------
90 void PagingLandScapeOctreeCamera::changeOcclusionMode( culling_modes nextOcclusionMode )
{
if ( nextOcclusionMode != mOcclusionMode )
{
if ( nextOcclusionMode == VIEW_FRUSTUM_DIRECT )
{
if ( mLastViewport )
mLastViewport->setClearEveryFrame ( true );
}
else
{
if ( !getSceneManager ( )->getDestinationRenderSystem ( )->getCapabilities( )->hasCapability( RSC_HWOCCLUSION ) )
{
OGRE_EXCEPT( 1,
"Your card does not support HWOCCLUSION ",
"PagingLandScapeOctreeCamera::setNextOcclusionMode" );
}
if ( mLastViewport )
mLastViewport->setClearEveryFrame ( false );
}
mOcclusionMode = nextOcclusionMode;
updateRegistrationInOcclusionSystem( );
}
}
//-----------------------------------------------------------------------
116 void PagingLandScapeOctreeCamera::updateRegistrationInOcclusionSystem( )
{
if ( needRegistrationInOcclusionSystem( ) && !isRegisteredInOcclusionSystem( ) )
{
static_cast <PagingLandScapeOctreeSceneManager *> ( getSceneManager ( ) )->registerCamera( this );
setRegisteredInOcclusionSystem ( true );
}
else if ( !needRegistrationInOcclusionSystem( ) && isRegisteredInOcclusionSystem( ) )
{
static_cast <PagingLandScapeOctreeSceneManager *> ( getSceneManager ( ) )->unregisterCamera( this );
setRegisteredInOcclusionSystem ( false );
}
}
//-----------------------------------------------------------------------
130 void PagingLandScapeOctreeCamera::setNextOcclusionMode( )
{
culling_modes nextOcclusionMode = static_cast <culling_modes> ( ( mOcclusionMode + 1 ) % NUM_CULLING_MODE );
changeOcclusionMode ( nextOcclusionMode );
}
//-----------------------------------------------------------------------
137 bool PagingLandScapeOctreeCamera::needRegistrationInOcclusionSystem( ) const
{
#ifdef _VISIBILITYDEBUG
return true;
#endif //_VISIBILITYDEBUG
if ( mOcclusionMode == CHC ||
mOcclusionMode == CHC_CONSERVATIVE )
return true;
else
return false;
};
//-----------------------------------------------------------------------
150 void PagingLandScapeOctreeCamera::setOcclusionMode( culling_modes occlusionMode )
{
changeOcclusionMode ( occlusionMode );
};
//-----------------------------------------------------------------------
155 void PagingLandScapeOctreeCamera::setOcclusionModeAsString( const String &cullingModeAsString )
{
culling_modes cullingmode ( VIEW_FRUSTUM_DIRECT );
if ( cullingModeAsString == "VIEW_FRUSTUM_DIRECT" )
cullingmode = VIEW_FRUSTUM_DIRECT;
else if ( cullingModeAsString == "CHC" )
cullingmode = CHC;
else if ( cullingModeAsString == "CHC_CONSERVATIVE" )
cullingmode = CHC_CONSERVATIVE;
setOcclusionMode( cullingmode );
};
//-----------------------------------------------------------------------
167 String PagingLandScapeOctreeCamera::getOcclusionModeAsString( ) const
{
switch ( getOcclusionMode( ) )
{
case CHC: return String( "CHC" );
case CHC_CONSERVATIVE: return String( "CHC_CONSERVATIVE" );
case VIEW_FRUSTUM_DIRECT:
default:
return String( "VIEW_FRUSTUM_DIRECT" );
}
}
//-----------------------------------------------------------------------
179 PagingLandScapeOctreeCamera::Visibility PagingLandScapeOctreeCamera::getVisibility( const AxisAlignedBox &bound ) const
{
// Null boxes always invisible
if ( bound.isNull( ) )
return NONE;
// Infinite boxes always visible
if ( bound.isInfinite( ) )
return FULL;
// Get centre of the box
const Vector3 ¢re ( bound.getCenter( ) );
// Get the half-size of the box
const Vector3 &halfSize ( bound.getHalfSize( ) );
bool all_inside = true;
const bool infinite_far_clip = ( mFarDist == 0 );
for ( unsigned int plane = 0; plane < 6; ++plane )
{
// Skip far plane if infinite view frustum
if ( plane == FRUSTUM_PLANE_FAR && infinite_far_clip )
continue;
// This updates frustum planes and deals with cull frustum
const Plane::Side side = getFrustumPlane( plane ).getSide( centre, halfSize );
if ( side == Plane::NEGATIVE_SIDE )
return NONE;
// We can't return now as the box could be later on the negative side of a plane.
if ( side == Plane::BOTH_SIDE )
all_inside = false;
}
if ( all_inside )
return FULL;
else
return PARTIAL;
}
}
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
OgrePagingLandScapeOctreeIntersectionSceneQuery.cpp - description
-------------------
begin : Tues July 20, 2004
copyright : ( C ) 2004by Jon Anderson
email : janders@users.sf.net
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgrePagingLandScapeOctreeIntersectionSceneQuery.h"
#include "OgrePagingLandScapeOctreeSceneManager.h"
#include "OgreEntity.h"
#include "OgreRoot.h"
namespace Ogre
{
//---------------------------------------------------------------------
47 PagingLandScapeOctreeIntersectionSceneQuery::PagingLandScapeOctreeIntersectionSceneQuery( SceneManager* creator )
: DefaultIntersectionSceneQuery( creator )
{
}
//---------------------------------------------------------------------
54 PagingLandScapeOctreeIntersectionSceneQuery::~PagingLandScapeOctreeIntersectionSceneQuery( void )
{
}
//---------------------------------------------------------------------
59 void PagingLandScapeOctreeIntersectionSceneQuery::execute( IntersectionSceneQueryListener* listener )
{
typedef std::pair<MovableObject *, MovableObject *> MovablePair;
typedef std::set
< std::pair<MovableObject *, MovableObject *> > MovableSet;
MovableSet set;
// Iterate over all movable types
Root::MovableObjectFactoryIterator factIt =
Root::getSingleton( ).getMovableObjectFactoryIterator( );
while( factIt.hasMoreElements( ) )
{
SceneManager::MovableObjectIterator it =
mParentSceneMgr->getMovableObjectIterator(
factIt.getNext( )->getType( ) );
while( it.hasMoreElements( ) )
{
MovableObject * e = it.getNext( );
std::list < SceneNode * > list;
//find the nodes that intersect the AAB
static_cast<PagingLandScapeOctreeSceneManager*>( mParentSceneMgr ) -> findNodesIn( e->getWorldBoundingBox( ), list, 0 );
//grab all movables from the node that intersect...
std::list < SceneNode * >::iterator itscn = list.begin( );
while( itscn != list.end( ) )
{
SceneNode::ObjectIterator oit = ( *itscn ) -> getAttachedObjectIterator( );
while( oit.hasMoreElements( ) )
{
MovableObject * m = oit.getNext( );
if( m != e &&
set.find( MovablePair( e, m ) ) == set.end( ) &&
set.find( MovablePair( m, e ) ) == set.end( ) &&
( m->getQueryFlags( ) & mQueryMask ) &&
( m->getTypeFlags( ) & mQueryTypeMask ) &&
m->isInScene( ) &&
e->getWorldBoundingBox( ).intersects( m->getWorldBoundingBox( ) ) )
{
listener -> queryResult( e, m );
// deal with attached objects, since they are not directly attached to nodes
if ( m->getMovableType( ) == "Entity" )
{
Entity* e2 = static_cast<Entity*>( m );
Entity::ChildObjectListIterator childIt = e2->getAttachedObjectIterator( );
while( childIt.hasMoreElements( ) )
{
MovableObject* c = childIt.getNext( );
if ( c->getQueryFlags( ) & mQueryMask &&
e->getWorldBoundingBox( ).intersects( c->getWorldBoundingBox( ) ) )
{
listener->queryResult( e, c );
}
}
}
}
set.insert( MovablePair( e, m ) );
}
++itscn;
}
}
}
}
}
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright ( c ) 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
PagingLandScapeOctreenode.cpp - description
-------------------
begin : Fri Sep 27 2002
copyright : ( C ) 2002 by Jon Anderson
email : janders@users.sf.net
Enhancements 2003 - 2004 ( C ) The OGRE Team
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreRoot.h"
#include "OgrePagingLandScapeOctreeNode.h"
#include "OgreOcclusionBoundingBox.h"
#include "OgreWireBoundingBox.h"
#include "OgreRenderQueue.h"
#include "OgreDebugRectangle2D.h"
namespace Ogre
{
//-----------------------------------------------------------------------
50 PagingLandScapeOctreeNode::PagingLandScapeOctreeNode( SceneManager* creator ) :
SceneNode( creator ),
OcclusionElement( ),
mOctant( 0 ),
mOcclusionBoundingBox( 0 ),
mIsStaticNode( true ),
mIsOccluder( true )
{
}
//-----------------------------------------------------------------------
62 PagingLandScapeOctreeNode::PagingLandScapeOctreeNode( SceneManager* creator, const String& name ) :
SceneNode( creator, name ),
OcclusionElement( ),
mOctant( 0 ),
mOcclusionBoundingBox( 0 ),
mIsStaticNode( true ),
mIsOccluder( true )
{
}
//-----------------------------------------------------------------------
74 PagingLandScapeOctreeNode::~PagingLandScapeOctreeNode( )
{
removeAllChildren( );
if ( mParent )
mParent->removeChild( this );
assert ( !mParent );
delete mOcclusionBoundingBox;
}
//-----------------------------------------------------------------------
//same as SceneNode, only it doesn't care about children...
84 void PagingLandScapeOctreeNode::_updateBounds( void )
{
mWorldAABB.setNull( );
mLocalAABB.setNull( );
// Update bounds from own attached objects
ObjectMap::const_iterator i = mObjectsByName.begin( );
while ( i != mObjectsByName.end( ) )
{
const MovableObject * const mo = i->second;
// Get local bounds of object
mLocalAABB.merge( mo->getBoundingBox( ) );
// Get World bounds of object
mWorldAABB.merge( mo->getWorldBoundingBox( true ) );
++i;
}
//update the PagingLandScapeOctreeSceneManager that things might have moved.
// if it hasn't been added to the PagingLandScapeOctree, add it, and if has moved
// enough to leave it's current node, we'll update it.
if ( ! mWorldAABB.isNull( ) )
{
assert ( mCreator );
static_cast < PagingLandScapeOctreeSceneManager * > ( mCreator )->_updatePagingLandScapeOctreeNode( this );
}
mHalfSize = ( mWorldAABB.getMaximum ( ) - mWorldAABB.getMinimum ( ) ) * 0.5;
if ( mOcclusionBoundingBox )
mOcclusionBoundingBox->setupBoundingBox( mWorldAABB );
if ( mWireBoundingBox )
mWireBoundingBox->setupBoundingBox( mWorldAABB );
if ( !mIsRegisteredToCam )
static_cast< PagingLandScapeOctreeSceneManager * > ( mCreator )->
registeredNodeInCamera ( this );
}
//-----------------------------------------------------------------------
/** Since we are loose, only check the center.
*/
123 bool PagingLandScapeOctreeNode::_isIn( const AxisAlignedBox &box ) const
{
// Always fail if not in the scene graph or box is null
if ( !mIsInSceneGraph || box.isNull( ) )
return false;
// Always succeed if AABB is infinite
if ( box.isInfinite( ) )
return true;
// Object Bounding Box Center
const Vector3 center = mWorldAABB.getMaximum( ).midPoint( mWorldAABB.getMinimum( ) );
// Min and Max of Octree BBox
const Vector3 &bmin = box.getMinimum( );
const Vector3 &bmax = box.getMaximum( );
// Object Bbox center is IN Octree BBox ?
const bool centre = bmax.x >= center.x && bmax.y >= center.y && bmax.z >= center.z &&
bmin.x <= center.x && bmin.y <= center.y && bmin.z <= center.z;
if ( !centre )
return false;
// Even if covering the centre line, need to make sure this BB is not large
// enough to require being moved up into parent. When added, bboxes would
// end up in parent due to cascade but when updating need to deal with
// bbox growing too large for this child
const Vector3 octreeSize ( bmax - bmin );
const Vector3 nodeSize ( mWorldAABB.getMaximum( ) - mWorldAABB.getMinimum( ) );
return ( nodeSize < octreeSize );
}
//-----------------------------------------------------------------------
/** Adds the attached objects of this PagingLandScapeOctreeScene node into the queue. */
158 void PagingLandScapeOctreeNode::_addToRenderQueue( Camera* cam,
RenderQueue * const queue,
const bool onlyShadowCasters,
VisibleObjectsBoundsInfo* visibleBounds )
{
ObjectMap::iterator mit = mObjectsByName.begin( );
while ( mit != mObjectsByName.end( ) )
{
MovableObject * const mo = mit->second;
mo->_notifyCurrentCamera( cam );
if ( mo->isVisible( ) &&
( !onlyShadowCasters || mo->getCastShadows( ) ) )
{
mo->_updateRenderQueue( queue );
if ( visibleBounds )
{
visibleBounds->merge( mo->getWorldBoundingBox( true ),
mo->getWorldBoundingSphere( true ), cam );
}
}
++mit;
}
// check if the scene manager or this node wants the bounding box shown.
if ( getShowBoundingBox( ) || mCreator->getShowBoundingBoxes( ) )
_addBoundingBoxToQueue( queue );
if ( mCreator->getDisplaySceneNodes( ) )
queue -> addRenderable( this );
}
//-----------------------------------------------------------------------
194 void PagingLandScapeOctreeNode::attachObject( MovableObject* obj )
{
if ( mIsStaticNode )
{
const String movableType = obj->getMovableType( );
if ( movableType == "Entity" || movableType == "StaticGeometry" )
{
if ( StringUtil::startsWith( obj->getName( ), "Static", false ) )
{
if ( mIsOccluder && !StringUtil::startsWith( obj->getName( ), "StaticOccluder", false ) )
{
mIsOccluder = false;
}
}
else
{
mIsStaticNode = false;
mIsOccluder = false;
}
}
else if ( movableType != "PagingLandScapeRenderable"
&& movableType != "TerrainMipMap" )
{
mIsStaticNode = false;
mIsOccluder = false;
}
}
SceneNode::attachObject ( obj );
}
//-----------------------------------------------------------------------
224 MovableObject* PagingLandScapeOctreeNode::detachObject( unsigned short index )
{
// if we detach 1 object, after the return,
// there's none left so we reset the thing.
if ( !mObjectsByName.empty( ) && 1 == mObjectsByName.size( ) )
{
mIsStaticNode = true;
mIsOccluder = true;
}
return SceneNode::detachObject ( index );
}
//-----------------------------------------------------------------------
237 MovableObject* PagingLandScapeOctreeNode::detachObject( const String& name )
{
if ( !mObjectsByName.empty( ) && 1 == mObjectsByName.size( ) )
{
mIsStaticNode = true;
mIsOccluder = true;
}
return SceneNode::detachObject ( name );
}
//-----------------------------------------------------------------------
247 void PagingLandScapeOctreeNode::detachObject( MovableObject* obj )
{
if ( !mObjectsByName.empty( ) && 1 == mObjectsByName.size( ) )
{
mIsStaticNode = true;
mIsOccluder = true;
}
SceneNode::detachObject ( obj );
}
//-----------------------------------------------------------------------
257 void PagingLandScapeOctreeNode::detachAllObjects( void )
{
SceneNode::detachAllObjects ( );
mIsStaticNode = true;
mIsOccluder = true;
}
//-----------------------------------------------------------------------
264 void PagingLandScapeOctreeNode::_addAlreadyNotifiedToVisibles( )
{
if ( !mNotifiedVisibles.empty( ) )
{
PagingLandScapeOctreeSceneManager * const osm = static_cast < PagingLandScapeOctreeSceneManager * > ( mCreator );
// create the render Queue.
MovableObjectList::iterator it = mNotifiedVisibles.begin( ),
itend = mNotifiedVisibles.end( );
while ( it != itend )
{
assert ( ( *it )->isVisible ( ) );
osm->addVisible ( *it );
++it;
}
mNotifiedVisibles.clear( );
}
}
//-----------------------------------------------------------------------
283 void PagingLandScapeOctreeNode::_addToVisibles( Camera* cam,
284 const bool onlyShadowCasters )
{
if ( !mNotifiedVisibles.empty( ) )
{
PagingLandScapeOctreeSceneManager * const osm = static_cast < PagingLandScapeOctreeSceneManager * > ( mCreator );
// create the render Queue.
ObjectMap::iterator mit = mObjectsByName.begin ( );
while ( mit != mObjectsByName.end ( ) )
{
MovableObject * const mo = mit->second;
mo->_notifyCurrentCamera ( cam );
if ( mo->isVisible ( ) &&
( !onlyShadowCasters || mo->getCastShadows ( ) ) )
{
osm->addVisible ( mo );
}
++mit;
}
mNotifiedVisibles.clear ( );
}
}
//-----------------------------------------------------------------------
307 bool PagingLandScapeOctreeNode::notifyNodeObjects( Camera* cam,
308 const bool onlyShadowCasters )
{
// if at least one is visible.
bool isVisible = false;
mNotifiedVisibles.clear( );
ObjectMap::iterator mit = mObjectsByName.begin ( );
while ( mit != mObjectsByName.end ( ) )
{
MovableObject * const mo = mit->second;
mo->_notifyCurrentCamera ( cam );
if ( mo->isVisible ( ) &&
( !onlyShadowCasters || mo->getCastShadows ( ) ) )
{
mNotifiedVisibles.push_back ( mo );
isVisible = true;
}
++mit;
}
return isVisible;
}
//-----------------------------------------------------------------------
329 MovableObjectList *PagingLandScapeOctreeNode::getVisibleNotifiedNodeObjects( Camera* cam,
330 const bool onlyShadowCasters )
{
notifyNodeObjects( cam, onlyShadowCasters );
return &mNotifiedVisibles;
}
//-----------------------------------------------------------------------
336 OcclusionBoundingBox* PagingLandScapeOctreeNode::getOcclusionBoundingBox( )
{
// Create an OcclusionBoundingBox if needed
if( mOcclusionBoundingBox == 0 )
{
mOcclusionBoundingBox = new OcclusionBoundingBox( );
//mOcclusionBoundingBox->setRenderQueueGroup ( RENDER_QUEUE_WORLD_GEOMETRY_2 );
mOcclusionBoundingBox->setupBoundingBox( mWorldAABB );
}
return mOcclusionBoundingBox;
}
//-----------------------------------------------------------------------
348 void PagingLandScapeOctreeNode::addChild( Node* child )
{
mIsRegisteredToCam = false;
static_cast< PagingLandScapeOctreeSceneManager * > ( mCreator )->registeredNodeInCamera( this );
// call superclass method
Node::addChild ( child );
}
//-----------------------------------------------------------------------
356 void PagingLandScapeOctreeNode::_removeNodeAndChildren( )
{
assert ( mCreator );
static_cast< PagingLandScapeOctreeSceneManager * > ( mCreator )->unregisteredNodeInCamera ( this );
mIsRegisteredToCam = false;
PagingLandScapeOctree * oct = getOctant( );
if ( oct )
oct->_removeNode( this );
setOctant ( 0 );
//remove all the children nodes as well from the PagingLandScapeOctree.
ChildNodeMap::iterator it = mChildren.begin( );
while( it != mChildren.end( ) )
{
static_cast<PagingLandScapeOctreeNode *>( it->second )->_removeNodeAndChildren( );
++it;
}
}
//-----------------------------------------------------------------------
376 void PagingLandScapeOctreeNode::removeAllChildren( void )
{
ChildNodeMap::iterator i, iend = mChildren.end( );
for ( i = mChildren.begin( ); i != iend; ++i )
{
static_cast <PagingLandScapeOctreeNode* > ( i->second )->_removeNodeAndChildren( );
}
Node::removeAllChildren( );
}
//-----------------------------------------------------------------------
386 Node * PagingLandScapeOctreeNode::removeChild( unsigned short index )
{
PagingLandScapeOctreeNode *on = static_cast<PagingLandScapeOctreeNode* >( SceneNode::removeChild( index ) );
on->_removeNodeAndChildren( );
return on;
}
//-----------------------------------------------------------------------
393 Node * PagingLandScapeOctreeNode::removeChild( Node* child )
{
PagingLandScapeOctreeNode *on = static_cast<PagingLandScapeOctreeNode* >( SceneNode::removeChild( child ) );
on->_removeNodeAndChildren( );
return on;
}
//-----------------------------------------------------------------------
400 Node * PagingLandScapeOctreeNode::removeChild( const String & name )
{
PagingLandScapeOctreeNode *on = static_cast< PagingLandScapeOctreeNode * >( SceneNode::removeChild( name ) );
on->_removeNodeAndChildren( );
return on;
}
#ifdef _VISIBILITYDEBUG
//-----------------------------------------------------------------------
408 void PagingLandScapeOctreeNode::setDebugCorners( PagingLandScapeOctreeSceneManager *scnMgr )
{
// use the ratio ( OCtreeAAB / thisAAB ) / 8
const Vector3 &max = mWorldAABB.getMaximum ( );
const Vector3 &min = mWorldAABB.getMinimum ( );
Real left = 0, top = 0, right = 0, bottom = 0;
const Vector3 &sceneMax = scnMgr->getBoundingBox ( ).getMaximum ( );
const Vector3 &sceneMin = scnMgr->getBoundingBox ( ).getMinimum ( );
const Real width = sceneMax.x - sceneMin.x;
const Real height = sceneMax.z - sceneMin.z;
if ( Math::Abs( width ) > 1e-08 && Math::Abs( height ) > 1e-08 )
{
const Real toScreenDivider = 1.0f / 3;
const Real xleft = min.x - sceneMin.x;
if ( Math::Abs( xleft ) > 1e-08 )
left = ( xleft / width ) * toScreenDivider;
const Real ztop = min.z - sceneMin.z;
if ( Math::Abs( ztop ) > 1e-08 )
top = ( ztop / height ) * toScreenDivider;
const Real xright = max.x - sceneMin.x;
if ( Math::Abs( xright ) > 1e-08 )
right = ( xright / width ) * toScreenDivider;
const Real zbottom = max.z - sceneMin.z;
if ( Math::Abs( zbottom ) > 1e-08 )
bottom = ( zbottom / height ) * toScreenDivider;
getRectangle2d ( scnMgr )->setCorners ( ( 1.0f - toScreenDivider ) + left,
( 1.0f - toScreenDivider ) + top,
( 1.0f - toScreenDivider ) + right,
( 1.0f - toScreenDivider ) + bottom );
}
}
#endif //_VISIBILITYDEBUG
}
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
OgrePagingLandScapeOctreePlaneBoundedVolumeListSceneQuery.cpp - description
-------------------
begin : Tues July 20, 2004
copyright : ( C ) 2004by Jon Anderson
email : janders@users.sf.net
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgrePagingLandScapeOctreePlaneBoundedVolumeListSceneQuery.h"
#include "OgrePagingLandScapeOctreeSceneManager.h"
#include "OgreEntity.h"
namespace Ogre
{
//---------------------------------------------------------------------
46 PagingLandScapeOctreePlaneBoundedVolumeListSceneQuery::PagingLandScapeOctreePlaneBoundedVolumeListSceneQuery( SceneManager* creator )
: DefaultPlaneBoundedVolumeListSceneQuery( creator )
{
}
//---------------------------------------------------------------------
52 PagingLandScapeOctreePlaneBoundedVolumeListSceneQuery::~PagingLandScapeOctreePlaneBoundedVolumeListSceneQuery( void )
{
}
//---------------------------------------------------------------------
57 void PagingLandScapeOctreePlaneBoundedVolumeListSceneQuery::execute( SceneQueryListener* listener )
{
PlaneBoundedVolumeList::iterator pi, piend;
piend = mVolumes.end( );
for ( pi = mVolumes.begin( ); pi != piend; ++pi )
{
std::list < SceneNode* > list;
//find the nodes that intersect the AAB
static_cast< PagingLandScapeOctreeSceneManager* >( mParentSceneMgr )->findNodesIn( *pi, list, 0 );
//grab all moveables from the node that intersect...
std::list < SceneNode* >::iterator it = list.begin( );
while ( it != list.end( ) )
{
SceneNode::ObjectIterator oit = ( *it )->getAttachedObjectIterator( );
while ( oit.hasMoreElements( ) )
{
MovableObject* m = oit.getNext( );
if ( ( m->getQueryFlags( ) & mQueryMask ) && m->isInScene( ) && ( *pi ).intersects( m->getWorldBoundingBox( ) ) )
{
listener->queryResult( m );
}
}
++it;
}
}
}
}
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
OgrePagingLandScapeOctreeRaySceneQuery.cpp - description
-------------------
begin : Tues July 20, 2004
copyright : ( C ) 2004by Jon Anderson
email : janders@users.sf.net
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgrePagingLandScapeOctreeRaySceneQuery.h"
#include "OgrePagingLandScapeOctreeSceneManager.h"
#include "OgreEntity.h"
namespace Ogre
{
//---------------------------------------------------------------------
46 PagingLandScapeOctreeRaySceneQuery::PagingLandScapeOctreeRaySceneQuery( SceneManager* creator )
: DefaultRaySceneQuery( creator )
{
}
//---------------------------------------------------------------------
52 PagingLandScapeOctreeRaySceneQuery::~PagingLandScapeOctreeRaySceneQuery( void )
{
}
//---------------------------------------------------------------------
57 void PagingLandScapeOctreeRaySceneQuery::execute( RaySceneQueryListener* listener )
{
// if anything else is queried, ask Octree Scene Manager.
if ( getQueryTypeMask( ) != SceneManager::WORLD_GEOMETRY_TYPE_MASK )
{
std::list < SceneNode* > list;
//find the nodes that intersect the AAB
static_cast< PagingLandScapeOctreeSceneManager* >( mParentSceneMgr )->findNodesIn( mRay, list, 0 );
//grab all movables from the node that intersect...
std::list < SceneNode* >::iterator it = list.begin( );
while ( it != list.end( ) )
{
SceneNode::ObjectIterator oit = ( *it )->getAttachedObjectIterator( );
while ( oit.hasMoreElements( ) )
{
MovableObject* m = oit.getNext( );
if ( ( m->getQueryFlags( ) & mQueryMask ) && m->isInScene( ) )
{
std::pair< bool, Real > result = mRay.intersects( m->getWorldBoundingBox( ) );
if ( result.first )
{
listener->queryResult( m, result.second );
}
}
}
++it;
}
}
//else
// { //if we want to handle static scene geometry inside the scene manager ?
//
// }
}
}
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright ( c ) 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
PagingLandScapeOctreescenemanager.cpp - description
-------------------
begin : Fri Sep 27 2002
copyright : ( C ) 2002 by Jon Anderson
email : janders@users.sf.net
Enhancements 2003 - 2004 ( C ) The OGRE Team
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgrePagingLandScapeOctreeSceneManager.h"
#include "OgrePagingLandScapeOctreeAxisAlignedBoxSceneQuery.h"
#include "OgrePagingLandScapeOctreeIntersectionSceneQuery.h"
#include "OgrePagingLandScapeOctreePlaneBoundedVolumeListSceneQuery.h"
#include "OgrePagingLandScapeOctreeRaySceneQuery.h"
#include "OgrePagingLandScapeOctreeSphereSceneQuery.h"
#include "OgreRenderSystem.h"
#include "OgreWireBoundingBox.h"
#include "OgreRenderOperation.h"
#include "OgreStringConverter.h"
#include "OgreOverlayManager.h"
#include "OgreOverlayElement.h"
#include "OgrePagingLandScapeOctreeCamera.h"
#include "OgrePagingLandScapeOctree.h"
#include "OgrePagingLandScapeOctreeNode.h"
#include "OgreOcclusionBoundingBox.h"
#include "OgrePagingLandScapeOcclusionSorter.h"
#include "OgrePagingLandScapeOcclusionVisibilityData.h"
#include "OgrePagingLandScapeOcclusionTraversal.h"
#include "OgrePagingLandScapeOcclusionCameraTraversal.h"
#include "OgrePagingLandScapeOcclusionVFTraversal.h"
#include "OgrePagingLandScapeOcclusionSWTraversal.h"
#include "OgrePagingLandScapeOcclusionDebugTraversal.h"
extern "C"
{
70 void findNodesInBox( Ogre::SceneManager *sm,
const Ogre::AxisAlignedBox &box,
std::list < Ogre::SceneNode * > &list,
const Ogre::SceneNode * const exclude )
{
static_cast<Ogre::PagingLandScapeOctreeSceneManager*>( sm )->findNodesIn( box, list, exclude );
}
77 void findNodesInSphere( Ogre::SceneManager *sm,
const Ogre::Sphere &sphere,
std::list < Ogre::SceneNode * > &list,
const Ogre::SceneNode * const exclude )
{
static_cast<Ogre::PagingLandScapeOctreeSceneManager*>( sm )->findNodesIn( sphere, list, exclude );
}
}
namespace Ogre
{
//---------------------------------------------------------------------
enum Intersection
{
OUTSIDE=0,
INSIDE=1,
INTERSECT=2
};
int PagingLandScapeOctreeSceneManager::intersect_call = 0;
//---------------------------------------------------------------------
97 Intersection intersect( const Ray &ray, const AxisAlignedBox &box )
{
// Null box?
if ( box.isNull( ) )
return OUTSIDE;
// Infinite box?
if ( box.isInfinite( ) )
return INTERSECT;
const Vector3& min = box.getMinimum( );
const Vector3& max = box.getMaximum( );
const Vector3& rayorig = ray.getOrigin( );
// Check origin inside first
if ( rayorig > min && rayorig < max )
return INSIDE;
const Vector3& raydir = ray.getDirection( );
Real lowt = 0.0f;
Real t;
bool hit = false;
Vector3 hitpoint;
// Check each face in turn, only check closest 3
// Min x
if ( rayorig.x < min.x && raydir.x > 0 )
{
t = ( min.x - rayorig.x ) / raydir.x;
if ( t > 0 )
{
// Substitute t back into ray and check bounds and dist
hitpoint = rayorig + raydir * t;
if ( hitpoint.y >= min.y && hitpoint.y <= max.y &&
hitpoint.z >= min.z && hitpoint.z <= max.z &&
( !hit || t < lowt ) )
{
return INTERSECT;
}
}
}
// Max x
if ( rayorig.x > max.x && raydir.x < 0 )
{
t = ( max.x - rayorig.x ) / raydir.x;
if ( t > 0 )
{
// Substitute t back into ray and check bounds and dist
hitpoint = rayorig + raydir * t;
if ( hitpoint.y >= min.y && hitpoint.y <= max.y &&
hitpoint.z >= min.z && hitpoint.z <= max.z &&
( !hit || t < lowt ) )
{
return INTERSECT;
}
}
}
// Min y
if ( rayorig.y < min.y && raydir.y > 0 )
{
t = ( min.y - rayorig.y ) / raydir.y;
if ( t > 0 )
{
// Substitute t back into ray and check bounds and dist
hitpoint = rayorig + raydir * t;
if ( hitpoint.x >= min.x && hitpoint.x <= max.x &&
hitpoint.z >= min.z && hitpoint.z <= max.z &&
( !hit || t < lowt ) )
{
return INTERSECT;
}
}
}
// Max y
if ( rayorig.y > max.y && raydir.y < 0 )
{
t = ( max.y - rayorig.y ) / raydir.y;
if ( t > 0 )
{
// Substitute t back into ray and check bounds and dist
hitpoint = rayorig + raydir * t;
if ( hitpoint.x >= min.x && hitpoint.x <= max.x &&
hitpoint.z >= min.z && hitpoint.z <= max.z &&
( !hit || t < lowt ) )
{
return INTERSECT;
}
}
}
// Min z
if ( rayorig.z < min.z && raydir.z > 0 )
{
t = ( min.z - rayorig.z ) / raydir.z;
if ( t > 0 )
{
// Substitute t back into ray and check bounds and dist
hitpoint = rayorig + raydir * t;
if ( hitpoint.x >= min.x && hitpoint.x <= max.x &&
hitpoint.y >= min.y && hitpoint.y <= max.y &&
( !hit || t < lowt ) )
{
return INTERSECT;
}
}
}
// Max z
if ( rayorig.z > max.z && raydir.z < 0 )
{
t = ( max.z - rayorig.z ) / raydir.z;
if ( t > 0 )
{
// Substitute t back into ray and check bounds and dist
hitpoint = rayorig + raydir * t;
if ( hitpoint.x >= min.x && hitpoint.x <= max.x &&
hitpoint.y >= min.y && hitpoint.y <= max.y &&
( !hit || t < lowt ) )
{
return INTERSECT;
}
}
}
return OUTSIDE;
}
//---------------------------------------------------------------------
222 Intersection intersect2( const Ray &one, const AxisAlignedBox &two )
{
PagingLandScapeOctreeSceneManager::intersect_call++;
// Null box?
if ( two.isNull( ) )
return OUTSIDE;
// Infinite box?
if ( two.isInfinite( ) )
return INTERSECT;
const Vector3* const pCorners = two.getAllCorners( );
const Vector3 origin = one.getOrigin( );
const Vector3 dir = one.getDirection( );
Vector3 maxT ( -1.0f, -1.0f, -1.0f );
unsigned int i = 0;
bool inside = true;
for ( i = 0; i < 3; i++ )
{
if ( origin[i] < pCorners[0][i] )
{
inside = false;
if( dir[i] > 0 )
maxT[i] = ( pCorners[0][i] - origin[i] ) / dir[i];
}
else if ( origin[i] > pCorners[4][i] )
{
inside = false;
if( dir[i] < 0 )
maxT[i] = ( pCorners[4][i] - origin[i] ) / dir[i];
}
}
if( inside )
{
return INTERSECT;
}
int whichPlane = 0;
if( maxT[1] > maxT[whichPlane] )
whichPlane = 1;
if( maxT[2] > maxT[whichPlane] )
whichPlane = 2;
if( ( ( int )maxT[whichPlane] ) & 0x80000000 )
{
return OUTSIDE;
}
const Real maxTThisPlane = maxT[whichPlane];
for( i = 0; i < 3; i++ )
{
if( i != whichPlane )
{
const Real f = origin[i] + maxTThisPlane * dir[i];
if ( f < ( pCorners[0][i] - 0.00001f ) ||
f > ( pCorners[4][i] + 0.00001f ) )
{
return OUTSIDE;
}
}
}
return INTERSECT;
}
//---------------------------------------------------------------------
/** Checks how the second box intersects with the first.
*/
291 Intersection intersect( const PlaneBoundedVolume &one, const AxisAlignedBox &two )
{
PagingLandScapeOctreeSceneManager::intersect_call++;
// Null box?
if ( two.isNull( ) )
return OUTSIDE;
if ( two.isInfinite( ) )
return INTERSECT;
// Get corners of the box
const Vector3 * const pCorners = two.getAllCorners( );
// For each plane, see if all points are on the negative side
// If so, object is not visible.
// If one or more are, it's partial.
// If all aren't, full
static const int corners[ 8 ] = {0, 4, 3, 5, 2, 6, 1, 7};
bool all_inside = true;
PlaneList::const_iterator i, iend = one.planes.end( );
for ( i = one.planes.begin( ); i != iend; ++i )
{
const Plane& plane = *i;
bool all_outside = true;
for ( unsigned int corner = 0; corner < 8; ++corner )
{
const Real distance = plane.getDistance( pCorners[ corners[ corner ] ] );
all_outside = all_outside && ( distance < 0 );
all_inside = all_inside && ( distance >= 0 );
if ( !all_outside && !all_inside )
break;
}
if ( all_outside )
return OUTSIDE;
}
if ( all_inside )
return INSIDE;
else
return INTERSECT;
}
//---------------------------------------------------------------------
/** Checks how the second box intersects with the first.
*/
338 Intersection intersect( const AxisAlignedBox &one, const AxisAlignedBox &two )
{
PagingLandScapeOctreeSceneManager::intersect_call++;
// Null box?
if ( one.isNull( ) || two.isNull( ) )
return OUTSIDE;
if ( one.isInfinite( ) )
return INSIDE;
if ( two.isInfinite( ) )
return INTERSECT;
const Vector3 * outside = one.getAllCorners( );
const Vector3 *inside = two.getAllCorners( );
if ( inside[ 4 ].x < outside[ 0 ].x ||
inside[ 4 ].y < outside[ 0 ].y ||
inside[ 4 ].z < outside[ 0 ].z ||
inside[ 0 ].x > outside[ 4 ].x ||
inside[ 0 ].y > outside[ 4 ].y ||
inside[ 0 ].z > outside[ 4 ].z )
{
return OUTSIDE;
}
const bool full = ( inside[ 0 ].x > outside[ 0 ].x &&
inside[ 0 ].y > outside[ 0 ].y &&
inside[ 0 ].z > outside[ 0 ].z &&
inside[ 4 ].x < outside[ 4 ].x &&
inside[ 4 ].y < outside[ 4 ].y &&
inside[ 4 ].z < outside[ 4 ].z );
if ( full )
return INSIDE;
else
return INTERSECT;
}
//---------------------------------------------------------------------
/** Checks how the box intersects with the sphere.
*/
379 Intersection intersect( const Sphere &one, const AxisAlignedBox &two )
{
PagingLandScapeOctreeSceneManager::intersect_call++;
// Null box?
if ( two.isNull( ) )
return OUTSIDE;
if ( two.isInfinite( ) )
return INTERSECT;
const Real sradius = Math::Sqr ( one.getRadius( ) );
const Vector3 scenter = one.getCenter( );
const Vector3 * const corners = two.getAllCorners( );
const Vector3 mndistance = ( corners[ 0 ] - scenter );
const Vector3 mxdistance = ( corners[ 4 ] - scenter );
if ( mndistance.squaredLength( ) < sradius &&
mxdistance.squaredLength( ) < sradius )
{
return INSIDE;
}
//find the square of the distance
//from the sphere to the box
Real d = 0;
for ( unsigned int i = 0 ; i < 3 ; i++ )
{
const Real sCenteri = scenter[ i ];
if ( sCenteri < corners[ 0 ][ i ] )
{
const Real s = sCenteri - corners[ 0 ][ i ];
d += s * s;
}
else if ( sCenteri > corners[ 4 ][ i ] )
{
const Real s = sCenteri - corners[ 4 ][ i ];
d += s * s;
}
}
const bool partial = ( d <= sradius );
if ( !partial )
{
return OUTSIDE;
}
else
{
return INTERSECT;
}
}
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
const String PagingLandScapeOctreeSceneManagerFactory::FACTORY_TYPE_NAME = "PagingLandScapeOctreeSceneManager";
//-----------------------------------------------------------------------
442 void PagingLandScapeOctreeSceneManagerFactory::initMetaData( void ) const
{
mMetaData.typeName = FACTORY_TYPE_NAME;
mMetaData.description = "Scene manager organising the scene on the basis of an octree, possibly using occlusion culling.";
mMetaData.sceneTypeMask = ST_EXTERIOR_REAL_FAR; // support all types
mMetaData.worldGeometrySupported = false;
}
//-----------------------------------------------------------------------
450 SceneManager* PagingLandScapeOctreeSceneManagerFactory::createInstance(
451 const String& instanceName )
{
return new PagingLandScapeOctreeSceneManager( instanceName );
}
//-----------------------------------------------------------------------
456 void PagingLandScapeOctreeSceneManagerFactory::destroyInstance( SceneManager* instance )
{
delete instance;
}
//---------------------------------------------------------------------
461 PagingLandScapeOctreeSceneManager::PagingLandScapeOctreeSceneManager( const String& name ):
SceneManager( name ),
mPagingLandScapeOctree( 0 ),
mCurrentOptionCamera( 0 )
{
mOctreeSet.setPoolSize ( 64 );
AxisAlignedBox b( -10000, -10000, -10000, 10000, 10000, 10000 );
int depth = 8;
init( b, depth );
}
//---------------------------------------------------------------------
472 PagingLandScapeOctreeSceneManager::PagingLandScapeOctreeSceneManager( const String& name, AxisAlignedBox &box, int max_depth ) :
SceneManager( name ),
mPagingLandScapeOctree( 0 )
{
init( box, max_depth );
}
//---------------------------------------------------------------------
479 const String& PagingLandScapeOctreeSceneManager::getTypeName( void ) const
{
return PagingLandScapeOctreeSceneManagerFactory::FACTORY_TYPE_NAME;
}
//---------------------------------------------------------------------
484 void PagingLandScapeOctreeSceneManager::init( const AxisAlignedBox &box, int depth )
{
delete mSceneRoot; //get rid of old root.
// -- Changes by Steve
// Don't do it this way, it will add it to the mSceneNodes which we don't want
//mSceneRoot = createSceneNode( "SceneRoot" );
mSceneRoot = new PagingLandScapeOctreeNode( this, "SceneRoot" );
mSceneRoot->_notifyRootNode( );
// -- End changes by Steve
if ( mPagingLandScapeOctree )
deleteOctree ( mPagingLandScapeOctree );
mPagingLandScapeOctree = mOctreeSet.getPoolable( );
assert ( mPagingLandScapeOctree );
mPagingLandScapeOctree->setSceneManager ( this );
mMaxDepth = depth;
mBox = box;
//mSceneRoot isn't put into the PagingLandScapeOctree since it has no volume.
mPagingLandScapeOctree->setBoundingBox ( box.getMinimum( ), box.getMaximum( ) );
#ifdef _VISIBILITYDEBUG
mShowBoxes = false;
mCullCamera = false;
// setDisplaySceneNodes( true );
#endif //_VISIBILITYDEBUG
mOcclusion.init ( this );
mOcclusionDepth = 0;
}
//---------------------------------------------------------------------
520 PagingLandScapeOctreeSceneManager::~PagingLandScapeOctreeSceneManager( )
{
// -- Changed by Steve
// Don't do this here, SceneManager will do it
/*
if( mSceneRoot )
delete mSceneRoot;
*/
// --End Changes by Steve
if ( mPagingLandScapeOctree )
{
deleteOctree ( mPagingLandScapeOctree );
mPagingLandScapeOctree = 0;
}
VisiblesPerCam::iterator i = mVisibles.begin ( );
while ( i != mVisibles.end( ) )
{
delete ( i->second );
++i;
}
mVisibles.clear( );
mOctreeSet.deletePool ( );
}
//---------------------------------------------------------------------
545 Camera * PagingLandScapeOctreeSceneManager::createCamera( const String &name )
{
if ( mCameras.find( name ) != mCameras.end( ) )
{
OGRE_EXCEPT(
Exception::ERR_DUPLICATE_ITEM,
"A camera with the name " + name + " already exists",
"PagingLandScapeSceneManager::createCamera" );
}
Camera * c = new PagingLandScapeOctreeCamera( name, this );
mCameras.insert( CameraList::value_type( name, c ) );
addCamera ( c );
return c;
}
//-----------------------------------------------------------------------
560 void PagingLandScapeOctreeSceneManager::addCamera( Camera *cam )
{
PagingLandScapeOctreeCamera *c = static_cast <PagingLandScapeOctreeCamera *> ( cam );
mVisibles[c->getId ( )] = new MovableObjectList( );
if ( !c->isRegisteredInOcclusionSystem( )
&& c->needRegistrationInOcclusionSystem( ) )
{
mPagingLandScapeOctree->traversal( RegisterCameraTraversal( c ), 0 );
c->setRegisteredInOcclusionSystem( true );
}
if ( !mCurrentOptionCamera )
mCurrentOptionCamera = c;
}
//-----------------------------------------------------------------------
574 void PagingLandScapeOctreeSceneManager::unregisterCamera( PagingLandScapeOctreeCamera *c )
{
VisiblesPerCam::iterator i = mVisibles.find ( c->getId ( ) );
if ( i != mVisibles.end( ) )
{
delete ( i->second );
mVisibles.erase( i );
}
if ( c->isRegisteredInOcclusionSystem ( ) )
{
mPagingLandScapeOctree->traversal ( UnregisterCameraTraversal( c ), 0 );
c->setRegisteredInOcclusionSystem ( false );
}
if ( mCurrentOptionCamera == c )
c = 0;
}
//-----------------------------------------------------------------------
591 void PagingLandScapeOctreeSceneManager::destroyCamera( Camera *cam )
{
SceneManager::destroyCamera( cam );
}
//-----------------------------------------------------------------------
596 void PagingLandScapeOctreeSceneManager::destroyCamera( const String& name )
{
// Find in list
CameraList::iterator i = mCameras.find( name );
if ( i != mCameras.end( ) )
{
unregisterCamera ( static_cast <PagingLandScapeOctreeCamera *> ( i->second ) );
SceneManager::destroyCamera ( name );
}
}
//-----------------------------------------------------------------------
607 void PagingLandScapeOctreeSceneManager::destroyAllCameras( void )
{
CameraList::iterator i = mCameras.begin( );
for ( ; i != mCameras.end( ); ++i )
{
unregisterCamera ( static_cast <PagingLandScapeOctreeCamera *> ( i->second ) );
// Notify render system
mDestRenderSystem->_notifyCameraRemoved( i->second );
delete i->second;
}
mCameras.clear ( );
}
//---------------------------------------------------------------------
620 void PagingLandScapeOctreeSceneManager::destroySceneNode( const String &name )
{
PagingLandScapeOctreeNode * on = static_cast < PagingLandScapeOctreeNode* > ( SceneManager::getSceneNode( name ) );
if ( on != 0 )
_removePagingLandScapeOctreeNode( on );
SceneManager::destroySceneNode( name );
}
//---------------------------------------------------------------------
630 bool PagingLandScapeOctreeSceneManager::getOptionValues( const String & key, StringVector &refValueList )
{
return SceneManager::getOptionValues( key, refValueList );
}
//---------------------------------------------------------------------
635 bool PagingLandScapeOctreeSceneManager::getOptionKeys( StringVector & refKeys )
{
SceneManager::getOptionKeys( refKeys );
refKeys.push_back( "CullCamera" );
refKeys.push_back( "Size" );
refKeys.push_back( "ShowPagingLandScapeOctree" );
refKeys.push_back( "Depth" );
return true;
}
//---------------------------------------------------------------------
647 void PagingLandScapeOctreeSceneManager::_updatePagingLandScapeOctreeNode( PagingLandScapeOctreeNode * onode )
{
const AxisAlignedBox box = onode->_getWorldAABB( );
if ( box.isNull( ) )
return ;
// Skip if octree has been destroyed ( shutdown conditions )
if ( !mPagingLandScapeOctree )
return;
if ( onode->getOctant( ) == 0 )
{
//if outside the PagingLandScapeOctree, force into the root node.
if ( ! onode->_isIn( mPagingLandScapeOctree->getBoundingBox( ) ) )
mPagingLandScapeOctree->_addNode( onode );
else
_addPagingLandScapeOctreeNode( onode, mPagingLandScapeOctree );
return ;
}
if ( ! onode->_isIn( onode->getOctant( )->getBoundingBox( ) ) )
{
_removePagingLandScapeOctreeNode( onode );
//if outside the PagingLandScapeOctree, force into the root node.
if ( ! onode->_isIn( mPagingLandScapeOctree->getBoundingBox( ) ) )
mPagingLandScapeOctree->_addNode( onode );
else
_addPagingLandScapeOctreeNode( onode, mPagingLandScapeOctree );
}
}
//---------------------------------------------------------------------
/** Only removes the node from the PagingLandScapeOctree. It leaves the PagingLandScapeOctree, even if it's empty.
*/
682 void PagingLandScapeOctreeSceneManager::_removePagingLandScapeOctreeNode( PagingLandScapeOctreeNode * n )
{
assert ( n );
// Skip if octree has been destroyed ( shutdown conditions )
if ( !mPagingLandScapeOctree )
return;
PagingLandScapeOctree * oct = n->getOctant( );
if ( oct )
oct->_removeNode ( n );
n->setOctant ( 0 );
unregisteredNodeInCamera ( n );
}
//---------------------------------------------------------------------
697 void PagingLandScapeOctreeSceneManager::_addPagingLandScapeOctreeMovableNode( PagingLandScapeOctreeNode * n,
698 PagingLandScapeOctree *octant,
int depth )
{
const AxisAlignedBox bx = n->_getWorldAABB( );
//if the PagingLandScapeOctree is twice as big as the scene node,
//we will add it to a child.
if ( ( depth < mMaxDepth ) && octant->_isTwiceSize ( bx ) )
{
_addPagingLandScapeOctreeMovableNode( n,
octant->_getChildWhereBoxFits( bx, this ),
++depth );
}
else
{
#ifdef _VISIBILITYDEBUG
n ->setDebugCorners( this );
#endif //_VISIBILITYDEBUG
#ifdef _DEBUG
std::cout << "Depth Placement "
<< StringConverter::toString ( depth )
<< " \n";
#endif //_DEBUG
octant->_addNode( n );
}
}
//---------------------------------------------------------------------
727 void PagingLandScapeOctreeSceneManager::_addPagingLandScapeOctreeStaticNode( PagingLandScapeOctreeNode * n,
728 PagingLandScapeOctree *octant,
int depth )
{
const AxisAlignedBox bx = n->_getWorldAABB( );
//if the PagingLandScapeOctree is twice as big as the scene node,
//we will add it to a child.
if ( ( depth < mMaxDepth ) && octant->_isTwiceCullSize ( bx ) )
{
if ( octant->_isNotCrossingAxes( bx ) )
{
_addPagingLandScapeOctreeStaticNode( n,
octant->_getCullChildWhereBoxFits( bx, this ),
++depth );
}
else
{
// re-insert it as a moving node, therefore avoiding crossing problem.
n->setStaticCulling ( false );
_addPagingLandScapeOctreeMovableNode( n,
mPagingLandScapeOctree,
0 );
}
}
else
{
#ifdef _VISIBILITYDEBUG
n ->setDebugCorners( this );
#endif //_VISIBILITYDEBUG
octant->_addNode( n );
}
}
//---------------------------------------------------------------------
761 void PagingLandScapeOctreeSceneManager::_addPagingLandScapeOctreeNode( PagingLandScapeOctreeNode * n, PagingLandScapeOctree *octant, int depth )
{
assert ( n && octant );
if ( n->isStaticNode ( ) )
_addPagingLandScapeOctreeStaticNode( n, octant, depth );
else
_addPagingLandScapeOctreeMovableNode( n, octant, depth );
registeredNodeInCamera ( n );
}
//---------------------------------------------------------------------
771 SceneNode * PagingLandScapeOctreeSceneManager::createSceneNode( void )
{
PagingLandScapeOctreeNode * on = new PagingLandScapeOctreeNode( this );
mSceneNodes[ on->getName( ) ] = on;
return on;
}
//---------------------------------------------------------------------
778 SceneNode * PagingLandScapeOctreeSceneManager::createSceneNode( const String &name )
{
// Check name not used
if ( mSceneNodes.find( name ) != mSceneNodes.end( ) )
{
OGRE_EXCEPT(
Exception::ERR_DUPLICATE_ITEM,
"A scene node with the name " + name + " already exists",
"PagingLandScapeOctreeSceneManager::createSceneNode" );
}
PagingLandScapeOctreeNode * on = new PagingLandScapeOctreeNode( this, name );
mSceneNodes[ on->getName( ) ] = on;
return on;
}
//---------------------------------------------------------------------
793 void PagingLandScapeOctreeSceneManager::registeredNodeInCamera( OcclusionElement *on )
{
// register existing camera in nodes
bool isRegistered = false;
for ( CameraList::iterator it = mCameras.begin( ); it != mCameras.end( ); ++it )
{
// Notify occlusion system
PagingLandScapeOctreeCamera *c = static_cast <PagingLandScapeOctreeCamera *> ( it->second );
assert ( c );
if ( c->isRegisteredInOcclusionSystem ( ) )
{
on->traversal ( RegisterCameraTraversal( c ), 0 );
isRegistered = true;
}
}
on->setRegisteredtoCam ( isRegistered );
}
//---------------------------------------------------------------------
811 void PagingLandScapeOctreeSceneManager::unregisteredNodeInCamera( OcclusionElement *on )
{
// register existing camera in nodes
for ( CameraList::iterator it = mCameras.begin( );it != mCameras.end( ); ++it )
{
// Notify occlusion system
PagingLandScapeOctreeCamera *c = static_cast <PagingLandScapeOctreeCamera *> ( it->second );
assert ( c );
if ( c->isRegisteredInOcclusionSystem ( ) )
on->traversal ( UnregisterCameraTraversal( c ), 0 );
}
on->setRegisteredtoCam ( false );
}
//---------------------------------------------------------------------
825 void PagingLandScapeOctreeSceneManager::_updateSceneGraph( Camera * cam )
{
SceneManager::_updateSceneGraph( cam );
}
//---------------------------------------------------------------------
830 void PagingLandScapeOctreeSceneManager::enableHardwareOcclusionTests( )
{
Camera * const c_cam = mCameraInProgress;
// make sure we always occlude in SOLID MODE
mCamDetail = c_cam->getPolygonMode ( );
if ( mCamDetail != PM_SOLID )
{
mOcclusion.setIfNotSolidScene ( true );
c_cam->setPolygonMode ( PM_SOLID );
}
else
{
mOcclusion.setIfNotSolidScene ( false );
}
//#define HWOCCLUSIONRTT
#ifdef HWOCCLUSIONRTT
const Viewport * const c_camViewPort = c_cam->getViewport( );
assert ( c_camViewPort );
if ( mOcclusionDepth == 0 )
{
mOcclusionDepth = mDestRenderSystem->
createRenderTexture(
"OcclusionDepthTexture",
c_camViewPort->getActualWidth( ) / 8,
c_camViewPort->getActualHeight( ) / 8,
TEX_TYPE_2D,
PF_DEPTH );
mOcclusionDepth->setAutoUpdated ( false );
mOcclusionDepth->setActive ( false );
mOcclusionCamera = createCamera ( "OcclusionDepthTextureCamera" );
Viewport * const v = mOcclusionDepth->addViewport( mOcclusionCamera );
assert ( v );
v->setOverlaysEnabled ( false );
v->setClearEveryFrame( false );
v->setBackgroundColour( ColourValue::Black );
#define RENDERCOLOR
#ifdef RENDERCOLOR
MaterialPtr mat = MaterialManager::getSingleton( ).create (
"OcclusionDepthTextureMat",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );
mat->getTechnique( 0 )->getPass( 0 )->createTextureUnitState( "OcclusionDepthTexture" );
Overlay *OcclusionDepthOverlay = OverlayManager::getSingleton ( ).create( "OcclusionDepthOverlay" );
OverlayElement *OcclusionDepthPanel =
OverlayManager::getSingleton ( ).createOverlayElement ( "Panel",
"OcclusionDepthPanel",
false );
OcclusionDepthPanel->setMaterialName ( "OcclusionDepthTextureMat" );
OcclusionDepthOverlay->add2D ( ( OverlayContainer * )OcclusionDepthPanel );
OcclusionDepthOverlay->show ( );
//OcclusionDepthOverlay->setScale ( 0.5f, 0.5f );
OcclusionDepthPanel->setPosition ( 0.8, 0.8 );
#endif //RENDERCOLOR
mOcclusionCamera->setNearClipDistance( c_cam->getNearClipDistance( ) );
mOcclusionCamera->setFarClipDistance( c_cam->getFarClipDistance( ) );
mOcclusionCamera->setAspectRatio(
( Real )c_camViewPort->getActualWidth( ) / c_camViewPort->getActualHeight( ) );
}
// copy camera characteristics to occlusion camera.
mOcclusionCamera->setPosition ( c_cam->getWorldPosition ( ) );
mOcclusionCamera->setOrientation ( c_cam->getWorldOrientation ( ) );
mOcclusionCamera->setNearClipDistance( c_cam->getNearClipDistance( ) );
mOcclusionCamera->setFarClipDistance( c_cam->getFarClipDistance( ) );
mDestRenderSystem->_setViewport( mOcclusionCamera->getViewport ( ) );
mDestRenderSystem->_setWorldMatrix( Matrix4::IDENTITY );
mDestRenderSystem->_setViewMatrix( c_cam->getViewMatrix( ) );
mDestRenderSystem->_setProjectionMatrix( c_cam->getProjectionMatrix( ) );
mDestRenderSystem->_beginFrame( );
mDestRenderSystem->clearFrameBuffer ( FBT_DEPTH | FBT_COLOUR,
mOcclusionCamera->getViewport ( )->getBackgroundColour ( ) );
#else //HWOCCLUSIONRTT
assert ( c_cam->getViewport( ) );
mDestRenderSystem->_setViewport( c_cam->getViewport( ) );
mDestRenderSystem->clearFrameBuffer ( FBT_DEPTH | FBT_COLOUR,
c_cam->getViewport ( )->getBackgroundColour ( ), //color
1.0f, //depth
0 );//stencil
mDestRenderSystem->_beginFrame( );
assert ( c_cam->getViewport( )->getClearEveryFrame ( ) == false );
#endif //HWOCCLUSIONRTT
mDestRenderSystem->_beginGeometryCount( );
}
//---------------------------------------------------------------------
931 void PagingLandScapeOctreeSceneManager::disableHardwareOcclusionTests( )
{
PagingLandScapeOctreeCamera * const octreeCam = static_cast <PagingLandScapeOctreeCamera *> ( mCameraInProgress );
assert ( octreeCam->getViewport ( ) );
#ifdef HWOCCLUSIONRTT
mDestRenderSystem->_endFrame( );
mDestRenderSystem->_setViewport( octreeCam->getViewport ( ) );
#else //HWOCCLUSIONRTT
mDestRenderSystem->_endFrame( );
#endif //HWOCCLUSIONRTT
if ( mCamDetail != PM_SOLID )
{
mDestRenderSystem->clearFrameBuffer ( FBT_DEPTH | FBT_COLOUR,
octreeCam->getViewport ( )->getBackgroundColour ( ), //color
1.0f, //depth
0 );//stencil
}
// make sure we restore previous detail level.
octreeCam->setPolygonMode ( mCamDetail );
// Notify camera or vis faces
octreeCam->_addCHCRenderedFaces( mDestRenderSystem->_getFaceCount( ) );
}
//---------------------------------------------------------------------
#ifdef PLSM2_EIHORT
961 void PagingLandScapeOctreeSceneManager::_findVisibleObjects( Camera* cam, VisibleObjectsBoundsInfo * visibleBounds, bool onlyShadowCasters )
#else
void PagingLandScapeOctreeSceneManager::_findVisibleObjects( Camera * cam, bool onlyShadowCasters )
#endif
{
RenderQueue *q = SceneManager::getRenderQueue( );
PagingLandScapeOctreeCamera * const octreeCam = static_cast <PagingLandScapeOctreeCamera *> ( cam );
assert ( mVisibles.find( octreeCam->getId( ) ) != mVisibles.end( ) );
mCamInProgressVisibles = mVisibles[octreeCam->getId( )];
assert ( mCamInProgressVisibles );
#ifdef _VISIBILITYDEBUG
/*
if ( !octreeCam->isRegisteredInOcclusionSystem( ) )
{
mPagingLandScapeOctree->traversal( RegisterCameraTraversal( octreeCam ) );
octreeCam->setRegisteredInOcclusionSystem( true );
}
*/
mBoxes.clear( );
if ( mCullCamera )
{
if ( getCamera( "CullCamera" ) )
cam = getCamera( "CullCamera" );
}
#endif // _VISIBILITYDEBUG
if ( mPagingLandScapeOctree->hasChildren ( ) )
{
mNumObjects = 0;
// should find a way to be sure that
// it's a new frame, and not just a camera change or something.
if ( mOcclusion.nextFrame ( static_cast < PagingLandScapeOctreeCamera * > ( cam ),
mCamInProgressVisibles,
onlyShadowCasters,
q ) )
{
switch ( octreeCam->getOcclusionMode( ) )
{
case CHC:
{
enableHardwareOcclusionTests( );
mOcclusion.CHCtraversal ( mPagingLandScapeOctree, visibleBounds );
disableHardwareOcclusionTests( );
q->clear( );
#ifdef _VISIBILITYDEBUG
if ( mCullDebug && cam->getViewport ( ) )
{
mDebugText =(
"CHC = " + StringConverter::toString( mOcclusion.object_cnt ) + ", t=" +
StringConverter::toString( mOcclusion.traversed_nodes_cnt ) + ", f=" +
StringConverter::toString( mOcclusion.frustum_culled_nodes_cnt ) + ", q=" +
StringConverter::toString( mOcclusion.query_cnt )
);
}
#endif //_VISIBILITYDEBUG
}
break;
case CHC_CONSERVATIVE:
{
enableHardwareOcclusionTests( );
mOcclusion.CHCtraversalConservative ( mPagingLandScapeOctree, visibleBounds );
disableHardwareOcclusionTests( );
q->clear( );
#ifdef _VISIBILITYDEBUG
if ( mCullDebug && cam->getViewport ( ) )
{
mDebugText =(
"CHC Conservative = " + StringConverter::toString( mOcclusion.object_cnt ) + ", t=" +
StringConverter::toString( mOcclusion.traversed_nodes_cnt ) + ", f=" +
StringConverter::toString( mOcclusion.frustum_culled_nodes_cnt ) + ", q=" +
StringConverter::toString( mOcclusion.query_cnt )
);
}
#endif //_VISIBILITYDEBUG
}
break;
// case STOP_AND_WAIT:
// {
// enableHardwareOcclusionTests( );
// mOcclusion.initQueryPool ( );
// mPagingLandScapeOctree->traversal ( SWTraversal ( mOcclusion ), visibleBounds );
// disableHardwareOcclusionTests( ); q->clear( );
//
// #ifdef _VISIBILITYDEBUG
// if ( mCullDebug && cam->getViewport ( ) ) {cam->getViewport ( )->getTarget ( )->setDebugText(
// "SnW = " + StringConverter::toString( mOcclusion.object_cnt ) + ", t=" +
// StringConverter::toString( mOcclusion.traversed_nodes_cnt ) + ", f=" +
// StringConverter::toString( mOcclusion.frustum_culled_nodes_cnt ) + ", q=" +
// StringConverter::toString( mOcclusion.query_cnt )
// );}
//
// #endif //_VISIBILITYDEBUG
//
// }
// break;
// case VIEW_FRUSTUM:
// {
// mPagingLandScapeOctree->traversal ( ViewFrustumCullingTraversal ( mOcclusion ), visibleBounds );
// q->clear( );
// #ifdef _VISIBILITYDEBUG
// if ( mCullDebug && cam->getViewport ( ) )
// { cam->getViewport ( )->getTarget ( )->setDebugText(
// "VF = " + StringConverter::toString( mOcclusion.object_cnt ) + ", t=" +
// StringConverter::toString( mOcclusion.traversed_nodes_cnt ) + ", f=" +
// StringConverter::toString( mOcclusion.frustum_culled_nodes_cnt ) + ", q=" +
// StringConverter::toString( mOcclusion.query_cnt )
// );}
//
// #endif //_VISIBILITYDEBUG
// }
// break;
case VIEW_FRUSTUM_DIRECT:
{
ViewFrustumCullingTraversalDirect temp ( mOcclusion );
mPagingLandScapeOctree->traversal ( temp, visibleBounds );
#ifdef _VISIBILITYDEBUG
if ( mCullDebug && cam->getViewport ( ) )
{
mDebugText =(
"VFD = " + StringConverter::toString( mOcclusion.object_cnt ) + ", t=" +
StringConverter::toString( mOcclusion.traversed_nodes_cnt ) + ", f=" +
StringConverter::toString( mOcclusion.frustum_culled_nodes_cnt ) + ", q=" +
StringConverter::toString( mOcclusion.query_cnt )
);
}
#endif // _VISIBILITYDEBUG
}
break;
default:
assert ( 0 );
break;
}
}
if ( !mCamInProgressVisibles->empty( ) )
{
MovableObjectList::iterator movableIt = mCamInProgressVisibles->begin( );
MovableObjectList::iterator mitend = mCamInProgressVisibles->end( );
while ( movableIt != mitend )
{
( *movableIt )->_updateRenderQueue ( q );
++movableIt;
}
}
#ifdef _VISIBILITYDEBUG
if ( mCullDebug )
{
mPagingLandScapeOctree->traversal ( TreeOverlayDebug ( mOcclusion, this ), visibleBounds );
}
#endif // _VISIBILITYDEBUG
}
}
//---------------------------------------------------------------------
1123 void PagingLandScapeOctreeSceneManager::addVisible( MovableObject *mo )
{
mCamInProgressVisibles->push_back ( mo );
}
//---------------------------------------------------------------------
1128 void PagingLandScapeOctreeSceneManager::directRenderSingleQueue( RenderQueue *queue )
{
RenderQueue *oldQueue = mRenderQueue;
mRenderQueue = queue;
SceneManager::_renderVisibleObjects ( );
queue->clear ( );
mRenderQueue = oldQueue;
}
//---------------------------------------------------------------------
1139 void PagingLandScapeOctreeSceneManager::directRenderSingleObject( Renderable *r )
{
const Camera * const c_cam = mCameraInProgress;
mDestRenderSystem->_setWorldMatrix( Matrix4::IDENTITY );
// mDestRenderSystem->_setViewMatrix( c_cam->getViewMatrix( ) );
// mDestRenderSystem->_setProjectionMatrix( c_cam->getProjectionMatrix( ) );
mDestRenderSystem->setCurrentPassIterationCount( 1 );
_setPass( r->getMaterial( )->getBestTechnique( )->getPass( 0 ) );
useRenderableViewProjMode ( r );
RenderOperation ro;
r->getRenderOperation ( ro );
mDestRenderSystem->_render( ro );
}
//---------------------------------------------------------------------
1156 void PagingLandScapeOctreeSceneManager::registerCamera ( PagingLandScapeOctreeCamera *c )
{
mPagingLandScapeOctree->traversal( RegisterCameraTraversal( c ), 0 );
}
//---------------------------------------------------------------------
// --- non template versions
1162 void _findNodes( const AxisAlignedBox &t, std::list < SceneNode * > &list,
const Ogre::SceneNode * const exclude, const bool full, PagingLandScapeOctree *octant )
{
bool isFull = full;
if ( !full )
{
AxisAlignedBox obox;
octant->_getCullBounds( &obox );
const Intersection isect = intersect( t, obox );
if ( isect == OUTSIDE )
return ;
isFull = ( isect == INSIDE );
}
const bool b_full = isFull;
NodeList::iterator it = octant->mNodes.begin( );
while ( it != octant->mNodes.end( ) )
{
PagingLandScapeOctreeNode * const on = ( *it );
if ( on != exclude )
{
if ( b_full )
{
list.push_back( on );
}
else
{
const Intersection nsect = intersect( t, on->_getWorldAABB( ) );
if ( nsect != OUTSIDE )
{
list.push_back( on );
}
}
}
++it;
}
if ( octant->mChildren[ 0 ][ 0 ][ 0 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 0 ][ 0 ][ 0 ] );
if ( octant->mChildren[ 1 ][ 0 ][ 0 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 1 ][ 0 ][ 0 ] );
if ( octant->mChildren[ 0 ][ 1 ][ 0 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 0 ][ 1 ][ 0 ] );
if ( octant->mChildren[ 1 ][ 1 ][ 0 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 1 ][ 1 ][ 0 ] );
if ( octant->mChildren[ 0 ][ 0 ][ 1 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 0 ][ 0 ][ 1 ] );
if ( octant->mChildren[ 1 ][ 0 ][ 1 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 1 ][ 0 ][ 1 ] );
if ( octant->mChildren[ 0 ][ 1 ][ 1 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 0 ][ 1 ][ 1 ] );
if ( octant->mChildren[ 1 ][ 1 ][ 1 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 1 ][ 1 ][ 1 ] );
}
//---------------------------------------------------------------------
1238 void _findNodes( const Sphere &t, std::list < SceneNode * > &list,
const SceneNode * const exclude,
const bool full, PagingLandScapeOctree *octant )
{
bool isFull = full;
if ( !full )
{
AxisAlignedBox obox;
octant->_getCullBounds( &obox );
const Intersection isect = intersect( t, obox );
if ( isect == OUTSIDE )
return ;
isFull = ( isect == INSIDE );
}
const bool b_full = isFull;
NodeList::iterator it = octant->mNodes.begin( );
while ( it != octant->mNodes.end( ) )
{
PagingLandScapeOctreeNode * const on = ( *it );
if ( on != exclude )
{
if ( b_full )
{
list.push_back( on );
}
else
{
const Intersection nsect = intersect( t, on->_getWorldAABB( ) );
if ( nsect != OUTSIDE )
{
list.push_back( on );
}
}
}
++it;
}
if ( octant->mChildren[ 0 ][ 0 ][ 0 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 0 ][ 0 ][ 0 ] );
if ( octant->mChildren[ 1 ][ 0 ][ 0 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 1 ][ 0 ][ 0 ] );
if ( octant->mChildren[ 0 ][ 1 ][ 0 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 0 ][ 1 ][ 0 ] );
if ( octant->mChildren[ 1 ][ 1 ][ 0 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 1 ][ 1 ][ 0 ] );
if ( octant->mChildren[ 0 ][ 0 ][ 1 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 0 ][ 0 ][ 1 ] );
if ( octant->mChildren[ 1 ][ 0 ][ 1 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 1 ][ 0 ][ 1 ] );
if ( octant->mChildren[ 0 ][ 1 ][ 1 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 0 ][ 1 ][ 1 ] );
if ( octant->mChildren[ 1 ][ 1 ][ 1 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 1 ][ 1 ][ 1 ] );
}
//---------------------------------------------------------------------
1313 void _findNodes( const PlaneBoundedVolume &t, std::list < SceneNode * > &list,
const Ogre::SceneNode * const exclude, const bool full, PagingLandScapeOctree *octant )
{
bool isFull = full;
if ( !full )
{
AxisAlignedBox obox;
octant->_getCullBounds( &obox );
const Intersection isect = intersect( t, obox );
if ( isect == OUTSIDE )
return ;
isFull = ( isect == INSIDE );
}
const bool b_full = isFull;
NodeList::iterator it = octant->mNodes.begin( );
while ( it != octant->mNodes.end( ) )
{
PagingLandScapeOctreeNode * const on = ( *it );
if ( on != exclude )
{
if ( b_full )
{
list.push_back( on );
}
else
{
const Intersection nsect = intersect( t, on->_getWorldAABB( ) );
if ( nsect != OUTSIDE )
{
list.push_back( on );
}
}
}
++it;
}
if ( octant->mChildren[ 0 ][ 0 ][ 0 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 0 ][ 0 ][ 0 ] );
if ( octant->mChildren[ 1 ][ 0 ][ 0 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 1 ][ 0 ][ 0 ] );
if ( octant->mChildren[ 0 ][ 1 ][ 0 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 0 ][ 1 ][ 0 ] );
if ( octant->mChildren[ 1 ][ 1 ][ 0 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 1 ][ 1 ][ 0 ] );
if ( octant->mChildren[ 0 ][ 0 ][ 1 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 0 ][ 0 ][ 1 ] );
if ( octant->mChildren[ 1 ][ 0 ][ 1 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 1 ][ 0 ][ 1 ] );
if ( octant->mChildren[ 0 ][ 1 ][ 1 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 0 ][ 1 ][ 1 ] );
if ( octant->mChildren[ 1 ][ 1 ][ 1 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 1 ][ 1 ][ 1 ] );
}
//---------------------------------------------------------------------
1383 void _findNodes( const Ray &t, std::list < SceneNode * > &list,
const Ogre::SceneNode * const exclude,
const bool full, PagingLandScapeOctree *octant )
{
bool isFull = full;
if ( !full )
{
AxisAlignedBox obox;
octant->_getCullBounds( &obox );
const Intersection isect = intersect( t, obox );
if ( isect == OUTSIDE )
return ;
isFull = ( isect == INSIDE );
}
const bool b_full = isFull;
if ( !octant->mNodes.empty ( ) )
{
NodeList::iterator it = octant->mNodes.begin( );
while ( it != octant->mNodes.end( ) )
{
PagingLandScapeOctreeNode * const on = ( *it );
if ( on != exclude )
{
if ( b_full )
{
list.push_back( on );
}
else
{
const Intersection nsect = intersect( t, on->_getWorldAABB( ) );
if ( nsect != OUTSIDE )
list.push_back( on );
}
}
++it;
}
}
if ( octant->hasChildren ( ) )
{
if ( octant->mChildren[ 0 ][ 0 ][ 0 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 0 ][ 0 ][ 0 ] );
if ( octant->mChildren[ 1 ][ 0 ][ 0 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 1 ][ 0 ][ 0 ] );
if ( octant->mChildren[ 0 ][ 1 ][ 0 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 0 ][ 1 ][ 0 ] );
if ( octant->mChildren[ 1 ][ 1 ][ 0 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 1 ][ 1 ][ 0 ] );
if ( octant->mChildren[ 0 ][ 0 ][ 1 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 0 ][ 0 ][ 1 ] );
if ( octant->mChildren[ 1 ][ 0 ][ 1 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 1 ][ 0 ][ 1 ] );
if ( octant->mChildren[ 0 ][ 1 ][ 1 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 0 ][ 1 ][ 1 ] );
if ( octant->mChildren[ 1 ][ 1 ][ 1 ] != 0 )
_findNodes( t, list, exclude, b_full, octant->mChildren[ 1 ][ 1 ][ 1 ] );
}
}
//---------------------------------------------------------------------
1453 void PagingLandScapeOctreeSceneManager::findNodesIn( const AxisAlignedBox &box, std::list < SceneNode * > &list, const SceneNode* const exclude )
{
_findNodes( box, list, exclude, false, mPagingLandScapeOctree );
}
//---------------------------------------------------------------------
1458 void PagingLandScapeOctreeSceneManager::findNodesIn( const Sphere &sphere, std::list < SceneNode * > &list, const SceneNode* const exclude )
{
_findNodes( sphere, list, exclude, false, mPagingLandScapeOctree );
}
//---------------------------------------------------------------------
1463 void PagingLandScapeOctreeSceneManager::findNodesIn( const PlaneBoundedVolume &volume, std::list < SceneNode * > &list, const SceneNode* const exclude )
{
_findNodes( volume, list, exclude, false, mPagingLandScapeOctree );
}
//---------------------------------------------------------------------
1468 void PagingLandScapeOctreeSceneManager::findNodesIn( const Ray &r, std::list < SceneNode * > &list, const SceneNode* const exclude )
{
_findNodes( r, list, exclude, false, mPagingLandScapeOctree );
}
//---------------------------------------------------------------------
1473 void PagingLandScapeOctreeSceneManager::resize( const AxisAlignedBox &box, const int depth )
{
mMaxDepth = depth;
resize( box );
}
//---------------------------------------------------------------------
1479 void PagingLandScapeOctreeSceneManager::resize( const AxisAlignedBox &box )
{
std::list < SceneNode * > nodes;
_findNodes( mPagingLandScapeOctree->getBoundingBox ( ), nodes, 0, true, mPagingLandScapeOctree );
if ( mPagingLandScapeOctree )
deleteOctree ( mPagingLandScapeOctree );
mBox = box;
mPagingLandScapeOctree = mOctreeSet.getPoolable( );
assert ( mPagingLandScapeOctree );
mPagingLandScapeOctree->setSceneManager ( this );
mPagingLandScapeOctree ->setBoundingBox ( box.getMinimum( ), box.getMaximum( ) );
registeredNodeInCamera ( mPagingLandScapeOctree );
if ( !nodes.empty( ) )
{
std::list < SceneNode * > ::iterator it;
it = nodes.begin( );
while ( it != nodes.end( ) )
{
PagingLandScapeOctreeNode * const on = static_cast < PagingLandScapeOctreeNode * > ( *it );
on->setOctant( 0 );
_updatePagingLandScapeOctreeNode( on );
++it;
} // while ( it != nodes.end( ) )
}
}
//---------------------------------------------------------------------
1510 bool PagingLandScapeOctreeSceneManager::setOption( const String & key, const void * val )
{
if ( key == "Size" )
{
resize( * static_cast < const AxisAlignedBox * > ( val ) );
return true;
}
else if ( key == "Depth" )
{
assert ( mPagingLandScapeOctree );
mMaxDepth = * static_cast < const int * > ( val );
// copy the box since resize will delete mOctree and reference won't work
AxisAlignedBox box = mPagingLandScapeOctree->getBoundingBox( );
resize( box );
return true;
}
else if ( key == "NextCullMode" )
{
if ( val )
{
CameraList::iterator it = mCameras.find ( static_cast < const PagingLandScapeOctreeCamera * > ( val )->getName( ) );
if ( it != mCameras.end( ) )
{
static_cast < PagingLandScapeOctreeCamera * > ( it->second )->setNextOcclusionMode( );
return true;
}
}
return false;
}
else if ( key == "setNumberOfConservativeFrames" )
{
mOcclusion.setNumberOfConservativeFrames( *( static_cast < const unsigned int * > ( val ) ) );
}
else if ( key == "CurrentOptionCamera" )
{
if ( val )
{
CameraList::iterator it = mCameras.find ( static_cast < const PagingLandScapeOctreeCamera * > ( val )->getName( ) );
if ( it != mCameras.end( ) )
{
mCurrentOptionCamera = static_cast < PagingLandScapeOctreeCamera * > ( it->second );
}
return true;
}
}
else if ( key == "setCullingMode" )
{
assert ( mCurrentOptionCamera );
mCurrentOptionCamera->setOcclusionModeAsString( * static_cast < const String * > ( val ) );
return true;
}
#ifdef _VISIBILITYDEBUG
else if ( key == "ShowPagingLandScapeOctree" )
{
mShowBoxes = * static_cast < const bool * > ( val );
return true;
}
else if ( key == "CullDebug" )
{
mCullDebug = * static_cast < const bool * > ( val );
return true;
}
else if ( key == "CullCamera" )
{
mCullCamera = * static_cast < const bool * > ( val );
return true;
}
#endif //_VISIBILITYDEBUG
return SceneManager::setOption( key, val );
}
//---------------------------------------------------------------------
1584 bool PagingLandScapeOctreeSceneManager::getOption( const String & key, void *val )
{
if ( key == "Size" )
{
AxisAlignedBox * b = static_cast < AxisAlignedBox * > ( val );
b->setExtents( mPagingLandScapeOctree->getBoundingBox ( ).getMinimum( ), mPagingLandScapeOctree->getBoundingBox( ).getMaximum( ) );
return true;
}
else if ( key == "Depth" )
{
* static_cast < int * > ( val ) = mMaxDepth;
return true;
}
else if ( key == "setNumberOfConservativeFrames" )
{
* static_cast < unsigned int * > ( val ) = mOcclusion.getNumberOfConservativeFrames( );
return true;
}
else if ( key == "CurrentOptionCamera" )
{
*static_cast < String * > ( val ) = mCurrentOptionCamera->getName( );
return true;
}
else if ( key == "getCullingMode" )
{
assert ( mCurrentOptionCamera );
*static_cast < String * > ( val ) = mCurrentOptionCamera->getOcclusionModeAsString( );
return true;
}
#ifdef _VISIBILITYDEBUG
else if ( key == "ShowPagingLandScapeOctree" )
{
* static_cast < bool * > ( val ) = mShowBoxes;
return true;
}
else if ( key == "CullCamera" )
{
* static_cast < bool * > ( val ) = mCullCamera;
return true;
}
else if ( key == "CullDebug" )
{
* static_cast < bool * > ( val ) = mCullDebug;
return true;
}
else if ( key == "DebugText" )
{
* static_cast < String * > ( val ) = mDebugText;
return true;
}
#endif //_VISIBILITYDEBUG
return SceneManager::getOption( key, val );
}
//---------------------------------------------------------------------
1642 void PagingLandScapeOctreeSceneManager::clearScene( void )
{
SceneManager::clearScene( );
// reset cameras
//CameraList::iterator iCam = mCameras.begin( );
//for ( ; iCam != mCameras.end( ); ++iCam )
//{
// PagingLandScapeOctreeCamera *cam = static_cast <PagingLandScapeOctreeCamera *> ( iCam->second );
// if ( cam->isRegisteredInOcclusionSystem ( ) )
// {
// mPagingLandScapeOctree->traversal ( UnregisterCameraTraversal( cam ) );
// cam->setRegisteredInOcclusionSystem ( false );
// }
//}
init( mBox, mMaxDepth );
}
//---------------------------------------------------------------------
AxisAlignedBoxSceneQuery*
1663 PagingLandScapeOctreeSceneManager::createAABBQuery( const AxisAlignedBox& box, unsigned long mask )
{
PagingLandScapeOctreeAxisAlignedBoxSceneQuery* q = new PagingLandScapeOctreeAxisAlignedBoxSceneQuery( this );
q->setBox( box );
q->setQueryMask( mask );
return q;
}
//---------------------------------------------------------------------
SphereSceneQuery*
1672 PagingLandScapeOctreeSceneManager::createSphereQuery( const Sphere& sphere, unsigned long mask )
{
PagingLandScapeOctreeSphereSceneQuery* q = new PagingLandScapeOctreeSphereSceneQuery( this );
q->setSphere( sphere );
q->setQueryMask( mask );
return q;
}
//---------------------------------------------------------------------
PlaneBoundedVolumeListSceneQuery*
1681 PagingLandScapeOctreeSceneManager::createPlaneBoundedVolumeQuery( const PlaneBoundedVolumeList& volumes,
unsigned long mask )
{
PagingLandScapeOctreePlaneBoundedVolumeListSceneQuery* q = new PagingLandScapeOctreePlaneBoundedVolumeListSceneQuery( this );
q->setVolumes( volumes );
q->setQueryMask( mask );
return q;
}
//---------------------------------------------------------------------
RaySceneQuery*
1692 PagingLandScapeOctreeSceneManager::createRayQuery( const Ray& ray, unsigned long mask )
{
PagingLandScapeOctreeRaySceneQuery* q = new PagingLandScapeOctreeRaySceneQuery( this );
q->setRay( ray );
q->setQueryMask( mask );
return q;
}
//---------------------------------------------------------------------
IntersectionSceneQuery*
1701 PagingLandScapeOctreeSceneManager::createIntersectionQuery( unsigned long mask )
{
// PagingLandScapeOctree implementation performs WORSE for < 500 objects
// TODO: optimize it so it's better in all cases
//PagingLandScapeOctreeIntersectionSceneQuery* q = new PagingLandScapeOctreeIntersectionSceneQuery( this );
DefaultIntersectionSceneQuery* q;
if ( mPagingLandScapeOctree->numNodes ( ) > 500 )
q = new PagingLandScapeOctreeIntersectionSceneQuery( this );
else
q = new DefaultIntersectionSceneQuery( this );
q->setQueryMask( mask );
return q;
}
}
1 /*
-----------------------------------------------------------------------------
This source file is part of OGRE
( Object-oriented Graphics Rendering Engine )
For the latest info, see http://www.ogre3d.org/
Copyright 2000-2006 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or ( at your option ) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
/***************************************************************************
OgrePagingLandScapeOctreeSphereSceneQuery.cpp - description
-------------------
begin : Tues July 20, 2004
copyright : ( C ) 2004by Jon Anderson
email : janders@users.sf.net
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgrePagingLandScapeOctreeSphereSceneQuery.h"
#include "OgrePagingLandScapeOctreeSceneManager.h"
#include "OgreEntity.h"
namespace Ogre
{
//---------------------------------------------------------------------
46 PagingLandScapeOctreeSphereSceneQuery::PagingLandScapeOctreeSphereSceneQuery( SceneManager* creator )
: DefaultSphereSceneQuery( creator )
{
}
//---------------------------------------------------------------------
52 PagingLandScapeOctreeSphereSceneQuery::~PagingLandScapeOctreeSphereSceneQuery( void )
{
}
//---------------------------------------------------------------------
57 void PagingLandScapeOctreeSphereSceneQuery::execute( SceneQueryListener* listener )
{
std::list < SceneNode* > list;
//find the nodes that intersect the AAB
static_cast< PagingLandScapeOctreeSceneManager* >( mParentSceneMgr )->findNodesIn( mSphere, list, 0 );
//grab all moveables from the node that intersect...
std::list< SceneNode* >::iterator it = list.begin( );
while( it != list.end( ) )
{
SceneNode::ObjectIterator oit = ( *it )->getAttachedObjectIterator( );
while ( oit.hasMoreElements( ) )
{
MovableObject* m = oit.getNext( );
if ( ( m->getQueryFlags( ) & mQueryMask )
&& m->isInScene( )
&& mSphere.intersects( m->getWorldBoundingBox( ) ) )
{
listener->queryResult( m );
}
}
++it;
}
}
}
1 /***************************************************************************
OgrePagingLandScapeOptions.cpp - description
-------------------
begin : Sun Mar 02 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreRoot.h"
#include "OgreSceneManager.h"
#include "OgreRenderSystem.h"
#include "OgreGpuProgramManager.h"
#include "OgreStringConverter.h"
#include "OgreVector2.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreConfigFile.h"
#include "OgreImage.h"
#include "OgreMaterialManager.h"
#include "OgreMaterial.h"
#include "OgreTechnique.h"
#include "OgreCamera.h"
#include "OgreViewport.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeSceneManager.h"
#include "OgrePagingLandScapeCamera.h"
#include "OgrePagingLandScapeTileInfo.h"
#include "fileutils.h"
namespace Ogre
{
//-----------------------------------------------------------------------
49 PagingLandScapeOptions::PagingLandScapeOptions( PagingLandScapeSceneManager * scnMgr ):
mScnMgr( scnMgr )
{
cfgGroupName = "";
primaryCamera = 0;
isInit = false;
setDefault( );
};
//-----------------------------------------------------------------------
59 PagingLandScapeOptions::~PagingLandScapeOptions( )
{
clearTileInfo( );
}
//-----------------------------------------------------------------------
64 void PagingLandScapeOptions::setDefault( )
{
mUseLodMapCache = false;
materialPerPage = false;
textureModifiable = true;
roughnessLod = true;
data2DFormat = "HeightField";
textureFormat = "Image";
image_filename = "";
ImageNameLoad = false;
LandScape_filename = "";
LandScape_export_filename = "";
ColorMapName = "";
groupName = cfgGroupName;
LandScape_extension = "png";
LandScape_export_extension = "png";
TextureExtension = "png";
maxValue = 5000;
minValue = 0;
PageSize = 513;
TileSize = 65;
maxRenderLevel = 100;
world_width = 0;
world_height = 0;
maxScaledZ = 0;
maxScaledX = 0;
maxUnScaledZ = 0;
maxUnScaledX = 0;
max_adjacent_pages = 2;
max_preload_pages = 3;
PageLoadInterval = 30;
change_factor = 1;
distanceLOD = 4;
LOD_factor = 10;
scale = Ogre::Vector3::UNIT_SCALE;
invScale = Ogre::Vector3::UNIT_SCALE;
position = Ogre::Vector3::ZERO;
num_renderables = 64;
num_renderables_increment = 64;
num_tiles = 64;
num_tiles_increment = 64;
visible_renderables = 75;
cameraThreshold = 5;
num_renderables_loading = 10;
RenderableLoadInterval = 3;
normals = false;
lit = false;
colored = false;
vertex_shadowed = false;
base_vertex_color = false;
coverage_vertex_color = false;
vertex_instant_colored = false;
RawHeight = 0;
RawWidth = 0;
lightmoved = false;
Deformable = false;
saveDeformation = true;
VertexCompression = false;
BigImage = false;
lodMorphStart = 0.2f;
lodMorph = false;
maxPixelError = 0;
TextureStretchFactor = 1.0f;
NumMatHeightSplat = 0;
matHeight.reserve ( 0 );
matHeight.resize ( 0 );
matColor.reserve ( 0 );
matColor.resize ( 0 );
NumSplatMapToSplit = 0;
SplatMapNames.reserve ( 0 );
SplatMapNames.resize ( 0 );
NumTextureFormatSupported = 0;
TextureFormatSupported.reserve ( 0 );
TextureFormatSupported.resize ( 0 );
MaxLodUnderCam = false;
VisMap = false;
BigImage = false;
PageInvisibleUnloadFrames = 300;
TileInvisibleUnloadFrames = 300;
lodMaterialDistanceList.clear( );
lodMaterialDistanceList.push_back ( 80000.0f );
mResourceFilesystem.clear ( );
mResourceZip.clear( );
queryNoInterpolation = false;
queryResolutionFactor = 1.0f;
#ifdef _MAPSPLITTER
Blur = 0.0f;
Amb = 0.5f;
Diff = 0.5f;
Blur = 0.0f;
HeightMapBlurFactor = 0.0f;
Paged = true;
MiniMap = false;
BaseMap = false;
ColorMapGenerate = false;
ColorMapSplit = false;
LightMap = false;
NormalMap = false;
HeightMap = false;
AlphaMaps = false;
LitBaseMap = false;
InfiniteMap = false;
CoverageMap = false;
LitColorMapGenerate = false;
LitColorMapSplit = false;
HeightNormalMap = false;
Equalize = false;
ZHorizon = false;
SRTM_water = false;
#endif
}
//-----------------------------------------------------------------------
211 void PagingLandScapeOptions::init( )
{
// sets options that doesn't depend on maps.
if ( !isInit )
{
const RenderSystem *renderer = Root::getSingleton( ).getRenderSystem( );
if ( renderer )
{
const RenderSystemCapabilities* caps = renderer->getCapabilities( );
hasVertexShader = caps->hasCapability( RSC_VERTEX_PROGRAM ) && !( StringUtil::startsWith( caps->getMaxFragmentProgramVersion ( ), "vs_1_0", true ) );
hasVertexShader = caps->hasCapability( RSC_BLENDING ) && !( StringUtil::startsWith( caps->getMaxFragmentProgramVersion ( ), "vs_1_0", true ) );
hasFragmentShader = caps->hasCapability( RSC_FRAGMENT_PROGRAM );
const String &maxShaderVersion = caps->getMaxFragmentProgramVersion ( );
hasFragmentShader2 = hasFragmentShader && !( maxShaderVersion == "ps_1_1" || maxShaderVersion == "ps_1_0" );
numTextureUnits = caps->getNumTextureUnits ( );
isRenderGL = StringUtil::startsWith( renderer->getName( ), "OpenGL", false );
isInit = true;
}
}
}
//-----------------------------------------------------------------------
232 void PagingLandScapeOptions::loadcfg ( const String &filename, ConfigFile& config )
{
std::ifstream fs;
fs.open( filename.c_str( ), std::ios::in | std::ios::binary );
if ( fs )
{
// Wrap as a stream
DataStreamPtr stream(
new FileStreamDataStream( filename, &fs, false ) );
config.load( stream );
}
else
{
// otherwise try resource system
DataStreamPtr stream =
ResourceGroupManager::getSingleton( ).openResource( filename );
config.load( stream );
}
}
//-----------------------------------------------------------------------
255 bool PagingLandScapeOptions::load( const String &filename )
{
ConfigFile config;
loadcfg( filename, config );
return load( filename, config );
}
//-----------------------------------------------------------------------
262 bool PagingLandScapeOptions::load( DataStreamPtr &stream )
{
ConfigFile config;
config.load( stream );
return load( stream->getName ( ), config );
}
//-----------------------------------------------------------------------
269 bool PagingLandScapeOptions::load( const String &filename, ConfigFile& config )
{
init( );
// Set up the options :
// List of map associated with map names.
// or directly a map.
if ( config.getSetting ( "DefaultMap" ).empty( ) )
{
mConfig = &config;
mCurrentMap = filename;
loadMapOptions ( filename );
return true;
}
else
{
// Go through all sections & settings in the file
ConfigFile::SettingsIterator setIt = config.getSettingsIterator( );
while ( setIt.hasMoreElements( ) )
{
const String name = setIt.peekNextKey( );
const String value = setIt.getNext( );
mMapList.insert( LandScapeFileNames::value_type( name, value ) );
}
LandScapeFileNames::iterator i = mMapList.find( "GroupName" );
if ( i == mMapList.end( ) )
{
OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND,
"You need to define a GroupName where to find the map definition file ",
"PagingLandScapeOptions::load" );
}
cfgGroupName = i->second;
mMapList.erase ( i );
i = mMapList.find( "BatchMode" );
if ( ( i != mMapList.end( ) ) && ( i->second == "yes" ) )
{
mBatchMode = true;
mMapList.erase ( i );
}
else
{
mBatchMode = false;
}
i = mMapList.find( "TextureFormatDebug" );
if ( i != mMapList.end( ) )
{
TextureFormatDebug = config.getSetting( "TextureFormatDebug" ) == "yes";
mMapList.erase ( i );
}
i = mMapList.find( "DefaultMap" );
if ( i == mMapList.end( ) )
{
if( mBatchMode == false )
{
OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND,
"You need to define a DefaultMap= ",
"PagingLandScapeOptions::load" );
}
}
else
{
mCurrentMap = i->second;
}
if ( i != mMapList.end( ) )
mMapList.erase ( i );
#ifndef _MAPSPLITTER
ResourceGroupManager * const rgsm = ResourceGroupManager::getSingletonPtr( );
rgsm->initialiseResourceGroup ( cfgGroupName );
LandScapeFileNames::iterator iend = mMapList.end( );
LandScapeFileNames::iterator itCheck = mMapList.begin( );
const String cfgExt( ".cfg" );
for ( ; itCheck != iend; )
{
const String mapName ( itCheck->first );
const String mapFileName ( itCheck->second );
if (
!rgsm->resourceExists( cfgGroupName, mapFileName )
&&
!rgsm->resourceExists( cfgGroupName, mapFileName + cfgExt )
&&
!rgsm->resourceExists( cfgGroupName, mapName + cfgExt )
&&
!rgsm->resourceExists( cfgGroupName, mapName )
)
{
mMapList.erase ( itCheck++ );
}
else
{
++itCheck;
}
}
#endif //_MAPSPLITTER
if ( !mBatchMode && !StringUtil::startsWith( mCurrentMap, "none", true ) )
{
loadMap( mCurrentMap );
return true;
}
}
return false;
}
//-----------------------------------------------------------------------
386 const String &PagingLandScapeOptions::getCurrentTextureFormat( ) const
{
return textureFormat;
}
//-----------------------------------------------------------------------
391 void PagingLandScapeOptions::setTextureFormat ( const String &format )
{
if ( TextureFormatSupported.end( ) == std::find( TextureFormatSupported.begin( ),
TextureFormatSupported.end( ),
format ) )
{
TextureFormatSupported.push_back ( format );
}
textureFormat = format;
// sort of debugging hack til BigImage itself becomes a chunked Lod thing.
BigImage = BigImage && textureFormat == "Image";
}
//-----------------------------------------------------------------------
404 void PagingLandScapeOptions::insertTextureFormat ( const String &format )
{
if ( TextureFormatSupported.end( ) == std::find( TextureFormatSupported.begin( ),
TextureFormatSupported.end( ),
format ) )
{
TextureFormatSupported.push_back ( format );
}
}
//-----------------------------------------------------------------------
415 LandScapeFileNames& PagingLandScapeOptions::getMapList( )
{
return mMapList;
}
//-----------------------------------------------------------------------
420 const String& PagingLandScapeOptions::getPreviousMapName( ) const
{
if ( !mMapList.empty ( ) )
{
if ( StringUtil::startsWith( mCurrentMap, "none", true ) )
return mMapList.rbegin( )->first;
LandScapeFileNames::const_reverse_iterator iend = mMapList.rend( );
LandScapeFileNames::const_reverse_iterator i = mMapList.rbegin( );
for ( ; i != iend; ++i )
{
if ( i->first == mCurrentMap || i->second == mCurrentMap )
{
++i;
if ( i == iend )
i = mMapList.rbegin( );
return i->first;
}
}
}
return StringUtil::BLANK;
}
//-----------------------------------------------------------------------
442 const String& PagingLandScapeOptions::getNextMapName( ) const
{
if ( !mMapList.empty ( ) )
{
if ( StringUtil::startsWith( mCurrentMap, "none", true ) )
return mMapList.begin( )->first;
LandScapeFileNames::const_iterator iend = mMapList.end( );
LandScapeFileNames::const_iterator i = mMapList.begin( );
for ( ; i != iend; ++i )
{
if ( i->first == mCurrentMap || i->second == mCurrentMap )
{
++i;
if ( i == iend )
i = mMapList.begin( );
return i->first;
}
}
}
return StringUtil::BLANK;
}
//-----------------------------------------------------------------------
465 const String& PagingLandScapeOptions::getCurrentMapName( ) const
{
return mCurrentMap;
}
//-----------------------------------------------------------------------
470 void PagingLandScapeOptions::setCurrentMapName( const String& mapName )
{
if ( StringUtil::BLANK != mapName )
{
LandScapeFileNames::iterator ifind = mMapList.find ( mapName );
if ( ifind == mMapList.end( ) )
{
mMapList.insert( LandScapeFileNames::value_type( mapName, mapName ) );
}
mCurrentMap = mapName;
}
loadMap( mapName );
}
//-----------------------------------------------------------------------
484 void PagingLandScapeOptions::loadMap( const String& mapName )
{
ConfigFile config;
mConfig = &config;
const String fileMapName ( getMapFilename( mapName ) +
( StringUtil::endsWith( mapName, ".cfg", true ) ? StringUtil::BLANK : String( ".cfg" ) ) );
if ( !cfgGroupName.empty ( ) )
{
std::vector<Ogre::String>::iterator itFileSystem = mResourceFilesystem.begin( );
for( ; itFileSystem != mResourceFilesystem.end( ); ++itFileSystem )
{
ResourceGroupManager::getSingleton( ).removeResourceLocation(
*itFileSystem, cfgGroupName );
}
std::vector<Ogre::String>::iterator itZip = mResourceZip.begin( );
for( ; itZip != mResourceZip.end( ); ++itZip )
{
ResourceGroupManager::getSingleton( ).removeResourceLocation(
*itZip, cfgGroupName );
}
// Set up the options For a Map
mConfig->load ( fileMapName, cfgGroupName, String( "=" ), true );
}
else
{
mConfig->load ( fileMapName, ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME, String( "=" ), true );
}
/* Set up the options For a Map*/
loadMapOptions ( fileMapName );
}
//-----------------------------------------------------------------------
515 const String &PagingLandScapeOptions::getMapFilename( const String &currMapName ) const
{
LandScapeFileNames::const_iterator i = mMapList.find( currMapName );
LandScapeFileNames::const_iterator iEnd = mMapList.end( );
if ( i != iEnd )
return i->second;
for ( i = mMapList.begin( ); i != iEnd; ++i )
{
if ( StringUtil::match( i->second, currMapName, false ) ||
StringUtil::match( i->first, currMapName, false ) )
{
return i->second;
}
}
return currMapName;
}
//-----------------------------------------------------------------------
534 void PagingLandScapeOptions::insertMap( const String& mapName )
{
LandScapeFileNames::iterator ifind = mMapList.find ( mapName );
if ( ifind == mMapList.end( ) )
{
mMapList.insert( LandScapeFileNames::value_type( mapName, mapName ) );
}
}
//-----------------------------------------------------------------------
543 bool PagingLandScapeOptions::setUint ( unsigned int &u, const String &ValuetoGet )
{
const String valString = mConfig->getSetting( ValuetoGet );
if ( !valString.empty( ) )
{
u = static_cast<unsigned int> ( StringConverter::parseReal( valString ) );
return true;
}
return false;
}
//-----------------------------------------------------------------------
554 bool PagingLandScapeOptions::setBool ( bool &b, const String &ValuetoGet )
{
const String valString = mConfig->getSetting ( ValuetoGet );
if ( !valString.empty( ) )
{
b = StringUtil::startsWith( valString, "yes", true );
return true;
}
return false;
}
//-----------------------------------------------------------------------
565 bool PagingLandScapeOptions::setReal ( Real &r, const String &ValuetoGet )
{
const String valString = mConfig->getSetting( ValuetoGet );
if ( !valString.empty( ) )
{
const Ogre::Real val = StringConverter::parseReal( valString );
r = val;
return true;
}
return false;
}
//-----------------------------------------------------------------------
577 bool PagingLandScapeOptions::setColourValue( ColourValue &r, const String &ValuetoGet )
{
const String valString = mConfig->getSetting( ValuetoGet );
if ( !valString.empty( ) )
{
const ColourValue val = StringConverter::parseColourValue( valString );
r = val;
return true;
}
return false;
}
//-----------------------------------------------------------------------
589 bool PagingLandScapeOptions::setString ( String &s, const String &ValuetoGet )
{
const String val = mConfig->getSetting ( ValuetoGet );
if ( !val.empty( ) )
{
s = val;
return true;
}
return false;
}
//-----------------------------------------------------------------------
600 void PagingLandScapeOptions::loadMapOptions( const String& mapName )
{
unsigned int i;
init ( );
setDefault ( );
///By Ember start
// Set up the options For a Map
ConfigFile config;
config.load ( mapName, cfgGroupName, String( "=" ), true );
mConfig = &config;
///By Ember end
// Set up the dimensions For a Map
#if !defined( _MAPSPLITTER ) && !defined( _MAPEDITOR )
setUint ( world_height, "Height" );
setUint ( world_width, "Width" );
if ( world_width == 0 || world_height == 0 )
{
OGRE_EXCEPT( 1,
"Your map must at least have a width and height defined in the config file ",
"PagingLandScapeOptions::loadMapOptions" );
}
#endif // !defined( _MAPSPLITTER ) && !defined( _MAPEDITOR )
setUint ( PageSize, "PageSize" );
setUint ( TileSize, "TileSize" );
invPageSizeMinusOne = 1.0 / ( PageSize - 1 );
invTileSizeMinusOne = 1.0 / ( TileSize - 1 );
NumTiles = static_cast<unsigned int> ( static_cast <Real> ( PageSize ) / ( TileSize - 1 ) );
NumPages = static_cast<unsigned int> ( static_cast <Real> ( world_height * world_width ) );
const unsigned int totalNumTiles = NumPages * ( NumTiles*NumTiles ) + 1;
///EMBER: added for ember, since we never want the scale to be different from the page size
scale.x = scale.z = PageSize;
scale.y = 1;
// setReal ( scale.x, "ScaleX" );
// setReal ( scale.y, "ScaleY" );
// setReal ( scale.z, "ScaleZ" );
setReal( position.x, "PositionX" );
setReal( position.y, "PositionY" );
setReal( position.z, "PositionZ" );
// secret tweak helping joining tile using vertex compression
// leads to texture distortion at page breaks otherwise.
const double scalemodif = 1.0f;//static_cast <double> ( PageSize - 1 ) / PageSize;
ScaledPageSizeX = scale.x * scalemodif;
ScaledPageSizeZ = scale.z * scalemodif;
ScaledHeightY = scale.y / 65535;
setReal ( TextureStretchFactor, "TextureStretchFactor" );
#if !defined( _MAPSPLITTER ) && !defined( _MAPEDITOR )
// Scale x/z relative to page size
scale.x /= ( PageSize - 1 );
scale.z /= ( PageSize - 1 );
#else// defined( _MAPSPLITTER ) || defined( _MAPEDITOR )
//scale.y = scale.y;
scale.x /= ( PageSize - 1 ) * TextureStretchFactor;
scale.z /= ( PageSize - 1 ) * TextureStretchFactor;
#endif// defined( _MAPSPLITTER ) || defined( _MAPEDITOR )
invScale.x = 1 / scale.x;
invScale.y = 1 / scale.y;
invScale.z = 1 / scale.z;
maxUnScaledZ = world_height * ( PageSize - 1 ) * 0.5f;
maxUnScaledX = world_width * ( PageSize - 1 ) * 0.5f;
maxScaledZ = scale.z * maxUnScaledZ;
maxScaledX = scale.x * maxUnScaledX;
// Set up the names For a Map
setString ( groupName, "GroupName" );
if ( !setString ( LandScape_filename, "HeightMapFileName" ) )
setString ( LandScape_filename, "LandScapeFileName" );
if ( !setString ( TerrainName, "TerrainName" ) )
TerrainName = LandScape_filename;
//add Resources Group to Ogre if needed.
StringVector mResourceFilesystem = mConfig->getMultiSetting( "FileSystem" );
std::vector<Ogre::String>::iterator itFileSystem = mResourceFilesystem.begin( );
for( ; itFileSystem != mResourceFilesystem.end( ); ++itFileSystem )
{
String resourceFileSystem = *itFileSystem;
String BasePath, FilePath;
StringUtil::splitFilename( resourceFileSystem, BasePath, FilePath );
if ( StringUtil::endsWith ( BasePath, "terrainname", true ) )
{
BasePath = TerrainName;
}
else if ( StringUtil::endsWith ( BasePath, "landscapefilename", true ) )
{
BasePath = LandScape_filename;
}
else if ( StringUtil::endsWith ( BasePath, "landscapeexportfilename", true ) )
{
BasePath = LandScape_export_filename;
}
if ( !cfgGroupName.empty( ) && FilePath.empty ( ) && !mapName.empty( ) )
{
FileInfoListPtr finfo = ResourceGroupManager::getSingleton( ).findResourceFileInfo(
cfgGroupName,
mapName );
FilePath = ( finfo->begin( ) != finfo->end( ) )? ( finfo->begin( ) )->archive->getName( ) : ".";
}
if ( !FilePath.empty ( ) )
{
FilePath = FilePath + "/";
}
ResourceGroupManager::getSingleton( ).addResourceLocation(
FilePath + BasePath, "FileSystem", groupName );
}
StringVector mResourceZip = mConfig->getMultiSetting( "Zip" );
std::vector<Ogre::String>::iterator itZip = mResourceZip.begin( );
for( ; itZip != mResourceZip.end( ); ++itZip )
{
String resourceZip = *itZip;
if ( resourceZip != StringUtil::BLANK )
{
ResourceGroupManager::getSingleton( ).addResourceLocation(
resourceZip, "Zip", groupName );
}
}
if ( !setString ( LandScape_filename, "HeightMapFileName" ) )
setString ( LandScape_filename, "LandScapeFileName" );
if ( !setString ( LandScape_export_filename, "LandScapeExportFileName" ) )
LandScape_export_filename = LandScape_filename;
if ( !setString ( LandScape_extension, "HeightMapExtension" ) )
setString ( LandScape_extension, "LandScapeExtension" );
if ( !setString ( LandScape_export_extension, "HeightMapExportExtension" ) )
setString ( LandScape_export_extension, "LandScapeExportExtension" );
if ( !setString ( TextureExtension, "ImageExtension" ) )
if ( !setString ( TextureExtension, "ColorMapExtension" ) )
setString ( TextureExtension, "TextureExtension" );
if ( !setString ( TextureExportExtension, "ImageExportExtension" ) )
if ( !setString ( TextureExportExtension, "ColorMapExportExtension" ) )
setString ( TextureExportExtension, "TextureExportExtension" );
ImageNameLoad = setString ( image_filename, "ImageFilename" );
if ( !ImageNameLoad )
ImageNameLoad = setString ( image_filename, "ColorMapFileName" );
// Set up the data source For a Map
setString ( data2DFormat, "Data2DFormat" );
bool HeightField = StringUtil::endsWith( data2DFormat, "HeightField", false );
bool HeightFieldN = StringUtil::endsWith( data2DFormat, "HeightFieldN", false );
bool HeightFieldTC = StringUtil::endsWith( data2DFormat, "HeightFieldTC", false );
bool HeightFieldNTC = StringUtil::endsWith( data2DFormat, "HeightFieldNTC", false );
bool HeightFieldRawTC = StringUtil::endsWith( data2DFormat, "HeightFieldRawC", false );
bool HeightFieldRaw = StringUtil::endsWith( data2DFormat, "HeightFieldRaw", false );
if ( StringUtil::endsWith( LandScape_extension, "raw", true ) )
{
isRaw = true;
setUint ( RawHeight, "RawHeight" );
setUint ( RawWidth, "RawWidth" );
if ( HeightField || HeightFieldN )
{
data2DFormat = "HeightFieldRaw";
HeightField = false;
HeightFieldN = false;
HeightFieldRaw = true;
}
else if ( HeightFieldTC || HeightFieldNTC )
{
data2DFormat = "HeightFieldRawTC";
HeightFieldTC = false;
HeightFieldNTC = false;
HeightFieldRawTC = true;
}
}
else
isRaw = false;
if ( HeightFieldRawTC
|| HeightFieldTC
|| HeightFieldNTC )
{
setUint ( maxValue, "MaxValue" );
maxValue *= static_cast<unsigned int>( scale.y );
setUint ( minValue, "MinValue" );
minValue *= static_cast<unsigned int>( scale.y );
}
else
{
maxValue = static_cast<unsigned int> ( scale.y );
minValue = 0;
}
setBool ( materialPerPage, "MaterialPerPage" );
setBool ( textureModifiable, "TextureModifiable" );
setBool( mUseLodMapCache, "UseLodMapCache" );
setBool( roughnessLod, "RoughnessLod" );
// Set up the splatting options For a Map
setUint ( NumMatHeightSplat, "NumMatHeightSplat" );
matHeight.reserve ( NumMatHeightSplat );
matHeight.resize ( NumMatHeightSplat );
matColor.reserve ( NumMatHeightSplat );
matColor.resize ( NumMatHeightSplat );
SplatDetailMapNames.reserve ( NumMatHeightSplat );
SplatDetailMapNames.resize ( NumMatHeightSplat );
// Init to 0.0f for lazy config files omitting some.
for ( i = 0; i < NumMatHeightSplat; i++ )
{
matHeight[i] = 0.0f;
}
const Ogre::Real divider = ( maxValue - minValue ) / ( 100.0f );
for ( i = 0; i < NumMatHeightSplat; i++ )
{
setReal ( matHeight[i],
"MaterialHeight" + StringConverter::toString( i ) );
matHeight[i] *= divider;
}
const String baseSplatName ( "SplatFilename" );
for ( i = 0; i < NumMatHeightSplat; i++ )
setString ( SplatDetailMapNames[i],
baseSplatName + StringConverter::toString ( i ) );
getAvgColors ( );
Ogre::Real MaterialDistanceLod = 0.0f;
setReal ( MaterialDistanceLod, "MaterialDistanceLod" );
if ( MaterialDistanceLod != 0.0f )
{
lodMaterialDistanceList.clear( );
lodMaterialDistanceList.push_back ( MaterialDistanceLod );
}
#ifndef _MAPSPLITTER
// PLUGIN OPTIONS ONLY
// Set up the vertexes options For a Map
setBool ( colored, "VertexColors" );
setBool ( coverage_vertex_color, "CoverageVertexColor" );
setBool ( base_vertex_color, "BaseVertexColor" );
setBool ( vertex_shadowed, "BaseVertexShadow" );
setBool ( vertex_instant_colored, "BaseVertexInstantColor" );
// ensure combination are correct
if ( vertex_shadowed )
vertex_instant_colored = true;
if ( coverage_vertex_color || base_vertex_color
)// || vertex_shadowed || vertex_instant_colored )
colored = true;
// Set up the paging options For a Map
setUint ( num_renderables, "MaxNumRenderables" );
num_renderables = ( totalNumTiles < num_renderables )?totalNumTiles:num_renderables;
setUint ( num_renderables_increment, "IncrementRenderables" );
setUint ( num_tiles, "MaxNumTiles" );
num_tiles = ( totalNumTiles < num_tiles )? totalNumTiles : num_tiles;
setUint ( num_tiles_increment, "IncrementTiles" );
setUint ( num_renderables_loading, "NumRenderablesLoading" );
setUint ( RenderableLoadInterval, "RenderableLoadInterval" );
setUint ( max_adjacent_pages, "MaxAdjacentPages" );
setUint ( max_preload_pages, "MaxPreloadedPages" );
setUint ( PageLoadInterval, "PageLoadInterval" );
// Set up the LOD options For a Map
setUint ( maxRenderLevel, "MaxRenderLevel" );
if ( maxRenderLevel == 100 )
{
maxRenderLevel = 0;
const unsigned int halftileSize = static_cast<unsigned int>( TileSize * 0.5f );
while ( static_cast<unsigned int> ( ( 1 << maxRenderLevel ) ) < halftileSize )
maxRenderLevel++;
}
setReal ( change_factor, "ChangeFactor" );
change_factor *= ( static_cast <Real> ( PageSize * ( scale.z + scale.x ) * 0.5f ) / 9 );
// Set up the distance options For a Map
setReal ( visible_renderables, "VisibleRenderables" );
// compute the actual distance as a square
// Factor is a Tile distance squared
const Ogre::Real Factor = TileSize * scale.x * TileSize * scale.z;
// max distance upon which renderables are not rendered anymore
renderable_factor = visible_renderables * Factor;
//renderable_factor *= renderable_factor;
//setReal ( cameraThreshold, "CameraThreshold" );
// To avoid the use of a square root.
//cameraThreshold *= cameraThreshold;
cameraThreshold = ( ( scale.x < scale.z ) ? TileSize * scale.x : TileSize * scale.z ) * 0.25;
setReal ( distanceLOD, "DistanceLOD" );
// Compute the actual distance as a square
LOD_factor = distanceLOD * Factor;
loadMapInfo( );
setBool ( lit, "VertexLit" );
setBool ( normals, "VertexNormals" );
setBool ( Deformable, "Deformable" );
if ( !Deformable )
saveDeformation = false;
else
setBool ( saveDeformation, "SaveDeformation" );
//Morphing
if ( maxRenderLevel > 1 )
{
setBool ( lodMorph, "VertexProgramMorph" );
setReal ( lodMorphStart, "LODMorphStart" );
}
setUint ( maxPixelError, "MaxPixelError" );
setBool ( BigImage, "BigImage" );
setBool ( VisMap, "HorizonVisibilityComputing" );
setBool ( MaxLodUnderCam, "MaxLodUnderCam" );
setBool ( VertexCompression, "VertexCompression" );
VertexCompression = VertexCompression && hasVertexShader;
setUint ( NumTextureFormatSupported, "NumTextureFormatSupported" );
TextureFormatSupported.reserve ( NumTextureFormatSupported );
TextureFormatSupported.resize ( NumTextureFormatSupported );
for ( i = 0; i < NumTextureFormatSupported; i++ )
{
setString ( TextureFormatSupported[i], "TextureFormatSupported" + StringConverter::toString( i ) );
}
String tempTexformat;
setString ( tempTexformat, "TextureFormat" );
// must be after getting supported formats
setTextureFormat ( tempTexformat );
setUint ( TileInvisibleUnloadFrames, "TileInvisibleUnloadFrames" );
setUint ( PageInvisibleUnloadFrames, "PageInvisibleUnloadFrames" );
setReal ( BaseCameraViewpoint.x, "BaseCameraViewpoint.x" );
setReal ( BaseCameraViewpoint.y, "BaseCameraViewpoint.y" );
setReal ( BaseCameraViewpoint.z, "BaseCameraViewpoint.z" );
setReal ( Baselookat.x, "Baselookat.x" );
setReal ( Baselookat.y, "Baselookat.y" );
setReal ( Baselookat.z, "Baselookat.z" );
ResourceGroupManager::getSingleton( ).initialiseResourceGroup ( groupName );
#else
// MAP TOOL OPTIONS ONLY
setBool ( Paged, "Paged" );
setString ( OutDirectory, "OutDirectory" );
String BasePath, FilePath;
StringUtil::splitFilename( OutDirectory, BasePath, FilePath );
if ( StringUtil::endsWith ( BasePath, "landscapefilename", true ) )
{
BasePath = LandScape_filename;
}
if ( StringUtil::endsWith ( BasePath, "landscapeexportfilename", true ) )
{
BasePath = LandScape_export_filename;
}
if ( FilePath.empty( ) )
{
//Get cfg current Directory
FileInfoListPtr finfo = ResourceGroupManager::getSingleton( ).findResourceFileInfo (
cfgGroupName, mapName );
FileInfoList::iterator it = finfo->begin( );
if ( it != finfo->end( ) )
{
FilePath = ( it )->archive->getName( );
}
}
if ( StringUtil::endsWith ( FilePath, "/", true ) )
{
FilePath.resize ( FilePath.size( ) - 1 );
}
OutDirectory = FilePath + "/" + BasePath;
setBool ( MiniMap, "MiniMap" );
setBool ( BaseMap, "BaseMap" );
setBool ( ColorMapGenerate, "ColorMapGenerate" );
if ( !setBool ( ColorMapSplit, "ImageSplit" ) )
setBool ( ColorMapSplit, "ColorMapSplit" );
setBool ( LightMap, "LightMap" );
setBool ( NormalMap, "NormalMap" );
setBool ( HeightMap, "HeightMap" );
setBool ( AlphaMaps, "AlphaMaps" );
setBool ( LitBaseMap, "LitBaseMap" );
setBool ( InfiniteMap, "InfiniteMap" );
setBool ( CoverageMap, "CoverageMap" );
setBool ( LitColorMapGenerate, "LitColorMapGenerate" );
if ( !setBool ( LitColorMapSplit, "LitImageSplit" ) )
setBool ( LitColorMapSplit, "LitColorMapSplit" );
setBool ( HeightNormalMap, "HeightNormalMap" );
if ( !setString ( ColorMapName, "ImageFileName" ) )
if ( !setString ( ColorMapName, "ColorMapFileName" ) )
setString ( ColorMapName, "ColorMapName" );
if ( ( BaseMap || CoverageMap || AlphaMaps )
&& NumMatHeightSplat == 0 )
OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS,
"Generating a texture set from a heightmap needs some MaterialHeights in cfg file.",
"PagingLandScapeData2D_HeightField::getScale" );
setReal ( HeightMapBlurFactor, "HeightMapBlurFactor" );
setReal ( Sun.x, "Sunx" );
setReal ( Sun.y, "Suny" );
setReal ( Sun.z, "Sunz" );
setReal ( Amb, "Ambient" );
setReal ( Diff, "Diffuse" );
setUint ( Blur, "Blur" );
setBool ( Equalize, "Equalize" );
setBool ( ZHorizon, "ZHorizon" );
setBool ( SRTM_water, "SRTM_water" );
setUint ( MiniMapHeight, "MiniMapHeight" );
setUint( MiniMapWidth, "MiniMapWidth" );
setUint ( NumSplatMapToSplit, "NumSplatMapToSplit" );
SplatMapNames.reserve ( NumSplatMapToSplit );
SplatMapNames.resize ( NumSplatMapToSplit );
for ( i = 0; i < NumSplatMapToSplit; i++ )
{
setString ( SplatMapNames[i], "SplatMapName" + StringConverter::toString( i ) );
}
#endif
}
//-----------------------------------------------------------------------
1092 void PagingLandScapeOptions::calculateCFactor( )
{
// ConstOgre::Real A = 1 / Math::Tan( Math::AngleUnitsToRadians( opts.primaryCamera->getFOVy( ) ) );
// Turn off detail compression at higher FOVs
const Ogre::Real A = 1.0f;
assert ( primaryCamera );
const Viewport *v = primaryCamera->getViewport( );
if ( v )
{
const int vertRes = v->getActualHeight( );
assert ( vertRes != 0 );
const Ogre::Real T = 2 * static_cast <Ogre::Real > ( maxPixelError ) / vertRes;
if ( T != 0 )
CFactor = A / T;
else
CFactor = A * vertRes * 0.5f;
}
}
//-----------------------------------------------------------------------
1115 void PagingLandScapeOptions::setPrimaryCamera( PagingLandScapeCamera *cam )
{
primaryCamera = cam;
if ( cam && cam->getViewport( ) )
calculateCFactor ( );
}
//-----------------------------------------------------------------------
1122 bool PagingLandScapeOptions::setOption( const String& strKey, const void* pValue )
{
if ( strKey == "saveDeformation" )
{
saveDeformation = * static_cast < const bool * > ( pValue );
return true;
}
if ( strKey == "MaxLodUnderCam" )
{
MaxLodUnderCam = * static_cast < const bool * > ( pValue );
return true;
}
// if ( strKey == "VisibleRenderables" )
// {
// visible_renderables = * static_cast < const int * > ( pValue );
// // compute the actual distance as a square
// Ogre::Real Factor = TileSize;
// Factor = Factor * scale.x * Factor * scale.z;
//
// renderable_factor = visible_renderables * Factor;
// return true;
// }
if ( strKey == "DistanceLOD" )
{
distanceLOD = * static_cast < const Ogre::Real * > ( pValue );
// Compute the actual distance as a square
Ogre::Real Factor = TileSize;
Factor = Factor * scale.x * Factor * scale.z;
LOD_factor = distanceLOD * Factor;
return true;
}
if ( strKey == "Sun" )
{
Sun = * static_cast < const Ogre::Vector3 * > ( pValue );
lightmoved = true;
return true;
}
if ( strKey == "SunAngle" )
{
SunAngle = * static_cast < const Ogre::Real * > ( pValue );
lightmoved = true;
return true;
}
if ( strKey == "Width" )
{
world_width = * static_cast < const unsigned int * > ( pValue ) ;
#ifndef _MAPSPLITTER
#ifndef _MAPEDITOR
assert ( primaryCamera );
static_cast <PagingLandScapeSceneManager *> ( primaryCamera->getSceneManager( ) )->WorldDimensionChange( );
#endif //_MAPEDITOR
#endif //_MAPSPLITTER
return true;
}
if ( strKey == "Height" )
{
world_height = * static_cast < const unsigned int * > ( pValue );
#ifndef _MAPSPLITTER
#ifndef _MAPEDITOR
assert ( primaryCamera );
static_cast <PagingLandScapeSceneManager *> ( primaryCamera->getSceneManager( ) )->WorldDimensionChange( );
#endif //_MAPEDITOR
#endif //_MAPSPLITTER
return true;
}
if ( strKey == "WorldDimension" )
{
Vector2 dim = * static_cast < const Vector2 * > ( pValue );
world_height = static_cast < unsigned int > ( dim.x );
world_width = static_cast < unsigned int > ( dim.y );
#ifndef _MAPSPLITTER
#ifndef _MAPEDITOR
assert ( primaryCamera );
static_cast <PagingLandScapeSceneManager *> ( primaryCamera->getSceneManager( ) )->WorldDimensionChange( );
#endif //_MAPEDITOR
#endif //_MAPSPLITTER
return true;
}
if ( strKey == "primaryCamera" )
{
setPrimaryCamera ( const_cast < PagingLandScapeCamera * > ( static_cast < const PagingLandScapeCamera * > ( pValue ) ) );
return true;
}
if ( strKey == "TextureNameLayer0" )
{
SplatDetailMapNames[0] = * static_cast < const String * > ( pValue );
return true;
}
if ( strKey == "TextureNameLayer1" )
{
SplatDetailMapNames[1] = * static_cast < const String * > ( pValue );
return true;
}
if ( strKey == "TextureNameLayer2" )
{
SplatDetailMapNames[2] = * static_cast < const String * > ( pValue );
return true;
}
if ( strKey == "TextureNameLayer3" )
{
SplatDetailMapNames[3] = * static_cast < const String * > ( pValue );
return true;
}
if ( strKey == "MaxAdjacentPages" )
{
max_adjacent_pages = * static_cast < const unsigned int * > ( pValue );
return true;
}
if ( strKey == "MaxPreloadedPages" )
{
max_preload_pages = * static_cast < const unsigned int * > ( pValue );
return true;
}
if ( strKey == "PositionX" )
{
position.x = * static_cast < const Ogre::Real * > ( pValue );
return true;
}
if ( strKey == "PositionY" )
{
position.y = * static_cast < const Ogre::Real * > ( pValue );
return true;
}
if ( strKey == "PositionZ" )
{
position.z = * static_cast < const Ogre::Real * > ( pValue );
return true;
}
if ( strKey == "ConfigGroupName" )
{
cfgGroupName = * static_cast < const String * > ( pValue );
return true;
}
if ( strKey == "queryNoInterpolation" )
{
queryNoInterpolation = * static_cast < const bool * > ( pValue );
return true;
}
if ( strKey == "queryResolutionFactor" )
{
queryResolutionFactor = * static_cast < const Ogre::Real * > ( pValue );
return true;
}
return false;
}
//-----------------------------------------------------------------------
1274 bool PagingLandScapeOptions::getOption( const String& strKey, void* pDestValue )
{
if ( strKey == "saveDeformation" )
{
* static_cast < bool * > ( pDestValue ) = saveDeformation;
return true;
}
if ( strKey == "VisibleRenderables" )
{
* static_cast < int * > ( pDestValue ) = static_cast<int> ( visible_renderables );
return true;
}
if ( strKey == "DistanceLOD" )
{
* static_cast <Ogre::Real * > ( pDestValue ) = static_cast<Real> ( distanceLOD );
return true;
}
if ( strKey == "VisibleDistance" )
{
// we need to return the square root of the distance
* static_cast <Ogre::Real * > ( pDestValue ) = Math::Sqrt ( renderable_factor );
return true;
}
if ( strKey == "VisibleLOD" )
{
// we need to return the square root of the distance
* static_cast <Ogre::Real * > ( pDestValue ) = Math::Sqrt ( LOD_factor );
return true;
}
// Some options proposed by Praetor
if ( strKey == "Width" )
{
* static_cast < int * > ( pDestValue ) = world_width;
return true;
}
if ( strKey == "Height" )
{
* static_cast < int * > ( pDestValue ) = world_height;
return true;
}
if ( strKey == "MaxHeight" )
{
* static_cast <Ogre::Real * > ( pDestValue ) = scale.y;
return true;
}
if ( strKey == "PageSize" )
{
* static_cast < int * > ( pDestValue ) = PageSize;
return true;
}
if ( strKey == "Scale" )
{
* static_cast < Ogre::Vector3 * > ( pDestValue ) = scale;
return true;
}
if ( strKey == "ScaleX" )
{
* static_cast <Ogre::Real * > ( pDestValue ) = scale.x;
return true;
}
if ( strKey == "ScaleY" )
{
* static_cast <Ogre::Real * > ( pDestValue ) = scale.y;
return true;
}
if ( strKey == "ScaleZ" )
{
* static_cast <Ogre::Real * > ( pDestValue ) = scale.z;
return true;
}
if ( strKey == "PositionX" )
{
* static_cast <Ogre::Real * > ( pDestValue ) = position.x;
return true;
}
if ( strKey == "PositionY" )
{
* static_cast <Ogre::Real * > ( pDestValue ) = position.y;
return true;
}
if ( strKey == "PositionZ" )
{
* static_cast <Ogre::Real * > ( pDestValue ) = position.z;
return true;
}
if ( strKey == "TextureNameLayer0" )
{
* static_cast < String * > ( pDestValue ) = SplatDetailMapNames[0];
return true;
}
if ( strKey == "TextureNameLayer1" )
{
* static_cast < String * > ( pDestValue ) = SplatDetailMapNames[1];
return true;
}
if ( strKey == "TextureNameLayer2" )
{
* static_cast < String * > ( pDestValue ) = SplatDetailMapNames[2];
return true;
}
if ( strKey == "TextureNameLayer3" )
{
* static_cast < String * > ( pDestValue ) = SplatDetailMapNames[3];
return true;
}
if ( strKey == "GroupName" )
{
* static_cast < String * > ( pDestValue ) = groupName;
return true;
}
if ( strKey == "BaseCameraViewpoint" )
{
* static_cast < Ogre::Vector3 * > ( pDestValue ) = BaseCameraViewpoint;
return true;
}
if ( strKey == "Baselookat" )
{
* static_cast < Ogre::Vector3 * > ( pDestValue ) = Baselookat;
return true;
}
if ( strKey == "MaxAdjacentPages" )
{
* static_cast < unsigned int * > ( pDestValue ) = max_adjacent_pages;
return true;
}
if ( strKey == "MaxPreloadedPages" )
{
* static_cast < unsigned int * > ( pDestValue ) = max_preload_pages;
return true;
}
if ( strKey == "ConfigGroupName" )
{
* static_cast < String * > ( pDestValue ) = cfgGroupName;
return true;
}
if ( strKey == "queryNoInterpolation" )
{
* static_cast < bool * > ( pDestValue ) = queryNoInterpolation;
return true;
}
if ( strKey == "queryResolutionFactor" )
{
* static_cast <Ogre::Real * > ( pDestValue ) = queryResolutionFactor;
return true;
}
return false;
}
//-----------------------------------------------------------------------
1428 bool PagingLandScapeOptions::hasOption( const String& strKey ) const
{
if ( strKey == "VisibleRenderables" )
{
return true;
}
if ( strKey == "DistanceLOD" )
{
return true;
}
if ( strKey == "VisibleDistance" )
{
return true;
}
if ( strKey == "VisibleLOD" )
{
return true;
}
// Some options proposed by Praetor
if ( strKey == "Width" )
{
return true;
}
if ( strKey == "Height" )
{
return true;
}
if ( strKey == "PageSize" )
{
return true;
}
if ( strKey == "ScaleX" )
{
return true;
}
if ( strKey == "ScaleY" )
{
return true;
}
if ( strKey == "ScaleZ" )
{
return true;
}
if ( strKey == "PositionX" )
{
return true;
}
if ( strKey == "PositionY" )
{
return true;
}
if ( strKey == "PositionZ" )
{
return true;
}
return false;
}
//-----------------------------------------------------------------------
1487 bool PagingLandScapeOptions::getOptionValues( const String & key, StringVector &refValueList )
{
// if ( key == "VisibleRenderables" )
// {
// refValueList.push_back( DataStreamPtr( ) );
// return true;
// }
// if ( key == "DistanceLOD" )
// {
// refValueList.push_back( DataStreamPtr( ) );
// return true;
// }
// if ( key == "VisibleDistance" )
// {
// refValueList.push_back( DataStreamPtr( ) );
// return true;
// }
// if ( key == "VisibleLOD" )
// {
// refValueList.push_back( DataStreamPtr( ) );
// return true;
// }
// if ( key == "Width" )
// {
// refValueList.push_back( DataStreamPtr( ) );
// return true;
// }
// if ( key == "Height" )
// {
// refValueList.push_back( DataStreamPtr( ) );
// return true;
// }
// if ( key == "PageSize" )
// {
// refValueList.push_back( DataStreamPtr( ) );
// return true;
// }
// if ( key == "ScaleX" )
// {
// refValueList.push_back( DataStreamPtr( ) );
// return true;
// }
// if ( key == "ScaleY" )
// {
// refValueList.push_back( DataStreamPtr( ) );
// return true;
// }
// if ( key == "ScaleZ" )
// {
// refValueList.push_back( DataStreamPtr( ) );
// return true;
// }
return false;
}
//-----------------------------------------------------------------------
1543 bool PagingLandScapeOptions::getOptionKeys( StringVector &refKeys )
{
refKeys.push_back( "VisibleRenderables" );
refKeys.push_back( "DistanceLOD" );
refKeys.push_back( "VisibleDistance" );
refKeys.push_back( "VisibleLOD" );
// Some options from Praetor
refKeys.push_back( "Width" );
refKeys.push_back( "Height" );
refKeys.push_back( "PageSize" );
refKeys.push_back( "ScaleX" );
refKeys.push_back( "ScaleY" );
refKeys.push_back( "ScaleZ" );
refKeys.push_back( "PositionX" );
refKeys.push_back( "PositionY" );
refKeys.push_back( "PositionZ" );
return true;
}
//-----------------------------------------------------------------------
1562 void PagingLandScapeOptions::getAvgColors( )
{
bool AvgColorsExists = false;
setBool ( AvgColorsExists, "AvgColorsExists" );
if ( AvgColorsExists )
{
const String baseName ( "MaterialColor" );
for ( unsigned int i = 0; i < NumMatHeightSplat; i++ )
{
const String matColorString ( baseName + StringConverter::toString ( i ) );
setColourValue ( matColor[i], matColorString );
}
}
else
{
for ( unsigned int i = 0; i < NumMatHeightSplat; i++ )
matColor[i] = _getAvgColor( SplatDetailMapNames[i] );
}
}
//-----------------------------------------------------------------------
1582 ColourValue PagingLandScapeOptions::_getAvgColor( const String &tex ) const
{
if ( tex.empty( ) )
return ColourValue::White;
Image img;
img.load ( tex, groupName );
const uchar * const ogre_restrict data = img.getData( );
if ( !data )
{
OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND,
"You need to define SplatFilename that has at least 3 or 4 bytes componennts ( RGB or RGBA )",
"PagingLandScapeOptions::_getAvgColor" );
}
size_t bpp = PixelUtil::getNumElemBytes ( img.getFormat ( ) );
if ( bpp < 3 )
{
OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND,
"You need to define SplatFilename that has at least 3 or 4 bytes componennts ( RGB or RGBA )",
"PagingLandScapeOptions::_getAvgColor" );
}
int cr = 0, cg = 0, cb = 0, s = 0;
const size_t imgSize = img.getSize( );
for ( size_t i = 0; i < imgSize; i += bpp )
{
cr += data[i];
cg += data[i+1];
cb += data[i+2];
s++;
}
assert ( s > 0 );
Ogre::Real divider = 1.0f / ( s * 255 );
return ColourValue ( cr * divider, cg * divider, cb * divider, 1.0f );
}
//-----------------------------------------------------------------------
1619 void PagingLandScapeOptions::clearTileInfo( )
{
if ( !mTileInfoCache.empty( ) )
{
///don't do thses things when run in Ember
//assert ( mCurrentMap != "" );
//saveMapInfo( );
std::for_each( mTileInfoCache.begin ( ),
mTileInfoCache.end ( ),
delete_object( ) );
mTileInfoCache.clear( );
}
}
//-----------------------------------------------------------------------
1633 PagingLandScapeTileInfo *PagingLandScapeOptions::getTileInfo( const uint pageX, const uint pageZ,
1634 const uint tileX, const uint tileZ )
{
PagingLandScapeTileInfo *t = 0;
std::deque<PagingLandScapeTileInfo*>::iterator q = mTileInfoCache.begin ( );
std::deque<PagingLandScapeTileInfo*>::iterator qend = mTileInfoCache.end ( );
while ( q != qend )
{
t = *q;
if ( pageX == t->mPageX &&
pageZ == t->mPageZ &&
tileX == t->mTileX &&
tileZ == t->mTileZ )
{
return t;
}
++q;
}
// no info in cache.
t = new PagingLandScapeTileInfo( pageX, pageZ, tileX, tileZ );
setTileInfo ( t );
return t;
}
//-----------------------------------------------------------------------
1658 void PagingLandScapeOptions::setTileInfo( PagingLandScapeTileInfo *t )
{
mTileInfoCache.push_back ( t );
}
//-----------------------------------------------------------------------
1663 void PagingLandScapeOptions::loadMapInfo( )
{
// load terrain.info.cfg into the deque.
if ( mUseLodMapCache )
{
assert ( !mCurrentMap.empty ( ) );
const String fName ( mCurrentMap + ".info.cfg" );
if ( ResourceGroupManager::getSingleton( ).resourceExists( groupName, fName ) )
{
ConfigFile config;
config.load ( fName, cfgGroupName, String( "=" ), true );
// those info are dependent of Pagesize and Tilesize.
// if not the same as when generated...
// we must recompute them.
const String pageSizeString = config.getSetting( String( "PageSize" ) );
if ( pageSizeString.empty( ) || PageSize != StringConverter::parseUnsignedInt ( pageSizeString ) )
return;
const String tileSizeString = config.getSetting( String( "TileSize" ) );
if ( tileSizeString.empty( ) || TileSize != StringConverter::parseUnsignedInt ( tileSizeString ) )
return;
ConfigFile::SettingsIterator setIt = config.getSettingsIterator( );
const size_t numLod = maxRenderLevel;
PagingLandScapeTileInfo *t;
while ( setIt.hasMoreElements( ) )
{
const String name = setIt.peekNextKey( );
const String value = setIt.getNext( );
if ( name != "PageSize" && name != "TileSize" )
{
// name to pageX, uint pageZ, uint tileX, uint tileZ
{
std::vector<String> coordinates = StringUtil::split( name, "_" );
const uint pageX = StringConverter::parseUnsignedInt( coordinates[0] );
const uint pageZ = StringConverter::parseUnsignedInt( coordinates[1] );
const uint tileX = StringConverter::parseUnsignedInt( coordinates[2] );
const uint tileZ = StringConverter::parseUnsignedInt( coordinates[3] );
t = new PagingLandScapeTileInfo( pageX, pageZ, tileX, tileZ );
}
// name to LOD roughness value.
{
std::vector<String> minLevelDistSqr = StringUtil::split( value, "_" );
assert ( minLevelDistSqr.size ( ) == numLod );
t->mMinLevelDistSqr = new std::vector<Real>( );
t->mMinLevelDistSqr->reserve( numLod );
t->mMinLevelDistSqr->resize( numLod );
for ( size_t i = 0; i < numLod; i++ )
{
( *( t->mMinLevelDistSqr ) )[i] = StringConverter::parseReal( minLevelDistSqr[i] );
}
}
mTileInfoCache.push_back( t );
}
}
}
}
}
//-----------------------------------------------------------------------
1731 void PagingLandScapeOptions::saveMapInfo( )
{
if ( mUseLodMapCache )
{
//if( modif ||was_empty when loaded. ) ??
assert ( !mCurrentMap.empty ( ) );
const String fInfoName ( getMapFilename( mCurrentMap ) + ".cfg" );
FileInfoListPtr finfo = ResourceGroupManager::getSingleton( ).findResourceFileInfo (
groupName, fInfoName );
FileInfoList::iterator it = finfo->begin( );
if ( it != finfo->end( ) )
{
// save deque into terrain.info.cfg
const size_t numLod = maxRenderLevel;
const String eol( "\n" );
const String coordinateSeparator( "_" );
const String valueSeparator( "=" );
PagingLandScapeTileInfo *t;
String tilesInfo( "" );
// those info are dependent of Pagesize and Tilesize.
// if not the same as when generated...
// we must recompute them.
tilesInfo += String( "PageSize=" )+StringConverter::toString( PageSize ) + eol;
tilesInfo += String( "TileSize=" )+StringConverter::toString( TileSize ) + eol;
std::deque<PagingLandScapeTileInfo*>::iterator q = mTileInfoCache.begin ( );
std::deque<PagingLandScapeTileInfo*>::iterator qend = mTileInfoCache.end ( );
while ( q != qend )
{
t = *q;
if ( t->mMinLevelDistSqr )
{
bool notEmpty = false;
for ( size_t i = 0; i < numLod; i++ )
{
if ( ( *( t->mMinLevelDistSqr ) )[i] != 0.0f )
{
notEmpty = true;
break;
}
}
if ( notEmpty )
{
tilesInfo += StringConverter::toString( t->mPageX ) + coordinateSeparator;
tilesInfo += StringConverter::toString( t->mPageZ ) + coordinateSeparator;
tilesInfo += StringConverter::toString( t->mTileX ) + coordinateSeparator;
tilesInfo += StringConverter::toString( t->mTileZ );
tilesInfo += valueSeparator;
for ( size_t i = 0; i < numLod; i++ )
{
tilesInfo += StringConverter::toString( ( *( t->mMinLevelDistSqr ) )[i] ) + coordinateSeparator;
}
tilesInfo += eol;
}
}
++q;
}
const String fConfigName ( mCurrentMap + ".info.cfg" );
char *olddir = ChangeToDir ( const_cast< char * > ( ( ( it )->archive->getName( ) ).c_str( ) ) );
std::ofstream outfile;
outfile.open ( const_cast< char * > ( fConfigName.c_str( ) )
//, std::ios:binary
);
// Write out
outfile << tilesInfo;
outfile.close ( );
RetablishDir ( olddir );
}
}
}
} //namespace
1 /***************************************************************************
OgrePagingLandScapePage.cpp - description
-------------------
begin : Sat Mar 08 2003
copyright : ( C ) 2003-2006 by Jose A. Milan and Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreMovableObject.h"
#include "OgreAxisAlignedBox.h"
#include "OgreCamera.h"
#include "OgreStringConverter.h"
#include "OgreSceneNode.h"
#include "OgreException.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeCamera.h"
#include "OgrePagingLandScapePageManager.h"
#include "OgrePagingLandScapeRenderableManager.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeData2D.h"
#include "OgrePagingLandScapeTileInfo.h"
#include "OgrePagingLandScapeTile.h"
#include "OgrePagingLandScapeTileManager.h"
#include "OgrePagingLandScapeTextureManager.h"
#include "OgrePagingLandScapePage.h"
#include "OgrePagingLandScapePageRenderable.h"
#include "OgrePagingLandScapeListenerManager.h"
#include "OgrePagingLandScapeSceneManager.h"
#include "OgrePagingLandScapeHorizon.h"
namespace Ogre
{
53 PagingLandScapePage::PagingLandScapePage( PagingLandScapePageManager *pageMgr ) :
mParent ( pageMgr ),
mIsLoading ( false ),
mIsPreLoading ( false ),
mIsTextureLoading ( false ),
mIsUnloading ( false ),
mIsPostUnloading ( false ),
mIsTextureunloading ( false ),
mIsLoaded ( false ),
mIsTextureLoaded ( false ),
mIsPreLoaded ( false ),
mIsLoadable( true ),
mPageNode ( 0 ),
mRenderable( 0 )
{
for ( unsigned int i = 0; i < 4; i++ )
{
mNeighbors[i] = 0;
}
}
//-----------------------------------------------------------------------
74 PagingLandScapePage::~PagingLandScapePage( )
{
}
//-----------------------------------------------------------------------
78 void PagingLandScapePage::init ( const unsigned int tableX, const unsigned int tableZ )
{
assert ( !mIsLoading );
assert ( !mIsPreLoading );
assert ( !mIsTextureLoading );
assert ( !mIsUnloading );
assert ( !mIsPostUnloading );
assert ( !mIsTextureunloading );
assert ( !mIsLoaded );
assert ( !mIsTextureLoaded );
assert ( !mIsPreLoaded );
assert ( mIsLoadable );
mTableX = tableX;
mTableZ = tableZ;
//create a LandScape node that handles pages and tiles
const String NodeName = "PagingLandScapePage."
+ StringConverter::toString( mTableX ) + "." +
StringConverter::toString( mTableZ );
mPageNode = mParent->getSceneManager( )->createSceneNode ( NodeName + ".Node" );
const PagingLandScapeOptions * const opt = mParent->getOptions( );
mNumTiles = opt->NumTiles;
const unsigned int size = opt->PageSize - 1;
// Boundaries of this page
// the middle page is at world coordinates 0, 0
const Real factorX = size * opt->scale.x;
const Real factorZ = size * opt->scale.z;
mIniX = static_cast<Real> ( static_cast<int> ( mTableX + mTableX - opt->world_width ) ) * 0.5f * factorX + opt->position.x;
mIniZ = static_cast<Real> ( static_cast<int> ( mTableZ + mTableZ - opt->world_height ) ) * 0.5f * factorZ + opt->position.z;
// Set node position
mPageNode->setPosition( static_cast<Real> ( mIniX ) ,
opt->position.y,
static_cast<Real> ( mIniZ ) );
const Real EndX = mIniX + factorX;
const Real EndZ = mIniZ + factorZ;
const Real MaxHeight = mParent->getSceneManager( )->getData2DManager( )->getMaxHeight( mTableX, mTableZ );
const Real chgfactor = opt->change_factor;
mBounds.setExtents( mIniX ,
0.0f,
mIniZ ,
EndX ,
MaxHeight,
EndZ );
//Change Zone of this page
mBoundsInt.setExtents( mIniX + chgfactor,
0.0f,
mIniZ + chgfactor,
EndX - chgfactor,
MaxHeight,
EndZ - chgfactor );
mBoundsExt.setExtents( mIniX - factorX * 1.5f,
- MaxHeight * 1.5f,
mIniZ - factorZ * 1.5f,
mIniX + factorX * 1.5f,
MaxHeight * 1.5f ,
mIniZ + factorZ * 1.5f );
mWorldPosition = mBounds.getCenter( );
if ( opt->BigImage )
{
mRenderable = new PagingLandScapePageRenderable( mParent,
mPageNode->getName ( ) + "rend",
mTableX, mTableZ,
mBounds );
mPageNode->attachObject( mRenderable );
mRenderable->load ( );
}
PagingLandScapePageManager * const pageMgr = mParent;
PagingLandScapePage *n;
n = pageMgr->getPage ( tableX, tableZ + 1, false );
_setNeighbor( SOUTH, n );
if ( n )
n->_setNeighbor( NORTH, this );
n = pageMgr->getPage ( tableX, tableZ - 1, false );
_setNeighbor( NORTH, n );
if ( n )
n->_setNeighbor( SOUTH, this );
n = pageMgr->getPage ( tableX + 1, tableZ, false );
_setNeighbor( EAST, n );
if ( n )
n->_setNeighbor( WEST, this );
n = pageMgr->getPage ( tableX - 1, tableZ, false );
_setNeighbor( WEST, n );
if ( n )
n->_setNeighbor( EAST, this );
mVisible = false;
touch ( );
}
//-----------------------------------------------------------------------
191 void PagingLandScapePage::uninit ( )
{
postUnload ( );
assert ( mTiles.empty( ) );
if ( mParent->getOptions( )->BigImage )
{
mPageNode->detachObject ( mRenderable->getName( ) );
delete mRenderable;
}
assert ( mPageNode );
mPageNode->removeAndDestroyAllChildren ( );
mParent->getSceneManager( )->destroySceneNode ( mPageNode->getName ( ) );
mPageNode = 0;
PagingLandScapePage *n = mNeighbors[NORTH];
if ( n )
{
n->_setNeighbor( SOUTH, 0 );
mNeighbors[NORTH] = 0;
}
n = mNeighbors[SOUTH];
if ( n )
{
n->_setNeighbor( NORTH, 0 );
mNeighbors[SOUTH] = 0;
}
n = mNeighbors[EAST];
if ( n )
{
n->_setNeighbor( WEST, 0 );
mNeighbors[EAST] = 0;
}
n = mNeighbors[WEST];
if ( n )
{
n->_setNeighbor( EAST, 0 );
mNeighbors[WEST] = 0;
}
// restore init state.
mIsLoading = false;
mIsPreLoading = false;
mIsTextureLoading = false;
mIsUnloading = false;
mIsPostUnloading = false;
mIsTextureunloading = false;
mIsLoaded = false;
mIsTextureLoaded = false;
mIsPreLoaded = false;
mIsLoadable = true;
}
//-----------------------------------------------------------------------
248 void PagingLandScapePage::_setNeighbor( const Neighbor& n, PagingLandScapePage* p )
{
mNeighbors[ n ] = p;
const bool thisLoaded = mIsLoaded;
const bool neighLoaded = p && p->isLoaded( ) && p->isLoadable( );
if ( !thisLoaded && !neighLoaded )
return;
assert ( !thisLoaded || ( thisLoaded && !mTiles.empty( ) ) );
const unsigned int numTiles = mNumTiles;
switch ( n )
{
case EAST:
{
const unsigned int i = numTiles - 1;
for ( unsigned int j = 0; j < numTiles; j++ )
{
PagingLandScapeTile *t_nextpage = 0;
PagingLandScapeTile *t_currpage = 0;
if ( thisLoaded )
t_currpage = mTiles[ i ][ j ];
if ( neighLoaded )
t_nextpage = p->getTile ( 0 , j );
if ( thisLoaded )
t_currpage->_setNeighbor( EAST, t_nextpage );
if ( neighLoaded )
t_nextpage->_setNeighbor( WEST, t_currpage );
}
}
break;
case WEST:
{
const unsigned int i = numTiles - 1;
for ( unsigned int j = 0; j < numTiles; j++ )
{
PagingLandScapeTile *t_nextpage = 0;
PagingLandScapeTile *t_currpage = 0;
if ( thisLoaded )
t_currpage = mTiles[ 0 ][ j ];
if ( neighLoaded )
t_nextpage = p->getTile ( i , j );
if ( thisLoaded )
t_currpage->_setNeighbor( WEST, t_nextpage );
if ( neighLoaded )
t_nextpage->_setNeighbor( EAST, t_currpage );
}
}
break;
case NORTH:
{
const unsigned int j = numTiles - 1;
for ( unsigned int i = 0; i < numTiles; i++ )
{
PagingLandScapeTile *t_nextpage = 0;
PagingLandScapeTile *t_currpage = 0;
if ( thisLoaded )
t_currpage = mTiles[ i ][ 0 ];
if ( neighLoaded )
t_nextpage = p->getTile ( i , j );
if ( thisLoaded )
t_currpage->_setNeighbor( NORTH, t_nextpage );
if ( neighLoaded )
t_nextpage->_setNeighbor( SOUTH, t_currpage );
}
}
break;
case SOUTH:
{
const unsigned int j = numTiles - 1;
for ( unsigned int i = 0; i < numTiles; i++ )
{
PagingLandScapeTile *t_nextpage = 0;
PagingLandScapeTile *t_currpage = 0;
if ( thisLoaded )
t_currpage = mTiles[ i ][ j ];
if ( neighLoaded )
t_nextpage = p->getTile ( i , 0 );
if ( thisLoaded )
t_currpage->_setNeighbor( SOUTH, t_nextpage );
if ( neighLoaded )
t_nextpage->_setNeighbor( NORTH, t_currpage );
}
}
break;
default:
break;
}
}
//-----------------------------------------------------------------------
340 void PagingLandScapePage::setMapMaterial( )
{
if ( mParent->getOptions( )->BigImage )
{
mRenderable->setMaterial ( mParent->getSceneManager( )->getTextureManager( )->getMapMaterial( ) );
}
}
//-----------------------------------------------------------------------
348 void PagingLandScapePage::touch ( )
{
mTimeUntouched = mParent->getOptions( )->PageInvisibleUnloadFrames;
}
//-----------------------------------------------------------------------
353 const bool PagingLandScapePage::unloadUntouched ( )
{
if ( mTimeUntouched == 0 )
return true;
mTimeUntouched--;
return false;
}
//-----------------------------------------------------------------------
361 void PagingLandScapePage::preload( )
{
touch ( );
if ( mIsPreLoaded )
return;
mIsLoadable = mParent->getSceneManager( )->getData2DManager( )->load ( mTableX, mTableZ );
mIsPreLoaded = true;
mParent->getSceneManager( )->getListenerManager( )->firePagePreloaded( mTableX, mTableZ,
mParent->getSceneManager( )->getData2DManager( )->getData2D( mTableX, mTableZ )->getHeightData( ),
mBounds );
}
//-----------------------------------------------------------------------
377 void PagingLandScapePage::loadTexture( )
{
touch ( );
if ( !mIsPreLoaded )
preload ( );
if ( !mIsTextureLoaded )
{
if ( mIsLoadable )
mParent->getSceneManager( )->getTextureManager( )->load( mTableX, mTableZ );
mIsTextureLoaded = true;
}
}
//-----------------------------------------------------------------------
390 void PagingLandScapePage::load( )
{
touch ( );
if ( mIsLoaded )
return;
if ( !mIsPreLoaded )
preload ( );
if ( !mIsTextureLoaded )
loadTexture ( );
assert ( mTiles.empty( ) );
//mVisibletouch = 0;
mIsLoaded = true;
//mPageNode->showBoundingBox ( true ) ;
if ( mIsLoadable )
{
const unsigned int numTiles = mNumTiles;
unsigned int i, j;
mTiles.reserve ( numTiles );
mTiles.resize ( numTiles );
for ( i = 0; i < numTiles; ++i )
{
mTiles[i].reserve ( numTiles );
mTiles[i].resize ( numTiles );
}
PagingLandScapeTile *tile;
PagingLandScapeTileManager * const tileMgr = mParent->getSceneManager( )->getTileManager( );
for ( i = 0; i < numTiles; ++i )
{
for ( j = 0; j < numTiles; ++j )
{
//char name[ 24 ];
//sprintf( name, "page[%d, %d][%d, %d]", mTableX, mTableZ, i, j );
tile = tileMgr->getTile ( );
assert ( tile );
mTiles[ i ][ j ] = tile;
tile->init ( mPageNode, mTableX, mTableZ, i, j );
}
}
for ( i = 0; i < numTiles; ++i )
{
for ( j = 0; j < numTiles; ++j )
{
if ( j != numTiles - 1 )
{
mTiles[ i ][ j ]-> _setNeighbor( SOUTH, mTiles[ i ][ j + 1 ] );
mTiles[ i ][ j + 1 ] ->_setNeighbor( NORTH, mTiles[ i ][ j ] );
}
if ( i != numTiles - 1 )
{
mTiles[ i ][ j ]->_setNeighbor( EAST, mTiles[ i + 1 ][ j ] );
mTiles[ i + 1 ][ j ]->_setNeighbor( WEST, mTiles[ i ][ j ] );
}
}
}
PagingLandScapePageManager * const pageMgr = mParent;
PagingLandScapePage *n;
n = pageMgr->getPage ( mTableX, mTableZ + 1, false );
_setNeighbor( SOUTH, n );
if ( n )
n->_setNeighbor( NORTH, this );
n = pageMgr->getPage ( mTableX, mTableZ - 1, false );
_setNeighbor( NORTH, n );
if ( n )
n->_setNeighbor( SOUTH, this );
n = pageMgr->getPage ( mTableX + 1, mTableZ, false );
_setNeighbor( EAST, n );
if ( n )
n->_setNeighbor( WEST, this );
n = pageMgr->getPage ( mTableX - 1, mTableZ, false );
_setNeighbor( WEST, n );
if ( n )
n->_setNeighbor( EAST, this );
}
mParent->getSceneManager( )->getListenerManager( )->firePageLoaded( mTableX, mTableZ,
mParent->getSceneManager( )->getData2DManager( )->getData2D( mTableX, mTableZ )->getHeightData( ),
mBounds );
_Show( true );
}
//-----------------------------------------------------------------------
484 void PagingLandScapePage::unload( )
{
if ( mIsLoaded )
{
assert ( !mTiles.empty( ) );
// must be 0 to make sure page is really set as non visible
//mVisibletouch = 0;
//if ( mVisible )
_Show ( false );
// Unload the Tiles
PagingLandScapeTiles::iterator iend = mTiles.end( );
for ( PagingLandScapeTiles::iterator it = mTiles.begin( );
it != iend;
++it )
{
std::for_each( it->begin ( ),
it->end ( ),
std::mem_fun( &PagingLandScapeTile::uninit ) );
it->clear( );
}
mTiles.clear( );
assert ( mTiles.empty( ) );
mIsLoaded = false;
mParent->getSceneManager( )->getListenerManager( )->firePageUnloaded( mTableX, mTableZ,
mParent->getSceneManager( )->getData2DManager( )->getData2D( mTableX, mTableZ )->getHeightData( ),
mBounds );
assert ( mPageNode );
assert ( mPageNode->getParent ( ) == 0 );
}
}
//-----------------------------------------------------------------------
523 void PagingLandScapePage::unloadTexture( )
{
unload( );
if ( mIsTextureLoaded )
{
if ( mIsLoadable )
mParent->getSceneManager( )->getTextureManager( )->unload( mTableX, mTableZ );
mIsTextureLoaded = false;
}
}
//-----------------------------------------------------------------------
534 void PagingLandScapePage::postUnload( )
{
unloadTexture ( );
if ( mIsPreLoaded )
{
mIsPreLoaded = false;
if ( mIsLoadable )
mParent->getSceneManager( )->getData2DManager( )->unload( mTableX, mTableZ );
mParent->getSceneManager( )->getListenerManager( )->firePagePostunloaded ( mTableX, mTableZ );
}
}
//-----------------------------------------------------------------------
549 int PagingLandScapePage::isCameraIn( const Vector3 & pos ) const
{
if ( mBounds.intersects( pos ) )
{
if ( mBoundsInt.intersects( pos ) )
{
// Full into this page
return PAGE_INSIDE;
}
else
{
// Over the change zone
return PAGE_CHANGE;
}
}
else
{
// Not in this page
return PAGE_OUTSIDE;
}
}
//-----------------------------------------------------------------------
571 void PagingLandScapePage::_Show( const bool do_show )
{
assert ( mPageNode );
if ( do_show )
{
assert ( !mVisible );
if ( !mPageNode->getParent ( ) )
mParent->getSceneManager( )->getRootSceneNode( )->addChild ( mPageNode );
mParent->getSceneManager( )->getListenerManager( )->firePageShow ( mTableX, mTableZ,
mParent->getSceneManager( )->getData2DManager( )->getData2D( mTableX, mTableZ )->getHeightData( ),
mBounds );
if ( mIsLoadable )
{
unsigned int i, k;
for ( i = 0; i < mNumTiles; ++i )
{
PagingLandScapeTileRow &tr = mTiles[ i ];
for ( k = 0; k < mNumTiles; ++k )
{
tr[ k ]->setInUse( true );
}
}
}
mVisible = true;
}
else if ( mVisible )
{
assert ( do_show == false );
//if ( mVisibletouch == 0 )
{
if ( mPageNode->getParent ( ) )
mParent->getSceneManager( )->getRootSceneNode( )->removeChild ( mPageNode->getName ( ) );
mParent->getSceneManager( )->getListenerManager( )->firePageHide ( mTableX, mTableZ,
mParent->getSceneManager( )->getData2DManager( )->getData2D( mTableX, mTableZ )->getHeightData( ),
mBounds );
if ( mIsLoadable )
{
unsigned int i, k;
for ( i = 0; i < mNumTiles; ++i )
{
PagingLandScapeTileRow &tr = mTiles[ i ];
for ( k = 0; k < mNumTiles; ++k )
{
tr[ k ]->setInUse ( false );
}
}
}
mVisible = false;
}
//else
//{
// mVisibletouch--;
//}
}
}
//-----------------------------------------------------------------------
631 bool PagingLandScapePage::_Notify( const Vector3 &pos, const PagingLandScapeCamera * const Cam )
{
if ( mIsLoaded && mIsLoadable )
{
// ( ( pos - mWorldPosition ).squaredLength( ) < mParent->getOptions( )->page_factor ?
if (
1
//Cam->isVisible ( mBoundsExt )
//&&
// if we use an Horizon Visibility Map
//( !( mParent->getOptions( )->VisMap )
// || ( mParent->getOptions( )->VisMap
// && mParent->getSceneManager( )->getHorizon( )->IsPageVisible ( Cam, mTableX, mTableZ ) ) )
)
{
touch( );
//if ( !mVisible )
// _Show ( true );
//mVisibletouch = 30;
for ( unsigned int i = 0; i < mNumTiles; i++ )
{
PagingLandScapeTileRow &tr = mTiles[ i ];
for ( unsigned int k = 0; k < mNumTiles; k++ )
{
tr[ k ]->_Notify( pos, Cam );
}
}
return true;
}
else if ( mVisible )
{
// if it was visible it needs to change its state
//_Show ( false );
return false;
}
}
return false;
}
//-----------------------------------------------------------------------
672 PagingLandScapeTile *PagingLandScapePage::getTile( const Vector3& pos )
{
if ( mIsLoaded && mIsLoadable )
{
const unsigned int x = static_cast<unsigned int> ( pos.x / mParent->getOptions( )->scale.x / ( mParent->getOptions( )->TileSize ) );
const unsigned int z = static_cast<unsigned int> ( pos.z / mParent->getOptions( )->scale.z / ( mParent->getOptions( )->TileSize ) );
assert ( mTiles[x][z] && mTiles[x][z]-> isLoaded ( ) );
return mTiles[x][z];
}
return 0;
}
//-------------------------------------------------------------------------
685 void PagingLandScapePage::_updateLod( )
{
if ( mIsLoaded && mIsLoadable )
{
unsigned int i, k;
for ( i = 0; i < mNumTiles; ++i )
{
PagingLandScapeTileRow &tr = mTiles[ i ];
for ( k = 0; k < mNumTiles; ++k )
{
PagingLandScapeTile *t = tr[ k ];
if ( t->isVisible( ) )
t->_updateLod( );
}
}
}
}
//-------------------------------------------------------------------------
703 void PagingLandScapePage::setRenderQueue( uint8 qid )
{
if ( mVisible &&
mIsLoadable )
{
unsigned int i, k;
for ( i = 0; i < mNumTiles; ++i )
{
PagingLandScapeTileRow &tr = mTiles[ i ];
for ( k = 0; k < mNumTiles; ++k )
{
PagingLandScapeTile *t = tr[ k ];
if ( t->isVisible( ) )
t->setRenderQueueGroup( qid );
}
}
}
}
//-------------------------------------------------------------------------
722 PagingLandScapeTile* PagingLandScapePage::getTile( const unsigned int i , const unsigned int j ) const
{
if ( mIsLoaded )
{
assert ( !mTiles.empty( ) );
assert ( i < mParent->getOptions( )->NumTiles );
assert ( j < mParent->getOptions( )->NumTiles );
assert ( i < mTiles.size( ) );
assert ( j < mTiles[i].size( ) );
return mTiles[i][j];
}
return 0;
}
} //namespace
1 /***************************************************************************
OgrePagingLandScapePageManager.cpp - description
-------------------
begin : Sat May 01 2004
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreMovableObject.h"
#include "OgreAxisAlignedBox.h"
#include "OgreCamera.h"
#include "OgrePagingLandScapeSceneManager.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeCamera.h"
#include "OgrePagingLandScapePage.h"
#include "OgrePagingLandScapePageManager.h"
#include "OgrePagingLandScapeTileManager.h"
#include "OgrePagingLandScapeRenderableManager.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeTextureManager.h"
#include "OgrePagingLandScapeTexture.h"
#include "OgrePagingLandScapeTileInfo.h"
#include "OgrePagingLandScapeTile.h"
#include "OgrePagingLandScapeRenderable.h"
#include "OgrePagingLandScapeListenerManager.h"
#include "OgrePagingLandScapePageRenderable.h"
#include "OgrePagingLandScapeHorizon.h"
namespace Ogre
{
//-----------------------------------------------------------------------
49 PagingLandScapePageManager::PagingLandScapePageManager( PagingLandScapeSceneManager * scnMgr ) :
mSceneManager( scnMgr ),
mOptions( scnMgr->getOptions( ) ),
mData2d( scnMgr->getData2DManager( ) ),
mTexture( scnMgr->getTextureManager( ) ),
mRenderablesMgr( scnMgr->getRenderableManager( ) ),
mWidth( 0 ),
mHeight( 0 ),
mNextQueueFrameCount( 0 ),
mPause( 99 ),
mCurrentcam( 0 ),
mTerrainReady( false ),
mTimePreLoaded( 0 ),
mRenderQueueGroupID ( static_cast<Ogre::RenderQueueGroupID>( scnMgr->getWorldGeometryRenderQueue( ) ) ),
//mRenderQueueGroupID ( RENDER_QUEUE_WORLD_GEOMETRY_2 ),
mPageLoadInterval ( mOptions->PageLoadInterval ),
mOnFrame( false ),
mEnabled( false )
{
mPagePool.clear( );
mActivePages.clear( );
mFreePages.clear( );
}
//-----------------------------------------------------------------------
73 PagingLandScapePageManager::~PagingLandScapePageManager( void )
{
reset( );
// could save a delete if texture type is the same... ?
if ( !mPagePool.empty( ) )
{
std::for_each ( mPagePool.begin ( ), mPagePool.end ( ),
delete_object ( ) );
mPagePool.clear( );
mFreePages.clear( );
}
}
//-----------------------------------------------------------------------
86 void PagingLandScapePageManager::reset( void )
{
std::for_each( mActivePages.begin( ), mActivePages.end( ),
std::mem_fun( &PagingLandScapePage::uninit ) );
// Insert actives into free list
mFreePages.insert( mFreePages.end( ), mActivePages.begin( ), mActivePages.end( ) );
// Remove all active instances
mActivePages.clear( );
mPageLoadQueue.clear( );
mPagePreloadQueue.clear( );
mPageTextureloadQueue.clear( );
mLoadedPages.clear( );
mTextureLoadedPages.clear( );
mPreLoadedPages.clear( );
mWidth = 0;
mHeight = 0;
mOnFrame = false;
mEnabled = false;
}
//-----------------------------------------------------------------------
110 void PagingLandScapePageManager::load( void )
{
WorldDimensionChange ( );
mEnabled = true;
}
//-----------------------------------------------------------------------
116 void PagingLandScapePageManager::clear( void )
{
// before calling the scene manager node clearing
reset( );
}
//-----------------------------------------------------------------------
122 void PagingLandScapePageManager::WorldDimensionChange( void )
{
const unsigned int newWidth = mOptions->world_width;
const unsigned int newHeight = mOptions->world_height;
reset( );
mPageLoadInterval = mOptions->PageLoadInterval;
mWidth = newWidth;
mHeight = newHeight;
}
//-----------------------------------------------------------------------
134 void PagingLandScapePageManager::setMapMaterial( void )
{
std::for_each( mActivePages.begin( ), mActivePages.end( ),
std::mem_fun( &PagingLandScapePage::setMapMaterial ) );
}
//-----------------------------------------------------------------------
140 void PagingLandScapePageManager::_updateLod( void )
{
PagingLandScapePageList::iterator lend = mLoadedPages.end( );
for ( PagingLandScapePageList::iterator l = mLoadedPages.begin( ); l != lend; ++l )
{
( *l )->_updateLod( );
}
}
//-----------------------------------------------------------------------
149 bool PagingLandScapePageManager::frameStarted( const FrameEvent& evt )
{
if ( mEnabled )//if not queued to be removed from framelistener or Paused
{
--mTimePreLoaded;
if ( mOptions->VisMap )
{
mSceneManager->getHorizon ( )->prepare( static_cast< PagingLandScapeCamera* >( mOptions->primaryCamera ) );
}
mOnFrame = false;
}
return true;
}
//-----------------------------------------------------------------------
163 bool PagingLandScapePageManager::frameEnded( const FrameEvent& evt )
{
// mOnFrame If This Frame has seen any Camera,
// We won't unload anything.
// since un-focusing rendering may make this method unload all renderables.
// mEnabled sm paused or frame listener queued for deletion
if ( !mOnFrame || !mEnabled )
return true;
// unload some pages if no more in use
processUnloadQueues( );
// load some pages that are still queued
processLoadQueues( );
if ( !mTerrainReady &&
mPagePreloadQueue.empty( ) &&
mPageLoadQueue.empty( ) &&
mPageTextureloadQueue.empty( ) )
{
mSceneManager->getListenerManager( )->fireTerrainReady( );// no more to load
mTerrainReady = true;
}
if ( mOptions->VisMap )
mSceneManager->getHorizon( )->update( );
mSceneManager->getTileManager( )->unloadUntouched( );
mRenderablesMgr->resetVisibles( );
return true;
}
//-----------------------------------------------------------------------
194 PagingLandScapePage *PagingLandScapePageManager::getNewPage( const unsigned int x, const unsigned int z )
{
PagingLandScapePage *p;
// should we resize page pool
if ( mFreePages.empty( ) )
{
const size_t pool_size = mPagePool.size ( );
const size_t new_pool_size = ( pool_size == 0 ) ? 9 : pool_size * 2;
mPagePool.reserve( new_pool_size );
mPagePool.resize( new_pool_size );
// Create new pages
for ( size_t i = pool_size; i < new_pool_size; ++i )
{
p = new PagingLandScapePage ( this );
mPagePool[i] = p;
mFreePages.push_back ( p );
}
}
// Get a pre-allocated new page.
p = mFreePages.front ( );
mFreePages.pop_front ( );
mActivePages.push_back ( p );
p->init ( x, z );
return p;
}
//-----------------------------------------------------------------------
226 void PagingLandScapePageManager::releasePage( PagingLandScapePage *p )
{
removeFromQueues ( p );
p->uninit ( );
mActivePages.remove ( p );
mFreePages.push_back ( p );
}
//-----------------------------------------------------------------------
234 PagingLandScapePage *PagingLandScapePageManager::getPage( const unsigned int x, const unsigned int z,
235 const bool alwaysReturn )
{
if ( x < mWidth && z < mHeight )
{
if ( !mActivePages.empty( ) )
{
PagingLandScapePageList::iterator l, lend = mActivePages.end( );
for ( l = mActivePages.begin( ); l != lend; ++l )
{
if ( ( *l )->isCoord( x, z ) )
return ( *l );
}
}
if ( alwaysReturn )
return getNewPage( x, z );
}
assert ( !alwaysReturn );
return 0;
}
//-----------------------------------------------------------------------
255 void PagingLandScapePageManager::LoadFirstPage( PagingLandScapeCamera* cam )
{
const Vector3 CamPos = cam->getDerivedPosition( );
//gets page indices ( if outside Terrain gets nearest page )
unsigned int i, j;
getPageIndices ( CamPos.x, CamPos.z, i, j, true );
// update the camera page position
// does modify mIniX, mFinX, mIniZ, mFinZ
PagingLandScapePage *p = getPage ( i, j );
makePageLoadedNow ( p );
}
//-----------------------------------------------------------------------
269 void PagingLandScapePageManager::makePageLoadedNow( PagingLandScapePage * p )
{
// Have the current page be loaded now !
if ( !p->isLoaded( ) )
{
// remove from lists it does belongs to
if ( p->isTextureLoaded( ) )
mTextureLoadedPages.remove ( p );
else if ( p->isPreLoaded( ) )
mPreLoadedPages.remove ( p );
// remove from queue it does belongs to
removeFromQueues ( p );
p->load( );
assert ( std::find( mLoadedPages.begin( ), mLoadedPages.end( ), p ) == mLoadedPages.end( ) );
mLoadedPages.push_back ( p );
// make sure this brutal loading doesn't impact on fps
mNextQueueFrameCount = mPageLoadInterval;
}
else
{
p->touch ( );
}
}
//-----------------------------------------------------------------------
295 void PagingLandScapePageManager::updateLoadedPages( )
{
PagingLandScapeCamera * const cam = mCurrentcam;
// Make any pending updates to the calculated frustum
cam->updateView( );
const Vector3 pos ( cam->getDerivedPosition( ).x, 127.0f, cam->getDerivedPosition( ).z );
// hide page not visible by this Camera
// Notify those Page ( update tile vis/ rend load on cam distance )
// update Page Texture if needed
const unsigned int iniX = cam->mIniX;
const unsigned int finX = cam->mFinX;
const unsigned int iniZ = cam->mIniZ;
const unsigned int finZ = cam->mFinZ;
PagingLandScapePage *p;
const bool lightchange = mOptions->lightmoved;
PagingLandScapePageList::iterator l, lend = mLoadedPages.end ( );
for ( l = mLoadedPages.begin ( ); l != lend; ++l )
{
p = ( *l );
unsigned int x, z;
p->getCoordinates ( x, z );
if ( ( z >= iniZ ) && ( z <= finZ ) && ( x >= iniX ) && ( x <= finX ) )
{
// inform pages we are near Camera on next render.
if ( p->_Notify ( pos, cam ) )
{
// get pages that needs modification and Are visible..
PagingLandScapeTexture * const tex = mTexture->getTexture( x, z );
assert( tex );
if ( lightchange )
tex->lightUpdate( );
if ( tex->needUpdate( ) )
tex->update( );
}
}
else
{
p->_Show ( false );
}
}
if ( lightchange )
mOptions->lightmoved = false;
}
//-----------------------------------------------------------------------
347 void PagingLandScapePageManager::loadNow( PagingLandScapeCamera *cam )
{
updatePaging ( cam );
const Vector3 pos ( cam->getDerivedPosition( ).x, 127.0f, cam->getDerivedPosition( ).z );
while ( !mTerrainReady ||
!mPagePreloadQueue.empty( ) ||
!mPageLoadQueue.empty( ) ||
!mPageTextureloadQueue.empty( ) )
{
processLoadQueues( );// fill pages queues
updateLoadedPages( );// fill tiles queues
mTerrainReady = mRenderablesMgr->executeRenderableLoading( pos ); // load renderables
mNextQueueFrameCount = -1;
}
//assert ( )
}
//-----------------------------------------------------------------------
364 void PagingLandScapePageManager::queuePageNeighbors( )
{
const PagingLandScapeCamera * const cam = mCurrentcam;
// Queue the rest
// Loading must be done one by one to avoid FPS drop, so they are queued.
// We must load the next visible LandScape pages,
// check the LandScape boundaries
const unsigned int preIniX = cam->mPreIniX;
const unsigned int preFinX = cam->mPreFinX;
const unsigned int preIniZ = cam->mPreIniZ;
const unsigned int preFinZ = cam->mPreFinZ;
const unsigned int iniX = cam->mIniX;
const unsigned int finX = cam->mFinX;
const unsigned int iniZ = cam->mIniZ;
const unsigned int finZ = cam->mFinZ;
PagingLandScapePage *p;
for ( unsigned int i = preIniX; i <= preFinX; i++ )
{
for ( unsigned int j = preIniZ; j <= preFinZ; j++ )
{
// pages here, in this zone around camera,
// must be at least preloading.
// that means they can be loaded too.
p = getPage ( i, j, true );
if ( !( p->mIsLoading || p->isLoaded( ) ) )
{
if( ( j >= iniZ ) && ( j <= finZ ) && ( i >= iniX ) && ( i <= finX ) )
{
// pages here, in this tighter zone around camera,
// must be Loading or Loaded as they may
// be below camera very soon.
removeFromQueues ( p );
mPageLoadQueue.push ( p );
p->mIsLoading = true;
}
else if ( !p->mIsTextureLoading &&
!p->isTextureLoaded( ) &&
!p->mIsPreLoading &&
!p->isPreLoaded( ) )
{
// must be at least preloading.
removeFromQueues ( p );
mPagePreloadQueue.push ( p );
p->mIsPreLoading = true;
}
}
p->touch ( );
}
}
mTimePreLoaded = mPageLoadInterval;
}
//-----------------------------------------------------------------------
422 void PagingLandScapePageManager::updatePaging( PagingLandScapeCamera *cam )
{
mCurrentcam = cam;
// Here we have to look if we have to load, unload any of the LandScape Pages
// Fix from Praetor, so the camera used gives you "world-relative" coordinates
// make sure in the bounding box of LandScape
const Vector3 pos ( cam->getDerivedPosition( ).x,
127.0f,
cam->getDerivedPosition( ).z );
//updateStats( pos );
bool need_touch = false;//( mTimePreLoaded < 0 );
if ( mWidth == 0 && mHeight == 0 ) {
//just return if we haven't got any world yet
return;
}
if ( cam->mLastCameraPos != pos
&& ( mOptions->cameraThreshold < fabs ( cam->mLastCameraPos.x - pos.x ) ||
mOptions->cameraThreshold < fabs ( cam->mLastCameraPos.z - pos.z ) ) )
{
// Update only if the camera was moved
PagingLandScapePage * const oldPage = getPage ( cam->mCurrentCameraPageX, cam->mCurrentCameraPageZ, false );
PagingLandScapeTile * const oldTile = ( oldPage && oldPage->isLoaded( ) ?
oldPage->getTile ( cam->mCurrentCameraTileX, cam->mCurrentCameraTileZ ) : 0 );
unsigned int i, j;
//gets page indices ( if outside Terrain gets nearest page )
getPageIndices ( pos.x, pos.z, i, j, true );
PagingLandScapePage *p = getPage ( i, j );
if ( !p ) {
return;
}
makePageLoadedNow ( p );
// update current Cam Page info
if ( oldPage != p )
{
// update the camera info :
cam->updatePaging( i, j );
// need to inform neighbors pages
need_touch = true;
}
// Update current Cam Tile info.
if ( p->isLoadable( ) )
{
PagingLandScapeTile * const t = getTile ( pos.x, pos.z, i, j, true );
if ( t && t != oldTile )
{
if ( mOptions->MaxLodUnderCam )
{
// reset previous tile at normal LOD mechanism.
if ( oldTile && oldTile->isLoaded( ) )
{
assert ( oldTile->getRenderable( ) );
oldTile->getRenderable( )->setMaxLod ( false );
}
// set current tile at max LOD whatever complexity it is.
if ( t->isLoaded( ) )
{
assert ( t->getRenderable( ) );
t->getRenderable( )->setMaxLod ( true );
}
}
PagingLandScapeTileInfo * const CurrentTileInfo = t->getInfo( );
cam->mCurrentCameraTileX = CurrentTileInfo->mTileX;
cam->mCurrentCameraTileZ = CurrentTileInfo->mTileZ;
}
}
// Update the last camera position
if ( mOptions->cameraThreshold < fabs ( cam->mLastCameraPos.x - pos.x ) )
cam->mLastCameraPos.x = pos.x;
if ( mOptions->cameraThreshold < fabs ( cam->mLastCameraPos.z - pos.z ) )
cam->mLastCameraPos.z = pos.z;
}
if ( need_touch )
queuePageNeighbors( );
updateLoadedPages( );
//if ( mNextQueueFrameCount < 0 )
mRenderablesMgr->executeRenderableLoading( pos );
// This Frame has seen a Camera.
mOnFrame = true;
}
//-----------------------------------------------------------------------
514 void PagingLandScapePageManager::processUnloadQueues( )
{
// Check for pages that need to be unloaded.
// if touched, that means they didn't have been touch by any cameras
// for several frames and thus need to be unloaded.
PagingLandScapePage *p;
// LIST CHECKS
PagingLandScapePageList::iterator itl;
for ( itl = mPreLoadedPages.begin ( ); itl != mPreLoadedPages.end ( ); )
{
if ( ( *itl )->unloadUntouched ( ) )
{
p = *itl;
releasePage ( p );
itl = mPreLoadedPages.erase ( itl );
}
else
{
++itl;
}
}
for ( itl = mTextureLoadedPages.begin ( ); itl != mTextureLoadedPages.end ( ); )
{
if ( ( *itl )->unloadUntouched ( ) )
{
p = *itl;
releasePage ( p );
itl = mTextureLoadedPages.erase ( itl );
}
else
{
++itl;
}
}
for ( itl = mLoadedPages.begin ( ); itl != mLoadedPages.end ( ); )
{
if ( ( *itl )->unloadUntouched ( ) )
{
p = *itl;
releasePage ( p );
itl = mLoadedPages.erase ( itl );
}
else
{
++itl;
}
}
// QUEUES CHECKS
// check queues for page that need to be excluded from queues
PagingLandScapeQueue<PagingLandScapePage>::MsgQueType::iterator itq;
for ( itq = mPagePreloadQueue.begin ( ); itq != mPagePreloadQueue.end ( ); )
{
assert ( !( *itq )->isLoaded( ) && !( *itq )->isPreLoaded( ) && !( *itq )->isTextureLoaded( ) );
assert ( !( *itq )->mIsLoading && !( *itq )->mIsTextureLoading );
if ( ( *itq )->unloadUntouched ( ) )
{
p = *itq;
// remove from queue
p->mIsPreLoading = false;
itq = mPagePreloadQueue.erase ( itq );
// remove from active pages
//( must be removed from queue first )
releasePage ( p );
}
else
{
++itq;
}
}
for ( itq = mPageTextureloadQueue.begin( ); itq != mPageTextureloadQueue.end( ); )
{
assert ( !( *itq )->isLoaded( ) && ( *itq )->isPreLoaded( ) && !( *itq )->isTextureLoaded( ) );
assert ( !( *itq )->mIsLoading && ( *itq )->mIsTextureLoading && !( *itq )->mIsPreLoading );
if ( ( *itq )->unloadUntouched ( ) )
{
p = *itq;
// remove from queue
p->mIsTextureLoading = false;
itq = mPageTextureloadQueue.erase ( itq );
// remove from active pages
//( must be removed from queue first )
releasePage ( p );
}
else
{
++itq;
}
}
for ( itq = mPageLoadQueue.begin ( ); itq != mPageLoadQueue.end ( ); )
{
assert ( !( *itq )->isLoaded( ) );
assert ( ( *itq )->mIsLoading && !( *itq )->mIsTextureLoading && !( *itq )->mIsPreLoading );
if ( ( *itq )->unloadUntouched ( ) )
{
p = *itq;
// remove from queue
p->mIsLoading = false;
itq = mPageLoadQueue.erase ( itq );
// remove from active pages
//( must be removed from queue first )
releasePage ( p );
}
else
{
++itq;
}
}
}
//-----------------------------------------------------------------------
624 void PagingLandScapePageManager::processLoadQueues( )
{
// Should be called every count frame only
// to minimize fps impact
if ( mNextQueueFrameCount-- < 0 )
{
SceneManager::CameraIterator camIt = mSceneManager->getCameraIterator( );
while ( camIt.hasMoreElements( ) )
{
Camera const * const currentCamera = camIt.getNext( );
const Vector3 pos ( currentCamera->getDerivedPosition( ).x,
127.0f,
currentCamera->getDerivedPosition( ).z );
// We to Load nearest page in non-empty queue
if ( !mPageLoadQueue.empty ( ) )
{
// We to Load nearest page in non-empty queue
PagingLandScapePage *p = mPageLoadQueue.find_nearest ( pos );
assert ( p && !p->isLoaded ( ) );
assert ( !p->mIsTextureLoading && !p->mIsPreLoading );
p->load ( );
p->mIsLoading = false;
mLoadedPages.push_back ( p );
mTextureLoadedPages.remove ( p );
mNextQueueFrameCount = mPageLoadInterval;
}
else if ( !mPageTextureloadQueue.empty ( ) )
{
// We TextureLoad nearest page in non-empty queue
PagingLandScapePage *p = mPageTextureloadQueue.find_nearest ( pos );
assert ( p && !p->isTextureLoaded( ) );
assert ( !p->mIsLoading && !p->mIsPreLoading );
p->loadTexture ( );
p->mIsTextureLoading = false;
mTextureLoadedPages.push_back ( p );
mPreLoadedPages.remove ( p );
// do not automatically push to level up.
//mPageLoadQueue.push ( p );
mNextQueueFrameCount = mPageLoadInterval;
}
else if ( !mPagePreloadQueue.empty ( ) )
{
// We PreLoad nearest page in non-empty queue
PagingLandScapePage *p = mPagePreloadQueue.find_nearest ( pos );
assert ( p && !p->isPreLoaded( ) );
assert ( !p->mIsLoading && !p->mIsTextureLoading );
p->preload ( );
p->mIsPreLoading = false;
mPreLoadedPages.push_back ( p );
mPageTextureloadQueue.push ( p );
p->mIsTextureLoading = true;
mNextQueueFrameCount = mPageLoadInterval;
}
}
} // if ( mNextQueueFrameCount-- < 0 )
}
//-----------------------------------------------------------------------
685 void PagingLandScapePageManager::removeFromQueues( PagingLandScapePage* p )
{
assert ( p );
if ( p->mIsLoading )
{
p->mIsLoading = false;
mPageLoadQueue.remove ( p );
}
else if ( p->mIsTextureLoading )
{
p->mIsTextureLoading = false;
mPageTextureloadQueue.remove ( p );
}
else if ( p->mIsPreLoading )
{
p->mIsPreLoading = false;
mPagePreloadQueue.remove ( p );
}
assert ( !p->mIsLoading && !p->mIsTextureLoading && !p->mIsPreLoading );
}
//-----------------------------------------------------------------------
706 unsigned int PagingLandScapePageManager::getCurrentCameraPageX( void ) const
{
if ( mCurrentcam )
{
return mCurrentcam->mCurrentCameraPageX;
}
return 0;
}
//-----------------------------------------------------------------------
717 unsigned int PagingLandScapePageManager::getCurrentCameraPageZ( void ) const
{
if ( mCurrentcam )
{
return mCurrentcam->mCurrentCameraPageZ;
}
return 0;
}
//-----------------------------------------------------------------------
727 unsigned int PagingLandScapePageManager::getCurrentCameraTileX( void ) const
{
if ( mCurrentcam )
{
return mCurrentcam->mCurrentCameraTileX;
}
return 0;
}
//-----------------------------------------------------------------------
737 unsigned int PagingLandScapePageManager::getCurrentCameraTileZ( void ) const
{
if ( mCurrentcam )
{
return mCurrentcam->mCurrentCameraTileZ;
}
return 0;
}
//-----------------------------------------------------------------------
746 void PagingLandScapePageManager::addLoadedPage( PagingLandScapePage *p )
{
mLoadedPages.push_back ( p );
}
//-----------------------------------------------------------------------
751 int PagingLandScapePageManager::getLoadedPageSize( void ) const
{
return static_cast< int >( mLoadedPages.size( ) );
}
//-----------------------------------------------------------------------
756 int PagingLandScapePageManager::getUnloadedPagesSize( void ) const
{
return static_cast< int >( mWidth*mHeight - mLoadedPages.size( ) );
}
//-----------------------------------------------------------------------
761 int PagingLandScapePageManager::getTextureLoadedPageSize( void ) const
{
return static_cast< int >( mTextureLoadedPages.size( ) );
}
//-----------------------------------------------------------------------
767 int PagingLandScapePageManager::getPreLoadedPageSize( void ) const
{
return static_cast< int >( mPreLoadedPages.size( ) );
}
//-----------------------------------------------------------------------
772 int PagingLandScapePageManager::getPagePreloadQueueSize( void ) const
{
return static_cast< int >( mPagePreloadQueue.getSize( ) );
}
//-----------------------------------------------------------------------
778 int PagingLandScapePageManager::getPageTextureloadQueueSize( void ) const
{
return static_cast< int >( mPageTextureloadQueue.getSize( ) );
}
//-----------------------------------------------------------------------
784 int PagingLandScapePageManager::getPageLoadQueueSize( void ) const
{
return static_cast< int >( mPageLoadQueue.getSize( ) );
}
//-----------------------------------------------------------------------
790 void PagingLandScapePageManager::getGlobalToPage( Real& x, Real& z ) const
{
const Real inv_pSize = 1.0f / ( mOptions->PageSize - 1 );
x = static_cast< int >( ( ( x / mOptions->scale.x ) + mOptions->maxUnScaledX ) * inv_pSize );
z = static_cast< int >( ( ( z / mOptions->scale.z ) + mOptions->maxUnScaledZ ) * inv_pSize );
}
//-----------------------------------------------------------------------
799 void PagingLandScapePageManager::getNearestPageIndicesUnscaled( const Real posx, const Real posz, unsigned int& x, unsigned int& z ) const
{
// adjust x and z to be local to page
const Real inv_pSize = 1.0f / ( mOptions->PageSize - 1 );
const int lx = static_cast< int >( ( posx + mOptions->maxUnScaledX ) * inv_pSize );
const int lz = static_cast< int >( ( posz + mOptions->maxUnScaledZ ) * inv_pSize );
const int w = static_cast< int >( mOptions->world_width );
const int h = static_cast< int >( mOptions->world_height );
// make sure indices are not negative or outside range of number of pages
if ( lx >= w )
{
x = static_cast< unsigned int >( w - 1 );
}
else if ( lx < 0 )
{
x = 0;
}
else
{
x = static_cast< unsigned int >( lx );
}
if ( lz >= h )
{
z = static_cast< unsigned int >( h - 1 );
}
else if ( lz < 0 )
{
z = 0;
}
else
{
z = static_cast< unsigned int >( lz );
}
}
//-----------------------------------------------------------------------
841 void PagingLandScapePageManager::getNearestTileIndicesUnscaled( const Real posx, const Real posz,
const unsigned int pagex, const unsigned int pagez,
unsigned int& x, unsigned int& z ) const
{
// adjust x and z to be local to page
const Real inv_tSize = 1.0f / ( mOptions->TileSize - 1 );
const int pSize = mOptions->PageSize - 1;
const int tilex = static_cast< int >( ( posx - ( ( pagex * pSize ) - mOptions->maxUnScaledX ) ) * inv_tSize );
//- mOptions->maxUnScaledX
const int tilez = static_cast< int >( ( posz - ( ( pagez * pSize ) - mOptions->maxUnScaledZ ) ) * inv_tSize );
//- mOptions->maxUnScaledZ
const int tilesPerPage = static_cast< int >( ( pSize * inv_tSize ) - 1 );
if ( tilex > tilesPerPage )
{
x = static_cast< unsigned int >( tilesPerPage );
}
else if ( tilex < 0 )
{
x = 0;
}
else
{
x = static_cast< unsigned int >( tilex );
}
if ( tilez > tilesPerPage )
{
z = static_cast< unsigned int >( tilesPerPage );
}
else if( tilez < 0 )
{
z = 0;
}
else
{
z = static_cast< unsigned int >( tilez );
}
}
//-----------------------------------------------------------------------
884 bool PagingLandScapePageManager::getTileIndices( const Real posx, const Real posz,
const unsigned int pagex, const unsigned int pagez,
886 unsigned int& x, unsigned int& z, bool alwaysAnswer ) const
{
if ( alwaysAnswer )
{
getNearestTileIndicesUnscaled( posx / mOptions->scale.x, posz / mOptions->scale.z, pagex, pagez, x, z );
return true;
}
else
{
return getRealTileIndicesUnscaled( posx / mOptions->scale.x, posz / mOptions->scale.z, pagex, pagez, x, z );
}
}
//-----------------------------------------------------------------------
899 PagingLandScapeTile* PagingLandScapePageManager::getTileUnscaled( const Real posx, const Real posz, const unsigned int pagex, const unsigned int pagez, bool alwaysAnswer )
{
unsigned int tilex, tilez;
if ( alwaysAnswer )
{
getNearestTileIndicesUnscaled( posx, posz, pagex, pagez, tilex, tilez );
PagingLandScapePage * const p = getPage ( pagex , pagez, false );
if ( p )
return p->getTile( tilex, tilez );
}
else
{
if ( getRealTileIndicesUnscaled( posx, posz, pagex, pagez, tilex, tilez ) )
{
PagingLandScapePage * const p = getPage ( pagex , pagez, false );
if ( p )
return p->getTile( tilex, tilez );
}
}
return 0;
}
//-----------------------------------------------------------------------
921 PagingLandScapeTile* PagingLandScapePageManager::getTile( const Real posx, const Real posz, const unsigned int pagex, const unsigned int pagez, bool alwaysAnswer )
{
return getTileUnscaled( posx / mOptions->scale.x, posz / mOptions->scale.z, pagex, pagez, alwaysAnswer );
}
//-----------------------------------------------------------------------
926 PagingLandScapeTile* PagingLandScapePageManager::getTile( const Real posx, const Real posz, bool alwaysAnswer )
{
return getTileUnscaled( posx / mOptions->scale.x, posz / mOptions->scale.z, alwaysAnswer );
}
//-----------------------------------------------------------------------
931 PagingLandScapeTile* PagingLandScapePageManager::getTileUnscaled( const Real posx, const Real posz, bool alwaysAnswer )
{
unsigned int pagex, pagez;
if ( alwaysAnswer )
{
unsigned int tilex, tilez;
getNearestPageIndicesUnscaled( posx, posz, pagex, pagez );
getNearestTileIndicesUnscaled( posx, posz, pagex, pagez, tilex, tilez );
return getPage ( pagex , pagez )->getTile( tilex, tilez );
}
else
{
if ( getRealPageIndicesUnscaled( posx, posz, pagex, pagez ) )
{
unsigned int tilex, tilez;
if ( getRealTileIndicesUnscaled( posx, posz, pagex, pagez, tilex, tilez ) )
{
PagingLandScapePage * const p = getPage ( pagex , pagez, false );
if ( p )
return p->getTile( tilex, tilez );
}
}
}
return 0;
}
//-------------------------------------------------------------------------
957 PagingLandScapeTile* PagingLandScapePageManager::getTilePage ( unsigned int &posx, unsigned int &posz,
const unsigned int pagex, const unsigned int pagez )
{
const Real tSize = mOptions->TileSize - 1;
const Real inv_tSize = 1.0f / tSize;
const int tilex = static_cast< int >( posx * inv_tSize );
const int tilez = static_cast< int >( posz * inv_tSize );
const int pSize = mOptions->PageSize - 1;
const int tilesPerPage = static_cast< int > ( mOptions->NumTiles - 1 );
unsigned int x;
if ( tilex > tilesPerPage )
{
x = static_cast< unsigned int >( tilesPerPage );
}
else if ( tilex < 0 )
{
x = 0;
}
else
{
x = static_cast< unsigned int >( tilex );
}
unsigned int z;
if ( tilez > tilesPerPage )
{
z = static_cast< unsigned int >( tilesPerPage );
}
else if( tilez < 0 )
{
z = 0;
}
else
{
z = static_cast< unsigned int >( tilez );
}
posx = posx - static_cast< unsigned int > ( x * tSize );
posz = posz - static_cast< unsigned int > ( z * tSize );
PagingLandScapePage *p = getPage ( pagex , pagez );
if ( p )
return p->getTile( x, z );
return 0;
}
//-------------------------------------------------------------------------
1003 void PagingLandScapePageManager::setWorldGeometryRenderQueue( uint8 qid )
{
PagingLandScapePageList::iterator l, lend = mLoadedPages.end( );
for ( l = mLoadedPages.begin( ); l != lend; ++l )
{
PagingLandScapePage *p = ( *l );
{
p->setRenderQueue( qid );
}
}
}
}
1 /***************************************************************************
OgrePagingLandScapePageRenderable.cpp - description
-------------------
begin : Thu Feb 27 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreRoot.h"
#include "OgreHardwareBufferManager.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreMovableObject.h"
#include "OgreAxisAlignedBox.h"
#include "OgreCamera.h"
#include "OgreViewport.h"
#include "OgreSceneNode.h"
#include "OgreSimpleRenderable.h"
#include "OgrePagingLandScapeSceneManager.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeCamera.h"
#include "OgrePagingLandScapePageRenderable.h"
#include "OgrePagingLandScapeTile.h"
#include "OgrePagingLandScapeTileInfo.h"
#include "OgrePagingLandScapeData2D.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeTextureManager.h"
#include "OgrePagingLandScapePageManager.h"
namespace Ogre
{
// Renderable Buffer definitions
#define MAIN_BINDING 0
PagingLandScapeOptions *PagingLandScapePageRenderable::mOpt;
String PagingLandScapePageRenderable::mType = "PagingLandScapePageBillBoard";
//-----------------------------------------------------------------------
61 PagingLandScapePageRenderable::PagingLandScapePageRenderable( PagingLandScapePageManager *pageMgr, const String& name, const unsigned int pageX, const unsigned int pageZ,
62 const AxisAlignedBox &bounds ) :
Renderable( ),
MovableObject( name ),
mParent( pageMgr ),
mX( pageX ),
mZ( pageZ ),
mBounds( bounds ),
mCurrVertexes ( 0 ),
mCurrIndexes ( 0 )
{
// No shadow projection
MovableObject::mCastShadows = false;
// Default query flags to top bit so users can exclude it if they wish
//MovableObject::mQueryFlags = SceneManager::WORLD_GEOMETRY_QUERY_MASK;
// Setup render op
mCurrIndexes = new IndexData( );
const unsigned int Numtiles = mParent->getOptions( )->NumTiles + 1;
const size_t new_length = ( ( Numtiles - 1 ) * ( Numtiles - 1 ) * 2 * 2 * 2 );
mCurrIndexes->indexCount = new_length;
mCurrIndexes->indexStart = 0;
mCurrIndexes->indexBuffer =
HardwareBufferManager::getSingleton( ).createIndexBuffer(
HardwareIndexBuffer::IT_16BIT,
new_length,
HardwareBuffer::HBU_STATIC_WRITE_ONLY );
mCurrVertexes = new VertexData( );
mCurrVertexes->vertexStart = 0;
mCurrVertexes->vertexCount = Numtiles * Numtiles + 1;
// Vertex declaration
VertexDeclaration* decl = mCurrVertexes->vertexDeclaration;
VertexBufferBinding* bind = mCurrVertexes->vertexBufferBinding;
// Vertex buffer #1, position
// positions
size_t offset = 0;
decl->addElement( MAIN_BINDING, 0, VET_FLOAT3, VES_POSITION );
offset += VertexElement::getTypeSize ( VET_FLOAT3 );
decl->addElement( MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0 );
offset += VertexElement::getTypeSize( VET_FLOAT2 );
HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton ( ).createVertexBuffer(
decl->getVertexSize ( MAIN_BINDING ),
mCurrVertexes->vertexCount,
HardwareBuffer::HBU_STATIC_WRITE_ONLY );
bind->setBinding( MAIN_BINDING, vbuf );
}
//-----------------------------------------------------------------------
119 PagingLandScapePageRenderable::~PagingLandScapePageRenderable( )
{
delete mCurrVertexes;
delete mCurrIndexes;
mMaterial.setNull( );
}
//-----------------------------------------------------------------------
128 void PagingLandScapePageRenderable::load( )
{
// case renderable was queued before page was unloaded
// when loaded, page exists no more.
VertexDeclaration* decl = mCurrVertexes->vertexDeclaration;
VertexBufferBinding* bind = mCurrVertexes->vertexBufferBinding;
const VertexElement* poselem = decl->findElementBySemantic( VES_POSITION );
const VertexElement* texelem = decl->findElementBySemantic( VES_TEXTURE_COORDINATES, 0 );
HardwareVertexBufferSharedPtr vVertices = bind->getBuffer( MAIN_BINDING );
uchar* pMain = static_cast<uchar*>( vVertices->lock( HardwareBuffer::HBL_DISCARD ) );
const unsigned int Numtiles = mParent->getOptions( )->NumTiles + 1;
const Real invpagesizeX = 1.0f / ( ( Numtiles - 1 ) * mParent->getOptions( )->world_width );
const Real invpagesizeZ = 1.0f / ( ( Numtiles - 1 )* mParent->getOptions( )->world_height );
const Real texOffsetX = mX * ( Numtiles - 1 ) * invpagesizeX;
const Real texOffsetZ = mZ * ( Numtiles - 1 ) * invpagesizeZ;
const Real scale_x = mOpt->scale.x * ( mOpt->TileSize - 1 );
const Real scale_z = mOpt->scale.z * ( mOpt->TileSize - 1 );
unsigned int i, j;
for ( j = 0; j < Numtiles ; j ++ )
{
// This allow to reuse the variables in the loop
const Real h_pos = j * scale_z;
const Real Tex_pos = texOffsetZ + j * invpagesizeZ;
for ( i = 0; i < Numtiles; i ++ )
{
// vertices are relative to the scene node
float *pPos;
poselem->baseVertexPointerToElement( pMain, &pPos );
*pPos++ = static_cast <float> ( i * scale_x ); //X
*pPos++ = static_cast <float> ( 0.0 ); //Y
*pPos = static_cast <float> ( h_pos ); //Z
float *pTex;
texelem->baseVertexPointerToElement( pMain, &pTex );
*pTex++ = static_cast <float> ( texOffsetX + i * invpagesizeX );
*pTex = static_cast <float> ( Tex_pos );
pMain += vVertices->getVertexSize ( );
}
}
// Unlock the buffers
vVertices->unlock( );
ushort* pIdx = static_cast<ushort*>( mCurrIndexes->indexBuffer->lock( 0,
mCurrIndexes->indexBuffer->getSizeInBytes( ),
HardwareBuffer::HBL_DISCARD ) );
unsigned int height_count = 0;
unsigned int NumIndexes = 0;
for ( j = 0; j < Numtiles - 1; j ++ )
{
for ( i = 0; i < Numtiles - 1; i ++ )
{
// Indexes
*pIdx++ = static_cast<ushort> ( i + height_count ); NumIndexes++;
*pIdx++ = static_cast<ushort> ( i + height_count + Numtiles ); NumIndexes++;
*pIdx++ = static_cast<ushort> ( i + 1 + height_count ); NumIndexes++;
*pIdx++ = static_cast<ushort> ( i + height_count + Numtiles ); NumIndexes++;
*pIdx++ = static_cast<ushort> ( i + 1 + height_count + Numtiles ); NumIndexes++;
*pIdx++ = static_cast<ushort> ( i + 1 + height_count ); NumIndexes++;
}
height_count += Numtiles;
}
mCurrIndexes->indexBuffer->unlock( );
assert ( NumIndexes < mCurrIndexes->indexCount );
const Real max =
mParent->getSceneManager( )->getData2DManager( )->getMaxHeight( mX,
mZ );
// Calculate the bounding box for this renderable
mBounds.setExtents( 0.0f,
0.0f,
0.0f,
0.0f + Numtiles * scale_x,
max,
0.0f + Numtiles * scale_z );
assert ( mParentNode );
mCenter = mBounds.getCenter( ) + mParentNode->getWorldPosition( );
mWorldBoundingSphere.setCenter( mCenter );
mWorldBoundingSphere.setRadius( mBounds.getMaximum( ).length( ) );
mParentNode->needUpdate( );
MovableObject::setRenderQueueGroup( mParent->getSceneManager( )->getPageManager( )->getRenderQueueGroupID( ) );
}
//-----------------------------------------------------------------------
239 void PagingLandScapePageRenderable::_updateRenderQueue( RenderQueue* queue )
{
queue->addRenderable( this );
}
//-----------------------------------------------------------------------
244 Technique* PagingLandScapePageRenderable::getTechnique( void ) const
{
return mMaterial->getBestTechnique ( );
}
//-----------------------------------------------------------------------
249 const LightList& PagingLandScapePageRenderable::getLights( void ) const
{
#ifdef PLSM2_EIHORT
return queryLights( );
#else
return MovableObject::getParentSceneNode( )->findLights( this->getBoundingRadius( ) );
#endif
}
//-----------------------------------------------------------------------
258 Real PagingLandScapePageRenderable::getSquaredViewDepth( const Camera* cam ) const
{
// Use squared length to avoid square root
return ( mCenter -
cam->getDerivedPosition ( ) ).squaredLength( );
}
//-----------------------------------------------------------------------
266 Real PagingLandScapePageRenderable::getBoundingRadius( void ) const
{
return mWorldBoundingSphere.getRadius( );
}
//-----------------------------------------------------------------------
271 void PagingLandScapePageRenderable::getRenderOperation( RenderOperation& op )
{
//setup indexes for vertices and uvs...
op.useIndexes = true;
op.operationType = RenderOperation::OT_TRIANGLE_LIST;
op.vertexData = mCurrVertexes;
op.indexData = mCurrIndexes;
}
//-----------------------------------------------------------------------
281 void PagingLandScapePageRenderable::getWorldTransforms( Matrix4* xform ) const
{
*xform = mParentNode->_getFullTransform( );
}
//-----------------------------------------------------------------------
286 const Quaternion& PagingLandScapePageRenderable::getWorldOrientation( void ) const
{
return mParentNode->_getDerivedOrientation( );
}
//-----------------------------------------------------------------------
291 const Vector3& PagingLandScapePageRenderable::getWorldPosition( void ) const
{
return mCenter;
}
//-----------------------------------------------------------------------
296 void PagingLandScapePageRenderable::setMaterial( const MaterialPtr &mat )
{
mMaterial = mat;
}
//-----------------------------------------------------------------------
301 uint32 PagingLandScapePageRenderable::getTypeFlags( void ) const
{
// return world flag
return SceneManager::WORLD_GEOMETRY_TYPE_MASK;
}
} //namespace
1 /***************************************************************************
OgrePagingLandScapePrecompiledHeaders.cpp - description
-------------------
copyright : ( C ) 2006 Tuan Kuranes
email : tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
1 /***************************************************************************
OgrePagingLandScapeRaySceneQuery.cpp - description
-------------------
begin : Fri Sep 10 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreEntity.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreSceneManager.h"
#include "OgrePagingLandScapeOctreeSceneManager.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeSceneManager.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeRaySceneQuery.h"
namespace Ogre
{
//----------------------------------------------------------------------------
// This function return the vertex interpolated height.
// Supplied by Praetor. Thanks a lot. ]: )
39 void PagingLandScapeRaySceneQuery::execute( RaySceneQueryListener* listener )
{
///Ember start
///Make sure that there really is some world geometry first
if ( ( static_cast<PagingLandScapeSceneManager*>( mParentSceneMgr )->mWorldGeomIsSetup ) && ( getQueryTypeMask( ) & SceneManager::WORLD_GEOMETRY_TYPE_MASK ) )
///Ember end
{
mWorldFrag.fragmentType = SceneQuery::WFT_SINGLE_INTERSECTION;
const Vector3& dir = mRay.getDirection( );
const Vector3& origin = mRay.getOrigin( );
PagingLandScapeSceneManager* mSceneMgr = static_cast<PagingLandScapeSceneManager*>( mParentSceneMgr );
if ( mWorldFragmentType & WFT_SINGLE_INTERSECTION )
{
if ( dir == Vector3::UNIT_Y ||
dir == Vector3::NEGATIVE_UNIT_Y )
{
Real height;
if ( mSceneMgr->getOptions( )->queryNoInterpolation )
height = mSceneMgr->getData2DManager( )->getWorldHeight( origin.x, origin.z );
else
height = mSceneMgr->getData2DManager( )->getInterpolatedWorldHeight( origin.x, origin.z );
mWorldFrag.singleIntersection.x = origin.x;
mWorldFrag.singleIntersection.z = origin.z;
mWorldFrag.singleIntersection.y = height;
mWorldFrag.singleIntersection += mSceneMgr->getOptions( )->position; //consider terrain offset
listener->queryResult( &mWorldFrag, ( Math::Abs( mWorldFrag.singleIntersection.y - origin.y ) ) );
return;
}
else if ( mSceneMgr->intersectSegmentTerrain(
origin,
dir * mSceneMgr->getOptions( )->queryResolutionFactor,
&mWorldFrag.singleIntersection ) )
{
listener->queryResult( &mWorldFrag, ( mWorldFrag.singleIntersection - origin ).length( ) );
///Ember start
PagingLandScapeOctreeRaySceneQuery::execute( listener );
///Ember end
return;
}
}
else
{
// multiple terrain intersection
const Vector3 raydir ( mRay.getDirection( ) );
const Vector3 raymove ( raydir * mSceneMgr->getOptions( )->queryResolutionFactor );
const Real distmove = mSceneMgr->getOptions( )->queryResolutionFactor;
const Real maxHeight = mSceneMgr->getData2DManager( )->getMaxHeight ( );
const Real MaxTerrainX = mSceneMgr->getOptions( )->maxScaledX;
const Real MaxTerrainZ = mSceneMgr->getOptions( )->maxScaledZ;
Vector3 ray ( mRay.getOrigin( ) );
Real dist = 0.0f;
// while ray is inside or ray is outside but raydir going inside
while ( ( ray.y < 0 && raydir.y > 0 ) ||
( ray.y > maxHeight && raydir.y < 0 ) ||
( ray.x < -MaxTerrainX && raydir.x > 0 ) ||
( ray.x > MaxTerrainX && raydir.x < 0 ) ||
( ray.z < -MaxTerrainZ && raydir.z > 0 ) ||
( ray.z > MaxTerrainZ && raydir.z < 0 ) )
{
ray += raymove;
dist += distmove;
if ( ray.y < maxHeight )// no need to do complex tests
{
const Vector3 land ( getHeightAt( ray ) );
if ( ray.y < land.y )
{
WorldFragment* frag = new WorldFragment( );
//fragmentList.push_back( frag );
frag->fragmentType = SceneQuery::WFT_SINGLE_INTERSECTION;
frag->singleIntersection = land;
if ( !listener->queryResult( frag, dist ) )
return;
}
}
}
}
}
// if anything else is queried, ask underlying Octree Scene Manager.
PagingLandScapeOctreeRaySceneQuery::execute( listener );
}
//----------------------------------------------------------------------------
130 Vector3 PagingLandScapeRaySceneQuery::getHeightAt( const Vector3& origin ) const
{
PagingLandScapeSceneManager * mSceneMgr = static_cast<PagingLandScapeSceneManager*>( mParentSceneMgr );
return Vector3( origin.x, mSceneMgr->getData2DManager( )->getInterpolatedWorldHeight( origin.x, origin.z ), origin.z );
}
} // namespace Ogre
/***************************************************************************
OgrePagingLandScapeRenderable.cpp - description
-------------------
begin : Thu Feb 27 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreRoot.h"
#include "OgreHardwareBufferManager.h"
#include "OgreLogManager.h"
#include "OgreStringConverter.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreMovableObject.h"
#include "OgreAxisAlignedBox.h"
#include "OgreSceneNode.h"
#include "OgreSimpleRenderable.h"
#include "OgrePagingLandScapeSceneManager.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeCamera.h"
#include "OgrePagingLandScapeRenderable.h"
#include "OgrePagingLandScapeRenderableManager.h"
//caches
#include "OgrePagingLandScapeIndexBuffer.h"
#include "OgrePagingLandScapeTextureCoordinatesManager.h"
#include "OgrePagingLandScapeTile.h"
#include "OgrePagingLandScapeTileInfo.h"
#include "OgrePagingLandScapeData2D.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeListenerManager.h"
#include "OgrePagingLandScapePageManager.h"
#include "OgrePagingLandScapeHorizon.h"
namespace Ogre
{
// Renderable Buffer definitions
#define MAIN_BINDING 0
#define DELTA_BINDING 2
#define TEXTURE_BINDING 1
String PagingLandScapeRenderable::mType = "PagingLandScapeRenderable";
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
70 PagingLandScapeRenderable::PagingLandScapeRenderable( PagingLandScapeRenderableManager *renderableMgr ) :
Renderable( ),
MovableObject( ),
mParent( renderableMgr ),
mCurrVertexes ( 0 ),
mCurrIndexes ( 0 ),
mInfo ( 0 ),
mMaterialLODIndex ( 0 ),
mInUse ( false ),
mIsLoaded ( false ),
mDeltaBuffers ( 0 ),
mLastNextLevel ( -1 ),
mLODMorphFactor ( 0.0f ),
83 mHeightfield ( 0 ),
mMinLevelDistSqr ( 0 ),
mRenderLevel ( -1 ),
mIsRectModified ( false ),
mRect ( 0, 0, 0, 0, 0, 1 ),
mForcedMaxLod ( false )
///Ember added start
, mNeedReload( false )
///Ember added stop
{
// No shadow projection
MovableObject::mCastShadows = false;
// Default query flags to top bit so users can exclude it if they wish
MovableObject::mQueryFlags = SceneManager::WORLD_GEOMETRY_TYPE_MASK;
MovableObject::setRenderQueueGroup(
mParent->getSceneManager( )->getPageManager( )->getRenderQueueGroupID( ) );
for ( unsigned int i = 0; i < 4; i++ )
mNeighbors[ i ] = 0;
// Setup render op
mCurrVertexes = new VertexData( );
mCurrVertexes->vertexStart = 0;
const unsigned int tileSize = mParent->getOptions ( )->TileSize;
mCurrVertexes->vertexCount = tileSize * tileSize;
// Vertex declaration
VertexDeclaration* decl = mCurrVertexes->vertexDeclaration;
VertexBufferBinding* bind = mCurrVertexes->vertexBufferBinding;
// Vertex buffer #1, position
// positions
size_t offset = 0;
VertexElementType t;
if ( mParent->getOptions( )->VertexCompression )
{
t = VET_SHORT2;
}
else
{
t = VET_FLOAT3;
}
decl->addElement( MAIN_BINDING, 0, t, VES_POSITION );
offset += VertexElement::getTypeSize ( t );
if ( mParent->getOptions( )->normals )
{
decl->addElement( MAIN_BINDING, offset, VET_FLOAT3, VES_NORMAL );
offset += VertexElement::getTypeSize ( VET_FLOAT3 );
}
if ( mParent->getOptions( )->colored )
{
decl->addElement ( MAIN_BINDING, offset, VET_COLOUR, VES_DIFFUSE );
offset += VertexElement::getTypeSize ( VET_COLOUR );
}
HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton ( ).createVertexBuffer(
decl->getVertexSize ( MAIN_BINDING ),
mCurrVertexes->vertexCount,
HardwareBuffer::HBU_STATIC_WRITE_ONLY );
//HardwareBuffer::HBU_STATIC );
bind->setBinding( MAIN_BINDING, vbuf );
if ( mParent->getOptions ( )->lodMorph )
{
// Create delta buffer for all except the lowest mipmap
assert ( mParent->getOptions ( )->maxRenderLevel > 1 );
const unsigned int maxmip = mParent->getOptions ( )->maxRenderLevel - 1;
mDeltaBuffers = new HardwareVertexBufferSharedPtr[maxmip];
// Create additional element for delta
decl->addElement( DELTA_BINDING, 0, VET_SHORT2, VES_BLEND_WEIGHTS );
//decl->addElement( DELTA_BINDING, 0, VET_SHORT1, VES_BLEND_WEIGHTS );
//decl->addElement( DELTA_BINDING, 0, VET_FLOAT1, VES_BLEND_WEIGHTS );
//decl->addElement( DELTA_BINDING, 0, VET_SHORT1, VES_TEXTURE_COORDINATES, 1 );
//decl->addElement( DELTA_BINDING, 0, VET_SHORT2, VES_TEXTURE_COORDINATES, 1 );
for ( unsigned int k = 0; k < maxmip; k++ )
{
assert ( mDeltaBuffers[k].isNull( ) );
mDeltaBuffers[k] = createDeltaBuffer( );
}
// NB binding is not set here, it is set when deriving the LOD
}
//No need to set the indexData since it is shared from LandScapeIndexBuffer class
mCustomGpuParameters = Vector4( mParent->getOptions ( )->ScaledPageSizeX,
mParent->getOptions ( )->ScaledHeightY,
mParent->getOptions ( )->ScaledPageSizeZ,
mLODMorphFactor );
mQueued = false;
mParentTile = 0;
}
//-----------------------------------------------------------------------
183 PagingLandScapeRenderable::~PagingLandScapeRenderable( )
{
delete mCurrVertexes;
delete [] mDeltaBuffers;
}
//------------------------------------------------------------------------
190 void PagingLandScapeRenderable::uninit( )
{
if ( mIsLoaded )
unload ( );
mParentTile = 0;
mParent->freeRenderable( this );
mInfo = 0;
mHeightfield = 0;
mCurrIndexes = 0;
mLastNextLevel = -1;
mRenderLevel = -1;
mVisible = false;
mInUse = false;
mMaterial.setNull( );
mLightListDirty = true;
mQueued = false;
mParentTile = 0;
mMinLevelDistSqr = 0;
}
//-----------------------------------------------------------------------
212 void PagingLandScapeRenderable::init( PagingLandScapeTileInfo* info )
{
mMinLevelDistSqr = 0;
mQueued = false;
mParentTile = 0;
mLightListDirty = true;
mInfo = info;
mInUse = true;
mName = StringConverter::toString( mInfo->mPageX ) + "." +
StringConverter::toString( mInfo->mPageZ ) + "." +
StringConverter::toString( mInfo->mTileX ) + "." +
StringConverter::toString( mInfo->mTileZ ) + "Rend";
mForcedMaxLod = false;
mUpperDistance = mParent->getOptions ( )->renderable_factor;
mIsLoaded = false;
//we can init texcoord buffer as it's data independent.
VertexDeclaration * const decl = mCurrVertexes->vertexDeclaration;
VertexBufferBinding * const bind = mCurrVertexes->vertexBufferBinding;
// make sure buffer isn't binded to another texture coordinate buffer
if ( decl->findElementBySemantic ( VES_TEXTURE_COORDINATES, 0 ) != 0 )
{
decl->removeElement( VES_TEXTURE_COORDINATES, 0 );
bind->unsetBinding ( TEXTURE_BINDING );
}
// Bind to an existing texture coordinate buffer if it exists
// or create a new one for this ( x, y ) combination tile position.
//( texture coordinate buffer are shared across buffers )
const VertexElementType t = VET_FLOAT2;
//const VertexElementType t = VET_SHORT2;
decl->addElement( TEXTURE_BINDING, 0, t, VES_TEXTURE_COORDINATES, 0 );
bind->setBinding( TEXTURE_BINDING,
mParent->getSceneManager( )->getTextureCoordinatesManager( )->getBuffer(
info->mTileX,
info->mTileZ ) );
}
//-----------------------------------------------------------------------
253 bool PagingLandScapeRenderable::load( )
{
assert ( mQueued || mNeedReload );
assert ( mInfo );
//if ( !mInUse )
//{
// if not in use, do not load.
//if ( mIsLoaded )
// return true;
//else
// return false;
//}
// case renderable was queued before page was unloaded
// when loaded, page exists no more.
PagingLandScapeData2D *data = mParent->getSceneManager( )->getData2DManager( )->getData2D( mInfo->mPageX, mInfo->mPageZ );
// Page could be unloaded since renderable queued...
if ( data == 0 || !data->isLoaded( ) )
return false;
mHeightfield = data->getHeightData ( );
if ( mHeightfield == 0 )
return false;
const bool b_lit = mParent->getOptions ( )->normals;
const bool b_coverage = mParent->getOptions ( )->coverage_vertex_color;
const bool b_colored = mParent->getOptions ( )->colored;
const Real scale_x = mParent->getOptions ( )->scale.x;
const Real scale_z = mParent->getOptions ( )->scale.z;
VertexDeclaration* decl = mCurrVertexes->vertexDeclaration;
VertexBufferBinding* bind = mCurrVertexes->vertexBufferBinding;
const VertexElement* poselem = decl->findElementBySemantic( VES_POSITION );
const VertexElement* colorelem;
if ( b_colored )
colorelem= decl->findElementBySemantic( VES_DIFFUSE );
const VertexElement* normelem;
if ( b_lit )
normelem = decl->findElementBySemantic( VES_NORMAL );
// Calculate the offset in the data
Real min, max;
const unsigned int tileSize = mParent->getOptions ( )->TileSize;
Image::Box oldrect = mRect;
if ( !mIsRectModified )
{
mRect.left = 0;
mRect.right = tileSize;
mRect.top = 0;
mRect.bottom = tileSize;
// Make sure we get a new min and max
min = mParent->getSceneManager( )->getData2DManager( )->getMaxHeight ( );
max = 0.0f;
}
else
{
mRect.right += 1;
mRect.bottom += 1;
// LogManager::getSingleton( ).logMessage( LML_CRITICAL,
// String( "PLSM2 : Deformation on tile " ) + StringConverter::toString( mInfo->tileX ) + ", " + StringConverter::toString( mInfo->tileZ )
// + " : " + StringConverter::toString( mRect.left ) + " - " + StringConverter::toString( mRect.right )
// + " | " + StringConverter::toString( mRect.top ) + " - " + StringConverter::toString( mRect.bottom ) );
// Make sure we get a new min and max
// only if modified heights exceed current bounds
min = mBounds.getMinimum( ).y;
max = mBounds.getMaximum( ).y;
}
const unsigned int offSetX = static_cast <unsigned int> ( mInfo->mTileX * ( tileSize - 1 ) + mRect.left );
const unsigned int endx = static_cast <unsigned int> ( offSetX + ( mRect.right - mRect.left ) );
const unsigned int offSetZ = static_cast <unsigned int> ( mInfo->mTileZ * ( tileSize - 1 ) + mRect.top );
const unsigned int endz = static_cast <unsigned int> ( offSetZ + ( mRect.bottom - mRect.top ) );
const double inv_scale = 65535.0 / mParent->getOptions ( )->scale.y;
const unsigned int pageSize = mParent->getOptions ( )->PageSize;
const Real * const ogre_restrict mheightField = mHeightfield;
const bool vs = mParent->getOptions( )->VertexCompression;
HardwareVertexBufferSharedPtr vVertices = bind->getBuffer( MAIN_BINDING );
const size_t VertexSize = vVertices->getVertexSize ( );
const size_t VertexTileSize = VertexSize * tileSize;
uchar* pMain = static_cast<uchar*>(
vVertices->lock( VertexTileSize * mRect.top + mRect.left * VertexSize, // offset
VertexTileSize *( mRect.bottom - mRect.top ) - ( tileSize - mRect.right ) * VertexSize, //length
HardwareBuffer::HBL_DISCARD ) );// buffer mode
// initial up-down shift and left-right shift
const Real * const heightField = mheightField + offSetZ * pageSize;
unsigned int K_heightFieldPos = 0;
for ( unsigned int k = offSetZ; k < endz; k ++ )
{
// This allow to reuse the variables in the loop
const Real k_pos = k * scale_z;
uchar *pMainLocal = pMain;
for ( unsigned int i = offSetX; i < endx; i ++ )
{
const Real height = heightField[ i + K_heightFieldPos ];
min = std::min ( height, min );
max = std::max ( height, max );
// vertices are relative to the scene node
if ( vs )
{
ushort *pPos;
poselem->baseVertexPointerToElement( pMainLocal, &pPos );
*pPos = static_cast<short> ( ( height * inv_scale ) - 32768 ); //Y
}
else
{
float *pPos;
poselem->baseVertexPointerToElement( pMainLocal, &pPos );
*pPos++ = static_cast <float> ( i * scale_x ); //X
*pPos++ = static_cast <float> ( height ); //Y
*pPos = static_cast <float> ( k_pos ); //Z
}
// normals
if ( b_lit )
{
float *pNorm;
normelem->baseVertexPointerToElement( pMainLocal, &pNorm );
const Vector3 norm = data->getNormal ( i, k );
*pNorm++ = static_cast <float> ( norm.x );
*pNorm++ = static_cast <float> ( norm.y );
*pNorm = static_cast <float> ( norm.z );
}
if ( b_colored )
{
ColourValue RGBA_precalc;
if ( b_coverage )
{
RGBA_precalc = data->getCoverage ( i, k );
Real a1;
const Real a2 = 1.0f - RGBA_precalc.a;
if ( a2 != 0.0f )
{
a1 = RGBA_precalc.r / a2 ;
}
else
a1 = 0.0f;
RGBA_precalc.r = a1;
RGBA_precalc.g = a1;
RGBA_precalc.b = a1;
RGBA_precalc.a = a2;
}
RGBA *pColor;
colorelem->baseVertexPointerToElement( pMainLocal, &pColor );
Root::getSingleton( ).convertColourValue ( RGBA_precalc,
pColor );
}
pMainLocal += VertexSize;
}
pMain += VertexTileSize;;
K_heightFieldPos += pageSize;
}
// Unlock the buffers
vVertices->unlock( );
// Calculate the bounding box for this renderable
if ( !mIsRectModified )
{
mBounds.setExtents( offSetX * scale_x,
min,
offSetZ * scale_z,
endx * scale_x,
max,
endz * scale_z );
} // if ( !mIsRectModified )
else
{
const Vector3 maxbound = mBounds.getMaximum( );
const Vector3 minbound = mBounds.getMinimum( );
mBounds.setExtents( minbound.x, min, minbound.z,
maxbound.x, max, maxbound.z );
}
mBoundingRadius = Math::Sqrt(
Math::Sqr( max - min ) +
Math::Sqr( ( endx - 1 - offSetX ) * scale_x ) +
Math::Sqr( ( endz - 1 - offSetZ ) * scale_z ) ) / 2;
if ( mParent->getOptions ( )->VisMap )
mParent->getSceneManager( )->getHorizon( )->registerMinMaxHeightTile ( mInfo, min, max );
mMinLevelDistSqr = 0;
_calculateMinLevelDist2( mParent->getOptions ( )->CFactor );
if ( !mIsLoaded )
{
mParent->getSceneManager( )->getListenerManager( )->fireTileLoaded ( mInfo->mPageX, mInfo->mPageZ,
mInfo->mTileX, mInfo->mTileZ, mParentTile->getWorldBbox ( ) );
mIsLoaded = true;
}
else if ( mNeedReload )
{
mParent->getSceneManager( )->getListenerManager( )->fireTileDeformed ( mInfo->mPageX, mInfo->mPageZ,
mInfo->mTileX, mInfo->mTileZ, mParentTile->getWorldBbox ( ) );
mNeedReload = false;
}
mRect.left = 0;
mRect.right = 0;
mRect.top = 0;
mRect.bottom = 0;
mIsRectModified = false;
mVisible = false;
mChangedRenderLevel = false;
mIndex = 0;
return true;
}
//-----------------------------------------------------------------------
486 void PagingLandScapeRenderable::unload( )
{
assert ( mIsLoaded && mInfo );
assert ( !mQueued );
if ( mNeighbors[SOUTH] )
mNeighbors[SOUTH]->_setNeighbor ( NORTH, 0 );
if ( mNeighbors[NORTH] )
mNeighbors[NORTH]->_setNeighbor ( SOUTH, 0 );
if ( mNeighbors[EAST] )
mNeighbors[EAST]->_setNeighbor ( WEST, 0 );
if ( mNeighbors[WEST] )
mNeighbors[WEST]->_setNeighbor ( EAST, 0 );
for ( unsigned int i = 0; i < 4; i++ )
{
mNeighbors[i] = 0;
}
assert ( mParentNode );
{
SceneNode * const s = static_cast <SceneNode*>( mParentNode );
s->detachObject ( mName );
s->needUpdate ( );
}
mInUse = false;
mIsLoaded = false;
mInfo = 0;
mLastNextLevel = -1;
mRenderLevel = -1;
mVisible = false;
mNeedReload = false;
mRect.left = 0;
mRect.right = 0;
mRect.top = 0;
mRect.bottom = 0;
mIsRectModified = false;
mMinLevelDistSqr = 0;
}
//-----------------------------------------------------------------------
523 void PagingLandScapeRenderable::_notifyCurrentCamera( Camera* cam )
{
if ( mInUse && mIsLoaded && mVisible )
{
// if some deformation
if ( mNeedReload )
{
// if between deformation and now, tile have been unloaded
if ( !load ( ) )
{
mVisible = false;
return;
}
}
// Horizon occlusion. ( needs data to be loaded or reloaded )
if ( mParent->getOptions ( )->VisMap )
{
PagingLandScapeCamera* plscam = static_cast<PagingLandScapeCamera*> ( cam );
if( !mParent->getSceneManager( )->getHorizon( )->IsTileVisible( plscam, mInfo ) )
{
mVisible = false;
return;
}
}
const int oldRenderLevel = mRenderLevel;
if ( mForcedMaxLod )
{
mRenderLevel = 0;
mMaterialLODIndex = 0;
}
else
{
// get distance between renderable and tile and adjust it by the camera bias
mDistanceToCam = ( getWorldPosition( ) - cam -> getDerivedPosition( ) ).squaredLength( ) * cam->getLodBias ( );
// Material LOD
if ( !mMaterial.isNull( )
&& mMaterial->getNumLodLevels( MaterialManager::getSingleton( )._getActiveSchemeIndex( ) ) > 1
)
{
const unsigned short LODIndex = mMaterial->getLodIndexSquaredDepth ( mDistanceToCam );
if ( LODIndex != mMaterialLODIndex )
mMaterialLODIndex = LODIndex;
}
mRenderLevel = -1;
const int maxMipmap = static_cast <int> ( mParent->getOptions ( )->maxRenderLevel );
assert ( mMinLevelDistSqr );
for ( int i = 0; i < maxMipmap; i++ )
{
if ( ( *mMinLevelDistSqr )[ i ] > mDistanceToCam )
{
mRenderLevel = i - 1;
break;
}
}
if ( mRenderLevel < 0 )
mRenderLevel = maxMipmap - 1;
// Get the next LOD level down
if ( mParent->getOptions ( )->lodMorph )
{
// Get the next LOD level down
const int nextLevel = mNextLevelDown[mRenderLevel];
if ( nextLevel == 0 )
{
// No next level, so never morph
mLODMorphFactor = 0.0f;
mCustomGpuParameters.w = mLODMorphFactor;
}
else
{
// Set the morph such that the morph happens in the last 0.25 of
// the distance range
const Real range = ( *mMinLevelDistSqr )[nextLevel] - ( *mMinLevelDistSqr )[mRenderLevel];
if ( range )
{
const Real percent = ( mDistanceToCam - ( *mMinLevelDistSqr )[mRenderLevel] ) / range;
// scale result so that msLODMorphStart == 0, 1 == 1, clamp to 0 below that
const Real rescale = 1.0f / ( 1.0f - mParent->getOptions ( )->lodMorphStart );
mLODMorphFactor = std::max( ( percent - mParent->getOptions ( )->lodMorphStart ) * rescale,
static_cast<Real>( 0.0f ) );
mCustomGpuParameters.w = mLODMorphFactor;
assert ( mLODMorphFactor <= 1.0f );
}
else
{
// Identical ranges
mLODMorphFactor = 0.0f;
mCustomGpuParameters.w = mLODMorphFactor;
}
}
// Bind the correct delta buffer if it has changed
// nextLevel - 1 since the first entry is for LOD 1 ( since LOD 0 never needs it )
if ( mLastNextLevel != nextLevel )
{
assert ( mDeltaBuffers );
if ( nextLevel > 1 )
{
mCurrVertexes->vertexBufferBinding->setBinding( DELTA_BINDING,
mDeltaBuffers[nextLevel - 1] );
}
else
{
// bind dummy ( in case bindings checked )
mCurrVertexes->vertexBufferBinding->setBinding( DELTA_BINDING,
mDeltaBuffers[0] );
}
}
mLastNextLevel = nextLevel;
}
}
//// If we change LOD update self and neighbor
if ( oldRenderLevel != mRenderLevel || mCurrIndexes == 0 )
{
update ( );
for ( unsigned int i = 0; i < 4; i++ )
{
PagingLandScapeRenderable * const r = mNeighbors[i];
if ( r && r->isLoaded ( ) && r->isVisible ( ) )
r->update ( );
}
}
mVisible = true;
}
else
{
mVisible = false;
}
}
//-----------------------------------------------------------------------
655 void PagingLandScapeRenderable::update( )
{
mChangedRenderLevel = true;
}
//-----------------------------------------------------------------------
660 void PagingLandScapeRenderable::_updateRenderQueue( RenderQueue* queue )
{
// Notify need to calculate light list when our sending to render queue
mLightListDirty = true;
assert ( mInUse && mParentNode && mIsLoaded && mVisible );
if ( mChangedRenderLevel )
{
for ( unsigned int i = 0; i < 4; i++ )
{
PagingLandScapeRenderable * const r = mNeighbors[i];
if ( r && r->isLoaded ( ) && r->isVisible ( ) )
r->update ( );
}
}
queue->addRenderable( this );
}
//-----------------------------------------------------------------------
678 Technique* PagingLandScapeRenderable::getTechnique( void ) const
{
return mMaterial->getBestTechnique ( mMaterialLODIndex );
}
//-----------------------------------------------------------------------
683 const LightList& PagingLandScapeRenderable::getLights( void ) const
{
if ( mLightListDirty )
{
getParentSceneNode( )->getCreator( )->_populateLightList(
mCenter,
this->getBoundingRadius( ),
mLightList );
mLightListDirty = false;
}
return mLightList;
}
//-----------------------------------------------------------------------
696 Real PagingLandScapeRenderable::getSquaredViewDepth( const Camera* cam ) const
{
// Use squared length to avoid square root
return ( PagingLandScapeRenderable::getWorldPosition( ) -
cam->getDerivedPosition ( ) ).squaredLength( );
}
//-----------------------------------------------------------------------
704 void PagingLandScapeRenderable::getRenderOperation( RenderOperation& op )
{
assert ( mIsLoaded );
assert ( mInUse );
assert ( mVisible );
assert ( mParentNode );
//setup indexes for vertices and uvs...
op.useIndexes = true;
op.operationType = RenderOperation::OT_TRIANGLE_LIST;
op.vertexData = mCurrVertexes;
if ( mChangedRenderLevel )
{
mIndex = mParent->getSceneManager( )->getIndexBufferManager( )->getIndexData( mRenderLevel,
mNeighbors );
mChangedRenderLevel = false;
}
assert ( mIndex );
op.indexData = mIndex;
mParent->addVisible ( );
}
//-----------------------------------------------------------------------
727 void PagingLandScapeRenderable::getWorldTransforms( Matrix4* xform ) const
{
*xform = mParentNode->_getFullTransform( );
}
//-----------------------------------------------------------------------
732 const Quaternion& PagingLandScapeRenderable::getWorldOrientation( void ) const
{
return mParentNode->_getDerivedOrientation( );
}
//-----------------------------------------------------------------------
737 const Vector3& PagingLandScapeRenderable::getWorldPosition( void ) const
{
return mCenter;
}
//-----------------------------------------------------------------------
742 void PagingLandScapeRenderable::setMaterial( const MaterialPtr &mat )
{
mMaterial = mat;
}
//-----------------------------------------------------------------------
747 void PagingLandScapeRenderable::_calculateMinLevelDist2( const Real C )
{
//level 0 has no delta.
PagingLandScapeOptions * const opt = mParent->getOptions( );
const bool lodMorph = opt->lodMorph;
const bool roughnessLod = opt->roughnessLod;
bool doComputeMinLevelDistSqr = mIsRectModified;
if ( mMinLevelDistSqr == 0 )
{
if ( mInfo->mMinLevelDistSqr == 0 )
{
mMinLevelDistSqr = new std::vector<Real>( );
const size_t numLod = mParent->getOptions ( )->maxRenderLevel;
mMinLevelDistSqr->reserve( numLod );
mMinLevelDistSqr->resize( numLod );
doComputeMinLevelDistSqr = true;
mInfo->mMinLevelDistSqr = mMinLevelDistSqr;
}
else
{
// already computed and in cache.
mMinLevelDistSqr = mInfo->mMinLevelDistSqr;
fillNextLevelDown( );
if ( !doComputeMinLevelDistSqr )
{
// no deformation modified
// no need to recompute it.
if ( !lodMorph )
{
// already computed and in cache.
// and no lodMorphing...
// so no need to recompute
return;
}
}
}
}
if ( doComputeMinLevelDistSqr )
( *mMinLevelDistSqr )[ 0 ] = 0.0f;
const double inv_scale = 65535.0 / opt->scale.y;
//const double scale = mParent->getOptions ( )->scale.y / 65535;
const int maxMip = static_cast <int> ( opt->maxRenderLevel );
const int tilesize = static_cast <int> ( opt->TileSize );
const unsigned int tileSize = opt->TileSize;
// should change if we're just refilling a part
if ( mIsRectModified )
{
// until we find a way to adjust the modification rect
// on step size
// should also refill the vertex map with deformed point
// ( BaseHeight )
mRect.left = 0;
mRect.right = tileSize;
mRect.top = 0;
mRect.bottom = tileSize;
} // if ( mIsRectModified )
const int offSetX = static_cast <int> ( mInfo->mTileX * ( tileSize - 1 ) + mRect.left );
const int endx = static_cast <int> ( offSetX + static_cast <int> ( mRect.right - mRect.left ) );
const int offSetZ = static_cast <int> ( mInfo->mTileZ * ( tileSize - 1 ) + mRect.top );
const int IntervallModifiedZ = static_cast <int> ( mRect.bottom - mRect.top );
const int endz = offSetZ + IntervallModifiedZ;
const int pageSize = static_cast <int> ( opt->PageSize );
const size_t blendWeights = 2;
//const size_t blendWeights = 1;
assert ( IntervallModifiedZ * tilesize > 0 );
// until we found a way to upload part of the data.
assert ( IntervallModifiedZ == tilesize );
const size_t size = blendWeights * IntervallModifiedZ * tilesize;
const size_t buffsize = size * sizeof( ushort ); // sizeof( Real );
int K_heightFieldPos;
ushort *BaseHeight = 0;
//Real *BaseHeight = 0;
int i, j;
const Real * const ogre_restrict heightField = mHeightfield + offSetZ * pageSize;
if ( lodMorph )// && mIsRectModified ) )
{
BaseHeight = new ushort [size];
//BaseHeight = new Real [size];
K_heightFieldPos = 0;
int k = 0;
for ( j = offSetZ; j < endz; j ++ )
{
// should change if we're just refilling a part to whole tile ( only if using discard, tough )
for ( i = offSetX; i < endx; i ++ )
{
// Save height
assert ( k < static_cast<int> ( size ) );
BaseHeight[k] = static_cast<short>
( ( heightField[ i + K_heightFieldPos]
* inv_scale ) - 32768 );
//BaseHeight[k] = static_cast<Real>
//( mheightField[ i + K_heightFieldPos] );
// should change if we're just refilling a part to whole tile, using a
//k += tilesize - IntervalleZ;
k += blendWeights;
}
// should change if we're just refilling a part to whole tile, using a
//k += tilesize - IntervalleX;
K_heightFieldPos += pageSize;
}
}
//const ushort * const heightField = BaseHeight;
//const Real * const heightField = BaseHeight;
Plane t1, t2;
const Real Csqr = C * C;
for ( int level = 1; level < maxMip; level++ )
{
ushort *pDeltaInit = 0;
//Real *pDeltaInit = 0;
if ( BaseHeight )
{
const size_t lvl_minus_one = level - 1;
// Create a set of delta values ( store at index - 1 since 0 has none )
// should change to an interval locking ( as in load ) ? if we're just refilling a part to whole tile
pDeltaInit = static_cast<ushort*> (
mDeltaBuffers[lvl_minus_one]->lock( HardwareBuffer::HBL_DISCARD ) );
memcpy ( pDeltaInit, BaseHeight, buffsize );
assert ( pDeltaInit );
} // if ( BaseHeight )
ushort * const pDeltas = pDeltaInit;
// should keep previous change in case of partial tile refilling ?
// But how could we lower value ? ( if terrain goes smoother )
if ( doComputeMinLevelDistSqr )
( *mMinLevelDistSqr )[ level ] = 0.0f;
const int step = 1 << level;
// find a way to take a good step end and start
// even with offset that would make us in "middle of a step"
const int tilesizeMinusstepZ = endz - step;
const int tilesizeMinusstepX = endx - step;
const Real invStep = 1.0f / step;
K_heightFieldPos = 0;
const int ZShift = step * pageSize;
for ( j = offSetZ; j < tilesizeMinusstepZ; j += step )
{
for ( i = offSetX; i < tilesizeMinusstepX; i += step )
{
//added for Ember
bool isInValidVertex;
{
const Vector3 v1( i, heightField[ i + K_heightFieldPos ], j );
const Vector3 v2( i + step, heightField[ i + step + K_heightFieldPos ], j );
const Vector3 v3( i, heightField[ i + K_heightFieldPos + ZShift], j + step );
const Vector3 v4( i + step, heightField[ i + step + K_heightFieldPos + ZShift], j + step );
t1.redefine( v1, v3, v2 );
t2.redefine( v2, v3, v4 );
//only update the distance if none of the heights are -1.0
//this is to allow for invalid Mercator::Segments without messing up the tricount
//the reason is that Ember will set the height for all invalid segments to -1
//if such a segment was to be next to a normal segment, the delta would be way to high,
//resulting in a tile which was always in LOD 0
isInValidVertex = v1.y == -1.0 || v2.y == -1.0 || v3.y == -1.0 || v4.y == -1.0;
}
if ( !isInValidVertex ) {
// include the bottommost row of vertices if this is the last row
const int zubound = ( j == ( tilesizeMinusstepZ )? step : step - 1 );
for ( int z = 0; z <= zubound; z++ )
{
const int fulldetailz = j + z;
const Real zpct = z * invStep;
const bool isFullDetailZ = ( fulldetailz % step == 0 );
const int zPageSize = z * pageSize;
{
// include the rightmost col of vertices if this is the last col
const int xubound = ( i == ( tilesizeMinusstepX )? step : step - 1 );
for ( int x = 0; x <= xubound; x++ )
{
const int fulldetailx = i + x;
if ( isFullDetailZ &&
fulldetailx % step == 0 )
{
// Skip, this one is a vertex at this level
continue;
}
const Real xpct = x * invStep;
//interpolated height
Real interp_h;
// Determine which triangle we're on
if ( xpct + zpct <= 1.0f )
{
// Solve for x/z
interp_h =
( -( t1.normal.x * fulldetailx )
- t1.normal.z * fulldetailz
- t1.d ) / t1.normal.y;
}
else
{
// Second triangle
interp_h =
( -( t2.normal.x * fulldetailx )
- t2.normal.z * fulldetailz
- t2.d ) / t2.normal.y;
}
assert ( ( fulldetailx + K_heightFieldPos + zPageSize ) < ( pageSize*pageSize ) );
const Real actual_h = heightField[ fulldetailx + K_heightFieldPos + zPageSize];
const Real delta = interp_h - actual_h;
if ( doComputeMinLevelDistSqr )
{
// need to recompute it.
const Real D2 = ( roughnessLod )? delta * delta * Csqr: Csqr;
if ( ( *mMinLevelDistSqr )[ level ] < D2 )
( *mMinLevelDistSqr )[ level ] = D2;
}
// Should be save height difference?
// Don't morph along edges
if ( lodMorph )
{
// Save height difference
if ( delta != 0.0f )
{
const int tileposx = fulldetailx - offSetX;
const int tileposy = fulldetailz - offSetZ;
if ( tileposx != 0 && tileposx != ( tilesize - 1 ) &&
tileposy != 0 && tileposy != ( tilesize - 1 ) )
{
assert ( ( tileposx + ( tileposy * tilesize ) )*blendWeights < size );
pDeltas[( tileposx + ( tileposy * tilesize ) )*blendWeights] =
static_cast<short>
( ( interp_h * inv_scale ) - 32768 );
// pDeltas[( tileposx + ( tileposy * tilesize ) )*blendWeights] =
// interp_h;
}
}
}
}
}
}
}
}
K_heightFieldPos += pageSize * step;
}
// Unlock morph deltas if required
if ( lodMorph )
mDeltaBuffers[level - 1]->unlock( );
}
// delete Height Data cache and Buffer initial value.
delete[] BaseHeight;
if ( doComputeMinLevelDistSqr )
{
if ( roughnessLod )
{
// Post validate the whole set
for ( i = 1; i < maxMip; i++ )
{
// Make sure no LOD transition within the tile
// This is especially a problem when using large tiles with flat areas
/* Hmm, this can look bad on some areas, disable for now
Vector3 delta( _vertex( 0, 0, 0 ), mCenter.y, _vertex( 0, 0, 2 ) );
delta = delta - mCenter;
Real minDist = delta.squaredLength( );
mMinLevelDistSqr[ i ] = std::max( mMinLevelDistSqr[ i ], minDist );
*/
//make sure the levels are increasing...
if ( ( *mMinLevelDistSqr )[ i ] < ( *mMinLevelDistSqr )[ i - 1 ] )
( *mMinLevelDistSqr )[ i ] = ( *mMinLevelDistSqr )[ i - 1 ];
}
}
else
{
const int maxMip = static_cast <int> ( mParent->getOptions ( )->maxRenderLevel ) - 1;
Real distanceLod = mParent->getOptions ( )->LOD_factor;
for ( int level = 1; level < maxMip; level++ )
{
( *mMinLevelDistSqr )[level] = distanceLod;
distanceLod *= 2;
}
}
fillNextLevelDown( );
}
}
//-----------------------------------------------------------------------
1069 void PagingLandScapeRenderable::fillNextLevelDown( void )
{
// reverse traverse the mMinLevelDistSqr list in order to set
// the 'next level down'
Real lastDist = -1;
int lastIndex = 0;
const int maxMip = static_cast <int> ( mParent->getOptions ( )->maxRenderLevel ) - 1;
for ( int i = maxMip; i >= 0; --i )
{
assert ( i >= 0 );
if ( i == maxMip )
{
// Last one is always 0
lastIndex = i;
lastDist = ( *mMinLevelDistSqr )[i];
mNextLevelDown[i] = 0;
}
else
{
mNextLevelDown[i] = lastIndex;
if ( ( *mMinLevelDistSqr )[i] != lastDist )
{
lastIndex = i;
lastDist = ( *mMinLevelDistSqr )[i];
}
}
}
}
//-----------------------------------------------------------------------
1099 HardwareVertexBufferSharedPtr PagingLandScapeRenderable::createDeltaBuffer( void ) const
{
// Delta buffer is a 1D Real buffer of height offsets
HardwareVertexBufferSharedPtr buf =
HardwareBufferManager::getSingleton( ).createVertexBuffer(
VertexElement::getTypeSize( VET_SHORT2 ),
//VertexElement::getTypeSize( VET_SHORT1 ),
//VertexElement::getTypeSize( VET_FLOAT1 ),
mParent->getOptions ( )->TileSize * mParent->getOptions ( )->TileSize,
HardwareBuffer::HBU_STATIC_WRITE_ONLY );
// HardwareBuffer::HBU_STATIC );
return buf;
}
//-----------------------------------------------------------------------
1115 Real PagingLandScapeRenderable::_vertex( const int x, const int z, const int n ) const
{
const unsigned int tilesize = mParent->getOptions ( )->TileSize - 1;
switch ( n )
{
case 0:
return ( ( mInfo->mTileX * tilesize ) + x )* mParent->getOptions ( )->scale.x;
case 1:
return mHeightfield[( ( mInfo->mTileX * tilesize ) + x ) +
( ( mInfo->mTileZ * tilesize ) + z ) * mParent->getOptions ( )->PageSize ];
case 2:
return ( ( mInfo->mTileZ * tilesize ) + z )* mParent->getOptions ( )->scale.z;
default:
return 0.0f;
}
}
//-----------------------------------------------------------------------
1132 void PagingLandScapeRenderable::_updateCustomGpuParameter(
1133 const GpuProgramParameters::AutoConstantEntry& constantEntry,
1134 GpuProgramParameters* params ) const
{
if ( constantEntry.data == MORPH_CUSTOM_PARAM_ID )
{
// Update morph LOD factor
//params->setConstant( constantEntry.index, mLODMorphFactor );
params->setNamedConstant( "compressionSettings", mCustomGpuParameters );
}
else
{
Renderable::_updateCustomGpuParameter( constantEntry, params );
}
}
//-----------------------------------------------------------------------
1149 void PagingLandScapeRenderable::adjustDeformationRectangle( unsigned int x, unsigned int z )
{
assert ( x < mParent->getOptions ( )->TileSize && z < mParent->getOptions ( )->TileSize );
if ( mIsRectModified )
{
if ( mRect.left > x )
mRect.left = x;
if ( mRect.right < x )
mRect.right = x;
if ( mRect.top > z )
mRect.top = z;
if ( mRect.bottom < z )
mRect.bottom = z;
}
else
{
// first modification :
// deformation rectangle is the point
mRect.left = x;
mRect.right = x;
mRect.top = z;
mRect.bottom = z;
mIsRectModified = true;
mNeedReload = true;
}
}
//-----------------------------------------------------------------------
1179 uint32 PagingLandScapeRenderable::getTypeFlags( void ) const
{
// return world flag
return SceneManager::WORLD_GEOMETRY_TYPE_MASK;
}
//-----------------------------------------------------------------------
1185 void PagingLandScapeRenderable::_notifyAttached( Node* parent, bool isTagPoint )
{
MovableObject::_notifyAttached( parent, isTagPoint );
if ( parent )
{
assert ( mIsLoaded );
mCenter = mBounds.getCenter( ) + mParentNode->getWorldPosition( );
mWorldBoundingSphere.setCenter( mCenter );
mWorldBoundingSphere.setRadius( ( mBounds.getMaximum( ) - mBounds.getMinimum( ) ).length( ) / 2 );
mParentNode->needUpdate( );
}
}
//-----------------------------------------------------------------------
1198 Vector3 PagingLandScapeRenderable::_getvertex( const int x, const int z ) const
{
const unsigned int tilesize = mParent->getOptions ( )->TileSize - 1;
const unsigned int pSize = mParent->getOptions ( )->PageSize -1;
Vector3 vertex;
vertex.x = ( mInfo->mTileX * tilesize ) + x;
vertex.z = ( mInfo->mTileZ * tilesize ) + z;
vertex.y = mHeightfield[static_cast<unsigned int>( vertex.x + ( vertex.z *mParent->getOptions ( )->PageSize ) )];
vertex.x += mInfo->mPageX * pSize - mParent->getOptions ( )->maxUnScaledX;
vertex.z += mInfo->mPageZ * pSize - mParent->getOptions ( )->maxUnScaledZ;
vertex.x *= mParent->getOptions ( )->scale.x;
vertex.z *= mParent->getOptions ( )->scale.z;
return vertex;
}
/**
* This returns the actual Polygon assignments for this renderable at the given renderLevel
* @param renderlevel LODLevel to get the Index data at
* @return the queried IndexData
*/
1223 IndexData* PagingLandScapeRenderable::getRawIndexData( const int renderlevel )
{
return mParent->getSceneManager( )->getIndexBufferManager( )->getRawIndexes( renderlevel );
}
/**
* Returns the Vertices for this renderable in world space
* @param pVerts >Pre-allocated< buffer to hold the vertices. The number of Vertices can be
* retrieved by a call to getVertexCount
* @note no checking is done on the array whatsoever
*/
1234 void PagingLandScapeRenderable::getRawVertexData( Vector3* pVerts )
{
// pVerts should be pre-allocated to tilesize*tilesize
// using getVertexCount( )
const unsigned int tilesize = mParent->getOptions ( )->TileSize -1 ;
Vector3 *vert = pVerts;
Vector3 snPosition = mParent->getOptions ( )->position;
Vector3 tmpVertex;
for ( unsigned int i=0; i<=tilesize; ++i )
{
for ( unsigned int j=0; j<=tilesize; ++j )
{
tmpVertex = _getvertex( j, i );
tmpVertex += snPosition; // translate current vertex relatively parent SN position
*vert++= tmpVertex;
}
}
}
/**
* Returns the number of this Renderable's vertices
* @return the number of this Renderable's vertices
*/
1259 const unsigned int PagingLandScapeRenderable::getVertexCount( )
{
return mParent->getOptions ( )->TileSize * mParent->getOptions ( )->TileSize ;
}
} //namespace
1 /***************************************************************************
OgrePagingLandScapeRenderableManager.cpp - description
-------------------
begin : Mon Jun 16 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreMovableObject.h"
#include "OgreCamera.h"
#include "OgreSceneNode.h"
#include "OgreSimpleRenderable.h"
#include "OgrePagingLandScapeSceneManager.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeCamera.h"
#include "OgrePagingLandScapeRenderable.h"
#include "OgrePagingLandScapeIndexBuffer.h"
#include "OgrePagingLandScapeRenderableManager.h"
#include "OgrePagingLandScapeTile.h"
namespace Ogre
{
//-----------------------------------------------------------------------
46 PagingLandScapeRenderableSet::PagingLandScapeRenderableSet( ):
PoolSet<PagingLandScapeRenderable>( ),
mRenderableManager( 0 )
{
}
//-----------------------------------------------------------------------
52 PagingLandScapeRenderable* PagingLandScapeRenderableSet::allocate ( )
{
return new PagingLandScapeRenderable( mRenderableManager );
}
//-----------------------------------------------------------------------
57 void PagingLandScapeRenderableSet::deallocate ( PagingLandScapeRenderable *r )
{
delete r;
}
//-----------------------------------------------------------------------
62 PagingLandScapeRenderableManager::PagingLandScapeRenderableManager( PagingLandScapeSceneManager * scnMgr ):
mSceneManager( scnMgr ),
mOptions( scnMgr->getOptions ( ) ),
mRenderableLoadInterval ( 0 ),
mLoadInterval( 0 ),
mNumRenderableLoading( 0 )
{
// auto extend ourself as we rather check
//if we can found non Freed Renderables before
mRenderablePool.setAutoextend ( false );
// don't Double renderables num each time... too much.
mRenderablePool.setExtendFactor ( 1.2f );
}
//-----------------------------------------------------------------------
76 PagingLandScapeRenderableManager::~PagingLandScapeRenderableManager( )
{
mRenderablePool.deletePool ( );
}
//-----------------------------------------------------------------------
81 void PagingLandScapeRenderableManager::clear( )
{
if ( !mTilesLoadRenderableQueue.empty ( ) )
{
PagingLandScapeTile *t = mTilesLoadRenderableQueue.pop( );
while ( t )
{
t->uninit ( );
t = mTilesLoadRenderableQueue.pop ( );
}
assert ( mTilesLoadRenderableQueue.empty ( ) );
}
// As Renderables change too much over maps ( +- lit, normals, etc... )
mRenderablePool.deletePool ( );
}
//-----------------------------------------------------------------------
97 void PagingLandScapeRenderableManager::load( )
{
mRenderablePool.setRenderableManager ( this );
PagingLandScapeOptions *opt = mOptions;
mNumRenderableLoading = opt->num_renderables_loading;
mNumRenderablesIncrement = opt->num_renderables_increment;
mRenderableLoadInterval = opt->RenderableLoadInterval;
mRenderablePool.setPoolSize ( opt->num_renderables );
mTilesLoadRenderableQueue.clear( );
}
//-----------------------------------------------------------------------
110 PagingLandScapeRenderable *PagingLandScapeRenderableManager::getRenderable( )
{
PagingLandScapeRenderable *r = mRenderablePool.getPoolable ( );
if ( r == 0 )
{
// unload some Tiles/renderables no more used to free some space.
processTileUnload ( );
r = mRenderablePool.getPoolable ( );
if ( r == 0 )
{
mRenderablePool.autoExtend( );
r = mRenderablePool.getPoolable( );
}
}
return r;
}
//-----------------------------------------------------------------------
128 void PagingLandScapeRenderableManager::freeRenderable( PagingLandScapeRenderable *rend )
{
assert ( rend->mParentTile == 0 );
mRenderablePool.removePoolable( rend );
}
//-----------------------------------------------------------------------
134 void PagingLandScapeRenderableManager::queueRenderableLoading( PagingLandScapeTile *tile )
{
assert ( tile );
assert ( !tile->isLoading( ) );
assert ( tile->getRenderable ( ) );
assert ( !tile->getRenderable ( )->mQueued );
assert ( tile->isLoaded ( ) );
assert ( !tile->getRenderable ( )->isLoaded ( ) );
assert ( tile->getRenderable ( )->isInUse ( ) );
//
tile->setLoading( true );
tile->getRenderable ( )->mQueued = true;
//
mTilesLoadRenderableQueue.push ( tile );
}
//-----------------------------------------------------------------------
155 void PagingLandScapeRenderableManager::unqueueRenderable ( PagingLandScapeTile *tile )
{
assert ( tile->isLoading( ) );
assert ( tile->getRenderable ( ) );
assert ( tile->getRenderable ( )->mQueued );
assert ( tile->isLoaded ( ) );
assert ( !tile->getRenderable ( )->isLoaded ( ) );
//assert ( !tile->getRenderable ( )->isInUse ( ) );
//
tile->setLoading ( false );
tile->getRenderable ( )->mQueued = false;
//
mTilesLoadRenderableQueue.remove ( tile );
}
//-----------------------------------------------------------------------
173 void PagingLandScapeRenderableManager::processTileUnload( )
{
if ( mTilesLoadRenderableQueue.empty( ) )
return;
PagingLandScapeTile *tile;
for ( PagingLandScapeQueue<PagingLandScapeTile>::MsgQueType::iterator itq = mTilesLoadRenderableQueue.begin( );
itq != mTilesLoadRenderableQueue.end( ); )
{
tile = *itq;
assert ( tile != 0 );
assert ( tile->isLoading( ) );
assert ( tile->getRenderable ( ) );
assert ( tile->getRenderable ( )->mQueued );
assert ( tile->isLoaded ( ) );
assert ( tile->getSceneNode( ) );
assert ( !tile->getRenderable ( )->isLoaded ( ) );
if ( !tile->getRenderable ( )->isInUse ( ) )
{
tile->setLoading ( false );
tile->getRenderable ( )->mQueued = false;
tile->unload ( );
itq = mTilesLoadRenderableQueue.erase ( itq );
}
else
{
++itq;
}
}
}
//-----------------------------------------------------------------------
207 bool PagingLandScapeRenderableManager::executeRenderableLoading( const Vector3 &Cameraposition )
{
if ( mTilesLoadRenderableQueue.empty( ) )
{
return true;
}
else
{
if ( mLoadInterval-- < 0 )
{
const size_t queueSize = mTilesLoadRenderableQueue.getSize ( ) ;
mTilesLoadRenderableQueue.sortNearest( Cameraposition );
const size_t k = mNumRenderableLoading > queueSize ? queueSize : mNumRenderableLoading;
for ( size_t i = 0; i < k; i++ )
{
PagingLandScapeTile * const tile = mTilesLoadRenderableQueue.pop ( );
// no more in queues.
assert ( tile != 0 );
assert ( tile->isLoaded ( ) );
assert ( tile->isLoading( ) );
PagingLandScapeRenderable * const rend = tile->getRenderable ( );
assert ( rend != 0 );
assert ( rend->mParentTile == tile );
assert ( rend->mQueued );
assert ( !rend->isLoaded ( ) );
SceneNode * const tileSceneNode = tile->getSceneNode ( );
assert ( tileSceneNode != 0 );
// if renderable can be loaded
if ( rend->load ( ) )
{
tileSceneNode->attachObject ( rend );
tile->_linkRenderableNeighbor ( );
}
else
{
// ( no data yet. ) empty tile.
tile->unload ( );
}
tile->setLoading( false );
rend->mQueued = false;
tileSceneNode->needUpdate ( );
}
mLoadInterval = mRenderableLoadInterval;
}
}
return false;
}
//-----------------------------------------------------------------------
262 size_t PagingLandScapeRenderableManager::numRenderables( void ) const
{
return static_cast< size_t > ( mRenderablePool.getPoolSize( ) );
}
//-----------------------------------------------------------------------
268 size_t PagingLandScapeRenderableManager::numFree( void ) const
{
return mRenderablePool.getPoolSize( ) - mRenderablePool.getActivePoolablesSize ( );
}
//-----------------------------------------------------------------------
274 size_t PagingLandScapeRenderableManager::numLoading( void ) const
{
return mTilesLoadRenderableQueue.getSize( );
}
//-----------------------------------------------------------------------
279 void PagingLandScapeRenderableManager::_addBatch( const unsigned int num )
{
mRenderablePool.setPoolSize ( mRenderablePool.getPoolSize( ) + num );
#ifdef _DEBUG
std::cout << "Renderables addBatch : " << mRenderablePool.getPoolSize( ) << "\n";
#endif
}
} //namespace
/***************************************************************************
OgrePagingLandScapeSceneManager.cpp - description
-------------------
begin : Mon May 12 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreRoot.h"
#include "OgreSceneManager.h"
#include "OgreVector2.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreMovableObject.h"
#include "OgreAxisAlignedBox.h"
#include "OgreCamera.h"
#include "OgreStringConverter.h"
#include "OgreSceneNode.h"
#include "OgreSimpleRenderable.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeCamera.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeRenderableManager.h"
#include "OgrePagingLandScapeTextureCoordinatesManager.h"
#include "OgrePagingLandScapeRenderable.h"
#include "OgrePagingLandScapeTextureManager.h"
#include "OgrePagingLandScapeTexture.h"
#include "OgrePagingLandScapePageManager.h"
#include "OgrePagingLandScapeTile.h"
#include "OgrePagingLandScapeTileInfo.h"
#include "OgrePagingLandScapeTileManager.h"
#include "OgrePagingLandScapeRenderable.h"
#include "OgrePagingLandScapeRenderableManager.h"
#include "OgrePagingLandScapeAxisAlignedBoxSceneQuery.h"
#include "OgrePagingLandScapeRaySceneQuery.h"
#include "OgrePagingLandScapeCamera.h"
#include "OgrePagingLandScapeMeshDecal.h"
#include "OgrePagingLandScapeListenerManager.h"
#include "OgrePagingLandScapeSceneManager.h"
#include "OgrePagingLandScapeHorizon.h"
namespace Ogre
{
//-----------------------------------------------------------------------
const String PagingLandScapeSceneManagerFactory::FACTORY_TYPE_NAME = "PagingLandScapeSceneManager";
//-----------------------------------------------------------------------
65 void PagingLandScapeSceneManagerFactory::initMetaData( void ) const
{
mMetaData.typeName = FACTORY_TYPE_NAME;
mMetaData.description = "Scene manager organising the scene on the basis of an octree, and paging heightmap when needed.";
mMetaData.sceneTypeMask = ST_EXTERIOR_REAL_FAR; // support all types
mMetaData.worldGeometrySupported = true;
}
//-----------------------------------------------------------------------
73 SceneManager* PagingLandScapeSceneManagerFactory::createInstance(
74 const String& instanceName )
{
return new PagingLandScapeSceneManager( instanceName );
}
//-----------------------------------------------------------------------
79 void PagingLandScapeSceneManagerFactory::destroyInstance( SceneManager* instance )
{
delete instance;
}
//-----------------------------------------------------------------------
84 PagingLandScapeSceneManager::PagingLandScapeSceneManager( const String& name ) :
PagingLandScapeOctreeSceneManager( name ),
mData2DManager ( 0 ),
mTextureManager ( 0 ),
mTileManager ( 0 ),
mRenderableManager ( 0 ),
mIndexesManager ( 0 ),
mTexCoordManager ( 0 ),
mPageManager ( 0 ),
mHorizon ( 0 ),
mNeedOptionsUpdate ( false ),
//JEFF
mWorldGeomIsSetup ( false ),
// TK
mWorldGeomIsInit ( false ),
mBrushSize ( 5 ),
mBrushScale ( 0.2f ),
101 mImpactInfo ( 0 ),
mBrushCenter ( Vector3::ZERO ),
mBrushArray ( 0 ), mCraterArray( 0 ),
mBrushArrayHeight ( 0 ),
mBrushArrayWidth ( 0 ),
mListenerManager( 0 ),
mOptions( 0 ),
textureFormatChanged ( false )
{
//showBoundingBoxes( true );
//setDisplaySceneNodes( true );
mMeshDecalFactory = new PagingLandScapeMeshDecalFactory;
if( !( Root::getSingleton( ).hasMovableObjectFactory( "PagingLandScapeMeshDecal" ) ) )
Root::getSingleton( ).addMovableObjectFactory( mMeshDecalFactory );
}
//-------------------------------------------------------------------------
118 const String& PagingLandScapeSceneManager::getTypeName( void ) const
{
return PagingLandScapeSceneManagerFactory::FACTORY_TYPE_NAME;
}
//-----------------------------------------------------------------------
123 void PagingLandScapeSceneManager::PagingLandScapeOctreeResize( )
{
const Ogre::Real x = mOptions->maxScaledX;
assert ( mData2DManager );
const Ogre::Real y = mData2DManager->getMaxHeight ( ) * 4;
const Ogre::Real z = mOptions->maxScaledZ;
PagingLandScapeOctreeSceneManager::resize( AxisAlignedBox( -x , 0, -z, x, y, z ) );
}
//-----------------------------------------------------------------------
132 void PagingLandScapeSceneManager::WorldDimensionChange( )
{
PagingLandScapeOctreeResize( );
assert ( mPageManager );
assert ( mData2DManager );
assert ( mTextureManager );
mPageManager->WorldDimensionChange( );
mData2DManager->WorldDimensionChange( );
mTextureManager->WorldDimensionChange( );
}
//-------------------------------------------------------------------------
144 void PagingLandScapeSceneManager::shutdown( void )
{
clearScene( );
delete mOptions;
mOptions = 0;
delete mData2DManager;
mData2DManager = 0;
delete mTextureManager;
mTextureManager = 0;
if ( mPageManager )
Root::getSingleton( ).removeFrameListener ( mPageManager );
delete mPageManager;
mPageManager = 0;
delete mListenerManager;
mListenerManager = 0;
delete mTileManager;
mTileManager = 0;
delete mRenderableManager;
mRenderableManager = 0;
delete mIndexesManager;
mIndexesManager = 0;
delete mTexCoordManager;
mTexCoordManager = 0;
delete[] mCraterArray;
mCraterArray = 0;
Root::getSingleton( ).removeMovableObjectFactory( mMeshDecalFactory );
delete mMeshDecalFactory;
}
//-----------------------------------------------------------------------
180 PagingLandScapeSceneManager::~PagingLandScapeSceneManager( )
{
shutdown( );
}
//-------------------------------------------------------------------------
185 void PagingLandScapeSceneManager::setWorldGeometry( DataStreamPtr& stream, const String& typeName )
{
if ( !mListenerManager )
mListenerManager = new PagingLandScapeListenerManager( this );
// Clear out any existing world resources ( if not default )
if ( ResourceGroupManager::getSingleton( ).getWorldResourceGroupName( ) !=
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME )
{
ResourceGroupManager::getSingleton( ).clearResourceGroup(
ResourceGroupManager::getSingleton( ).getWorldResourceGroupName( ) );
}
if ( mWorldGeomIsSetup )
clearScene( );
if ( !mOptions )
mOptions = new PagingLandScapeOptions( this );
InitScene ( );
// Load the configuration file
if ( !stream.isNull ( ) )
{
if ( mOptions->load( stream ) )
loadScene ( );
}
// Check if we need to set the camera
if ( !mOptions->primaryCamera && !mCameras.empty ( ) )
{
PagingLandScapeCamera* c = static_cast <PagingLandScapeCamera*> ( mCameras.begin( )->second );
mOptions->setPrimaryCamera ( c );
}
}
//-----------------------------------------------------------------------
216 void PagingLandScapeSceneManager::setWorldGeometry( const String& filename )
{
if ( filename.empty( ) )
{
#ifdef PLSM2_EIHORT
DataStreamPtr myStream;
#else
DataStreamPtr myStream ( 0 );
#endif
myStream.setNull( );
setWorldGeometry ( myStream );
return;
}
// try to open in the current folder first
std::ifstream fs;
fs.open( filename.c_str( ), std::ios::in | std::ios::binary );
if ( fs )
{
// Wrap as a stream
DataStreamPtr myStream ( new FileStreamDataStream ( filename, &fs, false ) );
setWorldGeometry ( myStream );
return;
}
// otherwise try resource system
DataStreamPtr myStream ( ResourceGroupManager::getSingleton( ).openResource( filename ) );
setWorldGeometry ( myStream );
}
//-----------------------------------------------------------------------
246 void PagingLandScapeSceneManager::InitScene ( )
{
// Only initialized once
// not to loose use listeners
if ( !mListenerManager )
mListenerManager = new PagingLandScapeListenerManager( this );
if ( !mTileManager )
mTileManager = new PagingLandScapeTileManager( this );
if ( !mData2DManager )
mData2DManager = new PagingLandScapeData2DManager( this, mOptions ); //
if ( !mTextureManager )
mTextureManager = new PagingLandScapeTextureManager( this );
if ( !mIndexesManager )
mIndexesManager = new PagingLandScapeIndexBufferManager( this );
if ( !mTexCoordManager )
mTexCoordManager = new PagingLandScapeTextureCoordinatesManager( this );
if ( !mRenderableManager )
mRenderableManager = new PagingLandScapeRenderableManager( this );
if ( !mCraterArray )
resizeCrater( );
if ( !mPageManager )
{
mPageManager = new PagingLandScapePageManager( this );
Root::getSingleton( ).addFrameListener( mPageManager );
mPageManager->setWorldGeometryRenderQueue ( static_cast<Ogre::RenderQueueGroupID>( SceneManager::getWorldGeometryRenderQueue( ) ) );
mData2DManager->setPageManager( this );
}
}
//-----------------------------------------------------------------------
276 void PagingLandScapeSceneManager::loadScene( )
{
if ( !mWorldGeomIsSetup )
{
// listen to frames to update queues independently of cam numbers.
// cannot do that if remove is called in same frame before it removes it
// ...
//Root::getSingleton( ).addFrameListener( mPageManager );
mPageManager->setEnabled ( true );
mTileManager->load( );
mData2DManager->load( );
mTextureManager->load( );
mIndexesManager->load( );
mTexCoordManager->load( );
if ( mOptions->VisMap )
{
assert ( !mHorizon );
mHorizon = new PagingLandScapeHorizon( mOptions );
}
mPageManager->load( );
mRenderableManager->load( );
// reset camera paging
// register existing camera in node
CameraList::iterator i = mCameras.begin( );
for ( ; i != mCameras.end( ); ++i )
{
// Notify occlusion system
PagingLandScapeCamera *c = static_cast <PagingLandScapeCamera *> ( i->second );
assert ( c );
c->resetPaging ( );
}
PagingLandScapeOctreeResize( );
mWorldGeomIsSetup = true;
}
}
//-----------------------------------------------------------------------
319 void PagingLandScapeSceneManager::clearScene( void )
{
//SceneManager::getRenderQueue( )->clear( );
PagingLandScapeSceneManager::resetScene( );
//Call the default
PagingLandScapeOctreeSceneManager::clearScene( );
}
//-----------------------------------------------------------------------
327 void PagingLandScapeSceneManager::resetScene( void )
{
if ( mWorldGeomIsSetup )
{
//Root::getSingleton( ).removeFrameListener ( mPageManager );
mPageManager->setEnabled ( false );
// clear the Managers
mPageManager->clear( );
mTextureManager->clear( );
mData2DManager->clear( );
if ( mHorizon )
{
delete mHorizon;
mHorizon = 0;
}
// clear queues
mRenderableManager->clear( );
mTileManager->clear( );
// unload cached map info
mOptions->clearTileInfo( );
// clear hardware buffer caches
//mIndexesManager->clear( ); //don't clear to keep index buffer if tilesize
//mTexCoordManager->clear( ); //don't clear to keep index buffer if tilesize
mWorldGeomIsSetup = false;
mWorldGeomIsInit = false;
//PagingLandScapeOctreeSceneManager::clearScene( );
}
}
//-----------------------------------------------------------------------
360 void PagingLandScapeSceneManager::_updateSceneGraph( Camera * cam )
{
// entry into here could come before setWorldGeometry
// got called which could be disastrous
// so check for init
assert( mPageManager );
if ( isRenderQueueToBeProcessed( mPageManager->getPageRenderQueue( ) ) )
{
if ( mWorldGeomIsInit )
{
mPageManager->updatePaging ( static_cast<PagingLandScapeCamera *> ( cam ) );
}
else
{
if ( mWorldGeomIsSetup )
{
mOptions->calculateCFactor ( );
assert ( mPageManager );
if ( mOptions->BigImage )
{
assert ( mTextureManager );
mTextureManager->setMapMaterial( );
mPageManager->setMapMaterial( );
}
mWorldGeomIsInit = true;
mPageManager->updatePaging ( static_cast<PagingLandScapeCamera *> ( cam ) );
}
}
}
// Call the default
PagingLandScapeOctreeSceneManager::_updateSceneGraph( cam );
}
//-----------------------------------------------------------------------
// void PagingLandScapeSceneManager::_renderVisibleObjects( void )
// {
// SceneManager::_renderVisibleObjects( );
// }
//-----------------------------------------------------------------------
// void PagingLandScapeSceneManager::_findVisibleObjects ( Camera * cam, bool onlyShadowCasters )
// {
// PagingLandScapeOctreeSceneManager::_findVisibleObjects( cam, onlyShadowCasters );
// }
//----------------------------------------------------------------------------
// IntersectionSceneQuery* PagingLandScapeSceneManager::createIntersectionQuery( unsigned long mask )
// {
// PagingLandScapeIntersectionSceneQuery* q = new PagingLandScapeIntersectionSceneQuery( this );
// q->setQueryMask( mask );
// return q;
// }
414 AxisAlignedBoxSceneQuery* PagingLandScapeSceneManager::createAABBQuery( const AxisAlignedBox& box,
unsigned long mask )
{
PagingLandScapeAxisAlignedBoxSceneQuery* q = new PagingLandScapeAxisAlignedBoxSceneQuery( this );
q->setBox( box );
q->setQueryMask( mask );
return q;
}
//----------------------------------------------------------------------------
424 RaySceneQuery* PagingLandScapeSceneManager::createRayQuery( const Ray& ray, unsigned long mask )
{
PagingLandScapeRaySceneQuery* q = new PagingLandScapeRaySceneQuery( this );
q->setRay( ray );
q->setQueryMask( mask );
return q;
}
//-------------------------------------------------------------------------
432 bool PagingLandScapeSceneManager::intersectSegment( const Ogre::Vector3 & raybegin,
433 const Ogre::Vector3 & rayend,
434 Ogre::Vector3 * rayresult )
{
return intersectSegmentTerrain ( raybegin, rayend, rayresult );
}
//-------------------------------------------------------------------------
439 bool PagingLandScapeSceneManager::intersectSegmentTerrain ( const Ogre::Vector3 & raybegin,
440 const Ogre::Vector3 & raydir,
441 Ogre::Vector3 * rayresult )
{
Ogre::Vector3 raystart ( raybegin );
assert ( mPageManager && mData2DManager );
const Ogre::Real maxHeight = mData2DManager->getMaxHeight ( );
if ( raystart.y > maxHeight )
{
// find an new ray start that is under highest terrain height
// so that we do not test intersection between terrain and ray
// on ray part where Y > maxHeight
// First check if not parallel to terrain
if ( Math::Abs( raydir.y ) < std::numeric_limits<Real>::epsilon( ) )
{
// Parallel ?
*rayresult = Ogre::Vector3( -1.0f, -1.0f, -1.0f );
return false;
}
// now ray should begin at a pertinent place.
const Ogre::Real t = -( raystart.y-maxHeight )/raydir.y;
raystart += raydir*t;
if ( raystart.y <= mData2DManager->getInterpolatedWorldHeight( raystart.x, raystart.z ) )
{
*rayresult = raystart;
return true;
}
}
PagingLandScapeTile * t = mPageManager->getTile ( raystart.x, raystart.z, false );
if ( t == 0 )
{
// we're outside LandScape
#ifndef _STRICT_LandScape
// if you want to be able to intersect from a point outside the canvas
//const int pageSize = mOptions->PageSize - 1;
const Ogre::Real W = mOptions->maxScaledX;
const Ogre::Real H = mOptions->maxScaledZ;
const Ogre::Real maxHeight = mData2DManager->getMaxHeight ( );
if ( W != 0 && H != 0 ) {
// while ray is outside but raydir going inside
while ( ( raystart.y < 0.0f && raydir.y > 0.0f ) ||
( raystart.y > maxHeight && raydir.y < 0.0f ) ||
( raystart.x < -W && raydir.x > 0.0f ) ||
( raystart.x > W && raydir.x < 0.0f ) ||
( raystart.z < -H && raydir.z > 0.0f ) ||
( raystart.z > H && raydir.z < 0.0f ) )
raystart += raydir;
}
if ( raystart.y < 0.0f || raystart.y >= maxHeight ||
raystart.x < -W || raystart.x > W ||
raystart.z < -H || raystart.z > H )
{
*rayresult = Ogre::Vector3( -1.0f, -1.0f, -1.0f );
return false;
}
t = mPageManager->getTile ( raystart.x, raystart.z, false );
if ( t == 0 )
return false;
#else //_STRICT_LandScape
// if you don't want to be able to intersect from a point outside the canvas
*rayresult = Ogre::Vector3( -1.0f, -1.0f, -1.0f );
return false;
#endif //_STRICT_LandScape
}
bool impact;
//special case...
// if ( raydir.x == 0.0f && raydir.z == 0.0f )
// {
// if ( raystart.y <= mData2DManager->getInterpolatedWorldHeight( raystart.x, raystart.z ) )
// {
// *rayresult = raystart;
// impact = true;
// }
// impact = false;
// }
// else
{
// should we scale ?
// const Ogre::Vector3 rayDirScaled (
// raydir.x * mOptions->scale.x,
// raydir.y * mOptions->scale.y,
// raydir.z * mOptions->scale.z );
if ( raystart.y >= mData2DManager->getInterpolatedWorldHeight( raystart.x, raystart.z ) )
{
impact = t->intersectSegmentFromAbove( raystart, raydir, rayresult );
}
else
{
impact = t->intersectSegmentFromBelow( raystart, raydir, rayresult );
}
}
return true;
}
//-------------------------------------------------------------------------
546 void PagingLandScapeSceneManager::resizeCrater ( )
{
const int radius = mBrushSize;
const unsigned int diameter = static_cast <unsigned int> ( radius ) * 2;
mBrushArrayHeight = diameter;
mBrushArrayWidth = diameter;
delete [] mCraterArray;
const unsigned int array_size = diameter * diameter;
mCraterArray = new Real[array_size];
memset ( mCraterArray, 0, array_size * sizeof( Real ) );
// Calculate the minimum X value
// make sure it is still on the height map
const int Zmin = -radius;
const int Zmax = radius;
const int Xmin = -radius;
const int Xmax = radius;
// ( goes through each X value )
unsigned int array_indx = 0;
const int radiussquare = radius * radius;
//const Ogre::Real scaler = mOptions->scale.y;// / radius;
const Ogre::Real scaler = 1.0 / radius;
for ( int Zcurr = Zmin; Zcurr < Zmax; Zcurr++ )
{
const Ogre::Real Precalc = radiussquare - ( Zcurr * Zcurr );
if ( Precalc > 1.0f )
{
// Determine the minimum and maximum X value for that
// line in the circle ( that Z value )
//const int Xmax = static_cast<int> ( Math::Sqrt( Precalc ) );
//const int Xmin = - Xmax;
unsigned int curr_indx = array_indx;// + Xmin + radius;
// For each of those Z values, calculate the new Y value
for ( int Xcurr = Xmin; Xcurr < Xmax; Xcurr++ )
{
assert ( curr_indx < array_size );
// Calculate the new theoretical height for the current point on the circle
const Ogre::Real val = static_cast <Real> ( Xcurr * Xcurr );
const Ogre::Real diffPrecalc = Precalc - val;
mCraterArray[curr_indx] = std::min( static_cast <Real> ( 1.0 ),
std::max( static_cast <Real> ( 0.0 ),
Math::Sqrt ( diffPrecalc )* scaler ) ) ;
curr_indx++;
} // for ( int Xcurr = Xmin; Xcurr < Xmax; Xcurr++ )
} // if ( Precalc > 1.0f )
array_indx += diameter;
//array_indx += diameter;
} // for ( int Zcurr = Zmin; Zcurr < radius; Zcurr++ )
mBrushArray = mCraterArray;
}
//-----------------------------------------------------------------------
602 void PagingLandScapeSceneManager::paint ( const Ogre::Vector3 &impact )
{
if ( mOptions->textureModifiable )
{
const int X = static_cast<int> ( impact.x / mOptions->scale.x );
const int Z = static_cast<int> ( impact.z / mOptions->scale.z );
//const int pageSize = mOptions->PageSize - 1;
const int W = static_cast<int> ( mOptions->maxUnScaledX );
const int H = static_cast<int> ( mOptions->maxUnScaledZ );
if ( X < -W || X > W || Z < -H || Z > H )
return;
const int brushW = static_cast<int> ( mBrushArrayWidth );
// Calculate the minimum X value
// make sure it is still on the height map
unsigned int xshift = 0;
int Xmin = static_cast<int> ( -brushW * 0.5f ) ;
if ( Xmin + X < -W )
{
//assert ( Xmin + X + W > 0 );
xshift = static_cast <unsigned int> ( abs ( Xmin + X + W ) );
Xmin = - X - W;
}
// Calculate the maximum X value
// make sure it is still on the height map
int Xmax = static_cast<int> ( brushW * 0.5f ) ;
if ( Xmax + X > W )
Xmax = W - X;
const int brushH = static_cast<int> ( mBrushArrayHeight );
// Calculate the minimum Z value
// make sure it is still on the height map
unsigned int zshift = 0;
int Zmin = - static_cast<int> ( brushH * 0.5 ) ;
if ( Zmin + Z < -H )
{
//assert ( Zmin + Z + H > 0 );
zshift = static_cast <unsigned int> ( abs ( Zmin + Z + H ) );
Zmin = - Z - H;
}
// Calculate the maximum Z value
// make sure it is still on the height map
int Zmax = static_cast<int> ( brushH * 0.5 );
if ( Zmax + Z > H )
Zmax = H - Z;
// Main loop to draw the circle on the height map
// ( goes through each X value )
unsigned int array_indx = zshift*brushW;
for ( int Zcurr = Zmin; Zcurr < Zmax; Zcurr++ )
{
// For each of those Z values, calculate the new Y value
unsigned int curr_indx = array_indx + xshift;
for ( int Xcurr = Xmin; Xcurr < Xmax; Xcurr++ )
{
// get results by page index ?
const Ogre::Real h = mBrushArray[curr_indx];
// Make sure we do it for something.
if ( h - 0.005f > 0 )
{
assert ( h >= 0.0f && h <= 1.0f );
const Ogre::Real bushForce = std::min( static_cast <Real> ( 1.0 ), h*mBrushScale );
if ( bushForce - 0.005f > 0 )
{
const Ogre::Vector3 currpoint ( X + Xcurr, static_cast <Real> ( 0.0 ), Z + Zcurr );
assert ( mPageManager&& mData2DManager && mTextureManager );
PagingLandScapeTile * t = mPageManager->getTileUnscaled ( currpoint.x, currpoint.z, false );
if ( t && t->isLoaded ( ) )
{
mImpactInfo = t->getInfo ( );
// check page boundaries to modify any page, tile neighbour
// tells any tile modified to update at next frame
assert ( curr_indx < mBrushArrayWidth*mBrushArrayHeight );
mTextureManager->paint ( currpoint, bushForce, mImpactInfo );
}// if ( t && t->isLoaded ( ) )
}
} // if ( h != 0.0f )
curr_indx++;
} // for ( int Xcurr = Xmin; Xcurr < Xmax; Xcurr++ )
array_indx += brushW;
} // for ( int Zcurr = Zmin; Zcurr < Zmax; Zcurr++ )
}
}//-----------------------------------------------------------------------
687 void PagingLandScapeSceneManager::setHeight ( const Ogre::Vector3 &impact )
{
if ( mOptions->Deformable )
{
const int X = static_cast<int> ( impact.x / mOptions->scale.x );
const int Z = static_cast<int> ( impact.z / mOptions->scale.z );
//const int pageSize = mOptions->PageSize - 1;
const int W = static_cast<int> ( mOptions->maxUnScaledX );
const int H = static_cast<int> ( mOptions->maxUnScaledZ );
if ( X < -W || X > W || Z < -H || Z > H )
return;
const int brushW = static_cast<int> ( mBrushArrayWidth );
// Calculate the minimum X value
// make sure it is still on the height map
unsigned int xshift = 0;
int Xmin = static_cast<int> ( -brushW * 0.5f );
if ( Xmin + X < -W )
{
//assert ( Xmin + X + W > 0 );
xshift = static_cast <unsigned int> ( abs ( Xmin + X + W ) );
Xmin = - X - W;
}
// Calculate the maximum X value
// make sure it is still on the height map
int Xmax = static_cast<int> ( brushW * 0.5f ) ;
if ( Xmax + X > W )
Xmax = W - X;
const int brushH = static_cast<int> ( mBrushArrayHeight );
// Calculate the minimum Z value
// make sure it is still on the height map
unsigned int zshift = 0;
int Zmin = static_cast<int> ( - brushH * 0.5f ) ;
if ( Zmin + Z < -H )
{
//assert ( Zmin + Z + H > 0 );
zshift = static_cast <unsigned int> ( abs ( Zmin + Z + H ) );
Zmin = - Z - H;
}
// Calculate the maximum Z value
// make sure it is still on the height map
int Zmax = static_cast<int> ( brushH * 0.5f ) ;
if ( Zmax + Z > H )
Zmax = H - Z;
const Ogre::Real Hscale = mOptions->scale.y * mBrushScale;
// Main loop to draw the circle on the height map
// ( goes through each X value )
unsigned int array_indx = zshift*brushW;
for ( int Zcurr = Zmin; Zcurr < Zmax; Zcurr++ )
{
// For each of those Z values, calculate the new Y value
unsigned int curr_indx = array_indx + xshift;
for ( int Xcurr = Xmin; Xcurr < Xmax; Xcurr++ )
{
// get results by page index ?
const Ogre::Real h = - mBrushArray[curr_indx] * mBrushScale * Hscale;
// Make sure we do it for something.
if ( h != 0.0f )
{
const Ogre::Vector3 currpoint ( X + Xcurr, 0.0f, Z + Zcurr );
assert ( mPageManager&& mData2DManager && mTextureManager );
PagingLandScapeTile * t = mPageManager->getTileUnscaled ( currpoint.x, currpoint.z, false );
if ( t && t->isLoaded ( ) )
{
mImpactInfo = t->getInfo ( );
// check page boundaries to modify any page, tile neighbour
// tells any tile modified to update at next frame
assert ( curr_indx < mBrushArrayWidth*mBrushArrayHeight );
if ( mData2DManager->setHeight ( currpoint, h, mImpactInfo ) )
mTextureManager->deformHeight ( currpoint, mImpactInfo );
} // if ( t && t->isLoaded ( ) )
} // if ( h != 0.0f )
curr_indx++;
} // for ( int Xcurr = Xmin; Xcurr < Xmax; Xcurr++ )
array_indx += brushW;
} // for ( int Zcurr = Zmin; Zcurr < Zmax; Zcurr++ )
} // if ( mOptions->Deformable )
}
//-----------------------------------------------------------------------
770 void PagingLandScapeSceneManager::deformHeight ( const Ogre::Vector3 &impact )
{
if ( mOptions->Deformable )
{
const int X = static_cast<int> ( impact.x / mOptions->scale.x );
const int Z = static_cast<int> ( impact.z / mOptions->scale.z );
//const int pageSize = mOptions->PageSize - 1;
const int W = static_cast<int> ( mOptions->maxUnScaledX );
const int H = static_cast<int> ( mOptions->maxUnScaledZ );
if ( X < -W || X > W || Z < -H || Z > H )
return;
const int brushW = static_cast<int> ( mBrushArrayWidth );
// Calculate the minimum X value
// make sure it is still on the height map
unsigned int xshift = 0;
int Xmin = static_cast<int> ( -brushW * 0.5f );
if ( Xmin + X < -W )
{
//assert ( Xmin + X + W > 0 );
xshift = static_cast <unsigned int> ( abs ( Xmin + X + W ) );
Xmin = - X - W;
}
// Calculate the maximum X value
// make sure it is still on the height map
int Xmax = static_cast<int> ( brushW * 0.5f ) ;
if ( Xmax + X > W )
Xmax = W - X;
const int brushH = static_cast<int> ( mBrushArrayHeight );
// Calculate the minimum Z value
// make sure it is still on the height map
unsigned int zshift = 0;
int Zmin = static_cast<int> ( - brushH * 0.5f ) ;
if ( Zmin + Z < -H )
{
//assert ( Zmin + Z + H > 0 );
zshift = static_cast <unsigned int> ( abs ( Zmin + Z + H ) );
Zmin = - Z - H;
}
// Calculate the maximum Z value
// make sure it is still on the height map
int Zmax = static_cast<int> ( brushH * 0.5f ) ;
if ( Zmax + Z > H )
Zmax = H - Z;
const Ogre::Real Hscale = mOptions->scale.y * mBrushScale;
// Main loop to draw the circle on the height map
// ( goes through each X value )
unsigned int array_indx = zshift*brushW;
for ( int Zcurr = Zmin; Zcurr < Zmax; Zcurr++ )
{
// For each of those Z values, calculate the new Y value
unsigned int curr_indx = array_indx + xshift;
for ( int Xcurr = Xmin; Xcurr < Xmax; Xcurr++ )
{
// get results by page index ?
const Ogre::Real h = - mBrushArray[curr_indx] * Hscale;
// Make sure we do it for something.
if ( h != 0.0f )
{
const Ogre::Vector3 currpoint ( X + Xcurr, 0.0f, Z + Zcurr );
assert ( mPageManager&& mData2DManager && mTextureManager );
PagingLandScapeTile * t = mPageManager->getTileUnscaled ( currpoint.x, currpoint.z, false );
if ( t && t->isLoaded ( ) )
{
mImpactInfo = t->getInfo ( );
// check page boundaries to modify any page, tile neighbour
// tells any tile modified to update at next frame
assert ( curr_indx < mBrushArrayWidth*mBrushArrayHeight );
if ( mData2DManager->deformHeight ( currpoint, h, mImpactInfo ) )
mTextureManager->deformHeight ( currpoint, mImpactInfo );
} // if ( t && t->isLoaded ( ) )
} // if ( h != 0.0f )
curr_indx++;
} // for ( int Xcurr = Xmin; Xcurr < Xmax; Xcurr++ )
array_indx += brushW;
} // for ( int Zcurr = Zmin; Zcurr < Zmax; Zcurr++ )
} // if ( mOptions->Deformable )
}
//-----------------------------------------------------------------------
854 void PagingLandScapeSceneManager::getAreaHeight ( const Ogre::Vector3 &impact )
{
const int X = static_cast<int> ( impact.x / mOptions->scale.x );
const int Z = static_cast<int> ( impact.z / mOptions->scale.z );
//const int pageSize = mOptions->PageSize - 1;
const int W = static_cast<int> ( mOptions->maxUnScaledX );
const int H = static_cast<int> ( mOptions->maxUnScaledZ );
if ( X < -W || X > W || Z < -H || Z > H )
return;
const int brushW = static_cast<int> ( mBrushArrayWidth );
// Calculate the minimum X value
// make sure it is still on the height map
unsigned int xshift = 0;
int Xmin = static_cast<int> ( -brushW * 0.5f );
if ( Xmin + X < -W )
{
//assert ( Xmin + X + W > 0 );
xshift = static_cast <unsigned int> ( abs ( Xmin + X + W ) );
Xmin = - X - W;
}
// Calculate the maximum X value
// make sure it is still on the height map
int Xmax = static_cast<int> ( brushW * 0.5f ) ;
if ( Xmax + X > W )
Xmax = W - X;
const int brushH = static_cast<int> ( mBrushArrayHeight );
// Calculate the minimum Z value
// make sure it is still on the height map
unsigned int zshift = 0;
int Zmin = static_cast<int> ( - brushH * 0.5f ) ;
if ( Zmin + Z < -H )
{
//assert ( Zmin + Z + H > 0 );
zshift = static_cast <unsigned int> ( abs ( Zmin + Z + H ) );
Zmin = - Z - H;
}
// Calculate the maximum Z value
// make sure it is still on the height map
int Zmax = static_cast<int> ( brushH * 0.5f ) ;
if ( Zmax + Z > H )
Zmax = H - Z;
const unsigned int pSize = mOptions->PageSize - 1;
const Ogre::Real Hscale = 1 / ( mOptions->scale.y * mBrushScale );
// Main loop to draw the circle on the height map
// ( goes through each X value )
unsigned int array_indx = zshift*brushW;
for ( int Zcurr = Zmin; Zcurr < Zmax; Zcurr++ )
{
// For each of those Z values, calculate the new Y value
unsigned int curr_indx = array_indx + xshift;
for ( int Xcurr = Xmin; Xcurr < Xmax; Xcurr++ )
{
const Ogre::Vector3 currpoint ( X + Xcurr, 0.0f, Z + Zcurr );
assert ( mPageManager&& mData2DManager && mTextureManager );
PagingLandScapeTile * t = mPageManager->getTileUnscaled ( currpoint.x, currpoint.z, false );
if ( t && t->isLoaded ( ) )
{
mImpactInfo = t->getInfo ( );
// check page boundaries to modify any page, tile neighbour
// tells any tile modified to update at next frame
assert ( curr_indx < mBrushArrayWidth*mBrushArrayHeight );
// adjust x and z to be local to page
const unsigned int x = static_cast<unsigned int> ( currpoint.x
- mImpactInfo->mPageX * pSize
+ W );
const unsigned int z = static_cast<unsigned int> ( currpoint.z
- mImpactInfo->mPageZ * pSize
+ H );
mBrushArray[curr_indx] = mData2DManager->getHeight( mImpactInfo->mPageX,
mImpactInfo->mPageZ,
x,
z )
*
Hscale;
} // if ( t && t->isLoaded ( ) )
curr_indx++;
} // for ( int Xcurr = Xmin; Xcurr < Xmax; Xcurr++ )
array_indx += brushW;
} // for ( int Zcurr = Zmin; Zcurr < Zmax; Zcurr++ )
}
//-----------------------------------------------------------------------
944 bool PagingLandScapeSceneManager::setOption( const String& strKey, const void* pValue )
{
//listeners
if ( StringUtil::endsWith( strKey, "listener", true ) )
{
if ( mListenerManager->setOption ( strKey, pValue ) )
return true;
}
if ( StringUtil::startsWith( strKey, "pause", true ) )
{
mPageManager->setEnabled( ! *( const_cast < bool * > ( static_cast < const bool * >( pValue ) ) ) );
}
// deformation and painting
if ( strKey == "BrushArray" )
{
mBrushArray = const_cast <Ogre::Real * > ( static_cast < const Ogre::Real * >( pValue ) );
return true;
}
if ( strKey == "BrushArrayHeight" )
{
mBrushArrayHeight = * static_cast < const unsigned int * > ( pValue );
return true;
}
if ( strKey == "BrushArrayWidth" )
{
mBrushArrayWidth = * static_cast < const unsigned int * > ( pValue );
return true;
}
if ( strKey == "BrushScale" )
{
mBrushScale = * static_cast < const Ogre::Real * > ( pValue ) ;
return true;
}
if ( strKey == "BrushSize" )
{
mBrushSize = * static_cast < const unsigned int * > ( pValue );
resizeCrater( );
return true;
}
if ( strKey == "setHeightCenter" )
{
mBrushCenter = * static_cast < const Ogre::Vector3 * > ( pValue );
setHeight ( mBrushCenter );
return true;
}
if ( strKey == "DeformationCenter" )
{
mBrushCenter = * static_cast < const Ogre::Vector3 * > ( pValue );
deformHeight ( mBrushCenter );
return true;
}
if ( strKey == "fillBrushArray" )
{
mBrushCenter = * static_cast < const Ogre::Vector3 * > ( pValue );
getAreaHeight ( mBrushCenter );
return true;
}
if ( strKey == "PaintCenter" )
{
mBrushCenter = * static_cast < const Ogre::Vector3 * > ( pValue );
paint( mBrushCenter );
return true;
}
if ( strKey == "setPaintChannelValues" )
{
mTextureManager->setPaintChannelValues (
static_cast < const std::vector<Real> *>
( pValue )
);
return true;
}
if ( strKey == "renderTextureModeToBaseTextures" )
{
const String alternateMaterial = *static_cast < const String * > ( pValue );
renderBaseTextures( alternateMaterial );
}
// Map Changes
if ( strKey == "LoadMap" )
{
const String textureFormatName( mOptions->getCurrentTextureFormat ( ) );
PagingLandScapeSceneManager::resetScene( );
PagingLandScapeSceneManager::loadScene ( );
textureFormatChanged = false;
return true;
}
if ( strKey == "CurrentMap" )
{
const String CurrentMapName = *static_cast < const String * > ( pValue );
mOptions->setCurrentMapName ( CurrentMapName );
return true;
}
if ( strKey == "InsertNewMap" )
{
const String CurrentMapName = *static_cast < const String * > ( pValue );
mOptions->insertMap( CurrentMapName );
return true;
}
// TextureFormat changes
if ( strKey == "CurrentTextureFormat" )
{
// Override File TextureFormat
mOptions->setTextureFormat ( *static_cast < const String * > ( pValue ) );
textureFormatChanged = true;
return true;
}
// TextureFormat changes
if ( strKey == "InsertTextureFormat" )
{
// Override File TextureFormat
mOptions->insertTextureFormat ( *static_cast < const String * > ( pValue ) );
return true;
}
if ( strKey == "PageUpdate" )
{
const Vector2 page = *static_cast < const Vector2 * > ( pValue );
// Reload Data. ALso must reload pages that depend on this
mData2DManager->reload ( page.x, page.y );
mTextureManager->reload( page.x, page.y );
if ( page.x > 0 )
{
mData2DManager->reload ( page.x-1, page.y );
mTextureManager->reload( page.x-1, page.y );
}
if ( page.y > 0 )
{
mTextureManager->reload( page.x, page.y-1 );
mData2DManager->reload ( page.x, page.y-1 );
}
if ( page.x > 0 && page.y > 0 )
{
mData2DManager->reload ( page.x-1, page.y-1 );
mTextureManager->reload( page.x-1, page.y-1 );
}
// Now reload pages
//mPageManager::getSingleton( ).getPage( page.x, page.y )->reload( );
}
if ( strKey == "LoadNow" )
{
assert ( mPageManager );
if ( mOptions->max_preload_pages*mOptions->max_preload_pages >= mOptions->NumPages )
{
// Configuration file is telling us to pre-load all pages at startup.
for ( unsigned int pageY = 0; pageY < mOptions->world_height; pageY++ )
{
for ( unsigned int pageX = 0; pageX < mOptions->world_width; pageX++ )
{
PagingLandScapePage * const p = mPageManager->getPage( pageX, pageY );
p->load( );
mPageManager->addLoadedPage( p );
}
}
if ( mOptions->primaryCamera )
mPageManager->loadNow ( mOptions->primaryCamera );
}
else if ( pValue )
{
PagingLandScapeCamera *cam = const_cast <PagingLandScapeCamera *> ( static_cast < const PagingLandScapeCamera * > ( pValue ) );
mPageManager->loadNow ( cam );
}
}
if ( strKey == "ResetScene" )
{
if( * static_cast < const bool * > ( pValue ) )
PagingLandScapeSceneManager::resetScene( );
return true;
}
if ( mOptions->setOption( strKey, pValue ) == true )
{
return true;
}
if ( PagingLandScapeOctreeSceneManager::setOption ( strKey, pValue ) == true )
{
return true;
}
return false;
}
//-----------------------------------------------------------------------
1139 bool PagingLandScapeSceneManager::getOption( const String& strKey, void* pDestValue )
{
if ( strKey == "h" || strKey == "getHeightAt" )
{
Ogre::Vector3 *p = static_cast < Ogre::Vector3 * > ( pDestValue );
p->y = getHeightAt ( p->x, p->z );
return true;
}
if ( strKey == "s" || strKey == "getSlopeAt" )
{
Ogre::Vector3 *p = static_cast < Ogre::Vector3 * > ( pDestValue );
p->y = getSlopeAt ( p->x, p->z );
return true;
}
if ( StringUtil::startsWith( strKey, "pause", true ) )
{
* ( static_cast < bool * > ( pDestValue ) ) = !mPageManager->isEnabled( );
return true;
}
// heightfield data an pos info
if ( strKey == "MapBoundaries" )
{
AxisAlignedBox *box = static_cast < AxisAlignedBox * > ( pDestValue );
box->setExtents( -mOptions->maxScaledX,
0,
-mOptions->maxScaledZ,
mOptions->maxScaledX,
mOptions->scale.y,
mOptions->maxScaledZ );
return true;
}
if ( strKey == "GlobalToPage" )
{
Ogre::Vector3 *pos = static_cast < Ogre::Vector3 * > ( pDestValue );
mPageManager->getGlobalToPage ( pos->x, pos->z );
return true;
}
if ( strKey == "getAreaSize" )
{
Ogre::Vector3 *vertices_array = static_cast < Ogre::Vector3 * > ( pDestValue );
mPageManager->getGlobalToPage ( vertices_array[0].x, vertices_array[0].z );
mPageManager->getGlobalToPage ( vertices_array[1].x, vertices_array[1].z );
mPageManager->getGlobalToPage ( vertices_array[2].x, vertices_array[2].z );
mPageManager->getGlobalToPage ( vertices_array[3].x, vertices_array[3].z );
// define an area an get number of point in it.
const Ogre::Real maxx = std::max ( vertices_array[0].x,
std::max ( vertices_array[1].x,
std::max ( vertices_array[2].x,
vertices_array[3].x ) ) );
const Ogre::Real minx = std::min ( vertices_array[0].x,
std::min ( vertices_array[1].x,
std::min ( vertices_array[2].x,
vertices_array[3].x ) ) );
const Ogre::Real maxz = std::max ( vertices_array[0].z,
std::max ( vertices_array[1].z,
std::max ( vertices_array[2].z,
vertices_array[3].z ) ) );
const Ogre::Real minz = std::min ( vertices_array[0].z,
std::min ( vertices_array[1].z,
std::min ( vertices_array[2].z,
vertices_array[3].z ) ) );
const unsigned int xpoints = static_cast<unsigned int> ( maxx - minx );
const unsigned int zpoints = static_cast<unsigned int> ( maxz - minz );
vertices_array[4].x = zpoints * xpoints;
return true;
}
// Visibility info
if ( strKey == "VisibilityMaterial" )
{
if ( mHorizon )
{
* static_cast < MaterialPtr * > ( pDestValue ) = mHorizon->getVisibilityMaterial( );
return true;
}
else
return false;
}
// TextureFormat info
if ( strKey == "NextTextureFormat" )
{
* static_cast < String * > ( pDestValue ) = mTextureManager->getNextTextureFormat( );
return true;
}
if ( strKey == "CurrentTextureFormat" )
{
* static_cast < String * > ( pDestValue ) = mTextureManager->getCurrentTextureFormat( );
return true;
}
// Map Info
if ( strKey == "NextMap" )
{
* static_cast < String * > ( pDestValue ) = mOptions->getNextMapName( );
return true;
}
if ( strKey == "PreviousMap" )
{
* static_cast < String * > ( pDestValue ) = mOptions->getPreviousMapName( );
return true;
}
if ( strKey == "CurrentMap" )
{
* static_cast < String * > ( pDestValue ) = mOptions->getCurrentMapName( );
return true;
}
if ( strKey == "CurrentMapFileName" )
{
* static_cast < String * > ( pDestValue ) = mOptions->LandScape_filename;
return true;
}
// PAGEINFO
if ( strKey == "CurrentCameraPageX" )
{
if ( mPageManager )
* static_cast < int * > ( pDestValue ) = mPageManager->getCurrentCameraPageX( );
return true;
}
if ( strKey == "CurrentCameraPageZ" )
{
if ( mPageManager )
* static_cast < int * > ( pDestValue ) = mPageManager->getCurrentCameraPageZ( );
return true;
}
if ( strKey == "PagePreloadQueue" )
{
if ( mPageManager )
* static_cast < int * > ( pDestValue ) = mPageManager->getPagePreloadQueueSize( );
return true;
}
if ( strKey == "PageTextureloadQueue" )
{
if ( mPageManager )
* static_cast < int * > ( pDestValue ) = mPageManager->getPageTextureloadQueueSize( );
return true;
}
if ( strKey == "PageLoadQueue" )
{
if ( mPageManager )
* static_cast < int * > ( pDestValue ) = mPageManager->getPageLoadQueueSize( );
return true;
}
if ( strKey == "PreLoadedPages" )
{
if ( mPageManager )
* static_cast < int * > ( pDestValue ) = mPageManager->getPreLoadedPageSize( );
return true;
}
if ( strKey == "TextureLoadedPages" )
{
if ( mPageManager )
* static_cast < int * > ( pDestValue ) = mPageManager->getTextureLoadedPageSize( );
return true;
}
if ( strKey == "LoadedPages" )
{
if ( mPageManager )
* static_cast < int * > ( pDestValue ) = mPageManager->getLoadedPageSize( );
return true;
}
if ( strKey == "UnloadedPages" )
{
if ( mPageManager )
* static_cast < int * > ( pDestValue ) = mPageManager->getUnloadedPagesSize( );
return true;
}
//TILES INFO
if ( strKey == "MaxNumTiles" )
{
if ( mTileManager )
* static_cast < int * > ( pDestValue ) = mTileManager->numTiles( );
return true;
}
if ( strKey == "TileFree" )
{
if ( mTileManager )
* static_cast < int * > ( pDestValue ) = ( int )mTileManager->numFree( );
return true;
}
if ( strKey == "CurrentCameraTileX" )
{
if ( mTileManager )
* static_cast < int * > ( pDestValue ) = mPageManager->getCurrentCameraTileX( );
return true;
}
if ( strKey == "CurrentCameraTileZ" )
{
if ( mTileManager )
* static_cast < int * > ( pDestValue ) = mPageManager->getCurrentCameraTileZ( );
return true;
}
//RENDERABLES INFO
if ( strKey == "MaxNumRenderables" )
{
if ( mRenderableManager )
* static_cast < int * > ( pDestValue ) = mRenderableManager->numRenderables( );
return true;
}
if ( strKey == "RenderableFree" )
{
if ( mRenderableManager )
* static_cast < int * > ( pDestValue ) = ( int )mRenderableManager->numFree( );
return true;
}
if ( strKey == "RenderableLoading" )
{
if ( mRenderableManager )
* static_cast < int * > ( pDestValue ) = ( int )mRenderableManager->numLoading( );
return true;
}
if ( strKey == "VisibleRenderables" )
{
if ( mRenderableManager )
* static_cast < unsigned int * > ( pDestValue ) = mRenderableManager->numVisibles( );
else
* static_cast < unsigned int * > ( pDestValue ) = 0;
return true;
}
// IMPACT INFO
if ( strKey == "Impact" )
{
* static_cast < Ogre::Vector3 * > ( pDestValue ) = mImpact;
return true;
}
if ( strKey == "ImpactPageX" )
{
if ( mImpactInfo )
* static_cast < int * > ( pDestValue ) = mImpactInfo->mPageX;
return true;
}
if ( strKey == "ImpactPageZ" )
{
if ( mImpactInfo )
* static_cast < int * > ( pDestValue ) = mImpactInfo->mPageZ;
return true;
}
if ( strKey == "ImpactTileX" )
{
if ( mImpactInfo )
* static_cast < int * > ( pDestValue ) = mImpactInfo->mTileZ;
return true;
}
if ( strKey == "ImpactTileZ" )
{
if ( mImpactInfo )
* static_cast < int * > ( pDestValue ) = mImpactInfo->mTileZ;
return true;
}
if ( strKey == "numModifiedTile" )
{
if ( mRenderableManager )
* static_cast < int * > ( pDestValue ) = mRenderableManager->numRenderables( );
return true;
}
if ( strKey == "BrushSize" )
{
* static_cast < int * > ( pDestValue ) = mBrushSize;
return true;
}
if ( strKey == "BrushScale" )
{
* static_cast <Ogre::Real * > ( pDestValue ) = mBrushScale;
return true;
}
// Paint
if ( strKey == "NumChannels" )
{
* static_cast < unsigned int * > ( pDestValue ) = mTextureManager->getNumChannels( );
return true;
}
if ( strKey == "getNumChannelsperTexture" )
{
unsigned int requestChannel = *static_cast<unsigned int *>( pDestValue );
* static_cast < unsigned int * > ( pDestValue ) = mTextureManager->getNumChannelsperTexture( requestChannel );
return true;
}
if ( strKey == "currentColors" )
{
//
return true;
}
//added for Vertex data retrieval
if ( strKey == "PageGetTileVertexData_2" )
{
/**
* This is the optimized, yet a bit fuzzy implementation of the getVertexDataPatch
* Usage: Pass in a std::vector<void*> Pointer to the getOption call containing at least 5 Elements
* [0]( Ogre::unsigned int* ) = X Index of the Page to retrieve data from
* [1]( Ogre::unsigned int* ) = Z Index of the Page to retrieve data from
* [2]( Ogre::unsigned int* ) = X Index of the Tile within the Page to retrieve data from
* [3]( Ogre::unsigned int* ) = Z Index of the Tile within the Page to retrieve data from
* [4]( Ogre::unsigned int* ) = LodLevel to get the data at ( note that level 0 means highest detail )
* The getData call will then append 3 entries to the end of the vector. In Detail( in order )
* [End-2]( Ogre::unsigned int* ) = Number of vertices returned
* [End-1] ( Ogre::Vector3* ) = The actual vertices, this is a array containing as many elements as returned in [End-2]
* [End] ( Ogre::IndexData* ) = The index data for the terrain polygons at the queried LodLevel
* @remark note that the caller is in charge of deleting the vector array, vertices array and indice array.
*/
unsigned int requestPageX = *static_cast<unsigned int *>( ( *static_cast<std::vector<void*>*>( pDestValue ) )[0] );
unsigned int requestPageZ = *static_cast<unsigned int *>( ( *static_cast<std::vector<void*>*>( pDestValue ) )[1] );
unsigned int requestTileX = *static_cast<unsigned int *>( ( *static_cast<std::vector<void*>*>( pDestValue ) )[2] );
unsigned int requestTileZ = *static_cast<unsigned int *>( ( *static_cast<std::vector<void*>*>( pDestValue ) )[3] );
unsigned int requestLodLevel = *static_cast<unsigned int *>( ( *static_cast<std::vector<void*>*>( pDestValue ) )[4] );
PagingLandScapePage* page = mPageManager->getPage( requestPageX, requestPageZ );
if( page )
{
PagingLandScapeTile* tile = page->getTile( requestTileX, requestTileZ );
if( tile )
{
PagingLandScapeRenderable* rend = tile->getRenderable( );
if( rend )
{
Vector3* tempPointer; //This will hold the vertexData and needs to be deleted by the caller
unsigned int* numPtr = new unsigned int;
*numPtr = rend->getVertexCount( );
( *static_cast<std::vector<void*>*>( pDestValue ) ).push_back( numPtr );
tempPointer = new Ogre::Vector3[*numPtr];
//warning! make sure that the allocated space for the vertices is big enough!
rend->getRawVertexData( tempPointer );
( *static_cast<std::vector<void*>*>( pDestValue ) ).push_back( tempPointer );
( *static_cast<std::vector<void*>*>( pDestValue ) ).push_back( rend->getRawIndexData( requestLodLevel ) );
return true;
}
}
}
return false;
}
if ( strKey == "getMaterialPageName" )
{
if ( mPageManager )
{
// convert position
Vector3 **pos = static_cast < Ogre::Vector3 ** > ( pDestValue );
mPageManager->getGlobalToPage ( ( *pos )->x, ( *pos )->z );
// get the texture
Ogre::PagingLandScapeTexture* texture_ptr =
mTextureManager->getTexture( ( *pos )->x, ( *pos )->z, false );
// check for valid texture
if( texture_ptr )
{
// get texture name
String* name_ptr = const_cast<String*>( &texture_ptr->getMaterialName( ) );
// convert void pointer to a string**
String** target_ptr = static_cast<String**>( pDestValue );
// save name at target position
*target_ptr = name_ptr;
}
}
return true;
}
//end of addition
if ( mOptions && mOptions->getOption( strKey, pDestValue ) == false )
{
return PagingLandScapeOctreeSceneManager::getOption ( strKey, pDestValue );
}
return true;
}
//-----------------------------------------------------------------------
1523 bool PagingLandScapeSceneManager::hasOption( const String& strKey ) const
{
if ( strKey == "AddNewHeight" )
{
return true;
}
if ( strKey == "RemoveNewHeight" )
{
return true;
}
if ( strKey == "CurrentCameraPageX" )
{
return true;
}
if ( strKey == "CurrentCameraPageZ" )
{
return true;
}
if ( strKey == "MaxNumTiles" )
{
return true;
}
if ( strKey == "TileFree" )
{
return true;
}
if ( strKey == "MaxNumRenderables" )
{
return true;
}
if ( strKey == "RenderableFree" )
{
return true;
}
if ( strKey == "RenderableLoading" )
{
return true;
}
if ( strKey == "PagePreloadQueue" )
{
return true;
}
if ( strKey == "PageLoadQueue" )
{
return true;
}
if ( strKey == "PageUnloadQueue" )
{
return true;
}
if ( strKey == "PagePostUnloadQueue" )
{
return true;
}
//added for Vertex data retrieval
if ( strKey == "PageGetTileVertexData" )
{
return true;
}
//end of addition
if ( mOptions && mOptions->hasOption( strKey ) == false )
{
return PagingLandScapeOctreeSceneManager::hasOption ( strKey );
}
return true;
}
//-----------------------------------------------------------------------
1591 bool PagingLandScapeSceneManager::getOptionValues( const String & key, StringVector &refValueList )
{
// if ( key == "CurrentCameraPageX" )
// {
// refValueList.push_back( MemoryDataStreamPtr( ) );
// return true;
// }
// if ( key == "CurrentCameraPageZ" )
// {
// refValueList.push_back( MemoryDataStreamPtr( ) );
// return true;
// }
// if ( key == "MaxNumTiles" )
// {
// refValueList.push_back( MemoryDataStreamPtr( ) );
// return true;
// }
// if ( key == "TileFree" )
// {
// refValueList.push_back( MemoryDataStreamPtr( ) );
// return true;
// }
// if ( key == "MaxNumRenderables" )
// {
// refValueList.push_back( MemoryDataStreamPtr( ) );
// return true;
// }
// if ( key == "RenderableFree" )
// {
// refValueList.push_back( MemoryDataStreamPtr( ) );
// return true;
// }
// if ( key == "RenderableLoading" )
// {
// refValueList.push_back( MemoryDataStreamPtr( ) );
// return true;
// }
// if ( key == "PagePreloadQueue" )
// {
// refValueList.push_back( MemoryDataStreamPtr( ) );
// return true;
// }
// if ( key == "PageLoadQueue" )
// {
// refValueList.push_back( MemoryDataStreamPtr( ) );
// return true;
// }
// if ( key == "PageUnloadQueue" )
// {
// refValueList.push_back( MemoryDataStreamPtr( ) );
// return true;
// }
// if ( key == "PagePostUnloadQueue" )
// {
// refValueList.push_back( MemoryDataStreamPtr( ) );
// return true;
// }
if ( mOptions->getOptionValues( key, refValueList ) == false )
{
return PagingLandScapeOctreeSceneManager::getOptionValues ( key, refValueList );
}
return true;
}
//-----------------------------------------------------------------------
1657 bool PagingLandScapeSceneManager::getOptionKeys( StringVector &refKeys )
{
refKeys.clear( );
refKeys.push_back( "AddNewHeight" );
refKeys.push_back( "RemoveNewHeight" );
refKeys.push_back( "CurrentCameraPageX" );
refKeys.push_back( "CurrentCameraPageZ" );
refKeys.push_back( "MaxNumTiles" );
refKeys.push_back( "TileFree" );
refKeys.push_back( "MaxNumRenderables" );
refKeys.push_back( "RenderableFree" );
refKeys.push_back( "RenderableLoading" );
refKeys.push_back( "PagePreloadQueue" );
refKeys.push_back( "PageLoadQueue" );
refKeys.push_back( "PageUnloadQueue" );
refKeys.push_back( "PagePostUnloadQueue" );
mOptions->getOptionKeys( refKeys );
return PagingLandScapeOctreeSceneManager::getOptionKeys ( refKeys );
}
//-------------------------------------------------------------------------
1677 void PagingLandScapeSceneManager::setWorldGeometryRenderQueue ( uint8 qid )
{
PagingLandScapeOctreeSceneManager::setWorldGeometryRenderQueue( qid );
if ( mPageManager )
mPageManager->setWorldGeometryRenderQueue ( qid );
}
//-----------------------------------------------------------------------
1684 Camera * PagingLandScapeSceneManager::createCamera( const String &name )
{
if ( mCameras.find( name ) != mCameras.end( ) )
{
OGRE_EXCEPT(
Exception::ERR_DUPLICATE_ITEM,
"A camera with the name " + name + " already exists",
"PagingLandScapeSceneManager::createCamera" );
}
Camera * c = new PagingLandScapeCamera( name, this );
mCameras.insert( CameraList::value_type( name, c ) );
PagingLandScapeOctreeSceneManager::addCamera ( c );
// Check if we need to set the primaryCamera
if ( mOptions && !mOptions->primaryCamera )
{
mOptions->setPrimaryCamera ( static_cast <PagingLandScapeCamera*> ( c ) );
}
//default values
c->setNearClipDistance( 1 );
// Infinite far plane?
if ( Root::getSingleton( ).getRenderSystem( )->getCapabilities( )->hasCapability( RSC_INFINITE_FAR_PLANE ) )
{
c->setFarClipDistance( 0 );
}
else if ( mOptions )
{
float tmp;
getOption( "VisibleDistance", &tmp );
c->setFarClipDistance( tmp );
}
#ifdef PLSM2_EIHORT
// create visible bounds aab map entry
mCamVisibleObjectsMap[c] = VisibleObjectsBoundsInfo( );
#endif
return c;
}
//-----------------------------------------------------------------------
1722 void PagingLandScapeSceneManager::destroyCamera( Camera *cam )
{
if ( mOptions->primaryCamera && cam->getName( ) == mOptions->primaryCamera->getName( ) )
{
mOptions->setPrimaryCamera ( 0 );
}
PagingLandScapeOctreeSceneManager::destroyCamera( cam );
}
//-----------------------------------------------------------------------
1731 void PagingLandScapeSceneManager::destroyCamera( const String& name )
{
if ( mOptions->primaryCamera && name == mOptions->primaryCamera->getName( ) )
{
mOptions->setPrimaryCamera ( 0 );
}
PagingLandScapeOctreeSceneManager::destroyCamera( name );
}
//-----------------------------------------------------------------------
1740 void PagingLandScapeSceneManager::destroyAllCameras( void )
{
mOptions->setPrimaryCamera ( 0 );
PagingLandScapeOctreeSceneManager::destroyAllCameras( );
}
//-----------------------------------------------------------------------
void _OgrePagingLandScapeExport PagingLandScapeSceneManager::getWorldSize( Real *worldSizeX, Ogre::Real *worldSizeZ )
{
1748 *worldSizeX = mOptions->maxScaledX * 2.0f;
1749 *worldSizeZ = mOptions->maxScaledZ * 2.0f;
// *worldSizeX = ( float )mOptions->world_width * mOptions->scale.x;
// *worldSizeZ = ( float )mOptions->world_height * mOptions->scale.z;
}
//-----------------------------------------------------------------------
float _OgrePagingLandScapeExport PagingLandScapeSceneManager::getMaxSlope( Vector3 location1, Ogre::Vector3 location2, float maxSlopeIn )
{
return mData2DManager->getMaxSlope( location1, location2, maxSlopeIn );
}
//-----------------------------------------------------------------------
void PagingLandScapeSceneManager::renderBaseTextures( const String& alternateMatName )
{
//only currently works for PLSplattingShaderLit mode
//because I can't figure out how to elegantly handle all texture modes ( yet )
if( mOptions->textureFormat != "PLSplattingShaderLit" || alternateMatName != "PLSplattingShaderUnlit" )
{
OGRE_EXCEPT(
Exception::ERR_NOT_IMPLEMENTED,
"Only currently supports PLSplattingShaderLit texture mode and alternate material SplattingShader",
"PagingLandScapeSceneManager::renderBaseTextures" );
}
PagingLandScapeTexture* t = NULL;
String matName;
TexturePtr texture;
RenderTexture *renderTexture;
Camera *rttCam;
texture = TextureManager::getSingleton ( ).createManual( "PLRTTBaseTexture",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
TEX_TYPE_2D,
256,
256,
0,
PF_A8R8G8B8,
TU_RENDERTARGET );
renderTexture = texture->getBuffer( )->getRenderTarget( );
renderTexture->setAutoUpdated( false );
rttCam = createCamera( "PLRTTBaseTextureCam" );
rttCam->setNearClipDistance( 1.0f );
rttCam->setFarClipDistance( 0 );
rttCam->setPosition( Vector3( 0, 0, 2 ) );
rttCam->lookAt( Vector3( 0, 0, 0 ) );
Viewport* const v = renderTexture->addViewport( rttCam );
v->setClearEveryFrame( true );
v->setBackgroundColour( ColourValue( 0.0f, 0.0f, 0.0f, 0.0f ) );
//addSpecialCaseRenderQueue( Ogre::RENDER_QUEUE_6 );
//setSpecialCaseRenderQueueMode( Ogre::SceneManager::SCRQM_INCLUDE );
Rectangle2D* rect = new Rectangle2D( true );
rect->setBoundingBox( AxisAlignedBox( -100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE ) );
rect->setCorners( -1, 1, 1, -1 );
rect->setRenderQueueGroup( Ogre::RENDER_QUEUE_OVERLAY );
SceneNode* node = getRootSceneNode( )->createChildSceneNode( "PLBaseTextureRectNode" );
rect->setVisible( true );
node->attachObject( rect );
String textureName;
size_t strPos = 0;
MaterialPtr material;
MaterialPtr alternateMaterial;
//this->setAmbientLight( ColourValue::White );
for( uint x = 0; x < mOptions->world_width; ++x )
{
for( uint z = 0; z < mOptions->world_height; ++z )
{
t = mTextureManager->getTexture( x, z );
if( !t->isLoaded( ) )
t->load( x, z );
textureName = mOptions->LandScape_filename + ".Base." + StringConverter::toString( z ) + "." + StringConverter::toString( x ) + ".png";
matName = t->getMaterialName( );
//if an alternate material name is specified, we'll use the texture units from our original material
//and the passes from our new material
if( alternateMatName != "" )
{
alternateMaterial = MaterialManager::getSingleton( ).getByName( alternateMatName + "_Clone" );
if( alternateMaterial.isNull( ) )
{
alternateMaterial = MaterialManager::getSingleton( ).getByName( alternateMatName );
if( alternateMaterial.isNull( ) )
{
OGRE_EXCEPT(
Exception::ERR_ITEM_NOT_FOUND,
"Could not find alternate material " + alternateMatName,
"PagingLandScapeSceneManager::renderBaseTextures" );
}
alternateMaterial = alternateMaterial->clone( alternateMatName + "_Clone" );
}
matName = alternateMaterial->getName( );
material = t->getMaterial( );
//we know that pass 2 of PLSplattingShaderLitDecompress has our coverage and
//splatting textures in specific texture units
//I think if we want this to be completely generic we'll have to load the original
//texture mode's material, iterate through and find the "Coverage" and "Splatting" references from it,
//and do the same for alternate material, and attempt to hook them up the same
for( uint i = 0; i < 5; ++i )
{
alternateMaterial->getTechnique( 0 )->getPass( 0 )->getTextureUnitState( i )->setTextureName( material->getTechnique( 0 )->getPass( 1 )->getTextureUnitState( i )->getTextureName( ) );
}
}
//assign the material to the rectangle
rect->setMaterial( matName );
_updateSceneGraph( rttCam );
renderTexture->update( );
renderTexture->writeContentsToFile( "../../../Media/paginglandscape2/terrains/" + mOptions->LandScape_filename + "/" + textureName );
TexturePtr texture = TextureManager::getSingleton( ).getByName( textureName );
if( !texture.isNull( ) )
texture->reload( );
if( mOptions->VertexCompression )
{
MaterialManager::getSingleton( ).remove( material->getHandle( ) );
}
}
}
TextureManager::getSingleton( ).remove( texture->getHandle( ) );
destroyCamera( "PLRTTBaseTextureCam" );
node->detachObject( rect );
destroySceneNode( "PLBaseTextureRectNode" );
}
} //namespace
/***************************************************************************
OgrePagingLandScapeSceneManagerDll.cpp - description
-------------------
begin : Mon May 12 2003
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke2@supercable.es && tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreRoot.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeSceneManager.h"
namespace Ogre
{
PagingLandScapeSceneManagerFactory* PagingLandScapePlugin;
extern "C" void _OgrePagingLandScapeExport dllStartPlugin( void )
{
// Create new scene manager Factory
34 PagingLandScapePlugin = new PagingLandScapeSceneManagerFactory( );
// Register Factory
37 Root::getSingleton( ).addSceneManagerFactory( PagingLandScapePlugin );
}
extern "C" void _OgrePagingLandScapeExport dllShutdownPlugin( void )
{
Root::getSingleton( ).removeSceneManagerFactory( PagingLandScapePlugin );
}
extern "C" void _OgrePagingLandScapeExport dllStopPlugin( void )
{
delete PagingLandScapePlugin;
}
}
1 /***************************************************************************
OgrePagingLandScapeTexture.cpp - description
-------------------
begin : Fri Apr 16 2004
copyright : ( C ) 2003-2006 by Jose A Milan && Tuan Kuranes
email : spoke@supercable.es & tuan.kuranes@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* ( at your option ) any later version. *
* *
***************************************************************************/
#include "OgrePagingLandScapePrecompiledHeaders.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreStringConverter.h"
#include "OgreMaterialManager.h"
#include "OgreTextureManager.h"
#include "OgreTechnique.h"
#include "OgrePass.h"
#include "OgrePagingLandScapeTexture.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeSceneManager.h"
#include "OgrePagingLandScapeTextureManager.h"
#include "OgrePagingLandScapeData2DManager.h"
#include "OgrePagingLandScapeData2D.h"
#include "fileutils.h"
namespace Ogre
{
//-----------------------------------------------------------------------
42 PagingLandScapeTexture::PagingLandScapeTexture( PagingLandScapeTextureManager *textureMgr,
43 const String materialBaseName,
const unsigned int numTexture,
45 const bool isSplatMode ) :
mParent( textureMgr ),
mMaterialBaseName( materialBaseName ),
mIsLoaded ( false ),
mIsModified ( false ),
mDataX ( 0 ),
mDataZ ( 0 ),
mPaintRect ( 0, 0, 0, 0, 0, 1 ),
mIsPaintRectModified( false ),
mDeformRect ( 0, 0, 0, 0, 0, 1 ),
mIsDeformRectModified( false ),
mIsSplatMode( isSplatMode ),
mNumTexture( numTexture ),
mIsShadowed( false ),
mIsShaderShadowed( false ),
mIsBaseMode( false )
{
mMaterial.setNull( );
}
//-----------------------------------------------------------------------
65 PagingLandScapeTexture::~PagingLandScapeTexture( )
{
mNumChannelperTexture.clear( );
mImages.clear( );
mTextures.clear( );
mBuffers.clear( );
doTextureNeedUpdate.clear( );
isTextureModified.clear( );
}
//-----------------------------------------------------------------------
75 void PagingLandScapeTexture::setNumTexture( )
{
if ( mNumTexture > 0 )
{
mNumChannelperTexture.reserve( mNumTexture );
doTextureNeedUpdate.reserve( mNumTexture );
isTextureModified.reserve( mNumTexture );
mTextures.reserve( mNumTexture );
mBuffers.reserve( mNumTexture );
mImages.reserve( mNumTexture );
mNumChannelperTexture.resize( mNumTexture );
doTextureNeedUpdate.resize( mNumTexture );
isTextureModified.resize( mNumTexture );
mTextures.resize( mNumTexture );
mBuffers.resize( mNumTexture );
mImages.resize( mNumTexture );
for ( size_t i = 0; i < mNumTexture; i++ )
{
mImages[i].loadDynamicImage ( 0, 0, 0, 1, PF_R8G8B8A8, true, 1, 0 );
}
}
}
//-----------------------------------------------------------------------
103 const String &PagingLandScapeTexture::getMaterialName( )
{
return mMaterial->getName ( );
}
//-----------------------------------------------------------------------
108 void PagingLandScapeTexture::bindCompressionSettings( )
{
const PagingLandScapeOptions * const opt = mParent->getOptions( );
Material::TechniqueIterator tIt = mMaterial->getTechniqueIterator ( );
while ( tIt.hasMoreElements ( ) )
{
Technique * const t = tIt.getNext ( );
Technique::PassIterator pIt = t->getPassIterator ( );
while ( pIt.hasMoreElements ( ) )
{
Pass *p = pIt.getNext ( );
if ( p->hasVertexProgram ( ) )
{
// vertex compression setting
GpuProgramParametersSharedPtr params = p->getVertexProgramParameters( );
if ( opt->VertexCompression )
{
bindCompressionSettings ( params );
bindCompressionSettings ( p->getShadowReceiverVertexProgramParameters ( ) );
}
// splat settings.
#ifdef PLSM2_EIHORT
GpuConstantDefinition const * const e = params->_findNamedConstantDefinition( "splatSettings", false );
if ( e )
{
// use index to get RealConstantEntry
params->_writeRawConstant( e->physicalIndex + 0, opt->matHeight[1] );
params->_writeRawConstant( e->physicalIndex + 1, opt->matHeight[2] );
params->_writeRawConstant( e->physicalIndex + 2, float( opt->maxValue ) );
params->_writeRawConstant( e->physicalIndex + 3, 0.0f );
}
#else
GpuProgramParameters::RealConstantEntry * const e = params->getNamedRealConstantEntry ( "splatSettings" );
if ( e )
{
e->val[0] = static_cast <float> ( opt->matHeight[1] );
e->val[1] = static_cast <float> ( opt->matHeight[2] );
e->val[2] = static_cast <float> ( opt->maxValue );
e->val[3] = static_cast <float> ( 0.0 );
e->isSet = true;
}
#endif
}
}
}
}
//-----------------------------------------------------------------------
159 void PagingLandScapeTexture::bindCompressionSettings( GpuProgramParametersSharedPtr params )
{
GpuProgramParameters::AutoConstantIterator aci = params->getAutoConstantIterator( );
bool found = false;
while ( aci.hasMoreElements( ) )
{
const GpuProgramParameters::AutoConstantEntry& ace = aci.getNext( );
if ( ace.paramType == GpuProgramParameters::ACT_CUSTOM &&
ace.data == MORPH_CUSTOM_PARAM_ID )
{
found = true;
}
}
if ( !found )
{
params->setNamedAutoConstant( "compressionSettings",
GpuProgramParameters::ACT_CUSTOM, MORPH_CUSTOM_PARAM_ID );
}
}
//-----------------------------------------------------------------------
179 void PagingLandScapeTexture::loadTexturesToModify( )
{
if ( mNumTexture > 0 || ( mIsShadowed && !mIsShaderShadowed ) )
{
const String nameSep( "." );
const PagingLandScapeOptions * const opt = mParent->getOptions( );
const String filename ( opt->LandScape_filename );
const String commonName ( StringConverter::toString( mDataZ ) +
nameSep + StringConverter::toString( mDataX ) );
unsigned int channel = 0;
TextureManager* texMgr = TextureManager::getSingletonPtr( );
const unsigned short numLodLevels =
mMaterial->getNumLodLevels( MaterialManager::getSingleton( )._getActiveSchemeIndex( ) );
// some texture are shared between techniques, ensure it's loaded once.
bool imageLoaded = false;
bool baseLoaded = false;
bool coverageLoaded = false;
bool lightLoaded = false;
bool horizonLoaded = false;
for( unsigned short k = 0; k < numLodLevels; k++ )
{
Technique *t = mMaterial->getBestTechnique ( k );
Technique::PassIterator pIt = t->getPassIterator ( );
String texType;
channel = 0;
while ( pIt.hasMoreElements ( ) )
{
Pass *p = pIt.getNext ( );
Pass::TextureUnitStateIterator tuIt = p->getTextureUnitStateIterator ( );
while ( tuIt.hasMoreElements ( ) )
{
TextureUnitState *tu = tuIt.getNext ( );
const String texName ( tu->getTextureName( ) );
if ( !imageLoaded && opt->ImageNameLoad &&
StringUtil::startsWith ( texName, opt->image_filename ) )
{
// if it's an Image Texture mode
mTextures[channel] = texMgr->getByName ( texName );
assert ( !mTextures[channel].isNull( ) &&
String( texName + " is missing" ).c_str( ) );
mBuffers[channel] = mTextures[channel]->getBuffer( );
loadColorTexture ( texName, channel );
channel++;
imageLoaded = true;
}
else if ( StringUtil::startsWith ( texName, filename, false ) )
{
// if it's a dynamic texture updated by texture mode
// subtracts filename from texname
String texNameInfo = texName.substr ( filename.size ( ) );
//then split on Dot ( in case of filename with dot in it. )
const StringVector texNameInfos =
StringUtil::split( texNameInfo, nameSep );
texType = texNameInfos[0];
if ( texType == "Alpha" )
{
mTextures[channel] = texMgr->getByName ( texName );
assert ( !mTextures[channel].isNull( ) &&
String( texName + " is missing" ).c_str( ) );
mBuffers[channel] = mTextures[channel]->getBuffer( );
loadAlphaTexture ( texName, channel );
channel++;
}
else if ( texType == "Coverage" )
{
mTextures[channel] = texMgr->getByName ( texName );
assert ( !mTextures[channel].isNull( ) &&
String( texName + " is missing" ).c_str( ) );
mBuffers[channel] = mTextures[channel]->getBuffer( );
loadColorTexture ( texName, channel );
coverageLoaded = true;
channel++;
}
else if ( !lightLoaded && !mIsShaderShadowed
&& texType == "Light" )
{
mLightTexture = texMgr->getByName ( texName );
assert ( !mLightTexture.isNull( ) &&
String( texName + " is missing" ).c_str( ) );
mLightBuffer = mLightTexture->getBuffer( );
loadTexture ( texName, mLightImage );
assert ( mLightBuffer->getWidth ( ) == mLightImage.getWidth ( ) &&
mLightBuffer->getHeight ( ) == mLightImage.getHeight ( ) );
String shadowTexName ( filename + nameSep + "HS" );
for ( size_t k = 1; k < texNameInfos.size( ); k++ )
shadowTexName += nameSep + texNameInfos[k];
if ( ResourceGroupManager::getSingleton( ).
resourceExists ( opt->groupName, shadowTexName ) )
{
loadTexture ( shadowTexName, mShadow );
assert ( mShadow.getWidth ( ) == mLightImage.getWidth ( ) &&
mShadow.getHeight ( ) == mLightImage.getHeight ( ) );
lightUpdate ( );
}
else
{
mIsShadowed = false;
}
lightLoaded = true;
}
else if ( !coverageLoaded && !baseLoaded && texType == "Base" )
{
mTextures[channel] = texMgr->getByName ( texName );
assert ( !mTextures[channel].isNull( ) &&
String( texName + " is missing" ).c_str( ) );
mBuffers[channel] = mTextures[channel]->getBuffer( );
loadColorTexture ( texName, channel );
channel++;
baseLoaded = true;
}
}
}
}
for ( unsigned int i = 0; i < mNumTexture; i++ )
{
mNumChannelperTexture[i] = mImages[i].getBPP ( ) / 8;
doTextureNeedUpdate[i] = false;
isTextureModified[i] = false;
}
}
}
}
//-----------------------------------------------------------------------
309 void PagingLandScapeTexture::setOptions( void )
{
PagingLandScapeOptions * const opt = mParent->getOptions( );
String matClassName (
( opt->VertexCompression ?
String( mMaterialBaseName + "Decompress" )
:
mMaterialBaseName ) );
MaterialPtr material = MaterialManager::getSingleton( ).getByName ( matClassName );
if ( opt->VertexCompression && material.isNull( ) )
{
matClassName = mMaterialBaseName;
opt->VertexCompression = false;
opt->lodMorph = false;
material = MaterialManager::getSingleton( ).getByName ( matClassName );
}
assert ( !material.isNull( ) &&
String( matClassName + "Must exists in the" + opt->groupName + "group" ).c_str ( ) );
bool hasVertexProgram = false;
bool hasFragmentProgram = false;
Material::TechniqueIterator tIt = material->getTechniqueIterator ( );
while ( tIt.hasMoreElements ( ) )
{
Technique * const t = tIt.getNext ( );
Technique::PassIterator pIt = t->getPassIterator ( );
while ( pIt.hasMoreElements ( ) )
{
Pass * const p = pIt.getNext ( );
// vertex shaders.
if ( p->hasVertexProgram ( ) )
{
if ( hasVertexProgram == false )
{
hasVertexProgram = p->hasVertexProgram ( );
}
GpuProgramParametersSharedPtr params = p->getVertexProgramParameters( );
#ifdef PLSM2_EIHORT
GpuConstantDefinition const * const e = params->_findNamedConstantDefinition( "splatSettings" );
#else
GpuProgramParameters::RealConstantEntry * const e = params->getNamedRealConstantEntry ( "splatSettings" );
#endif
if ( e )
{
opt->normals = true;
}
}
// pixel shaders.
if ( hasFragmentProgram == false )
{
hasFragmentProgram = p->hasFragmentProgram ( );
}
}
}
if ( !hasVertexProgram )
{
opt->VertexCompression = false;
opt->lodMorph = false;
}
}
//-----------------------------------------------------------------------
375 bool PagingLandScapeTexture::isMaterialSupported( bool recursive )
{
const PagingLandScapeOptions * const opt = mParent->getOptions( );
if ( opt->VertexCompression && recursive )
{
const String MatClassName ( mMaterialBaseName );
mMaterialBaseName = mMaterialBaseName + "Decompress";
const bool isOk = MaterialManager::getSingleton ( ).resourceExists ( mMaterialBaseName ) &&
isMaterialSupported( false );
mMaterialBaseName = MatClassName;
if ( isOk )
return true;
}
MaterialPtr material = MaterialManager::getSingleton( ).getByName ( mMaterialBaseName );
assert ( !material.isNull( ) &&
String( mMaterialBaseName + " Must exists in the" + opt->groupName + "group" ).c_str ( ) );
unsigned short numPasses = 0;
//these will store the maximum number of texture units, alpha textures,
//coverage textures, etc. after iterating through all passes in the material
size_t numTextureUnits = 0;
size_t numAlphaTexture = 0;
size_t numCoverageTexture = 0;
size_t numSplats = 0;
unsigned int numDynamicTexture = 0;
//per pass count
size_t passNumTextureUnits;
size_t passNumAlphaTextures;
size_t passNumCoverageTextures;
size_t passNumSplats;
unsigned int passNumDynamicTextures;
bool needVertexProgram = false;
bool needFragmentProgram = false;
bool isImageMode = false;
bool isSplatMode = false;
bool isBaseMode = false;
Material::TechniqueIterator tIt = material->getTechniqueIterator ( );
while ( tIt.hasMoreElements ( ) )
{
Technique * const t = tIt.getNext ( );
numPasses = std::max ( numPasses, t->getNumPasses( ) );
Technique::PassIterator pIt = t->getPassIterator ( );
while ( pIt.hasMoreElements ( ) )
{
passNumTextureUnits = 0;
passNumAlphaTextures = 0;
passNumCoverageTextures = 0;
passNumSplats = 0;
passNumDynamicTextures = 0;
Pass * const p = pIt.getNext ( );
if ( needVertexProgram == false )
needVertexProgram = p->hasVertexProgram ( );
if ( needFragmentProgram == false )
needFragmentProgram = p->hasFragmentProgram ( );
#ifdef PLSM2_EIHORT
numTextureUnits = std::max<unsigned int>( static_cast<unsigned int>( numTextureUnits ), static_cast<unsigned int>( p->getNumTextureUnitStates( ) ) );
#else
numTextureUnits = std::max ( numTextureUnits, p->getNumTextureUnitStates( ) );
#endif
Pass::TextureUnitStateIterator tuIt = p->getTextureUnitStateIterator ( );
while ( tuIt.hasMoreElements ( ) )
{
TextureUnitState * const tu = tuIt.getNext ( );
const String texType ( tu->getTextureName( ) );
if ( std::string::npos == texType.find( "." ) )
{
// This Texture Name is A keyword,
// check how many are dynamic in this material
if ( !isBaseMode &&
StringUtil::startsWith ( texType, "base", true ) )
{
isBaseMode = true;
passNumDynamicTextures++;
}
else if ( !isImageMode &&
StringUtil::startsWith ( texType, "image", true ) )
{
isImageMode = true;
passNumDynamicTextures++;
}
else if ( texType == "Alpha" &&
StringUtil::startsWith ( texType, "alpha", true ) )
{
isSplatMode = true;
passNumAlphaTextures++;
passNumDynamicTextures++;
}
else if ( texType == "Coverage" &&
StringUtil::startsWith ( texType, "coverage", true ) )
{
isSplatMode = true;
passNumDynamicTextures++;
passNumCoverageTextures++;
}
else if ( texType == "Splatting" &&
StringUtil::startsWith ( texType, "splatting", true ) )
{
mIsSplatMode = true;
passNumSplats++;
}
else if ( texType == "Light" &&
StringUtil::startsWith ( texType, "light", true ) )
{
//dynamic light... but in software
mIsShadowed = true;
}
else if ( texType == "Horizon" &&
StringUtil::startsWith ( texType, "horizon", true ) )
{
//dynamic light... but shader
mIsShaderShadowed = true;
mIsShadowed = true;
}
}
}
if( passNumTextureUnits > numTextureUnits )
numTextureUnits = passNumTextureUnits;
numAlphaTexture += passNumAlphaTextures;
numCoverageTexture += passNumCoverageTextures;
numSplats += passNumSplats;
numDynamicTexture += passNumDynamicTextures;
}
}
if ( isImageMode && !opt->ImageNameLoad )
return false;
if ( opt->numTextureUnits < numTextureUnits )
return false;
if ( needVertexProgram && opt->hasVertexShader == false )
return false;
if ( needFragmentProgram && opt->hasFragmentShader == false )
return false;
if ( isSplatMode && numAlphaTexture && opt->NumMatHeightSplat < numAlphaTexture )
return false;
// does all coverage must be 4 alpha ?
//if ( isSplatMode && numCoverageTexture && opt->NumMatHeightSplat < numCoverageTexture * 4 )
// return false;
if ( isSplatMode && numCoverageTexture && opt->NumMatHeightSplat < 4 )
return false;
if ( mIsShaderShadowed && !opt->hasFragmentShader2 )
return false;
mIsSplatMode = isSplatMode;
mIsBaseMode = !mIsSplatMode && isBaseMode;
mNumTexture = ( mParent->getOptions( )->textureModifiable )? numDynamicTexture : 0;
return true;
}
//-----------------------------------------------------------------------
535 void PagingLandScapeTexture::_loadMaterial( )
{
if ( mMaterial.isNull( ) )
{
const PagingLandScapeOptions * const opt = mParent->getOptions( );
const String nameSep( "." );
const String commonName ( StringConverter::toString( mDataZ ) +
nameSep + StringConverter::toString( mDataX ) );
if ( opt->materialPerPage )
{
// JEFF - all material settings configured through material script
mMaterial = MaterialManager::getSingleton( ).getByName(
mMaterialBaseName + commonName );
}
else
{
const String filename ( opt->LandScape_filename );
const bool compressed = opt->VertexCompression;
const String MatClassName (
( compressed ?
String( mMaterialBaseName + "Decompress" )
:
mMaterialBaseName ) );
const String matname ( MatClassName + nameSep
+ commonName + nameSep
+ filename );
mMaterial = MaterialManager::getSingleton( ).getByName( matname );
if ( mMaterial.isNull( ) )
{
mMaterial = MaterialManager::getSingleton( ).getByName( MatClassName );
assert ( !mMaterial.isNull( ) &&
String( MatClassName + "Must exists in the" + opt->groupName + "group" ).c_str ( ) );
mMaterial = mMaterial->clone( matname );
const String extName ( opt->TextureExtension );
const String beginName ( filename + nameSep );
const String endName ( nameSep + commonName +
nameSep );
bool deformable;
String texName, finalTexName;
unsigned int channel = 0;
unsigned int splat = 0;
unsigned int alphachannel = 0;
unsigned int coveragechannel = 0;
Material::TechniqueIterator tIt = mMaterial->getTechniqueIterator ( );
while ( tIt.hasMoreElements ( ) )
{
splat = 0;
channel = 0;
coveragechannel = 0;
alphachannel = 0;
Technique * const t = tIt.getNext ( );
Technique::PassIterator pIt = t->getPassIterator ( );
while ( pIt.hasMoreElements ( ) )
{
Pass * const p = pIt.getNext ( );
Pass::TextureUnitStateIterator tuIt = p->getTextureUnitStateIterator ( );
while ( tuIt.hasMoreElements ( ) )
{
TextureUnitState * const tu = tuIt.getNext ( );
const String texType ( tu->getTextureName( ) );
if ( std::string::npos == texType.find( "." ) )
{
// This Texture Name is A keyword,
// meaning we have to dynamically replace it
deformable = false;
// check by what texture to replace keyword
if ( StringUtil::startsWith ( texType, "image", true ) )
{
texName = opt->image_filename + endName;
deformable = true;
}
else if ( StringUtil::startsWith ( texType, "splatting", true ) )
{
texName = opt->SplatDetailMapNames[splat % opt->NumMatHeightSplat];
splat++;
}
else if ( StringUtil::startsWith ( texType, "base", true ) )
{
texName = beginName + texType + endName;
channel++;
deformable = true;
}
else if ( StringUtil::startsWith ( texType, "alpha", true ) )
{
texName = beginName + texType + nameSep +
StringConverter::toString( alphachannel ) + endName;
deformable = true;
alphachannel++;
channel++;
}
else if ( StringUtil::startsWith ( texType, "coverage", true ) )
{
texName = beginName + texType + nameSep +
StringConverter::toString( ( coveragechannel * 4 ) % opt->NumMatHeightSplat ) + endName;
deformable = true;
channel++;
coveragechannel++;
}
else if ( StringUtil::startsWith ( texType, "light", true ) )
{
texName = beginName + texType + endName + extName;
}
else if ( StringUtil::startsWith ( texType, "horizon", true ) )
{
texName = beginName + "HSP" + endName + extName;
mPositiveShadow = true;
}
if ( deformable )
{
if( opt->Deformable &&
ResourceGroupManager::getSingleton( ).resourceExists(
opt->groupName,
texName + "modif." + extName ) )
{
finalTexName = texName + "modif." + extName;
}
else
{
finalTexName = texName + extName;
}
}
else
{
finalTexName = texName;
}
tu->setTextureName ( finalTexName );
}
}
}
}
}
}
}
}
//-----------------------------------------------------------------------
672 void PagingLandScapeTexture::_unloadMaterial( )
{
}
//-----------------------------------------------------------------------
678 void PagingLandScapeTexture::load( unsigned int x, unsigned int z )
{
if ( !mIsLoaded && isMaterialSupported( ) )
{
mDataX = x;
mDataZ = z;
updated( );
setNumTexture ( );
_loadMaterial( );
const PagingLandScapeOptions * const opt = mParent->getOptions( );
mMaterial->setLightingEnabled ( opt->lit );
mMaterial->setLodLevels ( opt->lodMaterialDistanceList );
mMaterial->setReceiveShadows ( true );
// If vertex shader, have to bind parameters
bindCompressionSettings ( );
mMaterial->load ( );
// load texture in main memory if we want to update it Real-Time
loadTexturesToModify( );
mIsLoaded = true;
mIsModified = false;
}
}
//-----------------------------------------------------------------------
702 void PagingLandScapeTexture::unload( )
{
if ( mIsLoaded )
{
if ( mIsModified && mParent->getOptions( )->saveDeformation )
_save( );
if ( !mMaterial.isNull( ) )
mMaterial->unload( );
for ( unsigned int i = 0; i < mNumTexture; i++ )
{
doTextureNeedUpdate[i] = false;
isTextureModified[i] = false;
mBuffers[i].setNull ( );
mTextures[i].setNull ( );
mImages[i].loadDynamicImage ( 0, 0, 0, 1, PF_R8G8B8A8, true, 1, 0 );
}
// Anyway, they're surely null already, as they're freed by delete page( )
_unloadMaterial( );
const String resourceName ( mMaterial->getName ( ) );
assert ( !mMaterial.isNull( ) && "PagingLandScapeTexture::unload" );
mMaterial->unload( );
mMaterial.setNull( );
MaterialManager::getSingleton( ).remove ( resourceName );
mIsLoaded = false;
}
}
//-----------------------------------------------------------------------
736 void PagingLandScapeTexture::_save( void )
{
assert ( !mMaterial.isNull( ) && "PagingLandScapeTexture::::_save" );
const PagingLandScapeOptions * const opt = mParent->getOptions( );
if ( mNumTexture > 0 && opt->textureModifiable )
{
const String extname ( opt->TextureExtension );
for ( unsigned int i = 0; i < mNumTexture; i++ )
{
if ( isTextureModified[i] )
{
String texName = mTextures[i]->getName ( );
FileInfoListPtr finfo = ResourceGroupManager::getSingleton( ).findResourceFileInfo (
opt->groupName, texName );
FileInfoList::iterator it = finfo->begin( );
if ( it != finfo->end( ) )
{
char *olddir = ChangeToDir ( const_cast< char * > ( ( ( it )->archive->getName( ) ).c_str( ) ) );
//FileSystemArchive::pushDirectory( )
assert ( mImages[i].getData ( ) );
// check if we have to add modif to the name.
const String baseTexName ( texName, 0, texName.size ( ) - extname.size( ) );
if ( !StringUtil::endsWith ( baseTexName, "modif." ) )
{
texName = baseTexName + "modif." + extname;
}
mImages[i].save ( texName );
RetablishDir ( olddir );
//FileSystemArchive::popDirectory( );
} // if ( it != finfo->end( ) )
} // if ( doTextureNeedUpdate[i] )
} // for ( unsigned int i = 0; i < mNumTexture; i++ )
}
}
//-----------------------------------------------------------------------
776 void PagingLandScapeTexture::upload( const Image::Box& textureRect )
{
assert ( mNumTexture > 0 );
&nb