Dear Robert,

 

I'm working on the precompiled dependency package for Visual Studio 2013.

 

Please find attached the modified src\osgPlugins\dxf\dxfEntity.cpp and
src\osgPlugins\txf\TXFFont.cpp files.

In each I added the following conditional include to make the min() and
max() functions available:

 

#if (_MSC_VER > 1700)

       #include <algorithm>

#endif

 

I would be happy to see it merged into trunk to make OSG compatible to the
newest VS release.

 

Thanks,

Torben

 

 

 

 

/* -*-c++-*- OpenSceneGraph - Copyright (C) 2006 Mathias Froehlich
 *
 * 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 "TXFFont.h"
#include <iostream>
#include <osg/Notify>

#if (_MSC_VER > 1700)
#include <algorithm>
#endif

#define FNT_BYTE_FORMAT         0
#define FNT_BITMAP_FORMAT       1

struct GlyphData {
    unsigned short ch;
    unsigned char width;
    unsigned char height;
    signed char x_off;
    signed char y_off;
    signed char advance;
    short x;
    short y;
};

static inline void swap(unsigned short& x, bool isSwapped)
{
    if (!isSwapped)
        return;
    x = ((x >> 8) & 0x00FF) | ((x << 8) & 0xFF00);
}

static inline void swap(unsigned& x, bool isSwapped)
{
    if (!isSwapped)
        return;
    x = ((x >> 24) & 0x000000FF) | ((x >> 8) & 0x0000FF00) | ((x << 8) & 
0x00FF0000) | ((x << 24) & 0xFF000000);
}

static inline unsigned char readByte(std::istream& stream)
{
    unsigned char x;
    stream.read(reinterpret_cast<std::istream::char_type*>(&x), 1);
    return x;
}

static inline unsigned short readShort(std::istream& stream, bool isSwapped)
{
    unsigned short x;
    stream.read(reinterpret_cast<std::istream::char_type*>(&x), 2);
    swap(x, isSwapped);
    return x;
}

static inline unsigned readInt(std::istream& stream, bool isSwapped)
{
    unsigned x;
    stream.read(reinterpret_cast<std::istream::char_type*>(&x), 4);
    swap(x, isSwapped);
    return x;
}

TXFFont::TXFFont(const std::string& filename):
    _filename(filename)
{
}

TXFFont::~TXFFont()
{
}

std::string
TXFFont::getFileName() const
{
    return _filename;
}

osgText::Glyph* TXFFont::getGlyph(const osgText::FontResolution&, unsigned int 
charcode)
{
    GlyphMap::iterator i = _chars.find(charcode);
    if (i != _chars.end())
        return i->second.get();

    // ok, not available, we have an additional chance with some translations
    // That is to make the loader compatible with an other prominent one
    if (charcode >= 'A' && charcode <= 'Z')
    {
        i = _chars.find(charcode - 'A' + 'a');
        if (i != _chars.end())
        {
            _chars[charcode] = i->second;
            return i->second.get();
        }
    }
    else if (charcode >= 'a' && charcode <= 'z')
    {
        i = _chars.find(charcode - 'a' + 'A');
        if (i != _chars.end())
        {
            _chars[charcode] = i->second;
            return i->second.get();
        }
    }

    return 0;
}

bool
TXFFont::hasVertical() const
{
    return true;
}

osg::Vec2
TXFFont::getKerning(unsigned int, unsigned int, osgText::KerningType)
{
    return osg::Vec2(0, 0);
}

bool
TXFFont::loadFont(std::istream& stream)
{
    unsigned char magic[4];
    stream.read(reinterpret_cast<std::istream::char_type*>(&magic), 4);

    if (magic[0] != 0xFF || magic[1] != 't' || magic[2] != 'x'  || magic[3] != 
'f' )
    {
        OSG_FATAL << "osgdb_txf: input file \"" << _filename << "\" is not a 
texture font file!" << std::endl;
        return false;
    }

    // read endianess hint
    bool isSwapped = 0x12345678u != readInt(stream, false);

    unsigned format = readInt(stream, isSwapped);
    unsigned texwidth = readInt(stream, isSwapped);
    unsigned texheight = readInt(stream, isSwapped);
    unsigned maxheight = readInt(stream, isSwapped);
    readInt(stream, isSwapped);
    unsigned num_glyphs = readInt(stream, isSwapped);

    unsigned computedmaxheight = 0;

    unsigned w = texwidth;
    unsigned h = texheight;

    osgText::FontResolution fontResolution(maxheight, maxheight);

    std::vector<GlyphData> glyphs;
    for (unsigned i = 0; i < num_glyphs; ++i)
    {
        GlyphData glyphData;
        glyphData.ch = readShort(stream, isSwapped);
        glyphData.width = readByte(stream);
        glyphData.height = readByte(stream);
        glyphData.x_off = readByte(stream);
        glyphData.y_off = readByte(stream);
        glyphData.advance = readByte(stream);
        readByte(stream);
        glyphData.x = readShort(stream, isSwapped);
        glyphData.y = readShort(stream, isSwapped);

        computedmaxheight = std::max(computedmaxheight, 
(unsigned)glyphData.height);

        glyphs.push_back(glyphData);
    }

    unsigned ntexels = w * h;
    osg::ref_ptr<osg::Image> image = new osg::Image;
    image->allocateImage(w, h, 1, GL_ALPHA, GL_UNSIGNED_BYTE);

    if (format == FNT_BYTE_FORMAT)
    {
        stream.read(reinterpret_cast<std::istream::char_type*>(image->data()), 
ntexels);
        if (!stream)
        {
            OSG_FATAL << "osgdb_txf: unxpected end of file in txf file \"" << 
_filename << "\"!" << std::endl;
            return false;
        }
    }
    else if (format == FNT_BITMAP_FORMAT)
    {
        unsigned stride = (w + 7) >> 3;
        unsigned char *texbitmap = new unsigned char[stride*h] ;
        stream.read(reinterpret_cast<std::istream::char_type*>(texbitmap), 
stride*h);
        if (!stream)
        {
            delete [] texbitmap;
            OSG_FATAL << "osgdb_txf: unxpected end of file in txf file \"" << 
_filename << "\"!" << std::endl;
            return false;
        }

        for (unsigned i = 0; i < h; i++)
        {
            for (unsigned j = 0; j < w; j++)
            {
                if (texbitmap[i * stride + (j >> 3)] & (1 << (j & 7)))
                {
                    *image->data(j, i) = 255;
                }
                else
                {
                    *image->data(j, i) = 0;
                }
            }
        }

        delete [] texbitmap;
    }
    else
    {
        OSG_FATAL << "osgdb_txf: unxpected txf file!" << std::endl;
        return false;
    }

    float coord_scale = 1.0f/float(computedmaxheight);

    {
        // insert a trivial blank character
        osgText::Glyph* glyph = new osgText::Glyph(_facade, ' ');

        unsigned width = 1;
        unsigned height = 1;

        glyph->allocateImage(width, height, 1, GL_ALPHA, GL_UNSIGNED_BYTE);
        glyph->setInternalTextureFormat(GL_ALPHA);

        for (unsigned k = 0; k < width; ++k)
        {
            for (unsigned l = 0; l < height; ++l)
            {
                *glyph->data(k, l) = 0;
            }
        }

        glyph->setWidth(0.0f);
        glyph->setHeight(0.0f);
        glyph->setHorizontalAdvance(0.5f);
        glyph->setHorizontalBearing(osg::Vec2(0.0f, 0.0f));
        glyph->setVerticalAdvance(1.0f);
        glyph->setVerticalBearing(osg::Vec2(-0.25f, 0.0f));
        _chars[' '] = glyph;
        addGlyph(fontResolution, ' ', glyph);
    }

    for (unsigned i = 0; i < glyphs.size(); ++i)
    {
        // have a special one for that
        if (glyphs[i].ch == ' ')
            continue;

        // add the characters ...
        osgText::Glyph* glyph = new osgText::Glyph(_facade, glyphs[i].ch);

        unsigned width = glyphs[i].width;
        unsigned height = glyphs[i].height;

        glyph->allocateImage(width, height, 1, GL_ALPHA, GL_UNSIGNED_BYTE);
        glyph->setInternalTextureFormat(GL_ALPHA);

        for (unsigned k = 0; k < width; ++k)
        {
            for (unsigned l = 0; l < height; ++l)
            {
                *glyph->data(k, l) = *image->data(glyphs[i].x + k, glyphs[i].y 
+ l);
            }
        }

        glyph->setWidth(float(width)*coord_scale);
        glyph->setHeight(float(height)*coord_scale);

        // OSG_NOTICE<<"char="<<char(glyphs[i].ch)<<", 
glyphs[i].x_off="<<int(glyphs[i].x_off)<<", 
glyphs[i].y_off="<<int(glyphs[i].y_off)<<", 
glyphs[i].advance="<<int(glyphs[i].advance)<<", 
glyphs[i].width="<<int(glyphs[i].width)<<", 
glyphs[i].height="<<int(glyphs[i].height)<<std::endl;

        glyph->setHorizontalAdvance(float(glyphs[i].advance)*coord_scale);
        
glyph->setHorizontalBearing(osg::Vec2((float(glyphs[i].x_off)*coord_scale),
                                              
(float(glyphs[i].y_off)*coord_scale)) );

        glyph->setVerticalAdvance(1.0);
        
glyph->setVerticalBearing(osg::Vec2((float(glyphs[i].x_off-0.5f*float(glyphs[i].advance))*coord_scale),
                                              
(float(glyphs[i].y_off)*coord_scale)) );
        _chars[glyphs[i].ch] = glyph;

        addGlyph(fontResolution, glyphs[i].ch, glyph);
    }

    return true;
}
/* dxfReader for OpenSceneGraph  Copyright (C) 2005 by GraphArchitecture ( 
grapharchitecture.com )
 * Programmed by Paul de Repentigny <[email protected]>
 *
 * OpenSceneGraph is (C) 2004 Robert Osfield
 *
 * This library is provided as-is, without support of any kind.
 *
 * Read DXF docs or OSG docs for any related questions.
 *
 * You may contact the author if you have suggestions/corrections/enhancements.
 */

