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