位移吸附

  上文讲到可以通过计算法线角度实现旋转角的计算。
  那么为什么要计算出旋转角呢?
  直接吸附相关的点到对应的模型上不就OK了吗?

  问题当然没有那么简单,如果模型没有旋转正确的角度就去吸附的话,会产生问题的。

变形

  可以看到非正确的角度吸附会变形的。
  不过这个问题已经在上文中解决了。
  现在要解决的是头疼的吸附问题。

  最初想的效果是通过缩放比例来匹配目标点的大小,但是仔细一想就知道有多扯淡。
  怎样的缩放比例才是适合的,压根就没有谱。
  因此只有吸附位移点的操作才是重中之重。

操作逻辑

  其实仅仅是吸附到位的核心代码并不复杂。

![吸附点]https://cdn.jsdelivr.net/gh/FXTD-odyssey/FXTD-odyssey.github.io@master/post_img/52737/2.png)

![吸附点]https://cdn.jsdelivr.net/gh/FXTD-odyssey/FXTD-odyssey.github.io@master/post_img/52737/3.png)

  如此就可以将点吸附到想要的位置。
  然后记录下当前吸附的位置。
  然后吸附另一边的点,然后将刚才记录的位置返回给左边部分的点。
  通过点的模型拉伸就完美实现了。

  难点

  • 如何自动识别出需要吸附的顶点
  • 如何记录相应的点的位置

自动识别需要吸附的顶点

  要让两者互相配对,就需要识别对应关系。
  首先是模型自身的顶点——左下角和右下角顶点。
  这个还真的没有好的办法,因此我认为这个需要用户定义这两个角的序号。
  毕竟不同的模型,左下角和右下角的定义是不一样的。

  问题是如何让点与点之间产生配对关系,这个让我想了很久。
  最后我的解决方案也不是很完美,不过至少也是把问题解决了。

  我的想法是获取模型上的极端点,或者说是碰撞盒上的点。
  毕竟导入模型的左下角和右下角也算是极端的碰撞盒点了(至少面片属于的)
  那么我们的目标位置又如何有极端的碰撞盒点呢?
  这就需要借助之前提到的三角形了。
  三角形也是面片,只要分离出两者极端点的关系,就可以产生对应关系。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
