삼가 고인의 명복을 빕니다.

삼가 고인의 명복을 빕니다.

머라 할말이 없는 이시대에 ..



짜증난다....~~

Posted by Junios

2009/05/24 10:47 2009/05/24 10:47
Response
No Trackback , No Comment
RSS :
http://junios.net/tc/rss/response/243

Maxscript 관련

이 문서는 제가 3D Studio Max 3.x SDK 프로그래밍을 하면서 제가 필요한 것들만 정리
한것입니다. 저만 알아볼 수 있도록 되어 있는 부분이 많습니다. 시간날 때 다시 정리
하겠습니다.

--------------------
SDK 관련 사이트
--------------------
http://www.discreet.com/support/max/download/download.php3 : SDK 다운로드
http://sparks.discreet.com/downloads/downloadshome.cfm : SDK 관련 각종 다운로드
http://sparks.discreet.com/search/
http://support.ktx.com/~200/
http://sparks.discreet.com/webboard/wbpx.dll/~maxsdk/
http://support.discreet.com/webboard/wbpx.dll/%7Emos
http://www.gamasutra.com/features/19980220/baumann_01.htm
http://www.scriptspot.com : max sciprt 관련

--------------------
MAX SDK 관련 서적
--------------------

Maxscript and the Sdk for 3d Studio Max
 : http://www.amazon.com/exec/obidos/ASIN/0782127940/

--------------------
TimeValue
--------------------

  Max 에서 시간표현은 TimeValue 라는 타입으로 사용한다. 이것은 ticks 라는 단위의
  정수표현인데, 1초는 4800 ticks 에 해당한다. 이값은 아래의 표준 프레임수에 근거
  하여 모두 나누어 질 수 있는 적당한 값을 선택한 것이다.
  
  24 - 필름, 25 - PAL, 30 - NTSC
  
  TimeValue start = ip->GetAnimRange().Start();
  TimeValue end = ip->GetAnimRange().End();
  int number_of_frames = (end - start) / GetTicksPerFrame() + 1;
  int frame_per_second = GetFrameRate(); // = 4800 / GetTicksPerFrame()
  