#include "dxfEntity.h"
#include "dxfFile.h"
#include "scene.h"
#include "dxfBlock.h"
#include "codeValue.h"

#include <osg/io_utils> // just for debugging

#if (_MSC_VER > 1700)
        #include <algorithm>
#endif

using namespace std;
using namespace osg;

// static
std::map<std::string, ref_ptr<dxfBasicEntity> > dxfEntity::_registry;
RegisterEntityProxy<dxf3DFace> g_dxf3DFace;
RegisterEntityProxy<dxfCircle> g_dxfCircle;
RegisterEntityProxy<dxfArc> g_dxfArc;
RegisterEntityProxy<dxfPoint> g_dxfPoint;
RegisterEntityProxy<dxfLine> g_dxfLine;
RegisterEntityProxy<dxfVertex> g_dxfVertex;
RegisterEntityProxy<dxfPolyline> g_dxfPolyline;
RegisterEntityProxy<dxfLWPolyline> g_dxfLWPolyline;
RegisterEntityProxy<dxfInsert> g_dxfInsert;
RegisterEntityProxy<dxfText> g_dxfText;

void
dxfBasicEntity::assign(dxfFile* , codeValue& cv)
{
    switch (cv._groupCode) {
        case 8:
            _layer = cv._string;
            break;
        case 62:
            _color = cv._short;
            break;
    }
}