global proc int[] computeBoudingPt(string $target){

int $versNum[] = `polyEvaluate -v $target`;

//截取“.” 判断传入参数是否是面
string $buffer[];
tokenize $target "." $buffer;

select -r $target;

//将面转为顶点
ConvertSelectionToVertices;
string $selectedPt[] = `ls -sl `;

//如果传入的顶点信息是相连的情况需要进行处理
//例如这样:store5:store.vtx[0:9]
if(size($selectedPt) == 1){
string $buffer2[];
string $buffer3[];

//分离出 [***:***] 当中的数字 例如[123:321] 分离目标数据
tokenize `match "[0-9]]" $selectedPt[0]` "]" $buffer2;
tokenize `match "vtx[[0-9]+:" $selectedPt[0]` "[" $buffer3;

//数据类型转换
int $temp_1 = $buffer3[1];
int $temp_2 = $buffer2[0];

//将目标数据存放到一个数组变量中
int $pointNum_Seperate[] = {};
for($i = 0; $i + $temp_1 <= $temp_2; $i++ ){
$pointNum_Seperate[$i] = $i + $temp_1;
}
}

float $tempPtPos[];
float $MinPtX;
float $MinPtY;
float $MinPtZ;
float $MaxPtX;
float $MaxPtY;
float $MaxPtZ;

//遍历所有的点 计算点的世界坐标 算出所有轴向的最大值和最小值
for($j = 0; $j < $versNum[0]; $j++ ){

//获取点的世界坐标
if($buffer[1] == ""){//传入参数不是面
$tempPtPos = `xform -q -ws -t ($target + ".vtx[" + $j +"]")`;
}else{//传入参数是面
$tempPtPos = `xform -q -ws -t ($buffer[0] + ".vtx[" + $pointNum_Seperate[$j] +"]")`;
}

//初始化数值
if($j == 0){
$MinPtX = $tempPtPos[0];
$MinPtY = $tempPtPos[1];
$MinPtZ = $tempPtPos[2];

$MaxPtX = $tempPtPos[0];
$MaxPtY = $tempPtPos[1];
$MaxPtZ = $tempPtPos[2];
}

//计算极端值
$MinPtX = `min $MinPtX $tempPtPos[0]`;
$MinPtY = `min $MinPtY $tempPtPos[1]`;
$MinPtZ = `min $MinPtZ $tempPtPos[2]`;

$MaxPtX = `max $MaxPtX $tempPtPos[0]`;
$MaxPtY = `max $MaxPtY $tempPtPos[1]`;
$MaxPtZ = `max $MaxPtZ $tempPtPos[2]`;

}

int $CornerPT[] ;

//初始化数值
//复制-1是避免和0序号冲突
$CornerPT[0] = -1;
$CornerPT[1] = -1;
$CornerPT[2] = -1;
$CornerPT[3] = -1;
$CornerPT[4] = -1;
$CornerPT[5] = -1;
$CornerPT[6] = -1;
$CornerPT[7] = -1;

//由于mel自身的浮点数可能有偏差,没有办法让两次获取的数据相等
//经过网上查找,这里用python的代码强行保留小数点三位小数。
$MinPtX = `python ("round ("+ $MinPtX +", 3)")`;
$MinPtY = `python ("round ("+ $MinPtY +", 3)")`;
$MinPtZ = `python ("round ("+ $MinPtZ +", 3)")`;
$MaxPtX = `python ("round ("+ $MaxPtX +", 3)")`;
$MaxPtY = `python ("round ("+ $MaxPtY +", 3)")`;
$MaxPtZ = `python ("round ("+ $MaxPtZ +", 3)")`;

//根据点坐标最大值和最小值 获取边角的点序号
for($j = 0; $j < $versNum[0]; $j++){

//获取点的世界坐标
if($buffer[1] == ""){//传入参数不是面
$tempPtPos = `xform -q -ws -t ($target + ".vtx[" + $j +"]")`;

$tempPtPos[0] = `python ("round ("+ $tempPtPos[0] +", 3)")`;
$tempPtPos[1] = `python ("round ("+ $tempPtPos[1] +", 3)")`;
$tempPtPos[2] = `python ("round ("+ $tempPtPos[2] +", 3)")`;

if($tempPtPos[1] == $MinPtY ){

if($tempPtPos[0] == $MinPtX ){

if($tempPtPos[2] == $MinPtZ){

$CornerPT[0] = $j;

}else if($tempPtPos[2] == $MaxPtZ){

$CornerPT[1] = $j;

}

}else if($tempPtPos[0] == $MaxPtX ){

if($tempPtPos[2] == $MinPtZ){

$CornerPT[2] = $j;

}else if($tempPtPos[2] == $MaxPtZ){

$CornerPT[3] = $j;

}

}

}else if($tempPtPos[1] == $MaxPtY ){

if($tempPtPos[0] == $MinPtX ){

if($tempPtPos[2] == $MinPtZ){

$CornerPT[4] = $j;

}else if($tempPtPos[2] == $MaxPtZ){

$CornerPT[5] = $j;

}
}else if($tempPtPos[0] == $MaxPtX ){

if($tempPtPos[2] == $MinPtZ){

$CornerPT[6] = $j;

}else if($tempPtPos[2] == $MaxPtZ){

$CornerPT[7] = $j;

}

}

}

}else{//传入参数是面
$tempPtPos = `xform -q -ws -t ($buffer[0] + ".vtx[" + $pointNum_Seperate[$j] +"]")`;

$tempPtPos[0] = `python ("round ("+ $tempPtPos[0] +", 3)")`;
$tempPtPos[1] = `python ("round ("+ $tempPtPos[1] +", 3)")`;
$tempPtPos[2] = `python ("round ("+ $tempPtPos[2] +", 3)")`;

if($tempPtPos[1] == $MinPtY ){

if($tempPtPos[0] == $MinPtX ){

if($tempPtPos[2] == $MinPtZ){

$CornerPT[0] = $pointNum_Seperate[$j];

}else if($tempPtPos[2] == $MaxPtZ){

$CornerPT[1] = $pointNum_Seperate[$j];

}

}else if($tempPtPos[0] == $MaxPtX ){

if($tempPtPos[2] == $MinPtZ){

$CornerPT[2] = $pointNum_Seperate[$j];

}else if($tempPtPos[2] == $MaxPtZ){

$CornerPT[3] = $pointNum_Seperate[$j];

}

}

}else if($tempPtPos[1] == $MaxPtY ){

if($tempPtPos[0] == $MinPtX ){

if($tempPtPos[2] == $MinPtZ){

$CornerPT[4] = $pointNum_Seperate[$j];

}else if($tempPtPos[2] == $MaxPtZ){

$CornerPT[5] = $pointNum_Seperate[$j];

}
}else if($tempPtPos[0] == $MaxPtX ){

if($tempPtPos[2] == $MinPtZ){

$CornerPT[6] = $pointNum_Seperate[$j];

}else if($tempPtPos[2] == $MaxPtZ){

$CornerPT[7] = $pointNum_Seperate[$j];

}

}

}
}

}
//返回的$CornerPT包含8个数值,处于极端点的就会存储点序号,否则就输出-1值。
return $CornerPT;

}

  通过上面的方法就可以计算出boundingbox的点,但是缺点也很明显。
  如果是面片的话倒也还好,如果是个正方体之类的复杂模型,只要稍微一旋转。
  所有的点都不在碰撞盒里面,就无法获取想要的对应关系了。
  当然也不是没有解决方法,只是需要将模型旋转到正对轴向的方向才行,当然复杂的模型是不可能的了。
  我目前还没有想到更好的方案(估计更进一步就要学习复杂的算法了)

  如此一来就可以通过极端点的对应关系,知道左边的点对应的三角形面片的点。
  从而实现自动吸附功能。

