<commit_before>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "Foundation.h"
#include "OgreRenderingModule.h"
#include "Renderer.h"
#include "EC_OgrePlaceable.h"
#include "EC_OgreEnvironment.h"
#include "OgreConversionUtils.h"

// Ogre include
#include <Ogre.h>

// Caelum include
#include "Caelum.h"

namespace OgreRenderer
{

EC_OgreEnvironment::EC_OgreEnvironment(Foundation::ModuleInterface* module) :
    Foundation::ComponentInterface(module->GetFramework()),
    renderer_(checked_static_cast<OgreRenderingModule*>(module)->GetRenderer()),
    sunlight_(NULL),
    caelumSystem_(NULL),
    cameraUnderWater_(false),
    attached_(false),
    useCaelum_(true),
    sunColorMultiplier_(0.5)
{
    if (useCaelum_)
        InitCaelum();
    else
        CreateSunlight();

    InitShadows();
}

EC_OgreEnvironment::~EC_OgreEnvironment()
{
    SetBackgoundColor(Core::Color(0, 0, 0));
    DisableFog();

    if (sunlight_)
    {
        DetachSunlight();
        Ogre::SceneManager *sceneManager = renderer_->GetSceneManager();
        sceneManager->destroyLight(sunlight_);
        sunlight_ = NULL;
    }

    if (useCaelum_)
        ShutdownCaelum();
}

void EC_OgreEnvironment::SetPlaceable(Foundation::ComponentPtr placeable)
{
    DetachSunlight();
    placeable_ = placeable;
    AttachSunlight();
}

void EC_OgreEnvironment::SetBackgoundColor(const Core::Color &color)
{
    renderer_->GetCurrentCamera()->getViewport()->setBackgroundColour(ToOgreColor(color));
}

Core::Color EC_OgreEnvironment::GetBackgoundColor() const
{
    return ToCoreColor(renderer_->GetCurrentCamera()->getViewport()->getBackgroundColour());
}

void EC_OgreEnvironment::SetAmbientLightColor(const Core::Color &color)
{
    Ogre::SceneManager* sceneManager = renderer_->GetSceneManager();
    sceneManager->setAmbientLight(ToOgreColor(color));
}

Core::Color EC_OgreEnvironment::GetAmbientLightColor() const
{
    Ogre::SceneManager *sceneManager = renderer_->GetSceneManager();
    return ToCoreColor(sceneManager->getAmbientLight());
}

void EC_OgreEnvironment::SetSunColor(const Core::Color& color)
{
    sunlight_->setDiffuseColour(ToOgreColor(color));
}

void EC_OgreEnvironment::SetSunDirection(const Core::Vector3df& direction)
{
    sunlight_->setDirection(ToOgreVector3(direction));
}

void EC_OgreEnvironment::SetSunCastShadows(const bool &enabled)
{
    sunlight_->setCastShadows(enabled);
}

void EC_OgreEnvironment::SetTime(time_t time)
{
    assert(time);
    tm *ptm = gmtime(&time);

    // Calculate the time zone difference for hours and minutes.
    Poco::LocalDateTime *mytime = new Poco::LocalDateTime();
    int hour_diff = mytime->hour() - ptm->tm_hour;
    int min_diff = mytime->minute() - ptm->tm_min;
    SAFE_DELETE(mytime);

    if (useCaelum_)
    {
        caelumSystem_->getUniversalClock()->setGregorianDateTime(
            1900 + ptm->tm_year, 1 + ptm->tm_mon, ptm->tm_mday, ptm->tm_hour + hour_diff,
            ptm->tm_min + min_diff, ptm->tm_sec);

        SetTimeScale(1000);
    }
}

void EC_OgreEnvironment::UpdateVisualEffects(Core::f64 frametime)
{
    ///\todo Make this prettier (local -> member variables) when the right values are found.
    float fogStart(10.0f);
    float fogEnd(300.0f);
    float waterFogStart(1.0f);
    float waterFogEnd(50.0f);
    Ogre::ColourValue fogColor;
    Ogre::ColourValue waterFogColor(0.2, 0.4, 0.35);
    float cameraNearClip(0.5f);
    float cameraFarClip(500.0f);

    if (useCaelum_)
    {
        // Set sunlight attenuation using ambient multiplier.
        // Seems to be working ok, but feel free to fix if you find better logic and/or values.
        Ogre::ColourValue ambientMultiplier(sunColorMultiplier_, sunColorMultiplier_, sunColorMultiplier_, 1);
        caelumSystem_->getSun()->setAmbientMultiplier(ambientMultiplier);

        float sunDirZaxis = caelumSystem_->getSun()->getMainLight()->getDirection().z;
        if (sunDirZaxis > -0.1f)
        {
            sunColorMultiplier_ -= 0.002f;
            if (sunColorMultiplier_ <= 0.f)
                sunColorMultiplier_ = 0.f;
        }
        else if(sunDirZaxis < 0.2)
        {
            sunColorMultiplier_ += 0.005f;
            if (sunColorMultiplier_ >= 0.5f)
                sunColorMultiplier_ = 0.5f;
        }

        // Get the sky/sunlight and fog colors from Caelum.
        float julDay = caelumSystem_->getUniversalClock()->getJulianDay();
        float relDayTime = fmod(julDay, 1);
        Ogre::Vector3 sunDir = caelumSystem_->getSunDirection(julDay);
        fogColor = caelumSystem_->getGroundFog()->getColour();

        // Hide sun and moon sprites when they're below the water line (direction.z > ~0.10f).
        // Also disable the corresponding lights.
        ///\note Disabled for now. Seems to ok without this.
/*      if (caelumSystem_->getSun() > 0.10f)
            caelumSystem_->getSun()->setForceDisable(true);
        else
            caelumSystem_->getSun()->setForceDisable(false);*/

        /*if (caelumSystem_->getMoon()->getMainLight()->getDirection().z > 0.10f)
            caelumSystem_->getMoon()->setForceDisable(true);
        else
            caelumSystem_->getMoon()->setForceDisable(false);
*/
    }

    // Set fogging
    Ogre::Camera *camera = renderer_->GetCurrentCamera();
    Ogre::SceneManager *sceneManager = renderer_->GetSceneManager();
    Ogre::Entity *water = sceneManager->getEntity("WaterEntity");

    if (!water)
    {
        // No water entity. ///\todo Test.
        sceneManager->setFog(Ogre::FOG_LINEAR, fogColor, 0.001, fogStart, fogEnd);
        camera->getViewport()->setBackgroundColour(fogColor);
        camera->setFarClipDistance(cameraFarClip);
    }
    else if(camera->getPosition().z >= water->getParentNode()->getPosition().z)
    {
        // We're above the water.
        if (useCaelum_)
        {
            caelumSystem_->forceSubcomponentVisibilityFlags(Caelum::CaelumSystem::CAELUM_COMPONENTS_ALL);
            caelumSystem_->getCloudSystem()->forceLayerVisibilityFlags(0);
        }

        sceneManager->setFog(Ogre::FOG_LINEAR, fogColor, 0.001, fogStart, fogEnd);
        camera->getViewport()->setBackgroundColour(fogColor);
        camera->setFarClipDistance(cameraFarClip);
        cameraUnderWater_ = false;
    }
    else
    {
        // We're below the water.
        // Hide the Caleum subsystems.
        if (useCaelum_)
            caelumSystem_->forceSubcomponentVisibilityFlags(Caelum::CaelumSystem::CAELUM_COMPONENTS_NONE);

        sceneManager->setFog(Ogre::FOG_LINEAR, fogColor * waterFogColor, 0.001, waterFogStart, waterFogEnd);
        camera->getViewport()->setBackgroundColour(fogColor * waterFogColor);
        camera->setFarClipDistance(waterFogEnd + 10.f);
        cameraUnderWater_ = true;
    }

    if (useCaelum_)
    {
        // Force hiding of Caelum clouds, else shadows get messed up.
        caelumSystem_->getCloudSystem()->forceLayerVisibilityFlags(0);

        // Disable moon light.
        caelumSystem_->getMoon()->setForceDisable(true);

        // Update Caelum system.
        caelumSystem_->notifyCameraChanged(camera);
        caelumSystem_->updateSubcomponents(frametime);
    }
}

void EC_OgreEnvironment::DisableFog()
{
    Ogre::SceneManager *sceneManager = renderer_->GetSceneManager();
    sceneManager->setFog(Ogre::FOG_NONE);
}

void EC_OgreEnvironment::SetTimeScale(float value)
{
    if (useCaelum_)
        caelumSystem_->getUniversalClock()->setTimeScale(value);
}

void EC_OgreEnvironment::CreateSunlight()
{
    Ogre::SceneManager* sceneManager = renderer_->GetSceneManager();
    sunlight_ = sceneManager->createLight(renderer_->GetUniqueObjectName());
    sunlight_->setType(Ogre::Light::LT_DIRECTIONAL);
    ///\todo Read parameters from config file?
    sunlight_->setDiffuseColour(0.93f, 1, 0.13f);
    sunlight_->setDirection(-1, -1, -1);
    sunlight_->setCastShadows(true);
    SetAmbientLightColor(Core::Color(0.5, 0.5, 0.5, 1));
}

void EC_OgreEnvironment::AttachSunlight()
{
    if ((placeable_) && (!attached_))
    {
        EC_OgrePlaceable* placeable = checked_static_cast<EC_OgrePlaceable*>(placeable_.get());
        Ogre::SceneNode* node = placeable->GetSceneNode();
        node->attachObject(sunlight_);
        attached_ = true;
    }
}

void EC_OgreEnvironment::DetachSunlight()
{
    if ((placeable_) && (attached_))
    {
        EC_OgrePlaceable* placeable = checked_static_cast<EC_OgrePlaceable*>(placeable_.get());
        Ogre::SceneNode* node = placeable->GetSceneNode();
        node->detachObject(sunlight_);
        attached_ = false;
    }
}

void EC_OgreEnvironment::InitCaelum()
{
    caelumSystem_ = new Caelum::CaelumSystem(renderer_->GetRoot().get(),
        renderer_->GetSceneManager(), Caelum::CaelumSystem::CAELUM_COMPONENTS_ALL);

    // Flip the Caelum camera and ground node orientations 90 degrees.
    Ogre::Quaternion orientation(Ogre::Degree(90), Ogre::Vector3(1, 0, 0));
    caelumSystem_->getCaelumCameraNode()->setOrientation(orientation);
    caelumSystem_->getCaelumGroundNode()->setOrientation(orientation);

    // We want to manage the fog ourself.
    caelumSystem_->setManageSceneFog(false);

    // Use just one light (the brightest one) at a time.
    caelumSystem_->setEnsureSingleLightSource(true);
    caelumSystem_->setEnsureSingleShadowSource(true);
}

void EC_OgreEnvironment::ShutdownCaelum()
{
    if (caelumSystem_)
        caelumSystem_->shutdown(true);
}

void EC_OgreEnvironment::InitShadows()
{
    float shadowFarDist = 50;
    unsigned short shadowTextureSize = 2048;
    size_t shadowTextureCount = 1;
    Ogre::ColourValue shadowColor(0.6f, 0.6f, 0.6f);

    // This is the default material to use for shadow buffer rendering pass, overridable in script.
    // Note that we use the same single material (vertex program) for each object, so we're relying on
    // that we use Ogre software skinning. Hardware skinning would require us to do different vertex programs
    // for skinned/nonskinned geometry.
    std::string ogreShadowCasterMaterial = "rex/ShadowCaster";

    Ogre::SceneManager* sceneManager = renderer_->GetSceneManager();
    sceneManager->setShadowColour(shadowColor);
    sceneManager->setShadowFarDistance(shadowFarDist);

    sceneManager->setShadowTextureSize(shadowTextureSize);
    sceneManager->setShadowTextureCount(shadowTextureCount);

    sceneManager->setShadowTexturePixelFormat(Ogre::PF_FLOAT16_R);
    sceneManager->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_ADDITIVE_INTEGRATED);
    sceneManager->setShadowTextureCasterMaterial(ogreShadowCasterMaterial.c_str());
    sceneManager->setShadowTextureSelfShadow(true);

