text:
/*
 * Lightmap generator file
 *
 * This file is part of the "SoftPixel Engine" (Copyright (c) 2008 by Lukas Hermanns)
 * See "SoftPixelEngine.hpp" for license information.
 */

#include "Framework/Tools/LightmapGenerator/spLightmapGenerator.hpp"

#ifdef SP_COMPILE_WITH_LIGHTMAPGENERATOR

#include "Framework/Tools/LightmapGenerator/spLightmapGeneratorStructs.hpp"
#include "Base/spMathCollisionLibrary.hpp"
#include "Base/spMathRasterizer.hpp"
#include "Base/spTimer.hpp"
#include "Base/spSharedObjects.hpp"
#include "Platform/spSoftPixelDeviceOS.hpp"
#include "SceneGraph/spSceneManager.hpp"

#include <boost/foreach.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

namespace sp
{

extern video::RenderSystem* GlbRenderSys;
extern scene::SceneGraph* GlbSceneGraph;

namespace tool
{

using namespace LightmapGen;

/*
 * Static class members
 */

LightmapProgressCallback LightmapGenerator::ProgressCallback_ = 0;

s32 LightmapGenerator::Progress_                    = 0;
s32 LightmapGenerator::ProgressMax_                 = 0;
s32 LightmapGenerator::ProgressShadedTriangleNum_   = 0;

dim::size2di LightmapGenerator::LightmapSize_ = dim::size2di(512);

/*
 * LightmapGenerator class
 */

LightmapGenerator::LightmapGenerator() :
    FinalModel_ (0),
    CollMesh_   (0),
    CurLightmap_(0),
    CurRectRoot_(0)
{
}
LightmapGenerator::~LightmapGenerator()
{
    clearLightmapObjects();
}

bool LightmapGenerator::generateLightmaps(
    const std::vector<SCastShadowObject> &CastShadowObjects,
    const std::vector<SGetShadowObject> &GetShadowObjects,
    const std::vector<SLightmapLight> &LightSources,
    const SLightmapGenConfig &Config,
    const u8 ThreadCount,
    const u32 Flags)
{
    /* Print start-up information */
    const u64 StartTime = io::Timer::secs();

    io::Log::message(
        "Starting lightmap generation process [ " +
        LightmapGenerator::getProcessInfo(ThreadCount, Flags) + " ]"
    );
    io::Log::ScopedTab Unused;

    try
    {
        updateStateInfo(LIGHTMAPSTATE_INITIALIZING);

        // Initialize settings
        LightmapSize_ = Config.MaxLightmapSize;

        State_.Flags                    = Flags;
        State_.AmbientColor             = Config.AmbientColor;
        State_.TexelBlurRadius          = Config.TexelBlurRadius;
        State_.ThreadCount              = ThreadCount;
        State_.HasGeneratedSuccessful   = false;

        State_.validateFlags();

        // Delete the old lightmap objects & textures
        clearScene();

        // Create initial lightmap
        createNewLightmap();

        // Create the get-shadow objects, cast-shadow objects, light sources
        foreach (const SGetShadowObject &Obj, GetShadowObjects)
        {
            if (Obj.Mesh->getVisible())
            {
                SModel* NewModel = new SModel(Obj.Mesh, Obj.StayAlone, Obj.TrianglesDensity);
                ModelMap_[Obj.Mesh] = NewModel;
                GetShadowObjects_.push_back(NewModel);
            }
        }

        // Create cast-shadow collision mesh
        std::list<scene::Mesh*> CollMeshList;

        foreach (const SCastShadowObject &Obj, CastShadowObjects)
        {
            if (Obj.Mesh->getVisible())
                CollMeshList.push_back(Obj.Mesh);
        }

        //#define _DEB_LM_TIMER_
        #ifdef _DEB_LM_TIMER_//!!!
        u64 t = io::Timer::millisecs();
        #endif

        CollMesh_ = CollSys_.createMeshList(0, CollMeshList, 20);

        #ifdef _DEB_LM_TIMER_//!!!
        io::Log::message("kd-Tree generation Time: " + io::stringc(io::Timer::millisecs() - t) + " ms.");
        #endif

        foreach (const SLightmapLight &Light, LightSources)
        {
            if (Light.Visible)
                LightSources_.push_back(new SLight(Light));
        }

        // Setup GPU dispatcher
        if (State_.useGPU())
        {
            if ( !GPUDispatcher_.createResources(
                    CollMesh_, State_.useRadiosity(), (Flags & LIGHTMAPFLAG_GPU_TREE_HIERARCHY) != 0, Config.MaxLightmapSize) ||
                 !GPUDispatcher_.setupLightSources(LightSources) )
            {
                io::Log::warning("Hardware acceleration disabled");
                math::removeFlag(State_.Flags, LIGHTMAPFLAG_GPU_ACCELERATION);
                math::removeFlag(State_.Flags, LIGHTMAPFLAG_GPU_TREE_HIERARCHY);
                math::removeFlag(State_.Flags, LIGHTMAPFLAG_RADIOSITY);
            }
        }

        // Create the root object & partition the add-shadow objects
        estimateEntireProgress(Config.TexelBlurRadius > 0);

        FinalModel_ = GlbSceneGraph->createMesh();
        FinalModel_->getMaterial()->setLighting(false);

        partitionScene(Config.DefaultDensity);

        if (!LightmapGenerator::processRunning(0))
            throw std::exception();

        shadeAllLightmaps();

        if (!LightmapGenerator::processRunning(0))
            throw std::exception();

        // Copy image buffers
        foreach (SLightmap* LMap, Lightmaps_)
            LMap->copyImageBuffers();

        // Blur lightmaps
        if (Config.TexelBlurRadius > 0)
            blurAllLightmaps(Config.TexelBlurRadius);

        // Create the final lightmap textures
        createFinalLightmapTextures(Config.AmbientColor);

        // Build the final models
        buildAllFinalModels();

        // Store final lightmap textures
        foreach (SLightmap* LMap, Lightmaps_)
            LightmapTextures_.push_back(LMap->Texture);

        updateStateInfo(LIGHTMAPSTATE_COMPLETED);

        CurLightmap_ = 0;
        State_.HasGeneratedSuccessful = true;
    }
    catch (...)
    {
        io::Log::warning("Lightmap generation has been canceled");
        return false;
    }

    /* Print final information of success */
    io::Log::message(
        "Completed after " + io::Timer::secsAsString(io::Timer::secs() - StartTime)
    );

    return true;
}

void LightmapGenerator::clearScene()
{
    // Delete all lightmap scene nodes
    GlbSceneGraph->deleteNode(FinalModel_);
    FinalModel_ = 0;

    foreach (scene::Mesh* Obj, SingleModels_)
        GlbSceneGraph->deleteNode(Obj);
    SingleModels_.clear();

    // Delete all lightmap textures
    foreach (video::Texture* Tex, LightmapTextures_)
        GlbRenderSys->deleteTexture(Tex);
    LightmapTextures_.clear();

    // Delete all collision nodes
    CollSys_.clearScene();

    // Delete old lightmaps
    clearLightmapObjects();

    // Delete GPU dispatcher resources
    GPUDispatcher_.deleteResources();
}

bool LightmapGenerator::updateBluring(u8 TexelBlurRadius)
{
    if (!hasGeneratedSuccessful() || TexelBlurRadius == State_.TexelBlurRadius)
        return false;

    #ifdef SP_DEBUGMODE
    if (TexelBlurRadius > 16)
    {
        io::Log::debug(
            "LightmapGenerator::updateBluring",
            "Very high blur radius (" + io::stringc(static_cast<u32>(TexelBlurRadius)) + ")"
        );
    }
    #endif

    // Update texture bluring
    blurAllLightmaps(TexelBlurRadius);
    createFinalLightmapTextures(State_.AmbientColor);

    State_.TexelBlurRadius = TexelBlurRadius;

    return true;
}

bool LightmapGenerator::updateAmbientColor(const video::color &AmbientColor)
{
    if (!hasGeneratedSuccessful() || AmbientColor == State_.AmbientColor)
        return false;

    foreach (SLightmap* LMap, Lightmaps_)
        LMap->createTexture(AmbientColor);

    State_.AmbientColor = AmbientColor;

    return true;
}

void LightmapGenerator::setProgressCallback(const LightmapProgressCallback &Callback)
{
    ProgressCallback_ = Callback;
}

/*
 * ======= Private: =======
 */

void LightmapGenerator::estimateEntireProgress(bool BlurEnabled)
{
    // Calculate the progress maximum
    LightmapGenerator::Progress_    = 0;
    LightmapGenerator::ProgressMax_ = GetShadowObjects_.size() * 8;

    LightmapGenerator::ProgressShadedTriangleNum_ = 0;

    foreach (SModel* Obj, GetShadowObjects_)
        LightmapGenerator::ProgressShadedTriangleNum_ += Obj->Mesh->getTriangleCount();

    if (!State_.useGPU())
        LightmapGenerator::ProgressMax_ += LightmapGenerator::ProgressShadedTriangleNum_ * (LightSources_.size() + 1);

    if (BlurEnabled)
        LightmapGenerator::ProgressMax_ += GetShadowObjects_.size();
}

void LightmapGenerator::createFacesLightmaps(SModel* Model)
{
    for (s32 i = 0; i < 6; ++i)
    {
        foreach (SFace &Face, Model->Axles[i].Faces)
        {
            Face.Lightmap = new SLightmap(Face.Size + 2, false);
            putFaceIntoLightmap(&Face);
        }
    }
}

void LightmapGenerator::generateLightTexelsSingleThreaded(SLight* Light)
{
    // kd-Tree relevant variables
    std::list<const scene::TreeNode*> TreeNodeList;
    scene::CollisionMesh::TreeNodeDataType* TreeNodeData = 0;

    std::map<STriangle*, bool> UsedTriangles;
    SModel* Obj = 0;

    // Find each triangle using the kd-Tree
    CollMesh_->getRootTreeNode()->findLeafList(
        TreeNodeList, Light->Position, Light->FixedVolumetricRadius
    );

    foreach (const scene::TreeNode* Node, TreeNodeList)
    {
        if (!Node->getUserData())
            continue;

        TreeNodeData = static_cast<scene::CollisionMesh::TreeNodeDataType*>(Node->getUserData());

        // Loop each tree-node's triangle
        #ifndef _DEB_NEW_KDTREE_
        foreach (scene::SCollisionFace* Face, *TreeNodeData)
        #else
        foreach (scene::SCollisionFace &NodeFace, *TreeNodeData)
        #endif
        {
            #ifdef _DEB_NEW_KDTREE_
            scene::SCollisionFace* Face = &NodeFace;
            #endif

            // Get model object
            std::map<scene::Mesh*, SModel*>::iterator it = ModelMap_.find(Face->Mesh);

            if (it == ModelMap_.end())
                continue;

            Obj = it->second;

            // Get triangle object
            STriangle* Triangle = (Obj->Triangles[Face->Surface])[Face->Index];

            if (UsedTriangles.find(Triangle) != UsedTriangles.end())
            {
                if (!LightmapGenerator::processRunning(0))
                    throw std::exception();
                continue;
            }
            UsedTriangles[Triangle] = true;

            if (!LightmapGenerator::processRunning())
                throw std::exception();

            // Rasterize triangle
            rasterizeTriangle(Light, *Triangle);
        }
    }

    /*

    The following is legacy code. It was used to iterate over all scene triangles
    without making use of tree hierarchy optimizations. When the optimization part
    produce problems, use this code:
    ==============================================================

    foreach (SModel* Obj, GetShadowObjects_)
    {
        for (s32 i = 0; i < 6; ++i)
        {
            foreach (SFace &Face, Obj->Axles[i].Faces)
            {
                foreach (STriangle &Triangle, Face.Triangles)
                {
                    rasterizeTriangle(Light, Triangle);
                    if (!LightmapGenerator::processRunning())
                        throw std::exception();
                }
            }
        }
    }

    */
}

struct SRasterizerThreadData
{
    std::list<STriangle*>::iterator itStart, itEnd;
    s32* NumRunningThreads;
    CriticalSection* Mutex;
    SLight* Light;
    LightmapGenerator* LMGen;
};

THREAD_PROC(RasterizerThreadProc)
{
    SRasterizerThreadData* ThreadData = reinterpret_cast<SRasterizerThreadData*>(Arguments);

    SLight* Light               = ThreadData->Light;
    LightmapGenerator* LMGen    = ThreadData->LMGen;

    // Rasterize each triangle given to this thread
    for (std::list<STriangle*>::iterator it = ThreadData->itStart, itEnd = ThreadData->itEnd; it != itEnd; ++it)
        LMGen->rasterizeTriangle(Light, **it);

    // Decrement running thread counter
    ThreadData->Mutex->lock();
    --(*ThreadData->NumRunningThreads);
    ThreadData->Mutex->unlock();

    delete ThreadData;

    return 0;
}

void LightmapGenerator::generateLightTexelsMultiThreaded(SLight* Light)
{
    // Find surrounding faces
    std::list<const scene::TreeNode*> TreeNodeList;
    scene::CollisionMesh::TreeNodeDataType* TreeNodeData = 0;

    std::map<STriangle*, bool> UsedTriangles;
    SModel* Obj = 0;

    std::list<STriangle*> SurroundingTriangleList;

    // Find each triangle using the kd-Tree
    CollMesh_->getRootTreeNode()->findLeafList(
        TreeNodeList, Light->Position, Light->FixedVolumetricRadius
    );

    foreach (const scene::TreeNode* Node, TreeNodeList)
    {
        if (!Node->getUserData())
            continue;

        TreeNodeData = static_cast<scene::CollisionMesh::TreeNodeDataType*>(Node->getUserData());

        #ifndef _DEB_NEW_KDTREE_
        foreach (scene::SCollisionFace* Face, *TreeNodeData)
        #else
        foreach (scene::SCollisionFace &NodeFace, *TreeNodeData)
        #endif
        {
            #ifdef _DEB_NEW_KDTREE_
            scene::SCollisionFace* Face = &NodeFace;
            #endif

            // Get model object
            std::map<scene::Mesh*, SModel*>::iterator it = ModelMap_.find(Face->Mesh);

            if (it == ModelMap_.end())
                continue;

            Obj = it->second;

            // Get triangle object
            STriangle* Triangle = (Obj->Triangles[Face->Surface])[Face->Index];

            if (UsedTriangles.find(Triangle) == UsedTriangles.end())
            {
                SurroundingTriangleList.push_back(Triangle);
                UsedTriangles[Triangle] = true;
            }
        }
    }

    // Distribute faces to thread lists
    const u32 MaxBlockSize = math::Max(size_t(1), SurroundingTriangleList.size() / static_cast<size_t>(State_.ThreadCount));

    std::list<STriangle*>::iterator it      = SurroundingTriangleList.begin();
    std::list<STriangle*>::iterator itPrev  = it;

    u32 BlockSize = 0;
    s32 NumRunningThreads = 0;
    u32 NumStartedThreads = 0;

    CriticalSection Mutex;

    typedef boost::shared_ptr<ThreadManager> ThreadManagerPtr;
    std::vector<ThreadManagerPtr> Threads;

    while (1)
    {
        bool EndOfList          = (it == SurroundingTriangleList.end());
        bool ThreadsAlmostFull  = (NumStartedThreads + 1 >= State_.ThreadCount);

        ++BlockSize;

        if ( ( !ThreadsAlmostFull && BlockSize > MaxBlockSize ) || EndOfList )
        {
            // Setup thread data
            SRasterizerThreadData* ThreadData = new SRasterizerThreadData;

            ThreadData->itStart             = itPrev;
            ThreadData->itEnd               = it;
            ThreadData->NumRunningThreads   = (&NumRunningThreads);
            ThreadData->Mutex               = (&Mutex);
            ThreadData->Light               = Light;
            ThreadData->LMGen               = this;

            // Increment running thread counter
            Mutex.lock();
            ++NumRunningThreads;
            Mutex.unlock();

            ++NumStartedThreads;

            // Start new thread
            Threads.push_back(boost::make_shared<ThreadManager>(RasterizerThreadProc, ThreadData));

            // Reset counters
            BlockSize   = 0;
            itPrev      = it;

            if (EndOfList)
                break;
        }

        ++it;
    }

    // Wait here until all threads are finish
    static const u64 CALLBACK_UPDATE_INTERVAL = 100;
    u64 Time = io::Timer::millisecs();

    while (1)
    {
        // Check if threads are no longer running
        Mutex.lock();
        if (NumRunningThreads <= 0)
            break;
        Mutex.unlock();

        // Yield to give the threads time to run
        io::Timer::yield();

        // Progress callback
        if (io::Timer::millisecs() > Time)
        {
            Time = io::Timer::millisecs() + CALLBACK_UPDATE_INTERVAL;
            LightmapGenerator::processRunning(0);
        }
    }

    // Boost process
    LightmapGenerator::processRunning(LightmapGenerator::ProgressShadedTriangleNum_);
}

//! Used for "LMapRasterizePixelCallback" callback
struct SRasterizePixelData
{
    LightmapGenerator* LMGen;
    SFace* Face;
    SLightmap* Lightmap;
    const SLight* Light;
    dim::triangle3df TriangleCoords;
    dim::triangle3df TriangleMap;
};

void LMapRasterizePixelCallback(
    s32 x, s32 y, const SRasterizerVertex &Vertex, void* UserData)
{
    SRasterizePixelData* RasterData = reinterpret_cast<SRasterizePixelData*>(UserData);

    // Set the face into the texel buffer
    SLightmapTexel* Texel = &(RasterData->Lightmap->getTexel(x, y));
    Texel->Face = RasterData->Face;

    // Normalize normal vector
    dim::vector3df Normal(Vertex.Normal);
    Normal.normalize();

    // Compute final coordinate in 3D space via barycentric coordinates
    const dim::vector3df BarycentricCoord(
        math::getBarycentricCoord(
            RasterData->TriangleMap,
            dim::vector3df(static_cast<f32>(x) + 0.5f, static_cast<f32>(y) + 0.5f, 0.0f)
        )
    );

    const dim::vector3df Point = RasterData->TriangleCoords.getBarycentricPoint(BarycentricCoord);

    // Process the texel lighting
    RasterData->LMGen->processTexelLighting(Texel, RasterData->Light, Point, Normal);
}

void LightmapGenerator::rasterizeTriangle(const SLight* Light, const STriangle &Triangle)
{
    // Check if the triangle is able to get any light
    if (!Light->checkVisibility(Triangle))
        return;

    const SVertex* v = Triangle.Vertices;

    // Fill user-data for rasterize pixel callback
    SRasterizePixelData RasterData;
    {
        RasterData.LMGen    = this;
        RasterData.Face     = Triangle.Face;
        RasterData.Lightmap = Triangle.Face->RootLightmap;
        RasterData.Light    = Light;

        RasterData.TriangleCoords.PointA = v[0].Position;
        RasterData.TriangleCoords.PointB = v[1].Position;
        RasterData.TriangleCoords.PointC = v[2].Position;

        for (s32 i = 0; i < 3; ++i)
        {
            RasterData.TriangleMap[i].X = static_cast<f32>(v[i].LMapCoord.X);
            RasterData.TriangleMap[i].Y = static_cast<f32>(v[i].LMapCoord.Y);
        }
    }

    // Rasterize triangle
    math::Rasterizer::rasterizeTriangle<SRasterizerVertex>(
        LMapRasterizePixelCallback,
        SRasterizerVertex(v[0].Position, v[0].Normal, v[0].LMapCoord),
        SRasterizerVertex(v[1].Position, v[1].Normal, v[1].LMapCoord),
        SRasterizerVertex(v[2].Position, v[2].Normal, v[2].LMapCoord),
        (&RasterData)
    );
}

//! Used for "LMapRasterizePixelLocCallback" callback
struct SRasterizePixelLocData
{
    SFace* Face;
    SLightmap* Lightmap;
    dim::triangle3df TriangleCoords;
    dim::triangle3df TriangleMap;
    dim::vector3df Tangent;
};

void LMapRasterizePixelLocCallback(
    s32 x, s32 y, const SRasterizerVertex &Vertex, void* UserData)
{
    SRasterizePixelLocData* RasterData = reinterpret_cast<SRasterizePixelLocData*>(UserData);

    // Set the face into the texel buffer
    SLightmapTexel* Texel = &(RasterData->Lightmap->getTexel(x, y));
    Texel->Face = RasterData->Face;

    // Normalize normal vector
    dim::vector3df Normal(Vertex.Normal);
    Normal.normalize();

    // Compute final coordinate in 3D space via barycentric coordinates
    const dim::vector3df BarycentricCoord(
        math::getBarycentricCoord(
            RasterData->TriangleMap,
            dim::vector3df(static_cast<f32>(x) + 0.5f, static_cast<f32>(y) + 0.5f, 0.0f)
        )
    );

    const dim::vector3df Point = RasterData->TriangleCoords.getBarycentricPoint(BarycentricCoord);

    // Setup texel location
    SLightmapTexelLoc* TexelLoc = &(RasterData->Lightmap->getTexelLoc(x, y));

    TexelLoc->WorldPos  = Point;
    TexelLoc->Normal    = Normal;
    TexelLoc->Tangent   = RasterData->Tangent;
}

void LightmapGenerator::rasterizeTriangleTexelLoc(const LightmapGen::STriangle &Triangle)
{
    const SVertex* v = Triangle.Vertices;

    // Fill user-data for rasterize pixel callback
    SRasterizePixelLocData RasterData;
    {
        RasterData.Face     = Triangle.Face;
        RasterData.Lightmap = Triangle.Face->RootLightmap;

        // We only need any tangent lying onto the triangle's plane,
        // because this tangent is not used for normal mapping.
        RasterData.Tangent = v[1].Position - v[0].Position;
        RasterData.Tangent.normalize();

        RasterData.TriangleCoords.PointA = v[0].Position;
        RasterData.TriangleCoords.PointB = v[1].Position;
        RasterData.TriangleCoords.PointC = v[2].Position;

        for (s32 i = 0; i < 3; ++i)
        {
            RasterData.TriangleMap[i].X = static_cast<f32>(v[i].LMapCoord.X);
            RasterData.TriangleMap[i].Y = static_cast<f32>(v[i].LMapCoord.Y);
        }
    }

    // Rasterize triangle
    math::Rasterizer::rasterizeTriangle<SRasterizerVertex>(
        LMapRasterizePixelLocCallback,
        SRasterizerVertex(v[0].Position, v[0].Normal, v[0].LMapCoord),
        SRasterizerVertex(v[1].Position, v[1].Normal, v[1].LMapCoord),
        SRasterizerVertex(v[2].Position, v[2].Normal, v[2].LMapCoord),
        (&RasterData)
    );
}

void LightmapGenerator::rasterizeTriangleTexelLocLightmap(LightmapGen::SLightmap* Lightmap)
{
    if (Lightmap)
    {
        // Rasterize all triangles which belong to the specified lightmap.
        // Here all texel locations, normals and tangent vectors will be stored into the 'texel location buffer'.
        foreach (SFace* Face, Lightmap->Faces)
        {
            foreach (const STriangle &Tri, Face->Triangles)
                rasterizeTriangleTexelLoc(Tri);
        }
    }
}

void LightmapGenerator::processTexelLighting(
    SLightmapTexel* Texel, const SLight* Light, const dim::vector3df &Position, const dim::vector3df &Normal)
{
    static const f32 PICK_ROUND_ERR = 1.0e-4f;

    // Configure the picking ray
    dim::line3df PickLine;

    PickLine.End = Position;

    if (Light->Type == scene::LIGHT_DIRECTIONAL)
        PickLine.Start = PickLine.End - Light->FixedDirection * 100;
    else
        PickLine.Start = Light->Position;

    // Temporary variables
    dim::vector3df Color(1.0f);

    if (!(State_.Flags & LIGHTMAPFLAG_NOCOLORS))
        Color = Light->Color;

    video::MeshBuffer* Surface = 0;
    scene::Mesh* Mesh = 0;
    u32 Indices[3];

    if (State_.Flags & LIGHTMAPFLAG_NOTRANSPARENCY)
    {
        if (CollSys_.checkIntersection(PickLine, true))
            return;
    }
    else
    {
        // Make intersection tests
        std::list<scene::SIntersectionContact> ContactList;
        CollSys_.findIntersections(PickLine, ContactList);

        // Analyse the intersection results
        foreach (const scene::SIntersectionContact &Contact, ContactList)
        {
            // Finish the picking analyse
            if (math::getDistanceSq(Contact.Point, Position) <= PICK_ROUND_ERR)
                break;

            // Process transparency objects
            if (!Contact.Face)
                continue;

            Mesh    = Contact.Face->Mesh;
            Surface = Contact.Face->Mesh->getMeshBuffer(Contact.Face->Surface);

            Surface->getTriangleIndices(Contact.Face->Index, Indices);

            if ( Mesh->getMaterial()->getDiffuseColor().Alpha < 255 ||
                 Surface->getVertexColor(Indices[0]).Alpha < 255 ||
                 Surface->getVertexColor(Indices[1]).Alpha < 255 ||
                 Surface->getVertexColor(Indices[2]).Alpha < 255 ||
                 ( Surface->getTexture(0) && Surface->getTexture(0)->getColorKey().Alpha < 255 ) )
            {
                dim::point2df TexCoord;
                dim::vector3df VertexColor;
                f32 Alpha;

                STriangle::computeInterpolation(Contact, Indices, 0, TexCoord, VertexColor, Alpha);

                if (Surface->getTexture(0))
                {
                    video::ImageBuffer* ImgBuffer = Surface->getTexture(0)->getImageBuffer();
                    const video::color TexelColor(
                        ImgBuffer->getPixelColor(ImgBuffer->getPixelCoord(TexCoord))
                    );

                    Alpha *= static_cast<f32>(TexelColor.Alpha) / 255;
                    Color *= ( SVertex::getVectorColor(TexelColor) * Alpha + (1.0f - Alpha) );
                }

                Color *= VertexColor * (1.0f - Alpha);
            }
            else
                return;
        }
    }

    Color *= Light->getIntensity(Position, Normal);

    Texel->Color.Red    = math::MinMax<s32>(static_cast<s32>(Color.X * 255.0f) + Texel->Color.Red   , 0, 255);
    Texel->Color.Green  = math::MinMax<s32>(static_cast<s32>(Color.Y * 255.0f) + Texel->Color.Green , 0, 255);
    Texel->Color.Blue   = math::MinMax<s32>(static_cast<s32>(Color.Z * 255.0f) + Texel->Color.Blue  , 0, 255);
}

void LightmapGenerator::shadeAllLightmaps()
{
    if (State_.useGPU())
        shadeAllLightmapsOnGPU();
    else
        shadeAllLightmapsOnCPU();
}

void LightmapGenerator::shadeAllLightmapsOnCPU()
{
    u32 InfoLightNum = 0;

    // Compute each texel color of the infected triangle's face's lightmap by each light source
    foreach (SLight* Lit, LightSources_)
    {
        if (!LightmapGenerator::processRunning(0))
            throw std::exception();

        updateStateInfo(
            LIGHTMAPSTATE_SHADING,
            "Light source " + io::stringc(++InfoLightNum) + " / " + io::stringc(LightSources_.size())
        );

        if (State_.ThreadCount > 1)
            generateLightTexelsMultiThreaded(Lit);
        else
            generateLightTexelsSingleThreaded(Lit);
    }
}

//!INCOMPLETE!
void LightmapGenerator::shadeAllLightmapsOnGPU()
{
    u32 InfoLightmapNum = 0;

    // Compute inverse world matrix (using the scene's bounding box)
    dim::matrix4f InvWorldMatrix;
    //todo ...

    // Dispatch compute shader for each lightmap
    foreach (SLightmap* LMap, Lightmaps_)
    {
        if (!LightmapGenerator::processRunning(0))
            throw std::exception();

        updateStateInfo(
            LIGHTMAPSTATE_SHADING,
            "Lightmap " + io::stringc(++InfoLightmapNum) + " / " + io::stringc(Lightmaps_.size())
        );

        // Setup lightmap texel location buffer
        rasterizeTriangleTexelLocLightmap(LMap);

        // Dispatch compute shader
        GPUDispatcher_.setupLightmapGrid(LMap);
        GPUDispatcher_.dispatchDirectIllumination(InvWorldMatrix, State_.AmbientColor);

        //if (State_.useRadiosity())
        //    GPUDispatcher_.dispatchIndirectIllumination(InvWorldMatrix);
    }
}

void LightmapGenerator::partitionScene(f32 DefaultDensity)
{
    updateStateInfo(LIGHTMAPSTATE_PARTITIONING);

    foreach (SModel* Mdl, GetShadowObjects_)
    {
        if (!LightmapGenerator::processRunning())
            throw std::exception();

        Mdl->partitionMesh(LightmapGenerator::LightmapSize_, DefaultDensity);
        createFacesLightmaps(Mdl);
    }
}

void LightmapGenerator::createNewLightmap()
{
    bool UseTexelLocBuffer = State_.useGPU();

    CurLightmap_ = new SLightmap(LightmapSize_, true, UseTexelLocBuffer);
    {
        CurLightmap_->RectNode = new TRectNode();
        CurLightmap_->RectNode->setRect(dim::rect2di(0, 0, LightmapSize_.Width, LightmapSize_.Height));

        CurRectRoot_ = CurLightmap_->RectNode;
    }
    Lightmaps_.push_back(CurLightmap_);
}

void LightmapGenerator::putFaceIntoLightmap(SFace* Face)
{
    // Insert the face's lightmap into the current tree hierarchy
    TRectNode* Node = CurRectRoot_->insert(Face->Lightmap);

    // Store reference to the current final lightmap for the specified face
    Face->RootLightmap = CurLightmap_;

    if (Node)
    {
        // Add this face to the lightmap face list if GPU acceleration is used (otherwise we don't need this list)
        if (State_.useGPU())
            CurLightmap_->Faces.push_back(Face);

        // Map triangle texture coordiantes to be used in the final lightmap
        const dim::rect2di Rect(Face->Lightmap->RectNode->getRect());

        foreach (STriangle &Tri, Face->Triangles)
        {
            for (s32 i = 0; i < 3; ++i)
            {
                Tri.Vertices[i].LMapCoord.X += Rect.Left + 1;
                Tri.Vertices[i].LMapCoord.Y += Rect.Top  + 1;
            }
        }
    }
    else
    {
        // The face's lightmap does not fit into the current tree hierarchy -> create new lightmap.
        createNewLightmap();
        putFaceIntoLightmap(Face);
    }
}

void LightmapGenerator::buildFinalMesh(SModel* Model)
{
    if (Model->StayAlone)
    {
        scene::Mesh* Mesh = GlbSceneGraph->createMesh();

        Mesh->setName(Model->Mesh->getName());
        Mesh->setUserData(Model->Mesh->getUserData());

        Model->buildFaces(Mesh, LightmapGenerator::LightmapSize_);
        Mesh->mergeMeshBuffers();
        Mesh->getMaterial()->setLighting(false);

        SingleModels_.push_back(Mesh);
    }
    else
        Model->buildFaces(FinalModel_, LightmapGenerator::LightmapSize_);
}

void LightmapGenerator::buildAllFinalModels()
{
    // Build all final models
    foreach (SModel* Obj, GetShadowObjects_)
    {
        if (!LightmapGenerator::processRunning())
            throw std::exception();
        buildFinalMesh(Obj);
    }

    // Finalize and optimize final model
    FinalModel_->updateMeshBuffer();
    FinalModel_->mergeMeshBuffers();
}

//! Used for "LMapBlurPixelCallback" callback.
struct SBlurPixelData
{
    SLightmap* Map;
    SFace* Face;
    s32 Factor;
};

void LMapBlurPixelCallback(s32 x, s32 y, void* UserData)
{
    SBlurPixelData* BlurData = reinterpret_cast<SBlurPixelData*>(UserData);

    // Store options
    SLightmap* Map      = BlurData->Map;
    SFace* Face         = BlurData->Face;
    const s32 Factor    = BlurData->Factor;

    // Blur the texel
    s32 dx, dy, c = 0;
    dim::vector3df Color;

    for (dy = y - Factor; dy <= y + Factor; ++dy)
    {
        if (dy < 0 || dy >= LightmapGenerator::LightmapSize_.Width)
            continue;

        for (dx = x - Factor; dx <= x + Factor; ++dx)
        {
            // Check if the texel is inside the lightmap's face area
            if (dx < 0 || dx >= LightmapGenerator::LightmapSize_.Height || Map->getTexel(dx, dy).Face != Face)
                continue;

            Color += Map->getTexel(dx, dy).OrigColor.getVector();
            ++c;
        }
    }

    if (c)
        Map->getTexel(x, y).Color = video::color(Color / static_cast<f32>(c), false);
}

void LightmapGenerator::blurLightmapTexels(SModel* Model, s32 Factor)
{
    SBlurPixelData BlurData;
    BlurData.Factor = Factor;

    for (s32 i = 0; i < 6; ++i)
    {
        foreach (SFace &Face, Model->Axles[i].Faces)
        {
            BlurData.Map    = Face.RootLightmap;
            BlurData.Face   = (&Face);

            foreach (STriangle &Tri, Face.Triangles)
            {
                math::Rasterizer::rasterizeTriangle(
                    LMapBlurPixelCallback,
                    Tri.Vertices[0].LMapCoord,
                    Tri.Vertices[1].LMapCoord,
                    Tri.Vertices[2].LMapCoord,
                    (&BlurData)
                );
            }
        }
    }
}

void LightmapGenerator::blurAllLightmaps(u8 TexelBlurRadius)
{
    updateStateInfo(LIGHTMAPSTATE_BLURING);

    // Blur the lightmaps' texels
    foreach (SModel* Mdl, GetShadowObjects_)
    {
        if (!LightmapGenerator::processRunning())
            throw std::exception();
        blurLightmapTexels(Mdl, static_cast<s32>(TexelBlurRadius));
    }
}

void LightmapGenerator::createFinalLightmapTextures(const video::color &AmbientColor)
{
    updateStateInfo(LIGHTMAPSTATE_BAKING);

    foreach (SLightmap* LMap, Lightmaps_)
    {
        // Reduce texture bleeding and create final texture with given ambient color
        LMap->reduceBleeding();
        LMap->createTexture(AmbientColor);
    }
}

void LightmapGenerator::updateStateInfo(const ELightmapGenerationStates State, const io::stringc &Info)
{
    if (StateCallback_)
        StateCallback_(State, Info);
}

void LightmapGenerator::clearLightmapObjects()
{
    // Delete all old lightmaps
    foreach (SLightmap* LMap, Lightmaps_)
        MemoryManager::deleteMemory(LMap);
    Lightmaps_.clear();

    // Delete the get-shadow objects, light sources & lightmap textures
    MemoryManager::deleteList(GetShadowObjects_);
    MemoryManager::deleteList(LightSources_);
}

bool LightmapGenerator::processRunning(s32 BoostFactor)
{
    if (!ProgressCallback_)
        return true;

    Progress_ += BoostFactor;

    f32 Percent = static_cast<f32>(Progress_);

    if (ProgressMax_)
        Percent /= ProgressMax_;

    return ProgressCallback_(Percent);
}

io::stringc LightmapGenerator::getProcessInfo(const u8 ThreadCount, const u32 Flags)
{
    io::stringc Info;

    if (Flags & LIGHTMAPFLAG_GPU_ACCELERATION)
    {
        Info += "Hardware Accelerated";
        if (Flags & LIGHTMAPFLAG_RADIOSITY)
            Info += ", Radiosity";
    }
    else if (ThreadCount > 0)
        Info += "Multi-Threaded (" + io::stringc(static_cast<u32>(ThreadCount)) + " Threads)";
    else
        Info += "Single-Threaded";

    return Info;
}

/*
 * SInternalState structure
 */

LightmapGenerator::SInternalState::SInternalState() :
    Flags                   (0      ),
    AmbientColor            (20     ),
    TexelBlurRadius         (0      ),
    ThreadCount             (0      ),
    HasGeneratedSuccessful  (false  )
{
}
LightmapGenerator::SInternalState::~SInternalState()
{
}

void LightmapGenerator::SInternalState::validateFlags()
{
    if (useGPU() && !GlbRenderSys->queryVideoSupport(video::VIDEOSUPPORT_COMPUTE_SHADER))
    {
        io::Log::warning("Hardware acceleration for lightmap generation is not available");
        math::removeFlag(Flags, LIGHTMAPFLAG_GPU_ACCELERATION);
        math::removeFlag(Flags, LIGHTMAPFLAG_GPU_TREE_HIERARCHY);
    }
    if (useRadiosity() && !useGPU())
    {
        io::Log::warning("Radiosity lightmap generation is only supported with hardware acceleration");
        math::removeFlag(Flags, LIGHTMAPFLAG_RADIOSITY);
    }
}

} // /namespace tool

} // /namespace sp