记录点的位置

  记录点的位置需要一开始分别识别左边的点和右边的点。
  我想到的方法就是以X轴为界限,分别记录左边的点和右边的点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//记录左边和右边的点
//$target 就是导入的模型

//获取模型的点数 用于遍历
int $versNum[] = `polyEvaluate -v $target`;

string $leftPtSel[] ;
string $rightPtSel[] ;

for($j = 0; $j < $versNum[0]; $j++ ){

//获取每个点的世界坐标
$tempPtPos = `xform -q -ws -t ($target + ".vtx[" + $j +"]")`;

//无关变量赋予无关值
$leftPtSel[$j] = -1;
$rightPtSel[$j] = -1;
//区分左边和右边的点
if($tempPtPos[2] > 0){//判断Z轴
$leftPtSel[$j] = $j;
}else{
$rightPtSel[$j] = $j;
}

}

  下面要考虑的是如何通过这里的点信息来记录吸附点的坐标位置。
  并且在吸附结束之后,将记录的信息还原到对应的点上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
////////////////////////////////////////////////////////////
//////////////// 匹配需要吸附的点 //////////////////
///////////////////////////////////////////////////////////

select -r $leftCorner;//选择左下角的顶点

//目标模型的左下角点的面片
ConvertSelectionToFaces;
string $selFace[] = `ls -sl `;//获取左下角的面

int $CornerPtnum[] = FXTD_computeBoudingPt($selFace[0]);
int $TriPtnum[] = FXTD_computeBoudingPt($temp_tri[0]);

int $num_1 = -1;
int $num_2 = -1;

//找到互相匹配的点 进行吸附
for($j = 0; $j < 4; $j++){

if($CornerPtnum[$j] != -1 && $TriPtnum[$j] != -1){

if($num_1 == -1){
$num_1 = $j;
}else if($num_2 == -1){
$num_2 = $j;
}

}

}

//第一次吸附点
select -r ($target + ".vtx["+ $CornerPtnum[$num_1] + "]");

select -tgl ($temp_tri[0] + ".vtx["+ $TriPtnum[$num_1] + "]");

SnapPointToPoint;

float $left_vtx_position[] = {};//清空数组
float $right_vtx_position[] = {};//清空数组
//记录当前的位置信息
if($CornerPtnum[$num_1] == $leftNum){//如果是吸附左边的点

for($j = 0; $j < $versNum[0]; $j++ ){

if($leftPtSel[$j] != -1 ){

FXTD_floatPush($left_vtx_position,`xform -q -ws -t ($target + ".vtx[" + $j +"]")`);

}

}

}else{

for($j = 0; $j < $versNum[0]; $j++ ){

if($rightPtSel[$j] != -1 ){

FXTD_floatPush($right_vtx_position,`xform -q -ws -t ($target + ".vtx[" + $j +"]")`);

}

}

}


