<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 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/DisplaySettings>
#include <osg/ArgumentParser>
#include <osg/ApplicationUsage>
#include <osg/ref_ptr>

#include <algorithm>

using namespace osg;
using namespace std;

DisplaySettings* DisplaySettings::instance()
{
    static ref_ptr<DisplaySettings> s_displaySettings = new DisplaySettings;
    return s_displaySettings.get();
}

DisplaySettings::DisplaySettings(const DisplaySettings& vs):Referenced()
{
    setDisplaySettings(vs);
}

DisplaySettings::~DisplaySettings()
{
}

 DisplaySettings& DisplaySettings::operator = (const DisplaySettings& vs)
{
    if (this==&vs) return *this;
    setDisplaySettings(vs);
    return *this;
}

void DisplaySettings::setDisplaySettings(const DisplaySettings& vs)
{
    _displayType = vs._displayType;
    _stereo = vs._stereo;
    _stereoMode = vs._stereoMode;
    _eyeSeparation = vs._eyeSeparation;
    _screenWidth = vs._screenWidth;
    _screenHeight = vs._screenHeight;
    _screenDistance = vs._screenDistance;

    _splitStereoHorizontalEyeMapping = vs._splitStereoHorizontalEyeMapping;
    _splitStereoHorizontalSeparation = vs._splitStereoHorizontalSeparation;

    _splitStereoVerticalEyeMapping = vs._splitStereoVerticalEyeMapping;
    _splitStereoVerticalSeparation = vs._splitStereoVerticalSeparation;

    _splitStereoAutoAdjustAspectRatio = vs._splitStereoAutoAdjustAspectRatio;

    _doubleBuffer = vs._doubleBuffer;
    _RGB = vs._RGB;
    _depthBuffer = vs._depthBuffer;
    _minimumNumberAlphaBits = vs._minimumNumberAlphaBits;
    _minimumNumberStencilBits = vs._minimumNumberStencilBits;

    _maxNumOfGraphicsContexts = vs._maxNumOfGraphicsContexts;
    _numMultiSamples = vs._numMultiSamples;
}

void DisplaySettings::merge(const DisplaySettings& vs)
{
    if (_stereo       || vs._stereo)        _stereo = true;

    // need to think what to do about merging the stereo mode.

    if (_doubleBuffer || vs._doubleBuffer)  _doubleBuffer = true;
    if (_RGB          || vs._RGB)           _RGB = true;
    if (_depthBuffer  || vs._depthBuffer)   _depthBuffer = true;

    if (vs._minimumNumberAlphaBits>_minimumNumberAlphaBits) _minimumNumberAlphaBits = vs._minimumNumberAlphaBits;
    if (vs._minimumNumberStencilBits>_minimumNumberStencilBits) _minimumNumberStencilBits = vs._minimumNumberStencilBits;
    if (vs._numMultiSamples>_numMultiSamples) _numMultiSamples = vs._numMultiSamples;
}

void DisplaySettings::setDefaults()
{
    _displayType = MONITOR;

    _stereo = false;
    _stereoMode = ANAGLYPHIC;
    _eyeSeparation = 0.05f;
    _screenWidth = 0.325f;
    _screenHeight = 0.26f;
    _screenDistance = 0.5f;

    _splitStereoHorizontalEyeMapping = LEFT_EYE_LEFT_VIEWPORT;
    _splitStereoHorizontalSeparation = 0;

    _splitStereoVerticalEyeMapping = LEFT_EYE_TOP_VIEWPORT;
    _splitStereoVerticalSeparation = 0;

    _splitStereoAutoAdjustAspectRatio = true;

    _doubleBuffer = true;
    _RGB = true;
    _depthBuffer = true;
    _minimumNumberAlphaBits = 0;
    _minimumNumberStencilBits = 0;
    _minimumNumberAccumRedBits = 0;
    _minimumNumberAccumGreenBits = 0;
    _minimumNumberAccumBlueBits = 0;
    _minimumNumberAccumAlphaBits = 0;

    _maxNumOfGraphicsContexts = 3;
    _numMultiSamples = 0;

    #ifdef __sgi
    // switch on anti-aliasing by default, just in case we have an Onyx :-)
    _numMultiSamples = 4;
    #endif
}

void DisplaySettings::setMinimumNumAccumBits(unsigned int red, unsigned int green, unsigned int blue, unsigned int alpha)
{
    _minimumNumberAccumRedBits = red;
    _minimumNumberAccumGreenBits = green;
    _minimumNumberAccumBlueBits = blue;
    _minimumNumberAccumAlphaBits = alpha;
}