#endif

// ================================================================================

max_stars_repo_name: rontrek/softpixel

max_issues_repo_name: rontrek/softpixel

max_forks_repo_name: rontrek/softpixel


text:
// Copyright 2010 Christophe Henry
// henry UNDERSCORE christophe AT hotmail DOT com
// This is an extended version of the state machine available in the boost::mpl library
// Distributed under the same license as the original.
// Copyright for the original version:
// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
// under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#ifndef MENU_MODE_HPP
#define MENU_MODE_HPP

#include <iostream>
#include <boost/any.hpp>

#include "Events.hpp"
#include <boost/msm/back/favor_compile_time.hpp>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>

using namespace std;
namespace msm = boost::msm;

struct MenuMode_ : public msm::front::state_machine_def<MenuMode_>
{
    typedef mpl::vector1<MenuActive>        flag_list;
    struct WaitingForSongChoice : public msm::front::state<>
    {
        template <class Event,class FSM>
        void on_entry(Event const&,FSM& ) {std::cout << "starting: MenuMode::WaitingForSongChoice" << std::endl;}
        template <class Event,class FSM>
        void on_exit(Event const&,FSM& ) {std::cout << "finishing: MenuMode::WaitingForSongChoice" << std::endl;}
    };
    struct StartCurrentSong : public msm::front::state<>
    {
        template <class Event,class FSM>
        void on_entry(Event const&,FSM& ) {std::cout << "starting: MenuMode::StartCurrentSong" << std::endl;}
        template <class Event,class FSM>
        void on_exit(Event const&,FSM& ) {std::cout << "finishing: MenuMode::StartCurrentSong" << std::endl;}
    };
    struct MenuExit : public msm::front::exit_pseudo_state<CloseMenu>
    {
        template <class Event,class FSM>
        void on_entry(Event const&,FSM& ) {std::cout << "starting: MenuMode::WaitingForSongChoice" << std::endl;}
        template <class Event,class FSM>
        void on_exit(Event const&,FSM& ) {std::cout << "finishing: MenuMode::WaitingForSongChoice" << std::endl;}
    };
    typedef WaitingForSongChoice initial_state;
    typedef MenuMode_ fsm; // makes transition table cleaner
    // Transition table for player
    struct transition_table : mpl::vector2<
        //     Start                 Event           Next                Action                   Guard
        //    +---------------------+------------------+-------------------+---------------------+----------------------+
        _row < WaitingForSongChoice , MenuMiddleButton , StartCurrentSong                                               >,
        _row < StartCurrentSong     , SelectSong       , MenuExit                                                       >
        //    +---------------------+------------------+-------------------+---------------------+----------------------+
    > {};
};
typedef msm::back::state_machine<MenuMode_> MenuMode;

