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