1 //
2 //   Copyright 2013 Pixar
3 //
4 //   Licensed under the Apache License, Version 2.0 (the "Apache License")
5 //   with the following modification; you may not use this file except in
6 //   compliance with the Apache License and the following modification to it:
7 //   Section 6. Trademarks. is deleted and replaced with:
8 //
9 //   6. Trademarks. This License does not grant permission to use the trade
10 //      names, trademarks, service marks, or product names of the Licensor
11 //      and its affiliates, except as required to comply with Section 4(c) of
12 //      the License and to reproduce the content of the NOTICE file.
13 //
14 //   You may obtain a copy of the Apache License at
15 //
16 //       http://www.apache.org/licenses/LICENSE-2.0
17 //
18 //   Unless required by applicable law or agreed to in writing, software
19 //   distributed under the Apache License with the above modification is
20 //   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 //   KIND, either express or implied. See the Apache License for the specific
22 //   language governing permissions and limitations under the Apache License.
23 //
24 
25 #ifndef ST_PARTICLES_H
26 #define ST_PARTICLES_H
27 
28 #include <opensubdiv/far/topologyRefiner.h>
29 #include <opensubdiv/far/patchMap.h>
30 #include <opensubdiv/osd/types.h>
31 #include <iostream>
32 
33 //
34 // In order to emphasize the dynamic nature of the EvalLimit API, where the
35 // locations can be arbitrarily updated before each evaluation, the glEvalLimit
36 // example treats each sample as a 'ST particle'.
37 //
38 // ST Particles are a simplified parametric-space particle dynamics simulation: each
39 // particle is assigned a location on the subdivision surface limit that is
40 // composed of a unique ptex face index, with a local (s,t) parametric pair.
41 //
42 // The system also generates an array of parametric velocities (ds, dt) for each
43 // particle. An Update() function then applies the velocities to the locations and
44 // moves the points along the parametric space.
45 //
46 // Face boundaries are managed using a ptex adjacency table obtained from the
47 // Far::TopologyRefiner. Every time a particle moves outside of the [0.0f, 1.0f]
48 // parametric range, a 'warp' function moves it to the neighboring face, or
49 // bounces it, if the edge happens to be a boundary.
50 //
51 // Note: currently the adjacency code does not handle 'diagonal' crossings, nor
52 // crossings between quad and non-quad faces.
53 //
54 class STParticles {
55 
56 public:
57     /// \brief Coordinates set on a limit surface
58     ///
59     struct Position {
PositionPosition60         Position() { }
61 
62         /// \brief Constructor
63         ///
64         /// @param f Ptex face id
65         ///
66         /// @param x parametric location on face
67         ///
68         /// @param y parametric location on face
69         ///
PositionPosition70         Position(int f, float x, float y) : ptexIndex(f), s(x), t(y) { }
71 
72         int ptexIndex;      ///< ptex face index
73         float s, t;         ///< parametric location on face
74     };
75 
76     //
77     // Topology adjacency (borrowed from Ptexture.h)
78     //
79     struct FaceInfo {
80 
81         enum { flag_subface = 8 };
82 
FaceInfoFaceInfo83         FaceInfo() : adjedges(0), flags(0) {
84             adjfaces[0] = adjfaces[1] = adjfaces[2] = adjfaces[3] = -1;
85         }
86 
87         FaceInfo(int adjfaces_[4], int adjedges_[4], bool isSubface=false) :
88             flags(isSubface ? flag_subface : 0) {
89             setadjfaces(adjfaces_[0], adjfaces_[1], adjfaces_[2], adjfaces_[3]);
90             setadjedges(adjedges_[0], adjedges_[1], adjedges_[2], adjedges_[3]);
91         }
92 
setadjfacesFaceInfo93         void setadjfaces(int f0, int f1, int f2, int f3) {
94             adjfaces[0] = f0;
95             adjfaces[1] = f1;
96             adjfaces[2] = f2;
97             adjfaces[3] = f3;
98         }
99 
setadjedgesFaceInfo100         void setadjedges(int e0, int e1, int e2, int e3) {
101             adjedges = (e0&3) | ((e1&3)<<2) | ((e2&3)<<4) | ((e3&3)<<6);
102         }
103 
adjfaceFaceInfo104         int adjface(int eid) const { return adjfaces[eid]; }
105 
adjedgeFaceInfo106         int adjedge(int eid) const { return int((adjedges >> (2*eid)) & 3); }
107 
isSubfaceFaceInfo108         bool isSubface() const { return (flags & flag_subface) != 0; }
109 
110         unsigned int adjedges :8,
111                      flags    :8;
112                  int adjfaces[4];
113     };
114 
115     typedef OpenSubdiv::Far::TopologyRefiner Refiner;
116     typedef OpenSubdiv::Far::PatchTable PatchTable;
117 
118     STParticles(Refiner const & refiner, PatchTable const *patchTable,
119                 int nparticles, bool centered=false);
120 
121     ~STParticles();
122 
123     void Update(float deltaTime);
124 
GetNumParticles()125     int GetNumParticles() const {
126         return (int)_positions.size();
127     }
128 
SetSpeed(float speed)129     void SetSpeed(float speed) {
130         _speed = std::max(-1.0f, std::min(1.0f, speed));
131     }
132 
GetSpeed()133     float GetSpeed() const {
134         return _speed;
135     }
136 
GetPositions()137     std::vector<Position> & GetPositions() {
138         return _positions;
139     }
140 
GetVelocities()141     std::vector<float> & GetVelocities() {
142         return _velocities;
143     }
144 
GetPatchCoords()145     std::vector<OpenSubdiv::Osd::PatchCoord> GetPatchCoords() const {
146         return _patchCoords;
147     }
148 
149     friend std::ostream & operator << (std::ostream & os, STParticles const & f);
150 
151 private:
152 
153     //
154     // Particle "Dynamics"
155     //
156     std::vector<Position> _positions;
157 
158     std::vector<float> _velocities;
159 
160     std::vector<OpenSubdiv::Osd::PatchCoord> _patchCoords;
161 
162     float _speed;  // velocity multiplier
163     int _regFaceSize;
164 
165     friend std::ostream & operator << (std::ostream & os, FaceInfo const & f);
166 
167 
168     std::vector<FaceInfo> _adjacency;
169     OpenSubdiv::Far::PatchMap const *_patchMap;
170 };
171 
172 #endif // ST_PARTICLES_H
173