void
dxf3DFace::assign(dxfFile* dxf, codeValue& cv)
{
    double d = cv._double;
    switch (cv._groupCode) {
        case 10:
        case 11:
        case 12:
        case 13:
            _vertices[cv._groupCode - 10].x() = d;
            break;
        case 20:
        case 21:
        case 22:
        case 23:
            _vertices[cv._groupCode - 20].y() = d;
            break;
        case 30:
        case 31:
        case 32:
        case 33:
            _vertices[cv._groupCode - 30].z() = d;
            break;

        default:
            dxfBasicEntity::assign(dxf, cv);
            break;
    }
}

void
dxf3DFace::drawScene(scene* sc)
{
    std::vector<Vec3d> vlist;
    short nfaces = 3;

    // Hate to do that, but hey, that's written in the DXF specs:
    if (_vertices[2] != _vertices[3]) nfaces = 4;

    for (short i = nfaces-1; i >= 0; i--)
        vlist.push_back(_vertices[i]);

    if (nfaces == 3) {
        // to do make sure we're % 3
        sc->addTriangles(getLayer(), _color, vlist);
    } else if (nfaces == 4) {
        // to do make sure we're % 4
        sc->addQuads(getLayer(), _color, vlist);
    }
}

void
dxfVertex::assign(dxfFile* dxf, codeValue& cv)
{
    double d = cv._double;
    // 2005.12.13 pdr: learned today that negative indices mean something and 
were possible

    int s = cv._int; // 2005.12.13 pdr: group codes [70,78] now signed int.
    if ( s < 0 ) s = -s;
    switch (cv._groupCode) {
        case 10:
            _vertex.x() = d;
            break;
        case 20:
            _vertex.y() = d;
            break;
        case 30:
            _vertex.z() = d;
            break;
        case 71:
            _indice1 = s;
            break;
        case 72:
            _indice2 = s;
            break;
        case 73:
            _indice3 = s;
            break;
        case 74:
            _indice4 = s;
            break;

        default:
            dxfBasicEntity::assign(dxf, cv);
            break;
    }
}

void
dxfCircle::assign(dxfFile* dxf, codeValue& cv)
{
    double d = cv._double;
    //unsigned short s = cv._short;
    switch (cv._groupCode) {
        case 10:
            _center.x() = d;
            break;
        case 20:
            _center.y() = d;
            break;
        case 30:
            _center.z() = d;
            break;
        case 40:
            _radius = d;
            break;
        case 210:
            _ocs.x() = d;
            break;
        case 220:
            _ocs.y() = d;
            break;
        case 230:
            _ocs.z() = d;
            break;
        default:
            dxfBasicEntity::assign(dxf, cv);
            break;
    }
}