    Ogre::ShadowCameraSetupPtr shadowCameraSetup = Ogre::ShadowCameraSetupPtr(new Ogre::FocusedShadowCameraSetup());
    sceneManager->setShadowCameraSetup(shadowCameraSetup);

    // If set to true, problems with objects that clip into the ground
    sceneManager->setShadowCasterRenderBackFaces(false);
}

}
<commit_msg>Another tweak to Caelum. Using setDiffuseMultiplier instead of setAmbientMultiplier and enabled moon light (was disabled in last commit).<commit_after>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "Foundation.h"
#include "OgreRenderingModule.h"
#include "Renderer.h"
#include "EC_OgrePlaceable.h"
#include "EC_OgreEnvironment.h"
#include "OgreConversionUtils.h"

// Ogre include
#include <Ogre.h>

// Caelum include
#include "Caelum.h"

namespace OgreRenderer
{

EC_OgreEnvironment::EC_OgreEnvironment(Foundation::ModuleInterface* module) :
    Foundation::ComponentInterface(module->GetFramework()),
    renderer_(checked_static_cast<OgreRenderingModule*>(module)->GetRenderer()),
    sunlight_(NULL),
    caelumSystem_(NULL),
    cameraUnderWater_(false),
    attached_(false),
    useCaelum_(true),
    sunColorMultiplier_(2.f)
{
    if (useCaelum_)
        InitCaelum();
    else
        CreateSunlight();

    InitShadows();
}

EC_OgreEnvironment::~EC_OgreEnvironment()
{
    SetBackgoundColor(Core::Color(0, 0, 0));
    DisableFog();

    if (sunlight_)
    {
        DetachSunlight();
        Ogre::SceneManager *sceneManager = renderer_->GetSceneManager();
        sceneManager->destroyLight(sunlight_);
        sunlight_ = NULL;
    }

    if (useCaelum_)
        ShutdownCaelum();
}

void EC_OgreEnvironment::SetPlaceable(Foundation::ComponentPtr placeable)
{
    DetachSunlight();
    placeable_ = placeable;
    AttachSunlight();
}

void EC_OgreEnvironment::SetBackgoundColor(const Core::Color &color)
{
    renderer_->GetCurrentCamera()->getViewport()->setBackgroundColour(ToOgreColor(color));
}

Core::Color EC_OgreEnvironment::GetBackgoundColor() const
{
    return ToCoreColor(renderer_->GetCurrentCamera()->getViewport()->getBackgroundColour());
}

void EC_OgreEnvironment::SetAmbientLightColor(const Core::Color &color)
{
    Ogre::SceneManager* sceneManager = renderer_->GetSceneManager();
    sceneManager->setAmbientLight(ToOgreColor(color));
}

Core::Color EC_OgreEnvironment::GetAmbientLightColor() const
{
    Ogre::SceneManager *sceneManager = renderer_->GetSceneManager();
    return ToCoreColor(sceneManager->getAmbientLight());
}

void EC_OgreEnvironment::SetSunColor(const Core::Color& color)
{
    sunlight_->setDiffuseColour(ToOgreColor(color));
}

void EC_OgreEnvironment::SetSunDirection(const Core::Vector3df& direction)
{
    sunlight_->setDirection(ToOgreVector3(direction));
}

void EC_OgreEnvironment::SetSunCastShadows(const bool &enabled)
{
    sunlight_->setCastShadows(enabled);
}

void EC_OgreEnvironment::SetTime(time_t time)
{
    assert(time);
    tm *ptm = gmtime(&time);

    // Calculate the time zone difference for hours and minutes.
    Poco::LocalDateTime *mytime = new Poco::LocalDateTime();
    int hour_diff = mytime->hour() - ptm->tm_hour;
    int min_diff = mytime->minute() - ptm->tm_min;
    SAFE_DELETE(mytime);

    if (useCaelum_)
    {
        caelumSystem_->getUniversalClock()->setGregorianDateTime(
            1900 + ptm->tm_year, 1 + ptm->tm_mon, ptm->tm_mday, ptm->tm_hour + hour_diff,
            ptm->tm_min + min_diff, ptm->tm_sec);

        SetTimeScale(1000);
    }
}

void EC_OgreEnvironment::UpdateVisualEffects(Core::f64 frametime)
{
    ///\todo Make this prettier (local -> member variables) when the right values are found.
    float fogStart(10.0f);
    float fogEnd(300.0f);
    float waterFogStart(1.0f);
    float waterFogEnd(50.0f);
    Ogre::ColourValue fogColor;
    Ogre::ColourValue waterFogColor(0.2, 0.4, 0.35);
    float cameraNearClip(0.5f);
    float cameraFarClip(500.0f);

    if (useCaelum_)
    {
        // Set sunlight attenuation using ambient multiplier.
        // Seems to be working ok, but feel free to fix if you find better logic and/or values.
        Ogre::ColourValue diffuseMultiplier(sunColorMultiplier_, sunColorMultiplier_, sunColorMultiplier_, 1);
        caelumSystem_->getSun()->setDiffuseMultiplier(diffuseMultiplier);

        float sunDirZaxis = caelumSystem_->getSun()->getMainLight()->getDirection().z;
        if (sunDirZaxis > 0)
        {
            sunColorMultiplier_ -= 0.005f;
            if (sunColorMultiplier_ <= 0.05f)
                sunColorMultiplier_ = 0.05f;
        }
        else if(sunDirZaxis < 0)
        {
            sunColorMultiplier_ += 0.010f;
            if (sunColorMultiplier_ >= 2.f)
                sunColorMultiplier_ = 2.f;
        }

        // Get the sky/sunlight and fog colors from Caelum.
        float julDay = caelumSystem_->getUniversalClock()->getJulianDay();
        float relDayTime = fmod(julDay, 1);
        Ogre::Vector3 sunDir = caelumSystem_->getSunDirection(julDay);
        fogColor = caelumSystem_->getGroundFog()->getColour();

        // Hide sun and moon sprites when they're below the water line (direction.z > ~0.10f).
        // Also disable the corresponding lights.
        ///\note Disabled for now. Seems to ok without this.
/*      if (caelumSystem_->getSun() > 0.10f)
            caelumSystem_->getSun()->setForceDisable(true);
        else
            caelumSystem_->getSun()->setForceDisable(false);*/

        /*if (caelumSystem_->getMoon()->getMainLight()->getDirection().z > 0.10f)
            caelumSystem_->getMoon()->setForceDisable(true);
        else
            caelumSystem_->getMoon()->setForceDisable(false);
*/
    }

    // Set fogging
    Ogre::Camera *camera = renderer_->GetCurrentCamera();
    Ogre::SceneManager *sceneManager = renderer_->GetSceneManager();
    Ogre::Entity *water = sceneManager->getEntity("WaterEntity");

    if (!water)
    {
        // No water entity. ///\todo Test.
        sceneManager->setFog(Ogre::FOG_LINEAR, fogColor, 0.001, fogStart, fogEnd);
        camera->getViewport()->setBackgroundColour(fogColor);
        camera->setFarClipDistance(cameraFarClip);
    }
    else if(camera->getPosition().z >= water->getParentNode()->getPosition().z)
    {
        // We're above the water.
        if (useCaelum_)
        {
            caelumSystem_->forceSubcomponentVisibilityFlags(Caelum::CaelumSystem::CAELUM_COMPONENTS_ALL);
            caelumSystem_->getCloudSystem()->forceLayerVisibilityFlags(0);
        }

        sceneManager->setFog(Ogre::FOG_LINEAR, fogColor, 0.001, fogStart, fogEnd);
        camera->getViewport()->setBackgroundColour(fogColor);
        camera->setFarClipDistance(cameraFarClip);
        cameraUnderWater_ = false;
    }
    else
    {
        // We're below the water.
        // Hide the Caleum subsystems.
        if (useCaelum_)
            caelumSystem_->forceSubcomponentVisibilityFlags(Caelum::CaelumSystem::CAELUM_COMPONENTS_NONE);

        sceneManager->setFog(Ogre::FOG_LINEAR, fogColor * waterFogColor, 0.001, waterFogStart, waterFogEnd);
        camera->getViewport()->setBackgroundColour(fogColor * waterFogColor);
        camera->setFarClipDistance(waterFogEnd + 10.f);
        cameraUnderWater_ = true;
    }

    if (useCaelum_)
    {
        // Force hiding of Caelum clouds, else shadows get messed up.
        caelumSystem_->getCloudSystem()->forceLayerVisibilityFlags(0);

        // Update Caelum system.
        caelumSystem_->notifyCameraChanged(camera);
        caelumSystem_->updateSubcomponents(frametime);
    }
}

void EC_OgreEnvironment::DisableFog()
{
    Ogre::SceneManager *sceneManager = renderer_->GetSceneManager();
    sceneManager->setFog(Ogre::FOG_NONE);
}

void EC_OgreEnvironment::SetTimeScale(float value)
{
    if (useCaelum_)
        caelumSystem_->getUniversalClock()->setTimeScale(value);
}

void EC_OgreEnvironment::CreateSunlight()
{
    Ogre::SceneManager* sceneManager = renderer_->GetSceneManager();
    sunlight_ = sceneManager->createLight(renderer_->GetUniqueObjectName());
    sunlight_->setType(Ogre::Light::LT_DIRECTIONAL);
    ///\todo Read parameters from config file?
    sunlight_->setDiffuseColour(0.93f, 1, 0.13f);
    sunlight_->setDirection(-1, -1, -1);
    sunlight_->setCastShadows(true);
    SetAmbientLightColor(Core::Color(0.5, 0.5, 0.5, 1));
}

void EC_OgreEnvironment::AttachSunlight()
{
    if ((placeable_) && (!attached_))
    {
        EC_OgrePlaceable* placeable = checked_static_cast<EC_OgrePlaceable*>(placeable_.get());
        Ogre::SceneNode* node = placeable->GetSceneNode();
        node->attachObject(sunlight_);
        attached_ = true;
    }
}

void EC_OgreEnvironment::DetachSunlight()
{
    if ((placeable_) && (attached_))
    {
        EC_OgrePlaceable* placeable = checked_static_cast<EC_OgrePlaceable*>(placeable_.get());
        Ogre::SceneNode* node = placeable->GetSceneNode();
        node->detachObject(sunlight_);
        attached_ = false;
    }
}

void EC_OgreEnvironment::InitCaelum()
{
    caelumSystem_ = new Caelum::CaelumSystem(renderer_->GetRoot().get(),
        renderer_->GetSceneManager(), Caelum::CaelumSystem::CAELUM_COMPONENTS_ALL);

    // Flip the Caelum camera and ground node orientations 90 degrees.
    Ogre::Quaternion orientation(Ogre::Degree(90), Ogre::Vector3(1, 0, 0));
    caelumSystem_->getCaelumCameraNode()->setOrientation(orientation);
    caelumSystem_->getCaelumGroundNode()->setOrientation(orientation);

    // We want to manage the fog ourself.
    caelumSystem_->setManageSceneFog(false);

    // Use just one light (the brightest one) at a time.
    caelumSystem_->setEnsureSingleLightSource(true);
    caelumSystem_->setEnsureSingleShadowSource(true);

    caelumSystem_->getMoon()->setDiffuseMultiplier(Ogre::ColourValue(0.25f, 0.25f, 0.25f));
}

void EC_OgreEnvironment::ShutdownCaelum()
{
    if (caelumSystem_)
        caelumSystem_->shutdown(true);
}

void EC_OgreEnvironment::InitShadows()
{
    float shadowFarDist = 50;
    unsigned short shadowTextureSize = 2048;
    size_t shadowTextureCount = 1;
    Ogre::ColourValue shadowColor(0.6f, 0.6f, 0.6f);

    // This is the default material to use for shadow buffer rendering pass, overridable in script.
    // Note that we use the same single material (vertex program) for each object, so we're relying on
    // that we use Ogre software skinning. Hardware skinning would require us to do different vertex programs
    // for skinned/nonskinned geometry.
    std::string ogreShadowCasterMaterial = "rex/ShadowCaster";

    Ogre::SceneManager* sceneManager = renderer_->GetSceneManager();
    sceneManager->setShadowColour(shadowColor);
    sceneManager->setShadowFarDistance(shadowFarDist);

    sceneManager->setShadowTextureSize(shadowTextureSize);
    sceneManager->setShadowTextureCount(shadowTextureCount);

    sceneManager->setShadowTexturePixelFormat(Ogre::PF_FLOAT16_R);
    sceneManager->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_ADDITIVE_INTEGRATED);
    sceneManager->setShadowTextureCasterMaterial(ogreShadowCasterMaterial.c_str());
    sceneManager->setShadowTextureSelfShadow(true);