#endif

ext: hpp

max_stars_repo_name: zyiacas/boost-doc-zh

max_issues_repo_name: sdfict/boost-doc-zh

max_forks_repo_name: sdfict/boost-doc-zh


text:
//          Copyright Gavin Band 2008 - 2012.
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#ifndef GENFILE_VARIABLEINSET_SAMPLE_FILTER_HPP
#define GENFILE_VARIABLEINSET_SAMPLE_FILTER_HPP

#include <memory>
#include <vector>
#include <set>
#include <boost/ptr_container/ptr_vector.hpp>
#include "genfile/VariantEntry.hpp"
#include "genfile/SampleFilter.hpp"
#include "genfile/impl/cast_types_for_comparison.hpp"

namespace genfile {
	struct VariableInSetSampleFilter: public SampleFilter
	{
	public:
		typedef std::auto_ptr< VariableInSetSampleFilter > UniquePtr ;

	public:
		VariableInSetSampleFilter( std::string const& variable ) ;

		void summarise( std::ostream& o ) const ;
		void add_level( genfile::VariantEntry value ) ;
		bool test( genfile::CohortIndividualSource const& source, std::size_t i, DetailBlock* ) const ;

	private:
		std::string const m_variable ;
		std::vector< genfile::VariantEntry > m_levels ;
		friend struct VariableNotInSetSampleFilter ;
	} ;