void
dxfCircle::drawScene(scene* sc)
{
    Matrixd m;
    getOCSMatrix(_ocs, m);
    sc->ocs(m);
    std::vector<Vec3d> vlist;

    double theta=5.0; // we generate polyline from "spokes" at theta degrees at 
arc's center

    if (_useAccuracy) {
        // we generate points on a polyline where each point lies on the arc, 
thus the maximum error occurs at the midpoint of each line segment where it 
lies furthest inside the arc
        // If we divide the segment in half and connect the bisection point to 
the arc's center, we have two rightangled triangles with
        // one side=r-maxError, hypotenuse=r, and internal angle at center is 
half the angle we will step with:
        double maxError=min(_maxError,_radius); // Avoid offending acos() in 
the edge case where allowable deviation is greater than radius.
        double newtheta=acos( (_radius-maxError) / _radius);
        newtheta=osg::RadiansToDegrees(newtheta)*2.0;

        // Option to only use the new accuracy code when it would improve on 
the accuracy of the old method
        if (_improveAccuracyOnly) {
            theta=min(newtheta,theta);
        } else {
            theta=newtheta;
        }
    }
    theta=osg::DegreesToRadians(theta);

    // We create an anglestep<=theta so that the line's points are evenly 
distributed around the circle
    unsigned int numsteps=static_cast<unsigned int>(floor(osg::PI*2/theta));
    if (numsteps<3) numsteps=3; // Sanity check: minimal representation of a 
circle is a tri
    double anglestep=osg::PI*2/numsteps;

    double angle1 = 0.0;
    Vec3d a = _center;
    Vec3d b;
    for(unsigned int r=0;r<=numsteps;r++) {
        b = a + Vec3d(_radius * (double) sin(angle1), _radius * (double) 
cos(angle1), 0);
        angle1 += anglestep;
        vlist.push_back(b);
    }

    sc->addLineStrip(getLayer(), _color, vlist); // Should really add LineLoop 
implementation and save a vertex
    sc->ocs_clear();
}


void
dxfArc::assign(dxfFile* dxf, codeValue& cv)
{
    double d = cv._double;
    //unsigned short s = cv._short;
    switch (cv._groupCode) {
        case 10:
            _center.x() = d;
            break;
        case 20:
            _center.y() = d;
            break;
        case 30:
            _center.z() = d;
            break;
        case 40:
            _radius = d;
            break;
        case 50:
            _startAngle = d;
            break;
        case 51:
            _endAngle = d;
            break;
        case 210:
            _ocs.x() = d;
            break;
        case 220:
            _ocs.y() = d;
            break;
        case 230:
            _ocs.z() = d;
            break;
        default:
            dxfBasicEntity::assign(dxf, cv);
            break;
    }
}

void
dxfArc::drawScene(scene* sc)
{
    Matrixd m;
    getOCSMatrix(_ocs, m);
    sc->ocs(m);
    std::vector<Vec3d> vlist;
    double end;
    double start;
    if (_startAngle > _endAngle) {
        start = _startAngle;
        end = _endAngle + 360;
    } else {
        start = _startAngle;
        end = _endAngle;
    }

    double theta=5.0; // we generate polyline from "spokes" at theta degrees at 
arc's center

    if (_useAccuracy) {
        // we generate points on a polyline where each point lies on the arc, 
thus the maximum error occurs at the midpoint of each line segment where it 
lies furthest inside the arc
        // If we divide the segment in half and connect the bisection point to 
the arc's center, we have two rightangled triangles with
        // one side=r-maxError, hypotenuse=r, and internal angle at center is 
half the angle we will step with:
        double maxError=min(_maxError,_radius); // Avoid offending acos() in 
the edge case where allowable deviation is greater than radius.
        double newtheta=acos( (_radius-maxError) / _radius);
        newtheta=osg::RadiansToDegrees(newtheta)*2.0;
        //cout<<"r="<<_radius<<" _me="<<_maxError<<" 
(_radius-_maxError)="<<(_radius-_maxError)<<" newtheta="<<newtheta<<endl;
        // Option to only use the new accuracy code when it would improve on 
the accuracy of the old method
        if (_improveAccuracyOnly) {
            theta=min(newtheta,theta);
        } else {
            theta=newtheta;
        }
    }

    double angle_step = DegreesToRadians(end - start);
    int numsteps = (int)((end - start)/theta);
    //cout<<"arc theta="<<osg::RadiansToDegrees(theta)<<" end="<<end<<" 
start="<<start<<" numsteps="<<numsteps<<" e-s/theta="<<((end-start)/theta)<<" 
end-start="<<(end-start)<<endl;
    if (numsteps * theta < (end - start)) numsteps++;
    numsteps=max(numsteps,2); // Whatever else, minimum representation of an 
arc is a straightline
    angle_step /=  (double) numsteps;
    end = DegreesToRadians((-_startAngle)+90.0);
    start = DegreesToRadians((-_endAngle)+90.0);
    double angle1 = start;

    Vec3d a = _center;
    Vec3d b;

    for (int r = 0; r <= numsteps; r++)
    {
        b = a + Vec3d(_radius * (double) sin(angle1), _radius * (double) 
cos(angle1), 0);
        angle1 += angle_step;
        vlist.push_back(b);
    }


    sc->addLineStrip(getLayer(), _color, vlist);
    sc->ocs_clear();
}