select -r ($target + ".vtx["+ $CornerPtnum[$num_2] + "]");

select -tgl ($temp_tri[0] + ".vtx["+ $TriPtnum[$num_2] + "]");

SnapPointToPoint;

//复原上面记录的位置
int $temp = 0;
if($CornerPtnum[$num_1] == $leftNum){//如果是吸附左边的点

for($j = 0; $j < $versNum[0]; $j++ ){

if($leftPtSel[$j] != -1 ){

select -r ($target + ".vtx[" + $j +"]");
move -a $left_vtx_position[$temp*3] $left_vtx_position[$temp*3+1] $left_vtx_position[$temp*3+2];
$temp++;

}

}

}else{

for($j = 0; $j < $versNum[0]; $j++ ){

if($rightPtSel[$j] != -1 ){

select -r ($target + ".vtx[" + $j +"]");
move -a $right_vtx_position[$temp*3] $right_vtx_position[$temp*3+1] $right_vtx_position[$temp*3+2];
$temp++;

}

}

}

插件制作

  基本上整个插件的难点已经剖析出来了。
  剩下的就是将一些琐碎的功能连接到一起而已。
注:导入的模型面片一定要朝向X轴正方向,这里偷了懒,没有做法线方向的计算。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
//面片匹配插件 ver 1.0
//制作时间2018-8-25 - 2018-8-27
//制作人:智伤帝,可在B站关注我哟~

//模拟 push数组 的效果将数据放到数组最后
global proc FXTD_floatPush(float $array[],float $added[]){

int $addedSize = size($added);
int $arraySize = size($array);

for($i = $arraySize; $i < $arraySize+$addedSize; $i++ )
{
$array[$i] = $added[$i-$arraySize];
}

}