    Ogre::ShadowCameraSetupPtr shadowCameraSetup = Ogre::ShadowCameraSetupPtr(new Ogre::FocusedShadowCameraSetup());
    sceneManager->setShadowCameraSetup(shadowCameraSetup);

    // If set to true, problems with objects that clip into the ground
    sceneManager->setShadowCasterRenderBackFaces(false);
}

}
<|endoftext|>


<commit_before>//
//  ScanTargetVertexArrayAttributs.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 11/11/2018.
//  Copyright © 2018 Thomas Harte. All rights reserved.
//

#include "ScanTarget.hpp"

using namespace Outputs::Display::OpenGL;

std::string ScanTarget::globals(ShaderType type) {
	switch(type) {
		case ShaderType::Scan:
		return
			"#version 150\n"

			"uniform vec2 scale;"
			"uniform float rowHeight;"
			"uniform mat3 lumaChromaToRGB;"
			"uniform mat3 rgbToLumaChroma;"

			"in vec2 startPoint;"
			"in float startDataX;"
			"in float startCompositeAngle;"

			"in vec2 endPoint;"
			"in float endDataX;"
			"in float endCompositeAngle;"

			"in float dataY;"
			"in float lineY;"

			"void main(void) {"
				"float lateral = float(gl_VertexID & 1);"
				"float longitudinal = float((gl_VertexID & 2) >> 1);"

				"vec2 centrePoint = mix(startPoint, endPoint, lateral) / scale;"
				"vec2 height = normalize(endPoint - startPoint).yx * (longitudinal - 0.5) * rowHeight;"
				"gl_Position = vec4(centrePoint + height, 0.0, 1.0);"
			"}";

		case ShaderType::Line:
		return
			"#version 150\n"

			"in vec2 startPoint;"
			"in vec2 endPoint;";
	}
}

void ScanTarget::enable_vertex_attributes(ShaderType type, Shader &target) {
	switch(type) {
		case ShaderType::Scan:
			for(int c = 0; c < 2; ++c) {
				const std::string prefix = c ? "end" : "start";

				target.enable_vertex_attribute_with_pointer(
					prefix + "Point",
					2, GL_UNSIGNED_SHORT, GL_FALSE,
					sizeof(Scan),
					reinterpret_cast<void *>(offsetof(Scan, scan.end_points[c].x)),
					1);
				target.enable_vertex_attribute_with_pointer(
					prefix + "DataX",
					1, GL_UNSIGNED_SHORT, GL_FALSE,
					sizeof(Scan),
					reinterpret_cast<void *>(offsetof(Scan, scan.end_points[c].data_offset)),
					1);
				target.enable_vertex_attribute_with_pointer(
					prefix + "CompositeAngle",
					1, GL_UNSIGNED_SHORT, GL_FALSE,
					sizeof(Scan),
					reinterpret_cast<void *>(offsetof(Scan, scan.end_points[c].composite_angle)),
					1);
			}

			target.enable_vertex_attribute_with_pointer(
				"dataY",
				1, GL_UNSIGNED_SHORT, GL_FALSE,
				sizeof(Scan),
				reinterpret_cast<void *>(offsetof(Scan, data_y)),
				1);
			target.enable_vertex_attribute_with_pointer(
				"lineY",
				1, GL_UNSIGNED_SHORT, GL_FALSE,
				sizeof(Scan),
				reinterpret_cast<void *>(offsetof(Scan, line)),
				1);
		break;

		case ShaderType::Line:
			for(int c = 0; c < 2; ++c) {
				const std::string prefix = c ? "end" : "start";

				target.enable_vertex_attribute_with_pointer(
					prefix + "Point",
					2, GL_UNSIGNED_SHORT, GL_FALSE,
					sizeof(Line),
					reinterpret_cast<void *>(offsetof(Line, end_points[c].x)),
					1);
			}
		break;
	}
}
<commit_msg>Flips and properly sizes output scans.<commit_after>//
//  ScanTargetVertexArrayAttributs.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 11/11/2018.
//  Copyright © 2018 Thomas Harte. All rights reserved.
//

#include "ScanTarget.hpp"

using namespace Outputs::Display::OpenGL;

std::string ScanTarget::globals(ShaderType type) {
	switch(type) {
		case ShaderType::Scan:
		return
			"#version 150\n"

			"uniform vec2 scale;"
			"uniform float rowHeight;"
			"uniform mat3 lumaChromaToRGB;"
			"uniform mat3 rgbToLumaChroma;"

			"in vec2 startPoint;"
			"in float startDataX;"
			"in float startCompositeAngle;"

			"in vec2 endPoint;"
			"in float endDataX;"
			"in float endCompositeAngle;"

			"in float dataY;"
			"in float lineY;"

			"void main(void) {"
				"float lateral = float(gl_VertexID & 1);"
				"float longitudinal = float((gl_VertexID & 2) >> 1);"

				"vec2 centrePoint = mix(startPoint, endPoint, lateral) / scale;"
				"vec2 height = normalize(endPoint - startPoint).yx * (longitudinal - 0.5) * rowHeight;"
				"vec2 eyePosition = vec2(1.0) - 2.0 * (centrePoint + height);"
				"gl_Position = vec4(eyePosition, 0.0, 1.0);"
			"}";

		case ShaderType::Line:
		return
			"#version 150\n"

			"in vec2 startPoint;"
			"in vec2 endPoint;";
	}
}

void ScanTarget::enable_vertex_attributes(ShaderType type, Shader &target) {
	switch(type) {
		case ShaderType::Scan:
			for(int c = 0; c < 2; ++c) {
				const std::string prefix = c ? "end" : "start";

				target.enable_vertex_attribute_with_pointer(
					prefix + "Point",
					2, GL_UNSIGNED_SHORT, GL_FALSE,
					sizeof(Scan),
					reinterpret_cast<void *>(offsetof(Scan, scan.end_points[c].x)),
					1);
				target.enable_vertex_attribute_with_pointer(
					prefix + "DataX",
					1, GL_UNSIGNED_SHORT, GL_FALSE,
					sizeof(Scan),
					reinterpret_cast<void *>(offsetof(Scan, scan.end_points[c].data_offset)),
					1);
				target.enable_vertex_attribute_with_pointer(
					prefix + "CompositeAngle",
					1, GL_UNSIGNED_SHORT, GL_FALSE,
					sizeof(Scan),
					reinterpret_cast<void *>(offsetof(Scan, scan.end_points[c].composite_angle)),
					1);
			}

			target.enable_vertex_attribute_with_pointer(
				"dataY",
				1, GL_UNSIGNED_SHORT, GL_FALSE,
				sizeof(Scan),
				reinterpret_cast<void *>(offsetof(Scan, data_y)),
				1);
			target.enable_vertex_attribute_with_pointer(
				"lineY",
				1, GL_UNSIGNED_SHORT, GL_FALSE,
				sizeof(Scan),
				reinterpret_cast<void *>(offsetof(Scan, line)),
				1);
		break;

		case ShaderType::Line:
			for(int c = 0; c < 2; ++c) {
				const std::string prefix = c ? "end" : "start";

				target.enable_vertex_attribute_with_pointer(
					prefix + "Point",
					2, GL_UNSIGNED_SHORT, GL_FALSE,
					sizeof(Line),
					reinterpret_cast<void *>(offsetof(Line, end_points[c].x)),
					1);
			}
		break;
	}
}
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 2007, ALICE Experiment at CERN, All rights reserved.      *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// PHOS Cpv bad channels map.                                              //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include "AliPHOSCpvBadChannelsMap.h"
#include "AliPHOSGeometry.h"

ClassImp(AliPHOSCpvBadChannelsMap)

//________________________________________________________________

  AliPHOSCpvBadChannelsMap::AliPHOSCpvBadChannelsMap() : fBads(-1)
{
  Reset();
}

//________________________________________________________________

void AliPHOSCpvBadChannelsMap::Reset()
{
  //Set all channels as good.

  for(Int_t module=0; module<AliPHOSCpvParam::kNDDL; module++)
    for(Int_t column=0; column<AliPHOSCpvParam::kPadPcX; column++)
      for(Int_t row=0; row<AliPHOSCpvParam::kPadPcY; row++)
	fBadChannelCpv[module][column][row] = kFALSE;

  fBads=0;

}

//________________________________________________________________

void AliPHOSCpvBadChannelsMap::Reset(Int_t module)
{
  //Set all channels in module as good.
  Int_t nBadsInModule=0;
  for(Int_t column=0; column<AliPHOSCpvParam::kPadPcX; column++)
    for(Int_t row=0; row<AliPHOSCpvParam::kPadPcY; row++)
      if(fBadChannelCpv[module][column][row]){
	fBadChannelCpv[module][column][row] = kFALSE;
	nBadsInModule++;
      }
  fBads-=nBadsInModule;

}

//________________________________________________________________

AliPHOSCpvBadChannelsMap::AliPHOSCpvBadChannelsMap(const AliPHOSCpvBadChannelsMap &map):
  TObject(map),fBads(map.fBads)
{
  //Copy constructor.
  for(Int_t module=0; module<AliPHOSCpvParam::kNDDL; module++)
    for(Int_t column=0; column<AliPHOSCpvParam::kPadPcX; column++)
      for(Int_t row=0; row<AliPHOSCpvParam::kPadPcY; row++)
	fBadChannelCpv[module][column][row] = map.fBadChannelCpv[module][column][row];

}

//________________________________________________________________

AliPHOSCpvBadChannelsMap& AliPHOSCpvBadChannelsMap::operator= (const AliPHOSCpvBadChannelsMap &map)
{
  //Assignment operator.

  if(this != &map) {
    fBads = map.fBads;
    for(Int_t module=0; module<AliPHOSCpvParam::kNDDL; module++)
      for(Int_t column=0; column<AliPHOSCpvParam::kPadPcX; column++)
	for(Int_t row=0; row<AliPHOSCpvParam::kPadPcY; row++)
	  fBadChannelCpv[module][column][row] = map.fBadChannelCpv[module][column][row];
  }

  return *this;
}