	/* This class only exists because it prints itself more nicely than the negation of the above. */
	struct VariableNotInSetSampleFilter: public SampleFilter
	{
	public:
		typedef std::auto_ptr< VariableNotInSetSampleFilter > UniquePtr ;

	public:
		VariableNotInSetSampleFilter( std::string const& variable ) ;
		void summarise( std::ostream& o ) const ;
		void add_level( genfile::VariantEntry value ) ;
		bool test( genfile::CohortIndividualSource const& source, std::size_t i, DetailBlock* ) const ;

	private:
		VariableInSetSampleFilter m_inverse_filter ;
	} ;
}

#endif

max_stars_repo_name: gavinband/bingwa

max_issues_repo_name: gavinband/bingwa

max_forks_repo_name: gavinband/bingwa


text:
/*
	Program to Demonstrate the Use of Boost variant and Visitor concept.
*/
#include<iostream>
#include <boost/variant.hpp>

using namespace std;

int main()
{
	cout << "Hello World" << endl;

	/* union allows datatypes of primitive type,
	if I want to use strings in union, it will throw an error.
	To solve this problem we can use boost::variant*/
	union
	{
		int i;
		float f;
		//string s;
	} u;

	/*
		Boost variant allow us to make union of arbitrary datatypes. :)
	*/

	boost::variant<int, string> u1;
	u1 = 2;	// u1 becomes an int here
	cout << u1 << endl;
	u1 = "a string";	// u1 becomes a string here
	cout << u1 << endl;

	string str = boost::get<string>(u1);
	u1 = "good string"; // u1 is a string

	cout << u1 << endl;

	// If a function is taking a variant as a parameter, then we don't
	// know which datatype the variant is holding in actual.
	// eg. void Double(boost::variant<int, string> x);
	// we use visitors to solve this problem
	// We use operator overloading inside Visitor class, so that each
	// datatype gets a function for its own type.

	class DoubleVisitor : public boost::static_visitor<>
	{
	public:
		void operator()(int& i) const
		{
			i = i + i;
		}

		void operator()(string& i) const
		{
			i = i + i;
		}
	};

	u1 = 2;
	boost::apply_visitor(DoubleVisitor(), u1);	// 2 becomes 4
	cout << u1 << endl;

	u1 = "hello";
	boost::apply_visitor(DoubleVisitor(), u1);	// "hello" becomes "hellohello"
	cout << u1 << endl;

	getchar();
	return 0;
}

ext: cpp


text:
// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
// (C) Copyright 2003-2007 Jonathan Turkanis
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)

// See http://www.boost.org/libs/iostreams for documentation.

// To configure Boost to work with libbz2, see the
// installation instructions here:
// http://boost.org/libs/iostreams/doc/index.html?path=7

// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp>
// knows that we are building the library (possibly exporting code), rather
// than using it (possibly importing code).
#define BOOST_IOSTREAMS_SOURCE

#include <boost/throw_exception.hpp>
#include <boost/iostreams/detail/config/dyn_link.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
#include "bzlib.h"  // Julian Seward's "bzip.h" header.
                    // To configure Boost to work with libbz2, see the
                    // installation instructions here:
                    // http://boost.org/libs/iostreams/doc/index.html?path=7

namespace boost { namespace iostreams {

namespace bzip2 {

                    // Status codes

const int ok                   = BZ_OK;
const int run_ok               = BZ_RUN_OK;
const int flush_ok             = BZ_FLUSH_OK;
const int finish_ok            = BZ_FINISH_OK;
const int stream_end           = BZ_STREAM_END;
const int sequence_error       = BZ_SEQUENCE_ERROR;
const int param_error          = BZ_PARAM_ERROR;
const int mem_error            = BZ_MEM_ERROR;
const int data_error           = BZ_DATA_ERROR;
const int data_error_magic     = BZ_DATA_ERROR_MAGIC;
const int io_error             = BZ_IO_ERROR;
const int unexpected_eof       = BZ_UNEXPECTED_EOF;
const int outbuff_full         = BZ_OUTBUFF_FULL;
const int config_error         = BZ_CONFIG_ERROR;