void
dxfLine::assign(dxfFile* dxf, codeValue& cv)
{
    double d = cv._double;
    //unsigned short s = cv._short;
    switch (cv._groupCode) {
        case 10:
            _a.x() = d;
            break;
        case 20:
            _a.y() = d;
            break;
        case 30:
            _a.z() = d;
            break;
        case 11:
            _b.x() = d;
            break;
        case 21:
            _b.y() = d;
            break;
        case 31:
            _b.z() = d;
            break;
        case 210:
            _ocs.x() = d;
            break;
        case 220:
            _ocs.y() = d;
            break;
        case 230:
            _ocs.z() = d;
            break;
        default:
            dxfBasicEntity::assign(dxf, cv);
            break;
    }
}

void
dxfLine::drawScene(scene* sc)
{
    Matrixd m;
    getOCSMatrix(_ocs, m);
    // don't know why this doesn't work
//    sc->ocs(m);
    sc->addLine(getLayer(), _color, _b, _a);
//    static long lcount = 0;
//    std::cout << ++lcount << " ";
//    sc->ocs_clear();
}
void
dxfPoint::assign(dxfFile* dxf, codeValue& cv)
{
    double d = cv._double;
    //unsigned short s = cv._short;
    switch (cv._groupCode) {
        case 10:
            _a.x() = d;
            break;
        case 20:
            _a.y() = d;
            break;
        case 30:
            _a.z() = d;
            break;
        default:
            dxfBasicEntity::assign(dxf, cv);
            break;
    }
}

void
dxfPoint::drawScene(scene* sc)
{
    Matrixd m;
    getOCSMatrix(_ocs, m);
    sc->addPoint(getLayer(), _color,_a);
}

void
dxfPolyline::assign(dxfFile* dxf, codeValue& cv)
{
    string s = cv._string;
    if (cv._groupCode == 0) {
        if (s == "VERTEX") {
            _currentVertex = new dxfVertex;
            _vertices.push_back(_currentVertex);
        }
    } else if (_currentVertex) {
        _currentVertex->assign(dxf, cv);

        if ((_flag & 64 /*i.e. polymesh*/) &&
            (cv._groupCode == 70 /*i.e. vertex flag*/) &&
            (cv._int & 128 /*i.e. vertex is actually a face*/))
            _indices.push_back(_currentVertex); // Add the index only if 
_currentvertex is actually an index
    } else {
        double d = cv._double;
        switch (cv._groupCode) {
            case 10:
                // dummy
                break;
            case 20:
                // dummy
                break;
            case 30:
                _elevation = d; // what is elevation?
                break;
            case 70:
                _flag = cv._int; // 2005.12.13 pdr: group codes [70,78] now 
signed int.
                break;
            case 71:
                // Meaningful only when _surfacetype == 6, don' trust it for 
polymeshes.
                // From the docs :
                // "The 71 group specifies the number of vertices in the mesh, 
and the 72 group
                // specifies the number of faces. Although these counts are 
correct for all meshes
                // created with the PFACE command, applications are not 
required to place correct
                // values in these fields.)"
                // Amusing isn't it ?
                _mcount = cv._int; // 2005.12.13 pdr: group codes [70,78] now 
signed int.
                break;
            case 72:
                // Meaningful only when _surfacetype == 6, don' trust it for 
polymeshes.
                // From the docs :
                // "The 71 group specifies the number of vertices in the mesh, 
and the 72 group
                // specifies the number of faces. Although these counts are 
correct for all meshes
                // created with the PFACE command, applications are not 
required to place correct
                // values in these fields.)"
                // Amusing isn't it ?
                _ncount = cv._int; // 2005.12.13 pdr: group codes [70,78] now 
signed int.
                break;
            case 73:
                _mdensity = cv._int; // 2005.12.13 pdr: group codes [70,78] now 
signed int.
                break;
            case 74:
                _ndensity = cv._int; // 2005.12.13 pdr: group codes [70,78] now 
signed int.
                break;
            case 75:
                _surfacetype = cv._int; // 2005.12.13 pdr: group codes [70,78] 
now signed int.
                break;
            case 210:
                _ocs.x() = d;
                break;
            case 220:
                _ocs.y() = d;
                break;
            case 230:
                _ocs.z() = d;
                break;
            default:
                dxfBasicEntity::assign(dxf, cv);
                break;
        }
    }
}