//_________________________________________________________________

void AliPHOSCpvBadChannelsMap::SetBadChannel(Int_t module, Int_t col, Int_t row)
{
  // Declare a channel (module,col,row) as a bad, if it was not set before

  if (!fBadChannelCpv[module-1][col-1][row-1]) {
    fBadChannelCpv[module-1][col-1][row-1] = kTRUE;
    ++fBads;
  }
}
//_________________________________________________________________

void AliPHOSCpvBadChannelsMap::BadChannelIds(Int_t *badIds)
{
  //Fill array badIds by the Ids of bad channels.
  //Array badIds of length GetNumOfBadChannels() should be prepared in advance.

  if(!badIds) return;
  if(!fBads>0) return;

  AliPHOSGeometry* geom = AliPHOSGeometry::GetInstance();

  if(!geom)
    geom = AliPHOSGeometry::GetInstance("IHEP");

  Int_t absId;
  Int_t relId[4];

  Int_t iBad = 0;
  relId[1] =  -1; // CPV pad

  for(Int_t mod=1; mod<=AliPHOSCpvParam::kNDDL; mod++) {
    for(Int_t col=1; col<=AliPHOSCpvParam::kPadPcX; col++) {
      for(Int_t row=1; row<=AliPHOSCpvParam::kPadPcY; row++) {
	if(IsBadChannel(mod,col,row)) {
	  relId[0] = mod;
	  relId[3] = col;
	  relId[2] = row;
	  geom->RelToAbsNumbering(relId,absId);
	  badIds[iBad]=absId;
	  iBad++;
	}
      }
    }
  }

}
<commit_msg>Wrong statement for the number of bad channels is corrected<commit_after>/**************************************************************************
 * Copyright(c) 2007, ALICE Experiment at CERN, All rights reserved.      *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// PHOS Cpv bad channels map.                                              //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include "AliPHOSCpvBadChannelsMap.h"
#include "AliPHOSGeometry.h"

ClassImp(AliPHOSCpvBadChannelsMap)

//________________________________________________________________

  AliPHOSCpvBadChannelsMap::AliPHOSCpvBadChannelsMap() : fBads(-1)
{
  Reset();
}

//________________________________________________________________

void AliPHOSCpvBadChannelsMap::Reset()
{
  //Set all channels as good.

  for(Int_t module=0; module<AliPHOSCpvParam::kNDDL; module++)
    for(Int_t column=0; column<AliPHOSCpvParam::kPadPcX; column++)
      for(Int_t row=0; row<AliPHOSCpvParam::kPadPcY; row++)
	fBadChannelCpv[module][column][row] = kFALSE;

  fBads=0;

}

//________________________________________________________________

void AliPHOSCpvBadChannelsMap::Reset(Int_t module)
{
  //Set all channels in module as good.
  Int_t nBadsInModule=0;
  for(Int_t column=0; column<AliPHOSCpvParam::kPadPcX; column++)
    for(Int_t row=0; row<AliPHOSCpvParam::kPadPcY; row++)
      if(fBadChannelCpv[module][column][row]){
	fBadChannelCpv[module][column][row] = kFALSE;
	nBadsInModule++;
      }
  fBads-=nBadsInModule;

}

//________________________________________________________________

AliPHOSCpvBadChannelsMap::AliPHOSCpvBadChannelsMap(const AliPHOSCpvBadChannelsMap &map):
  TObject(map),fBads(map.fBads)
{
  //Copy constructor.
  for(Int_t module=0; module<AliPHOSCpvParam::kNDDL; module++)
    for(Int_t column=0; column<AliPHOSCpvParam::kPadPcX; column++)
      for(Int_t row=0; row<AliPHOSCpvParam::kPadPcY; row++)
	fBadChannelCpv[module][column][row] = map.fBadChannelCpv[module][column][row];

}

//________________________________________________________________

AliPHOSCpvBadChannelsMap& AliPHOSCpvBadChannelsMap::operator= (const AliPHOSCpvBadChannelsMap &map)
{
  //Assignment operator.

  if(this != &map) {
    fBads = map.fBads;
    for(Int_t module=0; module<AliPHOSCpvParam::kNDDL; module++)
      for(Int_t column=0; column<AliPHOSCpvParam::kPadPcX; column++)
	for(Int_t row=0; row<AliPHOSCpvParam::kPadPcY; row++)
	  fBadChannelCpv[module][column][row] = map.fBadChannelCpv[module][column][row];
  }

  return *this;
}

//_________________________________________________________________

void AliPHOSCpvBadChannelsMap::SetBadChannel(Int_t module, Int_t col, Int_t row)
{
  // Declare a channel (module,col,row) as a bad, if it was not set before

  if (!fBadChannelCpv[module-1][col-1][row-1]) {
    fBadChannelCpv[module-1][col-1][row-1] = kTRUE;
    ++fBads;
  }
}
//_________________________________________________________________

void AliPHOSCpvBadChannelsMap::BadChannelIds(Int_t *badIds)
{
  //Fill array badIds by the Ids of bad channels.
  //Array badIds of length GetNumOfBadChannels() should be prepared in advance.

  if(!badIds) return;
  if(fBads <=0 ) return;

  AliPHOSGeometry* geom = AliPHOSGeometry::GetInstance();

  if(!geom)
    geom = AliPHOSGeometry::GetInstance("IHEP");

  Int_t absId;
  Int_t relId[4];

  Int_t iBad = 0;
  relId[1] =  -1; // CPV pad

  for(Int_t mod=1; mod<=AliPHOSCpvParam::kNDDL; mod++) {
    for(Int_t col=1; col<=AliPHOSCpvParam::kPadPcX; col++) {
      for(Int_t row=1; row<=AliPHOSCpvParam::kPadPcY; row++) {
	if(IsBadChannel(mod,col,row)) {
	  relId[0] = mod;
	  relId[3] = col;
	  relId[2] = row;
	  geom->RelToAbsNumbering(relId,absId);
	  badIds[iBad]=absId;
	  iBad++;
	}
      }
    }
  }

}
<|endoftext|>


<commit_before>AliAnalysisTaskSE *AddTaskEmcalPreparation(const char *perstr  = "LHC11h",
					   const char *pass    = 0 /*should not be needed*/
					   ) {

  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr)
  {
    ::Error("AddTaskEmcalPreparation", "No analysis manager to connect to.");
    return NULL;
  }

  TString period(perstr);
  period.ToLower();

  Bool_t isMC = kFALSE;
  if(period.Sizeof()>7) isMC = kTRUE;
  //  Bool_t isMC = (mgr->GetMCtruthEventHandler() != NULL); //only works for ESD
  if(isMC) Printf("AddTaskEmcalPreparation: Running on MC");
  else     Printf("AddTaskEmcalPreparation: Running on DATA");

  //----------------------- Add tender -------------------------------------------------------
  Bool_t distBC         = kFALSE; //switch for recalculation cluster position from bad channel
  Bool_t recalibClus    = kFALSE;
  Bool_t recalcClusPos  = kFALSE;
  Bool_t nonLinearCorr  = kFALSE;
  Bool_t remExoticCell  = kFALSE;
  Bool_t remExoticClus  = kFALSE;
  Bool_t fidRegion      = kFALSE;
  Bool_t calibEnergy    = kTRUE;
  Bool_t calibTime      = kTRUE;
  Bool_t remBC          = kTRUE;
  UInt_t nonLinFunct    = 0;
  Bool_t reclusterize   = kFALSE;
  Float_t seedthresh    = 0.1;      // 100 MeV
  Float_t cellthresh    = 0.05;     // 50 MeV
  UInt_t clusterizer    = 0;
  Bool_t trackMatch     = kFALSE;
  Bool_t updateCellOnly = kFALSE;
  Float_t timeMin       = -50e-9;   // minimum time of physical signal in a cell/digit
  Float_t timeMax       =  50e-9;   // maximum time of physical signal in a cell/digit
  Float_t timeCut       = 1e6;
  if(isMC) {
    timeMin = -1.;
    timeMax = 1e6;
  }

  gROOT->LoadMacro("$ALICE_ROOT/PWG/EMCAL/macros/AddTaskEMCALTender.C");//tendertasks
  AliAnalysisTaskSE *tender = AddTaskEMCALTender(distBC, recalibClus, recalcClusPos, nonLinearCorr, /*remExoticCell,*/ remExoticClus,
						 fidRegion, calibEnergy, calibTime, remBC, nonLinFunct, reclusterize, seedthresh,
						 cellthresh, clusterizer, trackMatch, updateCellOnly, timeMin, timeMax, timeCut,pass);

  //----------------------- Add clusterizer -------------------------------------------------------
  clusterizer    = AliEMCALRecParam::kClusterizerv2;
  remExoticCell  = kTRUE;
  gROOT->LoadMacro("$ALICE_ROOT/PWG/EMCAL/macros/AddTaskClusterizerFast.C");
  AliAnalysisTaskEMCALClusterizeFast *clusterizerTask = AddTaskClusterizerFast("ClusterizerFast","","",clusterizer,cellthresh,seedthresh,
									       timeMin,timeMax,timeCut,remExoticCell,distBC,
									       AliAnalysisTaskEMCALClusterizeFast::kFEEData);

  //----------------------- Add cluster maker -----------------------------------------------------
  gROOT->LoadMacro("$ALICE_ROOT/PWG/EMCAL/macros/AddTaskEmcalClusterMaker.C"); //cluster maker: non-linearity,
  UInt_t nonLinFunct = AliEMCALRecoUtils::kBeamTestCorrected;
  if(isMC) {
    if(period == "lhc12a15a")
      nonLinFunct = AliEMCALRecoUtils::kPi0MCv2;
    else
      nonLinFunct = AliEMCALRecoUtils::kPi0MCv3;
  }
  remExoticClus  = kTRUE;
  AliEmcalClusterMaker *clusMaker = AddTaskEmcalClusterMaker(nonLinFunct,remExoticClus,0,"EmcCaloClusters",0.,kTRUE);

  return clusMaker;
}
<commit_msg>split exotic cell and cluster removal setter<commit_after>AliAnalysisTaskSE *AddTaskEmcalPreparation(const char *perstr  = "LHC11h",
					   const char *pass    = 0 /*should not be needed*/
					   ) {

  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr)
  {
    ::Error("AddTaskEmcalPreparation", "No analysis manager to connect to.");
    return NULL;
  }

  TString period(perstr);
  period.ToLower();

  Bool_t isMC = kFALSE;
  if(period.Sizeof()>7) isMC = kTRUE;
  //  Bool_t isMC = (mgr->GetMCtruthEventHandler() != NULL); //only works for ESD
  if(isMC) Printf("AddTaskEmcalPreparation: Running on MC");
  else     Printf("AddTaskEmcalPreparation: Running on DATA");

  //----------------------- Add tender -------------------------------------------------------
  Bool_t distBC         = kFALSE; //switch for recalculation cluster position from bad channel
  Bool_t recalibClus    = kFALSE;
  Bool_t recalcClusPos  = kFALSE;
  Bool_t nonLinearCorr  = kFALSE;
  Bool_t remExoticCell  = kFALSE;
  Bool_t remExoticClus  = kFALSE;
  Bool_t fidRegion      = kFALSE;
  Bool_t calibEnergy    = kTRUE;
  Bool_t calibTime      = kTRUE;
  Bool_t remBC          = kTRUE;
  UInt_t nonLinFunct    = 0;
  Bool_t reclusterize   = kFALSE;
  Float_t seedthresh    = 0.1;      // 100 MeV
  Float_t cellthresh    = 0.05;     // 50 MeV
  UInt_t clusterizer    = 0;
  Bool_t trackMatch     = kFALSE;
  Bool_t updateCellOnly = kFALSE;
  Float_t timeMin       = -50e-9;   // minimum time of physical signal in a cell/digit
  Float_t timeMax       =  50e-9;   // maximum time of physical signal in a cell/digit
  Float_t timeCut       = 1e6;
  if(isMC) {
    timeMin = -1.;
    timeMax = 1e6;
  }

  gROOT->LoadMacro("$ALICE_ROOT/PWG/EMCAL/macros/AddTaskEMCALTender.C");//tendertasks
  AliAnalysisTaskSE *tender = AddTaskEMCALTender(distBC, recalibClus, recalcClusPos, nonLinearCorr, remExoticCell, remExoticClus,
						 fidRegion, calibEnergy, calibTime, remBC, nonLinFunct, reclusterize, seedthresh,
						 cellthresh, clusterizer, trackMatch, updateCellOnly, timeMin, timeMax, timeCut,pass);

  //----------------------- Add clusterizer -------------------------------------------------------
  clusterizer    = AliEMCALRecParam::kClusterizerv2;
  remExoticCell  = kTRUE;
  gROOT->LoadMacro("$ALICE_ROOT/PWG/EMCAL/macros/AddTaskClusterizerFast.C");
  AliAnalysisTaskEMCALClusterizeFast *clusterizerTask = AddTaskClusterizerFast("ClusterizerFast","","",clusterizer,cellthresh,seedthresh,
									       timeMin,timeMax,timeCut,remExoticCell,distBC,
									       AliAnalysisTaskEMCALClusterizeFast::kFEEData);

  //----------------------- Add cluster maker -----------------------------------------------------
  gROOT->LoadMacro("$ALICE_ROOT/PWG/EMCAL/macros/AddTaskEmcalClusterMaker.C"); //cluster maker: non-linearity,
  UInt_t nonLinFunct = AliEMCALRecoUtils::kBeamTestCorrected;
  if(isMC) {
    if(period == "lhc12a15a")
      nonLinFunct = AliEMCALRecoUtils::kPi0MCv2;
    else
      nonLinFunct = AliEMCALRecoUtils::kPi0MCv3;
  }
  remExoticClus  = kTRUE;
  AliEmcalClusterMaker *clusMaker = AddTaskEmcalClusterMaker(nonLinFunct,remExoticClus,0,"EmcCaloClusters",0.,kTRUE);

  return clusMaker;
}
<|endoftext|>