//计算模型的边角点(仅在正90度的正方形、面片起作用)
global proc int[] FXTD_computeBoudingPt(string $target){

int $versNum[] = `polyEvaluate -v $target`;

//截取“.” 判断传入参数是否是面
string $buffer[];
int $pointNum_Seperate[] = {};
tokenize $target "." $buffer;

select -r $target;
ConvertSelectionToVertices;
string $selectedPt[] = `ls -sl `;

if(size($selectedPt) == 1){
string $buffer2[];
string $buffer3[];

//分离出 [***:***] 当中的数字 例如[123:321]
tokenize `match "[0-9]]" $selectedPt[0]` "]" $buffer2;
tokenize `match "vtx[[0-9]+:" $selectedPt[0]` "[" $buffer3;

//数据类型转换
int $temp_1 = $buffer3[1];
int $temp_2 = $buffer2[0];

for($i = 0; $i + $temp_1 <= $temp_2; $i++ ){
$pointNum_Seperate[$i] = $i + $temp_1;
}
}

float $tempPtPos[];
float $MinPtX;
float $MinPtY;
float $MinPtZ;
float $MaxPtX;
float $MaxPtY;
float $MaxPtZ;

//遍历所有的点 计算点的世界坐标 算出所有轴向的最大值和最小值
for($j = 0; $j < $versNum[0]; $j++ ){

//获取点的世界坐标
if($buffer[1] == ""){//传入参数不是面
$tempPtPos = `xform -q -ws -t ($target + ".vtx[" + $j +"]")`;
}else{//传入参数是面
$tempPtPos = `xform -q -ws -t ($buffer[0] + ".vtx[" + $pointNum_Seperate[$j] +"]")`;
}

//初始化数值
if($j == 0){
$MinPtX = $tempPtPos[0];
$MinPtY = $tempPtPos[1];
$MinPtZ = $tempPtPos[2];

$MaxPtX = $tempPtPos[0];
$MaxPtY = $tempPtPos[1];
$MaxPtZ = $tempPtPos[2];
}

$MinPtX = `min $MinPtX $tempPtPos[0]`;
$MinPtY = `min $MinPtY $tempPtPos[1]`;
$MinPtZ = `min $MinPtZ $tempPtPos[2]`;

$MaxPtX = `max $MaxPtX $tempPtPos[0]`;
$MaxPtY = `max $MaxPtY $tempPtPos[1]`;
$MaxPtZ = `max $MaxPtZ $tempPtPos[2]`;

}

int $CornerPT[] ;

//初始化数值
$CornerPT[0] = -1;
$CornerPT[1] = -1;
$CornerPT[2] = -1;
$CornerPT[3] = -1;
$CornerPT[4] = -1;
$CornerPT[5] = -1;
$CornerPT[6] = -1;
$CornerPT[7] = -1;

$MinPtX = `python ("round ("+ $MinPtX +", 3)")`;
$MinPtY = `python ("round ("+ $MinPtY +", 3)")`;
$MinPtZ = `python ("round ("+ $MinPtZ +", 3)")`;
$MaxPtX = `python ("round ("+ $MaxPtX +", 3)")`;
$MaxPtY = `python ("round ("+ $MaxPtY +", 3)")`;
$MaxPtZ = `python ("round ("+ $MaxPtZ +", 3)")`;

//根据点坐标最大值和最小值 获取边角的点序号
for($j = 0; $j < $versNum[0]; $j++){

//获取点的世界坐标
if($buffer[1] == ""){//传入参数不是面
$tempPtPos = `xform -q -ws -t ($target + ".vtx[" + $j +"]")`;

$tempPtPos[0] = `python ("round ("+ $tempPtPos[0] +", 3)")`;
$tempPtPos[1] = `python ("round ("+ $tempPtPos[1] +", 3)")`;
$tempPtPos[2] = `python ("round ("+ $tempPtPos[2] +", 3)")`;

if($tempPtPos[1] == $MinPtY ){

if($tempPtPos[0] == $MinPtX ){

if($tempPtPos[2] == $MinPtZ){

$CornerPT[0] = $j;

}else if($tempPtPos[2] == $MaxPtZ){

$CornerPT[1] = $j;

}

}else if($tempPtPos[0] == $MaxPtX ){

if($tempPtPos[2] == $MinPtZ){

$CornerPT[2] = $j;

}else if($tempPtPos[2] == $MaxPtZ){

$CornerPT[3] = $j;

}

}

}else if($tempPtPos[1] == $MaxPtY ){

if($tempPtPos[0] == $MinPtX ){

if($tempPtPos[2] == $MinPtZ){

$CornerPT[4] = $j;

}else if($tempPtPos[2] == $MaxPtZ){

$CornerPT[5] = $j;

}
}else if($tempPtPos[0] == $MaxPtX ){

if($tempPtPos[2] == $MinPtZ){

$CornerPT[6] = $j;

}else if($tempPtPos[2] == $MaxPtZ){

$CornerPT[7] = $j;

}

}

}

}else{//传入参数是面
$tempPtPos = `xform -q -ws -t ($buffer[0] + ".vtx[" + $pointNum_Seperate[$j] +"]")`;

$tempPtPos[0] = `python ("round ("+ $tempPtPos[0] +", 3)")`;
$tempPtPos[1] = `python ("round ("+ $tempPtPos[1] +", 3)")`;
$tempPtPos[2] = `python ("round ("+ $tempPtPos[2] +", 3)")`;

if($tempPtPos[1] == $MinPtY ){

if($tempPtPos[0] == $MinPtX ){

if($tempPtPos[2] == $MinPtZ){

$CornerPT[0] = $pointNum_Seperate[$j];

}else if($tempPtPos[2] == $MaxPtZ){

$CornerPT[1] = $pointNum_Seperate[$j];

}

}else if($tempPtPos[0] == $MaxPtX ){

if($tempPtPos[2] == $MinPtZ){

$CornerPT[2] = $pointNum_Seperate[$j];

}else if($tempPtPos[2] == $MaxPtZ){

$CornerPT[3] = $pointNum_Seperate[$j];

}

}

}else if($tempPtPos[1] == $MaxPtY ){

if($tempPtPos[0] == $MinPtX ){

if($tempPtPos[2] == $MinPtZ){

$CornerPT[4] = $pointNum_Seperate[$j];

}else if($tempPtPos[2] == $MaxPtZ){

$CornerPT[5] = $pointNum_Seperate[$j];

}
}else if($tempPtPos[0] == $MaxPtX ){

if($tempPtPos[2] == $MinPtZ){

$CornerPT[6] = $pointNum_Seperate[$j];

}else if($tempPtPos[2] == $MaxPtZ){

$CornerPT[7] = $pointNum_Seperate[$j];

}

}

}
}

}

return $CornerPT;

}

