pyjallib 0.1.9__py3-none-any.whl → 0.1.10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyjallib/__init__.py +1 -1
- pyjallib/max/ConfigFiles/Default_3DSMaxNamingConfig.json +161 -0
- pyjallib/max/__init__.py +14 -2
- pyjallib/max/anim.py +60 -36
- pyjallib/max/autoClavicle.py +97 -132
- pyjallib/max/autoClavicleChain.py +173 -0
- pyjallib/max/bip.py +211 -14
- pyjallib/max/bone.py +341 -16
- pyjallib/max/groinBone.py +116 -77
- pyjallib/max/groinBoneChain.py +173 -0
- pyjallib/max/header.py +42 -6
- pyjallib/max/helper.py +3 -21
- pyjallib/max/hip.py +239 -366
- pyjallib/max/kneeBone.py +517 -0
- pyjallib/max/macro/jal_macro_align.py +11 -10
- pyjallib/max/macro/jal_macro_bone.py +2 -1
- pyjallib/max/macro/jal_macro_constraint.py +2 -1
- pyjallib/max/macro/jal_macro_helper.py +2 -1
- pyjallib/max/macro/jal_macro_link.py +2 -1
- pyjallib/max/macro/jal_macro_select.py +2 -1
- pyjallib/max/mirror.py +1 -1
- pyjallib/max/twistBone.py +258 -475
- pyjallib/max/twistBoneChain.py +162 -0
- pyjallib/max/volumeBone.py +273 -0
- pyjallib/max/volumeBoneChain.py +363 -0
- pyjallib/namePart.py +16 -16
- pyjallib/nameToPath.py +1 -1
- pyjallib/naming.py +15 -16
- pyjallib/namingConfig.py +3 -3
- {pyjallib-0.1.9.dist-info → pyjallib-0.1.10.dist-info}/METADATA +1 -1
- pyjallib-0.1.10.dist-info/RECORD +46 -0
- pyjallib/max/volumePreserveBone.py +0 -209
- pyjallib/p4module.py +0 -488
- pyjallib-0.1.9.dist-info/RECORD +0 -41
- {pyjallib-0.1.9.dist-info → pyjallib-0.1.10.dist-info}/WHEEL +0 -0
pyjallib/max/twistBone.py
CHANGED
@@ -3,7 +3,11 @@
|
|
3
3
|
|
4
4
|
"""
|
5
5
|
트위스트 뼈대(Twist Bone) 모듈 - 3ds Max용 트위스트 뼈대 생성 관련 기능 제공
|
6
|
-
|
6
|
+
|
7
|
+
이 모듈은 3D 캐릭터 리깅에서 사용되는 트위스트 뼈대를 생성하고 제어하는 기능을 제공합니다.
|
8
|
+
트위스트 뼈대는 팔이나 다리의 회전 움직임을 더욱 자연스럽게 표현하기 위해 사용됩니다.
|
9
|
+
원본 MAXScript의 twistBone.ms를 Python으로 변환하였으며, pymxs 모듈 기반으로 구현되어
|
10
|
+
3ds Max 내에서 스크립트 형태로 실행할 수 있습니다.
|
7
11
|
"""
|
8
12
|
|
9
13
|
from pymxs import runtime as rt
|
@@ -19,526 +23,305 @@ from .bone import Bone
|
|
19
23
|
class TwistBone:
|
20
24
|
"""
|
21
25
|
트위스트 뼈대(Twist Bone) 관련 기능을 제공하는 클래스.
|
26
|
+
|
27
|
+
이 클래스는 3ds Max에서 트위스트 뼈대를 생성하고 제어하는 다양한 기능을 제공합니다.
|
22
28
|
MAXScript의 _TwistBone 구조체 개념을 Python으로 재구현한 클래스이며,
|
23
29
|
3ds Max의 기능들을 pymxs API를 통해 제어합니다.
|
30
|
+
|
31
|
+
트위스트 뼈대는 상체(Upper)와 하체(Lower) 두 가지 타입으로 생성이 가능하며,
|
32
|
+
각각 다른 회전 표현식을 사용하여 자연스러운 회전 움직임을 구현합니다.
|
24
33
|
"""
|
25
34
|
|
26
|
-
def __init__(self, nameService=None, animService=None,
|
35
|
+
def __init__(self, nameService=None, animService=None, constraintService=None, bipService=None, boneService=None):
|
27
36
|
"""
|
28
|
-
클래스 초기화.
|
37
|
+
TwistBone 클래스 초기화.
|
38
|
+
|
39
|
+
의존성 주입 방식으로 필요한 서비스들을 외부에서 제공받거나 내부에서 생성합니다.
|
40
|
+
서비스들이 제공되지 않을 경우 각 서비스의 기본 인스턴스를 생성하여 사용합니다.
|
29
41
|
|
30
42
|
Args:
|
31
|
-
nameService: 이름 처리
|
32
|
-
animService: 애니메이션
|
33
|
-
|
34
|
-
bipService: 바이페드
|
43
|
+
nameService (Name, optional): 이름 처리 서비스. 기본값은 None이며, 제공되지 않으면 새로 생성됩니다.
|
44
|
+
animService (Anim, optional): 애니메이션 서비스. 기본값은 None이며, 제공되지 않으면 새로 생성됩니다.
|
45
|
+
constraintService (Constraint, optional): 제약 서비스. 기본값은 None이며, 제공되지 않으면 새로 생성됩니다.
|
46
|
+
bipService (Bip, optional): 바이페드 서비스. 기본값은 None이며, 제공되지 않으면 새로 생성됩니다.
|
47
|
+
boneService (Bone, optional): 뼈대 서비스. 기본값은 None이며, 제공되지 않으면 새로 생성됩니다.
|
35
48
|
"""
|
36
49
|
self.name = nameService if nameService else Name()
|
37
50
|
self.anim = animService if animService else Anim()
|
38
51
|
# Ensure dependent services use the potentially newly created instances
|
39
|
-
self.const =
|
52
|
+
self.const = constraintService if constraintService else Constraint(nameService=self.name)
|
40
53
|
self.bip = bipService if bipService else Bip(animService=self.anim, nameService=self.name)
|
41
54
|
self.bone = boneService if boneService else Bone(nameService=self.name, animService=self.anim)
|
42
55
|
|
43
|
-
#
|
44
|
-
self.
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
"
|
52
|
-
"
|
53
|
-
"
|
54
|
-
"
|
55
|
-
"
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
"
|
61
|
-
"
|
62
|
-
"
|
63
|
-
)
|
64
|
-
|
65
|
-
# 종아리(Calf) 표현식
|
66
|
-
self.calfExpression = (
|
67
|
-
"try(\n"
|
68
|
-
"TM=Limb.transform*inverse Limb.parent.transform\n"
|
69
|
-
"vector=normalize (cross TM.row1 [1,0,0])\n"
|
70
|
-
"angle=acos (normalize TM.row1).x\n"
|
71
|
-
"TM.rotation*(quat -angle vector))\n"
|
72
|
-
"catch((quat 0 0 0 1))"
|
73
|
-
)
|
74
|
-
|
75
|
-
# 종아리 추가 표현식
|
76
|
-
self.calfExtraExpression = (
|
77
|
-
"try(dependson TB\n"
|
78
|
-
"TB.rotation.controller[1].value\n"
|
79
|
-
")catch((quat 0 0 0 1))"
|
80
|
-
)
|
81
|
-
|
82
|
-
# 상완(Upper Arm) 표현식
|
83
|
-
self.upperArmExpression = (
|
84
|
-
"try(\n"
|
85
|
-
"TM=Limb.transform*inverse Limb.parent.transform\n"
|
86
|
-
"vector=normalize (cross TM.row1 [1,0,0])\n"
|
87
|
-
"angle=acos (normalize TM.row1).x\n"
|
88
|
-
"(quat angle vector)*inverse TM.rotation)\n"
|
89
|
-
"catch((quat 0 0 0 1))"
|
90
|
-
)
|
91
|
-
|
92
|
-
# 상완 추가 표현식
|
93
|
-
self.upperArmExtraExpression = (
|
94
|
-
"try(\n"
|
95
|
-
"(Limb.transform*inverse LimbParent.transform).rotation\n"
|
96
|
-
")catch((quat 0 0 0 1))"
|
56
|
+
# 객체 속성 초기화
|
57
|
+
self.limb = None
|
58
|
+
self.child = None
|
59
|
+
self.twistNum = 0
|
60
|
+
self.bones = []
|
61
|
+
self.twistType = ""
|
62
|
+
|
63
|
+
self.upperTwistBoneExpression = (
|
64
|
+
"localTm = limb.transform * (inverse limbParent.transform)\n"
|
65
|
+
"tm = localTm * inverse(localRefTm)\n"
|
66
|
+
"\n"
|
67
|
+
"q = tm.rotation\n"
|
68
|
+
"\n"
|
69
|
+
"axis = [1,0,0]\n"
|
70
|
+
"proj = (dot q.axis axis) * axis\n"
|
71
|
+
"twist = quat q.angle proj\n"
|
72
|
+
"twist = normalize twist\n"
|
73
|
+
"--swing = tm.rotation * (inverse twist)\n"
|
74
|
+
"\n"
|
75
|
+
"inverse twist\n"
|
97
76
|
)
|
98
77
|
|
99
|
-
|
100
|
-
|
101
|
-
"
|
102
|
-
"
|
103
|
-
"
|
104
|
-
"
|
105
|
-
"
|
106
|
-
"
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
"
|
112
|
-
"TM=(matrix3 [1,0,0] [0,0,1] [0,-1,0] [0,0,0])*Limb.transform*inverse Limb.parent.transform\n"
|
113
|
-
"vector=normalize (cross TM.row1 [1,0,0])\n"
|
114
|
-
"angle=acos (normalize TM.row1).x\n"
|
115
|
-
"TM.rotation*(quat -angle vector))\n"
|
116
|
-
"catch((quat 0 0 0 1))"
|
117
|
-
)
|
118
|
-
|
119
|
-
# 전완 추가 표현식
|
120
|
-
self.foreArmExtraExpression = (
|
121
|
-
"try(dependson TB\n"
|
122
|
-
"TB.rotation.controller[1].value\n"
|
123
|
-
")catch((quat 0 0 0 1))"
|
124
|
-
)
|
125
|
-
|
126
|
-
def create_bones(self, inObj, inChild, inTwistNum, inExpression, inExtraExpression, inControllerLimb, inWeightVar):
|
127
|
-
"""
|
128
|
-
트위스트 뼈대 체인 생성
|
129
|
-
|
130
|
-
Args:
|
131
|
-
inObj: 시작 객체
|
132
|
-
inChild: 끝 객체
|
133
|
-
inTwistNum: 트위스트 뼈대 개수
|
134
|
-
inExpression: 기본 회전 표현식
|
135
|
-
inExtraExpression: 추가 회전 표현식
|
136
|
-
inControllerLimb: 컨트롤러 대상 팔다리
|
137
|
-
inWeightVar: 가중치
|
138
|
-
|
139
|
-
Returns:
|
140
|
-
생성된 트위스트 뼈대 체인 배열
|
141
|
-
"""
|
142
|
-
Limb = inObj
|
143
|
-
distanceVar = rt.distance(Limb, inChild)
|
144
|
-
|
145
|
-
TBExpression = inExpression
|
146
|
-
ControllerLimb = inControllerLimb
|
147
|
-
weightVar = inWeightVar
|
148
|
-
|
149
|
-
boneChainArray = []
|
150
|
-
|
151
|
-
# 첫 번째 트위스트 뼈대 생성
|
152
|
-
TwistBone = rt.BoneSys.createBone(
|
153
|
-
Limb.transform.position,
|
154
|
-
inChild.transform.position,
|
155
|
-
rt.Point3(0, 0, 1)
|
78
|
+
self.lowerTwistBoneExpression = (
|
79
|
+
"localTm = limb.transform * (inverse limbParent.transform)\n"
|
80
|
+
"tm = localTm * inverse(localRefTm)\n"
|
81
|
+
"\n"
|
82
|
+
"q = tm.rotation\n"
|
83
|
+
"\n"
|
84
|
+
"axis = [1,0,0]\n"
|
85
|
+
"proj = (dot q.axis axis) * axis\n"
|
86
|
+
"twist = quat q.angle proj\n"
|
87
|
+
"twist = normalize twist\n"
|
88
|
+
"--swing = tm.rotation * (inverse twist)\n"
|
89
|
+
"\n"
|
90
|
+
"twist\n"
|
156
91
|
)
|
157
|
-
boneName = self.name.get_string(inObj.name) + "Twist"
|
158
|
-
TwistBone.name = self.name.replace_Index(boneName, "0")
|
159
|
-
TwistBone.transform = Limb.transform
|
160
|
-
TwistBone.parent = Limb
|
161
|
-
TwistBone.length = distanceVar / inTwistNum
|
162
|
-
TwistBone.width = distanceVar / 8
|
163
|
-
TwistBone.height = TwistBone.width
|
164
|
-
TwistBone.taper = 0
|
165
|
-
TwistBone.sidefins = False
|
166
|
-
TwistBone.frontfin = False
|
167
|
-
TwistBone.backfin = False
|
168
|
-
|
169
|
-
# 회전 컨트롤러 설정
|
170
|
-
TBRotListController = self.const.assign_rot_list(TwistBone)
|
171
|
-
TBController = rt.Rotation_Script()
|
172
|
-
TBController.addNode("Limb", ControllerLimb)
|
173
|
-
TBController.setExpression(TBExpression)
|
174
|
-
|
175
|
-
rt.setPropertyController(TBRotListController, "Available", TBController)
|
176
|
-
TBRotListController.delete(1)
|
177
|
-
TBRotListController.setActive(TBRotListController.count)
|
178
|
-
TBRotListController.weight[0] = weightVar
|
179
|
-
|
180
|
-
boneChainArray.append(TwistBone)
|
181
|
-
|
182
|
-
# 추가 회전 컨트롤러 설정
|
183
|
-
TBExtraController = rt.Rotation_Script()
|
184
|
-
if rt.matchPattern(inExtraExpression, pattern="*\nTB.*"):
|
185
|
-
TBExtraController.addNode("TB", TwistBone)
|
186
|
-
else:
|
187
|
-
TBExtraController.addNode("Limb", Limb)
|
188
|
-
TBExtraController.addNode("LimbParent", TwistBone)
|
189
|
-
TBExtraController.setExpression(inExtraExpression)
|
190
|
-
|
191
|
-
PrevTBE = TwistBone
|
192
|
-
|
193
|
-
# 추가 트위스트 뼈대 생성 (2개 이상인 경우)
|
194
|
-
if inTwistNum > 1:
|
195
|
-
for j in range(2, inTwistNum):
|
196
|
-
TwistBoneExtra = rt.BoneSys.createBone(
|
197
|
-
rt.Point3(0, 0, 0),
|
198
|
-
rt.Point3(1, 0, 0),
|
199
|
-
rt.Point3(0, 0, 1)
|
200
|
-
)
|
201
|
-
matAux = rt.matrix3(1)
|
202
|
-
matAux.position = rt.Point3(distanceVar/inTwistNum, 0, 0)
|
203
|
-
TwistBoneExtra.transform = matAux * PrevTBE.transform
|
204
|
-
TwistBoneExtra.name = self.name.replace_Index(boneName, str(j-1))
|
205
|
-
TwistBoneExtra.parent = PrevTBE
|
206
|
-
TwistBoneExtra.length = distanceVar / inTwistNum
|
207
|
-
TwistBoneExtra.width = PrevTBE.width
|
208
|
-
TwistBoneExtra.height = PrevTBE.height
|
209
|
-
TwistBoneExtra.taper = 0
|
210
|
-
TwistBoneExtra.sidefins = False
|
211
|
-
TwistBoneExtra.frontfin = False
|
212
|
-
TwistBoneExtra.backfin = False
|
213
|
-
|
214
|
-
# 회전 컨트롤러 설정
|
215
|
-
TBExtraRotListController = self.const.assign_rot_list(TwistBoneExtra)
|
216
|
-
rt.setPropertyController(TBExtraRotListController, "Available", TBExtraController)
|
217
|
-
TBExtraRotListController.delete(1)
|
218
|
-
TBExtraRotListController.setActive(TBExtraRotListController.count)
|
219
|
-
TBExtraRotListController.weight[0] = 100 / (inTwistNum - 1)
|
220
|
-
|
221
|
-
PrevTBE = TwistBoneExtra
|
222
|
-
boneChainArray.append(TwistBoneExtra)
|
223
|
-
|
224
|
-
# 마지막 트위스트 뼈대 생성
|
225
|
-
TwistBoneEnd = rt.BoneSys.createBone(
|
226
|
-
rt.Point3(0, 0, 0),
|
227
|
-
rt.Point3(1, 0, 0),
|
228
|
-
rt.Point3(0, 0, 1)
|
229
|
-
)
|
230
|
-
matAux = rt.matrix3(1)
|
231
|
-
matAux.position = rt.Point3(distanceVar/inTwistNum, 0, 0)
|
232
|
-
TwistBoneEnd.transform = matAux * PrevTBE.transform
|
233
|
-
TwistBoneEnd.name = self.name.replace_Index(boneName, str(inTwistNum-1))
|
234
|
-
TwistBoneEnd.parent = inObj
|
235
|
-
TwistBoneEnd.length = distanceVar / inTwistNum
|
236
|
-
TwistBoneEnd.width = PrevTBE.width
|
237
|
-
TwistBoneEnd.height = PrevTBE.height
|
238
|
-
TwistBoneEnd.taper = 0
|
239
|
-
TwistBoneEnd.sidefins = False
|
240
|
-
TwistBoneEnd.frontfin = False
|
241
|
-
TwistBoneEnd.backfin = False
|
242
92
|
|
243
|
-
|
244
|
-
|
245
|
-
return boneChainArray
|
246
|
-
|
247
|
-
def reorder_bones(self, inBoneChainArray):
|
93
|
+
def reset(self):
|
248
94
|
"""
|
249
|
-
|
95
|
+
클래스의 주요 컴포넌트들을 초기화합니다.
|
96
|
+
서비스가 아닌 클래스 자체의 작업 데이터를 초기화하는 함수입니다.
|
250
97
|
|
251
|
-
Args:
|
252
|
-
inBoneChainArray: 재배치할 뼈대 체인 배열
|
253
|
-
|
254
98
|
Returns:
|
255
|
-
|
256
|
-
"""
|
257
|
-
boneChainArray = rt.deepcopy(inBoneChainArray)
|
258
|
-
returnBoneArray = []
|
259
|
-
|
260
|
-
# 첫 번째와 마지막 뼈대 가져오기
|
261
|
-
firstBone = boneChainArray[0]
|
262
|
-
lastBone = boneChainArray[-1]
|
263
|
-
returnBoneArray.append(lastBone)
|
264
|
-
|
265
|
-
# 뼈대가 2개 이상인 경우 위치 조정
|
266
|
-
if len(boneChainArray) > 1:
|
267
|
-
self.anim.move_local(firstBone, firstBone.length, 0, 0)
|
268
|
-
self.anim.move_local(lastBone, -(firstBone.length * (len(boneChainArray)-1)), 0, 0)
|
269
|
-
|
270
|
-
# 중간 뼈대들을 새 배열에 추가
|
271
|
-
for i in range(len(boneChainArray)-1):
|
272
|
-
returnBoneArray.append(boneChainArray[i])
|
273
|
-
|
274
|
-
# 새로운 순서대로 이름 재설정
|
275
|
-
for i in range(len(returnBoneArray)):
|
276
|
-
returnBoneArray[i].name = self.name.replace_Index(boneChainArray[i].name, str(i))
|
277
|
-
|
278
|
-
return returnBoneArray
|
279
|
-
|
280
|
-
def create_upperArm_type(self, inObj, inTwistNum):
|
99
|
+
self: 메소드 체이닝을 위한 자기 자신 반환
|
281
100
|
"""
|
282
|
-
|
101
|
+
self.limb = None
|
102
|
+
self.child = None
|
103
|
+
self.twistNum = 0
|
104
|
+
self.bones = []
|
105
|
+
self.twistType = ""
|
283
106
|
|
284
|
-
|
285
|
-
inObj: 상완 뼈대 객체
|
286
|
-
inTwistNum: 트위스트 뼈대 개수
|
107
|
+
return self
|
287
108
|
|
288
|
-
|
289
|
-
생성된 트위스트 뼈대 체인 또는 False(실패 시)
|
109
|
+
def create_upper_limb_bones(self, inObj, inChild, twistNum=4):
|
290
110
|
"""
|
291
|
-
|
292
|
-
return False
|
293
|
-
|
294
|
-
weightVal = 100.0
|
295
|
-
|
296
|
-
return self.create_bones(
|
297
|
-
inObj,
|
298
|
-
inObj.children[0],
|
299
|
-
inTwistNum,
|
300
|
-
self.upperArmExpression,
|
301
|
-
self.upperArmExtraExpression,
|
302
|
-
inObj,
|
303
|
-
weightVal
|
304
|
-
)
|
305
|
-
|
306
|
-
def create_foreArm_type(self, inObj, inTwistNum, reorder=True):
|
307
|
-
"""
|
308
|
-
전완(Forearm) 타입의 트위스트 뼈대 생성
|
309
|
-
|
310
|
-
Args:
|
311
|
-
inObj: 전완 뼈대 객체
|
312
|
-
inTwistNum: 트위스트 뼈대 개수
|
313
|
-
side: 좌/우측 ("left" 또는 "right", 기본값: "left")
|
314
|
-
|
315
|
-
Returns:
|
316
|
-
생성된 트위스트 뼈대 체인 또는 False(실패 시)
|
317
|
-
"""
|
318
|
-
if inObj.parent is None or inObj.children.count == 0:
|
319
|
-
return False
|
320
|
-
|
321
|
-
controllerLimb = None
|
322
|
-
weightVal = 100.0
|
111
|
+
상체(팔, 어깨 등) 부분의 트위스트 뼈대를 생성하는 메소드.
|
323
112
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
if self.bip.is_left_node(inObj):
|
329
|
-
controllerLimb = rt.biped.getNode(inObj.controller.rootNode, rt.Name("lArm"), link=4)
|
330
|
-
else:
|
331
|
-
controllerLimb = rt.biped.getNode(inObj.controller.rootNode, rt.Name("rArm"), link=4)
|
332
|
-
|
333
|
-
if inTwistNum > 1:
|
334
|
-
weightVal = 100 / (inTwistNum - 1)
|
335
|
-
|
336
|
-
createdBones = self.create_bones(
|
337
|
-
inObj,
|
338
|
-
controllerLimb,
|
339
|
-
inTwistNum,
|
340
|
-
TBExpression,
|
341
|
-
self.foreArmExtraExpression,
|
342
|
-
controllerLimb,
|
343
|
-
weightVal
|
344
|
-
)
|
345
|
-
|
346
|
-
return self.reorder_bones(createdBones) if reorder else createdBones
|
347
|
-
|
348
|
-
def create_thigh_type(self, inObj, inTwistNum):
|
349
|
-
"""
|
350
|
-
허벅지(Thigh) 타입의 트위스트 뼈대 생성
|
113
|
+
상체용 트위스트 뼈대는 부모 객체(inObj)의 위치에서 시작하여
|
114
|
+
자식 객체(inChild) 방향으로 여러 개의 뼈대를 생성합니다.
|
115
|
+
생성된 뼈대들은 스크립트 컨트롤러를 통해 자동으로 회전되어
|
116
|
+
자연스러운 트위스트 움직임을 표현합니다.
|
351
117
|
|
352
118
|
Args:
|
353
|
-
inObj:
|
354
|
-
|
355
|
-
|
356
|
-
Returns:
|
357
|
-
생성된 트위스트 뼈대 체인 또는 False(실패 시)
|
358
|
-
"""
|
359
|
-
if inObj.parent is None or inObj.children.count == 0:
|
360
|
-
return False
|
361
|
-
|
362
|
-
controllerLimb = None
|
363
|
-
weightVal = 100
|
364
|
-
|
365
|
-
return self.create_bones(
|
366
|
-
inObj,
|
367
|
-
inObj.children[0],
|
368
|
-
inTwistNum,
|
369
|
-
self.thighExpression,
|
370
|
-
self.thighExtraExpression,
|
371
|
-
inObj,
|
372
|
-
weightVal
|
373
|
-
)
|
374
|
-
|
375
|
-
def create_calf_type(self, inObj, inTwistNum, reorder=True):
|
376
|
-
"""
|
377
|
-
종아리(Calf) 타입의 트위스트 뼈대 생성
|
119
|
+
inObj: 트위스트 뼈대의 부모 객체(뼈). 일반적으로 상완 또는 대퇴부에 해당합니다.
|
120
|
+
inChild: 자식 객체(뼈). 일반적으로 전완 또는 하퇴부에 해당합니다.
|
121
|
+
twistNum (int, optional): 생성할 트위스트 뼈대의 개수. 기본값은 4입니다.
|
378
122
|
|
379
|
-
Args:
|
380
|
-
inObj: 종아리 뼈대 객체
|
381
|
-
inTwistNum: 트위스트 뼈대 개수
|
382
|
-
side: 좌/우측 ("left" 또는 "right", 기본값: "left")
|
383
|
-
|
384
123
|
Returns:
|
385
|
-
생성된 트위스트 뼈대
|
124
|
+
dict: 생성된 트위스트 뼈대 정보를 담고 있는 사전 객체입니다.
|
125
|
+
"Bones": 생성된 뼈대 객체들의 배열
|
126
|
+
"Type": "Upper" (상체 타입)
|
127
|
+
"Limb": 부모 객체 참조
|
128
|
+
"Child": 자식 객체 참조
|
129
|
+
"TwistNum": 생성된 트위스트 뼈대 개수
|
386
130
|
"""
|
387
|
-
|
388
|
-
|
131
|
+
limb = inObj
|
132
|
+
distance = rt.distance(limb, inChild)
|
133
|
+
facingDirVec = inChild.transform.position - inObj.transform.position
|
134
|
+
inObjXAxisVec = inObj.objectTransform.row1
|
135
|
+
distanceDir = 1.0 if rt.dot(inObjXAxisVec, facingDirVec) > 0 else -1.0
|
136
|
+
offssetAmount = (distance / twistNum) * distanceDir
|
137
|
+
weightVal = 100.0 / (twistNum-1)
|
389
138
|
|
390
|
-
|
391
|
-
weightVal = 100
|
392
|
-
|
393
|
-
# Biped 컨트롤러 노드 설정
|
394
|
-
if self.bip.is_left_node(inObj):
|
395
|
-
controllerLimb = rt.biped.getNode(inObj.controller.rootNode, rt.Name("lLeg"), link=3)
|
396
|
-
else:
|
397
|
-
controllerLimb = rt.biped.getNode(inObj.controller.rootNode, rt.Name("rLeg"), link=3)
|
398
|
-
|
399
|
-
# 복수 뼈대인 경우 가중치 조정
|
400
|
-
if inTwistNum > 1:
|
401
|
-
weightVal = 100 / (inTwistNum - 1)
|
402
|
-
|
403
|
-
createdBones = self.create_bones(
|
404
|
-
inObj,
|
405
|
-
controllerLimb,
|
406
|
-
inTwistNum,
|
407
|
-
self.calfExpression,
|
408
|
-
self.calfExtraExpression,
|
409
|
-
controllerLimb,
|
410
|
-
weightVal
|
411
|
-
)
|
412
|
-
|
413
|
-
return self.reorder_bones(createdBones) if reorder else createdBones
|
414
|
-
|
415
|
-
def create_bend_type(self):
|
416
|
-
"""
|
417
|
-
굽힘(Bend) 타입의 트위스트 뼈대 생성
|
418
|
-
(아직 구현되지 않음)
|
419
|
-
"""
|
420
|
-
pass
|
421
|
-
|
422
|
-
def get_upperArm_type(self, inObj):
|
423
|
-
"""
|
424
|
-
상완(Upper Arm) 타입의 트위스트 뼈대 가져오기
|
139
|
+
boneChainArray = []
|
425
140
|
|
426
|
-
|
427
|
-
|
141
|
+
# 첫 번째 트위스트 뼈대 생성
|
142
|
+
boneName = self.name.add_suffix_to_real_name(inObj.name, self.name._get_filtering_char(inObj.name) + "Twist")
|
143
|
+
if inObj.name[0].islower():
|
144
|
+
boneName = boneName.lower()
|
145
|
+
twistBone = self.bone.create_nub_bone(boneName, 2)
|
146
|
+
twistBone.name = self.name.replace_name_part("Index", boneName, "1")
|
147
|
+
twistBone.name = self.name.remove_name_part("Nub", twistBone.name)
|
148
|
+
twistBone.transform = limb.transform
|
149
|
+
twistBone.parent = limb
|
150
|
+
twistBoneLocalRefTM = limb.transform * rt.inverse(limb.parent.transform)
|
151
|
+
|
152
|
+
twistBoneRotListController = self.const.assign_rot_list(twistBone)
|
153
|
+
twistBoneController = rt.Rotation_Script()
|
154
|
+
twistBoneController.addConstant("localRefTm", twistBoneLocalRefTM)
|
155
|
+
twistBoneController.addNode("limb", limb)
|
156
|
+
twistBoneController.addNode("limbParent", limb.parent)
|
157
|
+
twistBoneController.setExpression(self.upperTwistBoneExpression)
|
158
|
+
twistBoneController.update()
|
159
|
+
|
160
|
+
rt.setPropertyController(twistBoneRotListController, "Available", twistBoneController)
|
161
|
+
twistBoneRotListController.delete(1)
|
162
|
+
twistBoneRotListController.setActive(twistBoneRotListController.count)
|
163
|
+
twistBoneRotListController.weight[0] = 100.0
|
164
|
+
|
165
|
+
boneChainArray.append(twistBone)
|
166
|
+
|
167
|
+
if twistNum > 1:
|
168
|
+
lastBone = self.bone.create_nub_bone(boneName, 2)
|
169
|
+
lastBone.name = self.name.replace_name_part("Index", boneName, str(twistNum))
|
170
|
+
lastBone.name = self.name.remove_name_part("Nub", lastBone.name)
|
171
|
+
lastBone.transform = limb.transform
|
172
|
+
lastBone.parent = limb
|
173
|
+
self.anim.move_local(lastBone, offssetAmount*(twistNum-1), 0, 0)
|
428
174
|
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
175
|
+
if twistNum > 2:
|
176
|
+
for i in range(1, twistNum-1):
|
177
|
+
twistExtraBone = self.bone.create_nub_bone(boneName, 2)
|
178
|
+
twistExtraBone.name = self.name.replace_name_part("Index", boneName, str(i+1))
|
179
|
+
twistExtraBone.name = self.name.remove_name_part("Nub", twistExtraBone.name)
|
180
|
+
twistExtraBone.transform = limb.transform
|
181
|
+
twistExtraBone.parent = limb
|
182
|
+
self.anim.move_local(twistExtraBone, offssetAmount*i, 0, 0)
|
183
|
+
|
184
|
+
twistExtraBoneRotListController = self.const.assign_rot_list(twistExtraBone)
|
185
|
+
twistExtraBoneController = rt.Rotation_Script()
|
186
|
+
twistExtraBoneController.addConstant("localRefTm", twistBoneLocalRefTM)
|
187
|
+
twistExtraBoneController.addNode("limb", limb)
|
188
|
+
twistExtraBoneController.addNode("limbParent", limb.parent)
|
189
|
+
twistExtraBoneController.setExpression(self.upperTwistBoneExpression)
|
190
|
+
|
191
|
+
rt.setPropertyController(twistExtraBoneRotListController, "Available", twistExtraBoneController)
|
192
|
+
twistExtraBoneRotListController.delete(1)
|
193
|
+
twistExtraBoneRotListController.setActive(twistExtraBoneRotListController.count)
|
194
|
+
twistExtraBoneRotListController.weight[0] = weightVal * (twistNum-1-i)
|
195
|
+
|
196
|
+
boneChainArray.append(twistExtraBone)
|
443
197
|
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
198
|
+
boneChainArray.append(lastBone)
|
199
|
+
|
200
|
+
# 결과를 멤버 변수에 저장
|
201
|
+
self.limb = inObj
|
202
|
+
self.child = inChild
|
203
|
+
self.twistNum = twistNum
|
204
|
+
self.bones = boneChainArray
|
205
|
+
self.twistType = "Upper"
|
206
|
+
|
207
|
+
returnVal = {
|
208
|
+
"Bones": boneChainArray,
|
209
|
+
"Type": "Upper",
|
210
|
+
"Limb": inObj,
|
211
|
+
"Child": inChild,
|
212
|
+
"TwistNum": twistNum
|
213
|
+
}
|
214
|
+
|
215
|
+
# 메소드 호출 후 데이터 초기화
|
216
|
+
self.reset()
|
450
217
|
|
451
218
|
return returnVal
|
452
|
-
|
453
|
-
def
|
454
|
-
"""
|
455
|
-
전완(Forearm) 타입의 트위스트 뼈대 가져오기
|
456
|
-
|
457
|
-
Args:
|
458
|
-
inObj: 전완 뼈대 객체
|
459
|
-
|
460
|
-
Returns:
|
461
|
-
전완 타입의 트위스트 뼈대 또는 False(실패 시)
|
219
|
+
|
220
|
+
def create_lower_limb_bones(self, inObj, inChild, twistNum=4):
|
462
221
|
"""
|
463
|
-
|
464
|
-
|
465
|
-
parentBipObj = None
|
222
|
+
하체(팔뚝, 다리 등) 부분의 트위스트 뼈대를 생성하는 메소드.
|
466
223
|
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
if self.bip.is_left_node(inObj):
|
471
|
-
parentBipObj = rt.biped.getNode(inObj.controller.rootNode, rt.Name("lArm"), link=3)
|
472
|
-
else:
|
473
|
-
parentBipObj = rt.biped.getNode(inObj.controller.rootNode, rt.Name("rArm"), link=3)
|
474
|
-
|
475
|
-
children = self.bone.get_every_children(parentBipObj)
|
476
|
-
for child in children:
|
477
|
-
if rt.matchPattern(child.name, pattern="*Twist*") and rt.classOf(child) == rt.BoneGeometry:
|
478
|
-
returnVal.append(child)
|
479
|
-
|
480
|
-
returnVal = self.name.sort_by_name(returnVal)
|
481
|
-
|
482
|
-
return returnVal
|
483
|
-
|
484
|
-
def get_thigh_type(self, inObj):
|
485
|
-
"""
|
486
|
-
허벅지(Thigh) 타입의 트위스트 뼈대 가져오기
|
224
|
+
하체용 트위스트 뼈대는 부모 객체(inObj)의 위치에서 시작하여
|
225
|
+
자식 객체(inChild) 쪽으로 여러 개의 뼈대를 생성합니다.
|
226
|
+
상체와는 다른 회전 표현식을 사용하여 하체에 적합한 트위스트 움직임을 구현합니다.
|
487
227
|
|
488
228
|
Args:
|
489
|
-
inObj:
|
490
|
-
|
491
|
-
|
492
|
-
허벅지 타입의 트위스트 뼈대 또는 False(실패 시)
|
493
|
-
"""
|
494
|
-
returnVal = []
|
495
|
-
|
496
|
-
parentBipObj = None
|
229
|
+
inObj: 트위스트 뼈대의 부모 객체(뼈). 일반적으로 전완 또는 하퇴부에 해당합니다.
|
230
|
+
inChild: 자식 객체(뼈). 일반적으로 손목 또는 발목에 해당합니다.
|
231
|
+
twistNum (int, optional): 생성할 트위스트 뼈대의 개수. 기본값은 4입니다.
|
497
232
|
|
498
|
-
if not self.bip.is_biped_object(inObj):
|
499
|
-
return returnVal
|
500
|
-
|
501
|
-
if self.bip.is_left_node(inObj):
|
502
|
-
parentBipObj = rt.biped.getNode(inObj.controller.rootNode, rt.Name("lLeg"), link=1)
|
503
|
-
else:
|
504
|
-
parentBipObj = rt.biped.getNode(inObj.controller.rootNode, rt.Name("rLeg"), link=1)
|
505
|
-
|
506
|
-
children = self.bone.get_every_children(parentBipObj)
|
507
|
-
for child in children:
|
508
|
-
if rt.matchPattern(child.name, pattern="*Twist*") and rt.classOf(child) == rt.BoneGeometry:
|
509
|
-
returnVal.append(child)
|
510
|
-
|
511
|
-
returnVal = self.name.sort_by_name(returnVal)
|
512
|
-
|
513
|
-
return returnVal
|
514
|
-
|
515
|
-
def get_calf_type(self, inObj):
|
516
|
-
"""
|
517
|
-
종아리(Calf) 타입의 트위스트 뼈대 가져오기
|
518
|
-
|
519
|
-
Args:
|
520
|
-
inObj: 종아리 뼈대 객체
|
521
|
-
|
522
233
|
Returns:
|
523
|
-
|
234
|
+
dict: 생성된 트위스트 뼈대 정보를 담고 있는 사전 객체입니다.
|
235
|
+
"Bones": 생성된 뼈대 객체들의 배열
|
236
|
+
"Type": "Lower" (하체 타입)
|
237
|
+
"Limb": 부모 객체 참조
|
238
|
+
"Child": 자식 객체 참조
|
239
|
+
"TwistNum": 생성된 트위스트 뼈대 개수
|
524
240
|
"""
|
525
|
-
|
241
|
+
limb = inChild
|
242
|
+
distance = rt.distance(inObj, inChild)
|
243
|
+
facingDirVec = inChild.transform.position - inObj.transform.position
|
244
|
+
inObjXAxisVec = inObj.objectTransform.row1
|
245
|
+
distanceDir = 1.0 if rt.dot(inObjXAxisVec, facingDirVec) > 0 else -1.0
|
246
|
+
offssetAmount = (distance / twistNum) * distanceDir
|
247
|
+
weightVal = 100.0 / (twistNum-1)
|
526
248
|
|
527
|
-
|
528
|
-
|
529
|
-
if not self.bip.is_biped_object(inObj):
|
530
|
-
return returnVal
|
249
|
+
boneChainArray = []
|
531
250
|
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
251
|
+
# 첫 번째 트위스트 뼈대 생성
|
252
|
+
boneName = self.name.add_suffix_to_real_name(inObj.name, self.name._get_filtering_char(inObj.name) + "Twist")
|
253
|
+
if inObj.name[0].islower():
|
254
|
+
boneName = boneName.lower()
|
255
|
+
twistBone = self.bone.create_nub_bone(boneName, 2)
|
256
|
+
twistBone.name = self.name.replace_name_part("Index", boneName, "1")
|
257
|
+
twistBone.name = self.name.remove_name_part("Nub", twistBone.name)
|
258
|
+
twistBone.transform = inObj.transform
|
259
|
+
twistBone.parent = inObj
|
260
|
+
self.anim.move_local(twistBone, offssetAmount*(twistNum-1), 0, 0)
|
261
|
+
twistBoneLocalRefTM = limb.transform * rt.inverse(limb.parent.transform)
|
262
|
+
|
263
|
+
twistBoneRotListController = self.const.assign_rot_list(twistBone)
|
264
|
+
twistBoneController = rt.Rotation_Script()
|
265
|
+
twistBoneController.addConstant("localRefTm", twistBoneLocalRefTM)
|
266
|
+
twistBoneController.addNode("limb", limb)
|
267
|
+
twistBoneController.addNode("limbParent", limb.parent)
|
268
|
+
twistBoneController.setExpression(self.lowerTwistBoneExpression)
|
269
|
+
twistBoneController.update()
|
270
|
+
|
271
|
+
rt.setPropertyController(twistBoneRotListController, "Available", twistBoneController)
|
272
|
+
twistBoneRotListController.delete(1)
|
273
|
+
twistBoneRotListController.setActive(twistBoneRotListController.count)
|
274
|
+
twistBoneRotListController.weight[0] = 100.0
|
275
|
+
|
276
|
+
if twistNum > 1:
|
277
|
+
lastBone = self.bone.create_nub_bone(boneName, 2)
|
278
|
+
lastBone.name = self.name.replace_name_part("Index", boneName, str(twistNum))
|
279
|
+
lastBone.name = self.name.remove_name_part("Nub", lastBone.name)
|
280
|
+
lastBone.transform = inObj.transform
|
281
|
+
lastBone.parent = inObj
|
282
|
+
self.anim.move_local(lastBone, 0, 0, 0)
|
536
283
|
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
284
|
+
if twistNum > 2:
|
285
|
+
for i in range(1, twistNum-1):
|
286
|
+
twistExtraBone = self.bone.create_nub_bone(boneName, 2)
|
287
|
+
twistExtraBone.name = self.name.replace_name_part("Index", boneName, str(i+1))
|
288
|
+
twistExtraBone.name = self.name.remove_name_part("Nub", twistExtraBone.name)
|
289
|
+
twistExtraBone.transform = inObj.transform
|
290
|
+
twistExtraBone.parent = inObj
|
291
|
+
self.anim.move_local(twistExtraBone, offssetAmount*(twistNum-1-i), 0, 0)
|
292
|
+
|
293
|
+
twistExtraBoneRotListController = self.const.assign_rot_list(twistExtraBone)
|
294
|
+
twistExtraBoneController = rt.Rotation_Script()
|
295
|
+
twistExtraBoneController.addConstant("localRefTm", twistBoneLocalRefTM)
|
296
|
+
twistExtraBoneController.addNode("limb", limb)
|
297
|
+
twistExtraBoneController.addNode("limbParent", limb.parent)
|
298
|
+
twistExtraBoneController.setExpression(self.lowerTwistBoneExpression)
|
299
|
+
|
300
|
+
rt.setPropertyController(twistExtraBoneRotListController, "Available", twistExtraBoneController)
|
301
|
+
twistExtraBoneRotListController.delete(1)
|
302
|
+
twistExtraBoneRotListController.setActive(twistExtraBoneRotListController.count)
|
303
|
+
twistExtraBoneRotListController.weight[0] = weightVal * (twistNum-1-i)
|
304
|
+
|
305
|
+
boneChainArray.append(twistExtraBone)
|
306
|
+
|
307
|
+
boneChainArray.append(lastBone)
|
308
|
+
|
309
|
+
# 결과를 멤버 변수에 저장
|
310
|
+
self.limb = inObj
|
311
|
+
self.child = inChild
|
312
|
+
self.twistNum = twistNum
|
313
|
+
self.bones = boneChainArray
|
314
|
+
self.twistType = "Lower"
|
315
|
+
|
316
|
+
returnVal = {
|
317
|
+
"Bones": boneChainArray,
|
318
|
+
"Type": "Lower",
|
319
|
+
"Limb": inObj,
|
320
|
+
"Child": inChild,
|
321
|
+
"TwistNum": twistNum
|
322
|
+
}
|
323
|
+
|
324
|
+
# 메소드 호출 후 데이터 초기화
|
325
|
+
self.reset()
|
543
326
|
|
544
327
|
return returnVal
|