<commit_before>AliAnalysisTaskCombinHF *AddTaskCombinHF(Int_t meson = 0,
                                         Bool_t readMC = kTRUE,
                                         TString containerStr = "",
                                         TString cutObjFile = "",
                                         TString cutObjNam = "",
                                         Int_t filterMask = 1,
                                         Double_t ptcut = 0.1,
                                         Double_t etacut = 0.9,
                                         Int_t pidStrategy = 0,
                                         Int_t casePID = 0,
                                         Double_t bayesThresKaon = 0.4,
                                         Double_t bayesThresPion = 0.4,
                                         Double_t minMass = 1.6,
                                         Double_t maxMass = 2.15,
                                         Double_t maxPt = 20.,
                                         Double_t ptBinWidth = 0.5)
{

  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskCombinHF", "No analysis manager to connect to.");
  }

  //Analysis Task

  AliRDHFCuts* analysiscuts=0x0;
  AliESDtrackCuts* esdc = 0x0;
  if(!cutObjFile.IsNull()){
    TFile *f=TFile::Open(cutObjFile.Data(),"READ");
    if(f){
      analysiscuts=(AliRDHFCuts*)f->Get(cutObjNam.Data());
      esdc=analysiscuts->GetTrackCuts();
    }
  }
  else {
    if(meson==0) analysiscuts=new AliRDHFCutsD0toKpi();
    else if(meson==1) analysiscuts=new AliRDHFCutsDplustoKpipi();
    else if(meson==3) analysiscuts=new AliRDHFCutsDstoKKpi();
    analysiscuts->SetStandardCutsPP2010();
    AliAODPidHF* pid=new AliAODPidHF();
    pid->SetMatch(5);
    pid->SetTPCnSigmaRangeForPions(-3.,3.);
    pid->SetTPCnSigmaRangeForKaons(-2.,3.);
    pid->SetTPCnSigmaRangeForProtons(-3.,3.);
    pid->SetTOFnSigmaRangeForPions(-3.,3.);
    pid->SetTOFnSigmaRangeForKaons(-2.,2.);
    pid->SetTOFnSigmaRangeForProtons(-3.,3.);
    analysiscuts->SetPidHF(pid);
  }
  if(!analysiscuts){
    Printf("Wrong file or cut object name set");
    return 0x0;
  }

  AliAnalysisTaskCombinHF *dTask = new AliAnalysisTaskCombinHF(meson,analysiscuts);
  if(!cutObjFile.IsNull()){
    dTask->SetKaonTrackCuts(esdc);
    dTask->SetPionTrackCuts(esdc);
    dTask->SetTrackCuts(esdc);
  }
  dTask->SetReadMC(readMC);
  dTask->SetDebugLevel(0);

  dTask->SetFilterMask(filterMask);
  dTask->SetPtAccCut(ptcut);
  dTask->SetEtaAccCut(etacut);

  // mass and pt range for histograms
  dTask->SetMassWindow(minMass, maxMass);
  dTask->SetMaxPt(maxPt);
  dTask->SetPtBinWidth(ptBinWidth);

  // PID settings
  dTask->SetPIDstrategy(pidStrategy);
  dTask->SetPIDselCaseZero(casePID);
  dTask->SetBayesThres(bayesThresKaon, bayesThresPion);

  mgr->AddTask(dTask);

  // Create containers for input/output

  TString mesname="Dzero";
  if(meson==1) mesname="Dplus";
  else if(meson==3) mesname="Ds";
  TString inname = Form("cinput%s%s",mesname.Data(),containerStr.Data());
  TString outname = Form("coutput%s%s",mesname.Data(),containerStr.Data());
  TString normname = Form("coutput%sNorm%s",mesname.Data(),containerStr.Data());
  TString cutname = Form("coutput%sCuts%s",mesname.Data(),containerStr.Data());

  AliAnalysisDataContainer *cinput = mgr->CreateContainer(inname,TChain::Class(),
                                                          AliAnalysisManager::kInputContainer);
  TString outputfile = AliAnalysisManager::GetCommonFileName();
  outputfile += Form(":PWG3_D2H_InvMass%sLowPt%s",mesname.Data(),containerStr.Data());

  AliAnalysisDataContainer *coutput = mgr->CreateContainer(outname,TList::Class(),
                                                           AliAnalysisManager::kOutputContainer,
                                                           outputfile.Data());
  AliAnalysisDataContainer *coutputNorm = mgr->CreateContainer(normname,AliNormalizationCounter::Class(),
                                                               AliAnalysisManager::kOutputContainer,
                                                               outputfile.Data());
  AliAnalysisDataContainer* coutputCuts = mgr->CreateContainer(cutname,
							       TList::Class(),
							       AliAnalysisManager::kParamContainer,
							       outputfile.Data() );

  mgr->ConnectInput(dTask,0,mgr->GetCommonInputContainer());

  mgr->ConnectOutput(dTask,1,coutput);
  mgr->ConnectOutput(dTask,2,coutputNorm);
  mgr->ConnectOutput(dTask,3,coutputCuts);

  return dTask;
}
<commit_msg>Update names of containers<commit_after>AliAnalysisTaskCombinHF *AddTaskCombinHF(Int_t meson = 0,
                                         Bool_t readMC = kTRUE,
                                         TString containerStr = "",
                                         TString cutObjFile = "",
                                         TString cutObjNam = "",
                                         Int_t filterMask = 1,
                                         Double_t ptcut = 0.1,
                                         Double_t etacut = 0.9,
                                         Int_t pidStrategy = 0,
                                         Int_t casePID = 0,
                                         Double_t bayesThresKaon = 0.4,
                                         Double_t bayesThresPion = 0.4,
                                         Double_t minMass = 1.6,
                                         Double_t maxMass = 2.15,
                                         Double_t maxPt = 20.,
                                         Double_t ptBinWidth = 0.5)
{

  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskCombinHF", "No analysis manager to connect to.");
  }

  //Analysis Task

  AliRDHFCuts* analysiscuts=0x0;
  AliESDtrackCuts* esdc = 0x0;
  if(!cutObjFile.IsNull()){
    TFile *f=TFile::Open(cutObjFile.Data(),"READ");
    if(f){
      analysiscuts=(AliRDHFCuts*)f->Get(cutObjNam.Data());
      esdc=analysiscuts->GetTrackCuts();
    }
  }
  else {
    if(meson==0) analysiscuts=new AliRDHFCutsD0toKpi();
    else if(meson==1) analysiscuts=new AliRDHFCutsDplustoKpipi();
    else if(meson==3) analysiscuts=new AliRDHFCutsDstoKKpi();
    analysiscuts->SetStandardCutsPP2010();
    AliAODPidHF* pid=new AliAODPidHF();
    pid->SetMatch(5);
    pid->SetTPCnSigmaRangeForPions(-3.,3.);
    pid->SetTPCnSigmaRangeForKaons(-2.,3.);
    pid->SetTPCnSigmaRangeForProtons(-3.,3.);
    pid->SetTOFnSigmaRangeForPions(-3.,3.);
    pid->SetTOFnSigmaRangeForKaons(-2.,2.);
    pid->SetTOFnSigmaRangeForProtons(-3.,3.);
    analysiscuts->SetPidHF(pid);
  }
  if(!analysiscuts){
    Printf("Wrong file or cut object name set");
    return 0x0;
  }

  AliAnalysisTaskCombinHF *dTask = new AliAnalysisTaskCombinHF(meson,analysiscuts);
  if(!cutObjFile.IsNull()){
    dTask->SetKaonTrackCuts(esdc);
    dTask->SetPionTrackCuts(esdc);
    dTask->SetTrackCuts(esdc);
  }
  dTask->SetReadMC(readMC);
  dTask->SetDebugLevel(0);

  dTask->SetFilterMask(filterMask);
  dTask->SetPtAccCut(ptcut);
  dTask->SetEtaAccCut(etacut);

  // mass and pt range for histograms
  dTask->SetMassWindow(minMass, maxMass);
  dTask->SetMaxPt(maxPt);
  dTask->SetPtBinWidth(ptBinWidth);

  // PID settings
  dTask->SetPIDstrategy(pidStrategy);
  dTask->SetPIDselCaseZero(casePID);
  dTask->SetBayesThres(bayesThresKaon, bayesThresPion);

  mgr->AddTask(dTask);

  // Create containers for input/output

  TString mesname="Dzero";
  if(meson==AliAnalysisTaskCombinHF::kDplus) mesname="Dplus";
  else if(meson==AliAnalysisTaskCombinHF::kDs) mesname="Ds";
  else if(meson==AliAnalysisTaskCombinHF::kJpsi) mesname="Jpsi";
  else if(meson==AliAnalysisTaskCombinHF::kEtac) mesname="Etac";
  TString inname = Form("cinput%s%s",mesname.Data(),containerStr.Data());
  TString outname = Form("coutput%s%s",mesname.Data(),containerStr.Data());
  TString normname = Form("coutput%sNorm%s",mesname.Data(),containerStr.Data());
  TString cutname = Form("coutput%sCuts%s",mesname.Data(),containerStr.Data());

  AliAnalysisDataContainer *cinput = mgr->CreateContainer(inname,TChain::Class(),
                                                          AliAnalysisManager::kInputContainer);
  TString outputfile = AliAnalysisManager::GetCommonFileName();
  outputfile += Form(":PWG3_D2H_InvMass%sLowPt%s",mesname.Data(),containerStr.Data());

  AliAnalysisDataContainer *coutput = mgr->CreateContainer(outname,TList::Class(),
                                                           AliAnalysisManager::kOutputContainer,
                                                           outputfile.Data());
  AliAnalysisDataContainer *coutputNorm = mgr->CreateContainer(normname,AliNormalizationCounter::Class(),
                                                               AliAnalysisManager::kOutputContainer,
                                                               outputfile.Data());
  AliAnalysisDataContainer* coutputCuts = mgr->CreateContainer(cutname,
							       TList::Class(),
							       AliAnalysisManager::kParamContainer,
							       outputfile.Data() );

  mgr->ConnectInput(dTask,0,mgr->GetCommonInputContainer());

  mgr->ConnectOutput(dTask,1,coutput);
  mgr->ConnectOutput(dTask,2,coutputNorm);
  mgr->ConnectOutput(dTask,3,coutputCuts);

  return dTask;
}
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library 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
 * OpenSceneGraph Public License for more details.