--------------------
Transformation Matrix Order
--------------------

  Max 에서 TM(Transform Matrix)는 Matrix3 클래스로 정의된다. 이는 흔히 말하는
  행렬을 의미한다. 다른 점이 있다면 4x3 행렬이라는 것이다. 내부적으로는 
  float m[4][3]; 처럼 정의된 데이타타입을 가지고 있다. Max에서 모든 벡터는 
  행벡터로 간주되기 때문에 벡터-행렬곱은 다음과 같은 식으로 이루어진다.
  
  [v0 v1 v2 v3] * | m00 m01 m02 m03 | = [ v0' v1' v2' v3' ]
                  | m10 m11 m12 m13 |
                  | m20 m21 m22 m23 |
                  | m30 m31 m32 m33 |
  
  (* m00, m01,...mij 등등의 표현은 i번째 행, j번째 열의 행렬요소를 의미한다. 
     배열이라고 하면 m[i][j]라고 표현할 수 있다)
   
  오픈지엘에서는 아래와 같은 열벡터를 사용한다. 유의할 점은 맥스에서와는 달리 벡
  터가 곱하려는 행렬의 우측에 위치해야 한다는 것이다.
  
  | m00 m01 m02 m03 | * | v0 | = | v0' |
  | m10 m11 m12 m13 |   | v1 |   | v1' |
  | m20 m21 m22 m23 |   | v2 |   | v2' |
  | m30 m31 m32 m33 |   | v3 |   | v3' |
  
  하지만, 맥스에서는 vector * TM 뿐만 아니라, TM * vector 도 허용한다는 사실을
  알아두자(결과는 동일하다).
  
  맥스에서 사용하는 행렬은 앞서 말한것처럼 4x3 행렬이기 때문에 일반적인 행렬의
  w(scale)성분이 없다. 행렬이 아래와 같은 식으로 구성된다.
  
  | m00 m01 m02 |
  | m10 m11 m12 |
  | m20 m21 m22 |
  | m30 m31 m32 |
  
  만약, [v0 v1 v2] 인 벡터와의 형렬곱은 내부적으로 아래와 같이 계산될 것 같다.
  
  [v0 v1 v2 1] * | m00 m01 m02 | = [v0' v1' v2']
                 | m10 m11 m12 |  
                 | m20 m21 m22 |
                 | m30 m31 m32 |
  
  행벡터를 사용하는 맥스의 행렬을 열벡터를 사용하는 OpenGL에서 사용하려면 행렬을
  전치(Transpose)시켜야 한다.
  
    (맥스:행벡터사용)     (오픈지엘:열벡터사용)
  | m00 m01 m02 N/A |     | m00 m10 m20 m30 |
  | m10 m11 m12 N/A | =>  | m01 m11 m21 m31 |
  | m20 m21 m22 N/A |     | m02 m12 m22 m32 |
  | m30 m31 m32 N/A |     | N/A N/A N/A N/A |
  
  정의되어 있지 않은 [N/A N/A N/A N/A] 는 [0 0 0 1] 로 대입하여야 하며, 오픈지엘
  은 행렬을 배열로 표현시에 아래와 같은 순서를 취하기 때문에,
  
  | g0 g4 g8  g12 |   | g00 g10 g20 g30 |
  | g1 g5 g9  g13 | = | g01 g11 g21 g31 |
  | g2 g6 g10 g14 |   | g02 g12 g22 g32 |
  | g3 g7 g11 g15 |   | g03 g13 g23 g33 |
  
  맥스의 m배열은 OpenGL의 g배열로 아래와 같이 매핑된다.
  
  | m00 m10 m20 m30 |    | g00 g10 g20 g30 |
  | m01 m11 m21 m31 | =  | g01 g11 g21 g31 |
  | m02 m12 m22 m32 |    | g02 g12 g22 g32 |
  |   0   0   0   1 |    | g03 g13 g23 g33 |
  
  운좋게도, MAX 의 m[i][j] 의 값은 OpenGL 의 g[i][j] 와 같다. g[0][3] - g[3][3]
  의 값이 [0 0 0 1] 인 점만 제외하면 나머지 값은 MAX 배열 순서와 일치한다.
  코딩을 한다면 아래와 같을 것이다.
  
  for (i = 0; i < 4;i++) {
    for (j = 0; j < 3;j++) {
      OpenGL[i][j] = Max[i][j];
    }
    OpenGL[i][3] = 0.0;
  }
  OpenGL[3][3] = 1.0;
  

--------------------
Transformation Matrix
--------------------

o Object Offset TM
  Object Offset이란 맥스의 Pivot 축을 기준으로 하여 지오메트리가 위치하는 TM을
  말한다. 맥스에서 Pivot을 움직이거나 회전시킬 수도 있는 것은 이 때문이다.
  아래와 같이 계산된다.
  
  Object Offset TM = Offset Scale * Offset Rotation * Offset Position
 
o NodeTM
  NodeTM이란 Pivot 축을 월드좌표로 변환하기 위한 TM이다.
  
o Object TM
  Object TM이란 오브젝트의 한 점을 월드좌표계로 변환하기 위한 TM을 의미한다.
  ObjectTM은 부모TM, NodeTM, ObjectOffsetTM을 모두 포함한다.
  
  ObjectTM = Offset Scale * Offset Rotation * Offset Position * 
             Controller Scale * Controller Rotation * Controllers Position * 
             Parent Transformation

o Local Transformation
 
  NodeWorldTM = NodeLocalTM * ParentLocalTM * ParentLocalTM * ParentLocalTM ...
  
  ParentWorldTM = ParentLocalTM * ParentLocalTM * ParentLocalTM ...
  
  NodeWorldTM = NodeLocalTM * ParentWorldTM
  
  NodeLocalTM = NodeWorldTM * Inverse(ParentWorldTM)
  
  예제)
  
  ...
  INode *parent;
  Matrix3 parentTM, nodeTM, localTM;
  nodeTM = node->GetNodeTM(0);
  parent = node->GetParentNode();
  parentTM = parent->GetNodeTM(0);
  localTM = nodeTM*Inverse(parentTM);
  ...

