1 | /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield |
---|
2 | * |
---|
3 | * This library is open source and may be redistributed and/or modified under |
---|
4 | * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or |
---|
5 | * (at your option) any later version. The full license is in LICENSE file |
---|
6 | * included with this distribution, and on the openscenegraph.org website. |
---|
7 | * |
---|
8 | * This library is distributed in the hope that it will be useful, |
---|
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
11 | * OpenSceneGraph Public License for more details. |
---|
12 | */ |
---|
13 | |
---|
14 | #ifndef OSGSHADOW_OCCLUDERGEOMETRY |
---|
15 | #define OSGSHADOW_OCCLUDERGEOMETRY 1 |
---|
16 | |
---|
17 | #include <osg/Drawable> |
---|
18 | #include <osg/Array> |
---|
19 | #include <osg/PrimitiveSet> |
---|
20 | #include <osg/Polytope> |
---|
21 | |
---|
22 | #include <osgShadow/Export> |
---|
23 | |
---|
24 | |
---|
25 | namespace osgShadow { |
---|
26 | |
---|
27 | class ShadowVolumeGeometry; |
---|
28 | |
---|
29 | /** OccluderGeometry provides a sepecialised geometry representation of objects in scene that occlude light and therefore cast shadows. |
---|
30 | * OccluderGeometry supports the computation of silhouette edges and shadow volume geometries, as well as use as geometry that one can rendering |
---|
31 | * into a shadow map or end caps for the ZP+ algorithm. OccluderGeometry may be of the same resolution as an underlying geometry that it |
---|
32 | * represents, or can be of lower resolution and combine manager seperate geometries together into a single shadow casting object. |
---|
33 | * OccluderGeometry may be attached as UserData to Nodes or to Drawables. */ |
---|
34 | class OSGSHADOW_EXPORT OccluderGeometry : public osg::Drawable |
---|
35 | { |
---|
36 | public : |
---|
37 | OccluderGeometry(); |
---|
38 | |
---|
39 | OccluderGeometry(const OccluderGeometry& oc, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); |
---|
40 | |
---|
41 | virtual Object* cloneType() const { return new OccluderGeometry(); } |
---|
42 | virtual Object* clone(const osg::CopyOp& copyop) const { return new OccluderGeometry(*this,copyop); } |
---|
43 | virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const OccluderGeometry*>(obj)!=NULL; } |
---|
44 | virtual const char* libraryName() const { return "osgShadow"; } |
---|
45 | virtual const char* className() const { return "OccluderGeometry"; } |
---|
46 | |
---|
47 | /** Compute an occluder geometry containing all the geometry in specified subgraph.*/ |
---|
48 | void computeOccluderGeometry(osg::Node* subgraph, osg::Matrix* matrix=0, float sampleRatio=1.0f); |
---|
49 | |
---|
50 | /** Compute an occluder geometry containing the geometry in specified drawable.*/ |
---|
51 | void computeOccluderGeometry(osg::Drawable* drawable, osg::Matrix* matrix=0, float sampleRatio=1.0f); |
---|
52 | |
---|
53 | |
---|
54 | /** Compute ShadowVolumeGeometry. */ |
---|
55 | void computeShadowVolumeGeometry(const osg::Vec4& lightpos, ShadowVolumeGeometry& svg) const; |
---|
56 | |
---|
57 | |
---|
58 | /** Set the bounding polytope of the OccluderGeometry.*/ |
---|
59 | void setBoundingPolytope(const osg::Polytope& polytope) { _boundingPolytope = polytope; } |
---|
60 | |
---|
61 | /** Get the bounding polytope of the OccluderGeometry.*/ |
---|
62 | osg::Polytope& getBoundingPolytope() { return _boundingPolytope; } |
---|
63 | |
---|
64 | /** Get the const bounding polytope of the OccluderGeometry.*/ |
---|
65 | const osg::Polytope& getBoundingPolytope() const { return _boundingPolytope; } |
---|
66 | |
---|
67 | |
---|
68 | /** Render the occluder geometry. */ |
---|
69 | virtual void drawImplementation(osg::RenderInfo& renderInfo) const; |
---|
70 | |
---|
71 | /** Compute the bounding box around occluder geometry.*/ |
---|
72 | virtual osg::BoundingBox computeBound() const; |
---|
73 | |
---|
74 | typedef std::vector<osg::Vec3> Vec3List; |
---|
75 | typedef std::vector<GLuint> UIntList; |
---|
76 | |
---|
77 | public: |
---|
78 | |
---|
79 | void processGeometry(osg::Drawable* drawable, osg::Matrix* matrix=0, float sampleRatio=1.0f); |
---|
80 | |
---|
81 | protected : |
---|
82 | |
---|
83 | virtual ~OccluderGeometry() {} |
---|
84 | |
---|
85 | struct Edge |
---|
86 | { |
---|
87 | Edge(): |
---|
88 | _p1(0), |
---|
89 | _p2(0), |
---|
90 | _t1(-1), |
---|
91 | _t2(-1) {} |
---|
92 | |
---|
93 | Edge(unsigned int p1, unsigned int p2): |
---|
94 | _p1(p1), |
---|
95 | _p2(p2), |
---|
96 | _t1(-1), |
---|
97 | _t2(-1) |
---|
98 | { |
---|
99 | if (p1>p2) |
---|
100 | { |
---|
101 | // swap ordering so p1 is less than or equal to p2 |
---|
102 | _p1 = p2; |
---|
103 | _p2 = p1; |
---|
104 | } |
---|
105 | } |
---|
106 | |
---|
107 | inline bool operator < (const Edge& rhs) const |
---|
108 | { |
---|
109 | if (_p1 < rhs._p1) return true; |
---|
110 | if (_p1 > rhs._p1) return false; |
---|
111 | return (_p2 < rhs._p2); |
---|
112 | } |
---|
113 | |
---|
114 | bool addTriangle(unsigned int tri) const |
---|
115 | { |
---|
116 | if (_t1<0) |
---|
117 | { |
---|
118 | _t1 = tri; |
---|
119 | return true; |
---|
120 | } |
---|
121 | else if (_t2<0) |
---|
122 | { |
---|
123 | _t2 = tri; |
---|
124 | return true; |
---|
125 | } |
---|
126 | // argg more than two triangles assigned |
---|
127 | return false; |
---|
128 | } |
---|
129 | |
---|
130 | bool boundaryEdge() const { return _t2<0; } |
---|
131 | |
---|
132 | unsigned int _p1; |
---|
133 | unsigned int _p2; |
---|
134 | |
---|
135 | mutable int _t1; |
---|
136 | mutable int _t2; |
---|
137 | |
---|
138 | mutable osg::Vec3 _normal; |
---|
139 | }; |
---|
140 | |
---|
141 | typedef std::vector<Edge> EdgeList; |
---|
142 | |
---|
143 | inline bool isLightPointSilhouetteEdge(const osg::Vec3& lightpos, const Edge& edge) const |
---|
144 | { |
---|
145 | if (edge.boundaryEdge()) return true; |
---|
146 | |
---|
147 | float offset = 0.0f; |
---|
148 | |
---|
149 | osg::Vec3 delta(lightpos-_vertices[edge._p1]); |
---|
150 | delta.normalize(); |
---|
151 | |
---|
152 | float n1 = delta * _triangleNormals[edge._t1] + offset; |
---|
153 | float n2 = delta * _triangleNormals[edge._t2] + offset; |
---|
154 | |
---|
155 | float angle_offset = 0.0f; |
---|
156 | |
---|
157 | n1 = cos(acosf(n1) + angle_offset); |
---|
158 | n2 = cos(acosf(n2) + angle_offset); |
---|
159 | |
---|
160 | if (n1==0.0f && n2==0.0f) return false; |
---|
161 | |
---|
162 | return n1*n2 <= 0.0f; |
---|
163 | } |
---|
164 | |
---|
165 | inline bool isLightDirectionSilhouetteEdge(const osg::Vec3& lightdirection, const Edge& edge) const |
---|
166 | { |
---|
167 | if (edge.boundaryEdge()) return true; |
---|
168 | |
---|
169 | float offset = 0.0f; |
---|
170 | |
---|
171 | float n1 = lightdirection * _triangleNormals[edge._t1] + offset; |
---|
172 | float n2 = lightdirection * _triangleNormals[edge._t2] + offset; |
---|
173 | |
---|
174 | float angle_offset = 0.0f; |
---|
175 | |
---|
176 | n1 = cos(acosf(n1) + angle_offset); |
---|
177 | n2 = cos(acosf(n2) + angle_offset); |
---|
178 | |
---|
179 | if (n1==0.0f && n2==0.0f) return false; |
---|
180 | |
---|
181 | return n1*n2 <= 0.0f; |
---|
182 | } |
---|
183 | |
---|
184 | void setUpInternalStructures(); |
---|
185 | |
---|
186 | void removeDuplicateVertices(); |
---|
187 | void removeNullTriangles(); |
---|
188 | void computeNormals(); |
---|
189 | void buildEdgeMaps(); |
---|
190 | |
---|
191 | void computeLightDirectionSilhouetteEdges(const osg::Vec3& lightdirection, UIntList& silhouetteIndices) const; |
---|
192 | void computeLightPositionSilhouetteEdges(const osg::Vec3& lightpos, UIntList& silhouetteIndices) const; |
---|
193 | |
---|
194 | osg::Polytope _boundingPolytope; |
---|
195 | |
---|
196 | Vec3List _vertices; |
---|
197 | Vec3List _normals; |
---|
198 | Vec3List _triangleNormals; |
---|
199 | UIntList _triangleIndices; |
---|
200 | |
---|
201 | EdgeList _edges; |
---|
202 | }; |
---|
203 | |
---|
204 | class OSGSHADOW_EXPORT ShadowVolumeGeometry : public osg::Drawable |
---|
205 | { |
---|
206 | public : |
---|
207 | ShadowVolumeGeometry(); |
---|
208 | |
---|
209 | ShadowVolumeGeometry(const ShadowVolumeGeometry& oc, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); |
---|
210 | |
---|
211 | virtual Object* cloneType() const { return new ShadowVolumeGeometry(); } |
---|
212 | virtual Object* clone(const osg::CopyOp& copyop) const { return new ShadowVolumeGeometry(*this,copyop); } |
---|
213 | virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const ShadowVolumeGeometry*>(obj)!=NULL; } |
---|
214 | virtual const char* libraryName() const { return "osgShadow"; } |
---|
215 | virtual const char* className() const { return "ShadowVolumeGeometry"; } |
---|
216 | |
---|
217 | enum DrawMode |
---|
218 | { |
---|
219 | GEOMETRY, |
---|
220 | STENCIL_TWO_PASS, |
---|
221 | STENCIL_TWO_SIDED |
---|
222 | }; |
---|
223 | |
---|
224 | void setDrawMode(DrawMode mode) { _drawMode = mode; } |
---|
225 | DrawMode getDrawMode() const { return _drawMode; } |
---|
226 | |
---|
227 | typedef std::vector<osg::Vec3> Vec3List; |
---|
228 | typedef std::vector<GLuint> UIntList; |
---|
229 | |
---|
230 | void setVertices(const Vec3List& vertices) { _vertices = vertices; } |
---|
231 | Vec3List& getVertices() { return _vertices; } |
---|
232 | const Vec3List& getVertices() const { return _vertices; } |
---|
233 | |
---|
234 | void setNormals(const Vec3List& normals) { _normals = normals; } |
---|
235 | Vec3List& getNormals() { return _normals; } |
---|
236 | const Vec3List& getNormals() const { return _normals; } |
---|
237 | |
---|
238 | |
---|
239 | /** Render the occluder geometry. */ |
---|
240 | virtual void drawImplementation(osg::RenderInfo& renderInfo) const; |
---|
241 | |
---|
242 | /** Compute the bounding box around occluder geometry.*/ |
---|
243 | virtual osg::BoundingBox computeBound() const; |
---|
244 | |
---|
245 | public: |
---|
246 | |
---|
247 | protected : |
---|
248 | |
---|
249 | virtual ~ShadowVolumeGeometry() {} |
---|
250 | |
---|
251 | DrawMode _drawMode; |
---|
252 | Vec3List _vertices; |
---|
253 | Vec3List _normals; |
---|
254 | UIntList _indices; |
---|
255 | }; |
---|
256 | |
---|
257 | } |
---|
258 | |
---|
259 | #endif |
---|