*/
#include <osg/BoundingSphere>
#include <osg/BoundingBox>

using namespace osg;

void BoundingSphere::expandBy(const Vec3f& v)
{
    if (valid())
    {
        vec_type dv = v-_center;
        value_type r = dv.length();
        if (r>_radius)
        {
            value_type dr = (r-_radius)*0.5;
            _center += dv*(dr/r);
            _radius += dr;
        } // else do nothing as vertex is within sphere.
    }
    else
    {
        _center = v;
        _radius = 0.0;
    }
}

void BoundingSphere::expandRadiusBy(const Vec3f& v)
{
    if (valid())
    {
        value_type r = (v-_center).length();
        if (r>_radius) _radius = r;
        // else do nothing as vertex is within sphere.
    }
    else
    {
        _center = v;
        _radius = 0.0;
    }
}

void BoundingSphere::expandBy(const Vec3d& v)
{
    if (valid())
    {
        vec_type dv = v-_center;
        value_type r = dv.length();
        if (r>_radius)
        {
            value_type dr = (r-_radius)*0.5;
            _center += dv*(dr/r);
            _radius += dr;
        } // else do nothing as vertex is within sphere.
    }
    else
    {
        _center = v;
        _radius = 0.0;
    }
}

void BoundingSphere::expandRadiusBy(const Vec3d& v)
{
    if (valid())
    {
        value_type r = (v-_center).length();
        if (r>_radius) _radius = r;
        // else do nothing as vertex is within sphere.
    }
    else
    {
        _center = v;
        _radius = 0.0;
    }
}

void BoundingSphere::expandBy(const BoundingSphere& sh)
{

    // This sphere is not set so use the inbound sphere
    if (!valid())
    {
        _center = sh._center;
        _radius = sh._radius;

        return;
    }

    // Calculate d == The distance between the sphere centers
    double d = ( _center - sh.center() ).length();

    // New sphere is already inside this one
    if ( d + sh.radius() <= _radius )
    {
        return;
    }

    //  New sphere completely contains this one
    if ( d + _radius <= sh.radius() )
    {
        _center = sh._center;
        _radius = sh._radius;
        return;
    }

    // Build a new sphere that completely contains the other two:
    //
    // The center point lies halfway along the line between the furthest
    // points on the edges of the two spheres.
    //
    // Computing those two points is ugly - so we'll use similar triangles
    double new_radius = (_radius + d + sh.radius() ) * 0.5;
    double ratio = ( new_radius - _radius ) / d ;

    _center[0] += ( sh.center()[0] - _center[0] ) * ratio;
    _center[1] += ( sh.center()[1] - _center[1] ) * ratio;
    _center[2] += ( sh.center()[2] - _center[2] ) * ratio;

    _radius = new_radius;

}

void BoundingSphere::expandRadiusBy(const BoundingSphere& sh)
{
    if (sh.valid())
    {
        if (valid())
        {
            value_type r = (sh._center-_center).length()+sh._radius;
            if (r>_radius) _radius = r;
            // else do nothing as vertex is within sphere.
        }
        else
        {
            _center = sh._center;
            _radius = sh._radius;
        }
    }
}

void BoundingSphere::expandBy(const BoundingBox& bb)
{
    if (bb.valid())
    {
        if (valid())
        {
            BoundingBox newbb(bb);

            for(unsigned int c=0;c<8;++c)
            {
                Vec3 v = bb.corner(c)-_center; // get the direction vector from corner
                v.normalize(); // normalise it.
                v *= -_radius; // move the vector in the opposite direction distance radius.
                v += _center; // move to absolute position.
                newbb.expandBy(v); // add it into the new bounding box.
            }

            _center = newbb.center();
            _radius = newbb.radius();

        }
        else
        {
            _center = bb.center();
            _radius = bb.radius();
        }
    }
}

void BoundingSphere::expandRadiusBy(const BoundingBox& bb)
{
    if (bb.valid())
    {
        if (valid())
        {
            for(unsigned int c=0;c<8;++c)
            {
                expandRadiusBy(bb.corner(c));
            }
        }
        else
        {
            _center = bb.center();
            _radius = bb.radius();
        }
    }
}
<commit_msg>Added missing check against handling invalid bounding sphere's<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library 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
 * OpenSceneGraph Public License for more details.
*/
#include <osg/BoundingSphere>
#include <osg/BoundingBox>

using namespace osg;

void BoundingSphere::expandBy(const Vec3f& v)
{
    if (valid())
    {
        vec_type dv = v-_center;
        value_type r = dv.length();
        if (r>_radius)
        {
            value_type dr = (r-_radius)*0.5;
            _center += dv*(dr/r);
            _radius += dr;
        } // else do nothing as vertex is within sphere.
    }
    else
    {
        _center = v;
        _radius = 0.0;
    }
}

void BoundingSphere::expandRadiusBy(const Vec3f& v)
{
    if (valid())
    {
        value_type r = (v-_center).length();
        if (r>_radius) _radius = r;
        // else do nothing as vertex is within sphere.
    }
    else
    {
        _center = v;
        _radius = 0.0;
    }
}

void BoundingSphere::expandBy(const Vec3d& v)
{
    if (valid())
    {
        vec_type dv = v-_center;
        value_type r = dv.length();
        if (r>_radius)
        {
            value_type dr = (r-_radius)*0.5;
            _center += dv*(dr/r);
            _radius += dr;
        } // else do nothing as vertex is within sphere.
    }
    else
    {
        _center = v;
        _radius = 0.0;
    }
}

void BoundingSphere::expandRadiusBy(const Vec3d& v)
{
    if (valid())
    {
        value_type r = (v-_center).length();
        if (r>_radius) _radius = r;
        // else do nothing as vertex is within sphere.
    }
    else
    {
        _center = v;
        _radius = 0.0;
    }
}

void BoundingSphere::expandBy(const BoundingSphere& sh)
{
    // ignore operation if incomming BoundingSphere is invalid.
    if (!sh.valid()) return;

    // This sphere is not set so use the inbound sphere
    if (!valid())
    {
        _center = sh._center;
        _radius = sh._radius;

        return;
    }

    // Calculate d == The distance between the sphere centers
    double d = ( _center - sh.center() ).length();

    // New sphere is already inside this one
    if ( d + sh.radius() <= _radius )
    {
        return;
    }

    //  New sphere completely contains this one
    if ( d + _radius <= sh.radius() )
    {
        _center = sh._center;
        _radius = sh._radius;
        return;
    }

    // Build a new sphere that completely contains the other two:
    //
    // The center point lies halfway along the line between the furthest
    // points on the edges of the two spheres.
    //
    // Computing those two points is ugly - so we'll use similar triangles
    double new_radius = (_radius + d + sh.radius() ) * 0.5;
    double ratio = ( new_radius - _radius ) / d ;

    _center[0] += ( sh.center()[0] - _center[0] ) * ratio;
    _center[1] += ( sh.center()[1] - _center[1] ) * ratio;
    _center[2] += ( sh.center()[2] - _center[2] ) * ratio;

    _radius = new_radius;

}

void BoundingSphere::expandRadiusBy(const BoundingSphere& sh)
{
    if (sh.valid())
    {
        if (valid())
        {
            value_type r = (sh._center-_center).length()+sh._radius;
            if (r>_radius) _radius = r;
            // else do nothing as vertex is within sphere.
        }
        else
        {
            _center = sh._center;
            _radius = sh._radius;
        }
    }
}

void BoundingSphere::expandBy(const BoundingBox& bb)
{
    if (bb.valid())
    {
        if (valid())
        {
            BoundingBox newbb(bb);

            for(unsigned int c=0;c<8;++c)
            {
                Vec3 v = bb.corner(c)-_center; // get the direction vector from corner
                v.normalize(); // normalise it.
                v *= -_radius; // move the vector in the opposite direction distance radius.
                v += _center; // move to absolute position.
                newbb.expandBy(v); // add it into the new bounding box.
            }

            _center = newbb.center();
            _radius = newbb.radius();

        }
        else
        {
            _center = bb.center();
            _radius = bb.radius();
        }
    }
}

void BoundingSphere::expandRadiusBy(const BoundingBox& bb)
{
    if (bb.valid())
    {
        if (valid())
        {
            for(unsigned int c=0;c<8;++c)
            {
                expandRadiusBy(bb.corner(c));
            }
        }
        else
        {
            _center = bb.center();
            _radius = bb.radius();
        }
    }
}
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library 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
 * OpenSceneGraph Public License for more details.
*/

#include <osg/GraphicsThread>
#include <osg/GraphicsContext>
#include <osg/GLObjects>
#include <osg/Notify>

using namespace osg;
using namespace OpenThreads;

GraphicsThread::GraphicsThread()
{
}

void GraphicsThread::run()
{
    // make the graphics context current.
    GraphicsContext* graphicsContext = dynamic_cast<GraphicsContext*>(_parent.get());
    if (graphicsContext)
    {
        graphicsContext->makeCurrent();

        graphicsContext->getState()->initializeExtensionProcs();
    }

    OperationThread::run();

    if (graphicsContext)
    {
        graphicsContext->releaseContext();
    }

}

void GraphicsOperation::operator () (Object* object)
{
    osg::GraphicsContext* context = dynamic_cast<osg::GraphicsContext*>(object);
    if (context) operator() (context);
}

void SwapBuffersOperation::operator () (GraphicsContext* context)
{
    context->swapBuffersImplementation();
    context->clear();
}

void BarrierOperation::release()
{
    Barrier::release();
}

void BarrierOperation::operator () (Object* /*object*/)
{
    if (_preBlockOp!=NO_OPERATION)
    {
        if (_preBlockOp==GL_FLUSH) glFlush();
        else if (_preBlockOp==GL_FINISH) glFinish();
    }

    block();
}

void ReleaseContext_Block_MakeCurrentOperation::release()
{
    Block::release();
}

void ReleaseContext_Block_MakeCurrentOperation::operator () (GraphicsContext* context)
{
    // release the graphics context.
    context->releaseContext();

    // reset the block so that it the next call to block()
    reset();

    // block this thread, until the block is released externally.
    block();

    // re acquire the graphics context.
    context->makeCurrent();
}

