1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 Robert Osfield
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.
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.
13// Written by Wang Rui, (C) 2010
15#ifndef OSGPARTICLE_DOMAINOPERATOR
16#define OSGPARTICLE_DOMAINOPERATOR
19#include <osgParticle/Operator>
20#include <osgParticle/Particle>
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)
30class OSGPARTICLE_EXPORT DomainOperator : public Operator
48 Domain( Type t ) : r1(0.0f), r2(0.0f), type(t) {}
64 DomainOperator( const DomainOperator& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY )
65 : Operator(copy, copyop), _domains(copy._domains), _backupDomains(copy._backupDomains)
68 META_Object( osgParticle, DomainOperator );
70 /// Add a point domain
71 inline void addPointDomain( const osg::Vec3& p );
73 /// Add a line segment domain
74 inline void addLineSegmentDomain( const osg::Vec3& v1, const osg::Vec3& v2 );
76 /// Add a triangle domain
77 inline void addTriangleDomain( const osg::Vec3& v1, const osg::Vec3& v2, const osg::Vec3& v3 );
79 /// Add a rectangle domain
80 inline void addRectangleDomain( const osg::Vec3& corner, const osg::Vec3& w, const osg::Vec3& h );
82 /// Add a plane domain
83 inline void addPlaneDomain( const osg::Plane& plane );
85 /// Add a sphere domain
86 inline void addSphereDomain( const osg::Vec3& c, float r );
89 inline void addBoxDomain( const osg::Vec3& min, const osg::Vec3& max );
92 inline void addDiskDomain( const osg::Vec3& c, const osg::Vec3& n, float r1, float r2=0.0f );
94 /// Add a domain object directly, used by the .osg wrappers and serializers.
95 void addDomain( const Domain& domain ) { _domains.push_back(domain); }
97 /// Get a domain object directly, used by the .osg wrappers and serializers.
98 const Domain& getDomain( unsigned int i ) const { return _domains[i]; }
100 /// Remove a domain at specific index
101 void removeDomain( unsigned int i )
102 { if (i<_domains.size()) _domains.erase(_domains.begin() + i); }
104 /// Remove all existing domains
105 void removeAllDomains() { _domains.clear(); }
107 /// Get number of domains
108 unsigned int getNumDomains() const { return _domains.size(); }
110 /// Apply the acceleration to a particle. Do not call this method manually.
111 void operate( Particle* P, double dt );
113 /// Perform some initializations. Do not call this method manually.
114 void beginOperate( Program* prg );
116 /// Perform some post-operations. Do not call this method manually.
120 virtual ~DomainOperator() {}
121 DomainOperator& operator=( const DomainOperator& ) { return *this; }
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"); }
132 inline void computeNewBasis( const osg::Vec3&, const osg::Vec3&, osg::Vec3&, osg::Vec3& );
133 inline void ignore( const std::string& func );
135 std::vector<Domain> _domains;
136 std::vector<Domain> _backupDomains;
141inline void DomainOperator::addPointDomain( const osg::Vec3& p )
143 Domain domain( Domain::POINT_DOMAIN );
145 _domains.push_back( domain );
148inline void DomainOperator::addLineSegmentDomain( const osg::Vec3& v1, const osg::Vec3& v2 )
150 Domain domain( Domain::LINE_DOMAIN );
153 domain.r1 = (v2 - v1).length();
154 _domains.push_back( domain );
157inline void DomainOperator::addTriangleDomain( const osg::Vec3& v1, const osg::Vec3& v2, const osg::Vec3& v3 )
159 Domain domain( Domain::TRI_DOMAIN );
163 domain.plane.set(v1, v2, v3);
164 computeNewBasis( v2-v1, v3-v1, domain.s1, domain.s2 );
165 _domains.push_back( domain );
168inline void DomainOperator::addRectangleDomain( const osg::Vec3& corner, const osg::Vec3& w, const osg::Vec3& h )
170 Domain domain( Domain::RECT_DOMAIN );
174 domain.plane.set(corner, corner+w, corner+h);
175 computeNewBasis( w, h, domain.s1, domain.s2 );
176 _domains.push_back( domain );
179inline void DomainOperator::addPlaneDomain( const osg::Plane& plane )
181 Domain domain( Domain::PLANE_DOMAIN );
182 domain.plane.set(plane);
183 _domains.push_back( domain );
186inline void DomainOperator::addSphereDomain( const osg::Vec3& c, float r )
188 Domain domain( Domain::SPHERE_DOMAIN );
191 _domains.push_back( domain );
194inline void DomainOperator::addBoxDomain( const osg::Vec3& min, const osg::Vec3& max )
196 Domain domain( Domain::BOX_DOMAIN );
199 _domains.push_back( domain );
202inline void DomainOperator::addDiskDomain( const osg::Vec3& c, const osg::Vec3& n, float r1, float r2 )
204 Domain domain( Domain::DISK_DOMAIN );
209 domain.plane.set(n, c);
210 _domains.push_back( domain );
213inline void DomainOperator::computeNewBasis( const osg::Vec3& u, const osg::Vec3& v, osg::Vec3& s1, osg::Vec3& s2 )
215 // Copied from David McAllister's Particle System API (http://www.particlesystems.org), pDomain.h
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();
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() );
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() );
227inline void DomainOperator::ignore( const std::string& func )
229 OSG_NOTICE << className() << ": " << func << " domain not yet implemented. " << std::endl;