void
dxfPolyline::drawScene(scene* sc)
{
    Matrixd m;
    getOCSMatrix(_ocs, m);
    sc->ocs(m);
    std::vector<Vec3d> vlist;
    std::vector<Vec3d> qlist;
    Vec3d a, b, c, d;
    bool invert_order = false;
    if (_flag & 16) {
        std::vector<Vec3d> nlist;
        Vec3d nr;
        bool nset = false;
        //dxfVertex* v = NULL;
        unsigned int ncount;
        unsigned int mcount;
        if (_surfacetype == 6) {
            // I dont have examples of type 5 and 8, but they may be the same 
as 6
            mcount = _mdensity;
            ncount = _ndensity;
        } else {
            mcount = _mcount;
            ncount = _ncount;
        }
        for (unsigned int n = 0; n < ncount-1; n++) {
            for (unsigned int m = 1; m < mcount; m++) {
                // 0
                a = _vertices[(m-1)*ncount+n].get()->getVertex();
                // 1
                b = _vertices[m*ncount+n].get()->getVertex();
                // 3
                c = _vertices[(m)*ncount+n+1].get()->getVertex();
                // 2
                d = _vertices[(m-1)*ncount+n+1].get()->getVertex();
                if (a == b ) {
                    vlist.push_back(a);
                    vlist.push_back(c);
                    vlist.push_back(d);
                    b = c;
                    c = d;
                } else if (c == d) {
                    vlist.push_back(a);
                    vlist.push_back(b);
                    vlist.push_back(c);
                } else {
                    qlist.push_back(a);
                    qlist.push_back(b);
                    qlist.push_back(c);
                    qlist.push_back(d);
                }
                if (!nset) {
                    nset = true;
                    nr = (b - a) ^ (c - a);
                    nr.normalize();
                }
                nlist.push_back(a);
            }
        }
        if (_flag & 1) {
            for (unsigned int n = 0; n < ncount-1; n++) {
                // 0
                a = _vertices[(mcount-1)*ncount+n].get()->getVertex();
                // 1
                b = _vertices[0*ncount+n].get()->getVertex();
                // 3
                c = _vertices[(0)*ncount+n+1].get()->getVertex();
                // 2
                d = _vertices[(mcount-1)*ncount+n+1].get()->getVertex();
                if (a == b ) {
                    vlist.push_back(a);
                    vlist.push_back(c);
                    vlist.push_back(d);
                    b = c;
                    c = d;
                } else if (c == d) {
                    vlist.push_back(a);
                    vlist.push_back(b);
                    vlist.push_back(c);
                } else {
                    qlist.push_back(a);
                    qlist.push_back(b);
                    qlist.push_back(c);
                    qlist.push_back(d);
                }
                nlist.push_back(a);
            }
        }
        if (_flag & 32) {
            for (unsigned int m = 1; m < mcount; m++) {
                // 0
                a = _vertices[(m-1)*ncount+(ncount-1)].get()->getVertex();
                // 1
                b = _vertices[m*ncount+(ncount-1)].get()->getVertex();
                // 3
                c = _vertices[(m)*ncount].get()->getVertex();
                // 2
                d = _vertices[(m-1)*ncount].get()->getVertex();
                if (a == b ) {
                    vlist.push_back(a);
                    vlist.push_back(c);
                    vlist.push_back(d);
                    b = c;
                    c = d;
                } else if (c == d) {
                    vlist.push_back(a);
                    vlist.push_back(b);
                    vlist.push_back(c);
                } else {
                    qlist.push_back(a);
                    qlist.push_back(b);
                    qlist.push_back(c);
                    qlist.push_back(d);
                }
                nlist.push_back(a);
            }
        }

/*
        // a naive attempt to determine vertex ordering
        VList::iterator itr = nlist.begin();
        Vec3d lastn = (*itr++);
        double bad_c = 0;
        double good_c = 0;
        long bad=0,good=0;
        for (; itr != nlist.end(); ++itr) {
            if ((*itr)== lastn) continue;
            Vec3d diff = ((*itr)-lastn);
            diff.normalize();
            float dot = diff * nr;
            if (dot > 0.0) {
                bad_c += dot;
                ++bad;
            } else {
                ++good;
                good_c += dot;
            }
        }
        if (bad > good) {
            invert_order = true;
        }
*/

        if (qlist.size())
            sc->addQuads(getLayer(), _color, qlist, invert_order);
        if (vlist.size())
            sc->addTriangles(getLayer(), _color, vlist, invert_order);

    } else if (_flag & 64) {
        unsigned short _facetype = 3;

        for (unsigned int i = 0; i < _indices.size(); i++) {
            dxfVertex* vindice = _indices[i].get();
            if (!vindice) continue;
            if (vindice->getIndice4()) {
                _facetype = 4;
                d = _vertices[vindice->getIndice4()-1].get()->getVertex();
            } else {
                _facetype = 3;
            }
            if (vindice->getIndice3()) {
                c = _vertices[vindice->getIndice3()-1].get()->getVertex();
            } else {
                c = vindice->getVertex(); // Vertex not indexed. Use as is
            }
            if (vindice->getIndice2()) {
                b = _vertices[vindice->getIndice2()-1].get()->getVertex();
            } else {
                b = vindice->getVertex(); // Vertex not indexed. Use as is
            }
            if (vindice->getIndice1()) {
                a = _vertices[vindice->getIndice1()-1].get()->getVertex();
            } else {
                a = vindice->getVertex(); // Vertex not indexed. Use as is
            }
            if (_facetype == 4) {
                qlist.push_back(d);
                qlist.push_back(c);
                qlist.push_back(b);
                qlist.push_back(a);
            } else {
                // 2005.12.13 pdr: vlist! not qlist!
                vlist.push_back(c);
                vlist.push_back(b);
                vlist.push_back(a);
            }
        }
        if (vlist.size())
            sc->addTriangles(getLayer(), _color, vlist);
        if (qlist.size())
            sc->addQuads(getLayer(), _color, qlist);
        // is there a flag 1 or 32 for 64?
    } else {
        // simple polyline?
        for (int i = _vertices.size()-1; i >= 0; i--)
            vlist.push_back(_vertices[i]->getVertex());
        if (_flag & 1) {
//            std::cout << "line loop " << _vertices.size() << std::endl;
            sc->addLineLoop(getLayer(), _color, vlist);
        } else {
//            std::cout << "line strip " << _vertices.size() << std::endl;
            sc->addLineStrip(getLayer(), _color, vlist);
        }

    }
    sc->ocs_clear();
}