//面片匹配的主函数
global proc FXTD_MatchPlane(){
global string $target;
////////////////////////////////////////////////////////////
//////////// 根据选择的点生成面 //////////////
///////////////////////////////////////////////////////////

string $sel[] = `ls -sl `;

float $vtx_position[] = {};//清空数组

//将收集的点的位置信息批量放进数组中
for($j = 0; $j < size($sel); $j++ )
{
FXTD_floatPush($vtx_position,`xform -q -ws -t $sel[$j]`);
}

print $vtx_position;

string $temp_tri[];

//通过数据生成三角面
string $temp_tri[] = `polyCreateFacet -ch off -tx 1 -s 1
-p $vtx_position[0] $vtx_position[1] $vtx_position[2]
-p $vtx_position[3] $vtx_position[4] $vtx_position[5]
-p $vtx_position[6] $vtx_position[7] $vtx_position[8]`;

////////////////////////////////////////////////////////////
//////////// 根据生成的面匹配旋转角度 //////////////
///////////////////////////////////////////////////////////

//获取法线角度信息
string $NormalFaceStr[] = `polyInfo -fn $temp_tri[0]`;
string $buffer[];

//分离出需要的法线数据
tokenize $NormalFaceStr[0] " " $buffer;

float $Normal[];
$Normal[0] = $buffer[2];
$Normal[1] = $buffer[3];
$Normal[2] = $buffer[4];

//获取旋转角度
float $rotation[] = `angleBetween -euler -v1 1.0 0.0 0.0 -v2 $Normal[0] $Normal[1] $Normal[2]`;

////////////////////////////////////////////////////////////
//////////// 将旋转角度赋予到目标模型上 /////////////
///////////////////////////////////////////////////////////

// file -i -ns "store" `textField -q -tx model_path`;

//用变量记录导入的物体
select -r ( `textField -q -tx model_name`) ;

string $storeSel[] = `ls -sl `;

select -r $storeSel[size($storeSel)-1];

duplicate -rr;

string $storeSel[] = `ls -sl `;

$target = $storeSel[0];
//记录左边和右边的点
int $leftNum = `intField -q -v leftCorner`;
int $rightNum = `intField -q -v rightCorner`;
string $leftCorner = $target + ".vtx["+ $leftNum + "]";
string $rightCorner = $target + ".vtx["+ $rightNum + "]";

int $versNum[] = `polyEvaluate -v $target`;

string $leftPtSel[] ;
string $rightPtSel[] ;

for($j = 0; $j < $versNum[0]; $j++ ){

$tempPtPos = `xform -q -ws -t ($target + ".vtx[" + $j +"]")`;

//无关变量赋予无关值
$leftPtSel[$j] = -1;
$rightPtSel[$j] = -1;
//区分左边和右边的点
if($tempPtPos[2] > 0){//判断Z轴
$leftPtSel[$j] = $j;
}else{
$rightPtSel[$j] = $j;
}

}

//矫正物体的旋转角度
select -r $target;

rotate -a -ws -fo 0 $rotation[1] 0 ;

////////////////////////////////////////////////////////////
//////////////// 匹配需要吸附的点 //////////////////
///////////////////////////////////////////////////////////

select -r $leftCorner;

//目标模型的左下角点的面片
ConvertSelectionToFaces;
string $selFace[] = `ls -sl `;

int $CornerPtnum[] = FXTD_computeBoudingPt($selFace[0]);
int $TriPtnum[] = FXTD_computeBoudingPt($temp_tri[0]);

int $num_1 = -1;
int $num_2 = -1;

//找到互相匹配的点 进行吸附
for($j = 0; $j < 4; $j++){

if($CornerPtnum[$j] != -1 && $TriPtnum[$j] != -1){

if($num_1 == -1){
$num_1 = $j;
}else if($num_2 == -1){
$num_2 = $j;
}

}

}

//第一次吸附点
select -r ($target + ".vtx["+ $CornerPtnum[$num_1] + "]");

select -tgl ($temp_tri[0] + ".vtx["+ $TriPtnum[$num_1] + "]");

SnapPointToPoint;

float $left_vtx_position[] = {};//清空数组
float $right_vtx_position[] = {};//清空数组
//记录当前的位置信息
if($CornerPtnum[$num_1] == $leftNum){//如果是吸附左边的点

for($j = 0; $j < $versNum[0]; $j++ ){

if($leftPtSel[$j] != -1 ){

FXTD_floatPush($left_vtx_position,`xform -q -ws -t ($target + ".vtx[" + $j +"]")`);

}

}

}else{

for($j = 0; $j < $versNum[0]; $j++ ){

if($rightPtSel[$j] != -1 ){

FXTD_floatPush($right_vtx_position,`xform -q -ws -t ($target + ".vtx[" + $j +"]")`);

}

}

}


select -r ($target + ".vtx["+ $CornerPtnum[$num_2] + "]");

select -tgl ($temp_tri[0] + ".vtx["+ $TriPtnum[$num_2] + "]");

SnapPointToPoint;

//复原上面记录的位置
int $temp = 0;
if($CornerPtnum[$num_1] == $leftNum){//如果是吸附左边的点

for($j = 0; $j < $versNum[0]; $j++ ){

if($leftPtSel[$j] != -1 ){

select -r ($target + ".vtx[" + $j +"]");
move -a $left_vtx_position[$temp*3] $left_vtx_position[$temp*3+1] $left_vtx_position[$temp*3+2];
$temp++;

}

}

}else{

for($j = 0; $j < $versNum[0]; $j++ ){

if($rightPtSel[$j] != -1 ){

select -r ($target + ".vtx[" + $j +"]");
move -a $right_vtx_position[$temp*3] $right_vtx_position[$temp*3+1] $right_vtx_position[$temp*3+2];
$temp++;

}

}

}

////////////////////////////////////////////////////////////
//////////////// 添加偏移避免重面 //////////////////
///////////////////////////////////////////////////////////

float $offset = `floatField -q -v offset`;

select -r $target;

move -r ($Normal[0]*$offset) ($Normal[1]*$offset) ($Normal[2]*$offset);

//获取三角面的中心位置
global float $rightPtPos[];
global float $leftPtPos[];
$leftPtPos = `xform -q -ws -t ($temp_tri[0] + ".vtx["+ $TriPtnum[$num_1] + "]")`;
$rightPtPos = `xform -q -ws -t ($temp_tri[0] + ".vtx["+ $TriPtnum[$num_2] + "]")`;
//删除临时三角面
delete $temp_tri[0];

}