BlockAndFlushOperation::BlockAndFlushOperation():
    GraphicsOperation("Block",false)
{
    reset();
}

void BlockAndFlushOperation::release()
{
    Block::release();
}

void BlockAndFlushOperation::operator () (GraphicsContext*)
{
    glFlush();
    Block::release();
}

FlushDeletedGLObjectsOperation::FlushDeletedGLObjectsOperation(double availableTime, bool keep):
    GraphicsOperation("FlushDeletedGLObjectsOperation",keep),
    _availableTime(availableTime)
{
}

void FlushDeletedGLObjectsOperation::operator () (GraphicsContext* context)
{
    State* state = context->getState();
    unsigned int contextID = state ? state->getContextID() : 0;
    const FrameStamp* frameStamp = state ? state->getFrameStamp() : 0;
    double currentTime = frameStamp ? frameStamp->getReferenceTime() : 0.0;
    double availableTime = _availableTime;

    flushDeletedGLObjects(contextID, currentTime, availableTime);
}

void RunOperations::operator () (osg::GraphicsContext* context)
{
    context->runOperations();
}

/////////////////////////////////////////////////////////////////////////////
//
// EndOfDynamicDrawBlock
//
EndOfDynamicDrawBlock::EndOfDynamicDrawBlock(unsigned int numberOfBlocks):
    BlockCount(numberOfBlocks)
{
}

void EndOfDynamicDrawBlock::completed(osg::State* /*state*/)
{
    BlockCount::completed();
}
<commit_msg>Introduced a releaseAllOperation after completeion of OperationThread::run() to enable CUDA integration (in osgCuda) to be able to free up its resources.  Code drawn from a submission from Mick.<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library 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
 * OpenSceneGraph Public License for more details.
*/

#include <osg/GraphicsThread>
#include <osg/GraphicsContext>
#include <osg/GLObjects>
#include <osg/Notify>

using namespace osg;
using namespace OpenThreads;

GraphicsThread::GraphicsThread()
{
}

void GraphicsThread::run()
{
    // make the graphics context current.
    GraphicsContext* graphicsContext = dynamic_cast<GraphicsContext*>(_parent.get());
    if (graphicsContext)
    {
        graphicsContext->makeCurrent();

        graphicsContext->getState()->initializeExtensionProcs();
    }

    OperationThread::run();

    // release operations before the thread stops working.
    _operationQueue->releaseAllOperations();

    if (graphicsContext)
    {
        graphicsContext->releaseContext();
    }

}

void GraphicsOperation::operator () (Object* object)
{
    osg::GraphicsContext* context = dynamic_cast<osg::GraphicsContext*>(object);
    if (context) operator() (context);
}

void SwapBuffersOperation::operator () (GraphicsContext* context)
{
    context->swapBuffersImplementation();
    context->clear();
}

void BarrierOperation::release()
{
    Barrier::release();
}

void BarrierOperation::operator () (Object* /*object*/)
{
    if (_preBlockOp!=NO_OPERATION)
    {
        if (_preBlockOp==GL_FLUSH) glFlush();
        else if (_preBlockOp==GL_FINISH) glFinish();
    }

    block();
}

void ReleaseContext_Block_MakeCurrentOperation::release()
{
    Block::release();
}

void ReleaseContext_Block_MakeCurrentOperation::operator () (GraphicsContext* context)
{
    // release the graphics context.
    context->releaseContext();

    // reset the block so that it the next call to block()
    reset();

    // block this thread, until the block is released externally.
    block();

    // re acquire the graphics context.
    context->makeCurrent();
}

BlockAndFlushOperation::BlockAndFlushOperation():
    GraphicsOperation("Block",false)
{
    reset();
}

void BlockAndFlushOperation::release()
{
    Block::release();
}

void BlockAndFlushOperation::operator () (GraphicsContext*)
{
    glFlush();
    Block::release();
}

FlushDeletedGLObjectsOperation::FlushDeletedGLObjectsOperation(double availableTime, bool keep):
    GraphicsOperation("FlushDeletedGLObjectsOperation",keep),
    _availableTime(availableTime)
{
}

void FlushDeletedGLObjectsOperation::operator () (GraphicsContext* context)
{
    State* state = context->getState();
    unsigned int contextID = state ? state->getContextID() : 0;
    const FrameStamp* frameStamp = state ? state->getFrameStamp() : 0;
    double currentTime = frameStamp ? frameStamp->getReferenceTime() : 0.0;
    double availableTime = _availableTime;

    flushDeletedGLObjects(contextID, currentTime, availableTime);
}

void RunOperations::operator () (osg::GraphicsContext* context)
{
    context->runOperations();
}

/////////////////////////////////////////////////////////////////////////////
//
// EndOfDynamicDrawBlock
//
EndOfDynamicDrawBlock::EndOfDynamicDrawBlock(unsigned int numberOfBlocks):
    BlockCount(numberOfBlocks)
{
}

void EndOfDynamicDrawBlock::completed(osg::State* /*state*/)
{
    BlockCount::completed();
}
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library 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
 * OpenSceneGraph Public License for more details.
*/

#include <osg/GraphicsThread>
#include <osg/GraphicsContext>
#include <osg/Notify>

using namespace osg;
using namespace OpenThreads;

struct BlockOperation : public Operation, public Block
{
    BlockOperation():
        Operation("Block",false)
    {
        reset();
    }

    virtual void release()
    {
        Block::release();
    }

    virtual void operator () (Object*)
    {
        glFlush();
        Block::release();
    }
};

OperationsThread::OperationsThread():
    _parent(0),
    _done(false)
{
    _operationsBlock = new RefBlock;
}

OperationsThread::~OperationsThread()
{
    //osg::notify(osg::NOTICE)<<"Destructing graphics thread "<<this<<std::endl;

    cancel();

    //osg::notify(osg::NOTICE)<<"Done Destructing graphics thread "<<this<<std::endl;
}

void OperationsThread::setDone(bool done)
{
    if (_done==done) return;

    _done = true;

    if (done)
    {
        osg::notify(osg::INFO)<<"set done "<<this<<std::endl;

        {
            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
            if (_currentOperation.valid())
            {
                osg::notify(osg::INFO)<<"releasing "<<_currentOperation.get()<<std::endl;
                _currentOperation->release();
            }
        }

        _operationsBlock->release();
    }

}

int OperationsThread::cancel()
{
    osg::notify(osg::INFO)<<"Cancelling OperationsThred "<<this<<" isRunning()="<<isRunning()<<std::endl;

    int result = 0;
    if( isRunning() )
    {

        _done = true;

        osg::notify(osg::INFO)<<"   Doing cancel "<<this<<std::endl;

        for(OperationQueue::iterator itr = _operations.begin();
            itr != _operations.end();
            ++itr)
        {
            (*itr)->release();
        }

        // release the frameBlock and _databasePagerThreadBlock incase its holding up thread cancelation.
        _operationsBlock->release();

        // then wait for the the thread to stop running.
        while(isRunning())
        {
            _operationsBlock->release();

            {
                OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);

                for(OperationQueue::iterator itr = _operations.begin();
                    itr != _operations.end();
                    ++itr)
                {
                    (*itr)->release();
                }

                if (_currentOperation.valid()) _currentOperation->release();
            }

            // commenting out debug info as it was cashing crash on exit, presumable
            // due to osg::notify or std::cout destructing earlier than this destructor.
            osg::notify(osg::INFO)<<"   Waiting for OperationsThread to cancel "<<this<<std::endl;
            OpenThreads::Thread::YieldCurrentThread();
        }
    }

    osg::notify(osg::INFO)<<"  OperationsThread::cancel() thread cancelled "<<this<<" isRunning()="<<isRunning()<<std::endl;

    return result;
}

void OperationsThread::add(Operation* operation, bool waitForCompletion)
{
    osg::notify(osg::INFO)<<"Doing add"<<std::endl;

    ref_ptr<BlockOperation> block = 0;

    {
        // aquire the lock on the operations queue to prevent anyone else for modifying it at the same time
        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);

        // add the operation to the end of the list
        _operations.push_back(operation);

        if (waitForCompletion)
        {
            block = new BlockOperation;
            _operations.push_back(block.get());
        }

        _operationsBlock->set(true);
    }

    if (block.valid())
    {
        // now we wait till the barrier is joined by the graphics thread.
        block->block();
    }
}

void OperationsThread::remove(Operation* operation)
{
    osg::notify(osg::INFO)<<"Doing remove operation"<<std::endl;

    // aquire the lock on the operations queue to prevent anyone else for modifying it at the same time
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);

    for(OperationQueue::iterator itr = _operations.begin();
        itr!=_operations.end();)
    {
        if ((*itr)==operation) itr = _operations.erase(itr);
        else ++itr;
    }
}

void OperationsThread::remove(const std::string& name)
{
    osg::notify(osg::INFO)<<"Doing remove named operation"<<std::endl;

    // aquire the lock on the operations queue to prevent anyone else for modifying it at the same time
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);

    // find the remove all operations with specificed name
    for(OperationQueue::iterator itr = _operations.begin();
        itr!=_operations.end();)
    {
        if ((*itr)->getName()==name) itr = _operations.erase(itr);
        else ++itr;
    }

    if (_operations.empty())
    {
        _operationsBlock->set(false);
    }
}

void OperationsThread::removeAllOperations()
{
    osg::notify(osg::INFO)<<"Doing remove all operations"<<std::endl;

    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
    _operations.clear();

    if (_operations.empty())
    {
        _operationsBlock->set(false);
    }
}

void OperationsThread::run()
{
    // make the graphics context current.
    GraphicsContext* graphicsContext = dynamic_cast<GraphicsContext*>(_parent.get());
    if (graphicsContext)
    {
        graphicsContext->makeCurrent();
    }

    osg::notify(osg::INFO)<<"Doing run "<<this<<" isRunning()="<<isRunning()<<std::endl;

    bool firstTime = true;

    OperationQueue::iterator itr = _operations.begin();

    do
    {
        // osg::notify(osg::NOTICE)<<"In main loop "<<this<<std::endl;

        if (_operations.empty())
        {
            _operationsBlock->block();

            // exit from loop if _done is set.
            if (_done) break;

            itr = _operations.begin();
        }
        else
        {
            if  (itr == _operations.end()) itr = _operations.begin();
        }

        // osg::notify(osg::INFO)<<"get op "<<_done<<" "<<this<<std::endl;

        // get the front of the file request list.
        {
            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
            if (!_operations.empty())
            {
                // get the next item
                _currentOperation = *itr;

                if (!_currentOperation->getKeep())
                {
                    // osg::notify(osg::INFO)<<"removing "<<_currentOperation->getName()<<std::endl;

                    // remove it from the opeations queue
                    itr = _operations.erase(itr);

                    // osg::notify(osg::INFO)<<"size "<<_operations.size()<<std::endl;

                    if (_operations.empty())
                    {
                       // osg::notify(osg::INFO)<<"setting block "<<_operations.size()<<std::endl;
                       _operationsBlock->set(false);
                    }
                }
                else
                {
                    // osg::notify(osg::INFO)<<"increment "<<_currentOperation->getName()<<std::endl;

                    // move on to the next operation in the list.
                    ++itr;
                }

            }

        }

        if (_currentOperation.valid())
        {
            // osg::notify(osg::INFO)<<"Doing op "<<_currentOperation->getName()<<" "<<this<<std::endl;

            // call the graphics operation.
            (*_currentOperation)(_parent.get());

            {
                OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
                _currentOperation = 0;
            }
        }

        if (firstTime)
        {
            // do a yield to get round a peculiar thread hang when testCancel() is called
            // in certain cirumstances - of which there is no particular pattern.
            YieldCurrentThread();
            firstTime = false;
        }

        // osg::notify(osg::NOTICE)<<"operations.size()="<<_operations.size()<<" done="<<_done<<" testCancel()"<<testCancel()<<std::endl;

    } while (!testCancel() && !_done);

    if (graphicsContext)
    {
        graphicsContext->releaseContext();
    }

    osg::notify(osg::INFO)<<"exit loop "<<this<<" isRunning()="<<isRunning()<<std::endl;

}