--------------------
MAX 3.0 을 Windows 2000 (한) 에서 실행하기
--------------------

  Max 3.1 에서는 상관없지만 3.0 버젼을 Windows 2000 (한글) 에서 사용하려면 
  다음과 같은 옵션을 주어 실행한다.
  
  C:\3DSMAX3\3dsmax.exe -q
  
  Max 실행화일의 바로가기 아이콘을 만든다음 등록정보의 "대상"에서 실행옵션을 
  위와 같이 적어주면 된다.
  
--------------------
SDKLINK.ZIP
--------------------

  MAXSDK/HELP 디렉토리를 보면 SDKLINK.ZIP 라는 파일이 있다. 압축을 풀고 .DOC 
  파일을 보면 알 수 있겠지만, 이 파일은 비주얼 씨를 사용할 때에 TOOL 에 등록하여 
  헬프를 쉽게 사용하기 위한 방법을 설명해 주고 있다. 예를 들면, SDK 헬프에서 
  찾고자 하는 클래스 이름이나 함수명을 선택하고 Ctrl+Alt+C 를 누르면 해당하는 
  MAXSDK 헬프창이 뜨도록 할 수 있다. 물론 울트라에디트나 에디트플러스 등에서도 
  할 수 있다.

--------------------
Class Mesh
--------------------

[from MAX SDK Help]

- UVVert *tVerts;

  텍스쳐 버텍스 배열. UVW 좌표를 저장한다. 2D 매핑을 위해서는 2개의 값만 필요하 
  다. 예를 들면. UV 또는 VW, WU. 이는 사용자에게 UV, VW 또는 WU 중에서 선택할 
  수 있도록 하기 위함이다.

(UVVert 의 정의 : typedef Point3 UVVert;)

- TVFace *tvFace;

  3D 스튜디오(도스용) 시절에는 UV 배열과 버텍스 배열사이에 일대일대응이 되었으 
  다(즉, 각각의 버텍스에 대해서 하나의 UV만). 하지만, 맥스에서는 UVVert 배열은 
  배열과 완전히 독립적이다. 대신에, 별도의 TVFace 배열이 있다. 모든 면은 하나의 
  TVFace 를 가지며, 하나의 TVFace 는 UVVert 를 가리키는 세개의 인덱스가 
  필요하다. 이렇게 한 이유는 개발자가 매핑에 따라 완전히 다른 토폴로지를 적용할 
  수 있도록 하기 위함이다. 객체 각각의 면은 각자 자신의 매핑을 가질 수 있다. 
  (다시 말하면, 인접한 서로 다른 면의 버텍스에 대해서 연속적인 텍스쳐 매핑 
  좌표를 갖지 않아도 된다는 것이다.)     
  
--------------------
Object Creation 
--------------------
- utiltest.cpp -> MakeObject()

1. (Object * ip)->CreateInstance(CLASSID); // CLASSID from PLUGAPI.H
2. ParameterBlock->SetValue
3. CreateObjectNode()
4. Redraw()

--------------------
Rotate
--------------------
- DegToRad (45.0f)
  angle 은 radian 이므로 degree 로 바꿀것

--------------------
TM
--------------------
- A라는 TM에서 b만큼 떨어진 B라는 TM 구하기 (from camera.cpp)

  bM = aM;
  bM.PreTranslate(Point3(0.0f, 0.0f, b));
  