                    // Action codes

const int finish               = BZ_FINISH;
const int run                  = BZ_RUN;

} // End namespace bzip2.

//------------------Implementation of bzip2_error-----------------------------//

bzip2_error::bzip2_error(int error)
    : BOOST_IOSTREAMS_FAILURE("bzip2 error"), error_(error)
    { }

void bzip2_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(int error)
{
    switch (error) {
    case BZ_OK:
    case BZ_RUN_OK:
    case BZ_FLUSH_OK:
    case BZ_FINISH_OK:
    case BZ_STREAM_END:
        return;
    case BZ_MEM_ERROR:
        boost::throw_exception(std::bad_alloc());
    default:
        boost::throw_exception(bzip2_error(error));
    }
}

//------------------Implementation of bzip2_base------------------------------//

namespace detail {

bzip2_base::bzip2_base(const bzip2_params& params)
    : params_(params), stream_(new bz_stream), ready_(false)
    { }

bzip2_base::~bzip2_base() { delete static_cast<bz_stream*>(stream_); }

void bzip2_base::before( const char*& src_begin, const char* src_end,
                         char*& dest_begin, char* dest_end )
{
    bz_stream* s = static_cast<bz_stream*>(stream_);
    s->next_in = const_cast<char*>(src_begin);
    s->avail_in = static_cast<unsigned>(src_end - src_begin);
    s->next_out = reinterpret_cast<char*>(dest_begin);
    s->avail_out= static_cast<unsigned>(dest_end - dest_begin);
}

void bzip2_base::after(const char*& src_begin, char*& dest_begin)
{
    bz_stream* s = static_cast<bz_stream*>(stream_);
    src_begin = const_cast<char*>(s->next_in);
    dest_begin = s->next_out;
}

int bzip2_base::check_end(const char* src_begin, const char* dest_begin)
{
    bz_stream* s = static_cast<bz_stream*>(stream_);
    if( src_begin == s->next_in &&
        s->avail_in == 0 &&
        dest_begin == s->next_out) {
        return bzip2::unexpected_eof;
    } else {
        return bzip2::ok;
    }
}

void bzip2_base::end(bool compress)
{
    if(!ready_) return;
    ready_ = false;
    bz_stream* s = static_cast<bz_stream*>(stream_);
    bzip2_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
        compress ?
            BZ2_bzCompressEnd(s) :
            BZ2_bzDecompressEnd(s)
    );
}

int bzip2_base::compress(int action)
{
    return BZ2_bzCompress(static_cast<bz_stream*>(stream_), action);
}

int bzip2_base::decompress()
{
    return BZ2_bzDecompress(static_cast<bz_stream*>(stream_));
}

void bzip2_base::do_init
    ( bool compress,
      #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
          bzip2::alloc_func /* alloc */,
          bzip2::free_func /* free */,
      #endif
      void* derived )
{
    bz_stream* s = static_cast<bz_stream*>(stream_);

    // Current interface for customizing memory management
    // is non-conforming and has been disabled:
    //#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
    //    s->bzalloc = alloc;
    //    s->bzfree = free;
    //#else
        s->bzalloc = 0;
        s->bzfree = 0;
    //#endif
    s->opaque = derived;
    bzip2_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
        compress ?
            BZ2_bzCompressInit( s,
                                params_.block_size,
                                0,
                                params_.work_factor ) :
            BZ2_bzDecompressInit( s,
                                  0,
                                  params_.small )
    );
    ready_ = true;
}

} // End namespace detail.

//----------------------------------------------------------------------------//

} } // End namespaces iostreams, boost.


text:
/**
 *-----------------------------------------------------------------------------
 * Title      : Release GIL within scope.
 * ----------------------------------------------------------------------------
 * File       : GilRelease.cpp
 * Created    : 2017-02-28
 * ----------------------------------------------------------------------------
 * Description:
 * Release GIL for the scope of this class.
 * ----------------------------------------------------------------------------
 * This file is part of the rogue software platform. It is subject to
 * the license terms in the LICENSE.txt file found in the top-level directory
 * of this distribution and at:
 *    https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
 * No part of the rogue software platform, including this file, may be
 * copied, modified, propagated, or distributed except according to the terms
 * contained in the LICENSE.txt file.
 * ----------------------------------------------------------------------------
**/
#include <stdint.h>
#include <rogue/GilRelease.h>

#ifndef NO_PYTHON

#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <boost/python.hpp>
namespace bp = boost::python;
#endif

rogue::GilRelease::GilRelease() {
#ifndef NO_PYTHON
   state_ = NULL;
   release();
#endif
}

rogue::GilRelease::~GilRelease() {
#ifndef NO_PYTHON
   acquire();
#endif
}

void rogue::GilRelease::acquire() {
#ifndef NO_PYTHON
   if ( state_ != NULL ) PyEval_RestoreThread(state_);
   state_ = NULL;
#endif
}

void rogue::GilRelease::release() {
#ifndef NO_PYTHON
   if ( Py_IsInitialized() && PyGILState_Check() )
      state_ = PyEval_SaveThread();
   else state_ = NULL;
#endif
}

max_stars_repo_name: slaclab/rouge

max_issues_repo_name: slaclab/rouge

max_forks_repo_name: slaclab/rouge


text:
#ifndef SPROUT_TYPE_BOOST_MPL_VECTOR_HPP
#define SPROUT_TYPE_BOOST_MPL_VECTOR_HPP

#include <sprout/config.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/at.hpp>
#include <sprout/type/tuple.hpp>
#include <sprout/type/boost/mpl/v_iter.hpp>

namespace sprout {
	namespace types {
		//
		// begin
		//
		template<typename... Types>
		struct begin<boost::mpl::vector<Types...> >
			: public boost::mpl::begin<boost::mpl::vector<Types...> >
		{};
		//
		// end
		//
		template<typename... Types>
		struct end<boost::mpl::vector<Types...> >
			: public boost::mpl::end<boost::mpl::vector<Types...> >
		{};

		//
		// tuple_size
		//
		template<typename... Types>
		struct tuple_size<boost::mpl::vector<Types...> >
			: public boost::mpl::size<boost::mpl::vector<Types...> >
		{};
		//
		// tuple_element
		//
		template<std::size_t I, typename... Types>
		struct tuple_element<I, boost::mpl::vector<Types...> >
			: public boost::mpl::at_c<boost::mpl::vector<Types...>, I>
		{};
	}	// namespace types
}	// namespace sprout

#endif	// #ifndef SPROUT_TYPE_BOOST_MPL_VECTOR_HPP

max_stars_repo_name: osyo-manga/Sprout

max_issues_repo_name: jwakely/Sprout

max_forks_repo_name: jwakely/Sprout


text:
////////////////////////////////////////////////////////////////////////////////////////////////////
// and.hpp
// Contains the behavior of proto::and_ when used as a grammar element.
//
//  Copyright 2012 Eric Niebler. Distributed under the Boost
//  Software License, Version 1.0. (See accompanying file
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_PROTO_V5_GRAMMAR_AND_HPP_INCLUDED
#define BOOST_PROTO_V5_GRAMMAR_AND_HPP_INCLUDED

#include <boost/proto/v5/proto_fwd.hpp>
#include <boost/proto/v5/action/basic_action.hpp>
#include <boost/proto/v5/grammar/basic_grammar.hpp>
#include <boost/proto/v5/utility.hpp>

namespace boost
{
    namespace proto
    {
        inline namespace v5
        {
            namespace extension
            {
                // Handle proto::and_
                template<typename ...BoolActions>
                struct grammar_impl<proto::v5::and_(BoolActions...)>
                {
                    template<typename Expr>
                    struct apply
                      : utility::and_<detail::eval_bool_action_<BoolActions, Expr>...>
                    {};
                };
            }
        }
    }
}

#endif


text:
#pragma once

#include <memory>

#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/ip/tcp.hpp>

#include <eosio/chain_plugin/chain_plugin.hpp>
#include <eosio/chain/plugin_interface.hpp>

namespace eosio{

    class eoc_relay_plugin;
}

namespace eoc_icp {

class icp_connection;
using namespace std;
using tcp = boost::asio::ip::tcp;
namespace ws = boost::beast::websocket;
using icp_connection_ptr = std::shared_ptr<icp_connection>;
using namespace eosio;
using namespace eosio::chain;
using namespace eosio::chain::plugin_interface;

 class dispatch_manager {
   public:
      uint32_t just_send_it_max = 0;

      //vector<transaction_id_type> req_trx;

      //std::multimap<block_id_type, connection_ptr> received_blocks;
      //std::multimap<transaction_id_type, connection_ptr> received_transactions;

      //void bcast_transaction (const packed_transaction& msg);
      //void rejected_transaction (const transaction_id_type& msg);
      //void bcast_block (const signed_block& msg);
      //void rejected_block (const block_id_type &id);

      //void recv_block (connection_ptr conn, const block_id_type& msg, uint32_t bnum);
      //void recv_transaction(connection_ptr conn, const transaction_id_type& id);
      //void recv_notice (connection_ptr conn, const notice_message& msg, bool generated);

      void retry_fetch (icp_connection_ptr conn);
   };

class icp_sync_manager {
   private:
      enum stages {
         lib_catchup,
         head_catchup,
         in_sync
      };

      uint32_t       sync_known_lib_num;
      uint32_t       sync_last_requested_num;
      uint32_t       sync_next_expected_num;
      uint32_t       sync_req_span;
      icp_connection_ptr source;
      stages         state;

      chain_plugin* chain_plug = nullptr;

      constexpr auto stage_str(stages s );

   public:
      explicit icp_sync_manager(uint32_t span);
      void set_state(stages s);
      bool sync_required();
      void recv_handshake (icp_connection_ptr c, const icp_handshake_message &msg);

   };

}

max_stars_repo_name: tianyalangzi/eocs

max_issues_repo_name: tianyalangzi/eocs

max_forks_repo_name: tianyalangzi/eocs


text:
// Copyright 2010-2014 RethinkDB, all rights reserved.
#include "perfmon/filter.hpp"

#include "errors.hpp"
#include <boost/tokenizer.hpp>

#include "logger.hpp"
#include "perfmon/core.hpp"
#include "utils.hpp"

/* Construct a filter from a set of paths.  Paths are of the form foo/bar/baz,
   where each of those can be a regular expression.  They act a lot like XPath
   expressions, but for perfmon_t objects.  */
perfmon_filter_t::perfmon_filter_t(const std::set<std::vector<std::string> > &paths) {
    for (auto const &path : paths) {
        std::vector<scoped_ptr_t<RE2> > compiled_path;
        for (auto const &str : path) {
            scoped_ptr_t<RE2> re = make_scoped<RE2>("^" + str + "$");
            if (!re->ok()) {
                logWRN("Error: regex %s failed to compile, treating as empty.",
                       sanitize_for_logger(str).c_str());
				re = scoped_ptr_t<RE2>(new RE2("^$"));
                if (!re->ok()) {
                    crash("Regex '^$' failed to compile.\n");
                }
            }

            compiled_path.emplace_back(std::move(re));
        }
        regexps.emplace_back(std::move(compiled_path));
    }
}

