├── .gitattributes ├── .gitignore ├── LICENSE.txt ├── README.md ├── plug-ins ├── include │ ├── KdTreeMaya.h │ ├── kdTree.h │ └── mayaFuntions.h ├── intersectionDeformer.mll ├── intersectionDeformer │ ├── .svn │ │ ├── all-wcprops │ │ ├── entries │ │ ├── entries (David Behrens's conflicted copy 2010-05-11) │ │ ├── prop-base │ │ │ ├── intersectionDeformer.mll.svn-base │ │ │ └── testScene.mb.svn-base │ │ └── text-base │ │ │ ├── AEintDeformerTemplate.mel.svn-base │ │ │ ├── intersectionDeformer.cpp.svn-base │ │ │ ├── intersectionDeformer.h.svn-base │ │ │ ├── intersectionDeformer.mll.svn-base │ │ │ ├── intersectionDeformer.sln.svn-base │ │ │ ├── intersectionDeformer.vcproj.svn-base │ │ │ ├── reg.cpp.svn-base │ │ │ └── testScene.mb.svn-base │ ├── intersectionDeformer.cpp │ ├── intersectionDeformer.h │ ├── intersectionDeformer.suo.old │ ├── reg.cpp │ └── testScene.mb ├── smDef.mll ├── smDef │ ├── main.cpp │ ├── smDef.h │ └── smDefNode.cpp ├── snapDeformer.mll └── snapDeformer │ ├── reg.cpp │ ├── snapMeshCmd.cpp │ ├── snapMeshCmd.h │ ├── snapMeshDeformer.cpp │ └── snapMeshDeformer.h ├── scripts ├── AEintDeformerTemplate.mel ├── AlignNormals.py ├── alignVerts.py ├── chains.py ├── follicle.py ├── makeCenterLine.py ├── scratch.py ├── snapDeformer.mel └── softModCon.py └── windows ├── AlwaysOnTop.ahk └── windows_registry_cmd.reg /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | scripts/skinCluster.py 217 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 David Nelson david@ventosum.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | maya 2 | ==== 3 | 4 | maya plug ins 5 | 6 | These are a collection of common use maya plugin scripts I've collected from other online sources or my own work for generating maya deformers or inverted blendShapes, etc for quick rigging and common shot deformation work. The .mll are compiled for maya 2014. I have some other user's code with links or authors included here for students in rigging classes to have a common access point herein. 7 | 8 | place scripts dir into: 9 | MEL: `internalVar -usd` 10 | 11 | place plug-ins into: 12 | MEL: (`internalVar -usd`+"/..") 13 | 14 | python wrappers forthcoming. 15 | -------------------------------------------------------------------------------- /plug-ins/include/KdTreeMaya.h: -------------------------------------------------------------------------------- 1 | #ifndef __KD_TREEM 2 | #define __KD_TREEM 3 | 4 | #include 5 | #include 6 | 7 | //template 8 | KdTree_map KdFromPointArray(MPointArray &points) 9 | { 10 | int size = points.length(); 11 | KdTree_map newKd(size); 12 | for (int i=0; i< size; i++) 13 | { 14 | float pos[3] = {float(points[i].x), float(points[i].y), float(points[i].z)}; 15 | const int index = i; 16 | newKd.store(pos, &index); 17 | } 18 | newKd.balance(); 19 | return newKd; 20 | 21 | } 22 | 23 | #endif -------------------------------------------------------------------------------- /plug-ins/include/kdTree.h: -------------------------------------------------------------------------------- 1 | // KdTree.h 2 | // a kd tree baised on an example implementation of the KdTree 3 | // map data structure (Henrik Wann Jensen - February 2001) 4 | 5 | #ifndef __KD_TREE 6 | #define __KD_TREE 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | // This is the KdTree 14 | template 15 | struct KdTree { 16 | float pos[3]; // KdTree position 17 | short plane; // splitting plane for kd-tree 18 | ExtraInfo info; // whatever you want 19 | 20 | KdTree() 21 | : info(), plane(0) 22 | { 23 | pos[0] = 0.0f; 24 | pos[1] = 0.0f; 25 | pos[2] = 0.0f; 26 | } 27 | ExtraInfo* Info() { return &info; } 28 | void SetInfo(const ExtraInfo* info) 29 | { 30 | this->info = *info; 31 | } 32 | }; 33 | 34 | 35 | // This structure is used only to locate the nearest points 36 | template 37 | struct ClosestPoints { 38 | int max; 39 | int found; 40 | bool got_heap; 41 | float pos[3]; 42 | float *dist2; 43 | const KdTree **index; 44 | }; 45 | 46 | 47 | // This is the KdTree_map class 48 | template 49 | class KdTree_map { 50 | public: 51 | KdTree_map( int maxPoints ); 52 | ~KdTree_map(); 53 | 54 | void store( 55 | const float pos[3], // KdTree position 56 | const ExtraInfo* info); // user info 57 | 58 | void balance(void); // balance the kd-tree (before use!) 59 | 60 | int closestPoints( 61 | KdTree *thePoints, 62 | const float pos[3], // surface position 63 | const float max_dist, // max distance to look for points in KdTrees 64 | const int maxPoints ) const; // number of points to find 65 | 66 | void locate_points( 67 | ClosestPoints *const np, // np is used to locate the KdTrees 68 | const int index ) const; // call with index = 1 69 | 70 | 71 | private: 72 | 73 | void balance_segment( 74 | KdTree **pbal, 75 | KdTree **porg, 76 | const int index, 77 | const int start, 78 | const int end ); 79 | 80 | void median_split( 81 | KdTree **p, 82 | const int start, 83 | const int end, 84 | const int median, 85 | const int axis ); 86 | 87 | KdTree *KdTrees; 88 | 89 | int stored_KdTrees; 90 | int half_stored_KdTrees; 91 | int max_KdTrees; 92 | 93 | float bbox_min[3]; // use bbox_min; 94 | float bbox_max[3]; // use bbox_max; 95 | }; 96 | 97 | 98 | 99 | // This is the constructor for the KdTree map. 100 | // To create the KdTree map it is necessary to specify the 101 | // maximum number of KdTrees that will be stored 102 | template 103 | KdTree_map::KdTree_map( const int maxPoints ) 104 | { 105 | stored_KdTrees = 0; 106 | max_KdTrees = maxPoints; 107 | 108 | KdTrees = new KdTree[ max_KdTrees+1 ]; 109 | 110 | if (KdTrees == NULL) { 111 | fprintf(stderr,"Out of memory initializing KdTree map\n"); 112 | exit(-1); 113 | } 114 | 115 | bbox_min[0] = bbox_min[1] = bbox_min[2] = 1e8f; 116 | bbox_max[0] = bbox_max[1] = bbox_max[2] = -1e8f; 117 | } 118 | 119 | template 120 | KdTree_map::~KdTree_map() 121 | { 122 | delete[] KdTrees; 123 | } 124 | 125 | 126 | // KdTree_dir returns the direction of a KdTree 127 | template 128 | int KdTree_map::closestPoints( 129 | KdTree *thePoints, 130 | const float pos[3], // surface position 131 | const float max_dist, // max distance to look for KdTrees 132 | const int maxPoints ) const // number of KdTrees to use 133 | { 134 | //point[0] = point[1] = point[2] = 0.0; 135 | 136 | ClosestPoints np; 137 | np.dist2 = (float*)alloca( sizeof(float)*(maxPoints+1) ); 138 | np.index = (const KdTree**)alloca( sizeof(KdTree*)*(maxPoints+1) ); 139 | 140 | np.pos[0] = pos[0]; np.pos[1] = pos[1]; np.pos[2] = pos[2]; 141 | np.max = maxPoints; 142 | np.found = 0; 143 | np.got_heap = false; 144 | np.dist2[0] = max_dist*max_dist; 145 | 146 | // locate the nearest points 147 | locate_points( &np, 1 ); 148 | if (thePoints != NULL) 149 | { 150 | int i; 151 | 152 | float *distances = new float[np.found]; 153 | for (i = 0; i < np.found; i++) 154 | { 155 | distances[i] = np.dist2[i+1]; 156 | } 157 | for (i = 0; i < np.found; i++) 158 | { 159 | float dist2 = distances[i]; 160 | KdTree tempNode = *np.index[i+1]; 161 | int j = i; 162 | while (j > 0 && distances[j - 1] > dist2) 163 | { 164 | np.index[j] = np.index[j - 1]; 165 | distances[j] = distances[j - 1]; 166 | j--; 167 | } 168 | thePoints[j] = tempNode; 169 | distances[j] = dist2; 170 | } 171 | /* 172 | 173 | int max = min(np.found, maxPoints); 174 | for (i = 1; i <= np.found; i++) 175 | { 176 | thePoints[i - 1] = *np.index[i]; 177 | } 178 | */ 179 | } 180 | 181 | return np.found; 182 | } 183 | 184 | 185 | // locate_points finds the nearest KdTrees in the 186 | // KdTree map given the parameters in np 187 | template 188 | void KdTree_map::locate_points( 189 | ClosestPoints *const np, 190 | const int index ) const 191 | { 192 | const KdTree *p = &KdTrees[index]; 193 | float dist1; 194 | 195 | 196 | if (index<=half_stored_KdTrees) { 197 | dist1 = np->pos[ p->plane ] - p->pos[ p->plane ]; 198 | int leftIndex = index * 2; 199 | int rightIndex = leftIndex + 1; 200 | if (dist1>=0.0) { // if dist1 is positive search right plane 201 | if (rightIndex <= stored_KdTrees) 202 | locate_points( np, rightIndex ); 203 | if ( dist1*dist1 < np->dist2[0] ) 204 | locate_points( np, leftIndex ); 205 | } else { // dist1 is negative search left first 206 | locate_points( np, leftIndex ); 207 | if ( dist1*dist1 < np->dist2[0] && rightIndex <= stored_KdTrees) 208 | locate_points( np, rightIndex ); 209 | } 210 | } 211 | // compute squared distance between current point and np->pos 212 | 213 | dist1 = p->pos[0] - np->pos[0]; 214 | float dist2 = dist1*dist1; 215 | dist1 = p->pos[1] - np->pos[1]; 216 | dist2 += dist1*dist1; 217 | dist1 = p->pos[2] - np->pos[2]; 218 | dist2 += dist1*dist1; 219 | 220 | if ( dist2 < np->dist2[0] ) { 221 | // we found a point :) Insert it in the candidate list 222 | 223 | if ( np->found < np->max ) { 224 | // heap is not full; use array 225 | np->found++; 226 | np->dist2[np->found] = dist2; 227 | np->index[np->found] = p; 228 | } else { 229 | int j,parent; 230 | 231 | if (np->got_heap==false) { // Do we need to build the heap? 232 | // Build heap 233 | float dst2; 234 | const KdTree *phot; 235 | int half_found = np->found>>1; 236 | for ( int k=half_found; k>=1; k--) { 237 | parent=k; 238 | phot = np->index[k]; 239 | dst2 = np->dist2[k]; 240 | while ( parent <= half_found ) { 241 | j = parent+parent; 242 | if (jfound && np->dist2[j]dist2[j+1]) 243 | j++; 244 | if (dst2>=np->dist2[j]) 245 | break; 246 | np->dist2[parent] = np->dist2[j]; 247 | np->index[parent] = np->index[j]; 248 | parent=j; 249 | } 250 | np->dist2[parent] = dst2; 251 | np->index[parent] = phot; 252 | } 253 | np->got_heap = 1; 254 | } 255 | 256 | // insert new point into max heap 257 | // delete largest element, insert new and reorder the heap 258 | parent=1; 259 | j = 2; 260 | while ( j <= np->found ) { 261 | if ( j < np->found && np->dist2[j] < np->dist2[j+1] ) 262 | j++; 263 | if ( dist2 > np->dist2[j] ) 264 | break; 265 | np->dist2[parent] = np->dist2[j]; 266 | np->index[parent] = np->index[j]; 267 | parent = j; 268 | j += j; 269 | } 270 | if (dist2 < np->dist2[parent]) { 271 | np->index[parent] = p; 272 | np->dist2[parent] = dist2; 273 | } 274 | 275 | np->dist2[0] = np->dist2[1]; 276 | } 277 | } 278 | } 279 | 280 | 281 | // store puts a KdTree into the flat array that will form 282 | //the final kd-tree. 283 | //Call this function to store a KdTree. 284 | template 285 | void KdTree_map::store( 286 | const float pos[3], 287 | const ExtraInfo *info) 288 | { 289 | if (stored_KdTrees>=max_KdTrees) 290 | return; 291 | 292 | stored_KdTrees++; 293 | KdTree *const node = &KdTrees[stored_KdTrees]; 294 | 295 | for (int i=0; i<3; i++) { 296 | node->pos[i] = pos[i]; 297 | 298 | if (node->pos[i] < bbox_min[i]) 299 | bbox_min[i] = node->pos[i]; 300 | if (node->pos[i] > bbox_max[i]) 301 | bbox_max[i] = node->pos[i]; 302 | 303 | } 304 | node->SetInfo(info); 305 | 306 | } 307 | 308 | 309 | // balance creates a left balanced kd-tree from the flat KdTree array. 310 | //This function should be called before the KdTree map 311 | // is used for rendering. 312 | template 313 | void KdTree_map::balance(void) 314 | { 315 | if (stored_KdTrees>1) { 316 | // allocate two temporary arrays for the balancing procedure 317 | KdTree **pa1 = new KdTree*[stored_KdTrees+1]; 318 | KdTree **pa2 = new KdTree*[stored_KdTrees+1]; 319 | 320 | for (int i=0; i<=stored_KdTrees; i++){ 321 | pa2[i] = &KdTrees[i]; 322 | } 323 | 324 | balance_segment( pa1, pa2, 1, 1, stored_KdTrees ); 325 | delete[] pa2; 326 | 327 | // reorganize balanced kd-tree (make a heap) 328 | int d, j=1, foo=1; 329 | KdTree foo_KdTree = KdTrees[j]; 330 | 331 | for (int i=1; i<=stored_KdTrees; i++) { 332 | d=pa1[j]-KdTrees; 333 | //d = (((unsigned long)pa1[j]) - ((unsigned long)KdTrees)) / 334 | // sizeof(KdTrees); 335 | pa1[j] = NULL; 336 | if (d != foo) 337 | { 338 | KdTrees[j] = KdTrees[d]; 339 | } 340 | else { 341 | KdTrees[j] = foo_KdTree; 342 | if (i 371 | void KdTree_map :: median_split( 372 | KdTree **p, 373 | const int start, // start of KdTree block in array 374 | const int end, // end of KdTree block in array 375 | const int median, // desired median number 376 | const int axis ) // axis to split along 377 | { 378 | int left = start; 379 | int right = end; 380 | 381 | while ( right > left ) { 382 | const float v = p[right]->pos[axis]; 383 | int i=left-1; 384 | int j=right; 385 | for (;;) { 386 | while ( p[++i]->pos[axis] < v ) 387 | ; 388 | while ( p[--j]->pos[axis] > v && j>left ) 389 | ; 390 | if ( i >= j ) 391 | break; 392 | //swap(p,i,j); 393 | KdTree *ph2 = p[i]; 394 | p[i] = p[j]; 395 | p[j] = ph2; 396 | } 397 | 398 | KdTree *ph2 = p[i]; 399 | p[i] = p[right]; 400 | p[right] = ph2; 401 | //swap(p,i,right); 402 | if ( i >= median ) 403 | right=i-1; 404 | if ( i <= median ) 405 | left=i+1; 406 | } 407 | 408 | 409 | } 410 | 411 | 412 | // See "Realistic image synthesis using KdTree Mapping" chapter 6 413 | // for an explanation of this function 414 | template 415 | void KdTree_map :: balance_segment( 416 | KdTree **pbal, 417 | KdTree **porg, 418 | const int index, 419 | const int start, 420 | const int end ) 421 | { 422 | //-------------------- 423 | // compute new median 424 | //-------------------- 425 | 426 | int median=1; 427 | while ((4*median) <= (end-start+1)) 428 | median += median; 429 | 430 | if ((3*median) <= (end-start+1)) { 431 | median += median; 432 | median += start-1; 433 | } else 434 | median = end-median+1; 435 | 436 | //-------------------------- 437 | // find axis to split along 438 | //-------------------------- 439 | 440 | int axis=2; 441 | if ((bbox_max[0]-bbox_min[0])>(bbox_max[1]-bbox_min[1]) && 442 | (bbox_max[0]-bbox_min[0])>(bbox_max[2]-bbox_min[2])) 443 | axis=0; 444 | else if ((bbox_max[1]-bbox_min[1])>(bbox_max[2]-bbox_min[2])) 445 | axis=1; 446 | 447 | //------------------------------------------ 448 | // partition KdTree block around the median 449 | //------------------------------------------ 450 | 451 | median_split( porg, start, end, median, axis ); 452 | 453 | pbal[ index ] = porg[ median ]; 454 | pbal[ index ]->plane = axis; 455 | 456 | //---------------------------------------------- 457 | // recursively balance the left and right block 458 | //---------------------------------------------- 459 | 460 | if ( median > start ) { 461 | // balance left segment 462 | if ( start < median-1 ) { 463 | const float tmp=bbox_max[axis]; 464 | bbox_max[axis] = pbal[index]->pos[axis]; 465 | balance_segment( pbal, porg, 2*index, start, median-1 ); 466 | bbox_max[axis] = tmp; 467 | } else { 468 | pbal[ 2*index ] = porg[start]; 469 | } 470 | } 471 | 472 | if ( median < end ) { 473 | // balance right segment 474 | if ( median+1 < end ) { 475 | const float tmp = bbox_min[axis]; 476 | bbox_min[axis] = pbal[index]->pos[axis]; 477 | balance_segment( pbal, porg, 2*index+1, median+1, end ); 478 | bbox_min[axis] = tmp; 479 | } else { 480 | pbal[ 2*index+1 ] = porg[end]; 481 | } 482 | } 483 | } 484 | 485 | #endif 486 | -------------------------------------------------------------------------------- /plug-ins/include/mayaFuntions.h: -------------------------------------------------------------------------------- 1 | #ifndef __MAYA_FUN_TIONS 2 | #define __MAYA_FUN_TIONS 3 | 4 | #include 5 | #include 6 | 7 | ///quicky error message 8 | inline MStatus Err(MStatus status, const std::string messsage) 9 | { 10 | MGlobal::displayError(messsage.c_str()); 11 | return status; 12 | } 13 | 14 | inline int getArgPosition(const MArgList &args, const std::string flag) 15 | { 16 | unsigned argData = args.flagIndex(flag.c_str()); 17 | if (argData == args.kInvalidArgIndex) 18 | return -1; 19 | int value(argData); 20 | return value; 21 | } 22 | 23 | #endif -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer.mll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidrichardnelson/maya/c0f2677a7ae73a2305d60db0041102f4e3558748/plug-ins/intersectionDeformer.mll -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer/.svn/all-wcprops: -------------------------------------------------------------------------------- 1 | K 25 2 | svn:wc:ra_dav:version-url 3 | V 52 4 | /!svn/ver/20818/art/foomojo/src/intersectionDeformer 5 | END 6 | intersectionDeformer.h 7 | K 25 8 | svn:wc:ra_dav:version-url 9 | V 74 10 | /!svn/ver/5401/art/foomojo/src/intersectionDeformer/intersectionDeformer.h 11 | END 12 | intersectionDeformer.sln 13 | K 25 14 | svn:wc:ra_dav:version-url 15 | V 77 16 | /!svn/ver/20818/art/foomojo/src/intersectionDeformer/intersectionDeformer.sln 17 | END 18 | testScene.mb 19 | K 25 20 | svn:wc:ra_dav:version-url 21 | V 64 22 | /!svn/ver/5673/art/foomojo/src/intersectionDeformer/testScene.mb 23 | END 24 | intersectionDeformer.cpp 25 | K 25 26 | svn:wc:ra_dav:version-url 27 | V 76 28 | /!svn/ver/5907/art/foomojo/src/intersectionDeformer/intersectionDeformer.cpp 29 | END 30 | AEintDeformerTemplate.mel 31 | K 25 32 | svn:wc:ra_dav:version-url 33 | V 77 34 | /!svn/ver/5673/art/foomojo/src/intersectionDeformer/AEintDeformerTemplate.mel 35 | END 36 | intersectionDeformer.vcproj 37 | K 25 38 | svn:wc:ra_dav:version-url 39 | V 80 40 | /!svn/ver/20818/art/foomojo/src/intersectionDeformer/intersectionDeformer.vcproj 41 | END 42 | intersectionDeformer.mll 43 | K 25 44 | svn:wc:ra_dav:version-url 45 | V 76 46 | /!svn/ver/5907/art/foomojo/src/intersectionDeformer/intersectionDeformer.mll 47 | END 48 | reg.cpp 49 | K 25 50 | svn:wc:ra_dav:version-url 51 | V 59 52 | /!svn/ver/5401/art/foomojo/src/intersectionDeformer/reg.cpp 53 | END 54 | -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer/.svn/entries: -------------------------------------------------------------------------------- 1 | 10 2 | 3 | dir 4 | 21336 5 | https://foo.foomojo.com/art/foomojo/src/intersectionDeformer 6 | https://foo.foomojo.com 7 | 8 | 9 | 10 | 2010-04-22T04:26:42.552379Z 11 | 20818 12 | david 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | ec5cee31-96e2-4d84-80ef-8e086108736f 28 | 29 | intersectionDeformer.h 30 | file 31 | 32 | 33 | 34 | 35 | 2010-01-25T19:15:10.000000Z 36 | 64584c1f2e220b2541d43452ecdd1641 37 | 2008-11-05T03:07:24.656360Z 38 | 5401 39 | dave 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 3020 62 | 63 | intersectionDeformer.sln 64 | file 65 | 66 | 67 | 68 | 69 | 2010-04-23T17:15:06.421875Z 70 | 0d94c0325172b3c6c74271d9ddddb7c8 71 | 2010-04-22T04:26:42.552379Z 72 | 20818 73 | david 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 3248 96 | 97 | testScene.mb 98 | file 99 | 100 | 101 | 102 | 103 | 2010-01-25T19:15:11.000000Z 104 | 3e8c93746565e1ce11b16f31b65d6c08 105 | 2008-11-11T06:43:05.824497Z 106 | 5673 107 | joseph 108 | has-props 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 97876 130 | 131 | intersectionDeformer.cpp 132 | file 133 | 134 | 135 | 136 | 137 | 2010-01-25T19:15:11.000000Z 138 | 8e81de32ed0177c6fe74f4815b49eb9d 139 | 2008-11-14T18:57:57.160290Z 140 | 5907 141 | dave 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 20692 164 | 165 | AEintDeformerTemplate.mel 166 | file 167 | 168 | 169 | 170 | 171 | 2010-01-25T19:15:11.000000Z 172 | d4a902af52b3bd86067b61dc1012c5b9 173 | 2008-11-11T06:43:05.824497Z 174 | 5673 175 | joseph 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 1006 198 | 199 | intersectionDeformer.vcproj 200 | file 201 | 202 | 203 | 204 | 205 | 2010-04-23T17:15:06.421875Z 206 | e57e99404ec1def38d2beed88fd59925 207 | 2010-04-22T04:26:42.552379Z 208 | 20818 209 | david 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 32617 232 | 233 | intersectionDeformer.mll 234 | file 235 | 236 | 237 | 238 | 239 | 2010-01-25T19:15:11.000000Z 240 | bb188e98982032794de43215ac92bb38 241 | 2008-11-14T18:57:57.160290Z 242 | 5907 243 | dave 244 | has-props 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 38400 266 | 267 | reg.cpp 268 | file 269 | 270 | 271 | 272 | 273 | 2010-01-25T19:15:11.000000Z 274 | d14aadb1642a18b103897aa03fbdbfe5 275 | 2008-11-05T03:07:24.656360Z 276 | 5401 277 | dave 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 1578 300 | 301 | -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer/.svn/entries (David Behrens's conflicted copy 2010-05-11): -------------------------------------------------------------------------------- 1 | 10 2 | 3 | dir 4 | 21015 5 | https://foo.foomojo.com/art/foomojo/src/intersectionDeformer 6 | https://foo.foomojo.com 7 | 8 | 9 | 10 | 2010-04-22T04:26:42.552379Z 11 | 20818 12 | david 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | ec5cee31-96e2-4d84-80ef-8e086108736f 28 | 29 | intersectionDeformer.h 30 | file 31 | 32 | 33 | 34 | 35 | 2010-03-11T16:42:49.000000Z 36 | 64584c1f2e220b2541d43452ecdd1641 37 | 2008-11-05T03:07:24.656360Z 38 | 5401 39 | dave 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 3020 62 | 63 | intersectionDeformer.sln 64 | file 65 | 66 | 67 | 68 | 69 | 2010-04-21T15:36:42.000000Z 70 | 0d94c0325172b3c6c74271d9ddddb7c8 71 | 2010-04-22T04:26:42.552379Z 72 | 20818 73 | david 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 3248 96 | 97 | testScene.mb 98 | file 99 | 100 | 101 | 102 | 103 | 2010-03-11T16:42:49.000000Z 104 | 3e8c93746565e1ce11b16f31b65d6c08 105 | 2008-11-11T06:43:05.824497Z 106 | 5673 107 | joseph 108 | has-props 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 97876 130 | 131 | intersectionDeformer.cpp 132 | file 133 | 134 | 135 | 136 | 137 | 2010-03-11T16:42:50.000000Z 138 | 8e81de32ed0177c6fe74f4815b49eb9d 139 | 2008-11-14T18:57:57.160290Z 140 | 5907 141 | dave 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 20692 164 | 165 | AEintDeformerTemplate.mel 166 | file 167 | 168 | 169 | 170 | 171 | 2010-03-11T16:42:50.000000Z 172 | d4a902af52b3bd86067b61dc1012c5b9 173 | 2008-11-11T06:43:05.824497Z 174 | 5673 175 | joseph 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 1006 198 | 199 | intersectionDeformer.vcproj 200 | file 201 | 202 | 203 | 204 | 205 | 2010-04-21T16:24:18.000000Z 206 | e57e99404ec1def38d2beed88fd59925 207 | 2010-04-22T04:26:42.552379Z 208 | 20818 209 | david 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 32617 232 | 233 | intersectionDeformer.mll 234 | file 235 | 236 | 237 | 238 | 239 | 2010-03-11T16:42:50.000000Z 240 | bb188e98982032794de43215ac92bb38 241 | 2008-11-14T18:57:57.160290Z 242 | 5907 243 | dave 244 | has-props 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 38400 266 | 267 | reg.cpp 268 | file 269 | 270 | 271 | 272 | 273 | 2010-03-11T16:42:50.000000Z 274 | d14aadb1642a18b103897aa03fbdbfe5 275 | 2008-11-05T03:07:24.656360Z 276 | 5401 277 | dave 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 1578 300 | 301 | -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer/.svn/prop-base/intersectionDeformer.mll.svn-base: -------------------------------------------------------------------------------- 1 | K 13 2 | svn:mime-type 3 | V 24 4 | application/octet-stream 5 | END 6 | -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer/.svn/prop-base/testScene.mb.svn-base: -------------------------------------------------------------------------------- 1 | K 13 2 | svn:mime-type 3 | V 24 4 | application/octet-stream 5 | END 6 | -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer/.svn/text-base/AEintDeformerTemplate.mel.svn-base: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | global proc AEintDeformerTemplate ( string $nodeName ) 5 | { 6 | 7 | editorTemplate -beginScrollLayout; 8 | 9 | AEaddRampControl ($nodeName+".pushRamp"); 10 | editorTemplate -addControl "envelope"; 11 | editorTemplate -addControl "weight"; 12 | editorTemplate -addControl "lookMaxDist"; 13 | //editorTemplate -addControl "space"; 14 | editorTemplate -addSeparator; 15 | editorTemplate -addControl "lookDirection"; 16 | editorTemplate -addControl "lookVector"; 17 | editorTemplate -addSeparator; 18 | editorTemplate -addControl "pushDirection"; 19 | editorTemplate -addControl "center"; 20 | editorTemplate -addSeparator; 21 | editorTemplate -addControl "pushAboveDist"; 22 | editorTemplate -addControl "pushAboveAmount"; 23 | editorTemplate -addControl "pushBelowDist"; 24 | editorTemplate -addControl "pushBelowAmount"; 25 | editorTemplate -addControl "thicknessDist"; 26 | editorTemplate -addControl "thicknessTol"; 27 | editorTemplate -addSeparator; 28 | editorTemplate -addExtraControls; 29 | 30 | editorTemplate -endScrollLayout; 31 | } 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer/.svn/text-base/intersectionDeformer.cpp.svn-base: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // Copyright (C): FooMojo 3 | // File: intersectionDeformer.cpp 4 | // Authors: joseph 5 | // ====================================================================== 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | using namespace std; 23 | 24 | 25 | #include 26 | 27 | #include 28 | 29 | #include "intersectionDeformer.h" 30 | 31 | 32 | MTypeId intersectionDeformer::id( 0x8001e ); 33 | MObject intersectionDeformer::weight; //env overide 34 | MObject intersectionDeformer::space; //world, local 35 | MObject intersectionDeformer::lookDirection;//normals, vector, from, to 36 | MObject intersectionDeformer::lookVector;//vector for lookDirection 37 | MObject intersectionDeformer::lookVectorX; 38 | MObject intersectionDeformer::lookVectorY; 39 | MObject intersectionDeformer::lookVectorZ; 40 | MObject intersectionDeformer::lookMaxDist; //float 41 | MObject intersectionDeformer::center; //vector 42 | MObject intersectionDeformer::centerX; 43 | MObject intersectionDeformer::centerY; 44 | MObject intersectionDeformer::centerZ; 45 | MObject intersectionDeformer::pushDirection;//normals, vector, from, to 46 | MObject intersectionDeformer::pushRamp; //maya curve shape 47 | MObject intersectionDeformer::pushAboveDist; //float 48 | MObject intersectionDeformer::pushAboveAmount; //float 49 | MObject intersectionDeformer::pushBelowDist; //float 50 | MObject intersectionDeformer::pushBelowAmount; //float 51 | MObject intersectionDeformer::thicknessDist; //float 52 | MObject intersectionDeformer::thicknessTol; //float 53 | MObject intersectionDeformer::intersectionMesh; //mesh 54 | MMeshIsectAccelParams intersectionDeformer::accelParams(MFnMesh::autoUniformGridParams());//crazy maya stuff 55 | 56 | 57 | 58 | void *intersectionDeformer::creator() 59 | { 60 | return new intersectionDeformer; 61 | } 62 | 63 | 64 | MStatus intersectionDeformer::initialize() 65 | { 66 | MStatus stat; 67 | 68 | MFnNumericAttribute FnNumeric; 69 | MFnTypedAttribute FnTyped; 70 | MFnEnumAttribute FnEnum; 71 | MRampAttribute RampAt; 72 | 73 | //weight 74 | weight = FnNumeric.create("weight", "we", MFnNumericData::kFloat); 75 | FnNumeric.setDefault( 1.0 ); 76 | FnNumeric.setKeyable(true); 77 | FnNumeric.setStorable(true); 78 | FnNumeric.setReadable(true); 79 | FnNumeric.setWritable(true); 80 | addAttribute( weight ); 81 | 82 | 83 | //space 84 | space = FnEnum.create("space", "sp", 0); 85 | FnEnum.addField("world",0); 86 | FnEnum.addField("object",1); 87 | FnEnum.setStorable(true); 88 | FnEnum.setKeyable(true); 89 | addAttribute(space); 90 | 91 | 92 | //lookDirection 93 | lookDirection = FnEnum.create("lookDirection", "loo", 2); 94 | FnEnum.addField("normalOut",0); 95 | FnEnum.addField("normalIn",1); 96 | FnEnum.addField("vector",2); 97 | FnEnum.addField("fromPoint",3); 98 | FnEnum.addField("toPoint",4); 99 | FnEnum.setStorable(true); 100 | FnEnum.setKeyable(true); 101 | addAttribute(lookDirection); 102 | 103 | 104 | //lookMaxDist 105 | lookMaxDist = FnNumeric.create("lookMaxDist", "lod", MFnNumericData::kFloat); 106 | FnNumeric.setDefault( 5000.0 ); 107 | FnNumeric.setKeyable(true); 108 | FnNumeric.setStorable(true); 109 | FnNumeric.setReadable(true); 110 | FnNumeric.setWritable(true); 111 | addAttribute( lookMaxDist ); 112 | 113 | 114 | //lookVector 115 | lookVectorX = FnNumeric.create( "lookVectorX", "lox", MFnNumericData::kDouble ); 116 | FnNumeric.setStorable(true); 117 | FnNumeric.setKeyable(true); 118 | lookVectorY = FnNumeric.create( "lookVectorY", "loy", MFnNumericData::kDouble ); 119 | FnNumeric.setStorable(true); 120 | FnNumeric.setKeyable(true); 121 | lookVectorZ = FnNumeric.create( "lookVectorZ", "loz", MFnNumericData::kDouble ); 122 | FnNumeric.setStorable(true); 123 | FnNumeric.setKeyable(true); 124 | lookVector = FnNumeric.create( "lookVector", "lov", lookVectorX, lookVectorY, lookVectorZ ); 125 | FnNumeric.setDefault( 0.0, -1.0, 0.0 ); 126 | FnNumeric.setStorable(true); 127 | FnNumeric.setKeyable(true); 128 | addAttribute(lookVector); 129 | 130 | //Center 131 | centerX = FnNumeric.create( "centerX", "cx", MFnNumericData::kDouble ); 132 | FnNumeric.setStorable(true); 133 | FnNumeric.setKeyable(true); 134 | centerY = FnNumeric.create( "centerY", "cy", MFnNumericData::kDouble ); 135 | FnNumeric.setStorable(true); 136 | FnNumeric.setKeyable(true); 137 | centerZ = FnNumeric.create( "centerZ", "cz", MFnNumericData::kDouble ); 138 | FnNumeric.setStorable(true); 139 | FnNumeric.setKeyable(true); 140 | center = FnNumeric.create( "center", "c", centerX, centerY, centerZ ); 141 | FnNumeric.setDefault( 0.0, 5.0, 0.0 ); 142 | FnNumeric.setStorable(true); 143 | FnNumeric.setKeyable(true); 144 | addAttribute(center); 145 | 146 | 147 | //pushDirection 148 | pushDirection = FnEnum.create("pushDirection", "pud", 0); 149 | FnEnum.addField("normalOut",0); 150 | FnEnum.addField("normalIn",1); 151 | FnEnum.addField("vector",2); 152 | FnEnum.addField("fromCenter",3); 153 | FnEnum.addField("toCenter",4); 154 | FnEnum.setStorable(true); 155 | FnEnum.setKeyable(true); 156 | addAttribute(pushDirection); 157 | 158 | 159 | //pushRamp 160 | MString longName = "pushRamp"; 161 | MString shortName = "pur"; 162 | pushRamp = RampAt.createCurveRamp(longName, shortName); 163 | addAttribute(pushRamp); 164 | 165 | //pushAboveDist 166 | pushAboveDist = FnNumeric.create("pushAboveDist", "pad", MFnNumericData::kFloat); 167 | FnNumeric.setDefault( 0.5 ); 168 | FnNumeric.setKeyable(true); 169 | FnNumeric.setStorable(true); 170 | FnNumeric.setReadable(true); 171 | FnNumeric.setWritable(true); 172 | addAttribute( pushAboveDist ); 173 | 174 | //pushAboveAmount 175 | pushAboveAmount = FnNumeric.create("pushAboveAmount", "paa", MFnNumericData::kFloat); 176 | FnNumeric.setDefault( 0.5 ); 177 | FnNumeric.setKeyable(true); 178 | FnNumeric.setStorable(true); 179 | FnNumeric.setReadable(true); 180 | FnNumeric.setWritable(true); 181 | addAttribute( pushAboveAmount ); 182 | 183 | //pushBelowDist 184 | pushBelowDist = FnNumeric.create("pushBelowDist", "pbd", MFnNumericData::kFloat); 185 | FnNumeric.setDefault( 1.0 ); 186 | FnNumeric.setKeyable(true); 187 | FnNumeric.setStorable(true); 188 | FnNumeric.setReadable(true); 189 | FnNumeric.setWritable(true); 190 | FnNumeric.setMin( 0.001f ); 191 | addAttribute( pushBelowDist ); 192 | 193 | //pushBelowAmount 194 | pushBelowAmount = FnNumeric.create("pushBelowAmount", "pba", MFnNumericData::kFloat); 195 | FnNumeric.setDefault( 0.5 ); 196 | FnNumeric.setKeyable(true); 197 | FnNumeric.setStorable(true); 198 | FnNumeric.setReadable(true); 199 | FnNumeric.setWritable(true); 200 | addAttribute( pushBelowAmount ); 201 | 202 | //thicknessDist 203 | thicknessDist = FnNumeric.create("thicknessDist", "thd", MFnNumericData::kFloat); 204 | FnNumeric.setDefault( 0.3 ); 205 | FnNumeric.setKeyable(true); 206 | FnNumeric.setStorable(true); 207 | FnNumeric.setReadable(true); 208 | FnNumeric.setWritable(true); 209 | addAttribute( thicknessDist ); 210 | 211 | //thicknessTol 212 | thicknessTol = FnNumeric.create("thicknessTol", "tht", MFnNumericData::kFloat); 213 | FnNumeric.setDefault( 0.8 ); 214 | FnNumeric.setKeyable(true); 215 | FnNumeric.setStorable(true); 216 | FnNumeric.setReadable(true); 217 | FnNumeric.setWritable(true); 218 | addAttribute( thicknessTol ); 219 | 220 | 221 | //intersectionMesh 222 | intersectionMesh = FnTyped.create("intersectionMesh", "inm", MFnData::kMesh); 223 | FnTyped.setArray( false ); 224 | FnTyped.setReadable(true); 225 | FnTyped.setWritable(true); 226 | addAttribute( intersectionMesh ); 227 | 228 | 229 | attributeAffects(intersectionMesh, outputGeom); 230 | attributeAffects(thicknessTol, outputGeom); 231 | attributeAffects(thicknessDist, outputGeom); 232 | attributeAffects(pushBelowAmount, outputGeom); 233 | attributeAffects(pushBelowDist, outputGeom); 234 | attributeAffects(pushAboveAmount, outputGeom); 235 | attributeAffects(pushAboveDist, outputGeom); 236 | attributeAffects(pushRamp, outputGeom); 237 | attributeAffects(pushDirection, outputGeom); 238 | attributeAffects(center, outputGeom); 239 | attributeAffects(lookMaxDist, outputGeom); 240 | attributeAffects(lookVector, outputGeom); 241 | attributeAffects(lookDirection, outputGeom); 242 | attributeAffects(space, outputGeom); 243 | attributeAffects(weight, outputGeom); 244 | 245 | return stat; 246 | } 247 | 248 | 249 | 250 | MStatus intersectionDeformer::deform(MDataBlock &data, MItGeometry &iter, const MMatrix &mat, unsigned int multiIndex) 251 | { 252 | MStatus stat; 253 | 254 | //lets see if we need to do anything 255 | MDataHandle DataHandle = data.inputValue(envelope, &stat); 256 | float env = DataHandle.asFloat(); 257 | if (env == 0) 258 | return stat; 259 | DataHandle = data.inputValue(weight, &stat); 260 | const float weight = DataHandle.asFloat(); 261 | if (weight == 0) 262 | return stat; 263 | env = (env*weight); 264 | 265 | ///////////get user data 266 | short Space = data.inputValue(space, &stat).asShort(); 267 | short LookDirection = data.inputValue(lookDirection, &stat).asShort(); 268 | MVector LookVector = data.inputValue(lookVector, &stat).asDouble3(); 269 | float LookMaxDist = data.inputValue(lookMaxDist, &stat).asFloat(); 270 | MVector PushCenter = data.inputValue(center, &stat).asDouble3(); 271 | short PushDirection = data.inputValue(pushDirection, &stat).asShort(); 272 | float PushAboveDist = data.inputValue(pushAboveDist, &stat).asFloat(); 273 | float PushAboveAmount = data.inputValue(pushAboveAmount, &stat).asFloat(); 274 | float PushBelowDist = data.inputValue(pushBelowDist, &stat).asFloat(); 275 | float PushBelowAmount = data.inputValue(pushBelowAmount, &stat).asFloat(); 276 | float ThicknessDist = data.inputValue(thicknessDist, &stat).asFloat(); 277 | float ThicknessTol = data.inputValue(thicknessTol, &stat).asFloat(); 278 | 279 | //intersectionMesh 280 | MFnMesh IntMesh; 281 | DataHandle = data.inputValue(intersectionMesh, &stat); 282 | if (!stat) 283 | return Err(stat,"Can't get mesh to snap to"); 284 | MObject IntMeshObj = DataHandle.asMesh(); 285 | IntMesh.setObject(IntMeshObj); 286 | //MItMeshPolygon IntMeshIt(IntMeshObj); 287 | 288 | //maya curve shape 289 | MObject thisNode = this->thisMObject(); 290 | MFnDependencyNode fieldNode(thisNode); 291 | MPlug PushRampPlug = fieldNode.findPlug("pushRamp", &stat); 292 | MRampAttribute PushRamp(PushRampPlug, &stat); 293 | 294 | 295 | //get source object if needed for normal data 296 | MFnMesh sourceMesh; 297 | MFnNurbsSurface sourceNurbs; 298 | bool inMesh=true; 299 | if (LookDirection < 3 || PushDirection < 3 || ThicknessDist !=0) 300 | { 301 | MArrayDataHandle InputArrayData = data.inputValue(input, &stat); 302 | if (!stat) 303 | return Err(stat,"Can't get source for normal direction/thickness"); 304 | stat = InputArrayData.jumpToElement(multiIndex); 305 | if (!stat) 306 | return Err(stat,"Can't get source for normal direction/thickness"); 307 | MDataHandle InputData = InputArrayData.inputValue(); 308 | MDataHandle InputGeom = InputData.child(inputGeom); 309 | //check for mesh 310 | MObject tempObj = InputGeom.asMesh(); 311 | stat = sourceMesh.setObject(tempObj); 312 | if (!stat) 313 | { 314 | tempObj = InputGeom.asNurbsSurface(); 315 | stat = sourceNurbs.setObject(tempObj); 316 | if (!stat) 317 | return Err(stat,"Can't get source for normal direction/thickness"); 318 | else 319 | inMesh = false; 320 | } 321 | } 322 | 323 | 324 | //intersection vars 325 | MVector intersectionVec; 326 | MFloatVector intersectionVecF; 327 | MPoint startPointWS, startPointLS; 328 | MFloatPoint startPointWSF; 329 | MIntArray* nullIntArray = NULL; 330 | MFloatArray* nullArray = NULL; 331 | MFloatPointArray hitPoints; 332 | MFloatArray hitRayParams; 333 | 334 | 335 | /////////////////go 336 | iter.reset(); 337 | for ( ; !iter.isDone(); iter.next()) 338 | { 339 | //check for painted weights 340 | float currEnv = env * weightValue(data, multiIndex, iter.index()); 341 | 342 | if (currEnv !=0) 343 | { 344 | //get normal if needed 345 | MVector normalVec; 346 | if (LookDirection < 3 || PushDirection < 3 || ThicknessDist != 0) 347 | { 348 | if (inMesh) 349 | normalVec = getMeshNormal(sourceMesh, iter.index(), Space); 350 | else 351 | normalVec = getNurbsNormal(sourceNurbs, iter.index(), Space); 352 | } 353 | 354 | 355 | //get look direction 356 | MVector intersectionVec; 357 | switch (LookDirection) 358 | { 359 | case normalIn: 360 | intersectionVec = -normalVec; 361 | break; 362 | case normalOut: 363 | intersectionVec = normalVec; 364 | break; 365 | case vector: 366 | intersectionVec = LookVector; 367 | break; 368 | case fromPoint: 369 | intersectionVec = MVector(startPointWS - LookVector); 370 | break; 371 | case toPoint: 372 | intersectionVec = MVector(LookVector - startPointWS); 373 | break; 374 | } 375 | intersectionVec.normalize(); 376 | 377 | 378 | //get start point 379 | startPointLS = iter.position(); 380 | startPointWS = iter.position()*mat; 381 | 382 | //convert doubles to float for maya intersection call 383 | intersectionVecF = MFloatVector(intersectionVec); 384 | startPointWSF = MFloatPoint(startPointWS.x, startPointWS.y, startPointWS.z, startPointWS.w); 385 | 386 | //maya intersection check 387 | bool hit = IntMesh.allIntersections(startPointWSF, intersectionVecF, nullIntArray, nullIntArray, 388 | true, MSpace::kWorld, LookMaxDist, true, &accelParams, true, hitPoints, 389 | &hitRayParams, nullIntArray, nullIntArray, nullArray, nullArray, 0.01f); 390 | 391 | //if an intersection was found 392 | if (hit) 393 | { 394 | //MGlobal::displayInfo("found intersection"); 395 | float distToHit = hitRayParams[0]; 396 | MFloatPoint pointHit = hitPoints[0]; 397 | 398 | //if we hit or are within Tolerences 399 | float maxLook = max(0.0f, PushAboveDist); 400 | maxLook = max(maxLook, ThicknessDist); 401 | if (distToHit < maxLook) 402 | { 403 | //get push direction 404 | MVector pushVec; 405 | switch (PushDirection) 406 | { 407 | case normalIn: 408 | pushVec = -normalVec; 409 | break; 410 | case normalOut: 411 | pushVec = normalVec; 412 | break; 413 | case vector: 414 | pushVec = PushCenter; 415 | break; 416 | case fromPoint: 417 | pushVec = MVector(pointHit - PushCenter); 418 | break; 419 | case toPoint: 420 | pushVec = MVector(PushCenter - pointHit); 421 | break; 422 | } 423 | pushVec.normalize(); 424 | 425 | 426 | //if we have intersected (below) 427 | if (distToHit < 0.0f) 428 | { 429 | float distToHitCurr = min(-distToHit, PushBelowDist); 430 | float PushBelowDistCurr; 431 | 432 | //calc push amount 433 | if (PushRamp.getNumEntries() >1) 434 | { 435 | float rampPostion = ((distToHitCurr/PushBelowDist)*0.5f) + 0.5f; 436 | float rampValue; 437 | PushRamp.getValueAtPosition(rampPostion, rampValue, &stat); 438 | PushBelowDistCurr = rampValue; 439 | } 440 | else 441 | PushBelowDistCurr = (distToHitCurr/PushBelowDist); 442 | 443 | //calc the new point postion and run second intersection 444 | startPointWSF += (PushBelowDistCurr*PushBelowAmount)* pushVec ; 445 | hit = IntMesh.allIntersections(startPointWSF, intersectionVecF, nullIntArray, nullIntArray, 446 | true, MSpace::kWorld, LookMaxDist, true, &accelParams, true, hitPoints, 447 | &hitRayParams, nullIntArray, nullIntArray, nullArray, nullArray, 0.01f); 448 | 449 | 450 | if (hit) 451 | { 452 | MPoint outPoint(hitPoints[0]); 453 | 454 | //if thickness is on 455 | if (ThicknessDist !=0) 456 | outPoint = thickness(outPoint, normalVec, intersectionVecF, 1.0f, ThicknessDist, ThicknessTol); 457 | 458 | //calc out point 459 | outPoint = (outPoint * mat.inverse()); 460 | outPoint = (outPoint*currEnv) + (startPointLS *(1-currEnv)); 461 | iter.setPosition(outPoint); 462 | } 463 | } 464 | //PushAboveDist stuff here 465 | else if (distToHit < PushAboveDist) 466 | { 467 | float distToHitCurr = min(distToHit, PushAboveDist); 468 | float PushAboveDistCurr; 469 | 470 | //calc push amount 471 | if (PushRamp.getNumEntries() >1) 472 | { 473 | float rampPostion = (1-(distToHitCurr/PushAboveDist))/2; 474 | float rampValue; 475 | PushRamp.getValueAtPosition(rampPostion, rampValue, &stat); 476 | PushAboveDistCurr = rampValue; 477 | } 478 | else 479 | PushAboveDistCurr = 1 -(distToHitCurr/PushAboveDist); 480 | 481 | //calc the new point postion and run second intersection 482 | startPointWSF += (PushAboveDistCurr*PushAboveAmount)* pushVec ; 483 | hit = IntMesh.allIntersections(startPointWSF, intersectionVecF, nullIntArray, nullIntArray, 484 | true, MSpace::kWorld, LookMaxDist, true, &accelParams, true, hitPoints, 485 | &hitRayParams, nullIntArray, nullIntArray, nullArray, nullArray, 0.01f); 486 | 487 | 488 | if (hit) 489 | { 490 | MPoint outPoint(hitPoints[0]); 491 | 492 | 493 | //if thickness is on 494 | outPoint -= intersectionVecF*distToHit; 495 | if (ThicknessDist !=0 && distToHit < ThicknessDist) 496 | { 497 | float aboveDist = 1- (distToHit/ThicknessDist); 498 | outPoint = thickness(outPoint, normalVec, intersectionVecF, aboveDist, ThicknessDist, ThicknessTol); 499 | } 500 | 501 | //calc out point 502 | //outPoint -= intersectionVecF*distToHit; 503 | outPoint = (outPoint * mat.inverse()); 504 | outPoint = (outPoint*currEnv) + (startPointLS *(1-currEnv)); 505 | iter.setPosition(outPoint); 506 | } 507 | 508 | } 509 | 510 | 511 | 512 | //if hit is within thickness dist 513 | else if (distToHit < ThicknessDist) 514 | { 515 | float dist = ThicknessDist - distToHit;///ThicknessDist; 516 | float falloff = ThicknessDist/distToHit;///ThicknessDist; 517 | MPoint outPoint = thickness(startPointWS, normalVec, intersectionVecF, 1.0f, dist, ThicknessTol); 518 | 519 | //calc out point 520 | outPoint = (outPoint * mat.inverse()); 521 | outPoint = (outPoint*currEnv) + (startPointLS *(1-currEnv)); 522 | iter.setPosition(outPoint); 523 | } 524 | } 525 | } 526 | } 527 | } 528 | 529 | return stat; 530 | } 531 | 532 | // ====================================================================== 533 | // EOF 534 | // ====================================================================== 535 | -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer/.svn/text-base/intersectionDeformer.h.svn-base: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // Copyright (C): FooMojo 3 | // File: intersectionDeformer.h 4 | // Authors: joseph 5 | // ====================================================================== 6 | 7 | #ifndef __INTYDEF__ 8 | #define __INTYDEF__ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | class intersectionDeformer: public MPxDeformerNode 18 | { 19 | public: 20 | intersectionDeformer() {}; 21 | 22 | virtual ~intersectionDeformer() {}; 23 | 24 | static void *creator(); 25 | 26 | static MStatus initialize(); 27 | 28 | virtual MStatus deform(MDataBlock &data, MItGeometry &iter, const MMatrix &mat, unsigned int multiIndex); 29 | 30 | static MTypeId id; 31 | static MObject weight;//env overide 32 | static MObject space; //world, local 33 | static MObject lookDirection;//normals, vector, from, to 34 | static MObject lookVector;//vector for lookDirection 35 | static MObject lookVectorX; 36 | static MObject lookVectorY; 37 | static MObject lookVectorZ; 38 | static MObject lookMaxDist; //float 39 | static MObject center; //vector 40 | static MObject centerX; 41 | static MObject centerY; 42 | static MObject centerZ; 43 | static MObject pushDirection;//normals, vector, from, to 44 | static MObject pushRamp; //maya curve shape 45 | static MObject pushAboveDist; //float 46 | static MObject pushAboveAmount; //float 47 | static MObject pushBelowDist; //float 48 | static MObject pushBelowAmount; //float 49 | static MObject thicknessDist; //float 50 | static MObject thicknessTol; //float 51 | static MObject intersectionMesh; //mesh 52 | static MMeshIsectAccelParams accelParams;//crazy maya stuff 53 | }; 54 | 55 | 56 | enum lookDir 57 | { 58 | normalOut = 0, 59 | normalIn, 60 | vector, 61 | fromPoint, 62 | toPoint 63 | }; 64 | 65 | inline MVector getMeshNormal(MFnMesh &mesh, int index, short space) 66 | { 67 | MVector result; 68 | if (space ==0) 69 | mesh.getVertexNormal(index, result, MSpace::kWorld); 70 | else 71 | mesh.getVertexNormal(index, result); 72 | return result; 73 | } 74 | 75 | inline MVector getNurbsNormal(MFnNurbsSurface &surf, int index, short space) 76 | { 77 | MVector result; 78 | 79 | //this process sucks 80 | double u,v; 81 | MPointArray cvs; 82 | surf.getCVs(cvs); 83 | surf.getParamAtPoint( cvs[index], u, v, true); 84 | if (space ==0) 85 | result = surf.normal(u,v, MSpace::kWorld); 86 | else 87 | result = surf.normal(u,v); 88 | 89 | return result; 90 | } 91 | 92 | inline MPoint thickness(MPoint point, MVector normal, MVector ray, float dist, float thick, float tol) 93 | { 94 | MPoint outPoint = point; 95 | 96 | double d = (ray * normal); 97 | 98 | if (d <= -tol) 99 | outPoint = point+(-ray*(thick*dist)); 100 | else if (d < tol) 101 | { 102 | double tolCurr(1 - (d+tol)/(tol*2)); 103 | outPoint = point+(-ray*(thick*dist*tolCurr)); 104 | } 105 | 106 | return outPoint; 107 | } 108 | 109 | 110 | #endif 111 | 112 | // ====================================================================== 113 | // EOF 114 | // ====================================================================== 115 | 116 | -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer/.svn/text-base/intersectionDeformer.mll.svn-base: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidrichardnelson/maya/c0f2677a7ae73a2305d60db0041102f4e3558748/plug-ins/intersectionDeformer/.svn/text-base/intersectionDeformer.mll.svn-base -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer/.svn/text-base/intersectionDeformer.sln.svn-base: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 10.00 2 | # Visual Studio 2008 3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "intersectionDeformer", "intersectionDeformer.vcproj", "{681412B0-F197-4A2F-9263-DEA2E8690146}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | 2009x64|Win32 = 2009x64|Win32 8 | 2009x64|x64 = 2009x64|x64 9 | 2010x64|Win32 = 2010x64|Win32 10 | 2010x64|x64 = 2010x64|x64 11 | 2011x64|Win32 = 2011x64|Win32 12 | 2011x64|x64 = 2011x64|x64 13 | Debug|Win32 = Debug|Win32 14 | Debug|x64 = Debug|x64 15 | Release x64|Win32 = Release x64|Win32 16 | Release x64|x64 = Release x64|x64 17 | Release|Win32 = Release|Win32 18 | Release|x64 = Release|x64 19 | ReleaseDebug|Win32 = ReleaseDebug|Win32 20 | ReleaseDebug|x64 = ReleaseDebug|x64 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {681412B0-F197-4A2F-9263-DEA2E8690146}.2009x64|Win32.ActiveCfg = 2009x64|Win32 24 | {681412B0-F197-4A2F-9263-DEA2E8690146}.2009x64|Win32.Build.0 = 2009x64|Win32 25 | {681412B0-F197-4A2F-9263-DEA2E8690146}.2009x64|x64.ActiveCfg = 2009x64|x64 26 | {681412B0-F197-4A2F-9263-DEA2E8690146}.2009x64|x64.Build.0 = 2009x64|x64 27 | {681412B0-F197-4A2F-9263-DEA2E8690146}.2010x64|Win32.ActiveCfg = 2010x64|x64 28 | {681412B0-F197-4A2F-9263-DEA2E8690146}.2010x64|Win32.Build.0 = 2010x64|x64 29 | {681412B0-F197-4A2F-9263-DEA2E8690146}.2010x64|x64.ActiveCfg = 2010x64|x64 30 | {681412B0-F197-4A2F-9263-DEA2E8690146}.2010x64|x64.Build.0 = 2010x64|x64 31 | {681412B0-F197-4A2F-9263-DEA2E8690146}.2011x64|Win32.ActiveCfg = 2011x64|Win32 32 | {681412B0-F197-4A2F-9263-DEA2E8690146}.2011x64|Win32.Build.0 = 2011x64|Win32 33 | {681412B0-F197-4A2F-9263-DEA2E8690146}.2011x64|x64.ActiveCfg = 2011x64|x64 34 | {681412B0-F197-4A2F-9263-DEA2E8690146}.2011x64|x64.Build.0 = 2011x64|x64 35 | {681412B0-F197-4A2F-9263-DEA2E8690146}.Debug|Win32.ActiveCfg = Debug|Win32 36 | {681412B0-F197-4A2F-9263-DEA2E8690146}.Debug|Win32.Build.0 = Debug|Win32 37 | {681412B0-F197-4A2F-9263-DEA2E8690146}.Debug|x64.ActiveCfg = Debug|x64 38 | {681412B0-F197-4A2F-9263-DEA2E8690146}.Debug|x64.Build.0 = Debug|x64 39 | {681412B0-F197-4A2F-9263-DEA2E8690146}.Release x64|Win32.ActiveCfg = Release x64|Win32 40 | {681412B0-F197-4A2F-9263-DEA2E8690146}.Release x64|Win32.Build.0 = Release x64|Win32 41 | {681412B0-F197-4A2F-9263-DEA2E8690146}.Release x64|x64.ActiveCfg = Release x64|x64 42 | {681412B0-F197-4A2F-9263-DEA2E8690146}.Release x64|x64.Build.0 = Release x64|x64 43 | {681412B0-F197-4A2F-9263-DEA2E8690146}.Release|Win32.ActiveCfg = Release|Win32 44 | {681412B0-F197-4A2F-9263-DEA2E8690146}.Release|Win32.Build.0 = Release|Win32 45 | {681412B0-F197-4A2F-9263-DEA2E8690146}.Release|x64.ActiveCfg = Release|x64 46 | {681412B0-F197-4A2F-9263-DEA2E8690146}.Release|x64.Build.0 = Release|x64 47 | {681412B0-F197-4A2F-9263-DEA2E8690146}.ReleaseDebug|Win32.ActiveCfg = ReleaseDebug|Win32 48 | {681412B0-F197-4A2F-9263-DEA2E8690146}.ReleaseDebug|Win32.Build.0 = ReleaseDebug|Win32 49 | {681412B0-F197-4A2F-9263-DEA2E8690146}.ReleaseDebug|x64.ActiveCfg = ReleaseDebug|x64 50 | {681412B0-F197-4A2F-9263-DEA2E8690146}.ReleaseDebug|x64.Build.0 = ReleaseDebug|x64 51 | EndGlobalSection 52 | GlobalSection(SolutionProperties) = preSolution 53 | HideSolutionNode = FALSE 54 | EndGlobalSection 55 | EndGlobal 56 | -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer/.svn/text-base/intersectionDeformer.vcproj.svn-base: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 30 | 33 | 36 | 39 | 42 | 51 | 69 | 72 | 77 | 80 | 96 | 99 | 102 | 105 | 108 | 111 | 114 | 117 | 118 | 127 | 130 | 133 | 136 | 139 | 148 | 166 | 169 | 174 | 177 | 193 | 196 | 199 | 202 | 205 | 208 | 211 | 214 | 215 | 224 | 227 | 230 | 233 | 236 | 245 | 260 | 263 | 268 | 271 | 287 | 290 | 293 | 296 | 299 | 302 | 305 | 308 | 309 | 318 | 321 | 324 | 327 | 330 | 339 | 354 | 357 | 362 | 365 | 381 | 384 | 387 | 390 | 393 | 396 | 399 | 402 | 403 | 412 | 415 | 418 | 421 | 424 | 433 | 451 | 454 | 459 | 462 | 477 | 480 | 483 | 486 | 489 | 492 | 495 | 498 | 499 | 508 | 511 | 514 | 517 | 520 | 529 | 547 | 550 | 555 | 558 | 573 | 576 | 579 | 582 | 585 | 588 | 591 | 594 | 595 | 604 | 607 | 610 | 613 | 616 | 625 | 643 | 646 | 651 | 654 | 669 | 672 | 675 | 678 | 681 | 684 | 687 | 690 | 691 | 700 | 703 | 706 | 709 | 712 | 721 | 739 | 742 | 747 | 750 | 765 | 768 | 771 | 774 | 777 | 780 | 783 | 786 | 787 | 796 | 799 | 802 | 805 | 808 | 817 | 835 | 838 | 843 | 846 | 861 | 864 | 867 | 870 | 873 | 876 | 879 | 882 | 883 | 892 | 895 | 898 | 901 | 904 | 913 | 931 | 934 | 939 | 942 | 957 | 960 | 963 | 966 | 969 | 972 | 975 | 978 | 979 | 988 | 991 | 994 | 997 | 1000 | 1009 | 1027 | 1030 | 1035 | 1038 | 1053 | 1056 | 1059 | 1062 | 1065 | 1068 | 1071 | 1074 | 1075 | 1084 | 1087 | 1090 | 1093 | 1096 | 1105 | 1123 | 1126 | 1131 | 1134 | 1149 | 1152 | 1155 | 1158 | 1161 | 1164 | 1167 | 1170 | 1171 | 1172 | 1173 | 1174 | 1175 | 1178 | 1181 | 1182 | 1185 | 1186 | 1189 | 1190 | 1191 | 1192 | 1193 | 1194 | 1195 | -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer/.svn/text-base/reg.cpp.svn-base: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // Copyright (C): FooMojo 3 | // File: reg.cpp 4 | // Authors: joseph 5 | // ====================================================================== 6 | 7 | ///register the node with maya 8 | 9 | //#include 10 | #include 11 | #include "intersectionDeformer.h" 12 | 13 | MStatus initializePlugin( MObject obj ) 14 | { 15 | MString vendorStr( "FooMojo: " ); 16 | vendorStr += __DATE__; 17 | vendorStr += " @ "; 18 | vendorStr += __TIME__; 19 | vendorStr += " (authors: joseph)"; 20 | 21 | MFnPlugin plugin( obj, vendorStr.asChar(), "beta", "Any"); 22 | MStatus result; 23 | result = plugin.registerNode( "intDeformer", intersectionDeformer::id, intersectionDeformer::creator, 24 | intersectionDeformer::initialize, MPxNode::kDeformerNode ); 25 | 26 | MGlobal:: displayInfo("=================================================================="); 27 | MGlobal:: displayInfo("intersectionDeformer plugin loaded (see script editor for details)."); 28 | MGlobal:: displayInfo( vendorStr.asChar() ); 29 | MGlobal:: displayInfo("=================================================================="); 30 | 31 | return result; 32 | } 33 | 34 | MStatus uninitializePlugin( MObject obj) 35 | { 36 | MStatus result; 37 | MFnPlugin plugin( obj ); 38 | result = plugin.deregisterNode( intersectionDeformer::id ); 39 | return result; 40 | } 41 | 42 | // ====================================================================== 43 | // EOF 44 | // ====================================================================== 45 | -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer/.svn/text-base/testScene.mb.svn-base: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidrichardnelson/maya/c0f2677a7ae73a2305d60db0041102f4e3558748/plug-ins/intersectionDeformer/.svn/text-base/testScene.mb.svn-base -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer/intersectionDeformer.cpp: -------------------------------------------------------------------------------- 1 | // * main.cpp 2 | // File: intersectionDeformer.cpp 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | using namespace std; 20 | 21 | 22 | #include 23 | 24 | #include 25 | 26 | #include "intersectionDeformer.h" 27 | 28 | 29 | MTypeId intersectionDeformer::id( 0x8001e ); 30 | MObject intersectionDeformer::weight; //env overide 31 | MObject intersectionDeformer::space; //world, local 32 | MObject intersectionDeformer::lookDirection;//normals, vector, from, to 33 | MObject intersectionDeformer::lookVector;//vector for lookDirection 34 | MObject intersectionDeformer::lookVectorX; 35 | MObject intersectionDeformer::lookVectorY; 36 | MObject intersectionDeformer::lookVectorZ; 37 | MObject intersectionDeformer::lookMaxDist; //float 38 | MObject intersectionDeformer::center; //vector 39 | MObject intersectionDeformer::centerX; 40 | MObject intersectionDeformer::centerY; 41 | MObject intersectionDeformer::centerZ; 42 | MObject intersectionDeformer::pushDirection;//normals, vector, from, to 43 | MObject intersectionDeformer::pushRamp; //maya curve shape 44 | MObject intersectionDeformer::pushAboveDist; //float 45 | MObject intersectionDeformer::pushAboveAmount; //float 46 | MObject intersectionDeformer::pushBelowDist; //float 47 | MObject intersectionDeformer::pushBelowAmount; //float 48 | MObject intersectionDeformer::thicknessDist; //float 49 | MObject intersectionDeformer::thicknessTol; //float 50 | MObject intersectionDeformer::intersectionMesh; //mesh 51 | MMeshIsectAccelParams intersectionDeformer::accelParams(MFnMesh::autoUniformGridParams());//crazy maya stuff 52 | 53 | void *intersectionDeformer::creator() { 54 | return new intersectionDeformer; 55 | } 56 | 57 | 58 | MStatus intersectionDeformer::initialize() { 59 | MStatus stat; 60 | 61 | MFnNumericAttribute FnNumeric; 62 | MFnTypedAttribute FnTyped; 63 | MFnEnumAttribute FnEnum; 64 | MRampAttribute RampAt; 65 | 66 | //weight 67 | weight = FnNumeric.create("weight", "we", MFnNumericData::kFloat); 68 | FnNumeric.setDefault( 1.0 ); 69 | FnNumeric.setKeyable(true); 70 | FnNumeric.setStorable(true); 71 | FnNumeric.setReadable(true); 72 | FnNumeric.setWritable(true); 73 | addAttribute( weight ); 74 | 75 | 76 | //space 77 | space = FnEnum.create("space", "sp", 0); 78 | FnEnum.addField("world",0); 79 | FnEnum.addField("object",1); 80 | FnEnum.setStorable(true); 81 | FnEnum.setKeyable(true); 82 | addAttribute(space); 83 | 84 | 85 | //lookDirection 86 | lookDirection = FnEnum.create("lookDirection", "loo", 2); 87 | FnEnum.addField("normalOut",0); 88 | FnEnum.addField("normalIn",1); 89 | FnEnum.addField("vector",2); 90 | FnEnum.addField("fromPoint",3); 91 | FnEnum.addField("toPoint",4); 92 | FnEnum.setStorable(true); 93 | FnEnum.setKeyable(true); 94 | addAttribute(lookDirection); 95 | 96 | 97 | //lookMaxDist 98 | lookMaxDist = FnNumeric.create("lookMaxDist", "lod", MFnNumericData::kFloat); 99 | FnNumeric.setDefault( 5000.0 ); 100 | FnNumeric.setKeyable(true); 101 | FnNumeric.setStorable(true); 102 | FnNumeric.setReadable(true); 103 | FnNumeric.setWritable(true); 104 | addAttribute( lookMaxDist ); 105 | 106 | 107 | //lookVector 108 | lookVectorX = FnNumeric.create( "lookVectorX", "lox", MFnNumericData::kDouble ); 109 | FnNumeric.setStorable(true); 110 | FnNumeric.setKeyable(true); 111 | lookVectorY = FnNumeric.create( "lookVectorY", "loy", MFnNumericData::kDouble ); 112 | FnNumeric.setStorable(true); 113 | FnNumeric.setKeyable(true); 114 | lookVectorZ = FnNumeric.create( "lookVectorZ", "loz", MFnNumericData::kDouble ); 115 | FnNumeric.setStorable(true); 116 | FnNumeric.setKeyable(true); 117 | lookVector = FnNumeric.create( "lookVector", "lov", lookVectorX, lookVectorY, lookVectorZ ); 118 | FnNumeric.setDefault( 0.0, -1.0, 0.0 ); 119 | FnNumeric.setStorable(true); 120 | FnNumeric.setKeyable(true); 121 | addAttribute(lookVector); 122 | 123 | //Center 124 | centerX = FnNumeric.create( "centerX", "cx", MFnNumericData::kDouble ); 125 | FnNumeric.setStorable(true); 126 | FnNumeric.setKeyable(true); 127 | centerY = FnNumeric.create( "centerY", "cy", MFnNumericData::kDouble ); 128 | FnNumeric.setStorable(true); 129 | FnNumeric.setKeyable(true); 130 | centerZ = FnNumeric.create( "centerZ", "cz", MFnNumericData::kDouble ); 131 | FnNumeric.setStorable(true); 132 | FnNumeric.setKeyable(true); 133 | center = FnNumeric.create( "center", "c", centerX, centerY, centerZ ); 134 | FnNumeric.setDefault( 0.0, 5.0, 0.0 ); 135 | FnNumeric.setStorable(true); 136 | FnNumeric.setKeyable(true); 137 | addAttribute(center); 138 | 139 | 140 | //pushDirection 141 | pushDirection = FnEnum.create("pushDirection", "pud", 0); 142 | FnEnum.addField("normalOut",0); 143 | FnEnum.addField("normalIn",1); 144 | FnEnum.addField("vector",2); 145 | FnEnum.addField("fromCenter",3); 146 | FnEnum.addField("toCenter",4); 147 | FnEnum.setStorable(true); 148 | FnEnum.setKeyable(true); 149 | addAttribute(pushDirection); 150 | 151 | 152 | //pushRamp 153 | MString longName = "pushRamp"; 154 | MString shortName = "pur"; 155 | pushRamp = RampAt.createCurveRamp(longName, shortName); 156 | addAttribute(pushRamp); 157 | 158 | //pushAboveDist 159 | pushAboveDist = FnNumeric.create("pushAboveDist", "pad", MFnNumericData::kFloat); 160 | FnNumeric.setDefault( 0.5 ); 161 | FnNumeric.setKeyable(true); 162 | FnNumeric.setStorable(true); 163 | FnNumeric.setReadable(true); 164 | FnNumeric.setWritable(true); 165 | addAttribute( pushAboveDist ); 166 | 167 | //pushAboveAmount 168 | pushAboveAmount = FnNumeric.create("pushAboveAmount", "paa", MFnNumericData::kFloat); 169 | FnNumeric.setDefault( 0.5 ); 170 | FnNumeric.setKeyable(true); 171 | FnNumeric.setStorable(true); 172 | FnNumeric.setReadable(true); 173 | FnNumeric.setWritable(true); 174 | addAttribute( pushAboveAmount ); 175 | 176 | //pushBelowDist 177 | pushBelowDist = FnNumeric.create("pushBelowDist", "pbd", MFnNumericData::kFloat); 178 | FnNumeric.setDefault( 1.0 ); 179 | FnNumeric.setKeyable(true); 180 | FnNumeric.setStorable(true); 181 | FnNumeric.setReadable(true); 182 | FnNumeric.setWritable(true); 183 | FnNumeric.setMin( 0.001f ); 184 | addAttribute( pushBelowDist ); 185 | 186 | //pushBelowAmount 187 | pushBelowAmount = FnNumeric.create("pushBelowAmount", "pba", MFnNumericData::kFloat); 188 | FnNumeric.setDefault( 0.5 ); 189 | FnNumeric.setKeyable(true); 190 | FnNumeric.setStorable(true); 191 | FnNumeric.setReadable(true); 192 | FnNumeric.setWritable(true); 193 | addAttribute( pushBelowAmount ); 194 | 195 | //thicknessDist 196 | thicknessDist = FnNumeric.create("thicknessDist", "thd", MFnNumericData::kFloat); 197 | FnNumeric.setDefault( 0.3 ); 198 | FnNumeric.setKeyable(true); 199 | FnNumeric.setStorable(true); 200 | FnNumeric.setReadable(true); 201 | FnNumeric.setWritable(true); 202 | addAttribute( thicknessDist ); 203 | 204 | //thicknessTol 205 | thicknessTol = FnNumeric.create("thicknessTol", "tht", MFnNumericData::kFloat); 206 | FnNumeric.setDefault( 0.8 ); 207 | FnNumeric.setKeyable(true); 208 | FnNumeric.setStorable(true); 209 | FnNumeric.setReadable(true); 210 | FnNumeric.setWritable(true); 211 | addAttribute( thicknessTol ); 212 | 213 | 214 | //intersectionMesh 215 | intersectionMesh = FnTyped.create("intersectionMesh", "inm", MFnData::kMesh); 216 | FnTyped.setArray( false ); 217 | FnTyped.setReadable(true); 218 | FnTyped.setWritable(true); 219 | addAttribute( intersectionMesh ); 220 | 221 | 222 | attributeAffects(intersectionMesh, outputGeom); 223 | attributeAffects(thicknessTol, outputGeom); 224 | attributeAffects(thicknessDist, outputGeom); 225 | attributeAffects(pushBelowAmount, outputGeom); 226 | attributeAffects(pushBelowDist, outputGeom); 227 | attributeAffects(pushAboveAmount, outputGeom); 228 | attributeAffects(pushAboveDist, outputGeom); 229 | attributeAffects(pushRamp, outputGeom); 230 | attributeAffects(pushDirection, outputGeom); 231 | attributeAffects(center, outputGeom); 232 | attributeAffects(lookMaxDist, outputGeom); 233 | attributeAffects(lookVector, outputGeom); 234 | attributeAffects(lookDirection, outputGeom); 235 | attributeAffects(space, outputGeom); 236 | attributeAffects(weight, outputGeom); 237 | 238 | return stat; 239 | } 240 | 241 | MStatus intersectionDeformer::deform(MDataBlock &data, MItGeometry &iter, const MMatrix &mat, unsigned int multiIndex) { 242 | MStatus stat; 243 | 244 | //lets see if we need to do anything 245 | MDataHandle DataHandle = data.inputValue(envelope, &stat); 246 | float env = DataHandle.asFloat(); 247 | if (env == 0) 248 | return stat; 249 | DataHandle = data.inputValue(weight, &stat); 250 | const float weight = DataHandle.asFloat(); 251 | if (weight == 0) 252 | return stat; 253 | env = (env*weight); 254 | 255 | ///////////get user data 256 | short Space = data.inputValue(space, &stat).asShort(); 257 | short LookDirection = data.inputValue(lookDirection, &stat).asShort(); 258 | MVector LookVector = data.inputValue(lookVector, &stat).asDouble3(); 259 | float LookMaxDist = data.inputValue(lookMaxDist, &stat).asFloat(); 260 | MVector PushCenter = data.inputValue(center, &stat).asDouble3(); 261 | short PushDirection = data.inputValue(pushDirection, &stat).asShort(); 262 | float PushAboveDist = data.inputValue(pushAboveDist, &stat).asFloat(); 263 | float PushAboveAmount = data.inputValue(pushAboveAmount, &stat).asFloat(); 264 | float PushBelowDist = data.inputValue(pushBelowDist, &stat).asFloat(); 265 | float PushBelowAmount = data.inputValue(pushBelowAmount, &stat).asFloat(); 266 | float ThicknessDist = data.inputValue(thicknessDist, &stat).asFloat(); 267 | float ThicknessTol = data.inputValue(thicknessTol, &stat).asFloat(); 268 | 269 | //intersectionMesh 270 | MFnMesh IntMesh; 271 | DataHandle = data.inputValue(intersectionMesh, &stat); 272 | if (!stat) 273 | return Err(stat,"Can't get mesh to snap to"); 274 | MObject IntMeshObj = DataHandle.asMesh(); 275 | IntMesh.setObject(IntMeshObj); 276 | //MItMeshPolygon IntMeshIt(IntMeshObj); 277 | 278 | //maya curve shape 279 | MObject thisNode = this->thisMObject(); 280 | MFnDependencyNode fieldNode(thisNode); 281 | MPlug PushRampPlug = fieldNode.findPlug("pushRamp", &stat); 282 | MRampAttribute PushRamp(PushRampPlug, &stat); 283 | 284 | 285 | //get source object if needed for normal data 286 | MFnMesh sourceMesh; 287 | MFnNurbsSurface sourceNurbs; 288 | bool inMesh=true; 289 | if (LookDirection < 3 || PushDirection < 3 || ThicknessDist !=0) { 290 | MArrayDataHandle InputArrayData = data.inputValue(input, &stat); 291 | if (!stat) 292 | return Err(stat,"Can't get source for normal direction/thickness"); 293 | stat = InputArrayData.jumpToElement(multiIndex); 294 | if (!stat) 295 | return Err(stat,"Can't get source for normal direction/thickness"); 296 | MDataHandle InputData = InputArrayData.inputValue(); 297 | MDataHandle InputGeom = InputData.child(inputGeom); 298 | //check for mesh 299 | MObject tempObj = InputGeom.asMesh(); 300 | stat = sourceMesh.setObject(tempObj); 301 | if (!stat) 302 | { 303 | tempObj = InputGeom.asNurbsSurface(); 304 | stat = sourceNurbs.setObject(tempObj); 305 | if (!stat) 306 | return Err(stat,"Can't get source for normal direction/thickness"); 307 | else 308 | inMesh = false; 309 | } 310 | } 311 | 312 | 313 | //intersection vars 314 | MVector intersectionVec; 315 | MFloatVector intersectionVecF; 316 | MPoint startPointWS, startPointLS; 317 | MFloatPoint startPointWSF; 318 | MIntArray* nullIntArray = NULL; 319 | MFloatArray* nullArray = NULL; 320 | MFloatPointArray hitPoints; 321 | MFloatArray hitRayParams; 322 | 323 | 324 | /////////////////go 325 | iter.reset(); 326 | for ( ; !iter.isDone(); iter.next()) { 327 | //check for painted weights 328 | float currEnv = env * weightValue(data, multiIndex, iter.index()); 329 | 330 | if (currEnv !=0) { 331 | //get normal if needed 332 | MVector normalVec; 333 | if (LookDirection < 3 || PushDirection < 3 || ThicknessDist != 0) { 334 | if (inMesh) 335 | normalVec = getMeshNormal(sourceMesh, iter.index(), Space); 336 | else 337 | normalVec = getNurbsNormal(sourceNurbs, iter.index(), Space); 338 | } 339 | 340 | 341 | //get look direction 342 | MVector intersectionVec; 343 | switch (LookDirection) { 344 | case normalIn: 345 | intersectionVec = -normalVec; 346 | break; 347 | case normalOut: 348 | intersectionVec = normalVec; 349 | break; 350 | case vector: 351 | intersectionVec = LookVector; 352 | break; 353 | case fromPoint: 354 | intersectionVec = MVector(startPointWS - LookVector); 355 | break; 356 | case toPoint: 357 | intersectionVec = MVector(LookVector - startPointWS); 358 | break; 359 | } 360 | intersectionVec.normalize(); 361 | 362 | 363 | //get start point 364 | startPointLS = iter.position(); 365 | startPointWS = iter.position()*mat; 366 | 367 | //convert doubles to float for maya intersection call 368 | intersectionVecF = MFloatVector(intersectionVec); 369 | startPointWSF = MFloatPoint(startPointWS.x, startPointWS.y, startPointWS.z, startPointWS.w); 370 | 371 | //maya intersection check 372 | bool hit = IntMesh.allIntersections(startPointWSF, intersectionVecF, nullIntArray, nullIntArray, 373 | true, MSpace::kWorld, LookMaxDist, true, &accelParams, true, hitPoints, 374 | &hitRayParams, nullIntArray, nullIntArray, nullArray, nullArray, 0.01f); 375 | 376 | //if an intersection was found 377 | if (hit) { 378 | //MGlobal::displayInfo("found intersection"); 379 | float distToHit = hitRayParams[0]; 380 | MFloatPoint pointHit = hitPoints[0]; 381 | 382 | //if we hit or are within Tolerences 383 | float maxLook = max(0.0f, PushAboveDist); 384 | maxLook = max(maxLook, ThicknessDist); 385 | if (distToHit < maxLook) { 386 | //get push direction 387 | MVector pushVec; 388 | switch (PushDirection) { 389 | case normalIn: 390 | pushVec = -normalVec; 391 | break; 392 | case normalOut: 393 | pushVec = normalVec; 394 | break; 395 | case vector: 396 | pushVec = PushCenter; 397 | break; 398 | case fromPoint: 399 | pushVec = MVector(pointHit - PushCenter); 400 | break; 401 | case toPoint: 402 | pushVec = MVector(PushCenter - pointHit); 403 | break; 404 | } 405 | pushVec.normalize(); 406 | 407 | 408 | //if we have intersected (below) 409 | if (distToHit < 0.0f) { 410 | float distToHitCurr = min(-distToHit, PushBelowDist); 411 | float PushBelowDistCurr; 412 | 413 | //calc push amount 414 | if (PushRamp.getNumEntries() >1) { 415 | float rampPostion = ((distToHitCurr/PushBelowDist)*0.5f) + 0.5f; 416 | float rampValue; 417 | PushRamp.getValueAtPosition(rampPostion, rampValue, &stat); 418 | PushBelowDistCurr = rampValue; 419 | } else { 420 | PushBelowDistCurr = (distToHitCurr/PushBelowDist); 421 | } 422 | 423 | //calc the new point postion and run second intersection 424 | startPointWSF += (PushBelowDistCurr*PushBelowAmount)* pushVec ; 425 | hit = IntMesh.allIntersections(startPointWSF, intersectionVecF, nullIntArray, nullIntArray, 426 | true, MSpace::kWorld, LookMaxDist, true, &accelParams, true, hitPoints, 427 | &hitRayParams, nullIntArray, nullIntArray, nullArray, nullArray, 0.01f); 428 | 429 | 430 | if (hit) { 431 | MPoint outPoint(hitPoints[0]); 432 | 433 | //if thickness is on 434 | if (ThicknessDist !=0) 435 | outPoint = thickness(outPoint, normalVec, intersectionVecF, 1.0f, ThicknessDist, ThicknessTol); 436 | 437 | //calc out point 438 | outPoint = (outPoint * mat.inverse()); 439 | outPoint = (outPoint*currEnv) + (startPointLS *(1-currEnv)); 440 | iter.setPosition(outPoint); 441 | } 442 | } 443 | //PushAboveDist stuff here 444 | else if (distToHit < PushAboveDist) { 445 | float distToHitCurr = min(distToHit, PushAboveDist); 446 | float PushAboveDistCurr; 447 | 448 | //calc push amount 449 | if (PushRamp.getNumEntries() >1) { 450 | float rampPostion = (1-(distToHitCurr/PushAboveDist))/2; 451 | float rampValue; 452 | PushRamp.getValueAtPosition(rampPostion, rampValue, &stat); 453 | PushAboveDistCurr = rampValue; 454 | } else { 455 | PushAboveDistCurr = 1 -(distToHitCurr/PushAboveDist); 456 | } 457 | 458 | //calc the new point postion and run second intersection 459 | startPointWSF += (PushAboveDistCurr*PushAboveAmount)* pushVec ; 460 | hit = IntMesh.allIntersections(startPointWSF, intersectionVecF, nullIntArray, nullIntArray, 461 | true, MSpace::kWorld, LookMaxDist, true, &accelParams, true, hitPoints, 462 | &hitRayParams, nullIntArray, nullIntArray, nullArray, nullArray, 0.01f); 463 | 464 | 465 | if (hit) { 466 | MPoint outPoint(hitPoints[0]); 467 | 468 | 469 | //if thickness is on 470 | outPoint -= intersectionVecF*distToHit; 471 | if (ThicknessDist !=0 && distToHit < ThicknessDist) { 472 | float aboveDist = 1- (distToHit/ThicknessDist); 473 | outPoint = thickness(outPoint, normalVec, intersectionVecF, aboveDist, ThicknessDist, ThicknessTol); 474 | } 475 | 476 | //calc out point 477 | //outPoint -= intersectionVecF*distToHit; 478 | outPoint = (outPoint * mat.inverse()); 479 | outPoint = (outPoint*currEnv) + (startPointLS *(1-currEnv)); 480 | iter.setPosition(outPoint); 481 | } 482 | 483 | } 484 | 485 | 486 | 487 | //if hit is within thickness dist 488 | else if (distToHit < ThicknessDist) { 489 | float dist = ThicknessDist - distToHit;///ThicknessDist; 490 | float falloff = ThicknessDist/distToHit;///ThicknessDist; 491 | MPoint outPoint = thickness(startPointWS, normalVec, intersectionVecF, 1.0f, dist, ThicknessTol); 492 | 493 | //calc out point 494 | outPoint = (outPoint * mat.inverse()); 495 | outPoint = (outPoint*currEnv) + (startPointLS *(1-currEnv)); 496 | iter.setPosition(outPoint); 497 | } 498 | } 499 | } 500 | } 501 | } 502 | 503 | return stat; 504 | } -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer/intersectionDeformer.h: -------------------------------------------------------------------------------- 1 | // * header 2 | // File: intersectionDeformer.h 3 | 4 | #ifndef __INTYDEF__ 5 | #define __INTYDEF__ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | class intersectionDeformer: public MPxDeformerNode { 15 | public: 16 | intersectionDeformer() {}; 17 | 18 | virtual ~intersectionDeformer() {}; 19 | 20 | static void *creator(); 21 | 22 | static MStatus initialize(); 23 | 24 | virtual MStatus deform(MDataBlock &data, MItGeometry &iter, const MMatrix &mat, unsigned int multiIndex); 25 | 26 | static MTypeId id; 27 | static MObject weight; //env overide 28 | static MObject space; //world, local 29 | static MObject lookDirection; //normals, vector, from, to 30 | static MObject lookVector; //vector for lookDirection 31 | static MObject lookVectorX; 32 | static MObject lookVectorY; 33 | static MObject lookVectorZ; 34 | static MObject lookMaxDist; //float 35 | static MObject center; //vector 36 | static MObject centerX; 37 | static MObject centerY; 38 | static MObject centerZ; 39 | static MObject pushDirection; //normals, vector, from, to 40 | static MObject pushRamp; //maya curve shape 41 | static MObject pushAboveDist; //float 42 | static MObject pushAboveAmount; //float 43 | static MObject pushBelowDist; //float 44 | static MObject pushBelowAmount; //float 45 | static MObject thicknessDist; //float 46 | static MObject thicknessTol; //float 47 | static MObject intersectionMesh; //mesh 48 | static MMeshIsectAccelParams accelParams; //crazy maya stuff 49 | }; 50 | 51 | 52 | enum lookDir { 53 | normalOut = 0, 54 | normalIn, 55 | vector, 56 | fromPoint, 57 | toPoint 58 | }; 59 | 60 | inline MVector getMeshNormal(MFnMesh &mesh, int index, short space) { 61 | MVector result; 62 | if (space ==0) 63 | mesh.getVertexNormal(index, result, MSpace::kWorld); 64 | else 65 | mesh.getVertexNormal(index, result); 66 | return result; 67 | } 68 | 69 | inline MVector getNurbsNormal(MFnNurbsSurface &surf, int index, short space) { 70 | MVector result; 71 | 72 | //this process sucks 73 | double u,v; 74 | MPointArray cvs; 75 | surf.getCVs(cvs); 76 | surf.getParamAtPoint( cvs[index], u, v, true); 77 | if (space ==0) 78 | result = surf.normal(u,v, MSpace::kWorld); 79 | else 80 | result = surf.normal(u,v); 81 | 82 | return result; 83 | } 84 | 85 | inline MPoint thickness(MPoint point, MVector normal, MVector ray, float dist, float thick, float tol) { 86 | MPoint outPoint = point; 87 | 88 | double d = (ray * normal); 89 | 90 | if (d <= -tol) { 91 | outPoint = point+(-ray*(thick*dist)); 92 | } else if (d < tol) { 93 | double tolCurr(1 - (d+tol)/(tol*2)); 94 | outPoint = point+(-ray*(thick*dist*tolCurr)); 95 | } 96 | 97 | return outPoint; 98 | } 99 | 100 | 101 | #endif -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer/intersectionDeformer.suo.old: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidrichardnelson/maya/c0f2677a7ae73a2305d60db0041102f4e3558748/plug-ins/intersectionDeformer/intersectionDeformer.suo.old -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer/reg.cpp: -------------------------------------------------------------------------------- 1 | // * standard initialization procedures 2 | // File: reg.cpp 3 | 4 | ///register the node with maya 5 | 6 | #include 7 | #include "intersectionDeformer.h" 8 | 9 | MStatus initializePlugin( MObject obj ) { 10 | MString vendorStr( "" ); 11 | vendorStr += __DATE__; 12 | vendorStr += " @ "; 13 | vendorStr += __TIME__; 14 | 15 | MFnPlugin plugin( obj, vendorStr.asChar(), "beta", "Any"); 16 | MStatus result; 17 | result = plugin.registerNode( "intDeformer", intersectionDeformer::id, intersectionDeformer::creator, 18 | intersectionDeformer::initialize, MPxNode::kDeformerNode ); 19 | 20 | MGlobal:: displayInfo("intersectionDeformer plugin loaded (see script editor for details)."); 21 | MGlobal:: displayInfo( vendorStr.asChar() ); 22 | 23 | return result; 24 | } 25 | 26 | MStatus uninitializePlugin( MObject obj) { 27 | MStatus result; 28 | MFnPlugin plugin( obj ); 29 | result = plugin.deregisterNode( intersectionDeformer::id ); 30 | return result; 31 | } 32 | -------------------------------------------------------------------------------- /plug-ins/intersectionDeformer/testScene.mb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidrichardnelson/maya/c0f2677a7ae73a2305d60db0041102f4e3558748/plug-ins/intersectionDeformer/testScene.mb -------------------------------------------------------------------------------- /plug-ins/smDef.mll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidrichardnelson/maya/c0f2677a7ae73a2305d60db0041102f4e3558748/plug-ins/smDef.mll -------------------------------------------------------------------------------- /plug-ins/smDef/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * main.cpp 4 | * 5 | * standard initialization procedures 6 | * Created on: may 24, 2010 7 | * Author: katrin.schmid 8 | */ 9 | 10 | #include 11 | #include "smDef.h" 12 | 13 | 14 | MStatus initializePlugin( MObject obj ) 15 | { 16 | MStatus result; 17 | MFnPlugin plugin( obj, "www.lo-motion.de", "3.0", "Any"); 18 | result = plugin.registerNode( "smoothDeform", smoothDeformer::id, smoothDeformer::creator, 19 | smoothDeformer::initialize, MPxNode::kDeformerNode ); 20 | 21 | return result; 22 | } 23 | 24 | MStatus uninitializePlugin( MObject obj) 25 | { 26 | MStatus result; 27 | MFnPlugin plugin( obj ); 28 | result = plugin.deregisterNode( smoothDeformer::id ); 29 | 30 | return result; 31 | } -------------------------------------------------------------------------------- /plug-ins/smDef/smDef.h: -------------------------------------------------------------------------------- 1 | /* 2 | * smDef.h 3 | * 4 | * Created on: may 24, 2009 5 | * Author: katrin.schmid 6 | */ 7 | 8 | #ifndef smoothDeformer_H_ 9 | #define smoothDeformer_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | /*! \class smoothDeformer 16 | * \brief defines deformation node 17 | * 18 | */ 19 | class smoothDeformer : public MPxDeformerNode 20 | { 21 | public: 22 | smoothDeformer(); 23 | virtual ~smoothDeformer(); 24 | 25 | static void* creator(); 26 | static MStatus initialize(); 27 | // deformation function 28 | virtual MStatus deform(MDataBlock& block, 29 | MItGeometry& iter, 30 | const MMatrix& mat, 31 | unsigned int multiIndex); 32 | static MTypeId id; 33 | 34 | private: 35 | // node attributes 36 | static MObject aScale; 37 | static MObject aKeepBorder; 38 | static MObject aIterations; 39 | static MObject aUVMap; 40 | 41 | }; 42 | #endif -------------------------------------------------------------------------------- /plug-ins/smDef/smDefNode.cpp: -------------------------------------------------------------------------------- 1 | /** \defgroup Cellnoise 2 | * @file 3 | * @author katrin schmid 4 | * @version 0.2.0 5 | * 6 | * 7 | * @section DESCRIPTION 8 | * \brief 9 | * A smooth deformer that averages vertices based on a paintable vertex weights. 10 | * Option to keep border edges at position. 11 | * 12 | * To install: copy to maya bin\plugins directory or anywhere in plugin path 13 | * Create by "deformer -type smoothDeform" mel, paint bvetrex attributes in 14 | * Modify > Paint attributes tool. 15 | 16 | * 17 | * */ 18 | 19 | 20 | #ifdef debug 21 | #undef debug 22 | #endif 23 | //#define debug 24 | 25 | 26 | #define MAKE_INPUT(attr) \ 27 | CHECK_MSTATUS( attr.setKeyable(true) ); \ 28 | CHECK_MSTATUS( attr.setStorable(true) ); \ 29 | CHECK_MSTATUS( attr.setReadable(true) ); \ 30 | CHECK_MSTATUS( attr.setWritable(true) ); 31 | 32 | 33 | #define McheckErr(stat,msg) \ 34 | if ( MS::kSuccess != stat ) { \ 35 | cerr << msg; \ 36 | return MS::kFailure; \ 37 | } 38 | 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | 64 | #include 65 | #include 66 | 67 | #include "smDef.h" 68 | 69 | MTypeId smoothDeformer::id( 0x8123c ); 70 | MObject smoothDeformer::aScale; 71 | MObject smoothDeformer::aIterations; 72 | MObject smoothDeformer::aKeepBorder; 73 | 74 | void getAverageVector(std::vector directionVectors, int neighboursSize, float &avX, float &avY, float &avZ) 75 | { 76 | avX = avY =avZ=0.f;// Todo: make this a vector 77 | for (int y=0; y< directionVectors.size(); y++) 78 | { 79 | avX += directionVectors[y].x; 80 | avY += directionVectors[y].y; 81 | avZ += directionVectors[y].z; 82 | } 83 | 84 | avX = avX / float (neighboursSize); 85 | avY = avY / float (neighboursSize); 86 | avZ = avZ / float (neighboursSize); 87 | } 88 | 89 | 90 | smoothDeformer::smoothDeformer() 91 | {} 92 | 93 | smoothDeformer::~smoothDeformer() 94 | {} 95 | 96 | void* smoothDeformer::creator() 97 | { 98 | return new smoothDeformer(); 99 | } 100 | 101 | 102 | MStatus smoothDeformer::initialize() 103 | { 104 | MFnNumericAttribute nAttr; 105 | aScale=nAttr.create( "scale", "sc", MFnNumericData::kDouble ); 106 | nAttr.setDefault(1.); 107 | nAttr.setMin(-10.0), 108 | nAttr.setMax(10.0), 109 | nAttr.setKeyable(true); 110 | addAttribute( aScale); 111 | 112 | aIterations=nAttr.create( "smoothIterations", "its", MFnNumericData::kInt ); 113 | MAKE_INPUT(nAttr); 114 | nAttr.setDefault(0); 115 | nAttr.setKeyable(true); 116 | addAttribute( aIterations); 117 | 118 | aKeepBorder=nAttr.create( "keepBorders", "kbe", MFnNumericData::kBoolean, true); 119 | MAKE_INPUT(nAttr); 120 | nAttr.setDefault(1); 121 | nAttr.setKeyable(true); 122 | addAttribute( aKeepBorder); 123 | 124 | attributeAffects( smoothDeformer::aKeepBorder, smoothDeformer::outputGeom ); 125 | attributeAffects( smoothDeformer::aScale, smoothDeformer::outputGeom ); 126 | attributeAffects( smoothDeformer::aIterations, smoothDeformer::outputGeom); 127 | 128 | MGlobal::executeCommand( "makePaintable -attrType multiFloat -sm deformer smoothDeform weights;" ); 129 | 130 | return MS::kSuccess; 131 | } 132 | 133 | // Description: Deform the point with a smoothDeformer algorithm 134 | // iter : an iterator for the geometry to be deformed 135 | // m : matrix to transform the point into world space 136 | // multiIndex : the index of the geometry that we are deformin 137 | MStatus smoothDeformer::deform( MDataBlock& block, MItGeometry& iter, const MMatrix& m, unsigned int multiIndex) 138 | { 139 | MStatus status = MS::kSuccess; 140 | 141 | MObject node = this->thisMObject(); 142 | 143 | float vLength, defMulti, w, moveToX, moveToY, moveToZ, minLength = 1316134912; 144 | float avLength, avX, avY,avZ, maxLength =0; 145 | MVector pos, diffVec; 146 | MPoint condPointPos, objPos; 147 | MPointArray pointArray, outPoints; 148 | MIntArray condPoints; 149 | std::vector directionVectors; 150 | std::vector vWeights; 151 | MObject geoData; 152 | 153 | MDataHandle envData = block.inputValue(envelope,&status); 154 | McheckErr(status, "Error getting envelope data handle\n"); 155 | 156 | MPlug ip_plug(node, aScale); 157 | float scaleV = ip_plug.asFloat(); 158 | MPlug kb_plug(node, aKeepBorder); 159 | bool keepBorder = kb_plug.asBool(); 160 | 161 | MFnDependencyNode fnDependNode( node ); 162 | // Assign the '.inMesh' tPlug from the mesh node. 163 | MPlug inMeshPlug = fnDependNode.findPlug( "outputGeometry" );//arrayPlug 164 | MPlug it_plug(node, aIterations); 165 | int smoothIterations=it_plug.asInt(); 166 | 167 | // Get the envelope and blend weight 168 | float env = block.inputValue( envelope ).asFloat(); 169 | 170 | MArrayDataHandle cpHandle= block.outputArrayValue(inMeshPlug); 171 | cpHandle.jumpToElement(multiIndex); 172 | MDataHandle pntHandle = cpHandle.outputValue(); 173 | geoData=pntHandle.data(); 174 | if (geoData.isNull()) 175 | return status; 176 | 177 | MItMeshPolygon mMeshPolygon(geoData, &status); 178 | MFnDependencyNode fnDep (geoData); 179 | MFnMesh meshFn(geoData); 180 | MItMeshVertex iterMesh(geoData) ;//! Mesh iterator, over origMeshData 181 | 182 | if (env > 0) 183 | { 184 | int pointCount=iterMesh.count(); 185 | for (int z=0 ; z < smoothIterations ; z++ ) 186 | { 187 | meshFn.getPoints (pointArray, MSpace::kObject); 188 | iterMesh.reset(); 189 | 190 | // loop points 191 | for (int g=0 ; g < pointCount; g++ ) 192 | { 193 | objPos = pointArray[g]; 194 | //objPos = iterMesh.position(MSpace::kObject); 195 | if (z==0) 196 | { 197 | if (keepBorder==1 && iterMesh.onBoundary(&status)==1) 198 | w=0.0; 199 | else 200 | w = (weightValue( block, multiIndex, g))*env; 201 | 202 | vWeights.push_back(w); 203 | #ifdef debug 204 | std::cout < maxLength ) 234 | maxLength = vLength; 235 | } 236 | 237 | getAverageVector(directionVectors, condPoints.length(), avX, avY, avZ); 238 | // get average length 239 | avLength = float (avLength) / float (condPoints.length()); 240 | 241 | if (scaleV <= 0) 242 | { 243 | defMulti = minLength + (avLength - minLength); 244 | if (defMulti != 0) 245 | defMulti = scaleV*w/10 *defMulti / avLength; 246 | } 247 | else if (scaleV > 0) 248 | { 249 | defMulti = avLength + ( maxLength - avLength ); 250 | if (defMulti != 0) 251 | defMulti = scaleV*w/10 * defMulti/avLength; 252 | } 253 | #ifdef debug 254 | std::cout << defMulti << " : "<= smoothIterations-1) 268 | status=iter.setAllPositions(outPoints, MSpace::kObject); 269 | pointArray.clear(); 270 | outPoints.clear(); 271 | } 272 | }//iterations 273 | } 274 | 275 | return status; 276 | } -------------------------------------------------------------------------------- /plug-ins/snapDeformer.mll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidrichardnelson/maya/c0f2677a7ae73a2305d60db0041102f4e3558748/plug-ins/snapDeformer.mll -------------------------------------------------------------------------------- /plug-ins/snapDeformer/reg.cpp: -------------------------------------------------------------------------------- 1 | //register the node with maya 2 | 3 | #include 4 | #include "snapMeshDeformer.h" 5 | #include "snapMeshCmd.h" 6 | 7 | MStatus initializePlugin( MObject obj ) { 8 | 9 | MString vendorStr( "" ); 10 | vendorStr += __DATE__; 11 | vendorStr += " @ "; 12 | vendorStr += __TIME__; 13 | 14 | MFnPlugin plugin( obj, vendorStr.asChar(), "1.0", "Any"); 15 | MStatus result; 16 | result = plugin.registerNode( "snapMeshDeformer", snapDeformer::id, snapDeformer::creator, 17 | snapDeformer::initialize, MPxNode::kDeformerNode ); 18 | 19 | if (result)result = plugin.registerCommand("snapMeshCmd", snapMeshCmd::creator); 20 | 21 | MGlobal:: displayInfo("snapMeshCmd -s source -t target -max 1"); 22 | MGlobal:: displayInfo("snapDeformer plugin loaded (see script editor for details)."); 23 | MGlobal:: displayInfo( vendorStr.asChar() ); 24 | 25 | return result; 26 | } 27 | 28 | MStatus uninitializePlugin( MObject obj) { 29 | MStatus result; 30 | MFnPlugin plugin( obj ); 31 | result = plugin.deregisterNode( snapDeformer::id ); 32 | if (result)result = plugin.deregisterCommand("snapMeshCmd"); 33 | return result; 34 | } 35 | -------------------------------------------------------------------------------- /plug-ins/snapDeformer/snapMeshCmd.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "snapMeshCmd.h" 10 | 11 | void* snapMeshCmd::creator() { 12 | return new snapMeshCmd; 13 | } 14 | 15 | bool snapMeshCmd::isUndoable() const { 16 | return true; 17 | } 18 | 19 | MStatus snapMeshCmd::doIt(const MArgList& args) { 20 | Args = args; 21 | return redoIt(); 22 | } 23 | 24 | MStatus snapMeshCmd::redoIt() { 25 | MStatus stat; 26 | const MArgList args = Args; 27 | //get source 28 | int pos = getArgPosition(args, "-s"); 29 | if (pos == -1) 30 | return Usage(MStatus::kInvalidParameter); 31 | 32 | MSelectionList list; 33 | MDagPath source, target; 34 | MObject tempObject; 35 | list.add(args.asString(pos+1)); 36 | stat = list.getDagPath(0,source,tempObject); 37 | if (!stat) 38 | return Err(stat, "can't get source object"); 39 | 40 | //get target 41 | pos = getArgPosition(args, "-t"); 42 | if (pos == -1) 43 | MGlobal::getActiveSelectionList(list); 44 | else 45 | { 46 | list.clear(); 47 | list.add(args.asString(pos+1)); 48 | stat = list.getDagPath(0,target,tempObject); 49 | if (!stat) 50 | return Err(stat, "can't get target object"); 51 | } 52 | 53 | 54 | //max dist 55 | float maxDist = 1; 56 | pos = getArgPosition(args, "-max"); 57 | if (pos != -1) 58 | maxDist = float(args.asDouble(pos+1)); 59 | 60 | newDeformer = createSnapMesh(source,target,maxDist, &stat); 61 | return stat; 62 | } 63 | 64 | MStatus snapMeshCmd::undoIt() { 65 | MStatus stat; 66 | MGlobal::deleteNode(newDeformer); 67 | return stat; 68 | } 69 | 70 | MObject snapMeshCmd::createSnapMesh(const MDagPath &source, 71 | const MDagPath &target, 72 | const float maxDist, MStatus *stat) { 73 | //get soure mesh and create tree 74 | MObject deformer; 75 | MFnMesh sourceMesh(source); 76 | MPointArray sourcePoints; 77 | sourceMesh.getPoints(sourcePoints, MSpace::kWorld); 78 | KdTree_map sourceKd = KdFromPointArray(sourcePoints); 79 | 80 | 81 | //get target mesh and compair to kd tree 82 | MPointArray targetPoints; 83 | MFnMesh targetMesh(target); 84 | targetMesh.getPoints(targetPoints, MSpace::kWorld); 85 | MIntArray indexResults; 86 | 87 | KdTree* results; 88 | for (unsigned int i=0; i< targetPoints.length(); i++) { 89 | float pos[3] = {float(targetPoints[i].x), float(targetPoints[i].y), float(targetPoints[i].z)}; 90 | results = new KdTree[20]; 91 | //MGlobal::displayInfo("making intersection"); 92 | int pointsFound = sourceKd.closestPoints(results, pos, maxDist, 19); 93 | //MGlobal::displayInfo("made intersection"); 94 | if (pointsFound>0) 95 | indexResults.append(*results[0].Info()); 96 | else 97 | indexResults.append(-1); 98 | } 99 | 100 | delete[] results; 101 | 102 | //create deformer 103 | MStringArray resultString; 104 | MGlobal::selectByName(targetMesh.name(), MGlobal::kReplaceList); 105 | MGlobal::executeCommand("deformer -type snapMeshDeformer -name snapMeshDeformer", resultString); 106 | MSelectionList list; 107 | list.add(resultString[0]); 108 | list.getDependNode(0,deformer); 109 | MFnDependencyNode nodeDep(deformer); 110 | MDGModifier dgModifier; 111 | 112 | 113 | //connect souce to deformer 114 | MPlug snapMeshP = nodeDep.findPlug("snapMesh"); 115 | MFnDependencyNode meshDep(sourceMesh.object()); 116 | MPlug sourceMeshP = meshDep.findPlug("worldMesh"); 117 | MStatus statA; 118 | MPlug sourceMeshPA = sourceMeshP.elementByPhysicalIndex(0, &statA); 119 | sourceMeshP.selectAncestorLogicalIndex(0,sourceMeshP.attribute()); 120 | if (statA) 121 | dgModifier.connect(sourceMeshPA, snapMeshP); 122 | else 123 | dgModifier.connect(sourceMeshP, snapMeshP); 124 | dgModifier.doIt(); 125 | //write data to deformer 126 | MPlug pointsP = nodeDep.findPlug("pointList"); 127 | MFnIntArrayData intArrayData; 128 | MObject intArrayObject = intArrayData.create(indexResults); 129 | pointsP.setValue(intArrayObject); 130 | 131 | for (unsigned int i=0; i < indexResults.length(); i++) { 132 | pointsP.selectAncestorLogicalIndex(i,pointsP.attribute()); 133 | pointsP.setValue(indexResults[i]); 134 | } 135 | 136 | 137 | return deformer; 138 | } 139 | -------------------------------------------------------------------------------- /plug-ins/snapDeformer/snapMeshCmd.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // MAIN CLASS DECLARATION FOR THE MEL COMMAND: 7 | class snapMeshCmd : public MPxCommand { 8 | public: 9 | snapMeshCmd(){}; 10 | virtual ~snapMeshCmd() {}; 11 | static void* creator(); 12 | bool isUndoable() const; 13 | MStatus doIt(const MArgList&); 14 | MStatus redoIt( ); 15 | MStatus undoIt( ); 16 | MObject createSnapMesh(const MDagPath &source, 17 | const MDagPath &target, 18 | float maxDist, MStatus *stat); 19 | private: 20 | MObject newDeformer; 21 | MArgList Args; 22 | 23 | }; 24 | 25 | 26 | inline MStatus Usage(MStatus status) { 27 | MGlobal::displayInfo("usage: snapMeshCmd -s source -t target -max 1"); 28 | return status; 29 | } 30 | -------------------------------------------------------------------------------- /plug-ins/snapDeformer/snapMeshDeformer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "snapMeshDeformer.h" 12 | 13 | MTypeId snapDeformer::id( 0x8000e ); 14 | MObject snapDeformer::weight; 15 | MObject snapDeformer::space; 16 | MObject snapDeformer::spaceSource; 17 | MObject snapDeformer::pointList; 18 | MObject snapDeformer::snapMesh; 19 | 20 | void *snapDeformer::creator() { 21 | return new snapDeformer; 22 | } 23 | 24 | MStatus snapDeformer::initialize() { 25 | MStatus stat; 26 | 27 | MFnNumericAttribute FnNumeric; 28 | MFnNumericAttribute FnNumericA; 29 | MFnTypedAttribute FnTyped; 30 | MFnEnumAttribute FnEnum; 31 | 32 | //weight 33 | weight = FnNumeric.create("weight", "we", MFnNumericData::kFloat); 34 | FnNumeric.setKeyable(true); 35 | FnNumeric.setStorable(true); 36 | FnNumeric.setReadable(true); 37 | FnNumeric.setWritable(true); 38 | FnNumeric.setDefault( 1.0 ); 39 | addAttribute( weight ); 40 | 41 | 42 | ///space target 43 | space = FnEnum.create("space", "sp", 0); 44 | FnEnum.addField("world",0); 45 | FnEnum.addField("object",1); 46 | FnEnum.setStorable(true); 47 | FnEnum.setKeyable(true); 48 | addAttribute(space); 49 | 50 | ///space source 51 | spaceSource = FnEnum.create("spaceSource", "sps", 0); 52 | FnEnum.addField("world",0); 53 | FnEnum.addField("object",1); 54 | FnEnum.setStorable(true); 55 | FnEnum.setKeyable(true); 56 | addAttribute(spaceSource); 57 | 58 | 59 | //pointlist 60 | pointList = FnNumericA.create("pointList", "pl", MFnNumericData::kInt); 61 | FnNumericA.setArray( true ); 62 | FnNumericA.setKeyable(false); 63 | FnNumericA.setStorable(true); 64 | FnNumericA.setReadable(true); 65 | FnNumericA.setWritable(true); 66 | FnNumericA.setIndexMatters(true); 67 | addAttribute( pointList ); 68 | 69 | 70 | //snapMesh 71 | snapMesh = FnTyped.create("snapMesh", "sm", MFnData::kMesh); 72 | FnTyped.setArray( false ); 73 | FnTyped.setReadable(true); 74 | FnTyped.setWritable(true); 75 | addAttribute( snapMesh ); 76 | 77 | 78 | 79 | attributeAffects(snapMesh, outputGeom); 80 | attributeAffects(pointList, outputGeom); 81 | attributeAffects(space, outputGeom); 82 | attributeAffects(spaceSource, outputGeom); 83 | attributeAffects(weight, outputGeom); 84 | 85 | return stat; 86 | } 87 | 88 | MStatus snapDeformer::deform(MDataBlock &data, MItGeometry &iter, const MMatrix &mat, unsigned int multiIndex) { 89 | MStatus stat; 90 | 91 | 92 | //lets see if we need to do anything 93 | MDataHandle DataHandle = data.inputValue(envelope, &stat); 94 | float env = DataHandle.asFloat(); 95 | if (env == 0) 96 | return stat; 97 | DataHandle = data.inputValue(weight, &stat); 98 | const float weight = DataHandle.asFloat(); 99 | if (weight == 0) 100 | return stat; 101 | 102 | env = (env*weight); 103 | 104 | 105 | //space target 106 | DataHandle = data.inputValue(space, &stat); 107 | int SpaceInt = DataHandle.asInt(); 108 | 109 | //space source 110 | DataHandle = data.inputValue(spaceSource, &stat); 111 | int SpaceSourceInt = DataHandle.asInt(); 112 | 113 | //pointlist 114 | MArrayDataHandle pointArrayHandle = data.inputArrayValue(pointList); 115 | 116 | 117 | //snapMesh 118 | MFnMesh SnapMesh; 119 | DataHandle = data.inputValue(snapMesh, &stat); 120 | if (!stat) 121 | return Err(stat,"Can't get mesh to snap to"); 122 | MObject SnapMeshObj = DataHandle.asMesh(); 123 | SnapMesh.setObject(SnapMeshObj); 124 | MPointArray snapPoints; 125 | if (SpaceSourceInt==0) 126 | SnapMesh.getPoints(snapPoints, MSpace::kWorld); 127 | else 128 | SnapMesh.getPoints(snapPoints, MSpace::kObject); 129 | 130 | 131 | 132 | iter.reset(); 133 | for ( ; !iter.isDone(); iter.next()) { 134 | //check for painted weights 135 | float currEnv = env * weightValue(data, multiIndex, iter.index()); 136 | 137 | //get point to snap to 138 | unsigned int index; 139 | stat = pointArrayHandle.jumpToElement(iter.index()); 140 | if (!stat) 141 | index = 0; 142 | else { 143 | DataHandle = pointArrayHandle.outputValue(); 144 | index = DataHandle.asInt(); 145 | } 146 | 147 | if (index != -1) { 148 | //calc point location 149 | MPoint currPoint; 150 | if (snapPoints.length() > index) 151 | currPoint = snapPoints[index]; 152 | 153 | if (SpaceInt == 0) 154 | currPoint *= mat.inverse(); 155 | 156 | if (currEnv !=1) 157 | { 158 | MPoint p = (currPoint- iter.position()); 159 | currPoint = iter.position() + (p*currEnv); 160 | } 161 | 162 | 163 | //set point location 164 | iter.setPosition(currPoint); 165 | } 166 | 167 | 168 | } 169 | 170 | return stat; 171 | } -------------------------------------------------------------------------------- /plug-ins/snapDeformer/snapMeshDeformer.h: -------------------------------------------------------------------------------- 1 | #ifndef __SNAPPYDEF__ 2 | #define __SNAPPYDEF__ 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | class snapDeformer: public MPxDeformerNode { 9 | public: 10 | snapDeformer() {}; 11 | 12 | virtual ~snapDeformer() {}; 13 | static void *creator(); 14 | static MStatus initialize(); 15 | virtual MStatus deform(MDataBlock &data, MItGeometry &iter, const MMatrix &mat, unsigned int multiIndex); 16 | 17 | static MTypeId id; 18 | static MObject weight; 19 | static MObject space; 20 | static MObject spaceSource; 21 | static MObject pointList; 22 | static MObject snapMesh; 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /scripts/AEintDeformerTemplate.mel: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | global proc AEintDeformerTemplate ( string $nodeName ) 5 | { 6 | 7 | editorTemplate -beginScrollLayout; 8 | 9 | AEaddRampControl ($nodeName+".pushRamp"); 10 | editorTemplate -addControl "envelope"; 11 | editorTemplate -addControl "weight"; 12 | editorTemplate -addControl "lookMaxDist"; 13 | //editorTemplate -addControl "space"; 14 | editorTemplate -addSeparator; 15 | editorTemplate -addControl "lookDirection"; 16 | editorTemplate -addControl "lookVector"; 17 | editorTemplate -addSeparator; 18 | editorTemplate -addControl "pushDirection"; 19 | editorTemplate -addControl "center"; 20 | editorTemplate -addSeparator; 21 | editorTemplate -addControl "pushAboveDist"; 22 | editorTemplate -addControl "pushAboveAmount"; 23 | editorTemplate -addControl "pushBelowDist"; 24 | editorTemplate -addControl "pushBelowAmount"; 25 | editorTemplate -addControl "thicknessDist"; 26 | editorTemplate -addControl "thicknessTol"; 27 | editorTemplate -addSeparator; 28 | editorTemplate -addExtraControls; 29 | 30 | editorTemplate -endScrollLayout; 31 | } 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /scripts/AlignNormals.py: -------------------------------------------------------------------------------- 1 | __author__ = 's.sherbakov' 2 | 3 | """ 4 | Serge Scherbakov 5 | realismus@gmail.com 6 | www.serge-scherbakov.com 7 | ______________________________________________________________________________ 8 | 9 | AlignNormals.py - Snap vertices and Align Normals. 10 | ______________________________________________________________________________ 11 | 12 | How to install: 13 | - save script into your maya script directory 14 | - open Script Editor and switch to Python tab in Maya 15 | - write two following strings: 16 | import AlignNormals 17 | AlignNormals.main() 18 | 19 | ______________________________________________________________________________ 20 | 21 | How to use: 22 | - select Group of vertices on the first mesh and press "Ref" button 23 | - select vertices to adjust 24 | - press "Snap" to snap vertices to the nearest reference 25 | - press "AR" to align normals at selected vertices with normals at the nearest reference 26 | - press "AA" to set both normals (selected and the nearest reference) to calculated average value 27 | 28 | ______________________________________________________________________________ 29 | 30 | """ 31 | 32 | import maya.cmds as cmds 33 | import maya.OpenMaya as om 34 | import math 35 | 36 | 37 | class UI(): 38 | def __init__(self): 39 | self.aligner = VertexAligner() 40 | self.__initUI__() 41 | 42 | def __initUI__(self): 43 | if cmds.window("alignNormalWin", exists=True): cmds.deleteUI("alignNormalWin", window=True) 44 | cmds.window("alignNormalWin", title="Normal Tools", minimizeButton=False, maximizeButton=False, sizeable=False) 45 | cmds.rowLayout(numberOfColumns=2, rowAttach=(1, "both", 0), 46 | columnAttach=((1, "both", 0), (2, "both", 0))) 47 | self.refBtn = cmds.button(label="Ref\n0", width=60, height=70, c=lambda x: self.setRefVers()) 48 | cmds.setParent("..") 49 | cmds.columnLayout(columnAttach=('both', 0), rowSpacing=3, columnWidth=45) 50 | cmds.button(label="Snap", height=35, c=lambda x: self.snapToRef()) 51 | cmds.button(label="AR", height=35, c=lambda x: self.alignWithRef()) 52 | cmds.button(label="AA", height=35, c=lambda x: self.alignAverage()) 53 | cmds.showWindow("alignNormalWin") 54 | 55 | 56 | def setRefVers(self): 57 | verts = self.getSelectedVerts() 58 | if not verts: 59 | self.aligner.refVerts = [] 60 | cmds.button(self.refBtn, edit=True, label="Ref\n0") 61 | else: 62 | self.aligner.refVerts = verts 63 | cmds.button(self.refBtn, edit=True, 64 | label="Ref\n" + str(len(self.aligner.refVerts))) 65 | 66 | def getSelectedVerts(self): 67 | selection = cmds.ls(sl=True, long=True) 68 | if not selection: 69 | return None 70 | else: 71 | cmds.select(cmds.polyListComponentConversion(toVertex=True), replace=True) 72 | verts = cmds.filterExpand(sm=31, expand=True, fullPath=True) 73 | cmds.select(selection, replace=True) 74 | return verts 75 | 76 | def snapToRef(self): 77 | verts = self.getSelectedVerts() 78 | if verts: 79 | self.aligner.snapToRef(verts) 80 | 81 | def alignWithRef(self): 82 | selection = cmds.ls(sl=True, long=True) 83 | if not selection: 84 | cmds.error("Select Edges or Verts to align.") 85 | self.aligner.alignToRef() 86 | 87 | def alignAverage(self): 88 | selection = cmds.ls(sl=True, long=True) 89 | if not selection: 90 | cmds.error("Select Edges or Verts to align.") 91 | self.aligner.alignAverage() 92 | 93 | 94 | class VertexAligner(): 95 | def __init__(self): 96 | self.refVerts = None 97 | 98 | def findNearestVertIndex(self, vert): 99 | vertAT = cmds.xform(vert, q=True, ws=True, t=True) 100 | indexOfMin = 0 101 | minLen = float("inf") 102 | for index in range(len(self.refVerts)): 103 | vertBT = cmds.xform(self.refVerts[index], q=True, ws=True, t=True) 104 | vlen = math.sqrt(math.pow((vertAT[0] - vertBT[0]), 2) + 105 | math.pow((vertAT[1] - vertBT[1]), 2) + 106 | math.pow((vertAT[2] - vertBT[2]), 2)) 107 | if vlen < minLen: 108 | minLen = vlen 109 | indexOfMin = index 110 | return indexOfMin 111 | 112 | def snapToRef(self, verts): 113 | print "snaping", verts 114 | if len(self.refVerts) == 0: 115 | cmds.error("Set reference vertices and try again.") 116 | 117 | selection = cmds.ls(sl=True, long=True) 118 | if not selection: cmds.error("Select Edges or Vertices to snap and try again.") 119 | cmds.select(cmds.polyListComponentConversion(toVertex=True), replace=True) 120 | verts = cmds.filterExpand(sm=31, expand=True, fullPath=True) 121 | for vert in verts: 122 | index = self.findNearestVertIndex(vert) 123 | refVertTransforms = cmds.xform(self.refVerts[index], q=True, ws=True, t=True) 124 | cmds.xform(vert, ws=True, t=refVertTransforms) 125 | 126 | cmds.select(selection, r=True) 127 | 128 | def alignToRef(self): 129 | if len(self.refVerts) == 0: 130 | cmds.error("Reference vertexes are not defined. Please define ref first.") 131 | selection = cmds.ls(sl=True, long=True) 132 | cmds.select(cmds.polyListComponentConversion(toVertex=True), replace=True) 133 | verts = cmds.filterExpand(sm=31, expand=True, fullPath=True) 134 | 135 | shape = str(self.refVerts[0]).split(".")[0] 136 | refTransform = cmds.listRelatives(shape, parent=True, path=True, fullPath=True)[0] 137 | 138 | shape = str(verts[0]).split(".")[0] 139 | objTransform = cmds.listRelatives(shape, parent=True, path=True, fullPath=True)[0] 140 | objTransformMatrixInverse = getTransformMatrix(objTransform).inverse() 141 | 142 | refRot = cmds.xform(refTransform, q=True, ws=True, ro=True) 143 | refAngle = om.MEulerRotation(math.radians(refRot[0]), 144 | math.radians(refRot[1]), 145 | math.radians(refRot[2]), 146 | om.MEulerRotation.kXYZ) 147 | for vert in verts: 148 | refVertIndex = self.findNearestVertIndex(vert) 149 | refNormal = cmds.polyNormalPerVertex(self.refVerts[refVertIndex], q=True, xyz=True) 150 | 151 | vec = om.MVector(refNormal[0], refNormal[1], refNormal[2]) 152 | refNormal = vec.rotateBy(refAngle) 153 | normalVector = om.MVector(refNormal[0], refNormal[1], refNormal[2]) 154 | newVector = normalVector * objTransformMatrixInverse 155 | # Assuming normals are equal for all triangles at this vert, and using the first triple. 156 | cmds.polyNormalPerVertex(vert, xyz=(newVector[0], newVector[1], newVector[2])) 157 | cmds.select(selection, r=True) 158 | 159 | def alignAverage(self): 160 | if len(self.refVerts) == 0: 161 | cmds.error("Reference vertexes are not defined. Please define ref first.") 162 | selection = cmds.ls(sl=True, long=True) 163 | cmds.select(cmds.polyListComponentConversion(toVertex=True), replace=True) 164 | verts = cmds.filterExpand(sm=31, expand=True, fullPath=True) 165 | 166 | shape = str(self.refVerts[0]).split(".")[0] 167 | obj1Transform = cmds.listRelatives(shape, parent=True, path=True, fullPath=True)[0] 168 | n1Rot = cmds.xform(obj1Transform, q=True, ws=True, ro=True) 169 | n1Angle = om.MEulerRotation(math.radians(n1Rot[0]), 170 | math.radians(n1Rot[1]), 171 | math.radians(n1Rot[2]), 172 | om.MEulerRotation.kXYZ) 173 | 174 | shape = str(verts[0]).split(".")[0] 175 | obj2Transform = cmds.listRelatives(shape, parent=True, path=True, fullPath=True)[0] 176 | n2Rot = cmds.xform(obj2Transform, q=True, ws=True, ro=True) 177 | n2Angle = om.MEulerRotation(math.radians(n2Rot[0]), 178 | math.radians(n2Rot[1]), 179 | math.radians(n2Rot[2]), 180 | om.MEulerRotation.kXYZ) 181 | 182 | for vert in verts: 183 | refIndex = self.findNearestVertIndex(vert) 184 | vecData = cmds.polyNormalPerVertex(self.refVerts[refIndex], q=True, xyz=True) 185 | vec1 = om.MVector(vecData[0], vecData[1], vecData[2]) 186 | vec1 = vec1.rotateBy(n1Angle) 187 | 188 | vecData = cmds.polyNormalPerVertex(vert, q=True, xyz=True) 189 | vec2 = om.MVector(vecData[0], vecData[1], vecData[2]) 190 | vec2 = vec2.rotateBy(n2Angle) 191 | 192 | averageNormal = (vec1 + vec2) / 2.0 193 | 194 | n1New = averageNormal * getTransformMatrix(obj1Transform).inverse() 195 | cmds.polyNormalPerVertex(self.refVerts[refIndex], xyz=(n1New.x, n1New.y, n1New.z)) 196 | 197 | n2New = averageNormal * getTransformMatrix(obj2Transform).inverse() 198 | cmds.polyNormalPerVertex(vert, xyz=(n2New.x, n2New.y, n2New.z)) 199 | 200 | cmds.select(selection, r=True) 201 | 202 | 203 | def getTransformMatrix(obj): 204 | data = cmds.xform(obj, m=True, q=True, ws=True) 205 | matrix = om.MMatrix() 206 | for i in range(len(data)): 207 | om.MScriptUtil.setDoubleArray(matrix[i / 4], i - 4 * (i / 4), data[i]) 208 | return matrix 209 | 210 | 211 | def main(): 212 | ui = UI() -------------------------------------------------------------------------------- /scripts/alignVerts.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as mc 2 | import numpy as np 3 | import maya.OpenMaya as om 4 | 5 | def distance(p, q, r): 6 | p = np.array(p) 7 | q = np.array(q) 8 | r = np.array(r) 9 | x = p-q 10 | return np.dot(r-q, x)/np.dot(x, x) 11 | 12 | def line_param(p, q, r): 13 | p = np.array(p) 14 | q = np.array(q) 15 | r = np.array(r) 16 | return np.linalg.norm(distance(p, q, r)*(p-q)+q-r) 17 | 18 | def point(p, q, r): 19 | p1=np.array(p) 20 | p2=np.array(q) 21 | p3=np.array(r) 22 | d=np.cross(p2-p1,p3-p1)/np.linalg.norm(p2-p1) 23 | return d 24 | 25 | def intermediates(p1, p2, nb_points=3): 26 | """"Return a list of nb_points equally spaced points 27 | between p1 and p2""" 28 | # If we have 8 intermediate points, we have 8+1=9 spaces 29 | # between p1 and p2 30 | x_spacing = (p2[0] - p1[0]) / (nb_points + 1) 31 | y_spacing = (p2[1] - p1[1]) / (nb_points + 1) 32 | 33 | return [[p1[0] + i * x_spacing, p1[1] + i * y_spacing] for i in range(1, nb_points+1)] 34 | #print(intermediates([1, 2], [10, 6.5], nb_points=8)) 35 | 36 | def curve(a, b): 37 | return mc.curve(d=1, p=(a,b)) 38 | #npoc = mc.createNode('nearestPointOnCurve') 39 | #mc.connectAttr(c+'.create', npoc+'.inputCurve', f=True) 40 | #xf = mc.createNode('transform') 41 | #mc.connectAttr(xf+'.t', npoc+'.inPosition', f=True) 42 | 43 | def closestPointOnCurve(location, curveObject): 44 | 45 | curve = curveObject 46 | 47 | # put curve into the MObject 48 | tempList = om.MSelectionList() 49 | tempList.add(curve) 50 | curveObj = om.MObject() 51 | tempList.getDependNode(0, curveObj) # puts the 0 index of tempList's depend node into curveObj 52 | 53 | # get the dagpath of the object 54 | dagpath = om.MDagPath() 55 | tempList.getDagPath(0, dagpath) 56 | 57 | # define the curve object as type MFnNurbsCurve 58 | curveMF = om.MFnNurbsCurve(dagpath) 59 | 60 | # what's the input point (in world) 61 | point = om.MPoint( location[0], location[1], location[2]) 62 | 63 | # define the parameter as a double * (pointer) 64 | prm = om.MScriptUtil() 65 | pointer = prm.asDoublePtr() 66 | om.MScriptUtil.setDouble (pointer, 0.0) 67 | 68 | # set tolerance 69 | tolerance = .00000001 70 | 71 | # set the object space 72 | space = om.MSpace.kObject 73 | 74 | # result will be the worldspace point 75 | result = om.MPoint() 76 | result = curveMF.closestPoint (point, pointer, 0.0, space) 77 | 78 | position = [(result.x), (result.y), (result.z)] 79 | curvePoint = om.MPoint ((result.x), (result.y), (result.z)) 80 | 81 | # creates a locator at the position 82 | #mc.spaceLocator (p=(position[0], position[1], position[2])) 83 | 84 | parameter = om.MScriptUtil.getDouble (pointer) 85 | 86 | # just return - parameter, then world space coord. 87 | return [(result.x), (result.y), (result.z)]# parameter] 88 | 89 | 90 | def alignVerts(): 91 | v = mc.ls(orderedSelection=True, fl=True) 92 | if len(v) > 2: 93 | a = mc.pointPosition(v[0], w=1) 94 | z = mc.pointPosition(v[-1], w=1) 95 | crv = curve(a,z) 96 | j = mc.createNode('joint') 97 | for i in range(1, len(v)-1): 98 | x = mc.pointPosition(v[i], w=1) 99 | p = closestPointOnCurve(x, crv) 100 | c = mc.cluster(v[i]) 101 | mc.setAttr(j+'.t', p[0], p[1], p[2]) 102 | mc.delete(mc.pointConstraint(j,c[1])) 103 | mc.delete(crv, j) 104 | mc.delete(mc.ls(v, r=1, o=True), ch=True) 105 | -------------------------------------------------------------------------------- /scripts/chains.py: -------------------------------------------------------------------------------- 1 | """ 2 | usage: 3 | 4 | # create tubes from curves 5 | from pprint import pprint 6 | import maya.cmds 7 | import chains 8 | reload(chains) 9 | r = chains.circles(mc.ls(sl=1)[0]) 10 | pprint(r) 11 | 12 | 1) Select curve to build tubes and ribbons from 13 | 14 | # create curve from nulls 15 | from pprint import pprint 16 | import maya.cmds 17 | import chains 18 | reload(chains) 19 | pos = chains.curveFromTransforms(maya.cmds.ls(sl=1)) 20 | 21 | 1) select transforms to build chains from 22 | 23 | returns 24 | 25 | david@ventosum.com 26 | """ 27 | 28 | 29 | import maya.OpenMaya 30 | import maya.api.OpenMaya 31 | import maya.cmds 32 | from math import pow,sqrt 33 | 34 | def isCurve(crv): 35 | 36 | # Check object exists 37 | if not maya.cmds.objExists(crv): 38 | return False 39 | 40 | # Check shape 41 | if maya.cmds.objectType(crv) == 'transform': 42 | crv = maya.cmds.listRelatives(crv, s=True, ni=True, pa=True) 43 | if crv: 44 | crv = crv[0] 45 | else: 46 | return False 47 | 48 | if maya.cmds.objectType(crv) != 'nurbsCurve': 49 | return False 50 | 51 | return True 52 | 53 | 54 | def curveVectors(crv): 55 | """ 56 | given a curve, generate a dictonary of the following: 57 | { 58 | 'curve' : original curve 59 | 'position' : list from 0:end of (0,0,0) coordinates of nearest points on curve to CVs (root to anchor to) 60 | 'up' : list from 0:end of (0,0,0) coordinates of CVs from curve 61 | 'tangent' : List from 0:end of (0,0,0) coordinates of each CV 62 | 'param' : List from 0:end of coordinate on curve value for each CV 63 | } 64 | """ 65 | 66 | if not isCurve(crv): 67 | return 68 | 69 | dag = maya.OpenMaya.MDagPath() 70 | sel = maya.OpenMaya.MSelectionList() 71 | sel.add(crv) 72 | sel.getDagPath(0, dag) 73 | space = maya.OpenMaya.MSpace.kWorld 74 | 75 | cvFn = maya.OpenMaya.MFnNurbsCurve(dag) 76 | msu = maya.OpenMaya.MScriptUtil() 77 | paramPtr = msu.asDoublePtr() 78 | mp = maya.OpenMaya.MPoint() 79 | 80 | # get all CVs in the defined space 81 | CVs = maya.OpenMaya.MPointArray() 82 | cvFn.getCVs(CVs, space) 83 | 84 | # define params to output 85 | r = {'curve' : crv} 86 | p = [] 87 | u = [] 88 | t = [] 89 | cpos = [] 90 | 91 | # iterate over all the cvs 92 | for cv in range(CVs.length()): 93 | # get the position of the CV (this is the up vector since it is up off the curve 94 | pt = CVs[cv] 95 | 96 | # we get the closest point on the curve for the current cv 97 | ptOnCurve = cvFn.closestPoint(pt, paramPtr) 98 | param = msu.getDouble(paramPtr) 99 | 100 | # get the position on curve closest to the CV 101 | ptPosOnCurve = cvFn.getPointAtParam(param, mp, space) 102 | 103 | # get the tangent of the current CV 104 | tan = cvFn.tangent(param, space) 105 | 106 | # pass the params for return 107 | cpos.append(param) 108 | u.append((pt.x, pt.y, pt.z)) 109 | p.append((mp.x, mp.y, mp.z)) 110 | t.append((tan.x, tan.y, tan.z)) 111 | 112 | # pass the params for return to dict 113 | r['position'] = p 114 | r['up'] = u 115 | r['tangent'] = t 116 | r['param'] = cpos 117 | 118 | return r 119 | 120 | 121 | def jointsAtParams(crv): 122 | """ 123 | build a chain from a curve from 0:end of joints and align their aim to each other 124 | based on the curve chain n to n+1 vector and where up is n+1 up vector from curve to nearest CV 125 | """ 126 | 127 | if not isCurve(crv): 128 | return 129 | 130 | # get curve params 131 | r = curveVectors(crv) 132 | 133 | # build temp aim and up vectors from list of base positions on curve nearest CVs 134 | aims = [] 135 | ups = [] 136 | for i in range(len(r['position'])): 137 | 138 | aim = ( maya.cmds.createNode('joint') ) 139 | maya.cmds.setAttr(aim +'.t', r['position'][i][0], r['position'][i][1], r['position'][i][2]) 140 | aims.append(aim) 141 | 142 | up = ( maya.cmds.createNode('joint') ) 143 | maya.cmds.setAttr(up +'.t', r['up'][i][0], r['up'][i][1], r['up'][i][2]) 144 | ups.append(up) 145 | 146 | # build chain from n+1 to end 147 | # aim n at n+1 148 | # if end just use joint since it is on curve already 149 | # delete the cruft when done 150 | js = [] 151 | for i in range(len(r['position'])): 152 | 153 | if i != len(r['position'])-1: 154 | 155 | aim = aims[i+1] 156 | root = maya.cmds.createNode('joint') 157 | up = ups[i+1] 158 | 159 | maya.cmds.setAttr(root+'.t', r['position'][i][0], r['position'][i][1], r['position'][i][2]) 160 | 161 | ac = maya.cmds.aimConstraint(aim, root, wut='object', wuo=up) 162 | maya.cmds.setAttr(ac[0]+'.worldUpType', 1) 163 | maya.cmds.select(root) 164 | j = maya.cmds.joint(n=crv+'_'+str(i)+'_JNT') 165 | 166 | j = maya.cmds.parent(j, w=1)[0] 167 | 168 | maya.cmds.delete(root) 169 | 170 | else: 171 | 172 | j = maya.cmds.duplicate(aims[i], rr=True, n=crv+'_'+str(i)+'_JNT')[0] 173 | 174 | js.append(j) 175 | 176 | # delete the temp aim and up vector nulls 177 | maya.cmds.delete(aims, ups) 178 | 179 | # parent joints to each other 180 | for j in range(1, len(js)): 181 | js[j] = maya.cmds.parent(js[j], js[j-1])[0] 182 | 183 | # get distance between joints 184 | js = maya.cmds.ls(js, dag=True, ap=True) 185 | d_sum = 0.0 186 | for j in range(len(js)-1): 187 | d = distance(js[j], js[j+1]) 188 | d_sum += d 189 | 190 | # extra alignment to prevent flips (occurs when cvs cross the plane of curve edit point on curve between two CVs which wer use for UP vector) 191 | maya.cmds.joint(js[j], e=True, zso=True, oj="xyz") 192 | 193 | # pass average radius, just cleaner for tube generation and ribbons 194 | mean_d = d_sum / len(js) 195 | for j in range(len(js)-1): 196 | # TODO normalize from start to end the scales of the radius 197 | maya.cmds.setAttr(js[j]+'.radius', (mean_d * 0.4) ) 198 | 199 | # zero out the end joint 200 | end = js[len(js)-1] 201 | maya.cmds.setAttr(end+'.jo', 0, 0, 0) 202 | endParent = maya.cmds.listRelatives(end, p=True)[0] 203 | maya.cmds.setAttr( end+'.radius', maya.cmds.getAttr( endParent +'.radius' ) ) 204 | 205 | return js 206 | 207 | 208 | def distance(a, b): 209 | """ 210 | Get the distance between two nodes 211 | """ 212 | 213 | a1, b1 = maya.cmds.xform(a, ws=True, t=True, q=True), maya.cmds.xform(b, ws=True, t=True, q=True) 214 | 215 | return sqrt(pow(a1[0]-b1[0],2)+pow(a1[1]-b1[1],2)+pow(a1[2]-b1[2],2)) 216 | 217 | 218 | def curve(null, curve='circle', radius=1.0, degree=3): 219 | """ 220 | Put a circle under a null with history for control or construction history 221 | """ 222 | 223 | # check validity of args 224 | if not maya.cmds.objExists(null): 225 | return 226 | 227 | if maya.cmds.nodeType(null) == 'transform' or maya.cmds.nodeType(null) == 'joint': 228 | 229 | if curve == 'circle': 230 | cir = maya.cmds.circle(c=(0,0,0), nr=(1,0,0), sw=360, r=radius, d=degree, ut=0, tol=0.01, s=6, ch=1)[0] 231 | elif curve == 'line': 232 | radius = radius * 1.0 # proportion to circle 233 | cir = maya.cmds.curve(d=1, p=[(0,0,radius), (0,0,(-1*radius))], k=(0,1) ) 234 | 235 | cir = maya.cmds.parent(cir, null, r=1) 236 | shape = maya.cmds.parent(maya.cmds.listRelatives(cir, s=1, f=1, pa=1, type='nurbsCurve'), null, r=1, s=1) 237 | 238 | maya.cmds.delete(cir) 239 | 240 | return {'null' : null, 'make' : maya.cmds.listHistory(shape), 'curve' : shape[0] } 241 | 242 | 243 | def jointFromJoint(j, radius=1.0, name=''): 244 | """ 245 | Create a joint from a joint with zero jointOrient 246 | """ 247 | 248 | if not maya.cmds.objExists(j): 249 | return 250 | 251 | if maya.cmds.nodeType(j) != 'joint': 252 | return 253 | 254 | s = maya.cmds.ls(sl=True) 255 | 256 | maya.cmds.select(j) 257 | newj = maya.cmds.joint(n=name) 258 | maya.cmds.setAttr( newj+'.radius', (maya.cmds.getAttr( j +'.radius' ) * radius) ) 259 | 260 | if s: 261 | maya.cmds.select(s) 262 | 263 | return newj 264 | 265 | 266 | def zeroJointOrient(j): 267 | """ 268 | Zero jointOrient 269 | 270 | TODO: use API for clean fast method 271 | """ 272 | 273 | if not maya.cmds.objExists(j): 274 | return 275 | 276 | if maya.cmds.nodeType(j) != 'joint': 277 | return 278 | 279 | s = maya.cmds.ls(sl=True) 280 | 281 | p = maya.cmds.listRelatives(j, p=1, pa=1, f=1) 282 | 283 | tj = jointFromJoint(j) 284 | tj = maya.cmds.parent(tj, w=True)[0] 285 | 286 | maya.cmds.delete( maya.cmds.pointConstraint( j, tj ) ) 287 | maya.cmds.delete( maya.cmds.orientConstraint( j, tj ) ) 288 | 289 | j = maya.cmds.parent(j, tj)[0] 290 | maya.cmds.setAttr(j+'.t', 0, 0, 0) 291 | maya.cmds.setAttr(j+'.r', 0, 0, 0) 292 | maya.cmds.setAttr(j+'.jo', 0, 0, 0) 293 | j = maya.cmds.parent(j, p)[0] 294 | 295 | maya.cmds.delete(tj) 296 | 297 | if s: 298 | maya.cmds.select(s) 299 | 300 | return j 301 | 302 | 303 | 304 | def curveFromTransforms(nulls): 305 | """ 306 | Create a nurbsCurve from transforms 307 | """ 308 | 309 | pos = [] 310 | for i in range(len(nulls)): 311 | m = [maya.cmds.xform(nulls[i], q=True, t=True, ws=True)] 312 | pos.extend(m) 313 | 314 | degree = 1 315 | if len(pos) > 3: 316 | degree = 3 317 | 318 | c = maya.cmds.curve(d=degree, p=pos) 319 | 320 | return c 321 | 322 | 323 | 324 | def circles(crv, loft=True, bind=True, sets=True): 325 | """ 326 | Build circles per null with history 327 | """ 328 | 329 | if not isCurve(crv): 330 | return 331 | 332 | js = jointsAtParams(crv) 333 | 334 | shapes = [] 335 | cs = [] 336 | nulls = [] 337 | lines = [] 338 | 339 | for j in range(len(js)): 340 | 341 | circle_j = jointFromJoint(js[j], name=js[j]+'_CIRCLE_JNT') 342 | 343 | # create nurbsCircle and set makeNurbsCircle radius to joint radius 344 | c = curve(circle_j, curve='circle', radius = 0.5) 345 | maya.cmds.setAttr( c['make'][1]+'.radius', maya.cmds.getAttr( js[j]+'.radius' ) ) 346 | 347 | nulls.append(c['null']) 348 | shapes.append(c['make'][0]) 349 | cs.append(c['make'][1]) 350 | 351 | line_j = jointFromJoint(js[j], radius = 0.5, name=js[j]+'_LINE_JNT') 352 | l = curve(line_j, curve='line') 353 | 354 | lines.append(l['curve']) 355 | 356 | # average the rotations on the joints for loft cleanliness 357 | print circles 358 | print lines 359 | for i in range(1 , len(shapes)-1): 360 | cj0 = maya.cmds.listRelatives( shapes[i-1], p=1 )[0] 361 | cj1 = maya.cmds.listRelatives( shapes[i+1], p=1 )[0] 362 | cj2 = maya.cmds.listRelatives( shapes[i], p=1 )[0] 363 | maya.cmds.delete( maya.cmds.orientConstraint( cj0, cj1, cj2 ) ) 364 | zeroJointOrient(cj2) 365 | 366 | lj0 = maya.cmds.listRelatives( lines[i-1], p=1 )[0] 367 | lj1 = maya.cmds.listRelatives( lines[i+1], p=1 )[0] 368 | lj2 = maya.cmds.listRelatives( lines[i], p=1 )[0] 369 | maya.cmds.delete( maya.cmds.orientConstraint( lj0, lj1, lj2 ) ) 370 | zeroJointOrient(lj2) 371 | 372 | r = { 373 | 'circles' : cs, 374 | 'shapes' : shapes, 375 | 'nulls' : nulls, 376 | 'lines' : lines 377 | } 378 | 379 | if loft: 380 | loft_tube = maya.cmds.loft(r['shapes'], n=crv+'_TUBE', ch=True, u=True, c=False, ar=True, d=3, ss=True, rn=False, po=False, rsn=True) 381 | loft_ribbon = maya.cmds.loft(r['lines'], n=crv+'_RIBBON', ch=True, u=True, c=False, ar=True, d=3, ss=True, rn=False, po=False, rsn=True) 382 | r['tube'] = loft_tube 383 | r['ribbon'] = loft_ribbon 384 | 385 | # ensure uniform in both U and V 386 | rebuild = maya.cmds.rebuildSurface([r['tube'][0], r['ribbon'][0]], ch=True, rpo=True, rt=0, end=1, kr=0, kcp=0, kc=0, su=0, du=3, sv=0, dv=3, tol=0.01, fr=0, dir=2) 387 | 388 | 389 | if bind and loft: 390 | bind = [] 391 | for j in range(len(js)): 392 | n = jointFromJoint(js[j], name='bind_'+js[j]) 393 | if maya.cmds.listRelatives(n, p=True): 394 | n = maya.cmds.parent(n, w=True)[0] 395 | bind.append(n) 396 | 397 | bind = bind[::-1] # reverse hier 398 | 399 | for j in range(len(bind)-1): 400 | bind[j] = maya.cmds.parent( bind[j], bind[j+1])[0] 401 | 402 | pols = maya.cmds.nurbsToPoly(loft_tube[0], n=crv+'_PXY', mnd=1, ch=True, f=3, pt=1, pc=200, chr=0.9, ft=0.01, mel=0.001, d=0.1, ut=1, un=3, vt=1, vn=3, uch=0, ucr=0, cht=0.2, es=0, ntr=0, mrt=0, uss=1) 403 | 404 | 405 | skin = maya.cmds.skinCluster(bind, [loft_tube[0],loft_ribbon[0]], tsb=True, mi=1, obeyMaxInfluences=True)[0] 406 | r['skin'] = skin 407 | r['influences'] = bind 408 | r['proxy'] = pols 409 | 410 | if sets: 411 | bind_set = maya.cmds.sets(bind, n=crv+'_bind_set') 412 | 413 | if sets: 414 | lines_set = maya.cmds.sets(lines, n=crv+'_lines_set') 415 | circles_set = maya.cmds.sets(shapes, n=crv+'_circles_set') 416 | 417 | 418 | return r 419 | 420 | 421 | def alignCVs(): 422 | a = maya.cmds.ls(sl=1, fl=1) 423 | if len(a) > 2: 424 | start = a[0] 425 | end = a[len(a)-1] 426 | rest = list(set(a)-set([start,end])) 427 | 428 | cStart = maya.cmds.cluster(start)[1] 429 | cEnd = maya.cmds.cluster(end)[1] 430 | cRest = [] 431 | for i in range(len(rest)): 432 | c = maya.cmds.cluster(rest[i])[1] 433 | cRest.append(c) 434 | maya.cmds.delete( maya.cmds.pointConstraint(cStart, cEnd, c)) 435 | 436 | maya.cmds.delete( maya.cmds.ls(a, o=1), ch=True ) 437 | 438 | # EOF -------------------------------------------------------------------------------- /scripts/follicle.py: -------------------------------------------------------------------------------- 1 | """ 2 | usage: 3 | 4 | import follicle 5 | import maya.cmds 6 | reload(follicle) 7 | x = follicle.folliclesFromSel(parent=True) 8 | 9 | 1) select transforms to attach 10 | 2) run follicle() method 11 | 3) parent the top resulting nul to anywhere in rig or constrain it so it follows rig 12 | 13 | returns a list of dictionaries for each null attached 14 | [ 15 | { 16 | 'null' : transform 17 | 'nurbs' : nurbs surface node 18 | 'follicle' : follicle shape node 19 | 'transform' : follicle transform node 20 | 'uv' : uv data 21 | { 22 | 'u' : u # U parameter 23 | 'v' : v # V parameter 24 | 'n' : (n.x, n.y, n.z) # normal 25 | 'nu' : nu # uniform U value (0-1) 26 | 'nv' : nv # uniform V value (0-1) 27 | } 28 | } 29 | ] 30 | 31 | david@ventosum.com 32 | """ 33 | 34 | import maya.cmds 35 | import maya.OpenMaya 36 | import maya.api.OpenMaya 37 | 38 | def getClostestUV(null, nurbs): 39 | """ 40 | Given a null, what's the closest U V N values in coordinate and uniform space 41 | Borrowed some logic from this thread: http://www.soup-dev.com/forum.html?p=post%2Fclosestpointonsurface-node-in-maya-python-api-8005994 42 | """ 43 | 44 | # check validity of args 45 | if not maya.cmds.objExists(null): 46 | return 47 | 48 | if not maya.cmds.objExists(nurbs): 49 | return 50 | 51 | if maya.cmds.nodeType(nurbs) != 'nurbsSurface': 52 | return 53 | 54 | # work around maya python api 55 | uu = maya.OpenMaya.MScriptUtil() 56 | pu = uu.createFromDouble(0.0) 57 | pu = uu.asDoublePtr() 58 | uv = maya.OpenMaya.MScriptUtil() 59 | pv = uv.createFromDouble(0.0) 60 | pv = uv.asDoublePtr() 61 | 62 | # get dag path to nurbs surface 63 | sl = maya.OpenMaya.MSelectionList() 64 | sl.add(nurbs) 65 | 66 | dp = maya.OpenMaya.MDagPath() 67 | sl.getDagPath(0, dp) 68 | 69 | fn = maya.OpenMaya.MFnNurbsSurface(dp) 70 | 71 | # get the closest point on surface to provided point 72 | mm = maya.cmds.xform( null, q=True, matrix=True, ws=True ) 73 | p = maya.OpenMaya.MPoint(mm[12], mm[13], mm[14]) 74 | cpos = fn.closestPoint(p) 75 | 76 | # get U and V parameters from the point on surface 77 | fn.getParamAtPoint(cpos, pu, pv) 78 | u = uu.getDouble(pu) 79 | v = uv.getDouble(pv) 80 | 81 | # get normal at U and V parameters 82 | n = fn.normal(u, v) 83 | 84 | # normalize U V to 0-1 for uniform values for nFollicles 85 | mxu = maya.cmds.getAttr(nurbs+'.mxu') 86 | mxv = maya.cmds.getAttr(nurbs+'.mxv') 87 | nu = u 88 | nv = v 89 | if u > 0: 90 | nu = u/mxu 91 | 92 | if v > 0: 93 | nv = v/mxv 94 | 95 | return {'u':u, 'v':v, 'n':(n.x, n.y, n.z), 'nu':nu, 'nv':nv} 96 | 97 | 98 | def getWorldTransform (obj): 99 | """ 100 | Return Matrix for worldpace coordinates of a transform null 101 | """ 102 | return maya.api.OpenMaya.MMatrix ( maya.cmds.xform( obj, q=True, matrix=True, ws=True ) ) 103 | 104 | 105 | def createFollicle(nurbs, u=0.0, v=0.0): 106 | """ 107 | Create a follicle for a nurbs surface given U and V. Duplicates can exist. 108 | """ 109 | 110 | # check validity of args 111 | if not maya.cmds.objExists(nurbs): 112 | return 113 | 114 | if maya.cmds.nodeType(nurbs) != 'nurbsSurface': 115 | return 116 | 117 | # get nice xf path to nurbs 118 | name = maya.cmds.listRelatives(nurbs, p=True, pa=True, f=True)[0].split('|')[-1] 119 | 120 | # get number of existing follicle to nurbs 121 | fols = maya.cmds.listConnections(nurbs+'.local', d=True, s=False, p=False) 122 | if fols: 123 | num = str(len(fols)) 124 | else: 125 | num = str(0) 126 | 127 | # create the follicle 128 | fol = maya.cmds.createNode('follicle', name=name+'_'+num.zfill(2)+'_follicle') 129 | maya.cmds.setAttr(fol+'.simulationMethod', 0) # static 130 | 131 | # name follicle xf 132 | xf = maya.cmds.listRelatives(fol, p=True)[0] 133 | xf = maya.cmds.rename( xf, name+'_'+num.zfill(2)+'_f') 134 | 135 | # hook up the nurbs and follicle 136 | maya.cmds.connectAttr( nurbs+'.local', fol+'.inputSurface', f=True) 137 | maya.cmds.connectAttr( nurbs+'.worldMatrix[0]', fol+'.inputWorldMatrix', f=True) 138 | maya.cmds.connectAttr( fol+'.outRotate', xf+'.r', f=True) 139 | maya.cmds.connectAttr( fol+'.outTranslate', xf+'.t', f=True) 140 | maya.cmds.setAttr( fol+'.parameterU', u) 141 | maya.cmds.setAttr( fol+'.parameterV', v) 142 | maya.cmds.setAttr( xf+'.t', l=True ) 143 | maya.cmds.setAttr( xf+'.r', l=True ) 144 | 145 | # return our follicle and its parent xf 146 | return {'follicle':fol, 'transform':xf} 147 | 148 | 149 | def follicleFromNode(null, nurbs, parent=True): 150 | """ 151 | Create an attachment of follicle for a null to a nurbs patch. 152 | """ 153 | 154 | # check validity of args 155 | if not maya.cmds.objExists(nurbs): 156 | return 157 | 158 | if maya.cmds.nodeType(nurbs) != 'nurbsSurface': 159 | return 160 | 161 | # get the UV params 162 | uv = getClostestUV(null, nurbs) 163 | 164 | # create the follicle attachment 165 | fols = createFollicle(nurbs, u=uv['nu'], v=uv['nv']) 166 | 167 | # parent and move to bottom so follicle is first in stack 168 | if parent: 169 | null = maya.cmds.parent(null, fols['transform']) 170 | maya.cmds.reorder(null, f=True) 171 | 172 | return { 173 | 'null': null, 174 | 'nurbs':nurbs, 175 | 'follicle':fols['follicle'], 176 | 'transform':fols['transform'], 177 | 'uv':uv 178 | } 179 | 180 | 181 | def folliclesFromSel(parent=True): 182 | """ 183 | Create attachment follicles per selected transforms to selected nurbs. 184 | - Only works on one patch at a time. 185 | - Parents transforms by default. 186 | """ 187 | 188 | # check for transforms and a nurbs surface 189 | s = maya.cmds.ls(sl=1, type='transform', l=True) 190 | nurbs = maya.cmds.ls(s, ap=True, dag=True, type='nurbsSurface') 191 | 192 | # if nurbs check for history intermediates 193 | nurbs_parents = list(set(maya.cmds.listRelatives(nurbs, p=True, pa=True, f=True))) 194 | if len(nurbs_parents) != 1: 195 | print('Only one nurbs surface in the stack of selected transforms supported (more than one nurbs transform selected.') 196 | return 197 | 198 | # get the nurbs parent and remove it from transforms list 199 | np = maya.cmds.listRelatives(nurbs, p=True, type='transform', pa=True, f=True) 200 | nurbs = nurbs[0] 201 | s.remove(np[0]) 202 | 203 | # build follicles if only one nurbs and one or more transforms 204 | r = [] 205 | for n in s: 206 | f = follicleFromNode(n, nurbs, parent=parent) 207 | r.append(f) 208 | 209 | return r 210 | 211 | # EOF 212 | -------------------------------------------------------------------------------- /scripts/makeCenterLine.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmd 2 | import maya.mel as mel 3 | import re 4 | 5 | def makeCenterLine(c=1, j=1): 6 | # track selection order must be ON for this to work 7 | points = 'curve -d 3 ' 8 | sel = cmd.ls(os=True, fl=True) 9 | ob = cmd.ls(o=True, sl=True) 10 | num = [] 11 | out = [] 12 | edges = [] 13 | joints = [] 14 | for one in sel: 15 | strip = re.search(r"\[([0-9]+)\]", one) 16 | num.append(strip.group(1)) 17 | size = len(num) 18 | if (size): 19 | if size == 1: 20 | edges = cmd.polySelect(edgeRing=(int(num[0])), ns=True) 21 | if size == 2: 22 | edges = cmd.polySelect(edgeRingPath=(int(num[0]), int(num[1])), ns=True) 23 | if size > 2: 24 | edges = num 25 | for one in edges: 26 | cmd.select(ob) 27 | cmd.polySelect(elb=int(one)) 28 | clust = cmd.cluster(n='poo#') 29 | cmd.select(clear=True) 30 | posi = cmd.getAttr(clust[1]+'.origin') 31 | if c: 32 | points = points + ('-p %s %s $%s ' %(posi[0][0], posi[0][1], posi[0][2])) 33 | if j: 34 | joints.append(cmd.joint(p = (posi[0][0], posi[0][1], posi[0][2]))) 35 | cmd.delete(clust) 36 | if c: 37 | print points 38 | out.append(mel.eval(points)) 39 | if j: 40 | for i in reversed(range(1, len(edges))): 41 | cmd.parent(joints[i], joints[i-1]) 42 | cmd.joint(joints[0], e=True, oj='xyz', sao='zup', ch=True, zso=True) 43 | cmd.joint(joints[-1], e=True, o = (0,0,0)) 44 | out.append(joints[0]) 45 | cmd.select(out) 46 | else: 47 | print('Nothing is selected.') 48 | 49 | -------------------------------------------------------------------------------- /scripts/snapDeformer.mel: -------------------------------------------------------------------------------- 1 | /* 2 | snapDeformer.mel 3 | david@ventosum.com 4 | 5 | Use this tool to create and connect surfaces using the snapDeformer. 6 | For snapping points to points of surfaces. Much like a wrap deformer, but 7 | it is fast and less buggy. 8 | */ 9 | 10 | global proc ui_snapDeformer() { 11 | string $win = "snapDeformer"; 12 | int $w = 205; 13 | int $h = 250; 14 | 15 | if (`about -linux`) $h = ($h-13); 16 | if (`about -mac`) $h = ($h+17); 17 | if (`window -ex $win`) deleteUI $win; 18 | $win = `window -rtf 0 -title $win -iconName $win -s 1 $win`; 19 | 20 | makePaintable -shapeMode "deformer" -attrType "multiFloat" "snapMeshDeformer" "weights"; 21 | 22 | snap_tryPlugin("snapDeformer"); 23 | 24 | menuBarLayout; 25 | menu -l "File" -en 1; 26 | string $exit = `menuItem -l "Exit" -c ("deleteUI " + $win)`; 27 | 28 | //main layout 29 | string $mainLayout = `formLayout -numberOfDivisions 200`; 30 | 31 | //first chunk inside main layout 32 | string $c = `columnLayout -adj 1 -w 210`; 33 | 34 | string $src = `button -p $c -h 22 -l "Source" -ann "Select the \"Driver\" geometry transforms" -c ("snapVariables 0")`; 35 | string $dest = `button -p $c -h 22 -l "Destination" -ann "Select the \"Driven\" geometry transforms" -c ("snapVariables 1")`; 36 | string $threshold = `floatField -p $c -min 0.0 -max 10.0 -v 0.010 -w $w`; 37 | string $connect = `button -p $c -h 30 -w $w -l "Connect" -ann "snapDeformer: Use \"Dest surfs\" button and \"Source\" surfs buttons to run with tolerance." -c ("snapDeformerUI "+$threshold)`; 38 | string $all = `button -p $c -h 22 -w $w -l "Delete All Snaps" -ann "This will search the scene and delete ALL snapDeformer(s)" -c ("deleteAllSnaps")`; 39 | 40 | setParent $mainLayout; 41 | 42 | string $close = `button -l "Close" -h 40 -w $w -c ("deleteUI "+$win+";")`; 43 | 44 | formLayout -e -af $c "top" 0 -af $c "left" 0 -af $c "right" 0 45 | -ac $c "bottom" 0 $close -an $close "top" -af $close "left" 0 46 | -af $close "right" 0 -af $close "bottom" 0 $mainLayout; 47 | 48 | showWindow $win; 49 | window -e -w $w -h $h $win; 50 | 51 | } 52 | 53 | global proc deleteAllSnaps() { 54 | string $type = "snapMeshDeformer"; 55 | 56 | string $msg = "Delete all deformers of type "+$type+" in your scene?"; 57 | string $confirm = `confirmDialog -title $msg -message $msg -b "Yes" -b "No" -db "Yes" -cb "No" -ds "No"`; 58 | 59 | if ($confirm == "Yes") { 60 | string $snaps[] = `ls -typ $type`; 61 | if (size($snaps)>0) { 62 | string $snapstring = `snap_stringArrayToString $snaps`; 63 | evalEcho ("delete "+$snapstring); 64 | } 65 | } 66 | } 67 | 68 | global proc string[] snapVariables(int $srcDest) { 69 | global string $snapSnapSourceMeshes[]; 70 | global string $snapSnapDestinationMeshes[]; 71 | 72 | string $type = "snapMeshDeformer"; 73 | 74 | string $geom[];clear($geom); 75 | if ($srcDest==0) clear($snapSnapSourceMeshes); 76 | else if ($srcDest==1) clear($snapSnapDestinationMeshes); 77 | string $sel[] = `ls -sl`; 78 | for ($n in $sel) { 79 | string $shapes[] = `listRelatives -s -pa -ni -f $n`; 80 | for ($i=0;$i0) { 136 | makePaintable -shapeMode "deformer" -attrType "multiFloat" "snapMeshDeformer" "weights"; 137 | print ("Created the following snapMeshDeformers:\n"); 138 | print $snaps; 139 | } 140 | print ("// Result: created snapDeformer(s) for "+$targets+" from "+$sources+" (see script editor for details).\n"); 141 | return $snaps; 142 | } 143 | 144 | global proc string snap_stringArrayToString(string $array[]) { 145 | string $string = ""; 146 | int $size = size($array); 147 | 148 | if (!$size) { 149 | warning ("empty array."); 150 | return "{\"\"}"; 151 | } else if ($size == 1) { 152 | $string = ("{\""+$array[0]+"\"}"); 153 | } else { 154 | $string = "{"; 155 | for ($i=0;$i size: size = cur 71 | 72 | ctrl = maya.cmds.circle(n=name+'_CON', r=size, ch=0, nrx=1, nry=0, nrz=0)[0] 73 | c2 = maya.cmds.circle(r=size, ch=0, nrx=0, nry=1, nrz=0)[0] 74 | c3 = maya.cmds.circle(r=size, ch=0, nrx=0, nry=0, nrz=1)[0] 75 | maya.cmds.parent(maya.cmds.listRelatives([c2,c3], s=1, ni=1), ctrl, r=1, s=1) 76 | maya.cmds.delete(c2,c3) 77 | 78 | piv = maya.cmds.circle(n=name+'_PIV', r=(size*1.1), ch=0, nrx=0, nry=1, nrz=0)[0] 79 | 80 | maya.cmds.delete(maya.cmds.pointConstraint(sm[1], ctrl)) 81 | maya.cmds.delete(maya.cmds.pointConstraint(sm[1], piv)) 82 | maya.cmds.makeIdentity(ctrl, a=True) 83 | maya.cmds.makeIdentity(piv, a=True) 84 | 85 | shape = maya.cmds.parent(maya.cmds.listRelatives(sm[1], c=1), ctrl, r=1, s=1)[0] 86 | maya.cmds.setAttr(shape+'.v', 0) 87 | maya.cmds.connectAttr(ctrl+'.worldMatrix', sm[0]+'.matrix', f=1) 88 | maya.cmds.delete(sm[1]) 89 | 90 | loc = maya.cmds.createNode('locator') 91 | locp = maya.cmds.listRelatives(loc, p=1) 92 | maya.cmds.delete(maya.cmds.pointConstraint(ctrl, locp)) 93 | maya.cmds.makeIdentity(locp, a=1) 94 | loc = maya.cmds.parent(loc, piv, r=True, s=True)[0] 95 | maya.cmds.setAttr(loc+'.v', 0) 96 | maya.cmds.delete(locp) 97 | maya.cmds.connectAttr(piv+".worldPosition[0]", sm[0]+".falloffCenter", f=1) 98 | maya.cmds.connectAttr(piv+'.worldInverseMatrix[0]', sm[0]+'.bindPreMatrix', f=1) 99 | 100 | zero = maya.cmds.createNode('transform', n=name+'_ZERO') 101 | maya.cmds.delete(maya.cmds.pointConstraint(ctrl,zero)) 102 | maya.cmds.makeIdentity(zero, a=True) 103 | 104 | piv = maya.cmds.parent(piv, zero) 105 | ctrl = maya.cmds.parent(ctrl, piv) 106 | 107 | maya.cmds.addAttr(ctrl, ln='falloffRadius', at='float', dv=(size*1500), r=1, h=0, k=1) 108 | maya.cmds.connectAttr(ctrl[0]+'.falloffRadius', sm[0]+'.falloffRadius', f=1) 109 | 110 | for c in maya.cmds.ls(zero, ap=1, dag=1, typ='nurbsCurve'): 111 | maya.cmds.reorder(c, b=1) 112 | shapename = maya.cmds.listRelatives(c, p=1, f=1, pa=1)[0].split('|')[-1]+'Shape' 113 | maya.cmds.rename(c, shapename) 114 | 115 | ret = { 116 | 'control' : ctrl[0], 117 | 'pivot' : piv[0], 118 | 'zero' : zero, 119 | 'softMod' : sm[0] 120 | } 121 | maya.cmds.select(ctrl) 122 | 123 | return ret 124 | -------------------------------------------------------------------------------- /windows/AlwaysOnTop.ahk: -------------------------------------------------------------------------------- 1 | #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. 2 | ; #Warn ; Enable warnings to assist with detecting common errors. 3 | SendMode Input ; Recommended for new scripts due to its superior speed and reliability. 4 | SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. 5 | 6 | ^SPACE:: Winset, Alwaysontop, , A -------------------------------------------------------------------------------- /windows/windows_registry_cmd.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [HKEY_CLASSES_ROOT\Directory\shell\cmdprompt] 4 | @="@shell32.dll,-8506" 5 | "NoWorkingDirectory"="" 6 | 7 | [HKEY_CLASSES_ROOT\Directory\shell\cmdprompt\command] 8 | @="cmd.exe /s /k pushd \"%V\"" 9 | 10 | [HKEY_CLASSES_ROOT\Directory\Background\shell\cmdprompt] 11 | @="@shell32.dll,-8506" 12 | "NoWorkingDirectory"="" 13 | 14 | [HKEY_CLASSES_ROOT\Directory\Background\shell\cmdprompt\command] 15 | @="cmd.exe /s /k pushd \"%V\"" 16 | 17 | [HKEY_CLASSES_ROOT\Drive\shell\cmdprompt] 18 | @="@shell32.dll,-8506" 19 | "NoWorkingDirectory"="" 20 | 21 | [HKEY_CLASSES_ROOT\Drive\shell\cmdprompt\command] 22 | @="cmd.exe /s /k pushd \"%V\"" --------------------------------------------------------------------------------