--------------------
Node 다루기
--------------------
 INode * node;
 TSTR name(_T("MyNode"));
 ip->MakeNameUnique(name);
 node->SetName(name); // Node 이름 바꾸기
 ip->RedrawViews(ip->GetTime());
 
 INode *parent;
 Matrix3 parentTM, nodeTM, localTM;
 nodeTM = node->GetNodeTM(0);
 parent = node->GetParentNode();
 parentTM = parent->GetNodeTM(0);
 localTM = nodeTM * Inverse(parentTM);
 ptm = node->GetParentTM(ip->GetTime());
 
 INode * GetINodeByName (const TCHAR *name) = 0;

--------------------
INode Method
--------------------

  Matrix3 GetNodeTM (TimeValue t, Interval * valid = NULL);
    ; 노드의 pivot 의 월드 TM 구하기
  
  Matrix3 GetObjectTM (TimeValue time, Inverval * valid = NULL);
    ; ObjectOffsetTM + NodeTM + WSM
  
  Point3 VectorTransform (const Matrix3& M, const Point3& V);
 
--------------------
대화상자 폰트 작게
--------------------
regedit.exe -> HKEY_CURRENT_CONFIG -> Software -> Fonts -> FONTS.FON 에서

hvgasys.fon 를 vgasys.fon 으로 변경 후 리부팅.

http://www.cgmate.com/zeroboard/zboard.php?id=cgmate_master&no=20

--------------------
플러그인이 로딩 안될 때
--------------------
작성한 플러그인이 어떤 시스템에서는 로딩되지만, 어떤 시스템에서는 로딩되지 않을
때에는, 컴파일시 사용한 .DLL 파일이 없어서일 수 있다. 
예를 들어, .net 환경에서 컴파일하면, msvcr70.dll 을 사용하게 되는데, 이 파일이 
없는 시스템에서는 dll이 동작하지 않는다.
플러그인 파일이 어떤 DLL을 사용하는 지 확인하려면, 비주얼씨의 bin 디렉토리에 있는,
dumpbin.exe 를 사용하여 확인한다. 

> dumpbin.exe /imports utility.dlu

--------------------
max script 실행
--------------------

스크립트는 Max 메뉴의 MAXScript->Run Script...를 통해 실행할 수 있으며, 간단한 
스크립트라면, 좌측 하단의 미니 리스너를 통해 입력하는 것도 좋다. F11키나 
MAXScript->MAXScript Listener...를 선택하여 나타내는 리스너 윈도우는 뷰포트 
메뉴의 Views->Extended->MAX Script Listener를 선택하면 뷰포트 내에 내장시킬 수도 
있다.

--------------------
Visual MAXScript
--------------------

MAXScript메뉴의 Visual MAX Script Editor...를 선택하면 스크립트 롤아웃의 사용자 
인터페이스 컨트롤 들을 마음대로 배치할 수 있는 툴이 실행된다. 이 툴을 사용하면 
버튼이나, 리스트 박스 등의 롤아웃 컨트롤 들을 자유롭게 배치할 수 있으며, .ms 
파일인 스크립트 파일로 저장할 수도 있다. 저장된 스크립트 파일은 다음과 같은 
형식을 가지며, 컨트롤들의 넓이와 높이 위치가 지정된 것을 확인할 수 있다.

rollout unnamedRollout "Untitled" width:215 height:314
(
	comboBox cbx1 "ComboBox" pos:[15,15] width:130 height:3
	listBox lbx1 "ListBox" pos:[16,88] width:81 height:2
	pickButton btn1 "PickButton" pos:[21,161] width:59 height:20
	checkButton ckb1 "CheckButton" pos:[98,159] width:80 height:29
	button btn2 "Button" pos:[21,209] width:62 height:31
	button btn3 "Button" pos:[102,204] width:64 height:35
)

--------------------
Mesh관련 max script 명령
--------------------

convertToMesh <node>
  : 씬 객체를 Editable Mesh로 변환한다.