void
dxfLWPolyline::assign(dxfFile* dxf, codeValue& cv)
{
    string s = cv._string;

    double d = cv._double;
    switch (cv._groupCode) {
        case 10:
            _lastv.x() = d;
            // x
            break;
        case 20:
            _lastv.y() = d;
            _lastv.z() = _elevation;
            _vertices.push_back ( _lastv );
            // y -> on shoot
            break;
        case 38:
            _elevation = d; // what is elevation?
            break;
        case 70:
            _flag = cv._int; // 2005.12.13 pdr: group codes [70,78] now signed 
int.
            break;
        case 90:
            _vcount = cv._short;
            break;
        case 210:
            _ocs.x() = d;
            break;
        case 220:
            _ocs.y() = d;
            break;
        case 230:
            _ocs.z() = d;
            break;
        default:
            dxfBasicEntity::assign(dxf, cv);
            break;
    }
}


void
dxfLWPolyline::drawScene(scene* sc)
{
//    if (getLayer() != "UDF2" && getLayer() != "ENGINES") return;
//    if (!(_flag & 16)) return;
    Matrixd m;
    getOCSMatrix(_ocs, m);
    sc->ocs(m);
    if (_flag & 1) {
//        std::cout << "lwpolyline line loop " << _vertices.size() << std::endl;
        sc->addLineLoop(getLayer(), _color, _vertices);
    } else {
//        std::cout << "lwpolyline line strip " << _vertices.size() << 
std::endl;
        sc->addLineStrip(getLayer(), _color, _vertices);
    }
    sc->ocs_clear();
}

void
dxfInsert::assign(dxfFile* dxf, codeValue& cv)
{
    string s = cv._string;
    if (_done || (cv._groupCode == 0 && s != "INSERT")) {
        _done = true;
        return;
    }
    if (cv._groupCode == 2 && !_block) {
        _blockName = s;
        _block = dxf->findBlock(s);
    } else {
        double d = cv._double;
        switch (cv._groupCode) {
            case 10:
                _point.x() = d;
                break;
            case 20:
                _point.y() = d;
                break;
            case 30:
                _point.z() = d;
                break;
            case 41:
                _scale.x() = d;
                break;
            case 42:
                _scale.y() = d;
                break;
            case 43:
                _scale.z() = d;
                break;
            case 50:
                _rotation = d;
                break;
            case 210:
                _ocs.x() = d;
                break;
            case 220:
                _ocs.y() = d;
                break;
            case 230:
                _ocs.z() = d;
                break;
            default:
                dxfBasicEntity::assign(dxf, cv);
                break;
        }
    }
}

/// hum. read the doc, then come back here. then try to figure.
void
dxfInsert::drawScene(scene* sc)
{
    // INSERTs can be nested. So pull the current matrix
    // and push it back after we fill our context
    // This is a snapshot in time. I will rewrite all this to be cleaner,
    // but for now, it seems working fine
    // (with the files I have, the results are equal to Voloview,
    // and better than Deep Exploration and Lightwave).

    // sanity check (useful when no block remains after all unsupported 
entities have been filtered out)
    if (!_block)
        return;

    Matrixd back = sc->backMatrix();
    Matrixd m;
    m.makeIdentity();
    sc->pushMatrix(m, true);
    Vec3d trans = _block->getPosition();
    sc->blockOffset(-trans);
    if (_rotation) {
        sc->pushMatrix(Matrixd::rotate(osg::DegreesToRadians(_rotation), 
0,0,1));
    }
    sc->pushMatrix(Matrixd::scale(_scale.x(), _scale.y(), _scale.z()));
    sc->pushMatrix(Matrixd::translate(_point.x(), _point.y(), _point.z()));
    getOCSMatrix(_ocs, m);
    sc->pushMatrix(m);
    sc->pushMatrix(back);

    EntityList& l = _block->getEntityList();
    for (EntityList::iterator itr = l.begin(); itr != l.end(); ++itr) {
        dxfBasicEntity* e = (*itr)->getEntity();
        if (e) {
            e->drawScene(sc);
        }
    }

    sc->popMatrix(); // ocs
    sc->popMatrix(); // translate
    sc->popMatrix(); // scale
    if (_rotation) {
        sc->popMatrix(); // rotate
    }
    sc->popMatrix(); // identity
    sc->popMatrix(); // back
    sc->blockOffset(Vec3d(0,0,0));

}

