openscenegraph
DomainOperator
Go to the documentation of this file.
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 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// Written by Wang Rui, (C) 2010
14
15#ifndef OSGPARTICLE_DOMAINOPERATOR
16#define OSGPARTICLE_DOMAINOPERATOR
17
18#include <osg/Plane>
19#include <osgParticle/Operator>
20#include <osgParticle/Particle>
21
22namespace osgParticle
23{
24
25
26/** A domain operator which accepts different domain shapes as the parameter.
27 It can be derived to implement operators that require particles interacting with domains.
28 Refer to David McAllister's Particle System API (http://www.particlesystems.org)
29*/
30class OSGPARTICLE_EXPORT DomainOperator : public Operator
31{
32public:
33 struct Domain
34 {
35 enum Type
36 {
37 UNDEFINED_DOMAIN = 0,
38 POINT_DOMAIN,
39 LINE_DOMAIN,
40 TRI_DOMAIN,
41 RECT_DOMAIN,
42 PLANE_DOMAIN,
43 SPHERE_DOMAIN,
44 BOX_DOMAIN,
45 DISK_DOMAIN
46 };
47
48 Domain( Type t ) : r1(0.0f), r2(0.0f), type(t) {}
49 osg::Plane plane;
50 osg::Vec3 v1;
51 osg::Vec3 v2;
52 osg::Vec3 v3;
53 osg::Vec3 s1;
54 osg::Vec3 s2;
55 float r1;
56 float r2;
57 Type type;
58 };
59
60 DomainOperator()
61 : Operator()
62 {}
63
64 DomainOperator( const DomainOperator& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY )
65 : Operator(copy, copyop), _domains(copy._domains), _backupDomains(copy._backupDomains)
66 {}
67
68 META_Object( osgParticle, DomainOperator );
69
70 /// Add a point domain
71 inline void addPointDomain( const osg::Vec3& p );
72
73 /// Add a line segment domain
74 inline void addLineSegmentDomain( const osg::Vec3& v1, const osg::Vec3& v2 );
75
76 /// Add a triangle domain
77 inline void addTriangleDomain( const osg::Vec3& v1, const osg::Vec3& v2, const osg::Vec3& v3 );
78
79 /// Add a rectangle domain
80 inline void addRectangleDomain( const osg::Vec3& corner, const osg::Vec3& w, const osg::Vec3& h );
81
82 /// Add a plane domain
83 inline void addPlaneDomain( const osg::Plane& plane );
84
85 /// Add a sphere domain
86 inline void addSphereDomain( const osg::Vec3& c, float r );
87
88 /// Add a box domain
89 inline void addBoxDomain( const osg::Vec3& min, const osg::Vec3& max );
90
91 /// Add a disk domain
92 inline void addDiskDomain( const osg::Vec3& c, const osg::Vec3& n, float r1, float r2=0.0f );
93
94 /// Add a domain object directly, used by the .osg wrappers and serializers.
95 void addDomain( const Domain& domain ) { _domains.push_back(domain); }
96
97 /// Get a domain object directly, used by the .osg wrappers and serializers.
98 const Domain& getDomain( unsigned int i ) const { return _domains[i]; }
99
100 /// Remove a domain at specific index
101 void removeDomain( unsigned int i )
102 { if (i<_domains.size()) _domains.erase(_domains.begin() + i); }
103
104 /// Remove all existing domains
105 void removeAllDomains() { _domains.clear(); }
106
107 /// Get number of domains
108 unsigned int getNumDomains() const { return _domains.size(); }
109
110 /// Apply the acceleration to a particle. Do not call this method manually.
111 void operate( Particle* P, double dt );
112
113 /// Perform some initializations. Do not call this method manually.
114 void beginOperate( Program* prg );
115
116 /// Perform some post-operations. Do not call this method manually.
117 void endOperate();
118
119protected:
120 virtual ~DomainOperator() {}
121 DomainOperator& operator=( const DomainOperator& ) { return *this; }
122
123 virtual void handlePoint( const Domain& /*domain*/, Particle* /*P*/, double /*dt*/ ) { ignore("Point"); }
124 virtual void handleLineSegment( const Domain& /*domain*/, Particle* /*P*/, double /*dt*/ ) { ignore("LineSegment"); }
125 virtual void handleTriangle( const Domain& /*domain*/, Particle* /*P*/, double /*dt*/ ) { ignore("Triangle"); }
126 virtual void handleRectangle( const Domain& /*domain*/, Particle* /*P*/, double /*dt*/ ) { ignore("Rectangle"); }
127 virtual void handlePlane( const Domain& /*domain*/, Particle* /*P*/, double /*dt*/ ) { ignore("Plane"); }
128 virtual void handleSphere( const Domain& /*domain*/, Particle* /*P*/, double /*dt*/ ) { ignore("Sphere"); }
129 virtual void handleBox( const Domain& /*domain*/, Particle* /*P*/, double /*dt*/ ) { ignore("Box"); }
130 virtual void handleDisk( const Domain& /*domain*/, Particle* /*P*/, double /*dt*/ ) { ignore("Disk"); }
131
132 inline void computeNewBasis( const osg::Vec3&, const osg::Vec3&, osg::Vec3&, osg::Vec3& );
133 inline void ignore( const std::string& func );
134
135 std::vector<Domain> _domains;
136 std::vector<Domain> _backupDomains;
137};
138
139// INLINE METHODS
140
141inline void DomainOperator::addPointDomain( const osg::Vec3& p )
142{
143 Domain domain( Domain::POINT_DOMAIN );
144 domain.v1 = p;
145 _domains.push_back( domain );
146}
147
148inline void DomainOperator::addLineSegmentDomain( const osg::Vec3& v1, const osg::Vec3& v2 )
149{
150 Domain domain( Domain::LINE_DOMAIN );
151 domain.v1 = v1;
152 domain.v2 = v2;
153 domain.r1 = (v2 - v1).length();
154 _domains.push_back( domain );
155}
156
157inline void DomainOperator::addTriangleDomain( const osg::Vec3& v1, const osg::Vec3& v2, const osg::Vec3& v3 )
158{
159 Domain domain( Domain::TRI_DOMAIN );
160 domain.v1 = v1;
161 domain.v2 = v2;
162 domain.v3 = v3;
163 domain.plane.set(v1, v2, v3);
164 computeNewBasis( v2-v1, v3-v1, domain.s1, domain.s2 );
165 _domains.push_back( domain );
166}
167
168inline void DomainOperator::addRectangleDomain( const osg::Vec3& corner, const osg::Vec3& w, const osg::Vec3& h )
169{
170 Domain domain( Domain::RECT_DOMAIN );
171 domain.v1 = corner;
172 domain.v2 = w;
173 domain.v3 = h;
174 domain.plane.set(corner, corner+w, corner+h);
175 computeNewBasis( w, h, domain.s1, domain.s2 );
176 _domains.push_back( domain );
177}
178
179inline void DomainOperator::addPlaneDomain( const osg::Plane& plane )
180{
181 Domain domain( Domain::PLANE_DOMAIN );
182 domain.plane.set(plane);
183 _domains.push_back( domain );
184}
185
186inline void DomainOperator::addSphereDomain( const osg::Vec3& c, float r )
187{
188 Domain domain( Domain::SPHERE_DOMAIN );
189 domain.v1 = c;
190 domain.r1 = r;
191 _domains.push_back( domain );
192}
193
194inline void DomainOperator::addBoxDomain( const osg::Vec3& min, const osg::Vec3& max )
195{
196 Domain domain( Domain::BOX_DOMAIN );
197 domain.v1 = min;
198 domain.v2 = max;
199 _domains.push_back( domain );
200}
201
202inline void DomainOperator::addDiskDomain( const osg::Vec3& c, const osg::Vec3& n, float r1, float r2 )
203{
204 Domain domain( Domain::DISK_DOMAIN );
205 domain.v1 = c;
206 domain.v2 = n;
207 domain.r1 = r1;
208 domain.r2 = r2;
209 domain.plane.set(n, c);
210 _domains.push_back( domain );
211}
212
213inline void DomainOperator::computeNewBasis( const osg::Vec3& u, const osg::Vec3& v, osg::Vec3& s1, osg::Vec3& s2 )
214{
215 // Copied from David McAllister's Particle System API (http://www.particlesystems.org), pDomain.h
216 osg::Vec3 w = u ^ v;
217 float det = w.z()*u.x()*v.y() - w.z()*u.y()*v.x() - u.z()*w.x()*v.y() -
218 u.x()*v.z()*w.y() + v.z()*w.x()*u.y() + u.z()*v.x()*w.y();
219 det = 1.0f / det;
220
221 s1.set( v.y()*w.z() - v.z()*w.y(), v.z()*w.x() - v.x()*w.z(), v.x()*w.y() - v.y()*w.x() );
222 s1 = s1 * det;
223 s2.set( u.y()*w.z() - u.z()*w.y(), u.z()*w.x() - u.x()*w.z(), u.x()*w.y() - u.y()*w.x() );
224 s2 = s2 * (-det);
225}
226
227inline void DomainOperator::ignore( const std::string& func )
228{
229 OSG_NOTICE << className() << ": " << func << " domain not yet implemented. " << std::endl;
230}
231
232
233}
234
235#endif