ql::datum_t perfmon_filter_t::filter(const ql::datum_t &stats) const {
    guarantee(stats.has(), "perfmon_filter_t::filter was passed an uninitialized datum");
    return subfilter(stats, 0, std::vector<bool>(regexps.size(), true));
}

/* Filter a perfmon result.  [depth] is how deep we are in the paths that
   the [perfmon_filter_t] was constructed from, and [active] is the set of paths
   that are still active (i.e. that haven't failed a match yet).  This should
   only be called by [filter]. */
ql::datum_t perfmon_filter_t::subfilter(const ql::datum_t &stats,
                                        const size_t depth,
                                        const std::vector<bool> active) const {
    if (stats.get_type() == ql::datum_t::R_OBJECT) {
        ql::datum_object_builder_t builder;

        for (size_t i = 0; i < stats.obj_size(); ++i) {
            std::vector<bool> subactive = active;
            std::pair<datum_string_t, ql::datum_t> pair = stats.get_pair(i);

            bool some_subpath = false;
            for (size_t j = 0; j < regexps.size(); ++j) {
                if (!active[j]) {
                    continue;
                }
                if (depth >= regexps[j].size()) {
                    some_subpath = true;
                    continue;
                }
                subactive[j] = RE2::FullMatch(pair.first.to_std(), *regexps[j][depth]);
                some_subpath |= subactive[j];
            }

            // Only write the stats if there was a match somewhere down the tree
            if (some_subpath) {
                ql::datum_t sub_stats = subfilter(pair.second, depth + 1, subactive);
                if (sub_stats.get_type() != ql::datum_t::R_OBJECT ||
                    sub_stats.obj_size() > 0) {
                    builder.overwrite(pair.first, sub_stats);
                }
            }
        }

        return std::move(builder).to_datum();
    }

    return stats;
}

ext: cc

max_stars_repo_name: zadcha/rethinkdb

max_issues_repo_name: RethonkDB/rethonkdb

max_forks_repo_name: RethonkDB/rethonkdb


text:
// Copyright (c) 2009-2019 The Bitcoin Core developers
// Copyright (c) 2014-2019 The DigiByte Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <chainparams.h>
#include <validation.h>
#include <net.h>

#include <test/test_digibyte.h>

#include <boost/signals2/signal.hpp>
#include <boost/test/unit_test.hpp>

#define END_OF_SUPPLY_CURVE 110579600

// Set OUTPUT_SUPPLY_SAMPLES_ENABLED to 1 to output
// sampled Supply-curve data points (SAMPLE_INTERVAL)
#ifndef OUTPUT_SUPPLY_SAMPLES_ENABLED
    #define OUTPUT_SUPPLY_SAMPLES_ENABLED 0
#endif

#ifndef SAMPLE_INTERVAL
    #define SAMPLE_INTERVAL 100
#endif

#ifndef WHOLE_COIN
    #define WHOLE_COIN false
#endif

#define CALC_COIN(amount) (WHOLE_COIN ? (amount / COIN) : (amount))

#if OUTPUT_SUPPLY_SAMPLES_ENABLED
    #define DEBUG(x,y) if (x % SAMPLE_INTERVAL == 0) { \
        std::cerr << x << ';' << CALC_COIN(y) << std::endl; \
    }
#else
    #define DEBUG(x,y) (void) (x)
#endif

#ifndef BLOCK_TIME_SECONDS
    #define BLOCK_TIME_SECONDS 15
#endif

#ifndef SECONDS_PER_MONTH
    #define SECONDS_PER_MONTH (60 * 60 * 24 * 365 / 12)
#endif

#ifndef ENABLE_TESTNET_SUBSIDY_TESTS
    #define ENABLE_TESTNET_SUBSIDY_TESTS 0
#endif

BOOST_FIXTURE_TEST_SUITE(main_tests, TestingSetup)

static void TestBlockSubsidy(const Consensus::Params& consensusParams, int nMaxBlocks, CAmount* nSumOut)
{
    CAmount nSum = 0;
    CAmount nInitialSubsidy = 72000 * COIN;

    CAmount nPreviousSubsidy = nInitialSubsidy * 2; // for height == 0
    BOOST_CHECK_EQUAL(nPreviousSubsidy, nInitialSubsidy * 2);

    /* Before first hard fork */

    // 72000 reward for the first 1440 blocks
    for (int nBlocks = 0; nBlocks < 1440 && nBlocks < consensusParams.nDiffChangeTarget; ++nBlocks)
    {
        int nHeight = nBlocks;
        CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams);
        BOOST_CHECK_EQUAL(nSubsidy, nInitialSubsidy);

        nSum += nSubsidy;
        DEBUG(nBlocks, nSubsidy);
    }

    // 16000 rewards until block height 5760
    for (int nBlocks = 1440; nBlocks < 5760 && nBlocks < consensusParams.nDiffChangeTarget; ++nBlocks)
    {
        int nHeight = nBlocks;
        CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams);
        BOOST_CHECK_EQUAL(nSubsidy, 16000 * COIN);

        nSum += nSubsidy;
        DEBUG(nBlocks, nSubsidy);
    }

    // 8000 mining rewards until block height 67,200
    for (int nBlocks = 5760; nBlocks < consensusParams.nDiffChangeTarget; ++nBlocks)
    {
        int nHeight = nBlocks;
        CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams);
        BOOST_CHECK_EQUAL(nSubsidy, 8000 * COIN);

        nSum += nSubsidy;
        DEBUG(nBlocks, nSubsidy);
    }

    // Dynamic mining rewards from block height 67,200 to block height 400,000
    for (int nBlocks = consensusParams.nDiffChangeTarget; nBlocks < consensusParams.alwaysUpdateDiffChangeTarget; ++nBlocks)
    {
        int nHeight = nBlocks;
        CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams);

        CAmount nExpectedSubsidy = 8000 * COIN;
        int nHeightWithinFork = (nHeight - consensusParams.nDiffChangeTarget);

        for (int i = 0; i < (nHeightWithinFork / consensusParams.patchBlockRewardDuration) + 1; ++i) {
            nExpectedSubsidy -= nExpectedSubsidy / 200; // dec by 0.5%
        }

        BOOST_CHECK_EQUAL(nSubsidy, nExpectedSubsidy);

        nSum += nSubsidy;
        DEBUG(nBlocks, nSubsidy);
    }

    // Updated dynamic mining rewards from block height 400,000 to block height 1,430,000
    for (int nBlocks = consensusParams.alwaysUpdateDiffChangeTarget; nBlocks < consensusParams.workComputationChangeTarget; ++nBlocks)
    {
        int nHeight = nBlocks;
        CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams);

        CAmount nExpectedSubsidy = 2459 * COIN;
        int nHeightWithinFork = (nHeight - consensusParams.alwaysUpdateDiffChangeTarget);

        for (int i = 0; i < (nHeightWithinFork / consensusParams.patchBlockRewardDuration2) + 1; ++i) {
            nExpectedSubsidy -= nExpectedSubsidy / 100; // dec by 1% per month
        }

        BOOST_CHECK_EQUAL(nSubsidy, nExpectedSubsidy);

        nSum += nSubsidy;
        DEBUG(nBlocks, nSubsidy);
    }

    {
        // Updated dynamic mining rewards from block height 1,430,000 to max block height.
        // Intended blockheight: 41.6 million
        // Actual blockheight: 110.5 million
        CAmount nExpectedSubsidyStart = 2157 * COIN / 2;
        CAmount nExpectedSubsidy = nExpectedSubsidyStart;
        int nMonthsConsidered = 0;

        for (int nBlocks = consensusParams.workComputationChangeTarget; nBlocks < nMaxBlocks; ++nBlocks) {
            int nHeight = nBlocks;
            CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams);

            int nHeightWithinFork = (nHeight - consensusParams.workComputationChangeTarget);
            int nMonths = nHeightWithinFork * BLOCK_TIME_SECONDS / SECONDS_PER_MONTH;

            if (nMonthsConsidered < nMonths) {
                // Calculate new subsidy for number of months `nMonths`.
                // This is a major optimization in order to reduce the
                // number of inner loops

                // Recalculate subsidy
                for (int i = nMonthsConsidered; i < nMonths; ++i) {
                    // Decay factor: 98884/100000
                    nExpectedSubsidy *= 98884;
                    nExpectedSubsidy /= 100000;
                    ++nMonthsConsidered;
                }
            }

            if (nExpectedSubsidy < COIN) { // ToDo: Alter consensus
                nExpectedSubsidy = COIN;
            }

            BOOST_CHECK_EQUAL(nSubsidy, nExpectedSubsidy);

            nSum += nSubsidy;
            DEBUG(nBlocks, nSubsidy);
        }
    }

    CAmount nSubsidy = GetBlockSubsidy(nMaxBlocks, consensusParams);
    CAmount nExpectedSubsidy = 1 * COIN;

    BOOST_CHECK_EQUAL(nSubsidy, nExpectedSubsidy);

    if (nSumOut != NULL) {
        *nSumOut = nSum;
    }
}

BOOST_AUTO_TEST_CASE(block_subsidy_test)
{
    CAmount sum;
    const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
    const auto testChainParams = CreateChainParams(CBaseChainParams::TESTNET);
    TestBlockSubsidy(chainParams->GetConsensus(), END_OF_SUPPLY_CURVE, &sum); // Mainnet

    CAmount nExpectedTotalSupply = 2239167398214795680ULL;
    BOOST_CHECK_EQUAL(sum, nExpectedTotalSupply);

#if OUTPUT_SUPPLY_SAMPLES_ENABLED
    // Output the accumulated supply until END_OF_SUPPLY_CURVE
    std::cout << "(mainnet): MAXIMUM SUPPLY: " << sum << " dgbSATS (" << (sum / COIN) << " DGB)";
#elif ENABLE_TESTNET_SUBSIDY_TESTS != 0
    // Only perform test on TESTNET too if requested so.
    TestBlockSubsidy(testChainParams->GetConsensus(), END_OF_SUPPLY_CURVE, NULL); // Testnet
#endif
}

static bool ReturnFalse() { return false; }
static bool ReturnTrue() { return true; }

BOOST_AUTO_TEST_CASE(test_combiner_all)
{
    boost::signals2::signal<bool (), CombinerAll> Test;
    BOOST_CHECK(Test());
    Test.connect(&ReturnFalse);
    BOOST_CHECK(!Test());
    Test.connect(&ReturnTrue);
    BOOST_CHECK(!Test());
    Test.disconnect(&ReturnFalse);
    BOOST_CHECK(Test());
    Test.disconnect(&ReturnTrue);
    BOOST_CHECK(Test());
}
BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: ycagel/digibyte

max_issues_repo_name: ycagel/digibyte

max_forks_repo_name: ycagel/digibyte


text:
/* -*- mode: c++; fill-column: 132; c-basic-offset: 4; indent-tabs-mode: nil -*- */

#ifndef __IRODS_DATABASE_TYPES_HPP__
#define __IRODS_DATABASE_TYPES_HPP__

// =-=-=-=-=-=-=-
// Boost Includes
#include <boost/shared_ptr.hpp>
#include <boost/any.hpp>