static ApplicationUsageProxy DisplaySetting_e0(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_DISPLAY_TYPE <type>","MONITOR | POWERWALL | REALITY_CENTER | HEAD_MOUNTED_DISPLAY");
static ApplicationUsageProxy DisplaySetting_e1(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO_MODE <mode>","QUAD_BUFFER | ANAGLYPHIC | HORIZONTAL_SPLIT | VERTICAL_SPLIT | LEFT_EYE | RIGHT_EYE | VERTICAL_INTERLACE | HORIZONTAL_INTERLACE");
static ApplicationUsageProxy DisplaySetting_e2(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO <mode>","OFF | ON");
static ApplicationUsageProxy DisplaySetting_e3(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_EYE_SEPARATION <float>","physical distance between eyes");
static ApplicationUsageProxy DisplaySetting_e4(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_DISTANCE <float>","physical distance between eyes and screen");
static ApplicationUsageProxy DisplaySetting_e5(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_HEIGHT <float>","physical screen height");
static ApplicationUsageProxy DisplaySetting_e6(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_WIDTH <float>","physical screen width");
static ApplicationUsageProxy DisplaySetting_e7(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_HORIZONTAL_EYE_MAPPING <mode>","LEFT_EYE_LEFT_VIEWPORT | LEFT_EYE_RIGHT_VIEWPORT");
static ApplicationUsageProxy DisplaySetting_e8(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_HORIZONTAL_SEPARATION <float>","number of pixels between viewports");
static ApplicationUsageProxy DisplaySetting_e9(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_VERTICAL_EYE_MAPPING <mode>","LEFT_EYE_TOP_VIEWPORT | LEFT_EYE_BOTTOM_VIEWPORT");
static ApplicationUsageProxy DisplaySetting_e10(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_AUTO_ADJUST_ASPECT_RATIO <mode>","OFF | ON  Default to ON to compenstate for the compression of the aspect ratio when viewing in split screen stereo.  Note, if you are setting fovx and fovy explicityly OFF should be used.");
static ApplicationUsageProxy DisplaySetting_e11(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_VERTICAL_SEPARATION <float>","number of pixels between viewports");
static ApplicationUsageProxy DisplaySetting_e12(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_MAX_NUMBER_OF_GRAPHICS_CONTEXTS <int>","maximum number of graphics contexts to be used with applications.");

void DisplaySettings::readEnvironmentalVariables()
{
    const char* ptr = 0;

    if ((ptr = getenv("OSG_DISPLAY_TYPE")) != 0)
    {
        if (strcmp(ptr,"MONITOR")==0)
        {
            _displayType = MONITOR;
        }
        else
        if (strcmp(ptr,"POWERWALL")==0)
        {
            _displayType = POWERWALL;
        }
        else
        if (strcmp(ptr,"REALITY_CENTER")==0)
        {
            _displayType = REALITY_CENTER;
        }
        else
        if (strcmp(ptr,"HEAD_MOUNTED_DISPLAY")==0)
        {
            _displayType = HEAD_MOUNTED_DISPLAY;
        }
    }

    if( (ptr = getenv("OSG_STEREO_MODE")) != 0)
    {
        if (strcmp(ptr,"QUAD_BUFFER")==0)
        {
            _stereoMode = QUAD_BUFFER;
        }
        else if (strcmp(ptr,"ANAGLYPHIC")==0)
        {
            _stereoMode = ANAGLYPHIC;
        }
        else if (strcmp(ptr,"HORIZONTAL_SPLIT")==0)
        {
            _stereoMode = HORIZONTAL_SPLIT;
        }
        else if (strcmp(ptr,"VERTICAL_SPLIT")==0)
        {
            _stereoMode = VERTICAL_SPLIT;
        }
        else if (strcmp(ptr,"LEFT_EYE")==0)
        {
            _stereoMode = LEFT_EYE;
        }
        else if (strcmp(ptr,"RIGHT_EYE")==0)
        {
            _stereoMode = RIGHT_EYE;
        }
        else if (strcmp(ptr,"HORIZONTAL_INTERLACE")==0)
        {
            _stereoMode = HORIZONTAL_INTERLACE;
        }
        else if (strcmp(ptr,"VERTICAL_INTERLACE")==0)
        {
            _stereoMode = VERTICAL_INTERLACE;
        }
    }

    if( (ptr = getenv("OSG_STEREO")) != 0)
    {
        if (strcmp(ptr,"OFF")==0)
        {
            _stereo = false;
        }
        else
        if (strcmp(ptr,"ON")==0)
        {
            _stereo = true;
        }
    }

    if( (ptr = getenv("OSG_EYE_SEPARATION")) != 0)
    {
        _eyeSeparation = atof(ptr);
    }

    if( (ptr = getenv("OSG_SCREEN_WIDTH")) != 0)
    {
        _screenWidth = atof(ptr);
    }

    if( (ptr = getenv("OSG_SCREEN_HEIGHT")) != 0)
    {
        _screenHeight = atof(ptr);
    }

    if( (ptr = getenv("OSG_SCREEN_DISTANCE")) != 0)
    {
        _screenDistance = atof(ptr);
    }

    if( (ptr = getenv("OSG_SPLIT_STEREO_HORIZONTAL_EYE_MAPPING")) != 0)
    {
        if (strcmp(ptr,"LEFT_EYE_LEFT_VIEWPORT")==0)
        {
            _splitStereoHorizontalEyeMapping = LEFT_EYE_LEFT_VIEWPORT;
        }
        else
        if (strcmp(ptr,"LEFT_EYE_RIGHT_VIEWPORT")==0)
        {
            _splitStereoHorizontalEyeMapping = LEFT_EYE_RIGHT_VIEWPORT;
        }
    }

    if( (ptr = getenv("OSG_SPLIT_STEREO_HORIZONTAL_SEPARATION")) != 0)
    {
        _splitStereoHorizontalSeparation = atoi(ptr);
    }

    if( (ptr = getenv("OSG_SPLIT_STEREO_VERTICAL_EYE_MAPPING")) != 0)
    {
        if (strcmp(ptr,"LEFT_EYE_TOP_VIEWPORT")==0)
        {
            _splitStereoVerticalEyeMapping = LEFT_EYE_TOP_VIEWPORT;
        }
        else
        if (strcmp(ptr,"LEFT_EYE_BOTTOM_VIEWPORT")==0)
        {
            _splitStereoVerticalEyeMapping = LEFT_EYE_BOTTOM_VIEWPORT;
        }
    }

    if( (ptr = getenv("OSG_SPLIT_STEREO_AUTO_ADJUST_ASPECT_RATIO")) != 0)
    {
        if (strcmp(ptr,"OFF")==0)
        {
            _splitStereoAutoAdjustAspectRatio = false;
        }
        else
        if (strcmp(ptr,"ON")==0)
        {
            _splitStereoAutoAdjustAspectRatio = true;
        }
    }

    if( (ptr = getenv("OSG_SPLIT_STEREO_VERTICAL_SEPARATION")) != 0)
    {
        _splitStereoVerticalSeparation = atoi(ptr);
    }

    if( (ptr = getenv("OSG_MAX_NUMBER_OF_GRAPHICS_CONTEXTS")) != 0)
    {
        _maxNumOfGraphicsContexts = atoi(ptr);
    }
}

void DisplaySettings::readCommandLine(ArgumentParser& arguments)
{

    // report the usage options.
    if (arguments.getApplicationUsage())
    {
        arguments.getApplicationUsage()->addCommandLineOption("--display <type>","MONITOR | POWERWALL | REALITY_CENTER | HEAD_MOUNTED_DISPLAY");
        arguments.getApplicationUsage()->addCommandLineOption("--stereo","Use default stereo mode which is ANAGLYPHIC if not overriden by environmental variable");
        arguments.getApplicationUsage()->addCommandLineOption("--stereo <mode>","ANAGLYPHIC | QUAD_BUFFER | HORIZONTAL_SPLIT | VERTICAL_SPLIT | LEFT_EYE | RIGHT_EYE | ON | OFF ");
        arguments.getApplicationUsage()->addCommandLineOption("--rgba","Request a RGBA color buffer visual");
        arguments.getApplicationUsage()->addCommandLineOption("--stencil","Request a stencil buffer visual");
        arguments.getApplicationUsage()->addCommandLineOption("--accum-rgb","Request a rgb accumulator buffer visual");
        arguments.getApplicationUsage()->addCommandLineOption("--accum-rgba","Request a rgb accumulator buffer visual");
        arguments.getApplicationUsage()->addCommandLineOption("--samples <num>","Request a multisample visual");
    }

    std::string str;
    while(arguments.read("--display",str))
    {
        if (str=="MONITOR") _displayType = MONITOR;
        else if (str=="POWERWALL") _displayType = POWERWALL;
        else if (str=="REALITY_CENTER") _displayType = REALITY_CENTER;
        else if (str=="HEAD_MOUNTED_DISPLAY") _displayType = HEAD_MOUNTED_DISPLAY;
    }

    int pos;
    while ((pos=arguments.find("--stereo"))!=0)
    {
        if (arguments.match(pos+1,"ANAGLYPHIC"))            { arguments.remove(pos,2); _stereo = true;_stereoMode = ANAGLYPHIC; }
        else if (arguments.match(pos+1,"QUAD_BUFFER"))      { arguments.remove(pos,2); _stereo = true;_stereoMode = QUAD_BUFFER; }
        else if (arguments.match(pos+1,"HORIZONTAL_SPLIT")) { arguments.remove(pos,2); _stereo = true;_stereoMode = HORIZONTAL_SPLIT; }
        else if (arguments.match(pos+1,"VERTICAL_SPLIT"))   { arguments.remove(pos,2); _stereo = true;_stereoMode = VERTICAL_SPLIT; }
        else if (arguments.match(pos+1,"HORIZONTAL_INTERLACE")) { arguments.remove(pos,2); _stereo = true;_stereoMode = HORIZONTAL_INTERLACE; }
        else if (arguments.match(pos+1,"VERTICAL_INTERLACE"))   { arguments.remove(pos,2); _stereo = true;_stereoMode = VERTICAL_INTERLACE; }
        else if (arguments.match(pos+1,"LEFT_EYE"))         { arguments.remove(pos,2); _stereo = true;_stereoMode = LEFT_EYE; }
        else if (arguments.match(pos+1,"RIGHT_EYE"))        { arguments.remove(pos,2); _stereo = true;_stereoMode = RIGHT_EYE; }
        else if (arguments.match(pos+1,"ON"))               { arguments.remove(pos,2); _stereo = true; }
        else if (arguments.match(pos+1,"OFF"))              { arguments.remove(pos,2); _stereo = false; }
        else                                                { arguments.remove(pos); _stereo = true; }
    }

    while (arguments.read("--rgba"))
    {
        _RGB = true;
        _minimumNumberAlphaBits = 1;
    }

    while (arguments.read("--stencil"))
    {
        _minimumNumberStencilBits = 1;
    }

    while (arguments.read("--accum-rgb"))
    {
        setMinimumNumAccumBits(8,8,8,0);
    }

    while (arguments.read("--accum-rgba"))
    {
        setMinimumNumAccumBits(8,8,8,8);
    }

    while(arguments.read("--samples",str))
    {
        _numMultiSamples = atoi(str.c_str());
    }
}
<commit_msg>Reset the default number of graphics context to 1.<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 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/DisplaySettings>
#include <osg/ArgumentParser>
#include <osg/ApplicationUsage>
#include <osg/ref_ptr>

#include <algorithm>

using namespace osg;
using namespace std;

DisplaySettings* DisplaySettings::instance()
{
    static ref_ptr<DisplaySettings> s_displaySettings = new DisplaySettings;
    return s_displaySettings.get();
}

DisplaySettings::DisplaySettings(const DisplaySettings& vs):Referenced()
{
    setDisplaySettings(vs);
}

DisplaySettings::~DisplaySettings()
{
}

 DisplaySettings& DisplaySettings::operator = (const DisplaySettings& vs)
{
    if (this==&vs) return *this;
    setDisplaySettings(vs);
    return *this;
}

void DisplaySettings::setDisplaySettings(const DisplaySettings& vs)
{
    _displayType = vs._displayType;
    _stereo = vs._stereo;
    _stereoMode = vs._stereoMode;
    _eyeSeparation = vs._eyeSeparation;
    _screenWidth = vs._screenWidth;
    _screenHeight = vs._screenHeight;
    _screenDistance = vs._screenDistance;

    _splitStereoHorizontalEyeMapping = vs._splitStereoHorizontalEyeMapping;
    _splitStereoHorizontalSeparation = vs._splitStereoHorizontalSeparation;

    _splitStereoVerticalEyeMapping = vs._splitStereoVerticalEyeMapping;
    _splitStereoVerticalSeparation = vs._splitStereoVerticalSeparation;

    _splitStereoAutoAdjustAspectRatio = vs._splitStereoAutoAdjustAspectRatio;

    _doubleBuffer = vs._doubleBuffer;
    _RGB = vs._RGB;
    _depthBuffer = vs._depthBuffer;
    _minimumNumberAlphaBits = vs._minimumNumberAlphaBits;
    _minimumNumberStencilBits = vs._minimumNumberStencilBits;

    _maxNumOfGraphicsContexts = vs._maxNumOfGraphicsContexts;
    _numMultiSamples = vs._numMultiSamples;
}

void DisplaySettings::merge(const DisplaySettings& vs)
{
    if (_stereo       || vs._stereo)        _stereo = true;

    // need to think what to do about merging the stereo mode.

    if (_doubleBuffer || vs._doubleBuffer)  _doubleBuffer = true;
    if (_RGB          || vs._RGB)           _RGB = true;
    if (_depthBuffer  || vs._depthBuffer)   _depthBuffer = true;

    if (vs._minimumNumberAlphaBits>_minimumNumberAlphaBits) _minimumNumberAlphaBits = vs._minimumNumberAlphaBits;
    if (vs._minimumNumberStencilBits>_minimumNumberStencilBits) _minimumNumberStencilBits = vs._minimumNumberStencilBits;
    if (vs._numMultiSamples>_numMultiSamples) _numMultiSamples = vs._numMultiSamples;
}

void DisplaySettings::setDefaults()
{
    _displayType = MONITOR;

    _stereo = false;
    _stereoMode = ANAGLYPHIC;
    _eyeSeparation = 0.05f;
    _screenWidth = 0.325f;
    _screenHeight = 0.26f;
    _screenDistance = 0.5f;

    _splitStereoHorizontalEyeMapping = LEFT_EYE_LEFT_VIEWPORT;
    _splitStereoHorizontalSeparation = 0;

    _splitStereoVerticalEyeMapping = LEFT_EYE_TOP_VIEWPORT;
    _splitStereoVerticalSeparation = 0;

    _splitStereoAutoAdjustAspectRatio = true;

    _doubleBuffer = true;
    _RGB = true;
    _depthBuffer = true;
    _minimumNumberAlphaBits = 0;
    _minimumNumberStencilBits = 0;
    _minimumNumberAccumRedBits = 0;
    _minimumNumberAccumGreenBits = 0;
    _minimumNumberAccumBlueBits = 0;
    _minimumNumberAccumAlphaBits = 0;

    _maxNumOfGraphicsContexts = 1;
    _numMultiSamples = 0;

    #ifdef __sgi
    // switch on anti-aliasing by default, just in case we have an Onyx :-)
    _numMultiSamples = 4;
    #endif
}

void DisplaySettings::setMinimumNumAccumBits(unsigned int red, unsigned int green, unsigned int blue, unsigned int alpha)
{
    _minimumNumberAccumRedBits = red;
    _minimumNumberAccumGreenBits = green;
    _minimumNumberAccumBlueBits = blue;
    _minimumNumberAccumAlphaBits = alpha;
}

static ApplicationUsageProxy DisplaySetting_e0(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_DISPLAY_TYPE <type>","MONITOR | POWERWALL | REALITY_CENTER | HEAD_MOUNTED_DISPLAY");
static ApplicationUsageProxy DisplaySetting_e1(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO_MODE <mode>","QUAD_BUFFER | ANAGLYPHIC | HORIZONTAL_SPLIT | VERTICAL_SPLIT | LEFT_EYE | RIGHT_EYE | VERTICAL_INTERLACE | HORIZONTAL_INTERLACE");
static ApplicationUsageProxy DisplaySetting_e2(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO <mode>","OFF | ON");
static ApplicationUsageProxy DisplaySetting_e3(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_EYE_SEPARATION <float>","physical distance between eyes");
static ApplicationUsageProxy DisplaySetting_e4(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_DISTANCE <float>","physical distance between eyes and screen");
static ApplicationUsageProxy DisplaySetting_e5(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_HEIGHT <float>","physical screen height");
static ApplicationUsageProxy DisplaySetting_e6(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_WIDTH <float>","physical screen width");
static ApplicationUsageProxy DisplaySetting_e7(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_HORIZONTAL_EYE_MAPPING <mode>","LEFT_EYE_LEFT_VIEWPORT | LEFT_EYE_RIGHT_VIEWPORT");
static ApplicationUsageProxy DisplaySetting_e8(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_HORIZONTAL_SEPARATION <float>","number of pixels between viewports");
static ApplicationUsageProxy DisplaySetting_e9(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_VERTICAL_EYE_MAPPING <mode>","LEFT_EYE_TOP_VIEWPORT | LEFT_EYE_BOTTOM_VIEWPORT");
static ApplicationUsageProxy DisplaySetting_e10(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_AUTO_ADJUST_ASPECT_RATIO <mode>","OFF | ON  Default to ON to compenstate for the compression of the aspect ratio when viewing in split screen stereo.  Note, if you are setting fovx and fovy explicityly OFF should be used.");
static ApplicationUsageProxy DisplaySetting_e11(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_VERTICAL_SEPARATION <float>","number of pixels between viewports");
static ApplicationUsageProxy DisplaySetting_e12(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_MAX_NUMBER_OF_GRAPHICS_CONTEXTS <int>","maximum number of graphics contexts to be used with applications.");

void DisplaySettings::readEnvironmentalVariables()
{
    const char* ptr = 0;

    if ((ptr = getenv("OSG_DISPLAY_TYPE")) != 0)
    {
        if (strcmp(ptr,"MONITOR")==0)
        {
            _displayType = MONITOR;
        }
        else
        if (strcmp(ptr,"POWERWALL")==0)
        {
            _displayType = POWERWALL;
        }
        else
        if (strcmp(ptr,"REALITY_CENTER")==0)
        {
            _displayType = REALITY_CENTER;
        }
        else
        if (strcmp(ptr,"HEAD_MOUNTED_DISPLAY")==0)
        {
            _displayType = HEAD_MOUNTED_DISPLAY;
        }
    }

    if( (ptr = getenv("OSG_STEREO_MODE")) != 0)
    {
        if (strcmp(ptr,"QUAD_BUFFER")==0)
        {
            _stereoMode = QUAD_BUFFER;
        }
        else if (strcmp(ptr,"ANAGLYPHIC")==0)
        {
            _stereoMode = ANAGLYPHIC;
        }
        else if (strcmp(ptr,"HORIZONTAL_SPLIT")==0)
        {
            _stereoMode = HORIZONTAL_SPLIT;
        }
        else if (strcmp(ptr,"VERTICAL_SPLIT")==0)
        {
            _stereoMode = VERTICAL_SPLIT;
        }
        else if (strcmp(ptr,"LEFT_EYE")==0)
        {
            _stereoMode = LEFT_EYE;
        }
        else if (strcmp(ptr,"RIGHT_EYE")==0)
        {
            _stereoMode = RIGHT_EYE;
        }
        else if (strcmp(ptr,"HORIZONTAL_INTERLACE")==0)
        {
            _stereoMode = HORIZONTAL_INTERLACE;
        }
        else if (strcmp(ptr,"VERTICAL_INTERLACE")==0)
        {
            _stereoMode = VERTICAL_INTERLACE;
        }
    }

    if( (ptr = getenv("OSG_STEREO")) != 0)
    {
        if (strcmp(ptr,"OFF")==0)
        {
            _stereo = false;
        }
        else
        if (strcmp(ptr,"ON")==0)
        {
            _stereo = true;
        }
    }

    if( (ptr = getenv("OSG_EYE_SEPARATION")) != 0)
    {
        _eyeSeparation = atof(ptr);
    }

    if( (ptr = getenv("OSG_SCREEN_WIDTH")) != 0)
    {
        _screenWidth = atof(ptr);
    }

    if( (ptr = getenv("OSG_SCREEN_HEIGHT")) != 0)
    {
        _screenHeight = atof(ptr);
    }

    if( (ptr = getenv("OSG_SCREEN_DISTANCE")) != 0)
    {
        _screenDistance = atof(ptr);
    }

    if( (ptr = getenv("OSG_SPLIT_STEREO_HORIZONTAL_EYE_MAPPING")) != 0)
    {
        if (strcmp(ptr,"LEFT_EYE_LEFT_VIEWPORT")==0)
        {
            _splitStereoHorizontalEyeMapping = LEFT_EYE_LEFT_VIEWPORT;
        }
        else
        if (strcmp(ptr,"LEFT_EYE_RIGHT_VIEWPORT")==0)
        {
            _splitStereoHorizontalEyeMapping = LEFT_EYE_RIGHT_VIEWPORT;
        }
    }

    if( (ptr = getenv("OSG_SPLIT_STEREO_HORIZONTAL_SEPARATION")) != 0)
    {
        _splitStereoHorizontalSeparation = atoi(ptr);
    }

    if( (ptr = getenv("OSG_SPLIT_STEREO_VERTICAL_EYE_MAPPING")) != 0)
    {
        if (strcmp(ptr,"LEFT_EYE_TOP_VIEWPORT")==0)
        {
            _splitStereoVerticalEyeMapping = LEFT_EYE_TOP_VIEWPORT;
        }
        else
        if (strcmp(ptr,"LEFT_EYE_BOTTOM_VIEWPORT")==0)
        {
            _splitStereoVerticalEyeMapping = LEFT_EYE_BOTTOM_VIEWPORT;
        }
    }

    if( (ptr = getenv("OSG_SPLIT_STEREO_AUTO_ADJUST_ASPECT_RATIO")) != 0)
    {
        if (strcmp(ptr,"OFF")==0)
        {
            _splitStereoAutoAdjustAspectRatio = false;
        }
        else
        if (strcmp(ptr,"ON")==0)
        {
            _splitStereoAutoAdjustAspectRatio = true;
        }
    }

    if( (ptr = getenv("OSG_SPLIT_STEREO_VERTICAL_SEPARATION")) != 0)
    {
        _splitStereoVerticalSeparation = atoi(ptr);
    }

    if( (ptr = getenv("OSG_MAX_NUMBER_OF_GRAPHICS_CONTEXTS")) != 0)
    {
        _maxNumOfGraphicsContexts = atoi(ptr);
    }
}

void DisplaySettings::readCommandLine(ArgumentParser& arguments)
{

    // report the usage options.
    if (arguments.getApplicationUsage())
    {
        arguments.getApplicationUsage()->addCommandLineOption("--display <type>","MONITOR | POWERWALL | REALITY_CENTER | HEAD_MOUNTED_DISPLAY");
        arguments.getApplicationUsage()->addCommandLineOption("--stereo","Use default stereo mode which is ANAGLYPHIC if not overriden by environmental variable");
        arguments.getApplicationUsage()->addCommandLineOption("--stereo <mode>","ANAGLYPHIC | QUAD_BUFFER | HORIZONTAL_SPLIT | VERTICAL_SPLIT | LEFT_EYE | RIGHT_EYE | ON | OFF ");
        arguments.getApplicationUsage()->addCommandLineOption("--rgba","Request a RGBA color buffer visual");
        arguments.getApplicationUsage()->addCommandLineOption("--stencil","Request a stencil buffer visual");
        arguments.getApplicationUsage()->addCommandLineOption("--accum-rgb","Request a rgb accumulator buffer visual");
        arguments.getApplicationUsage()->addCommandLineOption("--accum-rgba","Request a rgb accumulator buffer visual");
        arguments.getApplicationUsage()->addCommandLineOption("--samples <num>","Request a multisample visual");
    }

    std::string str;
    while(arguments.read("--display",str))
    {
        if (str=="MONITOR") _displayType = MONITOR;
        else if (str=="POWERWALL") _displayType = POWERWALL;
        else if (str=="REALITY_CENTER") _displayType = REALITY_CENTER;
        else if (str=="HEAD_MOUNTED_DISPLAY") _displayType = HEAD_MOUNTED_DISPLAY;
    }

    int pos;
    while ((pos=arguments.find("--stereo"))!=0)
    {
        if (arguments.match(pos+1,"ANAGLYPHIC"))            { arguments.remove(pos,2); _stereo = true;_stereoMode = ANAGLYPHIC; }
        else if (arguments.match(pos+1,"QUAD_BUFFER"))      { arguments.remove(pos,2); _stereo = true;_stereoMode = QUAD_BUFFER; }
        else if (arguments.match(pos+1,"HORIZONTAL_SPLIT")) { arguments.remove(pos,2); _stereo = true;_stereoMode = HORIZONTAL_SPLIT; }
        else if (arguments.match(pos+1,"VERTICAL_SPLIT"))   { arguments.remove(pos,2); _stereo = true;_stereoMode = VERTICAL_SPLIT; }
        else if (arguments.match(pos+1,"HORIZONTAL_INTERLACE")) { arguments.remove(pos,2); _stereo = true;_stereoMode = HORIZONTAL_INTERLACE; }
        else if (arguments.match(pos+1,"VERTICAL_INTERLACE"))   { arguments.remove(pos,2); _stereo = true;_stereoMode = VERTICAL_INTERLACE; }
        else if (arguments.match(pos+1,"LEFT_EYE"))         { arguments.remove(pos,2); _stereo = true;_stereoMode = LEFT_EYE; }
        else if (arguments.match(pos+1,"RIGHT_EYE"))        { arguments.remove(pos,2); _stereo = true;_stereoMode = RIGHT_EYE; }
        else if (arguments.match(pos+1,"ON"))               { arguments.remove(pos,2); _stereo = true; }
        else if (arguments.match(pos+1,"OFF"))              { arguments.remove(pos,2); _stereo = false; }
        else                                                { arguments.remove(pos); _stereo = true; }
    }

    while (arguments.read("--rgba"))
    {
        _RGB = true;
        _minimumNumberAlphaBits = 1;
    }

    while (arguments.read("--stencil"))
    {
        _minimumNumberStencilBits = 1;
    }

    while (arguments.read("--accum-rgb"))
    {
        setMinimumNumAccumBits(8,8,8,0);
    }

    while (arguments.read("--accum-rgba"))
    {
        setMinimumNumAccumBits(8,8,8,8);
    }

    while(arguments.read("--samples",str))
    {
        _numMultiSamples = atoi(str.c_str());
    }
}
<|endoftext|>


<commit_before>#include <sys/socket.h>

#include <common/buffer.h>

#include <event/action.h>
#include <event/callback.h>
#include <event/event_system.h>

#include <io/file_descriptor.h>
#include <io/socket.h>
#include <io/unix_server.h>

UnixServer *
UnixServer::listen(const std::string& name)
{
	Socket *socket = Socket::create(SocketAddressFamilyUnix, SocketTypeStream, "");
	if (socket == NULL) {
		ERROR("/unix/server") << "Unable to create socket.";
		return (NULL);
	}
	/*
	 * XXX
	 * After this we could leak a socket, sigh.  Need a blocking close, or
	 * a pool to return the socket to.
	 */
	if (!socket->bind(name)) {
		ERROR("/unix/server") << "Socket bind failed, leaking socket.";
		return (NULL);
	}
	if (!socket->listen(10)) {
		ERROR("/unix/server") << "Socket listen failed, leaking socket.";
		return (NULL);
	}
	UnixServer *server = new UnixServer(socket);
	return (server);
}
<commit_msg>Remove unused include.<commit_after>#include <common/buffer.h>

#include <event/action.h>
#include <event/callback.h>
#include <event/event_system.h>

#include <io/file_descriptor.h>
#include <io/socket.h>
#include <io/unix_server.h>

UnixServer *
UnixServer::listen(const std::string& name)
{
	Socket *socket = Socket::create(SocketAddressFamilyUnix, SocketTypeStream, "");
	if (socket == NULL) {
		ERROR("/unix/server") << "Unable to create socket.";
		return (NULL);
	}
	/*
	 * XXX
	 * After this we could leak a socket, sigh.  Need a blocking close, or
	 * a pool to return the socket to.
	 */
	if (!socket->bind(name)) {
		ERROR("/unix/server") << "Socket bind failed, leaking socket.";
		return (NULL);
	}
	if (!socket->listen(10)) {
		ERROR("/unix/server") << "Socket listen failed, leaking socket.";
		return (NULL);
	}
	UnixServer *server = new UnixServer(socket);
	return (server);
}
<|endoftext|>


<commit_before>// @(#)root/auth:$Id$
// Author: G. Ganis   08/07/2005

/*************************************************************************
 * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TRootSecContext                                                      //
//                                                                      //
// Special implementation of TSecContext                                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "RConfigure.h"

#include <stdlib.h>

#include "TError.h"
#include "TRootSecContext.h"
#include "TROOT.h"
#include "TSocket.h"
#include "TUrl.h"
#include "TVirtualMutex.h"

ClassImp(TRootSecContext)

//______________________________________________________________________________
   TRootSecContext::TRootSecContext(const char *user, const char *host, Int_t meth,
                                    Int_t offset, const char *id,
                                    const char *token, TDatime expdate,
                                    void *ctx, Int_t key)
      : TSecContext(user, host, meth, offset, id, token, expdate, ctx)
{
   // Ctor for SecContext object.
   R__ASSERT(gROOT);

   fRSAKey  = key;
   fMethodName = TAuthenticate::GetAuthMethod(fMethod);
}

//______________________________________________________________________________
TRootSecContext::TRootSecContext(const char *url, Int_t meth, Int_t offset,
                                 const char *id, const char *token,
                                 TDatime expdate, void *ctx, Int_t key)
   : TSecContext(url, meth, offset, id, token, expdate, ctx)
{
   // Ctor for SecContext object.
   // User and host from url = user@host .
   R__ASSERT(gROOT);

   fRSAKey  = key;
   fMethodName = TAuthenticate::GetAuthMethod(fMethod);
}

//______________________________________________________________________________
TRootSecContext::~TRootSecContext()
{
   // Dtor: delete (deActivate, local/remote cleanup, list removal)
   // all what is still active

   TSecContext::Cleanup();
}

//______________________________________________________________________________
void TRootSecContext::DeActivate(Option_t *Opt)
{
   // Set OffSet to -1 and expiring Date to default
   // Remove from the list
   // If globus, cleanup local stuff
   // If Opt contains "C" or "c", ask for remote cleanup
   // If Opt contains "R" or "r", remove from the list
   // Default Opt="CR"

   // Ask remote cleanup of this context
   Bool_t clean = (strstr(Opt,"C") || strstr(Opt,"c"));
   if (clean && fOffSet > -1)
      CleanupSecContext(kFALSE);

   // Cleanup TPwdCtx object fro UsrPwd and SRP
   if (fMethod == TAuthenticate::kClear ||
       fMethod == TAuthenticate::kSRP)
      if (fContext) {
         delete (TPwdCtx *)fContext;
         fContext = 0;
      }

   // Cleanup globus security context if needed
   if (fMethod == TAuthenticate::kGlobus && fContext) {
      GlobusAuth_t globusAuthHook = TAuthenticate::GetGlobusAuthHook();
      if (globusAuthHook != 0) {
         TString det("context");
         TString us("-1");
         (*globusAuthHook)((TAuthenticate *)fContext,us,det);
         fContext = 0;
      }
   }

   Bool_t remove = (strstr(Opt,"R") || strstr(Opt,"r"));
   if (remove && fOffSet > -1){
      R__LOCKGUARD2(gROOTMutex);
      // Remove from the global list
      gROOT->GetListOfSecContexts()->Remove(this);
      // Remove also from local lists in THostAuth objects
      TAuthenticate::RemoveSecContext(this);
   }

   // Set inactive
   fOffSet  = -1;
   fExpDate = kROOTTZERO;

}

//______________________________________________________________________________
Bool_t TRootSecContext::CleanupSecContext(Bool_t all)
{
   // Ask remote client to cleanup security context 'ctx'
   // If 'all', all sec context with the same host as ctx
   // are cleaned.
   Bool_t cleaned = kFALSE;

   // Nothing to do if inactive ...
   if (!IsActive())
      return kTRUE;

   // Contact remote services that used this context,
   // starting from the last ...
   TIter last(fCleanup,kIterBackward);
   TSecContextCleanup *nscc = 0;
   while ((nscc = (TSecContextCleanup *)last()) && !cleaned) {

      // First check if remote daemon supports cleaning
      Int_t srvtyp = nscc->GetType();
      Int_t rproto = nscc->GetProtocol();
      Int_t level = 2;
      if ((srvtyp == TSocket::kROOTD && rproto < 10) ||
          (srvtyp == TSocket::kPROOFD && rproto < 9))
         level = 1;
      if ((srvtyp == TSocket::kROOTD && rproto < 8) ||
          (srvtyp == TSocket::kPROOFD && rproto < 7))
         level = 0;
      if (level) {
         Int_t port = nscc->GetPort();

         TSocket *news = new TSocket(fHost.Data(),port,-1);

         if (news && news->IsValid()) {
            if (srvtyp == TSocket::kPROOFD) {
               news->SetOption(kNoDelay, 1);
               news->Send("cleaning request");
            } else
               news->SetOption(kNoDelay, 0);

            // Backward compatibility: send socket size
            if (srvtyp == TSocket::kROOTD && level == 1)
               news->Send((Int_t)0, (Int_t)0);

            if (all || level == 1) {
               news->Send(Form("%d",TAuthenticate::fgProcessID), kROOTD_CLEANUP);
               cleaned = kTRUE;
            } else {
               news->Send(Form("%d %d %d %s", TAuthenticate::fgProcessID, fMethod,
                               fOffSet, fUser.Data()), kROOTD_CLEANUP);
               if (TAuthenticate::SecureSend(news, 1, fRSAKey,
                                             (char *)(fToken.Data())) == -1) {
                  Info("CleanupSecContext", "problems secure-sending token");
               } else {
                  cleaned = kTRUE;
               }
            }
            if (cleaned && gDebug > 2) {
               char srvname[3][10] = {"sockd", "rootd", "proofd"};
               Info("CleanupSecContext",
                    "remote %s notified for cleanup (%s,%d)",
                    srvname[srvtyp],fHost.Data(),port);
            }
         }
         SafeDelete(news);
      }
   }

   if (!cleaned)
      if (gDebug > 2)
         Info("CleanupSecContext",
              "unable to open valid socket for cleanup for %s", fHost.Data());

   return cleaned;
}

//______________________________________________________________________________
void TRootSecContext::Print(Option_t *opt) const
{
   // If opt is "F" (default) print object content.
   // If opt is "<number>" print in special form for calls within THostAuth
   // with cardinality <number>
   // If opt is "S" prints short in-line form for calls within TFTP,
   // TSlave, TProof ...

   char cord[10] = {0};
   char cspc[10] = {0};

   // Check if option is numeric
   Int_t ord = -1, i = 0;
   for (; i < (Int_t)strlen(opt); i++) {
      if (opt[i] < 48 || opt[i] > 57) {
         ord = -2;
         break;
      }
   }
   // If numeric get the cardinality and prepare the strings
   if (ord == -1)
      ord = atoi(opt);

   // If asked to print ordinal number, preapre the string
   if (ord > -1) {
      snprintf(cord,10,"%d)",ord);
      // and take care of alignment
      Int_t len=strlen(cord);
      while (len--)
         strncat(cspc," ",10);
   }

   if (!strncasecmp(opt,"F",1)) {
      Info("Print",
           "+------------------------------------------------------+");
      Info("Print",
           "+ Host:%s Method:%d (%s) User:'%s'",
           GetHost(), fMethod, GetMethodName(),
           fUser.Data());
      Info("Print",
           "+         OffSet:%d Id: '%s'", fOffSet, fID.Data());
      if (fOffSet > -1)
         Info("Print",
              "+         Expiration time: %s",fExpDate.AsString());
      Info("Print",
           "+------------------------------------------------------+");
   } else if (!strncasecmp(opt,"S",1)) {
      if (fOffSet > -1) {
         if (fID.BeginsWith("AFS"))
            Printf("Security context:     Method: AFS, not reusable");
         else
            Printf("Security context:     Method: %d (%s) expiring on %s",
                   fMethod, GetMethodName(),
                   fExpDate.AsString());
      } else {
         Printf("Security context:     Method: %d (%s) not reusable",
                fMethod, GetMethodName());
      }
   } else {
      // special printing form for THostAuth
      Info("PrintEstblshed","+ %s h:%s met:%d (%s) us:'%s'",
           cord, GetHost(), fMethod, GetMethodName(),
           fUser.Data());
      Info("PrintEstblshed","+ %s offset:%d id: '%s'",
           cspc, fOffSet, fID.Data());
      if (fOffSet > -1)
         Info("PrintEstblshed","+ %s expiring: %s",cspc,fExpDate.AsString());
   }
}

//______________________________________________________________________________
const char *TRootSecContext::AsString(TString &out)
{
   // Returns short string with relevant information about this
   // security context

   if (fOffSet > -1) {
      if (fID.BeginsWith("AFS"))
         out = Form("Method: AFS, not reusable");
      else {
         char expdate[32];
         out = Form("Method: %d (%s) expiring on %s",
                    fMethod, GetMethodName(), fExpDate.AsString(expdate));
      }
   } else {
      if (fOffSet == -1)
         out = Form("Method: %d (%s) not reusable", fMethod, GetMethodName());
      else if (fOffSet == -3)
         out = Form("Method: %d (%s) authorized by /etc/hosts.equiv or $HOME/.rhosts",
                    fMethod, GetMethodName());
      else if (fOffSet == -4)
         out = Form("No authentication required remotely");
   }
   return out.Data();
}
<commit_msg>Optimize use of strings in TRootSecContext::Print<commit_after>// @(#)root/auth:$Id$
// Author: G. Ganis   08/07/2005

/*************************************************************************
 * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TRootSecContext                                                      //
//                                                                      //
// Special implementation of TSecContext                                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "RConfigure.h"

#include <stdlib.h>

#include "TError.h"
#include "TRootSecContext.h"
#include "TROOT.h"
#include "TSocket.h"
#include "TUrl.h"
#include "TVirtualMutex.h"

ClassImp(TRootSecContext)

//______________________________________________________________________________
   TRootSecContext::TRootSecContext(const char *user, const char *host, Int_t meth,
                                    Int_t offset, const char *id,
                                    const char *token, TDatime expdate,
                                    void *ctx, Int_t key)
      : TSecContext(user, host, meth, offset, id, token, expdate, ctx)
{
   // Ctor for SecContext object.
   R__ASSERT(gROOT);

   fRSAKey  = key;
   fMethodName = TAuthenticate::GetAuthMethod(fMethod);
}

//______________________________________________________________________________
TRootSecContext::TRootSecContext(const char *url, Int_t meth, Int_t offset,
                                 const char *id, const char *token,
                                 TDatime expdate, void *ctx, Int_t key)
   : TSecContext(url, meth, offset, id, token, expdate, ctx)
{
   // Ctor for SecContext object.
   // User and host from url = user@host .
   R__ASSERT(gROOT);

   fRSAKey  = key;
   fMethodName = TAuthenticate::GetAuthMethod(fMethod);
}

//______________________________________________________________________________
TRootSecContext::~TRootSecContext()
{
   // Dtor: delete (deActivate, local/remote cleanup, list removal)
   // all what is still active

   TSecContext::Cleanup();
}

//______________________________________________________________________________
void TRootSecContext::DeActivate(Option_t *Opt)
{
   // Set OffSet to -1 and expiring Date to default
   // Remove from the list
   // If globus, cleanup local stuff
   // If Opt contains "C" or "c", ask for remote cleanup
   // If Opt contains "R" or "r", remove from the list
   // Default Opt="CR"

   // Ask remote cleanup of this context
   Bool_t clean = (strstr(Opt,"C") || strstr(Opt,"c"));
   if (clean && fOffSet > -1)
      CleanupSecContext(kFALSE);

   // Cleanup TPwdCtx object fro UsrPwd and SRP
   if (fMethod == TAuthenticate::kClear ||
       fMethod == TAuthenticate::kSRP)
      if (fContext) {
         delete (TPwdCtx *)fContext;
         fContext = 0;
      }

   // Cleanup globus security context if needed
   if (fMethod == TAuthenticate::kGlobus && fContext) {
      GlobusAuth_t globusAuthHook = TAuthenticate::GetGlobusAuthHook();
      if (globusAuthHook != 0) {
         TString det("context");
         TString us("-1");
         (*globusAuthHook)((TAuthenticate *)fContext,us,det);
         fContext = 0;
      }
   }

   Bool_t remove = (strstr(Opt,"R") || strstr(Opt,"r"));
   if (remove && fOffSet > -1){
      R__LOCKGUARD2(gROOTMutex);
      // Remove from the global list
      gROOT->GetListOfSecContexts()->Remove(this);
      // Remove also from local lists in THostAuth objects
      TAuthenticate::RemoveSecContext(this);
   }

   // Set inactive
   fOffSet  = -1;
   fExpDate = kROOTTZERO;

}

//______________________________________________________________________________
Bool_t TRootSecContext::CleanupSecContext(Bool_t all)
{
   // Ask remote client to cleanup security context 'ctx'
   // If 'all', all sec context with the same host as ctx
   // are cleaned.
   Bool_t cleaned = kFALSE;

   // Nothing to do if inactive ...
   if (!IsActive())
      return kTRUE;

   // Contact remote services that used this context,
   // starting from the last ...
   TIter last(fCleanup,kIterBackward);
   TSecContextCleanup *nscc = 0;
   while ((nscc = (TSecContextCleanup *)last()) && !cleaned) {

      // First check if remote daemon supports cleaning
      Int_t srvtyp = nscc->GetType();
      Int_t rproto = nscc->GetProtocol();
      Int_t level = 2;
      if ((srvtyp == TSocket::kROOTD && rproto < 10) ||
          (srvtyp == TSocket::kPROOFD && rproto < 9))
         level = 1;
      if ((srvtyp == TSocket::kROOTD && rproto < 8) ||
          (srvtyp == TSocket::kPROOFD && rproto < 7))
         level = 0;
      if (level) {
         Int_t port = nscc->GetPort();

         TSocket *news = new TSocket(fHost.Data(),port,-1);

         if (news && news->IsValid()) {
            if (srvtyp == TSocket::kPROOFD) {
               news->SetOption(kNoDelay, 1);
               news->Send("cleaning request");
            } else
               news->SetOption(kNoDelay, 0);

            // Backward compatibility: send socket size
            if (srvtyp == TSocket::kROOTD && level == 1)
               news->Send((Int_t)0, (Int_t)0);

            if (all || level == 1) {
               news->Send(Form("%d",TAuthenticate::fgProcessID), kROOTD_CLEANUP);
               cleaned = kTRUE;
            } else {
               news->Send(Form("%d %d %d %s", TAuthenticate::fgProcessID, fMethod,
                               fOffSet, fUser.Data()), kROOTD_CLEANUP);
               if (TAuthenticate::SecureSend(news, 1, fRSAKey,
                                             (char *)(fToken.Data())) == -1) {
                  Info("CleanupSecContext", "problems secure-sending token");
               } else {
                  cleaned = kTRUE;
               }
            }
            if (cleaned && gDebug > 2) {
               char srvname[3][10] = {"sockd", "rootd", "proofd"};
               Info("CleanupSecContext",
                    "remote %s notified for cleanup (%s,%d)",
                    srvname[srvtyp],fHost.Data(),port);
            }
         }
         SafeDelete(news);
      }
   }

   if (!cleaned)
      if (gDebug > 2)
         Info("CleanupSecContext",
              "unable to open valid socket for cleanup for %s", fHost.Data());

   return cleaned;
}

//______________________________________________________________________________
void TRootSecContext::Print(Option_t *opt) const
{
   // If opt is "F" (default) print object content.
   // If opt is "<number>" print in special form for calls within THostAuth
   // with cardinality <number>
   // If opt is "S" prints short in-line form for calls within TFTP,
   // TSlave, TProof ...

   // Check if option is numeric
   Int_t ord = -1, i = 0;
   for (; i < (Int_t)strlen(opt); i++) {
      if (opt[i] < 48 || opt[i] > 57) {
         ord = -2;
         break;
      }
   }
   // If numeric get the cardinality and prepare the strings
   if (ord == -1)
      ord = atoi(opt);

   if (!strncasecmp(opt,"F",1)) {
      Info("Print",
           "+------------------------------------------------------+");
      Info("Print",
           "+ Host:%s Method:%d (%s) User:'%s'",
           GetHost(), fMethod, GetMethodName(),
           fUser.Data());
      Info("Print",
           "+         OffSet:%d Id: '%s'", fOffSet, fID.Data());
      if (fOffSet > -1)
         Info("Print",
              "+         Expiration time: %s",fExpDate.AsString());
      Info("Print",
           "+------------------------------------------------------+");
   } else if (!strncasecmp(opt,"S",1)) {
      if (fOffSet > -1) {
         if (fID.BeginsWith("AFS"))
            Printf("Security context:     Method: AFS, not reusable");
         else
            Printf("Security context:     Method: %d (%s) expiring on %s",
                   fMethod, GetMethodName(),
                   fExpDate.AsString());
      } else {
         Printf("Security context:     Method: %d (%s) not reusable",
                fMethod, GetMethodName());
      }
   } else {
      // special printing form for THostAuth
      Info("PrintEstblshed","+ %d \t h:%s met:%d (%s) us:'%s'",
                               ord, GetHost(), fMethod, GetMethodName(),
                               fUser.Data());
      Info("PrintEstblshed","+ \t offset:%d id: '%s'", fOffSet, fID.Data());
      if (fOffSet > -1)
         Info("PrintEstblshed","+ \t expiring: %s",fExpDate.AsString());
   }
}

//______________________________________________________________________________
const char *TRootSecContext::AsString(TString &out)
{
   // Returns short string with relevant information about this
   // security context

   if (fOffSet > -1) {
      if (fID.BeginsWith("AFS"))
         out = Form("Method: AFS, not reusable");
      else {
         char expdate[32];
         out = Form("Method: %d (%s) expiring on %s",
                    fMethod, GetMethodName(), fExpDate.AsString(expdate));
      }
   } else {
      if (fOffSet == -1)
         out = Form("Method: %d (%s) not reusable", fMethod, GetMethodName());
      else if (fOffSet == -3)
         out = Form("Method: %d (%s) authorized by /etc/hosts.equiv or $HOME/.rhosts",
                    fMethod, GetMethodName());
      else if (fOffSet == -4)
         out = Form("No authentication required remotely");
   }
   return out.Data();
}
<|endoftext|>


<commit_before>#include <vector>

#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>

#include <cal3d/buffersource.h>
#include <cal3d/coreanimation.h>
#include <cal3d/coreanimatedmorph.h>
#include <cal3d/corebone.h>
#include <cal3d/corematerial.h>
#include <cal3d/coremesh.h>
#include <cal3d/coreskeleton.h>
#include <cal3d/coresubmesh.h>
#include <cal3d/loader.h>
#include <cal3d/saver.h>
#include <cal3d/error.h>

using namespace boost::python;

CalCoreAnimationPtr loadCoreAnimationFromBuffer(const cal3d::Buffer& buffer) {
    CalBufferSource cbs(buffer.data(), buffer.size());
    return CalLoader::loadCoreAnimation(cbs);
}

bool saveCoreAnimation(const boost::shared_ptr<CalCoreAnimation>& animation, const std::string& path) {
    return CalSaver::saveCoreAnimation(path, animation.get());
}

CalCoreSkeletonPtr loadCoreSkeletonFromBuffer(const cal3d::Buffer& buffer) {
    CalBufferSource cbs(buffer.data(), buffer.size());
    return CalLoader::loadCoreSkeleton(cbs);
}

bool saveCoreSkeleton(const boost::shared_ptr<CalCoreSkeleton>& skeleton, const std::string& path) {
    return CalSaver::saveCoreSkeleton(path, skeleton.get());
}

CalCoreMaterialPtr loadCoreMaterialFromBuffer(const cal3d::Buffer& buffer) {
    CalBufferSource cbs(buffer.data(), buffer.size());
    return CalLoader::loadCoreMaterial(cbs);
}

bool saveCoreMaterial(const boost::shared_ptr<CalCoreMaterial>& material, const std::string& path) {
    return CalSaver::saveCoreMaterial(path, material.get());
}

CalCoreMeshPtr loadCoreMeshFromBuffer(const cal3d::Buffer& buffer) {
    CalBufferSource cbs(buffer.data(), buffer.size());
    return CalLoader::loadCoreMesh(cbs);
}

bool saveCoreMesh(const boost::shared_ptr<CalCoreMesh>& mesh, const std::string& path) {
    return CalSaver::saveCoreMesh(path, mesh.get());
}

CalCoreAnimatedMorphPtr loadCoreAnimatedMorphFromBuffer(const cal3d::Buffer& buffer) {
    CalBufferSource cbs(buffer.data(), buffer.size());
    return CalLoader::loadCoreAnimatedMorph(cbs);
}

bool saveCoreAnimatedMorph(const boost::shared_ptr<CalCoreAnimatedMorph>& animatedMorph, const std::string& path) {
    return CalSaver::saveCoreAnimatedMorph(path, animatedMorph.get());
}

tuple getCoreSkeletonSceneAmbientColor(const CalCoreSkeletonPtr& skel) {
    CalVector sceneAmbient = skel->sceneAmbientColor;
    return make_tuple(
        sceneAmbient.x,
        sceneAmbient.y,
        sceneAmbient.z
    );
}

void setCoreSkeletonSceneAmbientColor(const CalCoreSkeletonPtr& skel, tuple c) {
    if (len(c) != 3) {
        PyErr_SetString(PyExc_ValueError, "sceneAmbientColor must be a triple");
        throw_error_already_set();
    }
    skel->sceneAmbientColor.x = extract<float>(c[0]);
    skel->sceneAmbientColor.y = extract<float>(c[1]);
    skel->sceneAmbientColor.z = extract<float>(c[2]);
}

list getKeyframes(const CalCoreMorphTrack* t) {
    list rv;
    const std::vector<CalCoreMorphKeyframe>& keyframes = t->keyframes;
    for (
        std::vector<CalCoreMorphKeyframe>::const_iterator i = keyframes.begin();
        i != keyframes.end();
        ++i
    ) {
        rv.append(*i);
    }
    return rv;
}

list getTracks(const CalCoreAnimatedMorph* m) {
    list rv;
    const std::vector<CalCoreMorphTrack>& tracks = m->tracks;
    for (
        std::vector<CalCoreMorphTrack>::const_iterator i = tracks.begin();
        i != tracks.end();
        ++i
    ) {
        rv.append(*i);
    }
    return rv;
}

namespace cal3d {
    struct PythonBuffer : public Buffer {
    public:
        PythonBuffer(PyObject* p) {
            _ = p;
            incref(get());
        }

        ~PythonBuffer() {
            boost::python::PyGILState_AssertIsCurrent();
            decref(get());
        }

        size_t size() const {
            void* data;
            return get()->ob_type->tp_as_buffer->bf_getreadbuffer(get(), 0, &data);
        }

        const void* data() const {
            void* data;
            get()->ob_type->tp_as_buffer->bf_getreadbuffer(get(), 0, &data);
            return data;
        }

        boost::shared_ptr<Buffer> clone() const {
            return boost::shared_ptr<Buffer>(new PythonBuffer(get()));
        }
    private:
        PyObject* get() const {
            return static_cast<PyObject*>(_);
        }
    };

    struct BufferFromPythonObject {
        BufferFromPythonObject() {
            converter::registry::push_back(
                &convertible,
                &construct,
                boost::python::type_id<Buffer>()
            );
        }

        static void* convertible(PyObject* obj_ptr) {
            return (obj_ptr->ob_type->tp_as_buffer &&
                    obj_ptr->ob_type->tp_as_buffer->bf_getreadbuffer)
                   ? obj_ptr
                   : 0;
        }

        static void construct(
            PyObject* obj_ptr,
            boost::python::converter::rvalue_from_python_stage1_data* data
        ) {
            // Note that we're registered as a converter to the Buffer interface,
            // so Boost has already allocated sizeof(Buffer) for us.  Since we're
            // constructing PythonStringBuffer into that memory, assert that
            // PythonStringBuffer and Buffer have the same size.
            BOOST_STATIC_ASSERT(sizeof(Buffer) == sizeof(PythonBuffer));

            void* storage = ((boost::python::converter::rvalue_from_python_storage<PythonBuffer>*)data)->storage.bytes;

            new(storage) PythonBuffer(obj_ptr);

            data->convertible = storage;
        }
    };
}

template<unsigned i>
CalIndex getFaceIndex(const CalCoreSubmesh::Face& f) {
    return f.vertexId[i];
}

struct PythonVertex {
    PythonVertex() {}
    PythonVertex(const CalCoreSubmesh::Vertex& v) {
        position.x = v.position.x;
        position.y = v.position.y;
        position.z = v.position.z;

        normal.x = v.normal.x;
        normal.y = v.normal.y;
        normal.z = v.normal.z;
    }
    CalVector position;
    CalVector normal;

    bool operator==(const PythonVertex& rhs) const {
        return position == rhs.position && normal == rhs.normal;
    }
};

std::vector<PythonVertex> getVertices(const CalCoreSubmesh& submesh) {
    return std::vector<PythonVertex>(
        submesh.getVectorVertex().begin(),
        submesh.getVectorVertex().end());
}

template<typename T>
void exportVector(const char* name) {
    class_<std::vector<T> >(name)
        .def(vector_indexing_suite< std::vector<T>, true>())
        ;
}

#ifndef NDEBUG
BOOST_PYTHON_MODULE(_cal3d_debug)
#else
BOOST_PYTHON_MODULE(_cal3d)
#endif
{
    cal3d::BufferFromPythonObject();

    class_<CalVector>("Vector")
        .def_readwrite("x", &CalVector::x)
        .def_readwrite("y", &CalVector::y)
        .def_readwrite("z", &CalVector::z)
        ;

    class_<CalQuaternion>("Quaternion")
        .def_readwrite("x", &CalQuaternion::x)
        .def_readwrite("y", &CalQuaternion::y)
        .def_readwrite("z", &CalQuaternion::z)
        .def_readwrite("w", &CalQuaternion::w)
        ;

    class_<cal3d::Transform>("Transform")
        .def_readwrite("translation", &cal3d::Transform::translation)
        .def_readwrite("rotation", &cal3d::Transform::rotation)
        ;

    class_<CalCoreBone, boost::shared_ptr<CalCoreBone> >("CoreBone", no_init)
        .def(init<std::string>())
        .def_readwrite("parentIndex", &CalCoreBone::parentId)
        .def_readonly("name", &CalCoreBone::name)
        .def_readwrite("relativeTransform", &CalCoreBone::relativeTransform)
        .def_readwrite("boneSpaceTransform", &CalCoreBone::boneSpaceTransform)
        ;

    exportVector<CalCoreBonePtr>("BoneVector");

    class_<CalCoreSkeleton, boost::shared_ptr<CalCoreSkeleton>, boost::noncopyable>("CoreSkeleton")
        .def("addCoreBone", &CalCoreSkeleton::addCoreBone)
        .def("scale", &CalCoreSkeleton::scale)
        .def("zeroRootTransforms", &CalCoreSkeleton::zeroRootTransforms)
        .add_property("sceneAmbientColor", &getCoreSkeletonSceneAmbientColor, &setCoreSkeletonSceneAmbientColor)
        .add_property("bones", make_function(&CalCoreSkeleton::getCoreBones, return_value_policy<return_by_value>()))
        ;

    {
        scope CalCoreMaterial_class(
            class_<CalCoreMaterial, boost::shared_ptr<CalCoreMaterial> >("CoreMaterial")
                .def_readwrite("maps", &CalCoreMaterial::maps)
        );

        exportVector<CalCoreMaterial::Map>("MapVector");

        class_<CalCoreMaterial::Map>("Map")
            .def_readwrite("filename", &CalCoreMaterial::Map::filename)
            .def_readwrite("type", &CalCoreMaterial::Map::type)
            ;
    }

    class_<CalCoreSubmesh::Face>("Triangle")
        .add_property("v1", &getFaceIndex<0>)
        .add_property("v2", &getFaceIndex<1>)
        .add_property("v3", &getFaceIndex<2>)
        ;

    exportVector<CalCoreSubmesh::Face>("TriangleVector");

    class_<PythonVertex>("Vertex")
        .def_readwrite("position", &PythonVertex::position)
        .def_readwrite("normal", &PythonVertex::normal)
        ;

    exportVector<PythonVertex>("VertexVector");

    class_<CalCoreSubmesh::TextureCoordinate>("TextureCoordinate")
        .def_readwrite("u", &CalCoreSubmesh::TextureCoordinate::u)
        .def_readwrite("v", &CalCoreSubmesh::TextureCoordinate::v)
        ;

    exportVector<CalCoreSubmesh::TextureCoordinate>("TextureCoordinateVector");
    exportVector<std::vector<CalCoreSubmesh::TextureCoordinate> >("TextureCoordinateVectorVector");

    class_<CalCoreSubmesh::Influence>("Influence")
        .def_readwrite("boneId", &CalCoreSubmesh::Influence::boneId)
        .def_readwrite("weight", &CalCoreSubmesh::Influence::weight)
        .def_readwrite("isLast", &CalCoreSubmesh::Influence::lastInfluenceForThisVertex)
        ;

    exportVector<CalCoreSubmesh::Influence>("InfluenceVector");

    class_<CalCoreSubmesh, boost::shared_ptr<CalCoreSubmesh>, boost::noncopyable>("CoreSubmesh", no_init)
        .def_readwrite("coreMaterialThreadId", &CalCoreSubmesh::coreMaterialThreadId)
        .def_readwrite("triangles", &CalCoreSubmesh::faces)
        .add_property("vertices", &getVertices)
        .add_property("hasVertexColors", &CalCoreSubmesh::hasVertexColors)
        .add_property("colors", make_function(&CalCoreSubmesh::getVertexColors, return_value_policy<return_by_value>()))
        .add_property("texcoords", make_function(&CalCoreSubmesh::getVectorVectorTextureCoordinate, return_value_policy<return_by_value>()))
        .add_property("influences", make_function(&CalCoreSubmesh::getInfluences, return_value_policy<return_by_value>()))
        ;

    class_< CalCoreMesh::CalCoreSubmeshVector >("CalCoreSubmeshVector")
        .def(vector_indexing_suite<CalCoreMesh::CalCoreSubmeshVector, true>())
        ;

    class_<CalCoreMesh, boost::shared_ptr<CalCoreMesh> >("CoreMesh")
        .def_readwrite("submeshes", &CalCoreMesh::submeshes)
        .def("scale", &CalCoreMesh::scale)
        .def("fixup", &CalCoreMesh::fixup)
        ;

    class_<CalCoreAnimation, boost::shared_ptr<CalCoreAnimation> >("CoreAnimation")
        .def("scale", &CalCoreAnimation::scale)
        .def("fixup", &CalCoreAnimation::fixup)
        ;

    class_<CalCoreMorphKeyframe>("CoreMorphKeyframe")
        .add_property("time", &CalCoreMorphKeyframe::time)
        .add_property("weight", &CalCoreMorphKeyframe::weight)
        ;

    class_<CalCoreMorphTrack, boost::shared_ptr<CalCoreMorphTrack> >("CoreMorphTrack")
        .def_readonly("name", &CalCoreMorphTrack::morphName)
        .add_property("keyframes", &getKeyframes)
        ;

    class_<CalCoreAnimatedMorph, boost::shared_ptr<CalCoreAnimatedMorph> >("CoreAnimatedMorph")
        .def("removeZeroScaleTracks", &CalCoreAnimatedMorph::removeZeroScaleTracks)
        .def("scale", &CalCoreAnimatedMorph::scale)
        .def_readonly("duration", &CalCoreAnimatedMorph::duration)
        .add_property("tracks", &getTracks)
        ;

    def("loadCoreAnimationFromBuffer", &loadCoreAnimationFromBuffer);
    def("saveCoreAnimation", &saveCoreAnimation);
    def("saveCoreAnimationToBuffer", &CalSaver::saveCoreAnimationToBuffer);

    def("loadCoreSkeletonFromBuffer", &loadCoreSkeletonFromBuffer);
    def("saveCoreSkeleton", &saveCoreSkeleton);
    def("saveCoreSkeletonToBuffer", &CalSaver::saveCoreSkeletonToBuffer);

    def("loadCoreMaterialFromBuffer", &loadCoreMaterialFromBuffer);
    def("saveCoreMaterial", &saveCoreMaterial);
    def("saveCoreMaterialToBuffer", &CalSaver::saveCoreMaterialToBuffer);

    def("loadCoreMeshFromBuffer", &loadCoreMeshFromBuffer);
    def("saveCoreMesh", &saveCoreMesh);
    def("saveCoreMeshToBuffer", &CalSaver::saveCoreMeshToBuffer);

    def("loadCoreAnimatedMorphFromBuffer", &loadCoreAnimatedMorphFromBuffer);
    def("saveCoreAnimatedMorph", &saveCoreAnimatedMorph);
    def("saveCoreAnimatedMorphToBuffer", &CalSaver::saveCoreAnimatedMorphToBuffer);

    def("getLastErrorText", &CalError::getLastErrorText);
}
<commit_msg>Export skeletal animations in the asset server<commit_after>#include <vector>

#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>

#include <cal3d/buffersource.h>
#include <cal3d/coreanimation.h>
#include <cal3d/coreanimatedmorph.h>
#include <cal3d/corebone.h>
#include <cal3d/corematerial.h>
#include <cal3d/coremesh.h>
#include <cal3d/coreskeleton.h>
#include <cal3d/coresubmesh.h>
#include <cal3d/loader.h>
#include <cal3d/saver.h>
#include <cal3d/error.h>

using namespace boost::python;

CalCoreAnimationPtr loadCoreAnimationFromBuffer(const cal3d::Buffer& buffer) {
    CalBufferSource cbs(buffer.data(), buffer.size());
    return CalLoader::loadCoreAnimation(cbs);
}

bool saveCoreAnimation(const boost::shared_ptr<CalCoreAnimation>& animation, const std::string& path) {
    return CalSaver::saveCoreAnimation(path, animation.get());
}

CalCoreSkeletonPtr loadCoreSkeletonFromBuffer(const cal3d::Buffer& buffer) {
    CalBufferSource cbs(buffer.data(), buffer.size());
    return CalLoader::loadCoreSkeleton(cbs);
}

bool saveCoreSkeleton(const boost::shared_ptr<CalCoreSkeleton>& skeleton, const std::string& path) {
    return CalSaver::saveCoreSkeleton(path, skeleton.get());
}

CalCoreMaterialPtr loadCoreMaterialFromBuffer(const cal3d::Buffer& buffer) {
    CalBufferSource cbs(buffer.data(), buffer.size());
    return CalLoader::loadCoreMaterial(cbs);
}

bool saveCoreMaterial(const boost::shared_ptr<CalCoreMaterial>& material, const std::string& path) {
    return CalSaver::saveCoreMaterial(path, material.get());
}

CalCoreMeshPtr loadCoreMeshFromBuffer(const cal3d::Buffer& buffer) {
    CalBufferSource cbs(buffer.data(), buffer.size());
    return CalLoader::loadCoreMesh(cbs);
}

bool saveCoreMesh(const boost::shared_ptr<CalCoreMesh>& mesh, const std::string& path) {
    return CalSaver::saveCoreMesh(path, mesh.get());
}

CalCoreAnimatedMorphPtr loadCoreAnimatedMorphFromBuffer(const cal3d::Buffer& buffer) {
    CalBufferSource cbs(buffer.data(), buffer.size());
    return CalLoader::loadCoreAnimatedMorph(cbs);
}

bool saveCoreAnimatedMorph(const boost::shared_ptr<CalCoreAnimatedMorph>& animatedMorph, const std::string& path) {
    return CalSaver::saveCoreAnimatedMorph(path, animatedMorph.get());
}

tuple getCoreSkeletonSceneAmbientColor(const CalCoreSkeletonPtr& skel) {
    CalVector sceneAmbient = skel->sceneAmbientColor;
    return make_tuple(
        sceneAmbient.x,
        sceneAmbient.y,
        sceneAmbient.z
    );
}

void setCoreSkeletonSceneAmbientColor(const CalCoreSkeletonPtr& skel, tuple c) {
    if (len(c) != 3) {
        PyErr_SetString(PyExc_ValueError, "sceneAmbientColor must be a triple");
        throw_error_already_set();
    }
    skel->sceneAmbientColor.x = extract<float>(c[0]);
    skel->sceneAmbientColor.y = extract<float>(c[1]);
    skel->sceneAmbientColor.z = extract<float>(c[2]);
}

list getKeyframes(const CalCoreMorphTrack* t) {
    list rv;
    const std::vector<CalCoreMorphKeyframe>& keyframes = t->keyframes;
    for (
        std::vector<CalCoreMorphKeyframe>::const_iterator i = keyframes.begin();
        i != keyframes.end();
        ++i
    ) {
        rv.append(*i);
    }
    return rv;
}

list getTracks(const CalCoreAnimatedMorph* m) {
    list rv;
    const std::vector<CalCoreMorphTrack>& tracks = m->tracks;
    for (
        std::vector<CalCoreMorphTrack>::const_iterator i = tracks.begin();
        i != tracks.end();
        ++i
    ) {
        rv.append(*i);
    }
    return rv;
}

namespace cal3d {
    struct PythonBuffer : public Buffer {
    public:
        PythonBuffer(PyObject* p) {
            _ = p;
            incref(get());
        }

        ~PythonBuffer() {
            boost::python::PyGILState_AssertIsCurrent();
            decref(get());
        }

        size_t size() const {
            void* data;
            return get()->ob_type->tp_as_buffer->bf_getreadbuffer(get(), 0, &data);
        }

        const void* data() const {
            void* data;
            get()->ob_type->tp_as_buffer->bf_getreadbuffer(get(), 0, &data);
            return data;
        }

        boost::shared_ptr<Buffer> clone() const {
            return boost::shared_ptr<Buffer>(new PythonBuffer(get()));
        }
    private:
        PyObject* get() const {
            return static_cast<PyObject*>(_);
        }
    };

    struct BufferFromPythonObject {
        BufferFromPythonObject() {
            converter::registry::push_back(
                &convertible,
                &construct,
                boost::python::type_id<Buffer>()
            );
        }

        static void* convertible(PyObject* obj_ptr) {
            return (obj_ptr->ob_type->tp_as_buffer &&
                    obj_ptr->ob_type->tp_as_buffer->bf_getreadbuffer)
                   ? obj_ptr
                   : 0;
        }

        static void construct(
            PyObject* obj_ptr,
            boost::python::converter::rvalue_from_python_stage1_data* data
        ) {
            // Note that we're registered as a converter to the Buffer interface,
            // so Boost has already allocated sizeof(Buffer) for us.  Since we're
            // constructing PythonStringBuffer into that memory, assert that
            // PythonStringBuffer and Buffer have the same size.
            BOOST_STATIC_ASSERT(sizeof(Buffer) == sizeof(PythonBuffer));

            void* storage = ((boost::python::converter::rvalue_from_python_storage<PythonBuffer>*)data)->storage.bytes;

            new(storage) PythonBuffer(obj_ptr);

            data->convertible = storage;
        }
    };
}

template<unsigned i>
CalIndex getFaceIndex(const CalCoreSubmesh::Face& f) {
    return f.vertexId[i];
}

struct PythonVertex {
    PythonVertex() {}
    PythonVertex(const CalCoreSubmesh::Vertex& v) {
        position.x = v.position.x;
        position.y = v.position.y;
        position.z = v.position.z;

        normal.x = v.normal.x;
        normal.y = v.normal.y;
        normal.z = v.normal.z;
    }
    CalVector position;
    CalVector normal;

    bool operator==(const PythonVertex& rhs) const {
        return position == rhs.position && normal == rhs.normal;
    }
};

std::vector<PythonVertex> getVertices(const CalCoreSubmesh& submesh) {
    return std::vector<PythonVertex>(
        submesh.getVectorVertex().begin(),
        submesh.getVectorVertex().end());
}

template<typename T>
void exportVector(const char* name) {
    class_<std::vector<T> >(name)
        .def(vector_indexing_suite< std::vector<T>, true>())
        ;
}

#ifndef NDEBUG
BOOST_PYTHON_MODULE(_cal3d_debug)
#else
BOOST_PYTHON_MODULE(_cal3d)
#endif
{
    cal3d::BufferFromPythonObject();

    class_<CalVector>("Vector")
        .def_readwrite("x", &CalVector::x)
        .def_readwrite("y", &CalVector::y)
        .def_readwrite("z", &CalVector::z)
        ;

    class_<CalQuaternion>("Quaternion")
        .def_readwrite("x", &CalQuaternion::x)
        .def_readwrite("y", &CalQuaternion::y)
        .def_readwrite("z", &CalQuaternion::z)
        .def_readwrite("w", &CalQuaternion::w)
        ;

    class_<cal3d::Transform>("Transform")
        .def_readwrite("translation", &cal3d::Transform::translation)
        .def_readwrite("rotation", &cal3d::Transform::rotation)
        ;

    class_<CalCoreBone, boost::shared_ptr<CalCoreBone> >("CoreBone", no_init)
        .def(init<std::string>())
        .def_readwrite("parentIndex", &CalCoreBone::parentId)
        .def_readonly("name", &CalCoreBone::name)
        .def_readwrite("relativeTransform", &CalCoreBone::relativeTransform)
        .def_readwrite("boneSpaceTransform", &CalCoreBone::boneSpaceTransform)
        ;

    exportVector<CalCoreBonePtr>("BoneVector");

    class_<CalCoreSkeleton, boost::shared_ptr<CalCoreSkeleton>, boost::noncopyable>("CoreSkeleton")
        .def("addCoreBone", &CalCoreSkeleton::addCoreBone)
        .def("scale", &CalCoreSkeleton::scale)
        .def("zeroRootTransforms", &CalCoreSkeleton::zeroRootTransforms)
        .add_property("sceneAmbientColor", &getCoreSkeletonSceneAmbientColor, &setCoreSkeletonSceneAmbientColor)
        .add_property("bones", make_function(&CalCoreSkeleton::getCoreBones, return_value_policy<return_by_value>()))
        ;

    {
        scope CalCoreMaterial_class(
            class_<CalCoreMaterial, boost::shared_ptr<CalCoreMaterial> >("CoreMaterial")
                .def_readwrite("maps", &CalCoreMaterial::maps)
        );

        exportVector<CalCoreMaterial::Map>("MapVector");

        class_<CalCoreMaterial::Map>("Map")
            .def_readwrite("filename", &CalCoreMaterial::Map::filename)
            .def_readwrite("type", &CalCoreMaterial::Map::type)
            ;
    }

    class_<CalCoreSubmesh::Face>("Triangle")
        .add_property("v1", &getFaceIndex<0>)
        .add_property("v2", &getFaceIndex<1>)
        .add_property("v3", &getFaceIndex<2>)
        ;

    exportVector<CalCoreSubmesh::Face>("TriangleVector");

    class_<PythonVertex>("Vertex")
        .def_readwrite("position", &PythonVertex::position)
        .def_readwrite("normal", &PythonVertex::normal)
        ;

    exportVector<PythonVertex>("VertexVector");

    class_<CalCoreSubmesh::TextureCoordinate>("TextureCoordinate")
        .def_readwrite("u", &CalCoreSubmesh::TextureCoordinate::u)
        .def_readwrite("v", &CalCoreSubmesh::TextureCoordinate::v)
        ;

    exportVector<CalCoreSubmesh::TextureCoordinate>("TextureCoordinateVector");
    exportVector<std::vector<CalCoreSubmesh::TextureCoordinate> >("TextureCoordinateVectorVector");

    class_<CalCoreSubmesh::Influence>("Influence")
        .def_readwrite("boneId", &CalCoreSubmesh::Influence::boneId)
        .def_readwrite("weight", &CalCoreSubmesh::Influence::weight)
        .def_readwrite("isLast", &CalCoreSubmesh::Influence::lastInfluenceForThisVertex)
        ;

    exportVector<CalCoreSubmesh::Influence>("InfluenceVector");

    class_<CalCoreSubmesh, boost::shared_ptr<CalCoreSubmesh>, boost::noncopyable>("CoreSubmesh", no_init)
        .def_readwrite("coreMaterialThreadId", &CalCoreSubmesh::coreMaterialThreadId)
        .def_readwrite("triangles", &CalCoreSubmesh::faces)
        .add_property("vertices", &getVertices)
        .add_property("hasVertexColors", &CalCoreSubmesh::hasVertexColors)
        .add_property("colors", make_function(&CalCoreSubmesh::getVertexColors, return_value_policy<return_by_value>()))
        .add_property("texcoords", make_function(&CalCoreSubmesh::getVectorVectorTextureCoordinate, return_value_policy<return_by_value>()))
        .add_property("influences", make_function(&CalCoreSubmesh::getInfluences, return_value_policy<return_by_value>()))
        ;

    class_< CalCoreMesh::CalCoreSubmeshVector >("CalCoreSubmeshVector")
        .def(vector_indexing_suite<CalCoreMesh::CalCoreSubmeshVector, true>())
        ;

    class_<CalCoreMesh, CalCoreMeshPtr>("CoreMesh")
        .def_readwrite("submeshes", &CalCoreMesh::submeshes)
        .def("scale", &CalCoreMesh::scale)
        .def("fixup", &CalCoreMesh::fixup)
        ;

    class_<CalCoreKeyframe>("CoreKeyframe")
        .def_readwrite("time", &CalCoreKeyframe::time)
        .def_readwrite("transform", &CalCoreKeyframe::transform)
        ;

    class_<CalCoreTrack::KeyframeList>("CoreKeyframeVector")
        .def(vector_indexing_suite<CalCoreTrack::KeyframeList, true>())
        ;

    class_<CalCoreTrack>("CoreTrack", init<int, const CalCoreTrack::KeyframeList&>())
        .def_readwrite("coreBoneId", &CalCoreTrack::coreBoneId)
        .def_readwrite("keyframes", &CalCoreTrack::keyframes)
        ;

    class_< std::vector<CalCoreTrack> >("CoreTrackVector")
        .def(vector_indexing_suite< std::vector<CalCoreTrack>, true >())
        ;

    class_<CalCoreAnimation, CalCoreAnimationPtr>("CoreAnimation")
        .def("scale", &CalCoreAnimation::scale)
        .def("fixup", &CalCoreAnimation::fixup)
        .def_readwrite("duration", &CalCoreAnimation::duration)
        .def_readwrite("tracks", &CalCoreAnimation::tracks)
        ;

    class_<CalCoreMorphKeyframe>("CoreMorphKeyframe")
        .add_property("time", &CalCoreMorphKeyframe::time)
        .add_property("weight", &CalCoreMorphKeyframe::weight)
        ;

    class_<CalCoreMorphTrack, CalCoreMorphTrackPtr>("CoreMorphTrack")
        .def_readonly("name", &CalCoreMorphTrack::morphName)
        .add_property("keyframes", &getKeyframes)
        ;

    class_<CalCoreAnimatedMorph, CalCoreAnimatedMorphPtr>("CoreAnimatedMorph")
        .def("removeZeroScaleTracks", &CalCoreAnimatedMorph::removeZeroScaleTracks)
        .def("scale", &CalCoreAnimatedMorph::scale)
        .def_readonly("duration", &CalCoreAnimatedMorph::duration)
        .add_property("tracks", &getTracks)
        ;

    def("loadCoreAnimationFromBuffer", &loadCoreAnimationFromBuffer);
    def("saveCoreAnimation", &saveCoreAnimation);
    def("saveCoreAnimationToBuffer", &CalSaver::saveCoreAnimationToBuffer);

    def("loadCoreSkeletonFromBuffer", &loadCoreSkeletonFromBuffer);
    def("saveCoreSkeleton", &saveCoreSkeleton);
    def("saveCoreSkeletonToBuffer", &CalSaver::saveCoreSkeletonToBuffer);

    def("loadCoreMaterialFromBuffer", &loadCoreMaterialFromBuffer);
    def("saveCoreMaterial", &saveCoreMaterial);
    def("saveCoreMaterialToBuffer", &CalSaver::saveCoreMaterialToBuffer);

    def("loadCoreMeshFromBuffer", &loadCoreMeshFromBuffer);
    def("saveCoreMesh", &saveCoreMesh);
    def("saveCoreMeshToBuffer", &CalSaver::saveCoreMeshToBuffer);

    def("loadCoreAnimatedMorphFromBuffer", &loadCoreAnimatedMorphFromBuffer);
    def("saveCoreAnimatedMorph", &saveCoreAnimatedMorph);
    def("saveCoreAnimatedMorphToBuffer", &CalSaver::saveCoreAnimatedMorphToBuffer);

    def("getLastErrorText", &CalError::getLastErrorText);
}
<|endoftext|>


<commit_before>#include "vtkFLAC3DReader.h"

#include "vtkUnstructuredGrid.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include <vtksys/ios/sstream>
#include <sstream>

#include <vtkStringList.h>
#include <vtkStdString.h>
#include <vtkStringArray.h>
#include <vtkIntArray.h>
#include <vtkDoubleArray.h>
#include <vtkCellArray.h>
#include <vtkPointData.h>
#include <vtkCellData.h>

#include "StringUtilities.h"

vtkCxxRevisionMacro(vtkFLAC3DReader, "$Revision: 1.1 $");
vtkStandardNewMacro(vtkFLAC3DReader);

//_________________________________________________________________________
vtkFLAC3DReader::vtkFLAC3DReader()
{
	this->FileName = NULL;
	this->SetNumberOfInputPorts(0);

	this->DisplacementVectorsFile = NULL;
	this->ZonesScalarsFile = NULL;
	this->ZonesTensorsFile = NULL;
}

//_________________________________________________________________________
vtkFLAC3DReader::~vtkFLAC3DReader()
{
	this->SetFileName(NULL);
}

//_________________________________________________________________________
void vtkFLAC3DReader::PrintSelf(ostream& os, vtkIndent indent)
{
	this->Superclass::PrintSelf(os,indent);
	os << indent <<  "FileName: "
		<< (this->FileName ? this->FileName : "(none)") << "\n";
}

//_________________________________________________________________________
int vtkFLAC3DReader::CanReadFile( const char* fname )
{
	return 1;
}

//_________________________________________________________________________
int vtkFLAC3DReader::RequestInformation(vtkInformation* request,
									  vtkInformationVector** inputVector,
									  vtkInformationVector* outputVector)
{
	return 1;
}

//_________________________________________________________________________
int vtkFLAC3DReader::RequestData(vtkInformation* request,
							   vtkInformationVector** inputVector,
							   vtkInformationVector* outputVector)
{
	vtkInformation *outInfo = outputVector->GetInformationObject(0);
	vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));

	// Make sure we have a file to read.
	if(!this->FileName)  {
		vtkErrorMacro("No file name specified.  Cannot open.");
		return 0;
	}
	if(strlen(this->FileName)==0)  {
		vtkErrorMacro("File name is null.  Cannot open.");
		return 0;
	}

	ifstream inFile;
	inFile.open(this->FileName, ios::in);
	if(!inFile)
	{
		vtkErrorMacro("File Error: cannot open file: "<< this->FileName);
		return 0;
	}

	vtkPoints* outPoints = vtkPoints::New();

	vtkIdType ids[8];
	string line;
	vector<string> lineSplit;

	// skip the headers
	while(!inFile.eof())
	{
		getline(inFile, line);
		if(line.size() == 0) continue;
		if(line[0] == '*') continue;
		if(line[0] == 'G')
			break;
	}

	// read the GRIDPOINTS section
	while(line.substr(0,2) == "G ")
	{
		StringUtilities::split(line, lineSplit, " ");

		vtkIdType id;
		double pt[3];
		id = atoi(lineSplit[1].c_str());
		pt[0] = atof(lineSplit[2].c_str());
		pt[1] = atof(lineSplit[3].c_str());
		pt[2] = atof(lineSplit[4].c_str());

		outPoints->InsertNextPoint(pt);

		if(inFile.eof()) break;

		do
		{
			getline(inFile, line);
		}while((line.size() == 0 || line[0] == '*') &! inFile.eof());

		if(line.size() == 0 || line[0] == '*')
			break;
	}

	if(line.size() == 0 || line[0] == '*' || inFile.eof())
	{
		output->SetPoints(outPoints);
		outPoints->Delete();
		return 1;
	}

	vtkUnstructuredGrid* temp= vtkUnstructuredGrid::New();

	// read the ZONES section
	while(line.substr(0,2) == "Z ")
	{
		StringUtilities::split(line, lineSplit, " ");

		if(lineSplit[1] == "B8")
		{
			vtkIdType id = atoi(lineSplit[2].c_str());

			// see FLAC3D documentation for hexahedron topology
			ids[0] = atoi(lineSplit[3].c_str()) -1;
			ids[1] = atoi(lineSplit[4].c_str()) -1;
			ids[2] = atoi(lineSplit[7].c_str()) -1;
			ids[3] = atoi(lineSplit[5].c_str()) -1;
			ids[4] = atoi(lineSplit[6].c_str()) -1;
			ids[5] = atoi(lineSplit[9].c_str()) -1;
			ids[6] = atoi(lineSplit[10].c_str()) -1;
			ids[7] = atoi(lineSplit[8].c_str()) -1;

			temp->InsertNextCell(VTK_HEXAHEDRON,8,ids);
		}

		if(inFile.eof()) break;

		do
		{
			getline(inFile, line);
		}while((line.size() == 0 || line[0] == '*') &! inFile.eof());

		if(line.size() == 0 || line[0] == '*')
			break;
	}

	temp->SetPoints(outPoints);
	output->ShallowCopy(temp);
	outPoints->Delete();

	if(line.size() == 0 || line[0] == '*' || inFile.eof())
		return 1;

	vtkStringArray* groupNameArray = vtkStringArray::New();
	groupNameArray->SetName("Group Name");
	groupNameArray->SetNumberOfValues(temp->GetNumberOfCells());

	vtkIntArray* groupIdArray = vtkIntArray::New();
	groupIdArray->SetName("Group Id");
	groupIdArray->SetNumberOfValues(temp->GetNumberOfCells());

	// in case some zones doesn't belong to a group
	// if it's sure that all zones belong to a group, this
	// loop should be removed to save time
	//for(vtkIdType i=0; i<temp->GetNumberOfCells(); ++i)
	//{
	//	groupNameArray->SetValue(i, "");
	//	groupIdArray->SetValue(i,0);
	//}

	int groupId = 0;
	while(line.substr(0,7) == "ZGROUP ")
	{
		StringUtilities::split(line, lineSplit, " ");
		string groupName = lineSplit[1].substr(1,lineSplit[1].size()-2);

		while(true)
		{
			do
			{
				getline(inFile, line);
			}while((line.size() == 0 || line[0] == '*') &! inFile.eof());

			if(line.size() == 0 || line[0] == '*' || inFile.eof() || line.substr(0,6) == "ZGROUP")
				break;

			StringUtilities::split(line, lineSplit, " ");
			for(vector<string>::iterator it = lineSplit.begin(); it != lineSplit.end(); ++it)
			{
				int zone = atoi(it->c_str()) -1;
				groupNameArray->SetValue(zone, groupName);
				groupIdArray->SetValue(zone, groupId);
			}
		}
		++groupId;
	}

	output->GetCellData()->AddArray(groupNameArray);
	output->GetCellData()->AddArray(groupIdArray);

	inFile.close();

	this->importDisplacements(output);
	this->importScalars(output);
	this->importTensors(output);

	return 1;
}

//_________________________________________________________________________
void vtkFLAC3DReader::importDisplacements(vtkUnstructuredGrid *output)
{
	// Make sure we have a file to read.
	if(!this->DisplacementVectorsFile)  {
		return;
	}
	if(strlen(this->DisplacementVectorsFile)==0)  {
		return;
	}

	ifstream inFile;
	inFile.open(this->DisplacementVectorsFile, ios::in);
	if(!inFile)
	{
		vtkErrorMacro("File Error: cannot open file: "<< this->DisplacementVectorsFile);
		return;
	}

	vtkDoubleArray* dispArray = vtkDoubleArray::New();
	dispArray->SetName("Displacement Vectors");
	dispArray->SetNumberOfComponents(3);

	dispArray->SetNumberOfTuples(output->GetNumberOfPoints());
	for(vtkIdType i=0; i<output->GetNumberOfPoints(); ++i)
	{
		dispArray->SetTuple3(i,0,0,0);
	}

	string line;
	vector<string> lineSplit;

	// skip the headers
	while(!inFile.eof())
	{
		getline(inFile, line);
		if(line.size() > 0)
			break;
	}

	while(!inFile.eof())
	{
		getline(inFile, line);
		if(line.size() < 4)
			continue;

		StringUtilities::split(line, lineSplit, ";");
		vtkIdType id = atoi(lineSplit[0].c_str()) - 1;
		double dispX = atof(lineSplit[1].c_str());
		double dispY = atof(lineSplit[2].c_str());
		double dispZ = atof(lineSplit[3].c_str());

		dispArray->SetTuple3(id, dispX, dispY, dispZ);
	}

	inFile.close();

	output->GetPointData()->AddArray(dispArray);
}

//_________________________________________________________________________
void vtkFLAC3DReader::importScalars(vtkUnstructuredGrid *output)
{
	// Make sure we have a file to read.
	if(!this->ZonesScalarsFile)  {
		return;
	}
	if(strlen(this->ZonesScalarsFile)==0)  {
		return;
	}

	ifstream inFile;
	inFile.open(this->ZonesScalarsFile, ios::in);
	if(!inFile)
	{
		vtkErrorMacro("File Error: cannot open file: "<< this->ZonesScalarsFile);
		return;
	}

	vtkIntArray* stateArray = vtkIntArray::New();
	stateArray->SetName("state");

	vtkDoubleArray* cohesionArray = vtkDoubleArray::New();
	cohesionArray->SetName("cohesion(Pa)");

	vtkDoubleArray* frictionArray = vtkDoubleArray::New();
	frictionArray->SetName("friction()");

	vtkIntArray* excavationYearArray = vtkIntArray::New();
	excavationYearArray->SetName("Excavation Year");

	vtkDoubleArray* damageArray = vtkDoubleArray::New();
	damageArray->SetName("damage");

	stateArray->SetNumberOfValues(output->GetNumberOfCells());
	cohesionArray->SetNumberOfValues(output->GetNumberOfCells());
	frictionArray->SetNumberOfValues(output->GetNumberOfCells());
	excavationYearArray->SetNumberOfValues(output->GetNumberOfCells());
	damageArray->SetNumberOfValues(output->GetNumberOfCells());

	for(vtkIdType i=0; i<output->GetNumberOfCells(); ++i)
	{
		stateArray->SetValue(i,0);
		cohesionArray->SetValue(i,0);
		frictionArray->SetValue(i,0);
		excavationYearArray->SetValue(i,0);
		damageArray->SetValue(i,0);
	}

	string line;
	vector<string> lineSplit;

	// skip the headers
	while(!inFile.eof())
	{
		getline(inFile, line);
		if(line.size() > 0)
			break;
	}

	while(!inFile.eof())
	{
		getline(inFile, line);
		if(line.size() < 4)
			continue;

		StringUtilities::split(line, lineSplit, ";");
		vtkIdType id = atoi(lineSplit[0].c_str()) - 1;
		double state = atof(lineSplit[1].c_str());
		double cohesion = atof(lineSplit[2].c_str());
		double friction = atof(lineSplit[3].c_str());

		int excavationYear = atoi(lineSplit[4].c_str());
		if(lineSplit[4] == "pfin")
			excavationYear = 9999;

		double damage = atof(lineSplit[5].c_str());

		stateArray->SetValue(id,state);
		cohesionArray->SetValue(id,cohesion);
		frictionArray->SetValue(id,friction);
		excavationYearArray->SetValue(id,excavationYear);
		damageArray->SetValue(id,damage);
	}

	inFile.close();

	output->GetCellData()->AddArray(stateArray);
	output->GetCellData()->AddArray(cohesionArray);
	output->GetCellData()->AddArray(frictionArray);
	output->GetCellData()->AddArray(excavationYearArray);
	output->GetCellData()->AddArray(damageArray);
}

//_________________________________________________________________________
void vtkFLAC3DReader::importTensors(vtkUnstructuredGrid *output)
{
	// Make sure we have a file to read.
	if(!this->ZonesTensorsFile)  {
		return;
	}
	if(strlen(this->ZonesTensorsFile)==0)  {
		return;
	}

	ifstream inFile;
	inFile.open(this->ZonesTensorsFile, ios::in);
	if(!inFile)
	{
		vtkErrorMacro("File Error: cannot open file: "<< this->ZonesTensorsFile);
		return;
	}

	vtkDoubleArray* tensorsArray = vtkDoubleArray::New();
	tensorsArray->SetName("tensors(Pa)");
	tensorsArray->SetNumberOfComponents(9);

	tensorsArray->SetNumberOfTuples(output->GetNumberOfPoints());
	for(vtkIdType i=0; i<output->GetNumberOfPoints(); ++i)
	{
		tensorsArray->SetTuple9(i,0,0,0,0,0,0,0,0,0);
	}

	string line;
	vector<string> lineSplit;

	// skip the headers
	while(!inFile.eof())
	{
		getline(inFile, line);
		if(line.size() > 0)
			break;
	}

	while(!inFile.eof())
	{
		getline(inFile, line);
		if(line.size() < 4)
			continue;

		StringUtilities::split(line, lineSplit, ";");
		vtkIdType id = atoi(lineSplit[0].c_str()) - 1;
		double sxx = atof(lineSplit[1].c_str());
		double syy = atof(lineSplit[2].c_str());
		double szz = atof(lineSplit[3].c_str());
		double sxy = atof(lineSplit[4].c_str());
		double sxz = atof(lineSplit[5].c_str());
		double syz = atof(lineSplit[6].c_str());

		tensorsArray->SetTuple9(id, sxx, sxy, sxz, sxy, syy, syz, sxz, syz, szz);
	}

	inFile.close();

	output->GetCellData()->AddArray(tensorsArray);
}<commit_msg>FLAC3DReader fixed a bug in tensors array size<commit_after>#include "vtkFLAC3DReader.h"

#include "vtkUnstructuredGrid.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include <vtksys/ios/sstream>
#include <sstream>

#include <vtkStringList.h>
#include <vtkStdString.h>
#include <vtkStringArray.h>
#include <vtkIntArray.h>
#include <vtkDoubleArray.h>
#include <vtkCellArray.h>
#include <vtkPointData.h>
#include <vtkCellData.h>

#include "StringUtilities.h"

vtkCxxRevisionMacro(vtkFLAC3DReader, "$Revision: 1.1 $");
vtkStandardNewMacro(vtkFLAC3DReader);

//_________________________________________________________________________
vtkFLAC3DReader::vtkFLAC3DReader()
{
	this->FileName = NULL;
	this->SetNumberOfInputPorts(0);

	this->DisplacementVectorsFile = NULL;
	this->ZonesScalarsFile = NULL;
	this->ZonesTensorsFile = NULL;
}

//_________________________________________________________________________
vtkFLAC3DReader::~vtkFLAC3DReader()
{
	this->SetFileName(NULL);
}

//_________________________________________________________________________
void vtkFLAC3DReader::PrintSelf(ostream& os, vtkIndent indent)
{
	this->Superclass::PrintSelf(os,indent);
	os << indent <<  "FileName: "
		<< (this->FileName ? this->FileName : "(none)") << "\n";
}

//_________________________________________________________________________
int vtkFLAC3DReader::CanReadFile( const char* fname )
{
	return 1;
}

//_________________________________________________________________________
int vtkFLAC3DReader::RequestInformation(vtkInformation* request,
									  vtkInformationVector** inputVector,
									  vtkInformationVector* outputVector)
{
	return 1;
}

//_________________________________________________________________________
int vtkFLAC3DReader::RequestData(vtkInformation* request,
							   vtkInformationVector** inputVector,
							   vtkInformationVector* outputVector)
{
	vtkInformation *outInfo = outputVector->GetInformationObject(0);
	vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));

	// Make sure we have a file to read.
	if(!this->FileName)  {
		vtkErrorMacro("No file name specified.  Cannot open.");
		return 0;
	}
	if(strlen(this->FileName)==0)  {
		vtkErrorMacro("File name is null.  Cannot open.");
		return 0;
	}

	ifstream inFile;
	inFile.open(this->FileName, ios::in);
	if(!inFile)
	{
		vtkErrorMacro("File Error: cannot open file: "<< this->FileName);
		return 0;
	}

	vtkPoints* outPoints = vtkPoints::New();

	vtkIdType ids[8];
	string line;
	vector<string> lineSplit;

	// skip the headers
	while(!inFile.eof())
	{
		getline(inFile, line);
		if(line.size() == 0) continue;
		if(line[0] == '*') continue;
		if(line[0] == 'G')
			break;
	}

	// read the GRIDPOINTS section
	while(line.substr(0,2) == "G ")
	{
		StringUtilities::split(line, lineSplit, " ");

		vtkIdType id;
		double pt[3];
		id = atoi(lineSplit[1].c_str());
		pt[0] = atof(lineSplit[2].c_str());
		pt[1] = atof(lineSplit[3].c_str());
		pt[2] = atof(lineSplit[4].c_str());

		outPoints->InsertNextPoint(pt);

		if(inFile.eof()) break;

		do
		{
			getline(inFile, line);
		}while((line.size() == 0 || line[0] == '*') &! inFile.eof());

		if(line.size() == 0 || line[0] == '*')
			break;
	}

	if(line.size() == 0 || line[0] == '*' || inFile.eof())
	{
		output->SetPoints(outPoints);
		outPoints->Delete();
		return 1;
	}

	vtkUnstructuredGrid* temp= vtkUnstructuredGrid::New();

	// read the ZONES section
	while(line.substr(0,2) == "Z ")
	{
		StringUtilities::split(line, lineSplit, " ");

		if(lineSplit[1] == "B8")
		{
			vtkIdType id = atoi(lineSplit[2].c_str());

			// see FLAC3D documentation for hexahedron topology
			ids[0] = atoi(lineSplit[3].c_str()) -1;
			ids[1] = atoi(lineSplit[4].c_str()) -1;
			ids[2] = atoi(lineSplit[7].c_str()) -1;
			ids[3] = atoi(lineSplit[5].c_str()) -1;
			ids[4] = atoi(lineSplit[6].c_str()) -1;
			ids[5] = atoi(lineSplit[9].c_str()) -1;
			ids[6] = atoi(lineSplit[10].c_str()) -1;
			ids[7] = atoi(lineSplit[8].c_str()) -1;

			temp->InsertNextCell(VTK_HEXAHEDRON,8,ids);
		}

		if(inFile.eof()) break;

		do
		{
			getline(inFile, line);
		}while((line.size() == 0 || line[0] == '*') &! inFile.eof());

		if(line.size() == 0 || line[0] == '*')
			break;
	}

	temp->SetPoints(outPoints);
	output->ShallowCopy(temp);
	outPoints->Delete();

	if(line.size() == 0 || line[0] == '*' || inFile.eof())
		return 1;

	vtkStringArray* groupNameArray = vtkStringArray::New();
	groupNameArray->SetName("Group Name");
	groupNameArray->SetNumberOfValues(temp->GetNumberOfCells());

	vtkIntArray* groupIdArray = vtkIntArray::New();
	groupIdArray->SetName("Group Id");
	groupIdArray->SetNumberOfValues(temp->GetNumberOfCells());

	// in case some zones doesn't belong to a group
	// if it's sure that all zones belong to a group, this
	// loop should be removed to save time
	//for(vtkIdType i=0; i<temp->GetNumberOfCells(); ++i)
	//{
	//	groupNameArray->SetValue(i, "");
	//	groupIdArray->SetValue(i,0);
	//}

	int groupId = 0;
	while(line.substr(0,7) == "ZGROUP ")
	{
		StringUtilities::split(line, lineSplit, " ");
		string groupName = lineSplit[1].substr(1,lineSplit[1].size()-2);

		while(true)
		{
			do
			{
				getline(inFile, line);
			}while((line.size() == 0 || line[0] == '*') &! inFile.eof());

			if(line.size() == 0 || line[0] == '*' || inFile.eof() || line.substr(0,6) == "ZGROUP")
				break;

			StringUtilities::split(line, lineSplit, " ");
			for(vector<string>::iterator it = lineSplit.begin(); it != lineSplit.end(); ++it)
			{
				int zone = atoi(it->c_str()) -1;
				groupNameArray->SetValue(zone, groupName);
				groupIdArray->SetValue(zone, groupId);
			}
		}
		++groupId;
	}

	output->GetCellData()->AddArray(groupNameArray);
	output->GetCellData()->AddArray(groupIdArray);

	inFile.close();

	this->importDisplacements(output);
	this->importScalars(output);
	this->importTensors(output);

	return 1;
}

//_________________________________________________________________________
void vtkFLAC3DReader::importDisplacements(vtkUnstructuredGrid *output)
{
	// Make sure we have a file to read.
	if(!this->DisplacementVectorsFile)  {
		return;
	}
	if(strlen(this->DisplacementVectorsFile)==0)  {
		return;
	}

	ifstream inFile;
	inFile.open(this->DisplacementVectorsFile, ios::in);
	if(!inFile)
	{
		vtkErrorMacro("File Error: cannot open file: "<< this->DisplacementVectorsFile);
		return;
	}

	vtkDoubleArray* dispArray = vtkDoubleArray::New();
	dispArray->SetName("Displacement Vectors");
	dispArray->SetNumberOfComponents(3);

	dispArray->SetNumberOfTuples(output->GetNumberOfPoints());
	for(vtkIdType i=0; i<output->GetNumberOfPoints(); ++i)
	{
		dispArray->SetTuple3(i,0,0,0);
	}

	string line;
	vector<string> lineSplit;

	// skip the headers
	while(!inFile.eof())
	{
		getline(inFile, line);
		if(line.size() > 0)
			break;
	}

	while(!inFile.eof())
	{
		getline(inFile, line);
		if(line.size() < 4)
			continue;

		StringUtilities::split(line, lineSplit, ";");
		vtkIdType id = atoi(lineSplit[0].c_str()) - 1;
		double dispX = atof(lineSplit[1].c_str());
		double dispY = atof(lineSplit[2].c_str());
		double dispZ = atof(lineSplit[3].c_str());

		dispArray->SetTuple3(id, dispX, dispY, dispZ);
	}

	inFile.close();

	output->GetPointData()->AddArray(dispArray);
}

//_________________________________________________________________________
void vtkFLAC3DReader::importScalars(vtkUnstructuredGrid *output)
{
	// Make sure we have a file to read.
	if(!this->ZonesScalarsFile)  {
		return;
	}
	if(strlen(this->ZonesScalarsFile)==0)  {
		return;
	}

	ifstream inFile;
	inFile.open(this->ZonesScalarsFile, ios::in);
	if(!inFile)
	{
		vtkErrorMacro("File Error: cannot open file: "<< this->ZonesScalarsFile);
		return;
	}

	vtkIntArray* stateArray = vtkIntArray::New();
	stateArray->SetName("state");

	vtkDoubleArray* cohesionArray = vtkDoubleArray::New();
	cohesionArray->SetName("cohesion(Pa)");

	vtkDoubleArray* frictionArray = vtkDoubleArray::New();
	frictionArray->SetName("friction()");

	vtkIntArray* excavationYearArray = vtkIntArray::New();
	excavationYearArray->SetName("Excavation Year");

	vtkDoubleArray* damageArray = vtkDoubleArray::New();
	damageArray->SetName("damage");

	stateArray->SetNumberOfValues(output->GetNumberOfCells());
	cohesionArray->SetNumberOfValues(output->GetNumberOfCells());
	frictionArray->SetNumberOfValues(output->GetNumberOfCells());
	excavationYearArray->SetNumberOfValues(output->GetNumberOfCells());
	damageArray->SetNumberOfValues(output->GetNumberOfCells());

	for(vtkIdType i=0; i<output->GetNumberOfCells(); ++i)
	{
		stateArray->SetValue(i,0);
		cohesionArray->SetValue(i,0);
		frictionArray->SetValue(i,0);
		excavationYearArray->SetValue(i,0);
		damageArray->SetValue(i,0);
	}

	string line;
	vector<string> lineSplit;

	// skip the headers
	while(!inFile.eof())
	{
		getline(inFile, line);
		if(line.size() > 0)
			break;
	}

	while(!inFile.eof())
	{
		getline(inFile, line);
		if(line.size() < 4)
			continue;

		StringUtilities::split(line, lineSplit, ";");
		vtkIdType id = atoi(lineSplit[0].c_str()) - 1;
		double state = atof(lineSplit[1].c_str());
		double cohesion = atof(lineSplit[2].c_str());
		double friction = atof(lineSplit[3].c_str());

		int excavationYear = atoi(lineSplit[4].c_str());
		if(lineSplit[4] == "pfin")
			excavationYear = 9999;

		double damage = atof(lineSplit[5].c_str());

		stateArray->SetValue(id,state);
		cohesionArray->SetValue(id,cohesion);
		frictionArray->SetValue(id,friction);
		excavationYearArray->SetValue(id,excavationYear);
		damageArray->SetValue(id,damage);
	}

	inFile.close();

	output->GetCellData()->AddArray(stateArray);
	output->GetCellData()->AddArray(cohesionArray);
	output->GetCellData()->AddArray(frictionArray);
	output->GetCellData()->AddArray(excavationYearArray);
	output->GetCellData()->AddArray(damageArray);
}

//_________________________________________________________________________
void vtkFLAC3DReader::importTensors(vtkUnstructuredGrid *output)
{
	// Make sure we have a file to read.
	if(!this->ZonesTensorsFile)  {
		return;
	}
	if(strlen(this->ZonesTensorsFile)==0)  {
		return;
	}

	ifstream inFile;
	inFile.open(this->ZonesTensorsFile, ios::in);
	if(!inFile)
	{
		vtkErrorMacro("File Error: cannot open file: "<< this->ZonesTensorsFile);
		return;
	}

	vtkDoubleArray* tensorsArray = vtkDoubleArray::New();
	tensorsArray->SetName("tensors(Pa)");
	tensorsArray->SetNumberOfComponents(9);

	tensorsArray->SetNumberOfTuples(output->GetNumberOfCells());
	for(vtkIdType i=0; i<output->GetNumberOfCells(); ++i)
	{
		tensorsArray->SetTuple9(i,0,0,0,0,0,0,0,0,0);
	}

	string line;
	vector<string> lineSplit;

	// skip the headers
	while(!inFile.eof())
	{
		getline(inFile, line);
		if(line.size() > 0)
			break;
	}

	while(!inFile.eof())
	{
		getline(inFile, line);
		if(line.size() < 4)
			continue;

		StringUtilities::split(line, lineSplit, ";");
		vtkIdType id = atoi(lineSplit[0].c_str()) - 1;
		double sxx = atof(lineSplit[1].c_str());
		double syy = atof(lineSplit[2].c_str());
		double szz = atof(lineSplit[3].c_str());
		double sxy = atof(lineSplit[4].c_str());
		double sxz = atof(lineSplit[5].c_str());
		double syz = atof(lineSplit[6].c_str());

		tensorsArray->SetTuple9(id, sxx, sxy, sxz, sxy, syy, syz, sxz, syz, szz);
	}

	inFile.close();

	output->GetCellData()->AddArray(tensorsArray);
}<|endoftext|>