void SwapBuffersOperation::operator () (Object* object)
{
    GraphicsContext* context = dynamic_cast<GraphicsContext*>(object);
    if (context)
    {
        context->swapBuffersImplementation();
        context->clear();
    }
}

void BarrierOperation::release()
{
    Barrier::release();
}

void BarrierOperation::operator () (Object*)
{
    if (_preBlockOp==GL_FLUSH) glFlush();
    if (_preBlockOp==GL_FINISH) glFinish();

    block();
}

void ReleaseContext_Block_MakeCurrentOperation::release()
{
    Block::release();
}

void ReleaseContext_Block_MakeCurrentOperation::operator () (Object* object)
{
    GraphicsContext* context = dynamic_cast<GraphicsContext*>(object);
    if (!context) return;

    // release the graphics context.
    context->releaseContext();

    // reset the block so that it the next call to block()
    reset();

    // block this thread, untill the block is released externally.
    block();

    // re aquire the graphcis context.
    context->makeCurrent();
}
<commit_msg>Added OpertionQueue<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library 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
 * OpenSceneGraph Public License for more details.
*/

#include <osg/GraphicsThread>
#include <osg/GraphicsContext>
#include <osg/Notify>

using namespace osg;
using namespace OpenThreads;

struct BlockOperation : public Operation, public Block
{
    BlockOperation():
        Operation("Block",false)
    {
        reset();
    }

    virtual void release()
    {
        Block::release();
    }

    virtual void operator () (Object*)
    {
        glFlush();
        Block::release();
    }
};

/////////////////////////////////////////////////////////////////////////////
//
//  OperationsQueue
//

OperationQueue::OperationQueue()
{
}

OperationQueue::~OperationQueue()
{
}

void OperationQueue::add(Operation* operation)
{
    osg::notify(osg::INFO)<<"Doing add"<<std::endl;

    {
        // aquire the lock on the operations queue to prevent anyone else for modifying it at the same time
        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);

        // add the operation to the end of the list
        _operations.push_back(operation);

        _operationsBlock->set(true);
    }
}

void OperationQueue::remove(Operation* operation)
{
    osg::notify(osg::INFO)<<"Doing remove operation"<<std::endl;

    // aquire the lock on the operations queue to prevent anyone else for modifying it at the same time
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);

    for(Operations::iterator itr = _operations.begin();
        itr!=_operations.end();)
    {
        if ((*itr)==operation) itr = _operations.erase(itr);
        else ++itr;
    }
}

void OperationQueue::remove(const std::string& name)
{
    osg::notify(osg::INFO)<<"Doing remove named operation"<<std::endl;

    // aquire the lock on the operations queue to prevent anyone else for modifying it at the same time
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);

    // find the remove all operations with specificed name
    for(Operations::iterator itr = _operations.begin();
        itr!=_operations.end();)
    {
        if ((*itr)->getName()==name) itr = _operations.erase(itr);
        else ++itr;
    }

    if (_operations.empty())
    {
        _operationsBlock->set(false);
    }
}

void OperationQueue::removeAllOperations()
{
    osg::notify(osg::INFO)<<"Doing remove all operations"<<std::endl;

    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
    _operations.clear();

    if (_operations.empty())
    {
        _operationsBlock->set(false);
    }
}

/////////////////////////////////////////////////////////////////////////////
//
//  OperationsThread
//

OperationsThread::OperationsThread():
    _parent(0),
    _done(false)
{
    _operationsBlock = new RefBlock;
}

OperationsThread::~OperationsThread()
{
    //osg::notify(osg::NOTICE)<<"Destructing graphics thread "<<this<<std::endl;

    cancel();

    //osg::notify(osg::NOTICE)<<"Done Destructing graphics thread "<<this<<std::endl;
}

void OperationsThread::setDone(bool done)
{
    if (_done==done) return;

    _done = true;

    if (done)
    {
        osg::notify(osg::INFO)<<"set done "<<this<<std::endl;

        {
            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
            if (_currentOperation.valid())
            {
                osg::notify(osg::INFO)<<"releasing "<<_currentOperation.get()<<std::endl;
                _currentOperation->release();
            }
        }

        _operationsBlock->release();
    }

}

int OperationsThread::cancel()
{
    osg::notify(osg::INFO)<<"Cancelling OperationsThred "<<this<<" isRunning()="<<isRunning()<<std::endl;

    int result = 0;
    if( isRunning() )
    {

        _done = true;

        osg::notify(osg::INFO)<<"   Doing cancel "<<this<<std::endl;

        for(Operations::iterator itr = _operations.begin();
            itr != _operations.end();
            ++itr)
        {
            (*itr)->release();
        }

        // release the frameBlock and _databasePagerThreadBlock incase its holding up thread cancelation.
        _operationsBlock->release();

        // then wait for the the thread to stop running.
        while(isRunning())
        {
            _operationsBlock->release();

            {
                OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);

                for(Operations::iterator itr = _operations.begin();
                    itr != _operations.end();
                    ++itr)
                {
                    (*itr)->release();
                }

                if (_currentOperation.valid()) _currentOperation->release();
            }

            // commenting out debug info as it was cashing crash on exit, presumable
            // due to osg::notify or std::cout destructing earlier than this destructor.
            osg::notify(osg::INFO)<<"   Waiting for OperationsThread to cancel "<<this<<std::endl;
            OpenThreads::Thread::YieldCurrentThread();
        }
    }

    osg::notify(osg::INFO)<<"  OperationsThread::cancel() thread cancelled "<<this<<" isRunning()="<<isRunning()<<std::endl;

    return result;
}

void OperationsThread::add(Operation* operation, bool waitForCompletion)
{
    osg::notify(osg::INFO)<<"Doing add"<<std::endl;

    ref_ptr<BlockOperation> block = 0;

    {
        // aquire the lock on the operations queue to prevent anyone else for modifying it at the same time
        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);

        // add the operation to the end of the list
        _operations.push_back(operation);

        if (waitForCompletion)
        {
            block = new BlockOperation;
            _operations.push_back(block.get());
        }

        _operationsBlock->set(true);
    }

    if (block.valid())
    {
        // now we wait till the barrier is joined by the graphics thread.
        block->block();
    }
}

void OperationsThread::remove(Operation* operation)
{
    osg::notify(osg::INFO)<<"Doing remove operation"<<std::endl;

    // aquire the lock on the operations queue to prevent anyone else for modifying it at the same time
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);

    for(Operations::iterator itr = _operations.begin();
        itr!=_operations.end();)
    {
        if ((*itr)==operation) itr = _operations.erase(itr);
        else ++itr;
    }
}

void OperationsThread::remove(const std::string& name)
{
    osg::notify(osg::INFO)<<"Doing remove named operation"<<std::endl;

    // aquire the lock on the operations queue to prevent anyone else for modifying it at the same time
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);

    // find the remove all operations with specificed name
    for(Operations::iterator itr = _operations.begin();
        itr!=_operations.end();)
    {
        if ((*itr)->getName()==name) itr = _operations.erase(itr);
        else ++itr;
    }

    if (_operations.empty())
    {
        _operationsBlock->set(false);
    }
}

void OperationsThread::removeAllOperations()
{
    osg::notify(osg::INFO)<<"Doing remove all operations"<<std::endl;

    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
    _operations.clear();

    if (_operations.empty())
    {
        _operationsBlock->set(false);
    }
}

void OperationsThread::run()
{
    // make the graphics context current.
    GraphicsContext* graphicsContext = dynamic_cast<GraphicsContext*>(_parent.get());
    if (graphicsContext)
    {
        graphicsContext->makeCurrent();
    }

    osg::notify(osg::INFO)<<"Doing run "<<this<<" isRunning()="<<isRunning()<<std::endl;

    bool firstTime = true;

    Operations::iterator itr = _operations.begin();

    do
    {
        // osg::notify(osg::NOTICE)<<"In main loop "<<this<<std::endl;

        if (_operations.empty())
        {
            _operationsBlock->block();

            // exit from loop if _done is set.
            if (_done) break;

            itr = _operations.begin();
        }
        else
        {
            if  (itr == _operations.end()) itr = _operations.begin();
        }

        // osg::notify(osg::INFO)<<"get op "<<_done<<" "<<this<<std::endl;

        // get the front of the file request list.
        {
            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
            if (!_operations.empty())
            {
                // get the next item
                _currentOperation = *itr;

                if (!_currentOperation->getKeep())
                {
                    // osg::notify(osg::INFO)<<"removing "<<_currentOperation->getName()<<std::endl;

                    // remove it from the opeations queue
                    itr = _operations.erase(itr);

                    // osg::notify(osg::INFO)<<"size "<<_operations.size()<<std::endl;

                    if (_operations.empty())
                    {
                       // osg::notify(osg::INFO)<<"setting block "<<_operations.size()<<std::endl;
                       _operationsBlock->set(false);
                    }
                }
                else
                {
                    // osg::notify(osg::INFO)<<"increment "<<_currentOperation->getName()<<std::endl;

                    // move on to the next operation in the list.
                    ++itr;
                }

            }

        }

        if (_currentOperation.valid())
        {
            // osg::notify(osg::INFO)<<"Doing op "<<_currentOperation->getName()<<" "<<this<<std::endl;

            // call the graphics operation.
            (*_currentOperation)(_parent.get());

            {
                OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
                _currentOperation = 0;
            }
        }

        if (firstTime)
        {
            // do a yield to get round a peculiar thread hang when testCancel() is called
            // in certain cirumstances - of which there is no particular pattern.
            YieldCurrentThread();
            firstTime = false;
        }

        // osg::notify(osg::NOTICE)<<"operations.size()="<<_operations.size()<<" done="<<_done<<" testCancel()"<<testCancel()<<std::endl;

    } while (!testCancel() && !_done);

    if (graphicsContext)
    {
        graphicsContext->releaseContext();
    }

    osg::notify(osg::INFO)<<"exit loop "<<this<<" isRunning()="<<isRunning()<<std::endl;

}

void SwapBuffersOperation::operator () (Object* object)
{
    GraphicsContext* context = dynamic_cast<GraphicsContext*>(object);
    if (context)
    {
        context->swapBuffersImplementation();
        context->clear();
    }
}

void BarrierOperation::release()
{
    Barrier::release();
}

void BarrierOperation::operator () (Object*)
{
    if (_preBlockOp==GL_FLUSH) glFlush();
    if (_preBlockOp==GL_FINISH) glFinish();

    block();
}

void ReleaseContext_Block_MakeCurrentOperation::release()
{
    Block::release();
}

void ReleaseContext_Block_MakeCurrentOperation::operator () (Object* object)
{
    GraphicsContext* context = dynamic_cast<GraphicsContext*>(object);
    if (!context) return;

    // release the graphics context.
    context->releaseContext();

    // reset the block so that it the next call to block()
    reset();

    // block this thread, untill the block is released externally.
    block();

    // re aquire the graphcis context.
    context->makeCurrent();
}
<|endoftext|>