<mesh>.numverts
  : 버텍스 개수를 얻거나 설정한다.
<mesh>.numfaces
  : 페이스 개수를 얻거나 설정한다.
<mesh>.numtverts
  : 텍스쳐 버텍스 개수를 얻거나 설정한다.

--------------------
UltraEdit 에디터에서 max script 사용하기
--------------------

맥스자체에서 제공하는 스크립트 편집기를 사용하면 맥스 자체에서 제공하는 몇 가지 
이점이 있기는 하지만, 탭 인덴테이션이 제공되지 않아, 매 라인마다 탭 키를 눌러 야 
하는 불편함이 있다. 다행히 울트라 에디트에서 사용할 수 있는 max script용 
워드파일을 누군가 미리 만들어 놓았기 때문에, 이를 사용하면 울트라 에디트에서도 
maxscript를 위한 신택스 컬러링이라든가, 탭 인덴테이션을 사용할 수 있다.

아래의 주소에서 파일을 다운받아, 자신의 울트라에디트 설치폴더에서 wordfile.txt 
에 덧붙여 주면 된다.

ftp://ultraedit.com/wf/maxscript.txt

--------------------
max script로 다중 맵 채널 데이터 뽑아내기
--------------------

Max 3.0 이상부터는 텍스쳐 좌표를 여러 개 가질 수 있다. 하나의 메쉬에 여러 채널의 
텍스쳐 좌표를 가질 수 있게 되면, 건물의 라이트 맵에 대한 uv좌표와 디퓨즈 맵에 
대한 uv좌표를 다르게 가질 수 있다. 다중 채널 데이터를 뽑기 위한 명령으로 다음과 
같은 명령들이 있다.

meshop.setNumMaps / meshop.getNumMaps
  : 메쉬의 맵 채널을 얻거나 설정한다. 기본적으로 2개의 매핑 채널을 가지는데, 
  1번과 2번 채널이 버텍스 색상과 기본 텍스쳐 맵 채널로 사용된다.  
meshop.setMapSupport / meshop.getMapSupport
  : 해당 맵 채널이 사용되고 있는 지를 알려 주거나, 사용함을 알린다.
meshop.setNumMapVerts / meshop.getNumMapVerts
  : 맵 채널에 할당된 버텍스 개수를 설정하거나 얻는다. 
meshop.setMapVert / meshop.getMapVert
  : 맵 버텍스를 설정하거나 얻는다. 맵 버텍스는 Point3구조로서 통상 uv좌표가 
  들어가게 된다.
meshop.setMapFace / meshop.getMapFace
  : 맵 페이스를 설정하거나 얻는다. 맵 페이스에도 Point3구조이나 맵 버텍스에 대한 
  인덱스가 들어간다. 물론, 인덱스는 1부터 시작한다.  
meshop.setNumTVerts / meshop.getNumTVerts
  : 일반 텍스쳐 맵 채널 버텍스 개수를 얻거나 설정한다. set/getNumMapVerts 의 2번 
  채널을 사용한 것과 같은 결과이다.

--------------------
maxscript로 머티리얼 정보 뽑아내기
--------------------
맥스에서 메쉬의 face별로 재질을 다르게 선택하려면, Multi/Sub 재질을 만들어서 
하는 것이 정석이지만, 그렇게 하지 않았더라도, 내부적으로는 Multi/Sub  재질이 
하나 만들어집니다. 다음의 코드는 각 face 단위로 재질의 이름을 출력하는 
코드입니다.

for o in objects do 
( 
    faceCount = o.numfaces 
    for k = 1 to do 
    ( 
        mtlid = (getFaceMatID o k) 
        -- if no diffuse map enabled, skip 
        if (o.material[mtlid].maps[2] == undefined) then continue 
        -- if no diffuse texture exists, skip 
        if (o.material[mtlid].maps[2].filename == undefined) then continue 
        
        -- get the diffuse map filename
        texture_full_path = o.material[mtlid].maps[2].filename
        texture_name = filenameFromPath texture_full_path
        format "texture_name = %\n" texture_name
    ) 
) 