// =-=-=-=-=-=-=-
// irods includes
#include "irods_plugin_base.hpp"
#include "irods_lookup_table.hpp"

// =-=-=-=-=-=-=-
// irods includes
#include "rcConnect.hpp"

namespace irods {
    // =-=-=-=-=-=-=-
    // database plugin pointer type
    class database;
    typedef boost::shared_ptr< database > database_ptr;

    // =-=-=-=-=-=-=-
    // fwd decl of database manager for fco resolve
    class database_manager;

}; // namespace

#endif // __IRODS_DATABASE_TYPES_HPP__

max_stars_repo_name: PlantandFoodResearch/irods

max_issues_repo_name: PlantandFoodResearch/irods

max_forks_repo_name: PlantandFoodResearch/irods


text:
#pragma once

/**
 * @file
 * @brief amf(binary message format)
 */

#include <xul/io/amf_types.hpp>
#include <xul/io/data_input_stream.hpp>
#include <xul/std/maps.hpp>
#include <xul/data/variant.hpp>
#include <xul/data/list.hpp>
#include <xul/data/map.hpp>
#include <boost/noncopyable.hpp>
#include <stddef.h>
#include <stdint.h>

namespace xul {

/// amf(binary message format)
class amf0_reader : boost::noncopyable, public amf0_types
{
public:
    class null_type
    {
    public:
        null_type() { }
    };

    explicit amf0_reader(data_input_stream& is) : m_is(is)
    {
    }
    virtual ~amf0_reader()
    {
    }

    variant* read()
    {
        if (false == m_is.is_available(1))
        {
            return NULL;
        }
        variant* var = create_variant();
        uint8_t tag = m_is.read_byte();
        return read_item(tag, var) ? var : NULL;
    }

    list<variant*>* read_many()
    {
        list<variant*>* vars = create_variant_list();
        for (;;)
        {
            boost::intrusive_ptr<variant> var = read();
            if (!var)
            {
                XUL_APP_DEBUG("read failed");
                break;
            }
            vars->add(var.get());
        }
        return vars;
    }

private:
    bool read_item(int tag, variant* var)
    {
        switch (tag)
        {
        case amf0_null:
        case amf0_undefined:
            var->set_null();
            return true;
        case amf0_boolean:
            return read_bool(var);
        case amf0_number:
            return read_number(var);
        case amf0_string:
            return read_string(var);
        case amf0_array:
            return read_list(var);
        case amf0_object:
            return read_dict(var);
        }
        return false;
    }
    bool read_bool(variant* var)
    {
        uint8_t val = m_is.read_byte(val);
        var->set_bool(val != 0);
        return true;
    }
    bool read_number(variant* var)
    {
        double val = 0;
        if (!m_is.read_double(val))
            return false;
        var->set_float(val);
        return true;
    }
    bool read_string(variant* var)
    {
        std::string s;
        if (false == try_read_string(s))
        {
            var->set_null();
            return false;
        }
        var->set_bytes(s.c_str(), s.size());
        return true;
    }
    bool try_read_string(std::string& s)
    {
        uint16_t len = 0;
        if (false == m_is.read_uint16(len))
            return false;
        s.resize(static_cast<size_t>(len));
        if (false == m_is.read_n(reinterpret_cast<uint8_t*>(&s[0]), static_cast<size_t>(len)))
            return false;
        return true;
    }
    bool read_list(variant* var)
    {
        variant::list_type* items = var->set_list();
        for (;;)
        {
            if (false == m_is.is_available(1))
                return false;
            uint8_t tag = m_is.read_byte();
            boost::intrusive_ptr<variant> item = create_variant();
            if (read_item(tag, item.get()))
            {
                items->add(item.get());
            }
        }
        return false;
    }
    bool read_dict(variant* var)
    {
        variant::dict_type* items = var->set_dict();
        for (;;)
        {
            if (false == m_is.is_available(1))
                return true;
            std::string key;
            if (false == try_read_string(key))
                return true;
            boost::intrusive_ptr<variant> item = read();
            if (item)
            {
                items->set(key.c_str(), item.get());
            }
        }
        return true;
    }

private:
    data_input_stream& m_is;
};

}

max_stars_repo_name: hindsights/xul

max_issues_repo_name: hindsights/xul

max_forks_repo_name: hindsights/xul


text:
#include "random.h"
#include "sync.h"
#include "test/test_bitcoin.h"
#include "utiltime.h"

#include <boost/bind/bind.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread.hpp>

namespace number
{
    int n = 0;
}

namespace locker
{
    CCriticalSection cs_number;
}

static void plusOneThread(int nIterations)
{
    for (int i = 0; i < nIterations; ++i) {
        LOCK(locker::cs_number);
        int n = number::n;
        int nSleep = GetRandInt(10);
        MilliSleep(nSleep);
        number::n = n + 1;
    }
}

