1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
7 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
9 \*---------------------------------------------------------------------------*/
10 /*---------------------------------------------------------------------------*\
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. *
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. *
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. *
26 \*---------------------------------------------------------------------------*/
27 /*---------------------------------------------------------------------------*\
35 \*---------------------------------------------------------------------------*/
38 #pragma warning( disable : 4305 )
41 //---------------------------------------------------------------------------
43 //---------------------------------------------------------------------------
48 #include "OSGConfig.h"
50 #include "OSGFrustumVolume.h"
51 #include "OSGQuaternion.h"
52 #include "OSGMaterial.h"
53 #include "OSGSimpleMaterial.h"
54 #include "OSGLineChunk.h"
55 #include "OSGGeoProperties.h"
56 #include "OSGSimpleLightGeometry.h" // for DefaultMaterials
57 #include "OSGTypedGeoIntegralProperty.h"
58 #include "OSGTypedGeoVectorProperty.h"
62 /***************************************************************************\
64 \***************************************************************************/
66 #if defined(OSG_WIN32_ICL) && !defined(OSG_CHECK_FIELDSETARG)
67 #pragma warning (disable : 383)
70 // The Simple Light Geometry creation functions
73 // Attention: the created geometry from these functions do not contain
74 // texture coordinates.
77 /*! Creates a spot light with spot direction in +y-direction with the tip
78 of the spot at (0,0,0).
80 \param[in] R is the spot range/radius of influence
81 \param[in] angle is the spot half angle in radians
82 \param[in] slices is the number of subdivisions in y-Dir, i.e. in spot direction
83 \param[in] sides is the number of circle subdivisions
84 \return NodeTransitPtr to a newly created Node with a Geometry core.
86 \ingroup GrpDrawablesGeometryUtils
88 NodeTransitPtr
makeSpot(
94 GeometryTransitPtr pGeo
= makeSpotGeo(R
, angle
, slices
, sides
);
98 return NodeTransitPtr(NULL
);
101 NodeTransitPtr node
= Node::create();
108 /*! Creates a spot light geometry with spot direction in +y-direction with the tip
109 of the spot at (0,0,0).
111 \param[in] R is the spot range/radius of influence
112 \param[in] angle is the spot half angle in radians
113 \param[in] slices is the number of subdivisions in y-Dir, i.e. in spot direction
114 \param[in] sides is the number of circle subdivisions
115 \return GeometryTransitPtr to a newly created Geometry core.
117 \ingroup GrpDrawablesGeometryUtils
119 GeometryTransitPtr
makeSpotGeo(
125 if(R
<= 0 || angle
<= 0)
127 SWARNING
<< "makeSpotGeo: illegal geometric parameters R=" << R
128 << ", angle=" << angle
130 return GeometryTransitPtr(NULL
);
133 if(! slices
|| ! sides
)
135 SWARNING
<< "makeSpotGeo: illegal subdivision parameters slices=" << slices
<< ", sides="
136 << sides
<< std::endl
;
137 return GeometryTransitPtr(NULL
);
140 GeoUInt8PropertyRefPtr types
= GeoUInt8Property::create();
141 GeoUInt32PropertyRefPtr lens
= GeoUInt32Property::create();
142 GeoPnt3fPropertyRefPtr pnts
= GeoPnt3fProperty::create();
143 GeoVec3fPropertyRefPtr norms
= GeoVec3fProperty::create();
145 GeoUInt8Property::StoredFieldType
*t
= types
->editFieldPtr();
146 GeoUInt32Property::StoredFieldType
*l
= lens
->editFieldPtr();
147 GeoPnt3fProperty::StoredFieldType
*p
= pnts
->editFieldPtr();
148 GeoVec3fProperty::StoredFieldType
*n
= norms
->editFieldPtr();
150 // get even slices and sides
151 if ( (slices
& 1) == 1 )
154 if ( (sides
& 1) == 1 )
157 Real32 a_cone
= angle
;
158 Real32 h_cone
= R
* osgCos(a_cone
);
159 Real32 d_cone
= h_cone
/ slices
;
161 Real32 delta_phi
= 2.f
* Pi
/ (sides
-1);
165 typedef std::vector
<Pnt3f
> VecPntsT
;
167 VecPntsT
vecOddPnts(sides
), vecEvenPnts(sides
);
168 VecPntsT
* pvecLast
= &vecOddPnts
;
169 VecPntsT
* pvecCurr
= &vecEvenPnts
;
172 // First the cone itself
174 std::vector
<Vec3f
> vecNormals(sides
);
175 for (UInt32 i
= 0; i
< sides
; ++i
)
177 Real32 phi
= i
* delta_phi
;
179 vecNormals
[i
] = -Vec3f(osgCos(a_cone
) * osgCos(phi
), osgSin(a_cone
), osgCos(a_cone
) * osgSin(phi
));
182 Pnt3f
pT(0,0,0); // tip of spot cone
186 for (UInt32 j
= 1; j
<= slices
; ++j
)
188 Real32 l_cone
= j
* d_cone
;
189 Real32 r_cone
= l_cone
* osgTan(a_cone
);
191 Pnt3f pR
= pT
+ l_cone
* ey
;
193 // Real32 d_phi = (j & 0) ? delta_phi : delta_phi + delta_phi/2.f;
195 Real32 phi
= (j
& 0) ? 0 : delta_phi
/2.f
;
197 for (UInt32 i
= 0; i
< sides
-1; ++i
)
200 (*pvecCurr
)[i
] = pR
+ r_cone
* Vec3f(osgSin(phi
), 0, -osgCos(phi
));
203 (*pvecCurr
)[sides
-1] = (*pvecCurr
)[0];
207 t
->push_back(GL_TRIANGLE_FAN
);
208 l
->push_back(1 + sides
);
210 p
->push_back((*pvecLast
)[0]);
211 n
->push_back(Vec3f(0,-1,0));
213 for (UInt32 i
= 0; i
< sides
; ++i
)
215 p
->push_back((*pvecCurr
)[i
]);
216 n
->push_back(vecNormals
[i
]);
221 t
->push_back(GL_TRIANGLE_STRIP
);
222 l
->push_back(2*sides
);
224 for (UInt32 i
= 0; i
< sides
; ++i
)
226 p
->push_back((*pvecLast
)[i
]);
227 p
->push_back((*pvecCurr
)[i
]);
229 n
->push_back(vecNormals
[i
]);
230 n
->push_back(vecNormals
[i
]);
234 std::swap(pvecLast
, pvecCurr
);
238 // Second the sphere cap
240 Real32 d_alpha
= a_cone
/ (slices
-1);
242 for (UInt32 j
= 0; j
< slices
; ++j
)
246 Real32 da_cone
= a_cone
- j
* d_alpha
;
248 Real32 l_cone
= R
* osgCos(da_cone
);
249 Real32 r_cone
= R
* osgSin(da_cone
);
251 Pnt3f pj
= pT
+ l_cone
* ey
;
253 Real32 phi
= (j
& 0) ? 0 : delta_phi
/2.f
;
255 for (UInt32 i
= 0; i
< sides
-1; ++i
)
258 (*pvecCurr
)[i
] = pj
+ r_cone
* Vec3f(osgSin(phi
), 0, -osgCos(phi
));
260 Vec3f vN
= (*pvecCurr
)[i
] - pT
;
265 (*pvecCurr
)[sides
-1] = (*pvecCurr
)[0];
267 t
->push_back(GL_TRIANGLE_STRIP
);
268 l
->push_back(2*sides
);
270 for (UInt32 i
= 0; i
< sides
; ++i
)
272 p
->push_back((*pvecLast
)[i
]);
273 p
->push_back((*pvecCurr
)[i
]);
275 n
->push_back(vecNormals
[i
]);
276 n
->push_back(vecNormals
[i
]);
281 t
->push_back(GL_TRIANGLE_FAN
);
282 l
->push_back(1 + sides
);
284 p
->push_back(pT
+ R
* ey
);
285 n
->push_back(Vec3f(0,-1,0));
287 for (Int32 i
= sides
-1; i
>= 0; --i
)
289 p
->push_back((*pvecLast
)[i
]);
290 n
->push_back(vecNormals
[i
]);
294 std::swap(pvecLast
, pvecCurr
);
297 GeometryTransitPtr geo
= Geometry::create();
299 geo
->setTypes (types
);
300 geo
->setLengths (lens
);
301 geo
->setPositions(pnts
);
302 geo
->setNormals (norms
);
304 geo
->setMaterial(getDefaultUnlitMaterial());
309 /*! Creates a cinema light with spot direction in +y-direction with the tip
310 of the spot at (0,0,0).
312 \param[in] a is the superellipses width
313 \param[in] b is the superellipses height
314 \param[in] r is the superellipses roundness parameter
315 \param[in] theta is the superellipses twist parameter in radians
316 \param[in] h is the cinema light range/radius of influence, i.e. the geometry extend along the y-axis
317 \param[in] slices is the number of subdivisions in y-Dir, i.e. in spot direction
318 \param[in] sides is the number of circle subdivisions
319 \return NodeTransitPtr to a newly created Node with a Geometry core.
321 \ingroup GrpDrawablesGeometryUtils
323 NodeTransitPtr
makeCinema(
332 GeometryTransitPtr pGeo
= makeCinemaGeo(a
, b
, r
, theta
, h
, slices
, sides
);
336 return NodeTransitPtr(NULL
);
339 NodeTransitPtr node
= Node::create();
346 /*! Creates a cinema light geometry with spot direction in +y-direction with the tip
347 of the spot at (0,0,0).
349 \param[in] a is the superellipses width
350 \param[in] b is the superellipses height
351 \param[in] r is the superellipses roundness parameter
352 \param[in] theta is the superellipses twist parameter in radians
353 \param[in] h is the cinema light range/radius of influence, i.e. the geometry extend along the y-axis
354 \param[in] slices is the number of subdivisions in y-Dir, i.e. in spot direction
355 \param[in] sides is the number of circle subdivisions
356 \return GeometryTransitPtr to a Geometry core.
358 \ingroup GrpDrawablesGeometryUtils
360 GeometryTransitPtr
makeCinemaGeo(
369 if(a
<= 0 || b
<= 0 || r
<= 0 || h
<= 0)
371 SWARNING
<< "makeCinemaGeo: illegal geometric parameters a=" << a
376 return GeometryTransitPtr(NULL
);
379 if(! slices
|| ! sides
)
381 SWARNING
<< "makeCinemaGeo: illegal subdivision parameters slices=" << slices
<< ", sides="
382 << sides
<< std::endl
;
383 return GeometryTransitPtr(NULL
);
386 GeoUInt8PropertyRefPtr types
= GeoUInt8Property::create();
387 GeoUInt32PropertyRefPtr lens
= GeoUInt32Property::create();
388 GeoPnt3fPropertyRefPtr pnts
= GeoPnt3fProperty::create();
389 GeoVec3fPropertyRefPtr norms
= GeoVec3fProperty::create();
391 GeoUInt8Property::StoredFieldType
*t
= types
->editFieldPtr();
392 GeoUInt32Property::StoredFieldType
*l
= lens
->editFieldPtr();
393 GeoPnt3fProperty::StoredFieldType
*p
= pnts
->editFieldPtr();
394 GeoVec3fProperty::StoredFieldType
*n
= norms
->editFieldPtr();
396 // get even slices and sides
397 if ( (slices
& 1) == 1 )
400 if ( (sides
& 1) == 1 )
403 Real32 cos_theta
= osgCos(theta
);
404 Real32 sin_theta
= osgSin(theta
);
406 Real32 d_body
= h
/ slices
;
408 Real32 delta_phi
= 2.f
* Pi
/ (sides
-1);
410 Real32 two_inv_r
= 2.0/r
;
414 typedef std::vector
<Pnt3f
> VecPntsT
;
416 VecPntsT
vecOddPnts(sides
), vecEvenPnts(sides
);
417 VecPntsT
* pvecLast
= &vecOddPnts
;
418 VecPntsT
* pvecCurr
= &vecEvenPnts
;
421 // First the superellipses body itself
423 Pnt3f
pT(0,0,0); // tip of body
427 for (UInt32 j
= 1; j
<= slices
; ++j
)
429 Real32 l_body
= j
* d_body
;
431 Pnt3f pR
= pT
+ l_body
* ey
;
433 Real32 A
= l_body
* a
;
434 Real32 B
= l_body
* b
;
438 for (UInt32 i
= 0; i
< sides
-1; ++i
)
440 Real32 c
= osgCos(phi
);
441 Real32 s
= osgSin(phi
);
443 Real32 x
= A
* osgSgn(c
) * osgPow(osgAbs(c
), two_inv_r
);
444 Real32 z
= B
* osgSgn(s
) * osgPow(osgAbs(s
), two_inv_r
);
446 Pnt3f pP
= pR
+ Vec3f(
447 x
* cos_theta
- z
* sin_theta
,
449 x
* sin_theta
+ z
* cos_theta
452 Real32 L
= pP
.subZero().length();
456 Vec3f v
= pP
.subZero();
467 (*pvecCurr
)[sides
-1] = (*pvecCurr
)[0];
471 t
->push_back(GL_TRIANGLE_FAN
);
472 l
->push_back(1 + sides
);
474 p
->push_back((*pvecLast
)[0]);
475 n
->push_back(Vec3f(0,-1,0));
477 for (UInt32 i
= 0; i
< sides
; ++i
)
479 p
->push_back((*pvecCurr
)[i
]);
486 v0
= (*pvecCurr
)[i
] - (*pvecLast
)[0];
487 v1
= (*pvecCurr
)[i
+1] - (*pvecLast
)[0];
489 else if (i
== sides
-1)
491 v0
= (*pvecCurr
)[0] - (*pvecLast
)[0];
492 v1
= (*pvecCurr
)[1] - (*pvecLast
)[0];
495 Vec3f v
= v1
.cross(v0
);
502 t
->push_back(GL_TRIANGLE_STRIP
);
503 l
->push_back(2*sides
);
505 for (UInt32 i
= 0; i
< sides
; ++i
)
507 p
->push_back((*pvecLast
)[i
]);
508 p
->push_back((*pvecCurr
)[i
]);
516 v0
= (*pvecLast
)[i
+1] - (*pvecCurr
)[i
];
517 v1
= (*pvecLast
)[i
+1] - (*pvecLast
)[i
];
518 v2
= (*pvecCurr
)[i
+1] - (*pvecLast
)[i
+1];
520 else if (i
== sides
-1)
522 v0
= (*pvecLast
)[1] - (*pvecCurr
)[0];
523 v1
= (*pvecLast
)[1] - (*pvecLast
)[0];
524 v2
= (*pvecCurr
)[1] - (*pvecLast
)[1];
527 Vec3f n0
= v1
.cross(v0
);
528 Vec3f n1
= v2
.cross(v1
);
538 std::swap(pvecLast
, pvecCurr
);
542 // Second the sphere cap
544 Real32 delta_a
= a
/ (slices
- 1);
545 Real32 delta_b
= b
/ (slices
- 1);
547 Pnt3f pE
= pT
+ h
* ey
;
549 for (Int32 j
= slices
-2; j
>= 0; --j
)
551 Real32 A
= h
* delta_a
* j
;
552 Real32 B
= h
* delta_b
* j
;
556 for (UInt32 i
= 0; i
< sides
-1; ++i
)
558 Real32 c
= osgCos(phi
);
559 Real32 s
= osgSin(phi
);
561 Real32 x
= A
* osgSgn(c
) * osgPow(osgAbs(c
), two_inv_r
);
562 Real32 z
= B
* osgSgn(s
) * osgPow(osgAbs(s
), two_inv_r
);
564 Pnt3f pP
= pE
+ Vec3f(
565 x
* cos_theta
- z
* sin_theta
,
567 x
* sin_theta
+ z
* cos_theta
570 Real32 L
= pP
.subZero().length();
574 Vec3f v
= pP
.subZero();
585 (*pvecCurr
)[sides
-1] = (*pvecCurr
)[0];
587 if (j
< Int32(slices
-1) && j
> 0)
589 t
->push_back(GL_TRIANGLE_STRIP
);
590 l
->push_back(2*sides
);
592 for (UInt32 i
= 0; i
< sides
; ++i
)
594 p
->push_back((*pvecLast
)[i
]);
595 p
->push_back((*pvecCurr
)[i
]);
603 v0
= (*pvecLast
)[i
+1] - (*pvecCurr
)[i
];
604 v1
= (*pvecLast
)[i
+1] - (*pvecLast
)[i
];
605 v2
= (*pvecCurr
)[i
+1] - (*pvecLast
)[i
+1];
607 else if (i
== sides
-1)
609 v0
= (*pvecLast
)[1] - (*pvecCurr
)[0];
610 v1
= (*pvecLast
)[1] - (*pvecLast
)[0];
611 v2
= (*pvecCurr
)[1] - (*pvecLast
)[1];
614 Vec3f n0
= v1
.cross(v0
);
615 Vec3f n1
= v2
.cross(v1
);
627 t
->push_back(GL_TRIANGLE_FAN
);
628 l
->push_back(1 + sides
);
631 n
->push_back(Vec3f(0,1,0));
633 for (Int32 i
= sides
-1; i
>= 0; --i
)
635 p
->push_back((*pvecCurr
)[i
]);
640 if (i
< Int32(sides
-1))
642 v0
= (*pvecCurr
)[i
] - pE
;
643 v1
= (*pvecCurr
)[i
+1] - pE
;
645 else if (i
== Int32(sides
-1))
647 v0
= (*pvecCurr
)[0] - pE
;
648 v1
= (*pvecCurr
)[1] - pE
;
651 Vec3f v
= v1
.cross(v0
);
657 std::swap(pvecLast
, pvecCurr
);
660 GeometryTransitPtr geo
= Geometry::create();
662 geo
->setTypes (types
);
663 geo
->setLengths (lens
);
664 geo
->setPositions(pnts
);
665 geo
->setNormals (norms
);
667 geo
->setMaterial(getDefaultUnlitMaterial());
672 /*! Creates a frustum volume
674 \param[in] nlt is the near left top point of the frustum
675 \param[in] nlb is the near left bottom point of the frustum
676 \param[in] nrt is the near right top point of the frustum
677 \param[in] nrb is the near right bottom point of the frustum
678 \param[in] flt is the far left top point of the frustum
679 \param[in] flb is the far left bottom point of the frustum
680 \param[in] frt is the far right top point of the frustum
681 \param[in] frb is the far right bottom point of the frustum
682 \return NodeTransitPtr to a newly created Node with a Geometry core.
684 \ingroup GrpDrawablesGeometryUtils
686 NodeTransitPtr
makeFrustumVolume(
687 const Pnt3f
& nlt
, const Pnt3f
& nlb
,
688 const Pnt3f
& nrt
, const Pnt3f
& nrb
,
689 const Pnt3f
& flt
, const Pnt3f
& flb
,
690 const Pnt3f
& frt
, const Pnt3f
& frb
)
692 GeometryTransitPtr pGeo
= makeFrustumVolumeGeo(nlt
, nlb
, nrt
, nrb
, flt
, flb
, frt
, frb
);
696 return NodeTransitPtr(NULL
);
699 NodeTransitPtr node
= Node::create();
706 /*! Creates a frustum volume geometry
708 \param[in] nlt is the near left top point of the frustum
709 \param[in] nlb is the near left bottom point of the frustum
710 \param[in] nrt is the near right top point of the frustum
711 \param[in] nrb is the near right bottom point of the frustum
712 \param[in] flt is the far left top point of the frustum
713 \param[in] flb is the far left bottom point of the frustum
714 \param[in] frt is the far right top point of the frustum
715 \param[in] frb is the far right bottom point of the frustum
716 \return GeometryTransitPtr to a newly created Geometry core.
718 \ingroup GrpDrawablesGeometryUtils
720 GeometryTransitPtr
makeFrustumVolumeGeo(
721 const Pnt3f
& nlt
, const Pnt3f
& nlb
,
722 const Pnt3f
& nrt
, const Pnt3f
& nrb
,
723 const Pnt3f
& flt
, const Pnt3f
& flb
,
724 const Pnt3f
& frt
, const Pnt3f
& frb
)
726 GeoUInt8PropertyRefPtr type
= GeoUInt8Property::create();
727 type
->addValue(GL_QUADS
);
729 GeoUInt32PropertyRefPtr lens
= GeoUInt32Property::create();
730 lens
->addValue(6 * 4);
732 GeoPnt3fPropertyRefPtr pnts
= GeoPnt3fProperty::create();
769 GeoVec3fPropertyRefPtr normals
= GeoVec3fProperty::create();
773 v1
= nrb
- nlb
; v2
= nlt
- nlb
; n
= v1
.cross(v2
); n
.normalize(); for (int i
= 0; i
< 4; ++i
) normals
->addValue(n
);
776 v1
= flb
- frb
; v2
= frt
- frb
; n
= v1
.cross(v2
); n
.normalize(); for (int i
= 0; i
< 4; ++i
) normals
->addValue(n
);
779 v1
= nlb
- flb
; v2
= flt
- flb
; n
= v1
.cross(v2
); n
.normalize(); for (int i
= 0; i
< 4; ++i
) normals
->addValue(n
);
782 v1
= frb
- nrb
; v2
= nrt
- nrb
; n
= v1
.cross(v2
); n
.normalize(); for (int i
= 0; i
< 4; ++i
) normals
->addValue(n
);
785 v1
= frt
- nrt
; v2
= nlt
- nrt
; n
= v1
.cross(v2
); n
.normalize(); for (int i
= 0; i
< 4; ++i
) normals
->addValue(n
);
788 v1
= flb
- nlb
; v2
= nrb
- nlb
; n
= v1
.cross(v2
); n
.normalize(); for (int i
= 0; i
< 4; ++i
) normals
->addValue(n
);
790 GeometryTransitPtr geo
= Geometry::create();
792 geo
->setTypes (type
);
793 geo
->setLengths (lens
);
794 geo
->setPositions(pnts
);
795 geo
->setNormals (normals
);
797 geo
->setMaterial(getDefaultUnlitMaterial());
802 /*! Creates a frustum volume
804 \param[in] vol is frustum volume
805 \return NodeTransitPtr to a newly created Node with a Geometry core.
807 \ingroup GrpDrawablesGeometryUtils
809 NodeTransitPtr
makeFrustumVolume(const FrustumVolume
& vol
)
811 GeometryTransitPtr pGeo
= makeFrustumVolumeGeo(vol
);
815 return NodeTransitPtr(NULL
);
818 NodeTransitPtr node
= Node::create();
825 /*! Creates a frustum volume geometry
827 \param[in] vol is frustum volume
828 \return GeometryTransitPtr to a newly created Geometry core.
830 \ingroup GrpDrawablesGeometryUtils
832 GeometryTransitPtr
makeFrustumVolumeGeo(const FrustumVolume
& vol
)
834 Pnt3f nlt
= vol
.getCorner(FrustumVolume::NEAR_LEFT_TOP
);
835 Pnt3f nlb
= vol
.getCorner(FrustumVolume::NEAR_LEFT_BOTTOM
);
836 Pnt3f nrt
= vol
.getCorner(FrustumVolume::NEAR_RIGHT_TOP
);
837 Pnt3f nrb
= vol
.getCorner(FrustumVolume::NEAR_RIGHT_BOTTOM
);
838 Pnt3f flt
= vol
.getCorner(FrustumVolume::FAR_LEFT_TOP
);
839 Pnt3f flb
= vol
.getCorner(FrustumVolume::FAR_LEFT_BOTTOM
);
840 Pnt3f frt
= vol
.getCorner(FrustumVolume::FAR_RIGHT_TOP
);
841 Pnt3f frb
= vol
.getCorner(FrustumVolume::FAR_RIGHT_BOTTOM
);
843 GeometryTransitPtr geo
= makeFrustumVolumeGeo(nlt
, nlb
, nrt
, nrb
, flt
, flb
, frt
, frb
);