// global proc FXTD_importModel(){
// file -i -ns "store" `textField -q -tx model_path`;
// }
global proc FXTD_planeFix(){
global string $target;
global float $rightPtPos[];
global float $leftPtPos[];

select $target;

move -a (($leftPtPos[0]+$rightPtPos[0])/2) (($leftPtPos[1]+$rightPtPos[1])/2)
(($leftPtPos[2]+$rightPtPos[2])/2) ($target+ ".scalePivot") ($target+ ".rotatePivot");

rotate -r -ws -fo 0 180 0 ;
}

if (`window -ex FXTD_MatchPlaneWin` != true){

window -w 310 -h 100 -t ("面片自动匹配 - 插件") -in "将面片自动匹配模型上(能自动拉伸模型)" -s true -tb true FXTD_MatchPlaneWin;

columnLayout FXTD_mainCol;

separator -style "in" -w 300 -h 8;
rowColumnLayout -nc 2 -cw 1 70 -cw 2 230;
text -l "偏移值: " -al "right";
floatField -v 0 -w 60 -min 0 offset;
setParent "..";
rowColumnLayout -nc 2 -cw 1 70 -cw 2 230;
text -l "模型名称: " -al "right";
textField -tx "store2:store" model_name ;
setParent "..";
rowColumnLayout -nc 2 -cw 1 70 -cw 2 230;
text -l "左下角顶点: " -al "right";
intField -v 3 -w 60 -min 0 leftCorner;
setParent "..";
rowColumnLayout -nc 2 -cw 1 70 -cw 2 230;
text -l "右下角顶点: " -al "right";
intField -v 2 -w 60 -min 0 rightCorner;
setParent "..";
separator -style "none" -w 300 -h 4;
button -l "导入模型" -al "center" -w 300 -c ("Import;") -ann "" FXTD_Import;
button -l "一键匹配" -al "center" -w 300 -c ("FXTD_MatchPlane();") -ann "" FXTD_Match;
button -l "一键修正" -al "center" -w 300 -c ("FXTD_planeFix();") -ann "" FXTD_Fix;
showWindow FXTD_MatchPlaneWin;
}else // else just pop it up from being minimized again
{
showWindow FXTD_MatchPlaneWin;
}