BOOST_FIXTURE_TEST_SUITE(elysium_lock_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(multithread_locking)
{
    int nThreadsNum = 4;
    int nIterations = 20;

    boost::thread_group threadGroup;
    for (int i = 0; i < nThreadsNum; ++i) {
        threadGroup.create_thread(boost::bind(&plusOneThread, nIterations));
    }

    threadGroup.join_all();
    BOOST_CHECK_EQUAL(number::n, (nThreadsNum * nIterations));
}

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: ConsulTent/firo

max_issues_repo_name: ConsulTent/firo

max_forks_repo_name: ConsulTent/firo


text:
#include <iostream>
#include <fstream>
#include <Eigen/Eigen>
//include the bie header files
#include "material.hh"
#include "precomputed_kernel.hh"
#include "bimat_interface.hh"
#include "infinite_boundary.hh"
//include the fem header files
#include "mesh_Abaqus_multi_faults.hpp"
#include "bcdof.hpp"
#include "bcdof_ptr.hpp"
#include "cal_ke.hpp"
#include "cal_fe_global_vary_ke.hpp"
#include "mapglobal.hpp"
#include "maplocal.hpp"
#include "cal_M.hpp"
#include "Slip_Weakening_lumpM.hpp"
#include "cal_slip_sliprate_angle.hpp"
#include "time_advance.hpp"
#include "BIE_correct.hpp"
#include <math.h>
using namespace Eigen;
using namespace std;

typedef Eigen::Matrix<int, -1, -1,RowMajor> MatrixXi_rm;

double time_fem=0;
double time_bie;
int main() {
    //std::string filename = "abaqus_cpp_two_faults_5degree_0d_flat.inp";
   // std::string filename = "abaqus_Rice_fish_bone_8_25m.inp";
    std::string filename = "abaqus_cpp_three_fault.inp";
    std::cout<<filename<<std::endl;
   // double fault_angle  = 0/180.0*M_PI;
    int dim = 2.0;
    double x_max = 5.0e3;
    double x_min = -5.0e3;
    double dx = 50.0;
    double dy = 50.0;
    std::vector<int> BIE_top, BIE_bot;
    MatrixXd Node;
    MatrixXi_rm Element;
    int num_faults = 3;
    std::vector<std::vector<int>> fault_nodes(2*num_faults);
    mesh_Abaqus_multi_faults(filename, Node, Element, BIE_top, BIE_bot,fault_nodes,num_faults);
    int nx_BIE = BIE_top.size();
    int n_nodes = Node.rows();
    int n_el = Element.rows();
    int Ndofn = 2;
    int Nnel = Element.cols();
    // Material
    double density = 2670.0;
    double v_s =3.464e3;
    double v_p = 6.0e3;
    double G= pow(v_s,2)*density;
    double Lambda = pow(v_p,2)*density-2.0*G;
    double E  = G*(3.0*Lambda+2.0*G)/(Lambda+G);
    double nu = Lambda/(2.0*(Lambda+G));
    // Slip weakening friction parameters
    double Dc = 0.2;
    double mu_d= 0.5;
    double mu_s = 0.6;
    // Intialization
    // disp velocity current and next time step (new)
    VectorXd u_n = VectorXd::Zero(n_nodes*Ndofn,1);
    VectorXd v_n = VectorXd::Zero(n_nodes*Ndofn,1);
    VectorXd u_new = VectorXd::Zero(n_nodes*Ndofn,1);
    VectorXd v_new = VectorXd::Zero(n_nodes*Ndofn,1);
    VectorXd a_n = VectorXd::Zero(n_nodes*Ndofn,1);
    // slip and slip-rate
    std::vector<Eigen::Array<double, -1, 1> > delt_u_n(num_faults);
    std::vector<Eigen::Array<double, -1, 1> > delt_v_n(num_faults);
    std::vector<Eigen::Array<double, -1, 1> > T_c(num_faults);
    std::vector<Eigen::Array<double, -1, 1> > T_0(num_faults);
    std::vector<Eigen::Array<double, -1, 1> > tau_s(num_faults);

    // Vector containing number of elements on each faults (nx)
    std::vector<int> nx_faults(num_faults);
    for (int i=0;i<num_faults;i++)
    {
        nx_faults[i] =fault_nodes[2*i].size();
    }

    for (int i=0;i<num_faults;i++)
    {
        delt_u_n[i] = ArrayXd::Zero(Ndofn*(nx_faults[i]),1);
        delt_v_n[i] = ArrayXd::Zero(Ndofn*(nx_faults[i]),1);
        T_c[i] = ArrayXd::Zero(Ndofn*(nx_faults[i]),1);
        T_0[i] = ArrayXd::Zero(Ndofn*(nx_faults[i]),1);
        tau_s[i] = ArrayXd::Zero(Ndofn*(nx_faults[i]),1);
    }
    VectorXd F_ext_global = VectorXd::Zero(n_nodes*Ndofn,1);
    // Write the x coordiantes for each fault
    std::vector<double> fault_angle(num_faults);
    for (int j=0;j<num_faults; j++)
    {
        VectorXd x = VectorXd::Zero(nx_faults[j], 1);
        VectorXd y = VectorXd::Zero(nx_faults[j], 1);

        for (int i=0; i<x.size(); i++)
        {
            x(i) = Node(fault_nodes[2*j][i],0);
            y(i) = Node(fault_nodes[2*j][i],1);
        }

        //std::ofstream x_output("results/fault_x_coord.txt");
        std::string  x_fault= "results/x_fault_"+std::to_string(j)+".txt";
        std::ofstream x_output(x_fault);
        x_output<<x;
        //std::cout<<x<<std::endl;
        fault_angle[j]= std::atan(std::abs(y.maxCoeff()-y.minCoeff())/std::abs(x.maxCoeff()-x.minCoeff()));
    }

    // Calcualte the resolving shear and nommal stress on each fault
    std::vector<double> sigma_f(num_faults);
    std::vector<double> tau_f(num_faults);
    double sigma_xx = 0.0e6;
    double sigma_yy = -50.0e6;
    double tau_xy = -27.5e6;
    for (int i=0; i<num_faults; i++)
    {
        double c = std::cos(fault_angle[i]);
        double s = std::sin(fault_angle[i]);

        sigma_f[i] = sigma_xx*s*s+sigma_yy*c*c+tau_xy*s*c;
        tau_f[i] = -sigma_xx*s*c+sigma_yy*s*c-tau_xy*(c*c-s*s);
    }

   // std::cout<<x<<std::endl;
    // Setting intial stress on the all fault according the the stress depcomposition.
    for (int j=0; j<num_faults;j++)
    {
        for (int i=0; i<nx_faults[j]; i++)
        {
            T_0[j](2*i+1) = sigma_f[j];
            T_0[j](2*i) = tau_f[j];
        }
    }
    //Adding pertubation to the main fault 0
    VectorXd x_main = VectorXd::Zero(nx_faults[0], 1);

    for (int i=0; i<x_main.size(); i++)
    {
        x_main(i) = Node(fault_nodes[0][i],0);
    }

    for (int i=0 ; i<nx_faults[0]; i++)
    {
        if ((x_main(i)<=(x_main.minCoeff()+x_main.maxCoeff())/2+0.6e3)&&(x_main(i)>=(x_main.minCoeff()+x_main.maxCoeff())/2-0.6e3))
        {
            T_0[0](2*i) = 31.0e6;
        }
    }

    // Get the index degree of freedome for each element
    VectorXi index_el = VectorXi::Zero(Ndofn*Nnel,1);
    MatrixXi index_store = MatrixXi::Zero(Nnel*Ndofn,n_el);
    for (int i=0;i<n_el;i++)
    {
        bcdof(Element.row(i),dim,index_el);
        index_store.col(i) = index_el;
    }
  //  VectorXi BIE_top_surf_index = VectorXi::Zero(Ndofn*(BIE_top_surf_nodes.size()),1);
   // VectorXi BIE_bot_surf_index = VectorXi::Zero(Ndofn*(BIE_bot_surf_nodes.size()),1);
    VectorXi BIE_top_surf_index = VectorXi::Zero(Ndofn*(BIE_top.size()),1);
    VectorXi BIE_bot_surf_index = VectorXi::Zero(Ndofn*(BIE_bot.size()),1);
    std::vector<Eigen::ArrayXi> Fault_surf_index(num_faults*2);
    for (int i=0; i <num_faults*2; i++)
    {
        Fault_surf_index[i] = ArrayXi::Zero(Ndofn*(fault_nodes[i].size()),1);
    }

    // Getting the faults DOF index
    for (int i=0; i<num_faults*2;i++)
    {
        bcdof_ptr(fault_nodes[i], dim, Fault_surf_index[i].data());
    }

    bcdof_ptr(BIE_top,dim,BIE_top_surf_index.data());
    bcdof_ptr(BIE_bot,dim,BIE_bot_surf_index.data());
    // Calculating the Global Mass Vector (lumped mass)
    // Element stiffness matrix,Element mass
    std::vector<MatrixXd> ke_store(n_el);
    MatrixXd M_el = MatrixXd::Zero(Nnel*Ndofn,Nnel*Ndofn);
    VectorXd M_el_vec = VectorXd::Zero(Nnel*Ndofn,1);
    VectorXd M_global_vec=VectorXd::Zero(n_nodes*Ndofn,1);
    std::vector<double> dx_min_store;
    for (int i=0; i<n_el;i++)
    {
        MatrixXd coord = MatrixXd::Zero(4,2);
        VectorXi Element_0= Element.row(i);
        coord.row(0) = Node.row(Element_0(0));
        coord.row(1) = Node.row(Element_0(1));
        coord.row(2) = Node.row(Element_0(2));
        coord.row(3) = Node.row(Element_0(3));
        VectorXd dx_cal = VectorXd::Zero(4,1);
        dx_cal(0)=std::sqrt(pow(std::abs(coord(0,0)-coord(1,0)),2)+pow(std::abs(coord(0,1)-coord(1,1)),2));
        dx_cal(1)=std::sqrt(pow(std::abs(coord(1,0)-coord(2,0)),2)+pow(std::abs(coord(1,1)-coord(2,1)),2));
        dx_cal(2)=std::sqrt(pow(std::abs(coord(2,0)-coord(3,0)),2)+pow(std::abs(coord(2,1)-coord(3,1)),2));
        dx_cal(3)=std::sqrt(pow(std::abs(coord(3,0)-coord(0,0)),2)+pow(std::abs(coord(3,1)-coord(0,1)),2));
        double dx_min = dx_cal.minCoeff();
        dx_min_store.push_back(dx_min);
       // std::cout<<dx_cal<<std::endl;

        cal_ke (coord,E,nu,ke_store[i]);
        cal_M(coord, density,M_el);
        M_el_vec = M_el.rowwise().sum();
        index_el = index_store.col(i);
        mapglobal(index_el,M_global_vec,M_el_vec);

    }
    double dx_min = *std::min_element(std::begin(dx_min_store), std::end(dx_min_store));
    // Time
    double alpha = 0.4;
    double dt = alpha*dx_min/v_p;
    // Reyleigh Damping
    double beta =0.1;
    double q = beta*dt;
    double time_run = 6.0;
    int numt = time_run/dt;
    //
    std::ofstream time_output("results/time.txt");
    time_output<<time_run<<"\n";
    time_output<<dt<<"\n";
    time_output<<numt<<std::endl;

    //numt = 1;
    VectorXd time = dt*VectorXd::LinSpaced(numt,1,numt);
//    MatrixXd ke = MatrixXd::Zero(8,8);
//    MatrixXd coord = MatrixXd::Zero(4,2);
//    VectorXi Element_0= Element.row(0);
//    coord.row(0) = Node.row(Element_0(0));
//    coord.row(1) = Node.row(Element_0(1));
//    coord.row(2) = Node.row(Element_0(2));
//    coord.row(3) = Node.row(Element_0(3));
//    cal_ke (coord,E,nu,ke);

    // BIE part initiation
    // Setting up the material property for the BIE code
    Material BIE_top_mat = Material(E,nu,density);
    Material BIE_bot_mat = Material(E,nu,density);
    double length = x_max-x_min;
    // infinte bc BIE call infinite_boundary.cc
    PrecomputedKernel h11("kernels/nu_.25_h11.dat");
    PrecomputedKernel h12("kernels/nu_.25_k12.dat");
    PrecomputedKernel h22("kernels/nu_.25_h22.dat");
    InfiniteBoundary BIE_inf_top(length,nx_BIE,1.0,&BIE_top_mat,&h11,&h12,&h22);
    InfiniteBoundary BIE_inf_bot(length,nx_BIE,-1.0,&BIE_bot_mat,&h11,&h12,&h22);
    // BIE setting time step
    BIE_inf_top.setTimeStep(dt);
    BIE_inf_bot.setTimeStep(dt);
    // BIE initialization
    BIE_inf_top.init();
    BIE_inf_bot.init();
    printf("ready to start\n");
    // Output
    ofstream file;
    file.open("results/num_nodes_fault.bin",ios::binary);
    file.write((char*)(nx_faults.data()),nx_faults.size()*sizeof(int));
    file.close();

    file.open("results/u_n.bin",ios::binary);
   // file.write((char*)(u_n.data()),u_n.size()*sizeof(double));
    file.close();
    file.open("results/v_n.bin",ios::binary);
    // file.write((char*)(u_n.data()),u_n.size()*sizeof(double));
    file.close();

    for (int i=0;i<num_faults;i++)
    {
        std::string slip = "results/slip_"+std::to_string(i)+".bin";
        file.open(slip);
        file.close();
        std::string slip_rate = "results/slip_rate_"+std::to_string(i)+".bin";
        file.open(slip_rate);
        file.close();
        std::string shear = "results/shear_"+std::to_string(i)+".bin";
        file.open(shear);
        file.close();
    }
    std::ofstream Element_output("results/Element.txt");
    std::ofstream Node_output("results/Node.txt");
    Node_output<<Node;
    Element_output<<Element;
    //    std::ofstream shear_x("results/shear.txt");
    //double start = omp_get_wtime();

    // Main time loop
    for (int j=0;j<numt;j++)
    {
        // Compute the global internal force
        VectorXd fe_global= VectorXd::Zero(n_nodes*Ndofn,1);
        cal_fe_global_vary_ke(n_nodes, n_el, index_store, q, u_n, v_n, Ndofn, ke_store, fe_global);
        // Friction subroutine
        VectorXd F_total = F_ext_global-fe_global;
        for (int i=0 ; i<num_faults; i++)
        {
            VectorXd F_fault = VectorXd::Zero(Ndofn*(nx_faults[i]),1);
            VectorXd M_pos = VectorXd::Zero(nx_faults[i], 1);
            VectorXd M_neg = VectorXd::Zero(nx_faults[i],1);
            maplocal(Fault_surf_index[2*i], M_global_vec, M_pos);
            maplocal(Fault_surf_index[2*i+1], M_global_vec, M_neg);
            //std::cout<<M_pos<<std::endl;
            Slip_Weakening_lumpM(M_global_vec, Fault_surf_index[2*i], Fault_surf_index[2*i+1], fe_global, dt, dx, dy, nx_faults[i]-1, delt_v_n[i], delt_u_n[i], T_0[i], tau_s[i], mu_s, mu_d, Dc, Ndofn, M_pos, M_neg , F_fault, T_c[i], fault_angle[i]);
            mapglobal(Fault_surf_index[2*i],F_total,-F_fault);
            mapglobal(Fault_surf_index[2*i+1],F_total,F_fault);
        }

        // Central Difference Time integration
        time_advance(u_n, v_n, F_total, M_global_vec, dt);
        // Get the slip and slip rate

        for (int i=0; i<num_faults; i++)
        {

            cal_slip_slip_rate_angle(u_n, v_n,  Fault_surf_index[2*i], Fault_surf_index[2*i+1] , Ndofn, nx_faults[i]-1, delt_u_n[i], delt_v_n[i],fault_angle[i]);
        }
        // Correct the BIE surf nodes solutions from FEM with the BIE solution
        BIE_correct(BIE_top_surf_index, BIE_bot_surf_index, fe_global, Ndofn, nx_BIE-1, dx, BIE_inf_top, BIE_inf_bot, u_n, v_n);

      //  if (j%4==3)
       // {
        for (int i=0;i<num_faults;i++)
        {
            std::string slip = "results/slip_"+std::to_string(i)+".bin";
            file.open(slip,ios::binary | ios::app);
            file.write((char*)(delt_u_n[i].data()),delt_u_n[i].size()*sizeof(double));
            file.close();

            std::string slip_rate = "results/slip_rate_"+std::to_string(i)+".bin";
            file.open(slip_rate,ios::binary | ios::app);
            file.write((char*)(delt_v_n[i].data()),delt_v_n[i].size()*sizeof(double));
            file.close();

            std::string shear = "results/shear_"+std::to_string(i)+".bin";
            file.open(shear,ios::binary | ios::app);
            file.write((char*)(T_c[i].data()),T_c[i].size()*sizeof(double));
            file.close();
        }
        file.open("results/u_n.bin",ios::binary | ios::app);
        file.write((char*)(u_n.data()),u_n.size()*sizeof(double));
        file.close();
        file.open("results/v_n.bin",ios::binary | ios::app);
        file.write((char*)(v_n.data()),v_n.size()*sizeof(double));
        file.close();
       // }
        printf("Simulation time = %f\n",time(j));
      //  double end_t = omp_get_wtime();
       // std::cout<<"time_cpu_t="<<end_t-start<<std::endl;
    //   std::cout<<"time_fem="<< time_fem<<std::endl;
    //   std::cout<<"time_bie="<< time_bie<<std::endl;
    }
    //double end = omp_get_wtime();
    //std::cout<<"time_cpu="<<end-start<<std::endl;
    return 0;
}