--------------------
maxscript 로 피지크 정보 뽑아내기
--------------------
캐릭터 스튜디오 3.x 에서 피지크에 대한 정보를 스크립트로 뽑아내려면,

1. 아래의 사이트에서 IPhysique.zip를 다운받는다.
http://www.max3d.com/plugins/r4/IPhysique.zip
http://sparks.discreet.com/downloads/downloadshome.cfm?f=2&wf_id=65
(등록을 해야 다운받을 수 있지만, 등록은 공짜이며 등록할 가치 충분히 있음)

2. IPhisique.gup 파일을 /plugins 디렉토리에 복사한다.

3. 사용법은 동봉된 IPhysique.doc 파일에 있다.

4. 간단한 사용예.
> physiqueops.getAPIversion $box01

--------------------
max sciprt로 피지크 정보 빼내오기
(IPhysique 사용)
--------------------
-------------------------------------
-- physique script extract example --
--
-- 다음의 플러그인이 필요하다.
-- 
-- http://sparks.discreet.com/downloads/downloadshome.cfm?f=2&wf_id=65
-- (또는 http://www.max3d.com/plugins/r4/IPhysique.zip )
--
-- by zho@korea.com
-- 2002.12.26
-------------------------------------

function extract_physique_info physiqued_obj =
(
  po = physiqued_obj
  pm = physiqueOps.getPhysiqueModifier po
  ver = physiqueOps.getAPIVersion po modifier:pm
  bone_arr = physiqueOps.getBones po modifier:pm
  vertex_count = physiqueOps.getVertexCount po modifier:pm
  format "총 버텍스 개수 : %\n" vertex_count
  for v_index = 1 to vertex_count do
  (
    -- check vertex type
    -- physiqueOps.getVertexType po v_index modifier:pm
    format "버텍스 번호[%] : " v_index
    affected_bone_count = physiqueOps.getVertexBoneCount po v_index modifier:pm
    format "총 %개의 본에 의해 영향받음\n" affected_bone_count
    for b_index = 1 to affected_bone_count do
    (
      bone_node = physiqueOps.getVertexBone po v_index b_index modifier:pm
      weight = physiqueOps.getVertexWeight po v_index b_index modifier:pm
      offset = physiqueOps.getVertexOffset po v_index b_index modifier:pm
      format "\t본정보 : 인덱스[%]-" b_index
      format "이름[%]-" bone_node.name
      format "가중치[%]-" weight
      format "오프셋[%]\n" offset
    )
    format "\n"
  )
)

extract_physique_info $Box01 -- sample test

---------- 실행 결과 -------------------
총 버텍스 개수 : 66
버텍스 번호[1] : 총 1개의 본에 의해 영향받음
  본정보 : 인덱스[1]-이름[Bip01 Pelvis]-가중치[1.0]-오프셋[[-46.969,-32.857,5.82977]]

버텍스 번호[2] : 총 1개의 본에 의해 영향받음
  본정보 : 인덱스[1]-이름[Bip01 R Foot]-가중치[1.0]-오프셋[[5.73779,0.0505373,6.23943]]
............
버텍스 번호[66] : 총 2개의 본에 의해 영향받음
  본정보 : 인덱스[1]-이름[Bip01 R Calf]-가중치[0.973368]-오프셋[[15.982,-5.13998,-4.0716]]
  본정보 : 인덱스[2]-이름[Bip01 L Calf]-가중치[0.0266323]-오프셋[[15.982,-5.13998,5.57165]]
  
--------------------
maxscript로 Limb IK 흉내낸 코드
--------------------
-------------------------------------- begin of iktest.ms
--------------------------------------
-- Simple Limb Inverse Kinematics Test
-- by Jiho Choi (zho@korea.com)
-- from [ http://zho.pe.kr ]
-- 2002.10.28
--------------------------------------

resetMAXFile()

-- object creation
global initial_hip_rotation
global initial_knee_rotation

bone pos:[0, 0, 0] name:"hip"
bone pos:[103.707,-7.60097,0] name:"ankle"
bone pos:[56.633,-1.67554,0] name:"knee"
bone pos:[49.3482,-52.7234,0] name:"target"

-- construct parent-child hierarchy
$ankle.parent = $knee
$knee.parent = $hip

-- rotate segment by a given knee angle
fn rotate_segment segment angle_axis =
(
    local local_pos = (in coordsys parent segment.pos)
    in coordsys parent segment.pos -= local_pos -- align to segment's origin
    in coordsys parent segment.rotation = angle_axis
    in coordsys parent segment.pos += local_pos
    in coordsys local segment.rotation = (quat 0 0 0 1)
)

-- compute rotation by from_vector and to_vector
-- returns AngleAxis value
fn get_rotation_from_vectors from_vector to_vector =
(
    from_vector = from_vector
    to_vector = to_vector
    axis_vector = normalize (cross from_vector to_vector)
    angle = acos (dot (normalize from_vector) (normalize to_vector))
    return (angleAxis angle axis_vector)
)

-- get knee rotation axis
fn get_knee_axis =
(
    knee_to_ankle = $ankle.pos - $knee.pos
    knee_to_hip = $hip.pos - $knee.pos
    knee_axis = normalize (cross knee_to_ankle knee_to_hip)
    -- format "knee_axis = %, " knee_axis
    return knee_axis
)

-- rotate hip segment directing to end-effector
fn rotate_hip =
(
    rot = get_rotation_from_vectors $ankle.pos $target.pos
    $hip.rotation = rot
)

fn get_knee_angle =
(
    -- L^2 = L1^2 + L2^2 - 2*L1*L2*cos(theta)
    l1 = distance $knee.pos $hip.pos
    l2 = distance $ankle.pos $knee.pos
    L = distance $target.pos $hip.pos
    if (L > (l1 + l2)) do
    (
        L = l1 + l2 -- do not exceed total length
        -- print "cannot reach"
    )
    knee_angle = acos ((l1*l1 + l2*l2 - L*L) / (2*l1*l2))
    -- angle constraint
    -- if (knee_angle < 10) do knee_angle = 10 -- minimum
    -- if (knee_angle > 170) do knee_angle = 170
    -- current knee_angle means inner angle, thus convert to outer angle
    -- format "knee_angle = %\n" knee_angle
    knee_angle = 180 - knee_angle
    return knee_angle
)

fn rotate_knee =
(
    knee_angle = get_knee_angle() - initial_knee_rotation.angle
    -- knee_axis = get_knee_axis()
    knee_axis = initial_knee_rotation.axis
    rotate_segment $knee (angleAxis knee_angle knee_axis)
)

-- from initial configuration, compute knee axis for later use
initial_hip_rotation = $hip.rotation
initial_knee_rotation = get_rotation_from_vectors $knee.pos ($ankle.pos - $knee.pos)

viewport.activeViewport = 1
viewport.setType #view_top
max tool maximize
max move
select $target
when transform $target changes do
(
    $hip.rotation = initial_hip_rotation
    rotate_knee()
    rotate_hip()
)

-------------------------------------- end of iktest.ms








출처 http://zho.pe.kr/view.html?file_name=doc/maxsdk.txt#maxscript로_Limb_IK_흉내낸_코드












Posted by Junios

2009/05/18 10:59 2009/05/18 10:59
Response
4 Trackbacks , No Comment
RSS :
http://junios.net/tc/rss/response/242


블로그 이미지

Junios World

- Junios

Archives

Authors

  1. Junios

Calendar

«   2009/05   »
          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            

Site Stats

Total hits:
32815
Today:
25
Yesterday:
139