changed: gcc8 base update
[opensg.git] / Source / System / NodeCores / Drawables / Geometry / Util / OSGSimpleGeometry.cpp
blob9219468c67686262cbda4fac31aa449985954e60
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
6 * *
7 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
8 * *
9 \*---------------------------------------------------------------------------*/
10 /*---------------------------------------------------------------------------*\
11 * License *
12 * *
13 * This library is free software; you can redistribute it and/or modify it *
14 * under the terms of the GNU Library General Public License as published *
15 * by the Free Software Foundation, version 2. *
16 * *
17 * This library is distributed in the hope that it will be useful, but *
18 * WITHOUT ANY WARRANTY; without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
20 * Library General Public License for more details. *
21 * *
22 * You should have received a copy of the GNU Library General Public *
23 * License along with this library; if not, write to the Free Software *
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
25 * *
26 \*---------------------------------------------------------------------------*/
27 /*---------------------------------------------------------------------------*\
28 * Changes *
29 * *
30 * *
31 * *
32 * *
33 * *
34 * *
35 \*---------------------------------------------------------------------------*/
37 #ifdef WIN32
38 #pragma warning( disable : 4305 )
39 #endif
41 //---------------------------------------------------------------------------
42 // Includes
43 //---------------------------------------------------------------------------
45 #include <cstdlib>
46 #include <cstdio>
48 #include "OSGConfig.h"
49 #include "OSGLog.h"
50 #include "OSGQuaternion.h"
51 #include "OSGMaterial.h"
52 #include "OSGSimpleMaterial.h"
53 #include "OSGLineChunk.h"
54 #include "OSGGeoProperties.h"
55 #include "OSGSimpleGeometry.h" // for DefaultMaterials
56 #include "OSGTypedGeoIntegralProperty.h"
57 #include "OSGTypedGeoVectorProperty.h"
59 //#include "OSGTriangleIterator.h"
61 OSG_BEGIN_NAMESPACE
63 /***************************************************************************\
64 * Description *
65 \***************************************************************************/
67 #if defined(OSG_WIN32_ICL) && !defined(OSG_CHECK_FIELDSETARG)
68 #pragma warning (disable : 383)
69 #endif
71 // The Simple Geometry creation functions
73 /*! Creates a plane in the x/y plane. It spans the [-\a xsize /2,\a
74 xsize /2] x [-\a ysize /2,\a ysize/2] area and is subdivided into \a hor *
75 \a vert quads.
77 \param[in] xsize Length of plane edge in x direction.
78 \param[in] ysize Length of plane edge in y direction.
79 \param[in] hor Number of quads in x direction.
80 \param[in] vert Number of quads in y direction.
81 \return NodeTransitPtr to a newly created Node with a Geometry core.
83 \ingroup GrpDrawablesGeometryUtils
85 NodeTransitPtr makePlane(Real32 xsize, Real32 ysize, UInt16 hor, UInt16 vert)
87 GeometryTransitPtr pGeo = makePlaneGeo(xsize, ysize, hor, vert);
89 if(pGeo == NULL)
91 return NodeTransitPtr(NULL);
94 NodeTransitPtr node = Node::create();
96 node->setCore(pGeo);
98 return node;
101 /*! Create the Geometry core used by OSG::makePlane.
103 \param[in] xsize Length of plane edge in x direction.
104 \param[in] ysize Length of plane edge in y direction.
105 \param[in] hor Number of quads in x direction.
106 \param[in] vert Number of quads in y direction.
107 \return GeometryTransitPtr to a newly created Geometry core.
109 \sa OSG::makePlane
111 \ingroup GrpDrawablesGeometryUtils
113 GeometryTransitPtr makePlaneGeo(Real32 xsize, Real32 ysize,
114 UInt16 hor, UInt16 vert)
116 if(! hor || ! vert)
118 SWARNING << "makePlane: illegal parameters hor=" << hor << ", vert="
119 << vert << std::endl;
120 return GeometryTransitPtr(NULL);
123 GeoPnt3fPropertyUnrecPtr pnts = GeoPnt3fProperty ::create();
124 GeoVec3fPropertyUnrecPtr norms = GeoVec3fProperty ::create();
125 GeoVec2fPropertyUnrecPtr tex = GeoVec2fProperty ::create();
126 GeoUInt32PropertyUnrecPtr index = GeoUInt32Property::create();
127 GeoUInt32PropertyUnrecPtr lens = GeoUInt32Property::create();
128 GeoUInt8PropertyUnrecPtr types = GeoUInt8Property ::create();
130 UInt16 x,y;
131 Real32 xstep,ystep;
132 xstep=xsize / hor;
133 ystep=ysize / vert;
135 // calc the vertices
137 GeoPnt3fProperty::StoredFieldType *p = pnts ->editFieldPtr();
138 GeoVec3fProperty::StoredFieldType *n = norms->editFieldPtr();
139 GeoVec2fProperty::StoredFieldType *tx = tex ->editFieldPtr();
141 for(y = 0; y <= vert; y++)
143 for(x = 0; x <= hor; x++)
145 p->push_back(Pnt3f(x * xstep - xsize / 2, y * ystep - ysize / 2, 0));
146 n->push_back(Vec3f(0, 0, 1));
147 tx->push_back(Vec2f(x / Real32(hor), y / Real32(vert)));
151 // create the faces
153 GeoUInt32Property::StoredFieldType *i = index->editFieldPtr();
154 GeoUInt32Property::StoredFieldType *l = lens ->editFieldPtr();
155 GeoUInt8Property::StoredFieldType *t = types->editFieldPtr();
157 for(y = 0; y < vert; y++)
159 t->push_back(GL_TRIANGLE_STRIP);
160 l->push_back(2 * (hor + 1));
162 for(x = 0; x <= hor; x++)
164 i->push_back((y + 1) * (hor + 1) + x);
165 i->push_back( y * (hor + 1) + x);
169 // create the geometry
171 GeometryTransitPtr geo = Geometry::create();
173 geo->setMaterial(getDefaultMaterial());
174 geo->setPositions(pnts);
175 geo->setNormals(norms);
176 geo->setTexCoords(tex);
177 geo->setIndices(index);
178 geo->setTypes(types);
179 geo->setLengths(lens);
181 return geo;
184 /*! Creates a cone. It's center is in the origin and the bottom is parallel to
185 the x/y plane.
186 It's radius is \a botradius and the base is subdivided into \a sides parts.
188 Each part of the cone (bottom cap, sides) can be enabled or disabled.
190 \param[in] height Height of the cone.
191 \param[in] botradius Radius if the bottom.
192 \param[in] sides Number of sides the base is subdivided into.
193 \param[in] doSide If true side faces are created.
194 \param[in] doBottom If true bottom faces are created.
195 \return NodeTransitPtr to a newly created Node with a Geometry core.
197 \ingroup GrpDrawablesGeometryUtils
199 NodeTransitPtr makeCone(Real32 height,
200 Real32 botradius,
201 UInt16 sides,
202 bool doSide,
203 bool doBottom)
205 return makeConicalFrustum(height,
207 botradius,
208 sides,
209 doSide,
210 false,
211 doBottom);
214 /*! Create the Geometry Core used by OSG::makeCone.
216 \param[in] height Height of the cone.
217 \param[in] botradius Radius if the bottom.
218 \param[in] sides Number of sides the base is subdivided into.
219 \param[in] doSide If true side faces are created.
220 \param[in] doBottom If true bottom faces are created.
221 \return GeometryTransitPtr to a newly created Geometry core.
223 \sa OSG::makeCone
225 \ingroup GrpDrawablesGeometryUtils
227 GeometryTransitPtr makeConeGeo(Real32 height,
228 Real32 botradius,
229 UInt16 sides,
230 bool doSide,
231 bool doBottom)
233 return makeConicalFrustumGeo(height,
235 botradius,
236 sides,
237 doSide,
238 false,
239 doBottom);
242 /*! Creates a cylinder. It's center is in the origin with top and bottom
243 parallel to the x/y plane. It's radius is \a radius and the base is
244 subdivided into \a sides parts.
246 Each part of the cylinder (top cap, bottom cap, sides) can be enabled or
247 disabled.
249 \param[in] height Height of the cylinder.
250 \param[in] radius Radius of the cylinder.
251 \param[in] sides Number of sides the base is subdivided into.
252 \param[in] doSide If true, side faces are created.
253 \param[in] doTop If true, top cap faces are created.
254 \param[in] doBottom If true, bottom cap faces are created.
255 \return NodeTransitPtr to a newly created Node with a Geometry core.
257 \ingroup GrpDrawablesGeometryUtils
259 NodeTransitPtr makeCylinder(Real32 height,
260 Real32 radius,
261 UInt16 sides,
262 bool doSide,
263 bool doTop,
264 bool doBottom)
266 return makeConicalFrustum(height,
267 radius,
268 radius,
269 sides,
270 doSide,
271 doTop,
272 doBottom);
275 /*! Create the Geometry Core used by OSG::makeCylinder.
277 \param[in] height Height of the cylinder.
278 \param[in] radius Radius of the cylinder.
279 \param[in] sides Number of sides the base is subdivided into.
280 \param[in] doSide If true, side faces are created.
281 \param[in] doTop If true, top cap faces are created.
282 \param[in] doBottom If true, bottom cap faces are created.
283 \return GeometryTransitPtr to a newly created Geometry core.
285 \sa OSG::makeCylinder
287 \ingroup GrpDrawablesGeometryUtils
289 GeometryTransitPtr makeCylinderGeo(Real32 height,
290 Real32 radius,
291 UInt16 sides,
292 bool doSide,
293 bool doTop,
294 bool doBottom)
296 return makeConicalFrustumGeo(height,
297 radius,
298 radius,
299 sides,
300 doSide,
301 doTop,
302 doBottom);
306 /*! Creates a conical frustum. It's center is in the origin with top and bottom
307 parallel to the x/y plane. The height is \a height and the base is
308 subdivided into \a sides parts. The top radius is \a topradius, while the
309 bottom radius is \a botradius.
311 Each part of the frustum (top cap, bottom cap, sides) can be enabled or
312 disabled. Caps for radii 0 are automatically disabled.
314 \param[in] height Height of the conical frustum.
315 \param[in] topradius Radius at the top of the conical frustum.
316 \param[in] botradius Radius at the bottom of the conical frustum.
317 \param[in] sides Number of sides the base is subdivided into.
318 \param[in] doSide If true, side faces are created.
319 \param[in] doTop If true, top cap faces are created.
320 \param[in] doBottom If true, bottom cap faces are created.
321 \return NodeTransitPtr to a newly created Node with a Geometry core.
323 \ingroup GrpDrawablesGeometryUtils
325 NodeTransitPtr makeConicalFrustum(Real32 height,
326 Real32 topradius,
327 Real32 botradius,
328 UInt16 sides,
329 bool doSide,
330 bool doTop,
331 bool doBottom)
333 GeometryTransitPtr pGeo = makeConicalFrustumGeo(height,
334 topradius,
335 botradius,
336 sides,
337 doSide,
338 doTop,
339 doBottom);
341 if(pGeo == NULL)
343 return NodeTransitPtr(NULL);
346 NodeTransitPtr node = Node::create();
348 node->setCore(pGeo);
350 return node;
353 /*! Create the Geometry Core used by OSG::makeConicalFrustum.
355 \param[in] height Height of the conical frustum.
356 \param[in] topradius Radius at the top of the conical frustum.
357 \param[in] botradius Radius at the bottom of the conical frustum.
358 \param[in] sides Number of sides the base is subdivided into.
359 \param[in] doSide If true, side faces are created.
360 \param[in] doTop If true, top cap faces are created.
361 \param[in] doBottom If true, bottom cap faces are created.
362 \return GeometryTransitPtr to a newly created Geometry core.
364 \ingroup GrpDrawablesGeometryUtils
366 GeometryTransitPtr makeConicalFrustumGeo(Real32 height,
367 Real32 topradius,
368 Real32 botradius,
369 UInt16 sides,
370 bool doSide,
371 bool doTop,
372 bool doBottom)
374 if(height <= 0 || topradius < 0 || botradius < 0 || sides < 3)
376 SWARNING << "makeConicalFrustum: illegal parameters height=" << height
377 << ", topradius=" << topradius
378 << ", botradius=" << botradius
379 << ", sides=" << sides
380 << std::endl;
381 return GeometryTransitPtr(NULL);
384 GeoPnt3fPropertyUnrecPtr pnts = GeoPnt3fProperty ::create();
385 GeoVec3fPropertyUnrecPtr norms = GeoVec3fProperty ::create();
386 GeoVec2fPropertyUnrecPtr tex = GeoVec2fProperty ::create();
387 GeoUInt32PropertyUnrecPtr index = GeoUInt32Property::create();
388 GeoUInt32PropertyUnrecPtr lens = GeoUInt32Property::create();
389 GeoUInt8PropertyUnrecPtr types = GeoUInt8Property ::create();
391 Int16 j;
392 Real32 delta = 2.f * Pi / sides;
393 Real32 beta, x, z;
394 Real32 incl = (botradius - topradius) / height;
395 Real32 nlen = 1.f / osgSqrt(1 + incl * incl);
397 // vertices
399 GeoPnt3fProperty::StoredFieldType *p = pnts ->editFieldPtr();
400 GeoVec3fProperty::StoredFieldType *n = norms->editFieldPtr();
401 GeoVec2fProperty::StoredFieldType *tx = tex ->editFieldPtr();
403 // faces
405 GeoUInt32Property::StoredFieldType *i = index->editFieldPtr();
406 GeoUInt32Property::StoredFieldType *l = lens ->editFieldPtr();
407 GeoUInt8Property::StoredFieldType *t = types->editFieldPtr();
409 if(doSide)
411 UInt32 baseindex = p->size32();
413 for(j = 0; j <= sides; j++)
415 beta = j * delta;
416 x = osgSin(beta);
417 z = -osgCos(beta);
419 p->push_back(Pnt3f(x * topradius, height/2, z * topradius));
420 n->push_back(Vec3f(x/nlen, incl/nlen, z/nlen));
421 tx->push_back(Vec2f(1.f - j / Real32(sides), 1));
424 for(j = 0; j <= sides; j++)
426 beta = j * delta;
427 x = osgSin(beta);
428 z = -osgCos(beta);
430 p->push_back(Pnt3f(x * botradius, -height/2, z * botradius));
431 n->push_back(Vec3f(x/nlen, incl/nlen, z/nlen));
432 tx->push_back(Vec2f(1.f - j / Real32(sides), 0));
435 t->push_back(GL_TRIANGLE_STRIP);
436 l->push_back(2 * (sides + 1));
438 for(j = 0; j <= sides; j++)
440 i->push_back(baseindex + sides + 1 + j);
441 i->push_back(baseindex + j);
445 if(doTop && topradius > 0)
447 UInt32 baseindex = p->size32();
449 // need to duplicate the points fornow, as we don't have multi-index geo yet
451 for(j = sides - 1; j >= 0; j--)
453 beta = j * delta;
454 x = topradius * osgSin(beta);
455 z = -topradius * osgCos(beta);
457 p->push_back(Pnt3f(x, height/2, z));
458 n->push_back(Vec3f(0, 1, 0));
459 tx->push_back(Vec2f(x / topradius / 2 + .5f, -z / topradius / 2 + .5f));
462 t->push_back(GL_POLYGON);
463 l->push_back(sides);
465 for(j = 0; j < sides; j++)
467 i->push_back(baseindex + j);
471 if(doBottom && botradius > 0 )
473 UInt32 baseindex = p->size32();
475 // need to duplicate the points fornow, as we don't have multi-index geo yet
477 for(j = sides - 1; j >= 0; j--)
479 beta = j * delta;
480 x = botradius * osgSin(beta);
481 z = -botradius * osgCos(beta);
483 p->push_back(Pnt3f(x, -height/2, z));
484 n->push_back(Vec3f(0, -1, 0));
485 tx->push_back(Vec2f(x / botradius / 2 + .5f, z / botradius / 2 + .5f));
488 t->push_back(GL_POLYGON);
489 l->push_back(sides);
491 for(j = 0; j < sides; j++)
493 i->push_back(baseindex + sides - 1 - j);
497 // create the geometry
499 GeometryTransitPtr geo = Geometry::create();
501 geo->setMaterial(getDefaultMaterial());
502 geo->setPositions(pnts);
503 geo->setNormals(norms);
504 geo->setTexCoords(tex);
505 geo->setIndices(index);
506 geo->setTypes(types);
507 geo->setLengths(lens);
509 return geo;
512 /*! Creates a torus in the x/y plane. The number of subdivisions for
513 the inner radius is \a sides, for the outer radius it is \a rings.
515 \param[in] innerRadius Inner radius of the torus.
516 \param[in] outerRadius Outer radius of the torus.
517 \param[in] sides Number of subdivisions along the inner radius.
518 \param[in] rings Number of subdivisions along the outer radius.
519 \return NodeTransitPtr to a newly created Node with a Geometry core.
521 \ingroup GrpDrawablesGeometryUtils
523 NodeTransitPtr makeTorus(Real32 innerRadius,
524 Real32 outerRadius,
525 UInt16 sides,
526 UInt16 rings)
528 GeometryTransitPtr pGeo = makeTorusGeo(innerRadius,
529 outerRadius,
530 sides,
531 rings);
533 if(pGeo == NULL)
535 return NodeTransitPtr(NULL);
538 NodeTransitPtr node = Node::create();
540 node->setCore(pGeo);
542 return node;
545 /*! Create the Geometry Core used by OSG::makeTorus.
547 \param[in] innerRadius Inner radius of the torus.
548 \param[in] outerRadius Outer radius of the torus.
549 \param[in] sides Number of subdivisions along the inner radius.
550 \param[in] rings Number of subdivisions along the outer radius.
551 \return GeometryTransitPtr to a newly created Geometry core.
553 \sa OSG::makeTorus
555 \ingroup GrpDrawablesGeometryUtils
557 GeometryTransitPtr makeTorusGeo(Real32 innerRadius,
558 Real32 outerRadius,
559 UInt16 sides,
560 UInt16 rings)
562 if(innerRadius <= 0 || outerRadius <= 0 || sides < 3 || rings < 3)
564 SWARNING << "makeTorus: illegal parameters innerRadius=" << innerRadius
565 << ", outerRadius=" << outerRadius
566 << ", sides=" << sides
567 << ", rings=" << rings
568 << std::endl;
569 return GeometryTransitPtr(NULL);
572 GeoPnt3fPropertyUnrecPtr pnts = GeoPnt3fProperty ::create();
573 GeoVec3fPropertyUnrecPtr norms = GeoVec3fProperty ::create();
574 GeoVec2fPropertyUnrecPtr tex = GeoVec2fProperty ::create();
575 GeoUInt32PropertyUnrecPtr index = GeoUInt32Property::create();
576 GeoUInt32PropertyUnrecPtr lens = GeoUInt32Property::create();
577 GeoUInt8PropertyUnrecPtr types = GeoUInt8Property ::create();
579 UInt16 a, b;
580 Real32 theta, phi;
581 Real32 cosTheta, sinTheta;
582 Real32 ringDelta, sideDelta;
584 // calc the vertices
586 GeoPnt3fProperty::StoredFieldType *p = pnts ->editFieldPtr();
587 GeoVec3fProperty::StoredFieldType *n = norms->editFieldPtr();
588 GeoVec2fProperty::StoredFieldType *tx = tex ->editFieldPtr();
590 ringDelta = 2.f * Pi / rings;
591 sideDelta = 2.f * Pi / sides;
593 for(a = 0, theta = 0.0; a <= rings; a++, theta += ringDelta)
595 cosTheta = osgCos(theta);
596 sinTheta = osgSin(theta);
598 for(b = 0, phi = 0; b <= sides; b++, phi += sideDelta)
600 GLfloat cosPhi, sinPhi, dist;
602 cosPhi = osgCos(phi);
603 sinPhi = osgSin(phi);
604 dist = outerRadius + innerRadius * cosPhi;
606 n->push_back(Vec3f(cosTheta * cosPhi,
607 -sinTheta * cosPhi,
608 sinPhi));
609 p->push_back(Pnt3f(cosTheta * dist,
610 -sinTheta * dist,
611 innerRadius * sinPhi));
612 tx->push_back(Vec2f(- a / Real32(rings), b / Real32(sides)));
616 // create the faces
618 GeoUInt32Property::StoredFieldType *i = index->editFieldPtr();
619 GeoUInt32Property::StoredFieldType *l = lens ->editFieldPtr();
620 GeoUInt8Property::StoredFieldType *t = types->editFieldPtr();
622 for(a = 0; a < sides; a++)
624 t->push_back(GL_TRIANGLE_STRIP);
625 l->push_back((rings + 1) * 2);
627 for(b = 0; b <= rings; b++)
629 i->push_back(b * (sides+1) + a);
630 i->push_back(b * (sides+1) + a + 1);
634 // create the geometry
636 GeometryTransitPtr geo = Geometry::create();
638 geo->setMaterial(getDefaultMaterial());
639 geo->setPositions(pnts);
640 geo->setNormals(norms);
641 geo->setTexCoords(tex);
642 geo->setIndices(index);
643 geo->setTypes(types);
644 geo->setLengths(lens);
646 return geo;
649 #if !defined(OSG_DO_DOC) || defined(OSG_DOC_DEV)
651 /*! Scale the vector \a vec to the given \a length. If \a vec is degenerate,
652 i.e. has length 0 it is not changed.
654 \param[in,out] vec The vector to scale.
655 \param[in] length Length to scale \a vec to.
656 \return The \a length argument.
658 Real32 setVecLen(Vec3f &vec, Real32 length)
660 Real32 len = vec.length();
661 if(len == 0.0)
663 len = 1;
665 else
667 len = length / len;
669 vec *= len;
671 return length;
674 Real32 calcTexS(Vec3f &n, Real32 theta)
676 const Real32 TwoPiConst = 6.283185307179586f;
677 const Real32 HalfPi = 1.570796326794897f;
679 Real32 phi = osgATan2(-n[2], n[0]) - HalfPi;
681 if (phi <= -TypeTraits<Real32>::getDefaultEps())
682 phi += TwoPiConst;
683 phi /= TwoPiConst;
685 return phi;
688 void addPoint(Pnt3f v, UInt32 index, Real32 radius,
689 GeoPnt3fProperty::StoredFieldType *p,
690 GeoVec3fProperty::StoredFieldType *n,
691 GeoVec2fProperty::StoredFieldType *tx)
693 Vec3f norm(v[0], v[1], v[2]);
695 norm.normalize();
696 n->push_back(norm);
698 Pnt3f pnt(radius * norm);
699 p->push_back(pnt);
701 Vec2f texCoord;
703 // Theta -> v
704 texCoord[1] = (Pi - osgACos(norm[1])) / Pi;
706 texCoord[0] = calcTexS(norm, texCoord[1]);
708 tx->push_back(texCoord);
711 void subdivideTriangle( UInt32 i1,
712 UInt32 i2,
713 UInt32 i3,
714 Int32 depth,
715 GeoPnt3fProperty::StoredFieldType *p,
716 GeoVec3fProperty::StoredFieldType *n,
717 GeoVec2fProperty::StoredFieldType *tx,
718 GeoUInt32Property::StoredFieldType *i,
719 GeoUInt32Property::StoredFieldType *tci,
720 UInt32& z, Real32 radius )
722 if (depth == 0)
724 i->push_back(i1);
725 tci->push_back(i1);
726 i->push_back(i2);
727 tci->push_back(i2);
728 i->push_back(i3);
729 tci->push_back(i3);
731 return;
734 Pnt3f v1 = (*p)[i1],
735 v2 = (*p)[i2],
736 v3 = (*p)[i3];
737 Pnt3f v12, v23, v31;
739 v12 = v1 + (v2 - v1) * .5f;
740 v23 = v2 + (v3 - v2) * .5f;
741 v31 = v3 + (v1 - v3) * .5f;
743 v12 /= 2.0f;
744 v23 /= 2.0f;
745 v31 /= 2.0f;
747 UInt32 i12 = z++, i23 = z++, i31 = z++;
749 addPoint(v12,i12,radius,p,n,tx);
750 addPoint(v23,i23,radius,p,n,tx);
751 addPoint(v31,i31,radius,p,n,tx);
753 subdivideTriangle( i1, i12, i31, depth - 1, p,n,tx,i,tci, z, radius);
754 subdivideTriangle( i2, i23, i12, depth - 1, p,n,tx,i,tci, z, radius);
755 subdivideTriangle( i3, i31, i23, depth - 1, p,n,tx,i,tci, z, radius);
756 subdivideTriangle(i12, i23, i31, depth - 1, p,n,tx,i,tci, z, radius);
759 #endif // exclude from doc
761 /*! Creates a sphere centered in the origin. It is created by
762 recursive subdivision of an icosahedron, with \a depth giving the number
763 of subdivisions and \a radius being the radius.
765 \param[in] depth Number of recursive subdivisions to perform.
766 \param[in] radius Radius of sphere.
767 \return NodePtr to a newly created Node with a Geometry core.
769 \ingroup GrpDrawablesGeometryUtils
771 NodeTransitPtr makeSphere(UInt16 depth, Real32 radius)
773 GeometryTransitPtr pGeo = makeSphereGeo(depth, radius);
775 if(pGeo == NULL)
777 return NodeTransitPtr(NULL);
780 NodeTransitPtr node = Node::create();
782 node->setCore(pGeo);
784 return node;
787 /*! Create the Geometry Core for used by OSG::makeSphere.
789 \param[in] depth Number of recursive subdivisions to perform.
790 \param[in] radius Radius of sphere.
791 \return GeometryTransitPtr to a newly created Geometry core.
793 \sa OSG::makeSphere
795 \ingroup GrpDrawablesGeometryUtils
797 GeometryTransitPtr makeSphereGeo(UInt16 depth, Real32 radius)
799 const Real32 X = .525731112119133606f;
800 const Real32 Z = .850650808352039932f;
801 const Real32 HalfPi = 1.570796326794897f;
803 GeoPnt3fPropertyUnrecPtr pnts = GeoPnt3fProperty ::create();
804 GeoVec3fPropertyUnrecPtr norms = GeoVec3fProperty ::create();
805 GeoVec2fPropertyUnrecPtr tex = GeoVec2fProperty ::create();
806 GeoUInt32PropertyUnrecPtr index = GeoUInt32Property::create();
807 GeoUInt32PropertyUnrecPtr tcindex = GeoUInt32Property::create();
808 GeoUInt32PropertyUnrecPtr lens = GeoUInt32Property::create();
809 GeoUInt8PropertyUnrecPtr types = GeoUInt8Property ::create();
811 UInt32 j,z;
813 static Vec3f v[12] = { Vec3f(-X, 0., Z),
814 Vec3f( X, 0., Z),
815 Vec3f(-X, 0., -Z),
816 Vec3f( X, 0., -Z),
817 Vec3f(0., Z, X),
818 Vec3f(0., Z, -X),
819 Vec3f(0., -Z, X),
820 Vec3f(0., -Z, -X),
821 Vec3f( Z, X, 0.),
822 Vec3f(-Z, X, 0.),
823 Vec3f( Z, -X, 0.),
824 Vec3f(-Z, -X, 0.) };
826 Quaternion q(Vec3f(0,1,0), osgACos(Z) + HalfPi);
827 Matrix mat;
829 mat.setTransform(q);
831 for (j=0; j<12; j++)
832 mat.mult(v[j], v[j]);
834 Int32 tr[20][3] = { {1,4,0}, {4,9,0}, {4,5,9}, {8,5,4}, {1,8,4},
835 {1,10,8}, {10,3,8}, {8,3,5}, {3,2,5}, {3,7,2},
836 {3,10,7}, {10,6,7}, {6,11,7}, {6,0,11}, {6,1,0},
837 {10,1,6}, {11,0,9}, {2,11,9}, {5,2,9}, {11,2,7} };
839 GeoPnt3fProperty::StoredFieldType *p = pnts ->editFieldPtr();
840 GeoVec3fProperty::StoredFieldType *n = norms->editFieldPtr();
841 GeoVec2fProperty::StoredFieldType *tx = tex ->editFieldPtr();
843 GeoUInt32Property::StoredFieldType *i = index ->editFieldPtr();
844 GeoUInt32Property::StoredFieldType *tci = tcindex->editFieldPtr();
846 // initial sizing to prevent reallocation halfway through
847 UInt32 estimatedSize = UInt32(osgPow(4.f, Real32(depth)) * 20.f);
849 p->reserve (estimatedSize);
850 n->reserve (estimatedSize);
851 tx->reserve(estimatedSize);
852 i->reserve (estimatedSize);
853 tci->reserve (estimatedSize);
855 // add the initial points to the fields
856 for (j=0; j<12; j++)
858 Vec3f pnt = v[j];
859 Vec3f norm = v[j];
861 setVecLen(pnt, radius);
862 norm.normalize();
864 p->push_back(pnt.addToZero());
865 n->push_back(norm);
867 Vec2f texCoord;
869 // Theta -> v
870 texCoord[1] = (Pi - osgACos(norm[1])) / Pi;
872 // Phi -> u
873 texCoord[0] = calcTexS(norm, texCoord[1]);
875 tx->push_back(texCoord);
878 // subdivide the triangles
879 z=12;
880 for(j=0; j<20; j++)
882 subdivideTriangle(tr[j][0], tr[j][1], tr[j][2],
883 depth, p, n, tx, i, tci, z, radius);
886 types->push_back(GL_TRIANGLES);
887 lens->push_back(i->size32());
889 // create the geometry
890 GeometryTransitPtr geo = Geometry::create();
892 geo->setMaterial(getDefaultMaterial());
893 geo->setPositions(pnts);
894 geo->setNormals(norms);
895 geo->setTexCoords(tex);
896 geo->setIndices(index);
897 geo->setIndex(tcindex, Geometry::TexCoordsIndex);
898 geo->setTypes(types);
899 geo->setLengths(lens);
901 return geo;
904 /*! Creates a sphere centered in the origin and divided in latitude
905 and longitude. \a radius is the radius of the sphere, \a latres and
906 \a longres are the number of subdivisions along the latitudes and longitudes.
908 \param[in] latres Number of subdivisions along latitudes.
909 \param[in] longres Number of subdivisions along longitudes.
910 \param[in] radius Radius of sphere.
911 \return NodeTransitPtr to a newly created Node with a Geometry core.
913 \ingroup GrpDrawablesGeometryUtils
915 NodeTransitPtr makeLatLongSphere(UInt16 latres, UInt16 longres, Real32 radius)
917 GeometryTransitPtr pGeo = makeLatLongSphereGeo(latres, longres, radius);
919 if(pGeo == NULL)
921 return NodeTransitPtr(NULL);
924 NodeTransitPtr node = Node::create();
926 node->setCore(pGeo);
928 return node;
931 /*! Create the Geometry Core used by OSG::makeLatLongSphere.
933 \param[in] latres Number of subdivisions along latitudes.
934 \param[in] longres Number of subdivisions along longitudes.
935 \param[in] radius Radius of sphere.
936 \return GeometryTransitPtr to a newly created Geometry core.
938 \sa OSG::makeLatLongSphere
940 \ingroup GrpDrawablesGeometryUtils
942 GeometryTransitPtr makeLatLongSphereGeo(UInt16 latres,
943 UInt16 longres,
944 Real32 radius)
946 if(radius <= 0 || latres < 4 || longres < 4)
948 SWARNING << "makeLatLongSphere: illegal parameters "
949 << "latres=" << latres
950 << ", longres=" << longres
951 << ", radius=" << radius
952 << std::endl;
953 return GeometryTransitPtr(NULL);
956 GeoPnt3fPropertyUnrecPtr pnts = GeoPnt3fProperty ::create();
957 GeoVec3fPropertyUnrecPtr norms = GeoVec3fProperty ::create();
958 GeoVec2fPropertyUnrecPtr tex = GeoVec2fProperty ::create();
959 GeoUInt32PropertyUnrecPtr index = GeoUInt32Property::create();
960 GeoUInt32PropertyUnrecPtr lens = GeoUInt32Property::create();
961 GeoUInt8PropertyUnrecPtr types = GeoUInt8Property ::create();
963 UInt16 a, b;
964 Real32 theta, phi;
965 Real32 cosTheta, sinTheta;
966 Real32 latDelta, longDelta;
968 // calc the vertices
970 GeoPnt3fProperty::StoredFieldType *p = pnts ->editFieldPtr();
971 GeoVec3fProperty::StoredFieldType *n = norms->editFieldPtr();
972 GeoVec2fProperty::StoredFieldType *tx = tex ->editFieldPtr();
974 latDelta = Pi / latres;
975 longDelta = 2.f * Pi / longres;
977 for(a = 0, theta = -Pi / 2; a <= latres; a++, theta += latDelta)
979 cosTheta = osgCos(theta);
980 sinTheta = osgSin(theta);
982 for(b = 0, phi = -Pi; b <= longres; b++, phi += longDelta)
984 GLfloat cosPhi, sinPhi;
986 cosPhi = osgCos(phi);
987 sinPhi = osgSin(phi);
989 n->push_back(Vec3f(cosTheta * sinPhi,
990 sinTheta,
991 cosTheta * cosPhi));
993 p->push_back(Pnt3f( cosTheta * sinPhi * radius,
994 sinTheta * radius,
995 cosTheta * cosPhi * radius));
997 tx->push_back(Vec2f(b / Real32(longres),
998 a / Real32(latres)));
1002 // create the faces
1004 GeoUInt32Property::StoredFieldType *i = index->editFieldPtr();
1005 GeoUInt32Property::StoredFieldType *l = lens ->editFieldPtr();
1006 GeoUInt8Property::StoredFieldType *t = types->editFieldPtr();
1008 for(a = 0; a < longres; a++)
1010 t->push_back(GL_TRIANGLE_STRIP);
1011 l->push_back((latres + 1) * 2);
1013 for(b = 0; b <= latres; b++)
1015 i->push_back(b * (longres+1) + a);
1016 i->push_back(b * (longres+1) + a + 1);
1020 // create the geometry
1022 GeometryTransitPtr geo = Geometry::create();
1024 geo->setMaterial(getDefaultMaterial());
1025 geo->setPositions(pnts);
1026 geo->setNormals(norms);
1027 geo->setTexCoords(tex);
1028 geo->setIndices(index);
1029 geo->setTypes(types);
1030 geo->setLengths(lens);
1032 return geo;
1036 /*! Creates a sphere centered in the origin and divided in latitude
1037 and longitude. \a radius is the radius of the sphere, \a latres and
1038 \a longres are the number of subdivisions along the latitudes and longitudes.
1040 \param[in] latres Number of subdivisions along latitudes.
1041 \param[in] longres Number of subdivisions along longitudes.
1042 \param[in] rSemiMajorAxis Radius of ellipsoid major axis.
1043 \param[in] rSemiMinorAxis Radius of ellipsoid minor axis.
1044 \return NodeTransitPtr to a newly created Node with a Geometry core.
1046 \ingroup GrpDrawablesGeometryUtils
1048 NodeTransitPtr makeLatLongEllipsoid(UInt16 latres,
1049 UInt16 longres,
1050 Real32 rSemiMajorAxis,
1051 Real32 rSemiMinorAxis)
1053 GeometryTransitPtr pGeo = makeLatLongEllipsoidGeo(latres,
1054 longres,
1055 rSemiMajorAxis,
1056 rSemiMinorAxis);
1058 if(pGeo == NULL)
1060 return NodeTransitPtr(NULL);
1063 NodeTransitPtr node = Node::create();
1065 node->setCore(pGeo);
1067 return node;
1070 /*! Create the Geometry Core used by OSG::makeLatLongSphere.
1072 \param[in] latres Number of subdivisions along latitudes.
1073 \param[in] longres Number of subdivisions along longitudes.
1074 \param[in] rSemiMajorAxis Radius of ellipsoid major axis.
1075 \param[in] rSemiMinorAxis Radius of ellipsoid minor axis.
1076 \return GeometryTransitPtr to a newly created Geometry core.
1078 \sa OSG::makeLatLongSphere
1080 \ingroup GrpDrawablesGeometryUtils
1082 GeometryTransitPtr makeLatLongEllipsoidGeo(UInt16 latres,
1083 UInt16 longres,
1084 Real32 rSemiMajorAxis,
1085 Real32 rSemiMinorAxis)
1087 if(rSemiMajorAxis <= 0 || rSemiMinorAxis <= 0 || latres < 4 || longres < 4)
1089 SWARNING << "makeLatLongSphere: illegal parameters "
1090 << "latres=" << latres
1091 << ", longres=" << longres
1092 << ", rSemiMajorAxis=" << rSemiMajorAxis
1093 << ", rSemiMinorAxis=" << rSemiMinorAxis
1094 << std::endl;
1095 return GeometryTransitPtr(NULL);
1098 GeoPnt3fPropertyUnrecPtr pnts = GeoPnt3fProperty ::create();
1099 GeoVec3fPropertyUnrecPtr norms = GeoVec3fProperty ::create();
1100 GeoVec2fPropertyUnrecPtr tex = GeoVec2fProperty ::create();
1101 GeoUInt32PropertyUnrecPtr index = GeoUInt32Property ::create();
1102 GeoUInt32PropertyUnrecPtr lens = GeoUInt32Property ::create();
1103 GeoUInt8PropertyUnrecPtr types = GeoUInt8Property ::create();
1105 UInt16 a, b;
1106 Real32 theta, phi;
1107 Real32 cosTheta, sinTheta;
1108 Real32 latDelta, longDelta;
1110 // calc the vertices
1112 GeoPnt3fProperty ::StoredFieldType *p = pnts ->editFieldPtr();
1113 GeoVec3fProperty ::StoredFieldType *n = norms->editFieldPtr();
1114 GeoVec2fProperty ::StoredFieldType *tx = tex ->editFieldPtr();
1116 latDelta = Pi / latres;
1117 longDelta = 2.f * Pi / longres;
1119 // float ea = 6378.137;
1120 // float eb = 6356.7523142;
1122 float rSemiMajorAxisSquare = rSemiMajorAxis * rSemiMajorAxis;
1124 float e2 = (rSemiMajorAxisSquare -
1125 rSemiMinorAxis * rSemiMinorAxis) / (rSemiMajorAxisSquare);
1127 for(a = 0, theta = -Pi / 2; a <= latres; a++, theta += latDelta)
1129 cosTheta = osgCos(theta);
1130 sinTheta = osgSin(theta);
1132 float v = rSemiMajorAxis / osgSqrt(1 - (e2 * sinTheta * sinTheta));
1134 for(b = 0, phi = -Pi; b <= longres; b++, phi += longDelta)
1136 GLfloat cosPhi, sinPhi;
1138 cosPhi = osgCos(phi);
1139 sinPhi = osgSin(phi);
1142 n->push_back(Vec3f(cosTheta * sinPhi,
1143 sinTheta,
1144 cosTheta * cosPhi));
1146 p->push_back(Pnt3f(cosTheta * sinPhi * v,
1147 sinTheta * ((1 - e2) * v),
1148 cosTheta * cosPhi * v));
1150 tx->push_back(Vec2f(b / Real32(longres),
1151 a / Real32(latres)));
1156 // create the faces
1158 GeoUInt32Property::StoredFieldType *i = index->editFieldPtr();
1159 GeoUInt32Property::StoredFieldType *l = lens ->editFieldPtr();
1160 GeoUInt8Property::StoredFieldType *t = types->editFieldPtr();
1162 for(a = 0; a < longres; a++)
1164 t->push_back(GL_TRIANGLE_STRIP);
1165 l->push_back((latres + 1) * 2);
1167 for(b = 0; b <= latres; b++)
1169 i->push_back(b * (longres+1) + a);
1170 i->push_back(b * (longres+1) + a + 1);
1174 // create the geometry
1176 GeometryTransitPtr geo = Geometry::create();
1178 geo->setMaterial(getDefaultMaterial());
1179 geo->setPositions(pnts);
1180 geo->setNormals(norms);
1181 geo->setTexCoords(tex);
1182 geo->setIndices(index);
1183 geo->setTypes(types);
1184 geo->setLengths(lens);
1186 return geo;
1190 /*! Creates a sphere centered in the origin and divided in latitude
1191 and longitude. \a radius is the radius of the sphere, \a latres and
1192 \a longres are the number of subdivisions along the latitudes and
1193 longitudes.
1195 \param[in] latres Number of subdivisions along latitudes.
1196 \param[in] longres Number of subdivisions along longitudes.
1197 \param[in] rSemiMajorAxis Radius of ellipsoid major axis.
1198 \param[in] rSemiMinorAxis Radius of ellipsoid minor axis.
1199 \param[in] rStartLatRad Segment lat start.
1200 \param[in] rStartLongRad Segment long start.
1201 \param[in] rStopLatRad Segment lat stop.
1202 \param[in] rStopLongRad Segment long stop.
1204 \return NodeTransitPtr to a newly created Node with a Geometry core.
1206 \ingroup GrpDrawablesGeometryUtils
1209 NodeTransitPtr makeLatLongEllipsoidSeg(UInt16 latres,
1210 UInt16 longres,
1211 Real32 rSemiMajorAxis,
1212 Real32 rSemiMinorAxis,
1213 Real32 rStartLatRad,
1214 Real32 rStartLongRad,
1215 Real32 rStopLatRad,
1216 Real32 rStopLongRad)
1218 GeometryTransitPtr pGeo = makeLatLongEllipsoidGeoSeg(latres,
1219 longres,
1220 rSemiMajorAxis,
1221 rSemiMinorAxis,
1222 rStartLatRad,
1223 rStartLongRad,
1224 rStopLatRad,
1225 rStopLongRad );
1227 if(pGeo == NULL)
1229 return NodeTransitPtr(NULL);
1232 NodeTransitPtr node = Node::create();
1234 node->setCore(pGeo);
1236 return node;
1239 /*! Create the Geometry Core used by OSG::makeLatLongSphere.
1241 \param[in] latres Number of subdivisions along latitudes.
1242 \param[in] longres Number of subdivisions along longitudes.
1243 \param[in] rSemiMajorAxis Radius of ellipsoid major axis.
1244 \param[in] rSemiMinorAxis Radius of ellipsoid minor axis.
1245 \param[in] rStartLatRad Segment lat start.
1246 \param[in] rStartLongRad Segment long start.
1247 \param[in] rStopLatRad Segment lat stop.
1248 \param[in] rStopLongRad Segment long stop.
1249 \return GeometryTransitPtr to a newly created Geometry core.
1251 \sa OSG::makeLatLongSphere
1253 \ingroup GrpDrawablesGeometryUtils
1255 GeometryTransitPtr makeLatLongEllipsoidGeoSeg(UInt16 latres,
1256 UInt16 longres,
1257 Real32 rSemiMajorAxis,
1258 Real32 rSemiMinorAxis,
1259 Real32 rStartLatRad,
1260 Real32 rStartLongRad,
1261 Real32 rStopLatRad,
1262 Real32 rStopLongRad)
1264 if(rSemiMajorAxis <= 0 || rSemiMinorAxis <= 0 || latres < 4 || longres < 4)
1266 SWARNING << "makeLatLongSphere: illegal parameters "
1267 << "latres=" << latres
1268 << ", longres=" << longres
1269 << ", rSemiMajorAxis=" << rSemiMajorAxis
1270 << ", rSemiMinorAxis=" << rSemiMinorAxis
1271 << std::endl;
1272 return GeometryTransitPtr(NULL);
1275 GeoPnt3fPropertyUnrecPtr pnts = GeoPnt3fProperty ::create();
1276 GeoVec3fPropertyUnrecPtr norms = GeoVec3fProperty ::create();
1277 GeoVec2fPropertyUnrecPtr tex = GeoVec2fProperty ::create();
1278 GeoUInt32PropertyUnrecPtr index = GeoUInt32Property ::create();
1279 GeoUInt32PropertyUnrecPtr lens = GeoUInt32Property ::create();
1280 GeoUInt8PropertyUnrecPtr types = GeoUInt8Property ::create();
1282 UInt16 a, b;
1283 Real32 theta, phi;
1284 Real32 cosTheta, sinTheta;
1285 Real32 latDelta, longDelta;
1287 // calc the vertices
1289 GeoPnt3fProperty ::StoredFieldType *p = pnts ->editFieldPtr();
1290 GeoVec3fProperty ::StoredFieldType *n = norms->editFieldPtr();
1291 GeoVec2fProperty ::StoredFieldType *tx = tex ->editFieldPtr();
1293 Real32 latDiff = rStopLatRad - rStartLatRad;
1294 Real32 longDiff = rStopLongRad - rStartLongRad;
1296 latDelta = latDiff / latres;
1297 longDelta = longDiff / longres;
1299 // float ea = 6378.137;
1300 // float eb = 6356.7523142;
1302 float rSemiMajorAxisSquare = rSemiMajorAxis * rSemiMajorAxis;
1304 float e2 = (rSemiMajorAxisSquare -
1305 rSemiMinorAxis * rSemiMinorAxis) / (rSemiMajorAxisSquare);
1307 for(a = 0, theta = rStartLatRad; a <= latres; a++, theta += latDelta)
1309 cosTheta = osgCos(theta);
1310 sinTheta = osgSin(theta);
1312 float v = rSemiMajorAxis / osgSqrt(1 - (e2 * sinTheta * sinTheta));
1314 for(b = 0, phi = rStartLongRad; b <= longres; b++, phi += longDelta)
1316 GLfloat cosPhi, sinPhi;
1318 cosPhi = osgCos(phi);
1319 sinPhi = osgSin(phi);
1322 n->push_back(Vec3f(cosTheta * sinPhi,
1323 sinTheta,
1324 cosTheta * cosPhi));
1326 p->push_back(Pnt3f(cosTheta * sinPhi * v,
1327 sinTheta * ((1 - e2) * v),
1328 cosTheta * cosPhi * v));
1330 tx->push_back(Vec2f(b / Real32(longres),
1331 a / Real32(latres)));
1336 // create the faces
1338 GeoUInt32Property::StoredFieldType *i = index->editFieldPtr();
1339 GeoUInt32Property::StoredFieldType *l = lens ->editFieldPtr();
1340 GeoUInt8Property::StoredFieldType *t = types->editFieldPtr();
1342 for(a = 0; a < longres; a++)
1344 t->push_back(GL_TRIANGLE_STRIP);
1345 l->push_back((latres + 1) * 2);
1347 for(b = 0; b <= latres; b++)
1349 i->push_back(b * (longres+1) + a);
1350 i->push_back(b * (longres+1) + a + 1);
1354 // create the geometry
1356 GeometryTransitPtr geo = Geometry::create();
1358 geo->setMaterial(getDefaultMaterial());
1359 geo->setPositions(pnts);
1360 geo->setNormals(norms);
1361 geo->setTexCoords(tex);
1362 geo->setIndices(index);
1363 geo->setTypes(types);
1364 geo->setLengths(lens);
1366 return geo;
1369 /*! create Ellipsoid axis geometry
1370 \ingroup GrpDrawablesGeometryUtils
1372 GeometryTransitPtr makeEllipsoidAxisGeo(UInt16 latres,
1373 UInt16 longres,
1374 Real32 rSemiMajorAxis,
1375 Real32 rSemiMinorAxis)
1377 if(rSemiMajorAxis <= 0 || rSemiMinorAxis <= 0 || latres < 4 || longres < 4)
1379 SWARNING << "makeLatLongSphere: illegal parameters "
1380 << "latres=" << latres
1381 << ", longres=" << longres
1382 << ", rSemiMajorAxis=" << rSemiMajorAxis
1383 << ", rSemiMinorAxis=" << rSemiMinorAxis
1384 << std::endl;
1385 return GeometryTransitPtr(NULL);
1388 GeoPnt3fPropertyUnrecPtr pnts = GeoPnt3fProperty ::create();
1389 GeoColor3fPropertyUnrecPtr color = GeoColor3fProperty::create();
1390 GeoUInt32PropertyUnrecPtr index = GeoUInt32Property ::create();
1391 GeoUInt32PropertyUnrecPtr lens = GeoUInt32Property ::create();
1392 GeoUInt8PropertyUnrecPtr types = GeoUInt8Property ::create();
1394 UInt16 a, b;
1395 Real32 theta, phi;
1396 Real32 cosTheta, sinTheta;
1397 Real32 latDelta, longDelta;
1399 // calc the vertices
1401 GeoPnt3fProperty ::StoredFieldType *p = pnts ->editFieldPtr();
1402 GeoColor3fProperty::StoredFieldType *c = color->editFieldPtr();
1404 latDelta = Pi / (2 * latres);
1405 longDelta = Pi / (2 * longres);
1407 // float ea = 6378.137;
1408 // float eb = 6356.7523142;
1410 float rSemiMajorAxisSquare = rSemiMajorAxis * rSemiMajorAxis;
1412 float e2 = (rSemiMajorAxisSquare -
1413 rSemiMinorAxis * rSemiMinorAxis) / (rSemiMajorAxisSquare);
1415 for(a = 0, theta = 0; a <= latres; a++, theta += latDelta)
1417 cosTheta = osgCos(theta);
1418 sinTheta = osgSin(theta);
1420 float v = rSemiMajorAxis / osgSqrt(1 - (e2 * sinTheta * sinTheta));
1422 phi = 0;
1424 GLfloat cosPhi, sinPhi;
1426 cosPhi = osgCos(phi);
1427 sinPhi = osgSin(phi);
1430 p->push_back(Pnt3f(cosTheta * sinPhi * v,
1431 sinTheta * ((1 - e2) * v),
1432 cosTheta * cosPhi * v));
1434 c->push_back(Color3f(0.f, 1.f, 0.f));
1437 theta = 0;
1439 cosTheta = osgCos(theta);
1440 sinTheta = osgSin(theta);
1442 float v = rSemiMajorAxis / osgSqrt(1 - (e2 * sinTheta * sinTheta));
1444 for(b = 0, phi = 0; b <= longres; b++, phi += longDelta)
1446 GLfloat cosPhi, sinPhi;
1448 cosPhi = osgCos(phi);
1449 sinPhi = osgSin(phi);
1452 p->push_back(Pnt3f(cosTheta * sinPhi * v,
1453 sinTheta * ((1 - e2) * v),
1454 cosTheta * cosPhi * v));
1456 c->push_back(Color3f(1.f, 0.f, 0.f));
1460 // create the faces
1462 GeoUInt32Property::StoredFieldType *i = index->editFieldPtr();
1463 GeoUInt32Property::StoredFieldType *l = lens ->editFieldPtr();
1464 GeoUInt8Property ::StoredFieldType *t = types->editFieldPtr();
1466 t->push_back(GL_LINE_STRIP);
1467 l->push_back(latres + 1);
1469 t->push_back(GL_LINE_STRIP);
1470 l->push_back(longres + 1);
1472 for(a = 0; a <= latres; a++)
1474 i->push_back(a);
1477 for(b = 0; b <= longres; b++)
1479 i->push_back(b + a);
1482 // create the geometry
1484 GeometryUnrecPtr geo = Geometry::create();
1486 geo->setMaterial(getDefaultUnlitMaterial());
1487 geo->setPositions(pnts);
1488 geo->setColors(color);
1489 geo->setIndices(index);
1490 geo->setTypes(types);
1491 geo->setLengths(lens);
1493 return GeometryTransitPtr(geo);
1496 /*! create Ellipsoid axis node
1497 \ingroup GrpDrawablesGeometryUtils
1499 NodeTransitPtr makeEllipsoidAxis(UInt16 latres,
1500 UInt16 longres,
1501 Real32 rSemiMajorAxis,
1502 Real32 rSemiMinorAxis)
1504 GeometryTransitPtr pGeo = makeEllipsoidAxisGeo(latres,
1505 longres,
1506 rSemiMajorAxis,
1507 rSemiMinorAxis);
1509 if(pGeo == NULL)
1511 return NodeTransitPtr(NULL);
1514 NodeTransitPtr node = Node::create();
1516 node->setCore(pGeo);
1518 return node;
1521 /*! Creates a box around the origin. It spans the [-\a xsize /2,\a
1522 xsize /2] x [-\a ysize /2, \a ysize/2] x [-\a zsize /2,\a zsize/2] volume
1523 and is subdivided into \a hor * \a vert * \a depth quads.
1525 \param[in] xsize Length of edge along the x axis.
1526 \param[in] ysize Length of edge along the y axis.
1527 \param[in] zsize Length of edge along the z axis.
1528 \param[in] hor Number of quads along the x axis.
1529 \param[in] vert Number of quads along the y axis.
1530 \param[in] depth Number of quads along the z axis.
1531 \return NodeTransitPtr to a newly created Node with a Geometry core.
1533 \ingroup GrpDrawablesGeometryUtils
1535 NodeTransitPtr makeBox(Real32 xsize, Real32 ysize, Real32 zsize,
1536 UInt16 hor , UInt16 vert , UInt16 depth)
1538 GeometryTransitPtr pGeo = makeBoxGeo(xsize, ysize, zsize, hor, vert, depth);
1540 if(pGeo == NULL)
1542 return NodeTransitPtr(NULL);
1545 NodeTransitPtr node = Node::create();
1547 node->setCore(pGeo);
1549 return node;
1552 /*! Create the Geometry Core used by OSG::makeBox.
1554 \param[in] xsize Length of edge along the x axis.
1555 \param[in] ysize Length of edge along the y axis.
1556 \param[in] zsize Length of edge along the z axis.
1557 \param[in] hor Number of quads along the x axis.
1558 \param[in] vert Number of quads along the y axis.
1559 \param[in] depth Number of quads along the z axis.
1560 \return GeometryTransitPtr to a newly created Geometry core.
1562 \sa OSG::makeBox
1564 \ingroup GrpDrawablesGeometryUtils
1566 GeometryTransitPtr makeBoxGeo(Real32 xsize, Real32 ysize, Real32 zsize,
1567 UInt16 hor , UInt16 vert , UInt16 depth,
1568 bool bInv )
1570 if(! hor || ! vert || ! depth)
1572 SWARNING << "makeBox: illegal parameters hor=" << hor << ", vert="
1573 << vert << ", depth=" << depth << std::endl;
1574 return GeometryTransitPtr(NULL);
1577 GeoPnt3fPropertyUnrecPtr pnts = GeoPnt3fProperty ::create();
1578 GeoVec3fPropertyUnrecPtr norms = GeoVec3fProperty ::create();
1579 GeoVec2fPropertyUnrecPtr tex = GeoVec2fProperty ::create();
1580 GeoUInt32PropertyUnrecPtr index = GeoUInt32Property::create();
1581 GeoUInt32PropertyUnrecPtr lens = GeoUInt32Property::create();
1582 GeoUInt8PropertyUnrecPtr types = GeoUInt8Property ::create();
1584 UInt16 x,y,pl;
1585 Vec3f size(xsize, ysize, zsize);
1586 Vec3f step(xsize / hor, ysize / vert, zsize / depth);
1587 Vec3f res(hor, vert, depth);
1589 // calc the vertices
1591 GeoPnt3fProperty::StoredFieldType *p = pnts ->editFieldPtr();
1592 GeoVec3fProperty::StoredFieldType *n = norms->editFieldPtr();
1593 GeoVec2fProperty::StoredFieldType *tx = tex ->editFieldPtr();
1595 static int inds[6][2] = { {0,1}, {0,1}, {2,1}, {2,1}, {0,2}, {0,2} };
1596 static int signs[6][2] = { {1,1}, {-1,1}, {-1,1}, {1,1}, {1,-1}, {1,1} };
1597 static int asigns[6] = { 1, -1, 1, -1, 1, -1 };
1599 for(pl = 0; pl < 6; pl++)
1601 UInt16 axis = 3 - inds[pl][0] - inds[pl][1];
1603 for(y = 0; y <= res[inds[pl][1]] ; y++)
1605 for(x = 0; x <= res[inds[pl][0]]; x++)
1607 Pnt3f pnt;
1608 pnt[ inds[pl][0] ] = (x * step[inds[pl][0]] - size[inds[pl][0]] / 2) *
1609 signs[pl][0];
1610 pnt[ inds[pl][1] ] = (y * step[inds[pl][1]] - size[inds[pl][1]] / 2) *
1611 signs[pl][1];
1612 pnt[ axis ] = size[ axis ] * asigns[ pl ] / 2;
1613 p->push_back(pnt);
1615 Vec3f norm(0, 0, 0);
1616 norm[ axis ] = Real32(asigns[ pl ]);
1618 if(bInv == true)
1620 norm *= -1;
1623 n->push_back(norm);
1624 tx->push_back(Vec2f(x / Real32(res[inds[pl][0]]),
1625 y / Real32(res[inds[pl][1]])));
1630 // create the faces
1632 GeoUInt32Property::StoredFieldType *i = index->editFieldPtr();
1633 GeoUInt32Property::StoredFieldType *l = lens ->editFieldPtr();
1634 GeoUInt8Property::StoredFieldType *t = types->editFieldPtr();
1636 UInt32 basepoint = 0;
1638 for(pl = 0; pl < 6; pl++)
1640 for(y = 0; y < res[inds[pl][1]]; y++)
1642 UInt16 h = UInt16(res[inds[pl][0]]);
1644 t->push_back(GL_TRIANGLE_STRIP);
1645 l->push_back(2 * (h + 1));
1647 for(x = 0; x <= h; x++)
1649 if(bInv == true)
1651 i->push_back(basepoint + y * (h + 1) + x);
1652 i->push_back(basepoint + (y + 1) * (h + 1) + x);
1654 else
1656 i->push_back(basepoint + (y + 1) * (h + 1) + x);
1657 i->push_back(basepoint + y * (h + 1) + x);
1661 basepoint += UInt32((res[inds[pl][0]] + 1.f) *
1662 (res[inds[pl][1]] + 1.f) );
1665 // create the geometry
1667 GeometryTransitPtr geo = Geometry::create();
1669 geo->setMaterial(getDefaultMaterial());
1670 geo->setPositions(pnts);
1671 geo->setNormals(norms);
1672 geo->setTexCoords(tex);
1673 geo->setIndices(index);
1674 geo->setTypes(types);
1675 geo->setLengths(lens);
1677 return geo;
1680 /*! Create a model of the famous Utah teapot, based on Eric Haines' SPD code
1681 (http://www1.acm.org/tog/resources/SPD).
1683 \param[in] depth Subdivision depth.
1684 \param[in] rScale Rescale the Teapot
1685 \return NodeTransitPtr to a newly created Node with a Geometry core.
1687 \ingroup GrpDrawablesGeometryUtils
1689 NodeTransitPtr makeTeapot(UInt16 depth, Real32 rScale)
1691 GeometryTransitPtr pGeo = makeTeapotGeo(depth, rScale);
1693 if(pGeo == NULL)
1695 return NodeTransitPtr(NULL);
1698 NodeTransitPtr node = Node::create();
1700 node->setCore(pGeo);
1702 return node;
1705 namespace {
1707 // Teapot data and helper functions
1709 /* Teapot function. Taken from Eric Haines' SPD package
1710 (http://www1.acm.org/tog/resources/SPD)
1712 Slightly C++-ized for OpenSG
1715 /* comment out the next line to generate all patches except the bottom,
1716 * i.e. the original Newell teapot
1718 #define BOTTOM
1720 #ifdef BOTTOM
1721 #define NUM_PATCHES 32
1722 #else
1723 #define NUM_PATCHES 28
1724 #endif
1726 static int Patches[32][4][4] = {
1727 /* rim */
1728 {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}, {12, 13, 14, 15}},
1729 {{3, 16, 17, 18}, {7, 19, 20, 21}, {11, 22, 23, 24}, {15, 25, 26, 27}},
1730 {{18, 28, 29, 30}, {21, 31, 32, 33}, {24, 34, 35, 36}, {27, 37, 38, 39}},
1731 {{30, 40, 41, 0}, {33, 42, 43, 4}, {36, 44, 45, 8}, {39, 46, 47, 12}},
1732 /* body */
1733 {{12, 13, 14, 15}, {48, 49, 50, 51}, {52, 53, 54, 55}, {56, 57, 58, 59}},
1734 {{15, 25, 26, 27}, {51, 60, 61, 62}, {55, 63, 64, 65}, {59, 66, 67, 68}},
1735 {{27, 37, 38, 39}, {62, 69, 70, 71}, {65, 72, 73, 74}, {68, 75, 76, 77}},
1736 {{39, 46, 47, 12}, {71, 78, 79, 48}, {74, 80, 81, 52}, {77, 82, 83, 56}},
1737 {{56, 57, 58, 59}, {84, 85, 86, 87}, {88, 89, 90, 91}, {92, 93, 94, 95}},
1738 {{59, 66, 67, 68}, {87, 96, 97, 98}, {91, 99, 100, 101}, {95, 102, 103, 104}},
1739 {{68, 75, 76, 77}, {98, 105, 106, 107}, {101, 108, 109, 110}, {104, 111, 112, 113}},
1740 {{77, 82, 83, 56}, {107, 114, 115, 84}, {110, 116, 117, 88}, {113, 118, 119, 92}},
1741 /* handle */
1742 {{120, 121, 122, 123}, {124, 125, 126, 127}, {128, 129, 130, 131}, {132, 133, 134, 135}},
1743 {{123, 136, 137, 120}, {127, 138, 139, 124}, {131, 140, 141, 128}, {135, 142, 143, 132}},
1744 {{132, 133, 134, 135}, {144, 145, 146, 147}, {148, 149, 150, 151}, {68, 152, 153, 154}},
1745 {{135, 142, 143, 132}, {147, 155, 156, 144}, {151, 157, 158, 148}, {154, 159, 160, 68}},
1746 /* spout */
1747 {{161, 162, 163, 164}, {165, 166, 167, 168}, {169, 170, 171, 172}, {173, 174, 175, 176}},
1748 {{164, 177, 178, 161}, {168, 179, 180, 165}, {172, 181, 182, 169}, {176, 183, 184, 173}},
1749 {{173, 174, 175, 176}, {185, 186, 187, 188}, {189, 190, 191, 192}, {193, 194, 195, 196}},
1750 {{176, 183, 184, 173}, {188, 197, 198, 185}, {192, 199, 200, 189}, {196, 201, 202, 193}},
1751 /* lid */
1752 {{203, 203, 203, 203}, {204, 205, 206, 207}, {208, 208, 208, 208}, {209, 210, 211, 212}},
1753 {{203, 203, 203, 203}, {207, 213, 214, 215}, {208, 208, 208, 208}, {212, 216, 217, 218}},
1754 {{203, 203, 203, 203}, {215, 219, 220, 221}, {208, 208, 208, 208}, {218, 222, 223, 224}},
1755 {{203, 203, 203, 203}, {221, 225, 226, 204}, {208, 208, 208, 208}, {224, 227, 228, 209}},
1756 {{209, 210, 211, 212}, {229, 230, 231, 232}, {233, 234, 235, 236}, {237, 238, 239, 240}},
1757 {{212, 216, 217, 218}, {232, 241, 242, 243}, {236, 244, 245, 246}, {240, 247, 248, 249}},
1758 {{218, 222, 223, 224}, {243, 250, 251, 252}, {246, 253, 254, 255}, {249, 256, 257, 258}},
1759 {{224, 227, 228, 209}, {252, 259, 260, 229}, {255, 261, 262, 233}, {258, 263, 264, 237}},
1760 /* bottom */
1761 {{265, 265, 265, 265}, {266, 267, 268, 269}, {270, 271, 272, 273}, {92, 119, 118, 113}},
1762 {{265, 265, 265, 265}, {269, 274, 275, 276}, {273, 277, 278, 279}, {113, 112, 111, 104}},
1763 {{265, 265, 265, 265}, {276, 280, 281, 282}, {279, 283, 284, 285}, {104, 103, 102, 95}},
1764 {{265, 265, 265, 265}, {282, 286, 287, 266}, {285, 288, 289, 270}, {95, 94, 93, 92}}
1767 static Vec3f Verts[290] = {
1768 Vec3f(1.4, 0, 2.4),
1769 Vec3f(1.4, -0.784, 2.4),
1770 Vec3f(0.784, -1.4, 2.4),
1771 Vec3f(0, -1.4, 2.4),
1772 Vec3f(1.3375, 0, 2.53125),
1773 Vec3f(1.3375, -0.749, 2.53125),
1774 Vec3f(0.749, -1.3375, 2.53125),
1775 Vec3f(0, -1.3375, 2.53125),
1776 Vec3f(1.4375, 0, 2.53125),
1777 Vec3f(1.4375, -0.805, 2.53125),
1778 Vec3f(0.805, -1.4375, 2.53125),
1779 Vec3f(0, -1.4375, 2.53125),
1780 Vec3f(1.5, 0, 2.4),
1781 Vec3f(1.5, -0.84, 2.4),
1782 Vec3f(0.84, -1.5, 2.4),
1783 Vec3f(0, -1.5, 2.4),
1784 Vec3f(-0.784, -1.4, 2.4),
1785 Vec3f(-1.4, -0.784, 2.4),
1786 Vec3f(-1.4, 0, 2.4),
1787 Vec3f(-0.749, -1.3375, 2.53125),
1788 Vec3f(-1.3375, -0.749, 2.53125),
1789 Vec3f(-1.3375, 0, 2.53125),
1790 Vec3f(-0.805, -1.4375, 2.53125),
1791 Vec3f(-1.4375, -0.805, 2.53125),
1792 Vec3f(-1.4375, 0, 2.53125),
1793 Vec3f(-0.84, -1.5, 2.4),
1794 Vec3f(-1.5, -0.84, 2.4),
1795 Vec3f(-1.5, 0, 2.4),
1796 Vec3f(-1.4, 0.784, 2.4),
1797 Vec3f(-0.784, 1.4, 2.4),
1798 Vec3f(0, 1.4, 2.4),
1799 Vec3f(-1.3375, 0.749, 2.53125),
1800 Vec3f(-0.749, 1.3375, 2.53125),
1801 Vec3f(0, 1.3375, 2.53125),
1802 Vec3f(-1.4375, 0.805, 2.53125),
1803 Vec3f(-0.805, 1.4375, 2.53125),
1804 Vec3f(0, 1.4375, 2.53125),
1805 Vec3f(-1.5, 0.84, 2.4),
1806 Vec3f(-0.84, 1.5, 2.4),
1807 Vec3f(0, 1.5, 2.4),
1808 Vec3f(0.784, 1.4, 2.4),
1809 Vec3f(1.4, 0.784, 2.4),
1810 Vec3f(0.749, 1.3375, 2.53125),
1811 Vec3f(1.3375, 0.749, 2.53125),
1812 Vec3f(0.805, 1.4375, 2.53125),
1813 Vec3f(1.4375, 0.805, 2.53125),
1814 Vec3f(0.84, 1.5, 2.4),
1815 Vec3f(1.5, 0.84, 2.4),
1816 Vec3f(1.75, 0, 1.875),
1817 Vec3f(1.75, -0.98, 1.875),
1818 Vec3f(0.98, -1.75, 1.875),
1819 Vec3f(0, -1.75, 1.875),
1820 Vec3f(2, 0, 1.35),
1821 Vec3f(2, -1.12, 1.35),
1822 Vec3f(1.12, -2, 1.35),
1823 Vec3f(0, -2, 1.35),
1824 Vec3f(2, 0, 0.9),
1825 Vec3f(2, -1.12, 0.9),
1826 Vec3f(1.12, -2, 0.9),
1827 Vec3f(0, -2, 0.9),
1828 Vec3f(-0.98, -1.75, 1.875),
1829 Vec3f(-1.75, -0.98, 1.875),
1830 Vec3f(-1.75, 0, 1.875),
1831 Vec3f(-1.12, -2, 1.35),
1832 Vec3f(-2, -1.12, 1.35),
1833 Vec3f(-2, 0, 1.35),
1834 Vec3f(-1.12, -2, 0.9),
1835 Vec3f(-2, -1.12, 0.9),
1836 Vec3f(-2, 0, 0.9),
1837 Vec3f(-1.75, 0.98, 1.875),
1838 Vec3f(-0.98, 1.75, 1.875),
1839 Vec3f(0, 1.75, 1.875),
1840 Vec3f(-2, 1.12, 1.35),
1841 Vec3f(-1.12, 2, 1.35),
1842 Vec3f(0, 2, 1.35),
1843 Vec3f(-2, 1.12, 0.9),
1844 Vec3f(-1.12, 2, 0.9),
1845 Vec3f(0, 2, 0.9),
1846 Vec3f(0.98, 1.75, 1.875),
1847 Vec3f(1.75, 0.98, 1.875),
1848 Vec3f(1.12, 2, 1.35),
1849 Vec3f(2, 1.12, 1.35),
1850 Vec3f(1.12, 2, 0.9),
1851 Vec3f(2, 1.12, 0.9),
1852 Vec3f(2, 0, 0.45),
1853 Vec3f(2, -1.12, 0.45),
1854 Vec3f(1.12, -2, 0.45),
1855 Vec3f(0, -2, 0.45),
1856 Vec3f(1.5, 0, 0.225),
1857 Vec3f(1.5, -0.84, 0.225),
1858 Vec3f(0.84, -1.5, 0.225),
1859 Vec3f(0, -1.5, 0.225),
1860 Vec3f(1.5, 0, 0.15),
1861 Vec3f(1.5, -0.84, 0.15),
1862 Vec3f(0.84, -1.5, 0.15),
1863 Vec3f(0, -1.5, 0.15),
1864 Vec3f(-1.12, -2, 0.45),
1865 Vec3f(-2, -1.12, 0.45),
1866 Vec3f(-2, 0, 0.45),
1867 Vec3f(-0.84, -1.5, 0.225),
1868 Vec3f(-1.5, -0.84, 0.225),
1869 Vec3f(-1.5, 0, 0.225),
1870 Vec3f(-0.84, -1.5, 0.15),
1871 Vec3f(-1.5, -0.84, 0.15),
1872 Vec3f(-1.5, 0, 0.15),
1873 Vec3f(-2, 1.12, 0.45),
1874 Vec3f(-1.12, 2, 0.45),
1875 Vec3f(0, 2, 0.45),
1876 Vec3f(-1.5, 0.84, 0.225),
1877 Vec3f(-0.84, 1.5, 0.225),
1878 Vec3f(0, 1.5, 0.225),
1879 Vec3f(-1.5, 0.84, 0.15),
1880 Vec3f(-0.84, 1.5, 0.15),
1881 Vec3f(0, 1.5, 0.15),
1882 Vec3f(1.12, 2, 0.45),
1883 Vec3f(2, 1.12, 0.45),
1884 Vec3f(0.84, 1.5, 0.225),
1885 Vec3f(1.5, 0.84, 0.225),
1886 Vec3f(0.84, 1.5, 0.15),
1887 Vec3f(1.5, 0.84, 0.15),
1888 Vec3f(-1.6, 0, 2.025),
1889 Vec3f(-1.6, -0.3, 2.025),
1890 Vec3f(-1.5, -0.3, 2.25),
1891 Vec3f(-1.5, 0, 2.25),
1892 Vec3f(-2.3, 0, 2.025),
1893 Vec3f(-2.3, -0.3, 2.025),
1894 Vec3f(-2.5, -0.3, 2.25),
1895 Vec3f(-2.5, 0, 2.25),
1896 Vec3f(-2.7, 0, 2.025),
1897 Vec3f(-2.7, -0.3, 2.025),
1898 Vec3f(-3, -0.3, 2.25),
1899 Vec3f(-3, 0, 2.25),
1900 Vec3f(-2.7, 0, 1.8),
1901 Vec3f(-2.7, -0.3, 1.8),
1902 Vec3f(-3, -0.3, 1.8),
1903 Vec3f(-3, 0, 1.8),
1904 Vec3f(-1.5, 0.3, 2.25),
1905 Vec3f(-1.6, 0.3, 2.025),
1906 Vec3f(-2.5, 0.3, 2.25),
1907 Vec3f(-2.3, 0.3, 2.025),
1908 Vec3f(-3, 0.3, 2.25),
1909 Vec3f(-2.7, 0.3, 2.025),
1910 Vec3f(-3, 0.3, 1.8),
1911 Vec3f(-2.7, 0.3, 1.8),
1912 Vec3f(-2.7, 0, 1.575),
1913 Vec3f(-2.7, -0.3, 1.575),
1914 Vec3f(-3, -0.3, 1.35),
1915 Vec3f(-3, 0, 1.35),
1916 Vec3f(-2.5, 0, 1.125),
1917 Vec3f(-2.5, -0.3, 1.125),
1918 Vec3f(-2.65, -0.3, 0.9375),
1919 Vec3f(-2.65, 0, 0.9375),
1920 Vec3f(-2, -0.3, 0.9),
1921 Vec3f(-1.9, -0.3, 0.6),
1922 Vec3f(-1.9, 0, 0.6),
1923 Vec3f(-3, 0.3, 1.35),
1924 Vec3f(-2.7, 0.3, 1.575),
1925 Vec3f(-2.65, 0.3, 0.9375),
1926 Vec3f(-2.5, 0.3, 1.125),
1927 Vec3f(-1.9, 0.3, 0.6),
1928 Vec3f(-2, 0.3, 0.9),
1929 Vec3f(1.7, 0, 1.425),
1930 Vec3f(1.7, -0.66, 1.425),
1931 Vec3f(1.7, -0.66, 0.6),
1932 Vec3f(1.7, 0, 0.6),
1933 Vec3f(2.6, 0, 1.425),
1934 Vec3f(2.6, -0.66, 1.425),
1935 Vec3f(3.1, -0.66, 0.825),
1936 Vec3f(3.1, 0, 0.825),
1937 Vec3f(2.3, 0, 2.1),
1938 Vec3f(2.3, -0.25, 2.1),
1939 Vec3f(2.4, -0.25, 2.025),
1940 Vec3f(2.4, 0, 2.025),
1941 Vec3f(2.7, 0, 2.4),
1942 Vec3f(2.7, -0.25, 2.4),
1943 Vec3f(3.3, -0.25, 2.4),
1944 Vec3f(3.3, 0, 2.4),
1945 Vec3f(1.7, 0.66, 0.6),
1946 Vec3f(1.7, 0.66, 1.425),
1947 Vec3f(3.1, 0.66, 0.825),
1948 Vec3f(2.6, 0.66, 1.425),
1949 Vec3f(2.4, 0.25, 2.025),
1950 Vec3f(2.3, 0.25, 2.1),
1951 Vec3f(3.3, 0.25, 2.4),
1952 Vec3f(2.7, 0.25, 2.4),
1953 Vec3f(2.8, 0, 2.475),
1954 Vec3f(2.8, -0.25, 2.475),
1955 Vec3f(3.525, -0.25, 2.49375),
1956 Vec3f(3.525, 0, 2.49375),
1957 Vec3f(2.9, 0, 2.475),
1958 Vec3f(2.9, -0.15, 2.475),
1959 Vec3f(3.45, -0.15, 2.5125),
1960 Vec3f(3.45, 0, 2.5125),
1961 Vec3f(2.8, 0, 2.4),
1962 Vec3f(2.8, -0.15, 2.4),
1963 Vec3f(3.2, -0.15, 2.4),
1964 Vec3f(3.2, 0, 2.4),
1965 Vec3f(3.525, 0.25, 2.49375),
1966 Vec3f(2.8, 0.25, 2.475),
1967 Vec3f(3.45, 0.15, 2.5125),
1968 Vec3f(2.9, 0.15, 2.475),
1969 Vec3f(3.2, 0.15, 2.4),
1970 Vec3f(2.8, 0.15, 2.4),
1971 Vec3f(0, 0, 3.15),
1972 Vec3f(0.8, 0, 3.15),
1973 Vec3f(0.8, -0.45, 3.15),
1974 Vec3f(0.45, -0.8, 3.15),
1975 Vec3f(0, -0.8, 3.15),
1976 Vec3f(0, 0, 2.85),
1977 Vec3f(0.2, 0, 2.7),
1978 Vec3f(0.2, -0.112, 2.7),
1979 Vec3f(0.112, -0.2, 2.7),
1980 Vec3f(0, -0.2, 2.7),
1981 Vec3f(-0.45, -0.8, 3.15),
1982 Vec3f(-0.8, -0.45, 3.15),
1983 Vec3f(-0.8, 0, 3.15),
1984 Vec3f(-0.112, -0.2, 2.7),
1985 Vec3f(-0.2, -0.112, 2.7),
1986 Vec3f(-0.2, 0, 2.7),
1987 Vec3f(-0.8, 0.45, 3.15),
1988 Vec3f(-0.45, 0.8, 3.15),
1989 Vec3f(0, 0.8, 3.15),
1990 Vec3f(-0.2, 0.112, 2.7),
1991 Vec3f(-0.112, 0.2, 2.7),
1992 Vec3f(0, 0.2, 2.7),
1993 Vec3f(0.45, 0.8, 3.15),
1994 Vec3f(0.8, 0.45, 3.15),
1995 Vec3f(0.112, 0.2, 2.7),
1996 Vec3f(0.2, 0.112, 2.7),
1997 Vec3f(0.4, 0, 2.55),
1998 Vec3f(0.4, -0.224, 2.55),
1999 Vec3f(0.224, -0.4, 2.55),
2000 Vec3f(0, -0.4, 2.55),
2001 Vec3f(1.3, 0, 2.55),
2002 Vec3f(1.3, -0.728, 2.55),
2003 Vec3f(0.728, -1.3, 2.55),
2004 Vec3f(0, -1.3, 2.55),
2005 Vec3f(1.3, 0, 2.4),
2006 Vec3f(1.3, -0.728, 2.4),
2007 Vec3f(0.728, -1.3, 2.4),
2008 Vec3f(0, -1.3, 2.4),
2009 Vec3f(-0.224, -0.4, 2.55),
2010 Vec3f(-0.4, -0.224, 2.55),
2011 Vec3f(-0.4, 0, 2.55),
2012 Vec3f(-0.728, -1.3, 2.55),
2013 Vec3f(-1.3, -0.728, 2.55),
2014 Vec3f(-1.3, 0, 2.55),
2015 Vec3f(-0.728, -1.3, 2.4),
2016 Vec3f(-1.3, -0.728, 2.4),
2017 Vec3f(-1.3, 0, 2.4),
2018 Vec3f(-0.4, 0.224, 2.55),
2019 Vec3f(-0.224, 0.4, 2.55),
2020 Vec3f(0, 0.4, 2.55),
2021 Vec3f(-1.3, 0.728, 2.55),
2022 Vec3f(-0.728, 1.3, 2.55),
2023 Vec3f(0, 1.3, 2.55),
2024 Vec3f(-1.3, 0.728, 2.4),
2025 Vec3f(-0.728, 1.3, 2.4),
2026 Vec3f(0, 1.3, 2.4),
2027 Vec3f(0.224, 0.4, 2.55),
2028 Vec3f(0.4, 0.224, 2.55),
2029 Vec3f(0.728, 1.3, 2.55),
2030 Vec3f(1.3, 0.728, 2.55),
2031 Vec3f(0.728, 1.3, 2.4),
2032 Vec3f(1.3, 0.728, 2.4),
2033 Vec3f(0, 0, 0),
2034 Vec3f(1.425, 0, 0),
2035 Vec3f(1.425, 0.798, 0),
2036 Vec3f(0.798, 1.425, 0),
2037 Vec3f(0, 1.425, 0),
2038 Vec3f(1.5, 0, 0.075),
2039 Vec3f(1.5, 0.84, 0.075),
2040 Vec3f(0.84, 1.5, 0.075),
2041 Vec3f(0, 1.5, 0.075),
2042 Vec3f(-0.798, 1.425, 0),
2043 Vec3f(-1.425, 0.798, 0),
2044 Vec3f(-1.425, 0, 0),
2045 Vec3f(-0.84, 1.5, 0.075),
2046 Vec3f(-1.5, 0.84, 0.075),
2047 Vec3f(-1.5, 0, 0.075),
2048 Vec3f(-1.425, -0.798, 0),
2049 Vec3f(-0.798, -1.425, 0),
2050 Vec3f(0, -1.425, 0),
2051 Vec3f(-1.5, -0.84, 0.075),
2052 Vec3f(-0.84, -1.5, 0.075),
2053 Vec3f(0, -1.5, 0.075),
2054 Vec3f(0.798, -1.425, 0),
2055 Vec3f(1.425, -0.798, 0),
2056 Vec3f(0.84, -1.5, 0.075),
2057 Vec3f(1.5, -0.84, 0.075)
2060 /* at the center of the lid's handle and at bottom are cusp points -
2061 * check if normal is (0 0 0), if so, check that polygon is not degenerate.
2062 * If degenerate, return FALSE, else set normal.
2064 static bool
2065 check_for_cusp( int tot_vert, Pnt3f vert[], Vec3f norm[] )
2067 int count, i, nv ;
2069 for(count = 0, i = tot_vert; i--; )
2071 /* check if vertex is at cusp */
2072 if(osgAbs(vert[i][0]) < 0.0001 &&
2073 osgAbs(vert[i][1]) < 0.0001 )
2075 count++;
2076 nv = i;
2080 if(count > 1)
2082 /* degenerate */
2083 return false;
2085 if(count == 1)
2087 /* check if point is somewhere above the middle of the teapot */
2088 if(vert[nv][2] > 1.5)
2090 /* cusp at lid */
2091 norm[nv].setValues(0.0, 0.0, 1.0);
2093 else
2095 /* cusp at bottom */
2096 norm[nv].setValues(0.0, 0.0, -1.0);
2099 return true;
2102 static void
2103 points_from_basis(int tot_vert, Real64 s[], Real64 t[], Matrix mgm[3],
2104 Pnt3f vert[], Vec3f norm[] )
2106 int i, num_vert, p;
2107 double sval, tval, dsval, dtval, sxyz, txyz;
2108 Vec3f sdir, tdir;
2109 Vec4f sp, tp, dsp, dtp, tcoord;
2111 for(num_vert = 0; num_vert < tot_vert; num_vert++)
2113 sxyz = s[num_vert] ;
2114 txyz = t[num_vert] ;
2116 /* get power vectors and their derivatives */
2117 for(p = 4, sval = tval = 1.0; p--; )
2119 sp[p] = sval;
2120 tp[p] = tval;
2121 sval *= sxyz;
2122 tval *= txyz;
2124 if(p == 3)
2126 dsp[p] = dtp[p] = 0.0;
2127 dsval = dtval = 1.0;
2129 else
2131 dsp[p] = dsval * static_cast<double>(3 - p);
2132 dtp[p] = dtval * static_cast<double>(3 - p);
2133 dsval *= sxyz;
2134 dtval *= txyz;
2138 /* do for x,y,z */
2139 for(i = 0; i < 3; ++i)
2141 /* multiply power vectors times matrix to get value */
2142 mgm[i].mult(sp, tcoord);
2143 vert[num_vert][i] = tcoord.dot(tp);
2145 /* get s and t tangent vectors */
2146 mgm[i].mult(dsp, tcoord);
2147 sdir[i] = tcoord.dot(tp);
2149 mgm[i].mult(sp, tcoord);
2150 tdir[i] = tcoord.dot(dtp);
2153 /* find normal */
2154 norm[num_vert] = tdir.cross(sdir);
2155 norm[num_vert].normalize();
2159 } // namespace
2161 /*! Create the Geometry Core used by OSG::makeTeapot.
2163 \param[in] depth Subdivision depth.
2164 \param[in] rScale Teapot scale.
2165 \return GeometryTransitPtr to a newly created Geometry core.
2167 \sa OSG::makeTeapot
2169 \ingroup GrpDrawablesGeometryUtils
2171 GeometryTransitPtr makeTeapotGeo(UInt16 depth, Real32 rScale)
2173 GeoPnt3fPropertyUnrecPtr pnts = GeoPnt3fProperty ::create();
2174 GeoVec3fPropertyUnrecPtr norms = GeoVec3fProperty ::create();
2175 GeoUInt32PropertyUnrecPtr lens = GeoUInt32Property::create();
2176 GeoUInt8PropertyUnrecPtr types = GeoUInt8Property ::create();
2178 // calc the triangles
2180 GeoPnt3fProperty::StoredFieldType *p = pnts ->editFieldPtr();
2181 GeoVec3fProperty::StoredFieldType *n = norms->editFieldPtr();
2183 UInt32 vcount = 0;
2185 /* bezier form */
2186 static Matrix ms( -1.0, 3.0, -3.0, 1.0,
2187 3.0, -6.0, 3.0, 0.0,
2188 -3.0, 3.0, 0.0, 0.0,
2189 1.0, 0.0, 0.0, 0.0 );
2190 int surf, i, r, c, sstep, tstep, num_tri, num_vert, num_tri_vert;
2191 double s[3], t[3];
2192 Pnt3f vert[4];
2193 Vec3f norm[4];
2194 Matrix mst, g, mgm[3], tmtx;
2196 mst.transposeFrom(ms);
2198 for(surf = 0; surf < NUM_PATCHES; ++surf)
2200 /* get M * G * M matrix for x,y,z */
2201 for(i = 0; i < 3; ++i)
2203 /* get control patches */
2204 for(r = 0; r < 4 ; ++r)
2206 for(c = 0; c < 4; ++c)
2208 g[r][c] = Verts[Patches[surf][r][c]][i];
2212 tmtx = ms;
2213 tmtx.mult(g);
2214 tmtx.mult(mst);
2215 mgm[i] = tmtx;
2218 /* step along, get points, and output */
2219 for(sstep = 0; sstep < depth; ++sstep)
2221 for(tstep = 0; tstep < depth; ++tstep)
2223 for(num_tri = 0; num_tri < 2; ++num_tri)
2225 for(num_vert = 0; num_vert < 3; ++num_vert)
2227 num_tri_vert = (num_vert + num_tri * 2) % 4;
2228 /* trickiness: add 1 to sstep if 1 or 2 */
2229 s[num_vert] = static_cast<double>(
2230 sstep + (num_tri_vert / 2 ? 1 : 0)) /
2231 static_cast<double>(depth);
2233 /* trickiness: add 1 to tstep if 2 or 3 */
2234 t[num_vert] = static_cast<double>(
2235 tstep + (num_tri_vert % 3 ? 1 : 0)) /
2236 static_cast<double>(depth);
2238 points_from_basis(3, s, t, mgm, vert, norm);
2239 /* don't output degenerate polygons */
2240 if(check_for_cusp( 3, vert, norm))
2242 vert[0] *= rScale;
2243 vert[1] *= rScale;
2244 vert[2] *= rScale;
2246 p->push_back(vert[0]);
2247 p->push_back(vert[1]);
2248 p->push_back(vert[2]);
2250 n->push_back(norm[0]);
2251 n->push_back(norm[1]);
2252 n->push_back(norm[2]);
2254 vcount += 3;
2261 types->push_back(GL_TRIANGLES);
2262 lens ->push_back(vcount);
2264 // create the geometry
2266 GeometryTransitPtr geo = Geometry::create();
2268 geo->setMaterial(getDefaultMaterial());
2269 geo->setPositions(pnts);
2270 geo->setNormals(norms);
2271 geo->setTypes(types);
2272 geo->setLengths(lens);
2274 return geo;
2277 /*! Create coord axis node
2278 \ingroup GrpDrawablesGeometryUtils
2280 NodeTransitPtr makeCoordAxis(Real32 length, Real32 lineWidth, bool showAxisName)
2282 GeometryTransitPtr pGeo = makeCoordAxisGeo(length, lineWidth, showAxisName);
2284 if(pGeo == NULL)
2286 return NodeTransitPtr(NULL);
2289 NodeTransitPtr node = Node::create();
2291 node->setCore(pGeo);
2293 return node;
2296 /*! Create coord axis geometry
2297 \ingroup GrpDrawablesGeometryUtils
2299 GeometryTransitPtr makeCoordAxisGeo(Real32 length,
2300 Real32 lineWidth,
2301 bool showAxisName)
2303 GeoPnt3fPropertyUnrecPtr pnts = GeoPnt3fProperty ::create();
2304 GeoUInt32PropertyUnrecPtr lens = GeoUInt32Property::create();
2305 GeoUInt8PropertyUnrecPtr types = GeoUInt8Property ::create();
2306 GeoColor3fPropertyUnrecPtr colors = GeoColor3fProperty::create();
2308 Int32 pntCnt=0;
2310 GeoPnt3fProperty::StoredFieldType *p = pnts ->editFieldPtr();
2311 GeoUInt32Property::StoredFieldType *l = lens ->editFieldPtr();
2312 GeoUInt8Property::StoredFieldType *t = types->editFieldPtr();
2313 GeoColor3fProperty::StoredFieldType *c = colors->editFieldPtr();
2315 // the x-axis coords and colors
2316 p->push_back( Pnt3f(0,0,0) );
2317 p->push_back( Pnt3f(length,0,0) );
2318 pntCnt += 2;
2319 c->push_back( Color3f(1,0,0) );
2320 c->push_back( Color3f(1,0,0) );
2322 // the y-axis coords and colors
2323 p->push_back( Pnt3f(0,0,0) );
2324 p->push_back( Pnt3f(0,length,0) );
2325 pntCnt += 2;
2326 c->push_back( Color3f(0,1,0) );
2327 c->push_back( Color3f(0,1,0) );
2329 // the z-axis coords and colors
2330 p->push_back( Pnt3f(0,0,0) );
2331 p->push_back( Pnt3f(0,0,length) );
2332 pntCnt += 2;
2333 c->push_back( Color3f(0,0,1) );
2334 c->push_back( Color3f(0,0,1) );
2336 if( showAxisName )
2338 // the x text (drawn with lines)
2339 p->push_back( Pnt3f(length, 0.125, 0) );
2340 p->push_back( Pnt3f(length+0.25, -0.125, 0) );
2341 p->push_back( Pnt3f(length,-0.125,0) );
2342 p->push_back( Pnt3f(length+0.25,0.125,0) );
2343 pntCnt += 4;
2344 for (unsigned i=0;i<4;i++)
2345 { c->push_back( Color3f(1,0,0) ); }
2347 // the y text (drawn with lines)
2348 p->push_back( Pnt3f(-0.125, length, 0) );
2349 p->push_back( Pnt3f( 0.125, length+0.25, 0) );
2350 p->push_back( Pnt3f(-0.125, length+0.25, 0) );
2351 p->push_back( Pnt3f( 0.000, length+0.125,0) );
2352 pntCnt += 4;
2353 for (unsigned i=0;i<4;i++)
2354 { c->push_back( Color3f(0,1,0) ); }
2356 // the z text (drawn with lines)
2357 p->push_back( Pnt3f(-0.125, 0, length) );
2358 p->push_back( Pnt3f( 0.125, 0, length) );
2359 p->push_back( Pnt3f( 0.125, 0, length) );
2360 p->push_back( Pnt3f(-0.125, 0, length+0.25) );
2361 p->push_back( Pnt3f(-0.125, 0, length+0.25) );
2362 p->push_back( Pnt3f( 0.125, 0, length+0.25) );
2363 pntCnt += 6;
2364 for (unsigned i=0;i<6;i++)
2365 { c->push_back( Color3f(0,0,1) ); }
2369 //SLOG << "CoordAxis has " << pntCnt << " points.\n" << endl;
2370 t->push_back(GL_LINES);
2371 l->push_back(pntCnt);
2373 LineChunkUnrecPtr lineChunk = LineChunk::create();
2375 lineChunk->setWidth(lineWidth);
2377 SimpleMaterialUnrecPtr mat = SimpleMaterial::create();
2379 mat->setLit(false);
2380 mat->addChunk(lineChunk);
2381 #if !defined(OSG_OGL_COREONLY) || defined(OSG_CHECK_COREONLY)
2382 mat->setColorMaterial(GL_AMBIENT_AND_DIFFUSE);
2383 #endif
2385 GeometryTransitPtr geo = Geometry::create();
2386 geo->setMaterial(mat);
2387 geo->setPositions(pnts);
2388 geo->setTypes(types);
2389 geo->setLengths(lens);
2390 geo->setColors(colors);
2392 return geo;
2394 OSG_END_NAMESPACE