void
dxfText::assign(dxfFile* dxf, codeValue& cv)
{
    switch (cv._groupCode) {
        case 1:
            _string = cv._string;
            break;
        case 10:
            _point1.x() = cv._double;
            break;
        case 20:
            _point1.y() = cv._double;
            break;
        case 30:
            _point1.z() = cv._double;
            break;
        case 11:
            _point2.x() = cv._double;
            break;
        case 21:
            _point2.y() = cv._double;
            break;
        case 31:
            _point2.z() = cv._double;
            break;
        case 40:
            _height = cv._double;
            break;
        case 41:
            _xscale = cv._double;
            break;
        case 50:
            _rotation = cv._double;
            break;
        case 71:
            _flags = cv._int;
            break;
        case 72:
            _hjustify = cv._int;
            break;
        case 73:
            _vjustify = cv._int;
            break;
        case 210:
            _ocs.x() = cv._double;
            break;
        case 220:
            _ocs.y() = cv._double;
            break;
        case 230:
            _ocs.z() = cv._double;
            break;
        default:
            dxfBasicEntity::assign(dxf, cv);
            break;
    }
}


void
dxfText::drawScene(scene* sc)
{
    osgText::Text::AlignmentType align;

    Matrixd m;
    getOCSMatrix(_ocs, m);
    sc->ocs(m);

    ref_ptr<osgText::Text> _text = new osgText::Text;
    _text->setText(_string);

    _text->setCharacterSize( _height, 1.0/_xscale );
    _text->setFont("arial.ttf");

    Quat qr( DegreesToRadians(_rotation), Z_AXIS );

    if ( _flags & 2 ) qr = Quat( PI, Y_AXIS ) * qr;
    if ( _flags & 4 ) qr = Quat( PI, X_AXIS ) * qr;

    _text->setAxisAlignment(osgText::Text::USER_DEFINED_ROTATION);
    _text->setRotation(qr);

    if ( _hjustify != 0 || _vjustify !=0 ) _point1 = _point2;

    switch (_vjustify) {
    case 3:
        switch (_hjustify) {
        case 2:
            align = osgText::Text::RIGHT_TOP;
            break;
        case 1:
            align = osgText::Text::CENTER_TOP;
            break;
        default:
            align = osgText::Text::LEFT_TOP;
        }
        break;
    case 2:
        switch (_hjustify) {
        case 2:
            align = osgText::Text::RIGHT_CENTER;
            break;
        case 1:
            align = osgText::Text::CENTER_CENTER;
            break;
        default:
            align = osgText::Text::LEFT_CENTER;
        }
        break;
    case 1:
        switch (_hjustify) {
        case 2:
            align = osgText::Text::RIGHT_BOTTOM;
            break;
        case 1:
            align = osgText::Text::CENTER_BOTTOM;
            break;
        default:
            align = osgText::Text::LEFT_BOTTOM;
        }
        break;
    default:
        switch (_hjustify) {
        case 2:
            align = osgText::Text::RIGHT_BOTTOM_BASE_LINE;
            break;
        case 1:
            align = osgText::Text::CENTER_BOTTOM_BASE_LINE;
            break;
        default:
            align = osgText::Text::LEFT_BOTTOM_BASE_LINE;
        }
        break;
    }

    _text->setAlignment(align);

    sc->addText(getLayer(), _color, _point1, _text.get());
    sc->ocs_clear();
}


// static
void
dxfEntity::registerEntity(dxfBasicEntity* entity)
{
    _registry[entity->name()] = entity;
}

// static
void
dxfEntity::unregisterEntity(dxfBasicEntity* entity)
{
    map<string, ref_ptr<dxfBasicEntity > >::iterator itr = 
_registry.find(entity->name());
    if (itr != _registry.end()) {
        _registry.erase(itr);
    }
}

void dxfEntity::drawScene(scene* sc)
{
    for (std::vector<ref_ptr<dxfBasicEntity > >::iterator itr = 
_entityList.begin();
        itr != _entityList.end(); ++itr) {
            (*itr)->drawScene(sc);
    }
}

void
dxfEntity::assign(dxfFile* dxf, codeValue& cv)
{
    string s = cv._string;
    if (cv._groupCode == 66 && !(_entity && string("TABLE") == 
_entity->name())) {
        // The funny thing here. Group code 66 has been called 'obsoleted'
        // for a POLYLINE. But not for an INSERT. Moreover, a TABLE
        // can have a 66 for... an obscure bottom cell color value.
        // I decided to rely on the presence of the 66 code for
        // the POLYLINE. If you find a better alternative,
        // contact me, or correct this code
        // and post the correction to osg mailing list
        _seqend = true;
    } else if (_seqend && cv._groupCode == 0 && s == "SEQEND") {
        _seqend = false;
//        cout << "... off" << endl;
    } else if (_entity) {
        _entity->assign(dxf, cv);
    }
}
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to