OSGSimpleGeometry.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *             Copyright (C) 2000-2002 by the OpenSG Forum                   *
00006  *                                                                           *
00007  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00008  *                                                                           *
00009 \*---------------------------------------------------------------------------*/
00010 /*---------------------------------------------------------------------------*\
00011  *                                License                                    *
00012  *                                                                           *
00013  * This library is free software; you can redistribute it and/or modify it   *
00014  * under the terms of the GNU Library General Public License as published    *
00015  * by the Free Software Foundation, version 2.                               *
00016  *                                                                           *
00017  * This library is distributed in the hope that it will be useful, but       *
00018  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00020  * Library General Public License for more details.                          *
00021  *                                                                           *
00022  * You should have received a copy of the GNU Library General Public         *
00023  * License along with this library; if not, write to the Free Software       *
00024  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00025  *                                                                           *
00026 \*---------------------------------------------------------------------------*/
00027 /*---------------------------------------------------------------------------*\
00028  *                                Changes                                    *
00029  *                                                                           *
00030  *                                                                           *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035 \*---------------------------------------------------------------------------*/
00036
00037 #ifdef WIN32
00038 #pragma warning( disable : 4305 )
00039 #endif
00040 
00041 //---------------------------------------------------------------------------
00042 //  Includes
00043 //---------------------------------------------------------------------------
00044
00045 #include <cstdlib>
00046 #include <cstdio>
00047
00048 #include "OSGConfig.h"
00049 #include "OSGLog.h"
00050 #include "OSGQuaternion.h"
00051 #include "OSGMaterial.h"
00052 #include "OSGSimpleMaterial.h"
00053 #include "OSGLineChunk.h"
00054 #include "OSGGeoProperties.h"
00055 #include "OSGSimpleGeometry.h"  // for DefaultMaterials
00056 #include "OSGTypedGeoIntegralProperty.h"
00057 #include "OSGTypedGeoVectorProperty.h"
00058
00059 //#include "OSGTriangleIterator.h"
00060
00061 OSG_BEGIN_NAMESPACE
00062
00063 /***************************************************************************\
00064  *                            Description                                  *
00065 \***************************************************************************/
00066
00067 #if defined(OSG_WIN32_ICL) && !defined(OSG_CHECK_FIELDSETARG)
00068 #pragma warning (disable : 383)
00069 #endif
00070 
00071 // The Simple Geometry creation functions
00072
00085 NodeTransitPtr makePlane(Real32 xsize, Real32 ysize, UInt16 hor, UInt16 vert)
00086 {
00087     GeometryTransitPtr pGeo = makePlaneGeo(xsize, ysize, hor, vert);
00088
00089     if(pGeo == NULL)
00090     {
00091         return NodeTransitPtr(NULL);
00092     }
00093
00094     NodeTransitPtr node = Node::create();
00095
00096     node->setCore(pGeo);
00097
00098     return node;
00099 }
00100
00113 GeometryTransitPtr makePlaneGeo(Real32 xsize, Real32 ysize,
00114                                 UInt16 hor,   UInt16 vert)
00115 {
00116     if(! hor || ! vert)
00117     {
00118         SWARNING << "makePlane: illegal parameters hor=" << hor << ", vert="
00119                  << vert << std::endl;
00120         return GeometryTransitPtr(NULL);
00121     }
00122
00123     GeoPnt3fPropertyUnrecPtr  pnts  = GeoPnt3fProperty ::create();
00124     GeoVec3fPropertyUnrecPtr  norms = GeoVec3fProperty ::create();
00125     GeoVec2fPropertyUnrecPtr  tex   = GeoVec2fProperty ::create();
00126     GeoUInt32PropertyUnrecPtr index = GeoUInt32Property::create();
00127     GeoUInt32PropertyUnrecPtr lens  = GeoUInt32Property::create();
00128     GeoUInt8PropertyUnrecPtr  types = GeoUInt8Property ::create();
00129
00130     UInt16 x,y;
00131     Real32 xstep,ystep;
00132     xstep=xsize / hor;
00133     ystep=ysize / vert;
00134
00135     // calc the vertices
00136
00137     GeoPnt3fProperty::StoredFieldType *p  = pnts ->editFieldPtr();
00138     GeoVec3fProperty::StoredFieldType *n  = norms->editFieldPtr();
00139     GeoVec2fProperty::StoredFieldType *tx = tex ->editFieldPtr();
00140
00141     for(y = 0; y <= vert; y++)
00142     {
00143         for(x = 0; x <= hor; x++)
00144         {
00145             p->push_back(Pnt3f(x * xstep - xsize / 2, y * ystep - ysize / 2, 0));
00146             n->push_back(Vec3f(0, 0, 1));
00147             tx->push_back(Vec2f(x / Real32(hor), y / Real32(vert)));
00148         }
00149     }
00150
00151     // create the faces
00152
00153     GeoUInt32Property::StoredFieldType *i = index->editFieldPtr();
00154     GeoUInt32Property::StoredFieldType *l = lens ->editFieldPtr();
00155     GeoUInt8Property::StoredFieldType  *t = types->editFieldPtr();
00156
00157     for(y = 0; y < vert; y++)
00158     {
00159         t->push_back(GL_TRIANGLE_STRIP);
00160         l->push_back(2 * (hor + 1));
00161
00162         for(x = 0; x <= hor; x++)
00163         {
00164             i->push_back((y + 1) * (hor + 1) + x);
00165             i->push_back( y      * (hor + 1) + x);
00166         }
00167     }
00168
00169     // create the geometry
00170
00171     GeometryTransitPtr geo = Geometry::create();
00172
00173     geo->setMaterial(getDefaultMaterial());
00174     geo->setPositions(pnts);
00175     geo->setNormals(norms);
00176     geo->setTexCoords(tex);
00177     geo->setIndices(index);
00178     geo->setTypes(types);
00179     geo->setLengths(lens);
00180
00181     return geo;
00182 }
00183
00199 NodeTransitPtr makeCone(Real32 height,
00200                         Real32 botradius,
00201                         UInt16 sides,
00202                         bool   doSide,
00203                         bool   doBottom)
00204 {
00205     return makeConicalFrustum(height,
00206                               0,
00207                               botradius,
00208                               sides,
00209                               doSide,
00210                               false,
00211                               doBottom);
00212 }
00213
00227 GeometryTransitPtr makeConeGeo(Real32 height,
00228                                Real32 botradius,
00229                                UInt16 sides,
00230                                bool   doSide,
00231                                bool   doBottom)
00232 {
00233     return makeConicalFrustumGeo(height,
00234                                  0,
00235                                  botradius,
00236                                  sides,
00237                                  doSide,
00238                                  false,
00239                                  doBottom);
00240 }
00241
00259 NodeTransitPtr makeCylinder(Real32 height,
00260                             Real32 radius,
00261                             UInt16 sides,
00262                             bool   doSide,
00263                             bool   doTop,
00264                             bool   doBottom)
00265 {
00266     return makeConicalFrustum(height,
00267                               radius,
00268                               radius,
00269                               sides,
00270                               doSide,
00271                               doTop,
00272                               doBottom);
00273 }
00274
00289 GeometryTransitPtr makeCylinderGeo(Real32 height,
00290                                    Real32 radius,
00291                                    UInt16 sides,
00292                                    bool   doSide,
00293                                    bool   doTop,
00294                                    bool   doBottom)
00295 {
00296     return makeConicalFrustumGeo(height,
00297                                  radius,
00298                                  radius,
00299                                  sides,
00300                                  doSide,
00301                                  doTop,
00302                                  doBottom);
00303 }
00304
00305
00325 NodeTransitPtr makeConicalFrustum(Real32 height,
00326                                   Real32 topradius,
00327                                   Real32 botradius,
00328                                   UInt16 sides,
00329                                   bool   doSide,
00330                                   bool   doTop,
00331                                   bool   doBottom)
00332 {
00333     GeometryTransitPtr pGeo = makeConicalFrustumGeo(height,
00334                                                     topradius,
00335                                                     botradius,
00336                                                     sides,
00337                                                     doSide,
00338                                                     doTop,
00339                                                     doBottom);
00340
00341     if(pGeo == NULL)
00342     {
00343         return NodeTransitPtr(NULL);
00344     }
00345
00346     NodeTransitPtr node = Node::create();
00347
00348     node->setCore(pGeo);
00349
00350     return node;
00351 }
00352
00366 GeometryTransitPtr makeConicalFrustumGeo(Real32 height,
00367                                          Real32 topradius,
00368                                          Real32 botradius,
00369                                          UInt16 sides,
00370                                          bool   doSide,
00371                                          bool   doTop,
00372                                          bool   doBottom)
00373 {
00374     if(height <= 0 || topradius < 0 || botradius < 0 || sides < 3)
00375     {
00376         SWARNING << "makeConicalFrustum: illegal parameters height=" << height
00377                  << ", topradius=" << topradius
00378                  << ", botradius=" << botradius
00379                  << ", sides=" << sides
00380                  << std::endl;
00381         return GeometryTransitPtr(NULL);
00382     }
00383
00384     GeoPnt3fPropertyUnrecPtr  pnts  = GeoPnt3fProperty ::create();
00385     GeoVec3fPropertyUnrecPtr  norms = GeoVec3fProperty ::create();
00386     GeoVec2fPropertyUnrecPtr  tex   = GeoVec2fProperty ::create();
00387     GeoUInt32PropertyUnrecPtr index = GeoUInt32Property::create();
00388     GeoUInt32PropertyUnrecPtr lens  = GeoUInt32Property::create();
00389     GeoUInt8PropertyUnrecPtr  types = GeoUInt8Property ::create();
00390
00391     Int16  j;
00392     Real32 delta = 2.f * Pi / sides;
00393     Real32 beta, x, z;
00394     Real32 incl = (botradius - topradius) / height;
00395     Real32 nlen = 1.f / osgSqrt(1 + incl * incl);
00396
00397     // vertices
00398
00399     GeoPnt3fProperty::StoredFieldType  *p  = pnts ->editFieldPtr();
00400     GeoVec3fProperty::StoredFieldType  *n  = norms->editFieldPtr();
00401     GeoVec2fProperty::StoredFieldType  *tx = tex  ->editFieldPtr();
00402
00403     // faces
00404
00405     GeoUInt32Property::StoredFieldType *i  = index->editFieldPtr();
00406     GeoUInt32Property::StoredFieldType *l  = lens ->editFieldPtr();
00407     GeoUInt8Property::StoredFieldType  *t  = types->editFieldPtr();
00408
00409     if(doSide)
00410     {
00411         UInt32 baseindex = p->size();
00412
00413         for(j = 0; j <= sides; j++)
00414         {
00415             beta = j * delta;
00416             x    =  osgSin(beta);
00417             z    = -osgCos(beta);
00418
00419             p->push_back(Pnt3f(x * topradius, height/2, z * topradius));
00420             n->push_back(Vec3f(x/nlen, incl/nlen, z/nlen));
00421             tx->push_back(Vec2f(1.f - j / Real32(sides), 1));
00422         }
00423
00424         for(j = 0; j <= sides; j++)
00425         {
00426             beta = j * delta;
00427             x    =  osgSin(beta);
00428             z    = -osgCos(beta);
00429
00430             p->push_back(Pnt3f(x * botradius, -height/2, z * botradius));
00431             n->push_back(Vec3f(x/nlen, incl/nlen, z/nlen));
00432             tx->push_back(Vec2f(1.f - j / Real32(sides), 0));
00433         }
00434
00435         t->push_back(GL_TRIANGLE_STRIP);
00436         l->push_back(2 * (sides + 1));
00437
00438         for(j = 0; j <= sides; j++)
00439         {
00440                 i->push_back(baseindex + sides + 1 + j);
00441                 i->push_back(baseindex + j);
00442         }
00443     }
00444
00445     if(doTop && topradius > 0)
00446     {
00447         UInt32 baseindex = p->size();
00448
00449         // need to duplicate the points fornow, as we don't have multi-index geo yet
00450
00451         for(j = sides - 1; j >= 0; j--)
00452         {
00453             beta = j * delta;
00454             x    =  topradius * osgSin(beta);
00455             z    = -topradius * osgCos(beta);
00456
00457             p->push_back(Pnt3f(x, height/2, z));
00458             n->push_back(Vec3f(0, 1, 0));
00459             tx->push_back(Vec2f(x / topradius / 2 + .5f, -z / topradius / 2 + .5f));
00460         }
00461
00462         t->push_back(GL_POLYGON);
00463         l->push_back(sides);
00464
00465         for(j = 0; j < sides; j++)
00466         {
00467             i->push_back(baseindex + j);
00468         }
00469     }
00470
00471     if(doBottom && botradius > 0 )
00472     {
00473         UInt32 baseindex = p->size();
00474
00475         // need to duplicate the points fornow, as we don't have multi-index geo yet
00476
00477         for(j = sides - 1; j >= 0; j--)
00478         {
00479             beta = j * delta;
00480             x    =  botradius * osgSin(beta);
00481             z    = -botradius * osgCos(beta);
00482
00483             p->push_back(Pnt3f(x, -height/2, z));
00484             n->push_back(Vec3f(0, -1, 0));
00485             tx->push_back(Vec2f(x / botradius / 2 + .5f, z / botradius / 2 + .5f));
00486         }
00487
00488         t->push_back(GL_POLYGON);
00489         l->push_back(sides);
00490
00491         for(j = 0; j < sides; j++)
00492         {
00493             i->push_back(baseindex + sides - 1 - j);
00494         }
00495     }
00496
00497     // create the geometry
00498
00499     GeometryTransitPtr geo = Geometry::create();
00500
00501     geo->setMaterial(getDefaultMaterial());
00502     geo->setPositions(pnts);
00503     geo->setNormals(norms);
00504     geo->setTexCoords(tex);
00505     geo->setIndices(index);
00506     geo->setTypes(types);
00507     geo->setLengths(lens);
00508
00509     return geo;
00510 }
00511
00523 NodeTransitPtr makeTorus(Real32 innerRadius,
00524                          Real32 outerRadius,
00525                          UInt16 sides,
00526                          UInt16 rings)
00527 {
00528     GeometryTransitPtr pGeo = makeTorusGeo(innerRadius,
00529                                            outerRadius,
00530                                            sides,
00531                                            rings);
00532
00533     if(pGeo == NULL)
00534     {
00535         return NodeTransitPtr(NULL);
00536     }
00537
00538     NodeTransitPtr node = Node::create();
00539
00540     node->setCore(pGeo);
00541
00542     return node;
00543 }
00544
00557 GeometryTransitPtr makeTorusGeo(Real32 innerRadius,
00558                                 Real32 outerRadius,
00559                                 UInt16 sides,
00560                                 UInt16 rings)
00561 {
00562     if(innerRadius <= 0 || outerRadius <= 0 || sides < 3 || rings < 3)
00563     {
00564         SWARNING << "makeTorus: illegal parameters innerRadius=" << innerRadius
00565                  << ", outerRadius=" << outerRadius
00566                  << ", sides=" << sides
00567                  << ", rings=" << rings
00568                  << std::endl;
00569         return GeometryTransitPtr(NULL);
00570     }
00571
00572     GeoPnt3fPropertyUnrecPtr  pnts  = GeoPnt3fProperty ::create();
00573     GeoVec3fPropertyUnrecPtr  norms = GeoVec3fProperty ::create();
00574     GeoVec2fPropertyUnrecPtr  tex   = GeoVec2fProperty ::create();
00575     GeoUInt32PropertyUnrecPtr index = GeoUInt32Property::create();
00576     GeoUInt32PropertyUnrecPtr lens  = GeoUInt32Property::create();
00577     GeoUInt8PropertyUnrecPtr  types = GeoUInt8Property ::create();
00578
00579     UInt16 a, b;
00580     Real32 theta, phi;
00581     Real32 cosTheta, sinTheta;
00582     Real32 ringDelta, sideDelta;
00583
00584     // calc the vertices
00585
00586     GeoPnt3fProperty::StoredFieldType  *p  = pnts ->editFieldPtr();
00587     GeoVec3fProperty::StoredFieldType  *n  = norms->editFieldPtr();
00588     GeoVec2fProperty::StoredFieldType  *tx = tex  ->editFieldPtr();
00589
00590     ringDelta = 2.f * Pi / rings;
00591     sideDelta = 2.f * Pi / sides;
00592
00593     for(a = 0, theta = 0.0; a <= rings; a++, theta += ringDelta)
00594     {
00595         cosTheta = osgCos(theta);
00596         sinTheta = osgSin(theta);
00597
00598         for(b = 0, phi = 0; b <= sides; b++, phi += sideDelta)
00599         {
00600             GLfloat cosPhi, sinPhi, dist;
00601
00602             cosPhi = osgCos(phi);
00603             sinPhi = osgSin(phi);
00604             dist   = outerRadius + innerRadius * cosPhi;
00605
00606             n->push_back(Vec3f(cosTheta * cosPhi,
00607                               -sinTheta * cosPhi,
00608                               sinPhi));
00609             p->push_back(Pnt3f(cosTheta * dist,
00610                               -sinTheta * dist,
00611                               innerRadius * sinPhi));
00612             tx->push_back(Vec2f(- a / Real32(rings), b / Real32(sides)));
00613         }
00614     }
00615
00616     // create the faces
00617
00618     GeoUInt32Property::StoredFieldType *i  = index->editFieldPtr();
00619     GeoUInt32Property::StoredFieldType *l  = lens ->editFieldPtr();
00620     GeoUInt8Property::StoredFieldType  *t  = types->editFieldPtr();
00621
00622     for(a = 0; a < sides; a++)
00623     {
00624         t->push_back(GL_TRIANGLE_STRIP);
00625         l->push_back((rings + 1) * 2);
00626
00627         for(b = 0; b <= rings; b++)
00628         {
00629             i->push_back(b * (sides+1) + a);
00630             i->push_back(b * (sides+1) + a + 1);
00631         }
00632     }
00633
00634     // create the geometry
00635
00636     GeometryTransitPtr geo = Geometry::create();
00637
00638     geo->setMaterial(getDefaultMaterial());
00639     geo->setPositions(pnts);
00640     geo->setNormals(norms);
00641     geo->setTexCoords(tex);
00642     geo->setIndices(index);
00643     geo->setTypes(types);
00644     geo->setLengths(lens);
00645
00646     return geo;
00647 }
00648
00649 #if !defined(OSG_DO_DOC) || defined(OSG_DOC_DEV)
00650 
00658 Real32 setVecLen(Vec3f &vec, Real32 length)
00659 {
00660     Real32 len = vec.length();
00661     if(len == 0.0)
00662     {
00663         len = 1;
00664     }
00665     else
00666     {
00667         len = length / len;
00668     }
00669     vec *= len;
00670
00671     return length;
00672 }
00673
00674 Real32 calcTexS(Vec3f &n, Real32 theta)
00675 {
00676     const Real32 TwoPi  = 6.283185307179586f;
00677     const Real32 HalfPi = 1.570796326794897f;
00678
00679     Real32 phi = osgATan2(-n[2], n[0]) - HalfPi;
00680
00681     if (phi <= -Eps)
00682         phi += TwoPi;
00683     phi /= TwoPi;
00684
00685     return phi;
00686 }
00687
00688 void addPoint(Pnt3f v, UInt32 index, Real32 radius,
00689               GeoPnt3fProperty::StoredFieldType *p,
00690               GeoVec3fProperty::StoredFieldType *n,
00691               GeoVec2fProperty::StoredFieldType *tx)
00692 {
00693     Vec3f norm(v[0], v[1], v[2]);
00694
00695     norm.normalize();
00696     n->push_back(norm);
00697
00698     Pnt3f pnt(radius * norm);
00699     p->push_back(pnt);
00700
00701     Vec2f texCoord;
00702
00703     // Theta -> v
00704     texCoord[1] = (Pi - osgACos(norm[1])) / Pi;
00705
00706     texCoord[0] = calcTexS(norm, texCoord[1]);
00707
00708     tx->push_back(texCoord);
00709 }
00710
00711 void subdivideTriangle( UInt32 i1,
00712                         UInt32 i2,
00713                         UInt32 i3,
00714                         Int32 depth,
00715                         GeoPnt3fProperty::StoredFieldType  *p,
00716                         GeoVec3fProperty::StoredFieldType  *n,
00717                         GeoVec2fProperty::StoredFieldType  *tx,
00718                         GeoUInt32Property::StoredFieldType *i,
00719                         GeoUInt32Property::StoredFieldType *tci,
00720                         UInt32& z, Real32 radius )
00721 {
00722     if (depth == 0)
00723     {
00724         i->push_back(i1);
00725         tci->push_back(i1);
00726         i->push_back(i2);
00727         tci->push_back(i2);
00728         i->push_back(i3);
00729         tci->push_back(i3);
00730
00731         return;
00732     }
00733
00734     Pnt3f v1 = (*p)[i1],
00735           v2 = (*p)[i2],
00736           v3 = (*p)[i3];
00737     Pnt3f v12, v23, v31;
00738
00739     v12 = v1 + (v2 - v1) * .5f;
00740     v23 = v2 + (v3 - v2) * .5f;
00741     v31 = v3 + (v1 - v3) * .5f;
00742
00743     v12 /= 2.0f;
00744     v23 /= 2.0f;
00745     v31 /= 2.0f;
00746
00747     UInt32 i12 = z++, i23 = z++, i31 = z++;
00748
00749     addPoint(v12,i12,radius,p,n,tx);
00750     addPoint(v23,i23,radius,p,n,tx);
00751     addPoint(v31,i31,radius,p,n,tx);
00752
00753     subdivideTriangle( i1, i12, i31, depth - 1, p,n,tx,i,tci, z, radius);
00754     subdivideTriangle( i2, i23, i12, depth - 1, p,n,tx,i,tci, z, radius);
00755     subdivideTriangle( i3, i31, i23, depth - 1, p,n,tx,i,tci, z, radius);
00756     subdivideTriangle(i12, i23, i31, depth - 1, p,n,tx,i,tci, z, radius);
00757 }
00758
00759 #endif            // exclude from doc
00760 
00771 NodeTransitPtr makeSphere(UInt16 depth, Real32 radius)
00772 {
00773     GeometryTransitPtr pGeo = makeSphereGeo(depth, radius);
00774
00775     if(pGeo == NULL)
00776     {
00777         return NodeTransitPtr(NULL);
00778     }
00779
00780     NodeTransitPtr node = Node::create();
00781
00782     node->setCore(pGeo);
00783
00784     return node;
00785 }
00786
00797 GeometryTransitPtr makeSphereGeo(UInt16 depth, Real32 radius)
00798 {
00799     const Real32 X = .525731112119133606f;
00800     const Real32 Z = .850650808352039932f;
00801     const Real32 HalfPi = 1.570796326794897f;
00802
00803     GeoPnt3fPropertyUnrecPtr  pnts    = GeoPnt3fProperty ::create();
00804     GeoVec3fPropertyUnrecPtr  norms   = GeoVec3fProperty ::create();
00805     GeoVec2fPropertyUnrecPtr  tex     = GeoVec2fProperty ::create();
00806     GeoUInt32PropertyUnrecPtr index   = GeoUInt32Property::create();
00807     GeoUInt32PropertyUnrecPtr tcindex = GeoUInt32Property::create();
00808     GeoUInt32PropertyUnrecPtr lens    = GeoUInt32Property::create();
00809     GeoUInt8PropertyUnrecPtr  types   = GeoUInt8Property ::create();
00810
00811     UInt32              j,z;
00812
00813     static Vec3f v[12] = {  Vec3f(-X, 0.,  Z),
00814                             Vec3f( X, 0.,  Z),
00815                             Vec3f(-X, 0., -Z),
00816                             Vec3f( X, 0., -Z),
00817                             Vec3f(0.,  Z,  X),
00818                             Vec3f(0.,  Z, -X),
00819                             Vec3f(0., -Z,  X),
00820                             Vec3f(0., -Z, -X),
00821                             Vec3f( Z,  X, 0.),
00822                             Vec3f(-Z,  X, 0.),
00823                             Vec3f( Z, -X, 0.),
00824                             Vec3f(-Z, -X, 0.)  };
00825
00826     Quaternion q(Vec3f(0,1,0), osgACos(Z) + HalfPi);
00827     Matrix mat;
00828
00829     mat.setTransform(q);
00830
00831     for (j=0; j<12; j++)
00832         mat.mult(v[j], v[j]);
00833
00834     Int32 tr[20][3] = { {1,4,0},  {4,9,0},  {4,5,9},  {8,5,4},  {1,8,4},
00835                         {1,10,8}, {10,3,8}, {8,3,5},  {3,2,5},  {3,7,2},
00836                         {3,10,7}, {10,6,7}, {6,11,7}, {6,0,11}, {6,1,0},
00837                         {10,1,6}, {11,0,9}, {2,11,9}, {5,2,9},  {11,2,7} };
00838
00839     GeoPnt3fProperty::StoredFieldType  *p  = pnts ->editFieldPtr();
00840     GeoVec3fProperty::StoredFieldType  *n  = norms->editFieldPtr();
00841     GeoVec2fProperty::StoredFieldType  *tx = tex  ->editFieldPtr();
00842
00843     GeoUInt32Property::StoredFieldType *i   = index  ->editFieldPtr();
00844     GeoUInt32Property::StoredFieldType *tci = tcindex->editFieldPtr();
00845
00846     // initial sizing to prevent reallocation halfway through
00847     UInt32 estimatedSize = UInt32(osgPow(4.f, Real32(depth)) * 20.f);
00848
00849     p->reserve (estimatedSize);
00850     n->reserve (estimatedSize);
00851     tx->reserve(estimatedSize);
00852     i->reserve (estimatedSize);
00853     tci->reserve (estimatedSize);
00854
00855     // add the initial points to the fields
00856     for (j=0; j<12; j++)
00857     {
00858         Vec3f pnt = v[j];
00859         Vec3f norm = v[j];
00860
00861         setVecLen(pnt, radius);
00862         norm.normalize();
00863
00864         p->push_back(pnt.addToZero());
00865         n->push_back(norm);
00866
00867         Vec2f texCoord;
00868
00869         // Theta -> v
00870         texCoord[1] = (Pi - osgACos(norm[1])) / Pi;
00871
00872         // Phi -> u
00873         texCoord[0] = calcTexS(norm, texCoord[1]);
00874
00875         tx->push_back(texCoord);
00876     }
00877
00878     // subdivide the triangles
00879     z=12;
00880     for(j=0; j<20; j++)
00881     {
00882         subdivideTriangle(tr[j][0], tr[j][1], tr[j][2],
00883                           depth, p, n, tx, i, tci, z, radius);
00884     }
00885
00886     types->push_back(GL_TRIANGLES);
00887     lens->push_back(i->size());
00888
00889     // create the geometry
00890     GeometryTransitPtr geo = Geometry::create();
00891
00892     geo->setMaterial(getDefaultMaterial());
00893     geo->setPositions(pnts);
00894     geo->setNormals(norms);
00895     geo->setTexCoords(tex);
00896     geo->setIndices(index);
00897     geo->setIndex(tcindex, Geometry::TexCoordsIndex);
00898     geo->setTypes(types);
00899     geo->setLengths(lens);
00900
00901
00902 #if 0 // not sure what this was needed for??? *DR*
00903     // now check triangles
00904     beginEditCP(geo);
00905
00906     for (TriangleIterator ti = geo->beginTriangles();
00907                           ti != geo->endTriangles(); ++ti)
00908     {
00909         Vec3f q[3];
00910         q[0] = ti.getNormal(0);
00911         q[1] = ti.getNormal(1);
00912         q[2] = ti.getNormal(2);
00913
00914         if  ( (osgAbs(q[0][0]) <= 0.01 && q[0][2] >= Eps) ||
00915               (osgAbs(q[1][0]) <= 0.01 && q[1][2] >= Eps) ||
00916               (osgAbs(q[2][0]) <= 0.01 && q[2][2] >= Eps) )
00917         {
00918             for (UInt16 i=0; i<3; i++)
00919             {
00920                 Vec3f norm(q[i]);
00921
00922                 if (osgAbs(norm[0]) <= Eps && norm[2] <= Eps)
00923                 {
00924                     Real32 theta = ti.getTexCoords(i).y();
00925
00926                     if( !(q[0][0] <= -Eps ||
00927                           q[1][0] <= -Eps ||
00928                           q[2][0] <= -Eps  ) )
00929                     {
00930                         Vec2f texCoord(1, theta);
00931
00932                         if(osgAbs(osgAbs(norm[1]) - 1) <= Eps)
00933                             texCoord[0] = 0.5;
00934
00935                         tex->push_back(texCoord);
00936
00937                         tcindex->setValue( tex->size() - 1, ti.getTexCoordsIndex(i));
00938                     }
00939                     else
00940                     {
00941                         Vec2f texCoord(0, theta);
00942
00943                         if (osgAbs(osgAbs(norm[1]) - 1) <= Eps)
00944                             texCoord[0] = 0.5;
00945
00946                         tex->push_back(texCoord);
00947
00948                         index->setValue( tex->size() - 1, ti.getTexCoordsIndex(i));
00949                     }
00950                 }
00951             }
00952         }
00953     }
00954
00955     endEditCP(geo);
00956 #endif
00957 
00958     return geo;
00959 }
00960
00972 NodeTransitPtr makeLatLongSphere(UInt16 latres, UInt16 longres, Real32 radius)
00973 {
00974     GeometryTransitPtr pGeo = makeLatLongSphereGeo(latres, longres, radius);
00975
00976     if(pGeo == NULL)
00977     {
00978         return NodeTransitPtr(NULL);
00979     }
00980
00981     NodeTransitPtr node = Node::create();
00982
00983     node->setCore(pGeo);
00984
00985     return node;
00986 }
00987
00999 GeometryTransitPtr makeLatLongSphereGeo(UInt16 latres,
01000                                         UInt16 longres,
01001                                         Real32 radius)
01002 {
01003     if(radius <= 0 || latres < 4 || longres < 4)
01004     {
01005         SWARNING << "makeLatLongSphere: illegal parameters "
01006                  << "latres=" << latres
01007                  << ", longres=" << longres
01008                  << ", radius=" << radius
01009                  << std::endl;
01010         return GeometryTransitPtr(NULL);
01011     }
01012
01013     GeoPnt3fPropertyUnrecPtr  pnts  = GeoPnt3fProperty ::create();
01014     GeoVec3fPropertyUnrecPtr  norms = GeoVec3fProperty ::create();
01015     GeoVec2fPropertyUnrecPtr  tex   = GeoVec2fProperty ::create();
01016     GeoUInt32PropertyUnrecPtr index = GeoUInt32Property::create();
01017     GeoUInt32PropertyUnrecPtr lens  = GeoUInt32Property::create();
01018     GeoUInt8PropertyUnrecPtr  types = GeoUInt8Property ::create();
01019
01020     UInt16 a, b;
01021     Real32 theta, phi;
01022     Real32 cosTheta, sinTheta;
01023     Real32 latDelta, longDelta;
01024
01025     // calc the vertices
01026
01027     GeoPnt3fProperty::StoredFieldType  *p  = pnts ->editFieldPtr();
01028     GeoVec3fProperty::StoredFieldType  *n  = norms->editFieldPtr();
01029     GeoVec2fProperty::StoredFieldType  *tx = tex  ->editFieldPtr();
01030
01031     latDelta  =       Pi / latres;
01032     longDelta = 2.f * Pi / longres;
01033
01034     for(a = 0, theta = -Pi / 2; a <= latres; a++, theta += latDelta)
01035     {
01036         cosTheta = osgCos(theta);
01037         sinTheta = osgSin(theta);
01038
01039         for(b = 0, phi = -Pi; b <= longres; b++, phi += longDelta)
01040         {
01041             GLfloat cosPhi, sinPhi;
01042
01043             cosPhi = osgCos(phi);
01044             sinPhi = osgSin(phi);
01045
01046             n->push_back(Vec3f(cosTheta * sinPhi,
01047                                sinTheta,
01048                                cosTheta * cosPhi));
01049
01050             p->push_back(Pnt3f( cosTheta * sinPhi * radius,
01051                                sinTheta          * radius,
01052                                cosTheta * cosPhi * radius));
01053
01054             tx->push_back(Vec2f(b / Real32(longres),
01055                                 a / Real32(latres)));
01056         }
01057     }
01058
01059     // create the faces
01060
01061     GeoUInt32Property::StoredFieldType *i  = index->editFieldPtr();
01062     GeoUInt32Property::StoredFieldType *l  = lens ->editFieldPtr();
01063     GeoUInt8Property::StoredFieldType  *t  = types->editFieldPtr();
01064
01065     for(a = 0; a < longres; a++)
01066     {
01067         t->push_back(GL_TRIANGLE_STRIP);
01068         l->push_back((latres + 1) * 2);
01069
01070         for(b = 0; b <= latres; b++)
01071         {
01072             i->push_back(b * (longres+1) + a);
01073             i->push_back(b * (longres+1) + a + 1);
01074         }
01075     }
01076
01077     // create the geometry
01078
01079     GeometryTransitPtr geo = Geometry::create();
01080
01081     geo->setMaterial(getDefaultMaterial());
01082     geo->setPositions(pnts);
01083     geo->setNormals(norms);
01084     geo->setTexCoords(tex);
01085     geo->setIndices(index);
01086     geo->setTypes(types);
01087     geo->setLengths(lens);
01088
01089     return geo;
01090 }
01091
01092
01104 NodeTransitPtr makeLatLongEllipsoid(UInt16 latres,
01105                                     UInt16 longres,
01106                                     Real32 rSemiMajorAxis,
01107                                     Real32 rSemiMinorAxis)
01108 {
01109     GeometryTransitPtr pGeo = makeLatLongEllipsoidGeo(latres,
01110                                                       longres,
01111                                                       rSemiMajorAxis,
01112                                                       rSemiMinorAxis);
01113
01114     if(pGeo == NULL)
01115     {
01116         return NodeTransitPtr(NULL);
01117     }
01118
01119     NodeTransitPtr node = Node::create();
01120
01121     node->setCore(pGeo);
01122
01123     return node;
01124 }
01125
01137 GeometryTransitPtr makeLatLongEllipsoidGeo(UInt16 latres,
01138                                            UInt16 longres,
01139                                            Real32 rSemiMajorAxis,
01140                                            Real32 rSemiMinorAxis)
01141 {
01142     if(rSemiMajorAxis <= 0 || rSemiMinorAxis <= 0 || latres < 4 || longres < 4)
01143     {
01144         SWARNING << "makeLatLongSphere: illegal parameters "
01145                  << "latres=" << latres
01146                  << ", longres=" << longres
01147                  << ", rSemiMajorAxis=" << rSemiMajorAxis
01148                  << ", rSemiMinorAxis=" << rSemiMinorAxis
01149                  << std::endl;
01150         return GeometryTransitPtr(NULL);
01151     }
01152
01153     GeoPnt3fPropertyUnrecPtr   pnts  = GeoPnt3fProperty  ::create();
01154     GeoVec3fPropertyUnrecPtr   norms = GeoVec3fProperty  ::create();
01155     GeoVec2fPropertyUnrecPtr   tex   = GeoVec2fProperty  ::create();
01156     GeoUInt32PropertyUnrecPtr  index = GeoUInt32Property ::create();
01157     GeoUInt32PropertyUnrecPtr  lens  = GeoUInt32Property ::create();
01158     GeoUInt8PropertyUnrecPtr   types = GeoUInt8Property  ::create();
01159
01160     UInt16 a, b;
01161     Real32 theta, phi;
01162     Real32 cosTheta, sinTheta;
01163     Real32 latDelta, longDelta;
01164
01165     // calc the vertices
01166
01167     GeoPnt3fProperty  ::StoredFieldType  *p  = pnts ->editFieldPtr();
01168     GeoVec3fProperty  ::StoredFieldType  *n  = norms->editFieldPtr();
01169     GeoVec2fProperty  ::StoredFieldType  *tx = tex  ->editFieldPtr();
01170
01171     latDelta  =       Pi / latres;
01172     longDelta = 2.f * Pi / longres;
01173
01174 //    float ea = 6378.137;
01175 //    float eb = 6356.7523142;
01176
01177     float rSemiMajorAxisSquare = rSemiMajorAxis * rSemiMajorAxis;
01178
01179     float e2 = (rSemiMajorAxisSquare -
01180                 rSemiMinorAxis * rSemiMinorAxis) / (rSemiMajorAxisSquare);
01181
01182     for(a = 0, theta = -Pi / 2; a <= latres; a++, theta += latDelta)
01183     {
01184         cosTheta = osgCos(theta);
01185         sinTheta = osgSin(theta);
01186
01187         float v = rSemiMajorAxis / osgSqrt(1 - (e2 * sinTheta * sinTheta));
01188
01189         for(b = 0, phi = -Pi; b <= longres; b++, phi += longDelta)
01190         {
01191             GLfloat cosPhi, sinPhi;
01192
01193             cosPhi = osgCos(phi);
01194             sinPhi = osgSin(phi);
01195
01196
01197             n->push_back(Vec3f(cosTheta * sinPhi,
01198                                sinTheta,
01199                                cosTheta * cosPhi));
01200
01201             p->push_back(Pnt3f(cosTheta * sinPhi * v,
01202                                sinTheta          * ((1 - e2) * v),
01203                                cosTheta * cosPhi * v));
01204
01205             tx->push_back(Vec2f(b / Real32(longres),
01206                                 a / Real32(latres)));
01207
01208         }
01209     }
01210
01211     // create the faces
01212
01213     GeoUInt32Property::StoredFieldType *i  = index->editFieldPtr();
01214     GeoUInt32Property::StoredFieldType *l  = lens ->editFieldPtr();
01215     GeoUInt8Property::StoredFieldType  *t  = types->editFieldPtr();
01216
01217     for(a = 0; a < longres; a++)
01218     {
01219         t->push_back(GL_TRIANGLE_STRIP);
01220         l->push_back((latres + 1) * 2);
01221
01222         for(b = 0; b <= latres; b++)
01223         {
01224             i->push_back(b * (longres+1) + a);
01225             i->push_back(b * (longres+1) + a + 1);
01226         }
01227     }
01228
01229     // create the geometry
01230
01231     GeometryTransitPtr geo = Geometry::create();
01232
01233     geo->setMaterial(getDefaultMaterial());
01234     geo->setPositions(pnts);
01235     geo->setNormals(norms);
01236     geo->setTexCoords(tex);
01237     geo->setIndices(index);
01238     geo->setTypes(types);
01239     geo->setLengths(lens);
01240
01241     return geo;
01242 }
01243
01244
01257 NodeTransitPtr makeLatLongEllipsoidSeg(UInt16 latres,
01258                                        UInt16 longres,
01259                                        Real32 rSemiMajorAxis,
01260                                        Real32 rSemiMinorAxis,
01261                                        Real32 rStartLatRad,
01262                                        Real32 rStartLongRad,
01263                                        Real32 rStopLatRad,
01264                                        Real32 rStopLongRad)
01265 {
01266     GeometryTransitPtr pGeo = makeLatLongEllipsoidGeoSeg(latres,
01267                                                          longres,
01268                                                          rSemiMajorAxis,
01269                                                          rSemiMinorAxis,
01270                                                          rStartLatRad,
01271                                                          rStartLongRad,
01272                                                          rStopLatRad,
01273                                                          rStopLongRad );
01274
01275     if(pGeo == NULL)
01276     {
01277         return NodeTransitPtr(NULL);
01278     }
01279
01280     NodeTransitPtr node = Node::create();
01281
01282     node->setCore(pGeo);
01283
01284     return node;
01285 }
01286
01298 GeometryTransitPtr makeLatLongEllipsoidGeoSeg(UInt16 latres,
01299                                               UInt16 longres,
01300                                               Real32 rSemiMajorAxis,
01301                                               Real32 rSemiMinorAxis,
01302                                               Real32 rStartLatRad,
01303                                               Real32 rStartLongRad,
01304                                               Real32 rStopLatRad,
01305                                               Real32 rStopLongRad)
01306 {
01307     if(rSemiMajorAxis <= 0 || rSemiMinorAxis <= 0 || latres < 4 || longres < 4)
01308     {
01309         SWARNING << "makeLatLongSphere: illegal parameters "
01310                  << "latres=" << latres
01311                  << ", longres=" << longres
01312                  << ", rSemiMajorAxis=" << rSemiMajorAxis
01313                  << ", rSemiMinorAxis=" << rSemiMinorAxis
01314                  << std::endl;
01315         return GeometryTransitPtr(NULL);
01316     }
01317
01318     GeoPnt3fPropertyUnrecPtr   pnts  = GeoPnt3fProperty  ::create();
01319     GeoVec3fPropertyUnrecPtr   norms = GeoVec3fProperty  ::create();
01320     GeoVec2fPropertyUnrecPtr   tex   = GeoVec2fProperty  ::create();
01321     GeoUInt32PropertyUnrecPtr  index = GeoUInt32Property ::create();
01322     GeoUInt32PropertyUnrecPtr  lens  = GeoUInt32Property ::create();
01323     GeoUInt8PropertyUnrecPtr   types = GeoUInt8Property  ::create();
01324
01325     UInt16 a, b;
01326     Real32 theta, phi;
01327     Real32 cosTheta, sinTheta;
01328     Real32 latDelta, longDelta;
01329
01330     // calc the vertices
01331
01332     GeoPnt3fProperty  ::StoredFieldType  *p  = pnts ->editFieldPtr();
01333     GeoVec3fProperty  ::StoredFieldType  *n  = norms->editFieldPtr();
01334     GeoVec2fProperty  ::StoredFieldType  *tx = tex  ->editFieldPtr();
01335
01336     Real32 latDiff  = rStopLatRad   - rStartLatRad;
01337     Real32 longDiff = rStopLongRad  - rStartLongRad;
01338
01339     latDelta  = latDiff  / latres;
01340     longDelta = longDiff / longres;
01341
01342 //    float ea = 6378.137;
01343 //    float eb = 6356.7523142;
01344
01345     float rSemiMajorAxisSquare = rSemiMajorAxis * rSemiMajorAxis;
01346
01347     float e2 = (rSemiMajorAxisSquare -
01348                 rSemiMinorAxis * rSemiMinorAxis) / (rSemiMajorAxisSquare);
01349
01350     for(a = 0, theta = rStartLatRad; a <= latres; a++, theta += latDelta)
01351     {
01352         cosTheta = osgCos(theta);
01353         sinTheta = osgSin(theta);
01354
01355         float v = rSemiMajorAxis / osgSqrt(1 - (e2 * sinTheta * sinTheta));
01356
01357         for(b = 0, phi = rStartLongRad; b <= longres; b++, phi += longDelta)
01358         {
01359             GLfloat cosPhi, sinPhi;
01360
01361             cosPhi = osgCos(phi);
01362             sinPhi = osgSin(phi);
01363
01364
01365             n->push_back(Vec3f(cosTheta * sinPhi,
01366                                sinTheta,
01367                                cosTheta * cosPhi));
01368
01369             p->push_back(Pnt3f(cosTheta * sinPhi * v,
01370                                sinTheta          * ((1 - e2) * v),
01371                                cosTheta * cosPhi * v));
01372
01373             tx->push_back(Vec2f(b / Real32(longres),
01374                                 a / Real32(latres)));
01375
01376         }
01377     }
01378
01379     // create the faces
01380
01381     GeoUInt32Property::StoredFieldType *i  = index->editFieldPtr();
01382     GeoUInt32Property::StoredFieldType *l  = lens ->editFieldPtr();
01383     GeoUInt8Property::StoredFieldType  *t  = types->editFieldPtr();
01384
01385     for(a = 0; a < longres; a++)
01386     {
01387         t->push_back(GL_TRIANGLE_STRIP);
01388         l->push_back((latres + 1) * 2);
01389
01390         for(b = 0; b <= latres; b++)
01391         {
01392             i->push_back(b * (longres+1) + a);
01393             i->push_back(b * (longres+1) + a + 1);
01394         }
01395     }
01396
01397     // create the geometry
01398
01399     GeometryTransitPtr geo = Geometry::create();
01400
01401     geo->setMaterial(getDefaultMaterial());
01402     geo->setPositions(pnts);
01403     geo->setNormals(norms);
01404     geo->setTexCoords(tex);
01405     geo->setIndices(index);
01406     geo->setTypes(types);
01407     geo->setLengths(lens);
01408
01409     return geo;
01410 }
01411
01412
01413 GeometryTransitPtr makeEllipsoidAxisGeo(UInt16 latres,
01414                                         UInt16 longres,
01415                                         Real32 rSemiMajorAxis,
01416                                         Real32 rSemiMinorAxis)
01417 {
01418     if(rSemiMajorAxis <= 0 || rSemiMinorAxis <= 0 || latres < 4 || longres < 4)
01419     {
01420         SWARNING << "makeLatLongSphere: illegal parameters "
01421                  << "latres=" << latres
01422                  << ", longres=" << longres
01423                  << ", rSemiMajorAxis=" << rSemiMajorAxis
01424                  << ", rSemiMinorAxis=" << rSemiMinorAxis
01425                  << std::endl;
01426         return GeometryTransitPtr(NULL);
01427     }
01428
01429     GeoPnt3fPropertyUnrecPtr   pnts  = GeoPnt3fProperty  ::create();
01430     GeoColor3fPropertyUnrecPtr color = GeoColor3fProperty::create();
01431     GeoUInt32PropertyUnrecPtr  index = GeoUInt32Property ::create();
01432     GeoUInt32PropertyUnrecPtr  lens  = GeoUInt32Property ::create();
01433     GeoUInt8PropertyUnrecPtr   types = GeoUInt8Property  ::create();
01434
01435     UInt16 a, b;
01436     Real32 theta, phi;
01437     Real32 cosTheta, sinTheta;
01438     Real32 latDelta, longDelta;
01439
01440     // calc the vertices
01441
01442     GeoPnt3fProperty  ::StoredFieldType  *p  = pnts ->editFieldPtr();
01443     GeoColor3fProperty::StoredFieldType  *c  = color->editFieldPtr();
01444
01445     latDelta  = Pi / (2 * latres);
01446     longDelta = Pi / (2 * longres);
01447
01448 //    float ea = 6378.137;
01449 //    float eb = 6356.7523142;
01450
01451     float rSemiMajorAxisSquare = rSemiMajorAxis * rSemiMajorAxis;
01452
01453     float e2 = (rSemiMajorAxisSquare -
01454                 rSemiMinorAxis * rSemiMinorAxis) / (rSemiMajorAxisSquare);
01455
01456     for(a = 0, theta = 0; a <= latres; a++, theta += latDelta)
01457     {
01458         cosTheta = osgCos(theta);
01459         sinTheta = osgSin(theta);
01460
01461         float v = rSemiMajorAxis / osgSqrt(1 - (e2 * sinTheta * sinTheta));
01462
01463         phi = 0;
01464
01465         GLfloat cosPhi, sinPhi;
01466
01467         cosPhi = osgCos(phi);
01468         sinPhi = osgSin(phi);
01469
01470
01471         p->push_back(Pnt3f(cosTheta * sinPhi * v,
01472                            sinTheta          * ((1 - e2) * v),
01473                            cosTheta * cosPhi * v));
01474
01475         c->push_back(Color3f(0.f, 1.f, 0.f));
01476     }
01477
01478     theta = 0;
01479
01480     cosTheta = osgCos(theta);
01481     sinTheta = osgSin(theta);
01482
01483     float v = rSemiMajorAxis / osgSqrt(1 - (e2 * sinTheta * sinTheta));
01484
01485     for(b = 0, phi = 0; b <= longres; b++, phi += longDelta)
01486     {
01487         GLfloat cosPhi, sinPhi;
01488
01489         cosPhi = osgCos(phi);
01490         sinPhi = osgSin(phi);
01491
01492
01493         p->push_back(Pnt3f(cosTheta * sinPhi * v,
01494                            sinTheta          * ((1 - e2) * v),
01495                            cosTheta * cosPhi * v));
01496
01497         c->push_back(Color3f(1.f, 0.f, 0.f));
01498     }
01499
01500
01501     // create the faces
01502
01503     GeoUInt32Property::StoredFieldType *i  = index->editFieldPtr();
01504     GeoUInt32Property::StoredFieldType *l  = lens ->editFieldPtr();
01505     GeoUInt8Property ::StoredFieldType *t  = types->editFieldPtr();
01506
01507     t->push_back(GL_LINE_STRIP);
01508     l->push_back(latres + 1);
01509
01510     t->push_back(GL_LINE_STRIP);
01511     l->push_back(longres + 1);
01512
01513     for(a = 0; a <= latres; a++)
01514     {
01515         i->push_back(a);
01516     }
01517
01518     for(b = 0; b <= longres; b++)
01519     {
01520         i->push_back(b + a);
01521     }
01522
01523     // create the geometry
01524
01525     GeometryUnrecPtr geo = Geometry::create();
01526
01527     geo->setMaterial(getDefaultUnlitMaterial());
01528     geo->setPositions(pnts);
01529     geo->setColors(color);
01530     geo->setIndices(index);
01531     geo->setTypes(types);
01532     geo->setLengths(lens);
01533
01534     return GeometryTransitPtr(geo);
01535 }
01536
01537 NodeTransitPtr makeEllipsoidAxis(UInt16 latres,
01538                                  UInt16 longres,
01539                                  Real32 rSemiMajorAxis,
01540                                  Real32 rSemiMinorAxis)
01541 {
01542     GeometryTransitPtr pGeo = makeEllipsoidAxisGeo(latres,
01543                                                    longres,
01544                                                    rSemiMajorAxis,
01545                                                    rSemiMinorAxis);
01546
01547     if(pGeo == NULL)
01548     {
01549         return NodeTransitPtr(NULL);
01550     }
01551
01552     NodeTransitPtr node = Node::create();
01553
01554     node->setCore(pGeo);
01555
01556     return node;
01557 }
01558
01573 NodeTransitPtr makeBox(Real32 xsize, Real32 ysize, Real32 zsize,
01574                        UInt16 hor  , UInt16 vert , UInt16 depth)
01575 {
01576     GeometryTransitPtr pGeo = makeBoxGeo(xsize, ysize, zsize, hor, vert, depth);
01577
01578     if(pGeo == NULL)
01579     {
01580         return NodeTransitPtr(NULL);
01581     }
01582
01583     NodeTransitPtr node = Node::create();
01584
01585     node->setCore(pGeo);
01586
01587     return node;
01588 }
01589
01604 GeometryTransitPtr makeBoxGeo(Real32 xsize, Real32 ysize, Real32 zsize,
01605                               UInt16 hor  , UInt16 vert , UInt16 depth)
01606 {
01607     if(! hor || ! vert || ! depth)
01608     {
01609         SWARNING << "makeBox: illegal parameters hor=" << hor << ", vert="
01610                  << vert << ", depth=" << depth << std::endl;
01611         return GeometryTransitPtr(NULL);
01612     }
01613
01614     GeoPnt3fPropertyUnrecPtr  pnts  = GeoPnt3fProperty ::create();
01615     GeoVec3fPropertyUnrecPtr  norms = GeoVec3fProperty ::create();
01616     GeoVec2fPropertyUnrecPtr  tex   = GeoVec2fProperty ::create();
01617     GeoUInt32PropertyUnrecPtr index = GeoUInt32Property::create();
01618     GeoUInt32PropertyUnrecPtr lens  = GeoUInt32Property::create();
01619     GeoUInt8PropertyUnrecPtr  types = GeoUInt8Property ::create();
01620
01621     UInt16 x,y,pl;
01622     Vec3f size(xsize,  ysize,  zsize);
01623     Vec3f step(xsize / hor, ysize / vert, zsize / depth);
01624     Vec3f res(hor,  vert,  depth);
01625
01626     // calc the vertices
01627
01628     GeoPnt3fProperty::StoredFieldType  *p  = pnts ->editFieldPtr();
01629     GeoVec3fProperty::StoredFieldType  *n  = norms->editFieldPtr();
01630     GeoVec2fProperty::StoredFieldType  *tx = tex  ->editFieldPtr();
01631
01632     static int inds[6][2] =  { {0,1}, {0,1}, {2,1}, {2,1}, {0,2}, {0,2} };
01633     static int signs[6][2] = { {1,1}, {-1,1}, {-1,1}, {1,1}, {1,-1}, {1,1} };
01634     static int asigns[6] = { 1, -1, 1, -1, 1, -1 };
01635
01636     for(pl = 0; pl < 6; pl++)
01637     {
01638         UInt16 axis = 3 - inds[pl][0] - inds[pl][1];
01639
01640         for(y = 0; y <= res[inds[pl][1]] ; y++)
01641         {
01642             for(x = 0; x <= res[inds[pl][0]]; x++)
01643             {
01644                 Pnt3f pnt;
01645                 pnt[ inds[pl][0] ] = (x * step[inds[pl][0]] - size[inds[pl][0]] / 2) *
01646                                         signs[pl][0];
01647                 pnt[ inds[pl][1] ] = (y * step[inds[pl][1]] - size[inds[pl][1]] / 2) *
01648                                         signs[pl][1];
01649                 pnt[ axis ] = size[ axis ] * asigns[ pl ] / 2;
01650                 p->push_back(pnt);
01651
01652                 Vec3f norm(0, 0, 0);
01653                 norm[ axis ] = Real32(asigns[ pl ]);
01654                 n->push_back(norm);
01655                 tx->push_back(Vec2f(x / Real32(res[inds[pl][0]]),
01656                                     y / Real32(res[inds[pl][1]])));
01657             }
01658         }
01659     }
01660
01661     // create the faces
01662
01663     GeoUInt32Property::StoredFieldType *i  = index->editFieldPtr();
01664     GeoUInt32Property::StoredFieldType *l  = lens ->editFieldPtr();
01665     GeoUInt8Property::StoredFieldType  *t  = types->editFieldPtr();
01666
01667     UInt32 basepoint = 0;
01668
01669     for(pl = 0; pl < 6; pl++)
01670     {
01671         for(y = 0; y < res[inds[pl][1]]; y++)
01672         {
01673             UInt16 h = UInt16(res[inds[pl][0]]);
01674
01675             t->push_back(GL_TRIANGLE_STRIP);
01676             l->push_back(2 * (h + 1));
01677
01678             for(x = 0; x <= h; x++)
01679             {
01680                 i->push_back(basepoint + (y + 1) * (h + 1) + x);
01681                 i->push_back(basepoint +  y      * (h + 1) + x);
01682             }
01683         }
01684         basepoint += UInt32((res[inds[pl][0]] + 1.f) *
01685                             (res[inds[pl][1]] + 1.f) );
01686     }
01687
01688     // create the geometry
01689
01690     GeometryTransitPtr geo = Geometry::create();
01691
01692     geo->setMaterial(getDefaultMaterial());
01693     geo->setPositions(pnts);
01694     geo->setNormals(norms);
01695     geo->setTexCoords(tex);
01696     geo->setIndices(index);
01697     geo->setTypes(types);
01698     geo->setLengths(lens);
01699
01700     return geo;
01701 }
01702
01711 NodeTransitPtr makeTeapot(UInt16 depth, Real32 rScale)
01712 {
01713     GeometryTransitPtr pGeo = makeTeapotGeo(depth, rScale);
01714
01715     if(pGeo == NULL)
01716     {
01717         return NodeTransitPtr(NULL);
01718     }
01719
01720     NodeTransitPtr node = Node::create();
01721
01722     node->setCore(pGeo);
01723
01724     return node;
01725 }
01726
01727 namespace {
01728
01729 // Teapot data and helper functions
01730
01731 /* Teapot function. Taken from Eric Haines' SPD package
01732    (http://www1.acm.org/tog/resources/SPD)
01733 
01734    Slightly C++-ized for OpenSG
01735  */
01736
01737 /* comment out the next line to generate all patches except the bottom,
01738  * i.e. the original Newell teapot
01739  */
01740 #define BOTTOM
01741 
01742 #ifdef BOTTOM
01743 #define NUM_PATCHES 32
01744 #else
01745 #define NUM_PATCHES 28
01746 #endif
01747 
01748 static int Patches[32][4][4] = {
01749 /* rim */
01750 {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}, {12, 13, 14, 15}},
01751 {{3, 16, 17, 18}, {7, 19, 20, 21}, {11, 22, 23, 24}, {15, 25, 26, 27}},
01752 {{18, 28, 29, 30}, {21, 31, 32, 33}, {24, 34, 35, 36}, {27, 37, 38, 39}},
01753 {{30, 40, 41, 0}, {33, 42, 43, 4}, {36, 44, 45, 8}, {39, 46, 47, 12}},
01754 /* body */
01755 {{12, 13, 14, 15}, {48, 49, 50, 51}, {52, 53, 54, 55}, {56, 57, 58, 59}},
01756 {{15, 25, 26, 27}, {51, 60, 61, 62}, {55, 63, 64, 65}, {59, 66, 67, 68}},
01757 {{27, 37, 38, 39}, {62, 69, 70, 71}, {65, 72, 73, 74}, {68, 75, 76, 77}},
01758 {{39, 46, 47, 12}, {71, 78, 79, 48}, {74, 80, 81, 52}, {77, 82, 83, 56}},
01759 {{56, 57, 58, 59}, {84, 85, 86, 87}, {88, 89, 90, 91}, {92, 93, 94, 95}},
01760 {{59, 66, 67, 68}, {87, 96, 97, 98}, {91, 99, 100, 101}, {95, 102, 103, 104}},
01761 {{68, 75, 76, 77}, {98, 105, 106, 107}, {101, 108, 109, 110}, {104, 111, 112, 113}},
01762 {{77, 82, 83, 56}, {107, 114, 115, 84}, {110, 116, 117, 88}, {113, 118, 119, 92}},
01763 /* handle */
01764 {{120, 121, 122, 123}, {124, 125, 126, 127}, {128, 129, 130, 131}, {132, 133, 134, 135}},
01765 {{123, 136, 137, 120}, {127, 138, 139, 124}, {131, 140, 141, 128}, {135, 142, 143, 132}},
01766 {{132, 133, 134, 135}, {144, 145, 146, 147}, {148, 149, 150, 151}, {68, 152, 153, 154}},
01767 {{135, 142, 143, 132}, {147, 155, 156, 144}, {151, 157, 158, 148}, {154, 159, 160, 68}},
01768 /* spout */
01769 {{161, 162, 163, 164}, {165, 166, 167, 168}, {169, 170, 171, 172}, {173, 174, 175, 176}},
01770 {{164, 177, 178, 161}, {168, 179, 180, 165}, {172, 181, 182, 169}, {176, 183, 184, 173}},
01771 {{173, 174, 175, 176}, {185, 186, 187, 188}, {189, 190, 191, 192}, {193, 194, 195, 196}},
01772 {{176, 183, 184, 173}, {188, 197, 198, 185}, {192, 199, 200, 189}, {196, 201, 202, 193}},
01773 /* lid */
01774 {{203, 203, 203, 203}, {204, 205, 206, 207}, {208, 208, 208, 208}, {209, 210, 211, 212}},
01775 {{203, 203, 203, 203}, {207, 213, 214, 215}, {208, 208, 208, 208}, {212, 216, 217, 218}},
01776 {{203, 203, 203, 203}, {215, 219, 220, 221}, {208, 208, 208, 208}, {218, 222, 223, 224}},
01777 {{203, 203, 203, 203}, {221, 225, 226, 204}, {208, 208, 208, 208}, {224, 227, 228, 209}},
01778 {{209, 210, 211, 212}, {229, 230, 231, 232}, {233, 234, 235, 236}, {237, 238, 239, 240}},
01779 {{212, 216, 217, 218}, {232, 241, 242, 243}, {236, 244, 245, 246}, {240, 247, 248, 249}},
01780 {{218, 222, 223, 224}, {243, 250, 251, 252}, {246, 253, 254, 255}, {249, 256, 257, 258}},
01781 {{224, 227, 228, 209}, {252, 259, 260, 229}, {255, 261, 262, 233}, {258, 263, 264, 237}},
01782 /* bottom */
01783 {{265, 265, 265, 265}, {266, 267, 268, 269}, {270, 271, 272, 273}, {92, 119, 118, 113}},
01784 {{265, 265, 265, 265}, {269, 274, 275, 276}, {273, 277, 278, 279}, {113, 112, 111, 104}},
01785 {{265, 265, 265, 265}, {276, 280, 281, 282}, {279, 283, 284, 285}, {104, 103, 102, 95}},
01786 {{265, 265, 265, 265}, {282, 286, 287, 266}, {285, 288, 289, 270}, {95, 94, 93, 92}}
01787 };
01788
01789 static Vec3f Verts[290] = {
01790     Vec3f(1.4, 0, 2.4),
01791     Vec3f(1.4, -0.784, 2.4),
01792     Vec3f(0.784, -1.4, 2.4),
01793     Vec3f(0, -1.4, 2.4),
01794     Vec3f(1.3375, 0, 2.53125),
01795     Vec3f(1.3375, -0.749, 2.53125),
01796     Vec3f(0.749, -1.3375, 2.53125),
01797     Vec3f(0, -1.3375, 2.53125),
01798     Vec3f(1.4375, 0, 2.53125),
01799     Vec3f(1.4375, -0.805, 2.53125),
01800     Vec3f(0.805, -1.4375, 2.53125),
01801     Vec3f(0, -1.4375, 2.53125),
01802     Vec3f(1.5, 0, 2.4),
01803     Vec3f(1.5, -0.84, 2.4),
01804     Vec3f(0.84, -1.5, 2.4),
01805     Vec3f(0, -1.5, 2.4),
01806     Vec3f(-0.784, -1.4, 2.4),
01807     Vec3f(-1.4, -0.784, 2.4),
01808     Vec3f(-1.4, 0, 2.4),
01809     Vec3f(-0.749, -1.3375, 2.53125),
01810     Vec3f(-1.3375, -0.749, 2.53125),
01811     Vec3f(-1.3375, 0, 2.53125),
01812     Vec3f(-0.805, -1.4375, 2.53125),
01813     Vec3f(-1.4375, -0.805, 2.53125),
01814     Vec3f(-1.4375, 0, 2.53125),
01815     Vec3f(-0.84, -1.5, 2.4),
01816     Vec3f(-1.5, -0.84, 2.4),
01817     Vec3f(-1.5, 0, 2.4),
01818     Vec3f(-1.4, 0.784, 2.4),
01819     Vec3f(-0.784, 1.4, 2.4),
01820     Vec3f(0, 1.4, 2.4),
01821     Vec3f(-1.3375, 0.749, 2.53125),
01822     Vec3f(-0.749, 1.3375, 2.53125),
01823     Vec3f(0, 1.3375, 2.53125),
01824     Vec3f(-1.4375, 0.805, 2.53125),
01825     Vec3f(-0.805, 1.4375, 2.53125),
01826     Vec3f(0, 1.4375, 2.53125),
01827     Vec3f(-1.5, 0.84, 2.4),
01828     Vec3f(-0.84, 1.5, 2.4),
01829     Vec3f(0, 1.5, 2.4),
01830     Vec3f(0.784, 1.4, 2.4),
01831     Vec3f(1.4, 0.784, 2.4),
01832     Vec3f(0.749, 1.3375, 2.53125),
01833     Vec3f(1.3375, 0.749, 2.53125),
01834     Vec3f(0.805, 1.4375, 2.53125),
01835     Vec3f(1.4375, 0.805, 2.53125),
01836     Vec3f(0.84, 1.5, 2.4),
01837     Vec3f(1.5, 0.84, 2.4),
01838     Vec3f(1.75, 0, 1.875),
01839     Vec3f(1.75, -0.98, 1.875),
01840     Vec3f(0.98, -1.75, 1.875),
01841     Vec3f(0, -1.75, 1.875),
01842     Vec3f(2, 0, 1.35),
01843     Vec3f(2, -1.12, 1.35),
01844     Vec3f(1.12, -2, 1.35),
01845     Vec3f(0, -2, 1.35),
01846     Vec3f(2, 0, 0.9),
01847     Vec3f(2, -1.12, 0.9),
01848     Vec3f(1.12, -2, 0.9),
01849     Vec3f(0, -2, 0.9),
01850     Vec3f(-0.98, -1.75, 1.875),
01851     Vec3f(-1.75, -0.98, 1.875),
01852     Vec3f(-1.75, 0, 1.875),
01853     Vec3f(-1.12, -2, 1.35),
01854     Vec3f(-2, -1.12, 1.35),
01855     Vec3f(-2, 0, 1.35),
01856     Vec3f(-1.12, -2, 0.9),
01857     Vec3f(-2, -1.12, 0.9),
01858     Vec3f(-2, 0, 0.9),
01859     Vec3f(-1.75, 0.98, 1.875),
01860     Vec3f(-0.98, 1.75, 1.875),
01861     Vec3f(0, 1.75, 1.875),
01862     Vec3f(-2, 1.12, 1.35),
01863     Vec3f(-1.12, 2, 1.35),
01864     Vec3f(0, 2, 1.35),
01865     Vec3f(-2, 1.12, 0.9),
01866     Vec3f(-1.12, 2, 0.9),
01867     Vec3f(0, 2, 0.9),
01868     Vec3f(0.98, 1.75, 1.875),
01869     Vec3f(1.75, 0.98, 1.875),
01870     Vec3f(1.12, 2, 1.35),
01871     Vec3f(2, 1.12, 1.35),
01872     Vec3f(1.12, 2, 0.9),
01873     Vec3f(2, 1.12, 0.9),
01874     Vec3f(2, 0, 0.45),
01875     Vec3f(2, -1.12, 0.45),
01876     Vec3f(1.12, -2, 0.45),
01877     Vec3f(0, -2, 0.45),
01878     Vec3f(1.5, 0, 0.225),
01879     Vec3f(1.5, -0.84, 0.225),
01880     Vec3f(0.84, -1.5, 0.225),
01881     Vec3f(0, -1.5, 0.225),
01882     Vec3f(1.5, 0, 0.15),
01883     Vec3f(1.5, -0.84, 0.15),
01884     Vec3f(0.84, -1.5, 0.15),
01885     Vec3f(0, -1.5, 0.15),
01886     Vec3f(-1.12, -2, 0.45),
01887     Vec3f(-2, -1.12, 0.45),
01888     Vec3f(-2, 0, 0.45),
01889     Vec3f(-0.84, -1.5, 0.225),
01890     Vec3f(-1.5, -0.84, 0.225),
01891     Vec3f(-1.5, 0, 0.225),
01892     Vec3f(-0.84, -1.5, 0.15),
01893     Vec3f(-1.5, -0.84, 0.15),
01894     Vec3f(-1.5, 0, 0.15),
01895     Vec3f(-2, 1.12, 0.45),
01896     Vec3f(-1.12, 2, 0.45),
01897     Vec3f(0, 2, 0.45),
01898     Vec3f(-1.5, 0.84, 0.225),
01899     Vec3f(-0.84, 1.5, 0.225),
01900     Vec3f(0, 1.5, 0.225),
01901     Vec3f(-1.5, 0.84, 0.15),
01902     Vec3f(-0.84, 1.5, 0.15),
01903     Vec3f(0, 1.5, 0.15),
01904     Vec3f(1.12, 2, 0.45),
01905     Vec3f(2, 1.12, 0.45),
01906     Vec3f(0.84, 1.5, 0.225),
01907     Vec3f(1.5, 0.84, 0.225),
01908     Vec3f(0.84, 1.5, 0.15),
01909     Vec3f(1.5, 0.84, 0.15),
01910     Vec3f(-1.6, 0, 2.025),
01911     Vec3f(-1.6, -0.3, 2.025),
01912     Vec3f(-1.5, -0.3, 2.25),
01913     Vec3f(-1.5, 0, 2.25),
01914     Vec3f(-2.3, 0, 2.025),
01915     Vec3f(-2.3, -0.3, 2.025),
01916     Vec3f(-2.5, -0.3, 2.25),
01917     Vec3f(-2.5, 0, 2.25),
01918     Vec3f(-2.7, 0, 2.025),
01919     Vec3f(-2.7, -0.3, 2.025),
01920     Vec3f(-3, -0.3, 2.25),
01921     Vec3f(-3, 0, 2.25),
01922     Vec3f(-2.7, 0, 1.8),
01923     Vec3f(-2.7, -0.3, 1.8),
01924     Vec3f(-3, -0.3, 1.8),
01925     Vec3f(-3, 0, 1.8),
01926     Vec3f(-1.5, 0.3, 2.25),
01927     Vec3f(-1.6, 0.3, 2.025),
01928     Vec3f(-2.5, 0.3, 2.25),
01929     Vec3f(-2.3, 0.3, 2.025),
01930     Vec3f(-3, 0.3, 2.25),
01931     Vec3f(-2.7, 0.3, 2.025),
01932     Vec3f(-3, 0.3, 1.8),
01933     Vec3f(-2.7, 0.3, 1.8),
01934     Vec3f(-2.7, 0, 1.575),
01935     Vec3f(-2.7, -0.3, 1.575),
01936     Vec3f(-3, -0.3, 1.35),
01937     Vec3f(-3, 0, 1.35),
01938     Vec3f(-2.5, 0, 1.125),
01939     Vec3f(-2.5, -0.3, 1.125),
01940     Vec3f(-2.65, -0.3, 0.9375),
01941     Vec3f(-2.65, 0, 0.9375),
01942     Vec3f(-2, -0.3, 0.9),
01943     Vec3f(-1.9, -0.3, 0.6),
01944     Vec3f(-1.9, 0, 0.6),
01945     Vec3f(-3, 0.3, 1.35),
01946     Vec3f(-2.7, 0.3, 1.575),
01947     Vec3f(-2.65, 0.3, 0.9375),
01948     Vec3f(-2.5, 0.3, 1.125),
01949     Vec3f(-1.9, 0.3, 0.6),
01950     Vec3f(-2, 0.3, 0.9),
01951     Vec3f(1.7, 0, 1.425),
01952     Vec3f(1.7, -0.66, 1.425),
01953     Vec3f(1.7, -0.66, 0.6),
01954     Vec3f(1.7, 0, 0.6),
01955     Vec3f(2.6, 0, 1.425),
01956     Vec3f(2.6, -0.66, 1.425),
01957     Vec3f(3.1, -0.66, 0.825),
01958     Vec3f(3.1, 0, 0.825),
01959     Vec3f(2.3, 0, 2.1),
01960     Vec3f(2.3, -0.25, 2.1),
01961     Vec3f(2.4, -0.25, 2.025),
01962     Vec3f(2.4, 0, 2.025),
01963     Vec3f(2.7, 0, 2.4),
01964     Vec3f(2.7, -0.25, 2.4),
01965     Vec3f(3.3, -0.25, 2.4),
01966     Vec3f(3.3, 0, 2.4),
01967     Vec3f(1.7, 0.66, 0.6),
01968     Vec3f(1.7, 0.66, 1.425),
01969     Vec3f(3.1, 0.66, 0.825),
01970     Vec3f(2.6, 0.66, 1.425),
01971     Vec3f(2.4, 0.25, 2.025),
01972     Vec3f(2.3, 0.25, 2.1),
01973     Vec3f(3.3, 0.25, 2.4),
01974     Vec3f(2.7, 0.25, 2.4),
01975     Vec3f(2.8, 0, 2.475),
01976     Vec3f(2.8, -0.25, 2.475),
01977     Vec3f(3.525, -0.25, 2.49375),
01978     Vec3f(3.525, 0, 2.49375),
01979     Vec3f(2.9, 0, 2.475),
01980     Vec3f(2.9, -0.15, 2.475),
01981     Vec3f(3.45, -0.15, 2.5125),
01982     Vec3f(3.45, 0, 2.5125),
01983     Vec3f(2.8, 0, 2.4),
01984     Vec3f(2.8, -0.15, 2.4),
01985     Vec3f(3.2, -0.15, 2.4),
01986     Vec3f(3.2, 0, 2.4),
01987     Vec3f(3.525, 0.25, 2.49375),
01988     Vec3f(2.8, 0.25, 2.475),
01989     Vec3f(3.45, 0.15, 2.5125),
01990     Vec3f(2.9, 0.15, 2.475),
01991     Vec3f(3.2, 0.15, 2.4),
01992     Vec3f(2.8, 0.15, 2.4),
01993     Vec3f(0, 0, 3.15),
01994     Vec3f(0.8, 0, 3.15),
01995     Vec3f(0.8, -0.45, 3.15),
01996     Vec3f(0.45, -0.8, 3.15),
01997     Vec3f(0, -0.8, 3.15),
01998     Vec3f(0, 0, 2.85),
01999     Vec3f(0.2, 0, 2.7),
02000     Vec3f(0.2, -0.112, 2.7),
02001     Vec3f(0.112, -0.2, 2.7),
02002     Vec3f(0, -0.2, 2.7),
02003     Vec3f(-0.45, -0.8, 3.15),
02004     Vec3f(-0.8, -0.45, 3.15),
02005     Vec3f(-0.8, 0, 3.15),
02006     Vec3f(-0.112, -0.2, 2.7),
02007     Vec3f(-0.2, -0.112, 2.7),
02008     Vec3f(-0.2, 0, 2.7),
02009     Vec3f(-0.8, 0.45, 3.15),
02010     Vec3f(-0.45, 0.8, 3.15),
02011     Vec3f(0, 0.8, 3.15),
02012     Vec3f(-0.2, 0.112, 2.7),
02013     Vec3f(-0.112, 0.2, 2.7),
02014     Vec3f(0, 0.2, 2.7),
02015     Vec3f(0.45, 0.8, 3.15),
02016     Vec3f(0.8, 0.45, 3.15),
02017     Vec3f(0.112, 0.2, 2.7),
02018     Vec3f(0.2, 0.112, 2.7),
02019     Vec3f(0.4, 0, 2.55),
02020     Vec3f(0.4, -0.224, 2.55),
02021     Vec3f(0.224, -0.4, 2.55),
02022     Vec3f(0, -0.4, 2.55),
02023     Vec3f(1.3, 0, 2.55),
02024     Vec3f(1.3, -0.728, 2.55),
02025     Vec3f(0.728, -1.3, 2.55),
02026     Vec3f(0, -1.3, 2.55),
02027     Vec3f(1.3, 0, 2.4),
02028     Vec3f(1.3, -0.728, 2.4),
02029     Vec3f(0.728, -1.3, 2.4),
02030     Vec3f(0, -1.3, 2.4),
02031     Vec3f(-0.224, -0.4, 2.55),
02032     Vec3f(-0.4, -0.224, 2.55),
02033     Vec3f(-0.4, 0, 2.55),
02034     Vec3f(-0.728, -1.3, 2.55),
02035     Vec3f(-1.3, -0.728, 2.55),
02036     Vec3f(-1.3, 0, 2.55),
02037     Vec3f(-0.728, -1.3, 2.4),
02038     Vec3f(-1.3, -0.728, 2.4),
02039     Vec3f(-1.3, 0, 2.4),
02040     Vec3f(-0.4, 0.224, 2.55),
02041     Vec3f(-0.224, 0.4, 2.55),
02042     Vec3f(0, 0.4, 2.55),
02043     Vec3f(-1.3, 0.728, 2.55),
02044     Vec3f(-0.728, 1.3, 2.55),
02045     Vec3f(0, 1.3, 2.55),
02046     Vec3f(-1.3, 0.728, 2.4),
02047     Vec3f(-0.728, 1.3, 2.4),
02048     Vec3f(0, 1.3, 2.4),
02049     Vec3f(0.224, 0.4, 2.55),
02050     Vec3f(0.4, 0.224, 2.55),
02051     Vec3f(0.728, 1.3, 2.55),
02052     Vec3f(1.3, 0.728, 2.55),
02053     Vec3f(0.728, 1.3, 2.4),
02054     Vec3f(1.3, 0.728, 2.4),
02055     Vec3f(0, 0, 0),
02056     Vec3f(1.425, 0, 0),
02057     Vec3f(1.425, 0.798, 0),
02058     Vec3f(0.798, 1.425, 0),
02059     Vec3f(0, 1.425, 0),
02060     Vec3f(1.5, 0, 0.075),
02061     Vec3f(1.5, 0.84, 0.075),
02062     Vec3f(0.84, 1.5, 0.075),
02063     Vec3f(0, 1.5, 0.075),
02064     Vec3f(-0.798, 1.425, 0),
02065     Vec3f(-1.425, 0.798, 0),
02066     Vec3f(-1.425, 0, 0),
02067     Vec3f(-0.84, 1.5, 0.075),
02068     Vec3f(-1.5, 0.84, 0.075),
02069     Vec3f(-1.5, 0, 0.075),
02070     Vec3f(-1.425, -0.798, 0),
02071     Vec3f(-0.798, -1.425, 0),
02072     Vec3f(0, -1.425, 0),
02073     Vec3f(-1.5, -0.84, 0.075),
02074     Vec3f(-0.84, -1.5, 0.075),
02075     Vec3f(0, -1.5, 0.075),
02076     Vec3f(0.798, -1.425, 0),
02077     Vec3f(1.425, -0.798, 0),
02078     Vec3f(0.84, -1.5, 0.075),
02079     Vec3f(1.5, -0.84, 0.075)
02080 };
02081
02082 /* at the center of the lid's handle and at bottom are cusp points -
02083  * check if normal is (0 0 0), if so, check that polygon is not degenerate.
02084  * If degenerate, return FALSE, else set normal.
02085  */
02086 static bool
02087 check_for_cusp( int tot_vert, Pnt3f vert[], Vec3f norm[] )
02088 {
02089     int count, i, nv ;
02090
02091     for(count = 0, i = tot_vert; i--; )
02092     {
02093         /* check if vertex is at cusp */
02094         if(osgAbs(vert[i][0]) < 0.0001 &&
02095            osgAbs(vert[i][1]) < 0.0001    )
02096         {
02097             count++;
02098             nv = i;
02099         }
02100     }
02101
02102     if(count > 1)
02103     {
02104         /* degenerate */
02105         return  false;
02106     }
02107     if(count == 1)
02108     {
02109         /* check if point is somewhere above the middle of the teapot */
02110         if(vert[nv][2] > 1.5)
02111         {
02112             /* cusp at lid */
02113             norm[nv].setValues(0.0, 0.0, 1.0);
02114         }
02115         else
02116         {
02117             /* cusp at bottom */
02118             norm[nv].setValues(0.0, 0.0, -1.0);
02119         }
02120     }
02121     return true;
02122 }
02123
02124 static void
02125 points_from_basis(int tot_vert, Real64 s[], Real64 t[], Matrix mgm[3],
02126     Pnt3f vert[], Vec3f norm[] )
02127 {
02128     int    i, num_vert, p;
02129     double sval, tval, dsval, dtval, sxyz, txyz;
02130     Vec3f  sdir, tdir;
02131     Vec4f  sp, tp, dsp, dtp, tcoord;
02132
02133     for(num_vert = 0; num_vert < tot_vert; num_vert++)
02134     {
02135         sxyz = s[num_vert] ;
02136         txyz = t[num_vert] ;
02137
02138         /* get power vectors and their derivatives */
02139         for(p = 4, sval = tval = 1.0; p--; )
02140         {
02141             sp[p] = sval;
02142             tp[p] = tval;
02143             sval *= sxyz;
02144             tval *= txyz;
02145
02146             if(p == 3)
02147             {
02148                 dsp[p] = dtp[p] = 0.0;
02149                 dsval  = dtval  = 1.0;
02150             }
02151             else
02152             {
02153                 dsp[p] = dsval * static_cast<double>(3 - p);
02154                 dtp[p] = dtval * static_cast<double>(3 - p);
02155                 dsval *= sxyz;
02156                 dtval *= txyz;
02157             }
02158         }
02159
02160         /* do for x,y,z */
02161         for(i = 0; i < 3; ++i)
02162         {
02163             /* multiply power vectors times matrix to get value */
02164             mgm[i].mult(sp, tcoord);
02165             vert[num_vert][i] = tcoord.dot(tp);
02166
02167             /* get s and t tangent vectors */
02168             mgm[i].mult(dsp, tcoord);
02169             sdir[i] = tcoord.dot(tp);
02170
02171             mgm[i].mult(sp, tcoord);
02172             tdir[i] = tcoord.dot(dtp);
02173         }
02174
02175         /* find normal */
02176         norm[num_vert] = tdir.cross(sdir);
02177         norm[num_vert].normalize();
02178     }
02179 }
02180
02181 } // namespace
02182
02192 GeometryTransitPtr makeTeapotGeo(UInt16 depth, Real32 rScale)
02193 {
02194     GeoPnt3fPropertyUnrecPtr  pnts  = GeoPnt3fProperty ::create();
02195     GeoVec3fPropertyUnrecPtr  norms = GeoVec3fProperty ::create();
02196     GeoUInt32PropertyUnrecPtr lens  = GeoUInt32Property::create();
02197     GeoUInt8PropertyUnrecPtr  types = GeoUInt8Property ::create();
02198
02199     // calc the triangles
02200
02201     GeoPnt3fProperty::StoredFieldType  *p  = pnts ->editFieldPtr();
02202     GeoVec3fProperty::StoredFieldType  *n  = norms->editFieldPtr();
02203
02204     UInt32 vcount = 0;
02205
02206     /* bezier form */
02207     static Matrix ms( -1.0,  3.0, -3.0,  1.0,
02208                        3.0, -6.0,  3.0,  0.0,
02209                       -3.0,  3.0,  0.0,  0.0,
02210                        1.0,  0.0,  0.0,  0.0 );
02211     int    surf, i, r, c, sstep, tstep, num_tri, num_vert, num_tri_vert;
02212     double s[3], t[3];
02213     Pnt3f  vert[4];
02214     Vec3f  norm[4];
02215     Matrix mst, g, mgm[3], tmtx;
02216
02217     mst.transposeFrom(ms);
02218
02219     for(surf = 0; surf < NUM_PATCHES; ++surf)
02220     {
02221         /* get M * G * M matrix for x,y,z */
02222         for(i = 0; i < 3; ++i)
02223         {
02224             /* get control patches */
02225             for(r = 0; r < 4 ; ++r)
02226             {
02227                 for(c = 0; c < 4; ++c)
02228                 {
02229                     g[r][c] = Verts[Patches[surf][r][c]][i];
02230                 }
02231             }
02232
02233             tmtx = ms;
02234             tmtx.mult(g);
02235             tmtx.mult(mst);
02236             mgm[i] = tmtx;
02237         }
02238
02239         /* step along, get points, and output */
02240         for(sstep = 0; sstep < depth; ++sstep)
02241         {
02242             for(tstep = 0; tstep < depth; ++tstep)
02243             {
02244                 for(num_tri = 0; num_tri < 2; ++num_tri)
02245                 {
02246                     for(num_vert = 0; num_vert < 3; ++num_vert)
02247                     {
02248                         num_tri_vert = (num_vert + num_tri * 2) % 4;
02249                         /* trickiness: add 1 to sstep if 1 or 2 */
02250                         s[num_vert] = static_cast<double>(
02251                                         sstep + (num_tri_vert / 2 ? 1 : 0)) /
02252                                             static_cast<double>(depth);
02253
02254                         /* trickiness: add 1 to tstep if 2 or 3 */
02255                         t[num_vert] = static_cast<double>(
02256                                         tstep + (num_tri_vert % 3 ? 1 : 0)) /
02257                                             static_cast<double>(depth);
02258                     }
02259                     points_from_basis(3, s, t, mgm, vert, norm);
02260                     /* don't output degenerate polygons */
02261                     if(check_for_cusp( 3, vert, norm))
02262                     {
02263                         vert[0] *= rScale;
02264                         vert[1] *= rScale;
02265                         vert[2] *= rScale;
02266
02267                         p->push_back(vert[0]);
02268                         p->push_back(vert[1]);
02269                         p->push_back(vert[2]);
02270
02271                         n->push_back(norm[0]);
02272                         n->push_back(norm[1]);
02273                         n->push_back(norm[2]);
02274
02275                         vcount += 3;
02276                     }
02277                 }
02278             }
02279         }
02280     }
02281
02282     types->push_back(GL_TRIANGLES);
02283     lens ->push_back(vcount);
02284
02285     // create the geometry
02286
02287     GeometryTransitPtr geo = Geometry::create();
02288
02289     geo->setMaterial(getDefaultMaterial());
02290     geo->setPositions(pnts);
02291     geo->setNormals(norms);
02292     geo->setTypes(types);
02293     geo->setLengths(lens);
02294
02295     return geo;
02296 }
02297
02298 NodeTransitPtr makeCoordAxis(Real32 length, Real32 lineWidth, bool showAxisName)
02299 {
02300     GeometryTransitPtr pGeo = makeCoordAxisGeo(length, lineWidth, showAxisName);
02301
02302     if(pGeo == NULL)
02303     {
02304         return NodeTransitPtr(NULL);
02305     }
02306
02307     NodeTransitPtr node = Node::create();
02308
02309     node->setCore(pGeo);
02310
02311     return node;
02312 }
02313
02314 GeometryTransitPtr makeCoordAxisGeo(Real32 length,
02315                                     Real32 lineWidth,
02316                                     bool   showAxisName)
02317 {
02318     GeoPnt3fPropertyUnrecPtr   pnts    = GeoPnt3fProperty ::create();
02319     GeoUInt32PropertyUnrecPtr  lens    = GeoUInt32Property::create();
02320     GeoUInt8PropertyUnrecPtr   types   = GeoUInt8Property ::create();
02321     GeoColor3fPropertyUnrecPtr colors  = GeoColor3fProperty::create();
02322
02323     Int32 pntCnt=0;
02324
02325     GeoPnt3fProperty::StoredFieldType   *p = pnts ->editFieldPtr();
02326     GeoUInt32Property::StoredFieldType  *l = lens ->editFieldPtr();
02327     GeoUInt8Property::StoredFieldType   *t = types->editFieldPtr();
02328     GeoColor3fProperty::StoredFieldType *c = colors->editFieldPtr();
02329
02330     // the x-axis coords and colors
02331     p->push_back( Pnt3f(0,0,0) );
02332     p->push_back( Pnt3f(length,0,0) );
02333     pntCnt += 2;
02334     c->push_back( Color3f(1,0,0) );
02335     c->push_back( Color3f(1,0,0) );
02336
02337     // the y-axis coords and colors
02338     p->push_back( Pnt3f(0,0,0) );
02339     p->push_back( Pnt3f(0,length,0) );
02340     pntCnt += 2;
02341     c->push_back( Color3f(0,1,0) );
02342     c->push_back( Color3f(0,1,0) );
02343
02344     // the z-axis coords and colors
02345     p->push_back( Pnt3f(0,0,0) );
02346     p->push_back( Pnt3f(0,0,length) );
02347     pntCnt += 2;
02348     c->push_back( Color3f(0,0,1) );
02349     c->push_back( Color3f(0,0,1) );
02350
02351     if( showAxisName )
02352     {
02353        // the x text (drawn with lines)
02354        p->push_back( Pnt3f(length,         0.125,    0) );
02355        p->push_back( Pnt3f(length+0.25,    -0.125,    0) );
02356        p->push_back( Pnt3f(length,-0.125,0) );
02357        p->push_back( Pnt3f(length+0.25,0.125,0) );
02358        pntCnt += 4;
02359        for (unsigned i=0;i<4;i++)
02360        { c->push_back( Color3f(1,0,0) ); }
02361
02362        // the y text (drawn with lines)
02363        p->push_back( Pnt3f(-0.125, length,        0) );
02364        p->push_back( Pnt3f( 0.125, length+0.25,    0) );
02365        p->push_back( Pnt3f(-0.125, length+0.25,        0) );
02366        p->push_back( Pnt3f( 0.000, length+0.125,0) );
02367        pntCnt += 4;
02368        for (unsigned i=0;i<4;i++)
02369        { c->push_back( Color3f(0,1,0) ); }
02370
02371        // the z text (drawn with lines)
02372        p->push_back( Pnt3f(-0.125, 0,    length) );
02373        p->push_back( Pnt3f( 0.125, 0,    length) );
02374        p->push_back( Pnt3f( 0.125, 0,    length) );
02375        p->push_back( Pnt3f(-0.125, 0,    length+0.25) );
02376        p->push_back( Pnt3f(-0.125, 0,    length+0.25) );
02377        p->push_back( Pnt3f( 0.125, 0,    length+0.25) );
02378        pntCnt += 6;
02379        for (unsigned i=0;i<6;i++)
02380        { c->push_back( Color3f(0,0,1) ); }
02381     }
02382
02383
02384     //SLOG << "CoordAxis has " << pntCnt << " points.\n" << endl;
02385     t->push_back(GL_LINES);
02386     l->push_back(pntCnt);
02387
02388     LineChunkUnrecPtr      lineChunk = LineChunk::create();
02389
02390     lineChunk->setWidth(lineWidth);
02391
02392     SimpleMaterialUnrecPtr mat      = SimpleMaterial::create();
02393
02394     mat->setLit(false);
02395     mat->addChunk(lineChunk);
02396     mat->setColorMaterial(GL_AMBIENT_AND_DIFFUSE);
02397
02398
02399     GeometryTransitPtr geo = Geometry::create();
02400     geo->setMaterial(mat);
02401     geo->setPositions(pnts);
02402     geo->setTypes(types);
02403     geo->setLengths(lens);
02404     geo->setColors(colors);
02405
02406     return geo;
02407 }
02408 OSG_END_NAMESPACE