반응형

회사 모델러들이 맥스에서 엔진 버텍스를 바로 보고 싶다는 의견이 있어 혼자서 고민하며 만들어봤습니다.

여러가지 이유로 엔진과 동일한 수는 얻어 올 수 있지만, 아래와 같은 방법으로 비슷한 수치는 얻어 올 수 있었습니다.

첨부파일을 받으시면 사용하실 수 있습니다.



1. 모델링 버텍스가 아닌 언렙 버텍스를 계산하라!

언렙을 사용하면 한 버텍스에 두개의 UV정보를 가지게 되는 경우가 생기므로 이 때 버텍스가 증가하게 됩니다.

 

 

따라서 6200개의 버텍스의 모델링이

 

언렙된 버텍스의 수를 계산하면 8500여개가 됩니다.

 

따라서 언렙전과 언렙후에 엔진에서는 버텍스수가 달라지게 됩니다.

스크립트를 사용할 때도 반드시 언렙후에 사용해야 좀더 정확한 수치를 알게 됩니다.

 

 

 

2. 연속성이 떨어지는 메쉬를 재 연산하라.

엔진에서 불 연속성의 메시라고 파단될 경우 2배로 곱해져서 버텍스가 연산된다.

근데 그 기준을 잡기가 매우 애매하다.. 그래서 불연속성이 많이 발생할 것으로 예상되는 아웃라인 쪽의 메시를 한번더 연산했다.

선택하기가 매우 까다로워 약간의 꼼수를 사용했기 때문에 정확한 갯수는 집계가 어렵다.

현재는 이 두가지의 버텍스를 카운트 하여 제법 근사치에 가까운 결과를 얻었습니다.

유니티 9120 - 맥스 6248 = 2872 차이에서

유니티 9120 - 맥스 스크립트 9086 = 34 개 차이가 남


위 모델링 외에 5개를 더 테스트해봐도 꾀 만족스러운 결과를 얻었습니다.

테스트캐릭터   맥스 버텍스 엔진 버텍스 스크립트 사용시
samuro04  6248 (3000차이) 9120 9086 (40 차이)
Achilleus  699 (500차이) 1157 1155 (2 차이)
plane03  822 (700차이) 1568 1422(140 차이)
agentsmire  711 (400차이) 1162 1160 (2 차이)
akedb  685 (500차이) 1201 1152(50 차이)
alfina  783 (400차이) 1179 1203(20 차이)


하지만, 이 외에도 노멀벡터와 라이팅 등에 의해서 재 연산되는 엔진 버텍스를 정확히 재정의하는것은 무리가 있습니다.

위 정보에 따른 버텍스는 언리얼과 유니티도 버텍스수가 다릅니다.

EngineVertexCount.mse

 


 

반응형
반응형

제작한 스크립트를 메뉴에 등록하지 않으면 실 작업자들이 실제로 사용하는데 많은 제약이 따릅니다.

그런 문제가 없기 위해 제작한 스크립트는 반드시 메뉴에 등록을 해줘야하는데, 그 방법에 대한 가이드입니다.



맥스 스크립트 메뉴 등록 가이드

1. 맥스 스크립트 상단메뉴에 들어가려면 반드시 메크로 스크립트로 등록된 스크립트만 사용이 가능 합니다.

  • 현재 사내 매크로 스크립트는 맥스 설치폴더\\MacroSciprs\\Nlabs 폴더에 모여 있습니다.

  • 스크립트는 MacroScript 폴더에 모여있는 매크로 스크립트와 Script 폴더에 모여있는 보통 스크립트로 나뉘어 집니다..

  • 두 개의 차이점 : 

            (1) 매크로는 간단하게 실행가능한 원클릭 스크립트에 대부분 사용된다.  매크로는 맥스가 실행될께 함께 실행 되기 때문에 덩치가 커서는 안됩니다.

            (2) 일반 스크립트는 시퀀스 매니저나 애니메이션 라이브러리 같이 덩치가 큰 스크립트에 사용된다.

                내가 실행을 해야만 작동하기때문에 덩치가 커도 무리가 없습니다.

 

 

2.  매크로 스크립트를 만들기

- 현재 사내에 사용중인 매크로 스크립트들은 메뉴 등록에만 사용되고, 실제 만들어진 덩치큰 스크립트를 실행해주는 교두보 역할을 해주고 있습니다.

- 예) SequenceManeger가 메뉴에 등록될때는 매크로가 사용되고, 메뉴 버튼을 누르는 순간 실제 스크립트가 실행됩니다.

 

**사내에서 사용중인 본 메이커의 실행 매크로 스크립트

macroScript BoneMaker       --> 매크로 등록
category:"Nlabs"                    --> 카테고리 등록
buttonText:"Bone Maker"        --> 메뉴 버튼 이름 등록
tooltip:"Bone Maker"            --> 툴팁 등록
(
 on execute do
 (
   include "Nlabs/BoneMaker.ms"  --> 매크로 스크립트에 실제 스크립트가 실행되도록 연결해 줍니다.
  )
)



 

 

3. 위 매크로 스크립트를 메뉴에 등록시키기 위한 코드

- 아래 코드를 만든 후 Scripts\\Startup 폴더에 저장하시면 맥스가 실행될때 항상 메뉴가 나오게 됩니다.

스타트업에 들어간 스크립트는 맥스가 실행될때 항상 같이 실행되오니 꼭 필요한 것들만 넣어야 합니다.

 

--------------------------------------------------------------------------------------------------------

-- MainMenuClass

--------------------------------------------------------------------------------------------------------

struct MainMenuClass

(

 --------------------------------------------------------------------

 -- FindMenu

 --------------------------------------------------------------------

 fn FindMenu menuName = 

 (

             local menu = menuMan.findMenu menuName -- 없으면 undefined

             return menu

 ),

 

 --------------------------------------------------------------------

 -- AddMenu

 --------------------------------------------------------------------

 fn AddMenu menuName =

 (

             local newMenu

            

             -- 중복 추가 방지 --

             if FindMenu menuName != undefined then

              return undefined

            

             -- Menu 추가 --

             newMenu   = menuMan.createMenu menuName

             mainMenu  = menuMan.getMainMenuBar()

             subMenuItem = menuMan.createSubMenuItem menuName newMenu

             subMenuIndex = mainMenu.numItems() + 1

             mainMenu.addItem subMenuItem subMenuIndex

            

             return newMenu

 ),

 

 --------------------------------------------------------------------

 -- AddItem

 --------------------------------------------------------------------

 fn AddItem menuName item =

 (

             local newIndex

            

             menu = FindMenu menuName

            

             -- Menu가 없으면 패스 --

             if menu == undefined then

              return undefined

            

             newIndex = menu.numItems() + 1

             menu.addItem item newIndex

            

             return newItem

 ),

 

 --------------------------------------------------------------------

 -- RemoveMenu

 --------------------------------------------------------------------

 fn RemoveMenu menuName =

 (

             menu = menuMan.findMenu menuName

            

             if menu != undefined do

              menuMan.unRegisterMenu menu

            

             return ok

 ), 

 

 --------------------------------------------------------------------

 -- UpdateMenuBar

 --------------------------------------------------------------------

 fn UpdateMenuBar =

 (

             menuMan.updateMenuBar()

            

             return ok

 ), 

 

 --------------------------------------------------------------------

 -- CreateActionItem

 --------------------------------------------------------------------

 fn CreateActionItem macroScriptName categoryName =

 (

  local actionItem

 

  actionItem = menuMan.createActionItem macroScriptName categoryName

 

  return actionItem

 )

)

          

(

           menuName    = "Test"

           macroScriptName = "TestItem"

           categoryName   = "Nlabs"

 

           MainMenu = MainMenuClass()

 

           -- menu 만들기 --

           MainMenu.AddMenu menuName

 

           -- Item 만들기 --

           item = MainMenu.CreateActionItem  macroScriptName categoryName

 

           -- menu Item 등록 하기 --

           MainMenu.AddItem menuName item 

 

           -- 화면 갱신 하기 --

           MainMenu.UpdateMenuBar()

)



위 코드를 실행하면 아래 처럼 맥스 메인 메뉴에 원하는 스크립트가 등록이 됩니다.

 


위 상태에서 BoneMaker를 실행하시면 본 메이커 스크립트가 실행됩니다.

 

출처 - ​ http://hwanggoon.tistory.com/212

반응형
반응형

회사에서 맥스 스크립트를 많이 쓰게 되면서 스크립트 관리포인트가 상당히 많이 생겼습니다.

그러다보니 여기저기 버그도 발생하고, 누가 쓰고 있는지 알기도 힘들고, 업데이트 마다 mzp 파일 배포하는 것도 피곤하고..

그래서 SVN이 도입되어 사용되어 왔습니다. 제 선임이 멋지게 구축해 놓은걸 저는 인계받아 쓰고 있는데요

맥스 스크립트에서 SVN에 접근하는 방식에 대한 내용 정리입니다.

출처 -  http://hwanggoon.tistory.com/109

 

 

1. SVN Command Line 설치하기 

다운로드 경로 : http://tortoisesvn.net/downloads.html 

SVN 설치시에는 반드시 Comand 라인을 설치해 줘야만 맥스 설치폴더에서 접근할 수 있게 됩니다.

Command Line 이란? Dos 명령어를 사용해 Svn을 작동 시켜주는 방법입니다.

맥스도 Dos 명령어를 사용할 수 있기 때문에 Command Line을 설치함으로SVN을 맥스에서도 쓸 수 있게 됩니다.

 

 

2. 맥스에서 SVN 사용하기 

1) HiddenDOSCommand 

Dos 명령어를 사용하는 방법은 HiddenDOSCommand 함수를 사용하는 것이 일반적 입니다.

Dos 창이 보이지 않지만 Dos 명령어는 실행 되니깐 즐겨 사용 하는 방법 입니다.

그런데 HiddenDOSCommand는 기능 상 한계가 있는데요.

Log같은 정보를 받을 수 없습니다.

(return 되는 exitCode는 성공, 실패 같은 간단한 정보만을 보여줍니다.)

 

 

2) dotNet Process 

위와 같은 경우는 dotNet을 사용하면 해결 할 수 있습니다.

 

<예제 코드>

commandString = "info \"" + thePath + "\"" -- SVN 파일 경로

-- StartInfo -------------------------------------

 dno_ProcessStartInfo = dotNetObject "System.Diagnostics.ProcessStartInfo"
 dno_ProcessStartInfo.CreateNoWindow = true
 dno_ProcessStartInfo.UseShellExecute = false
 dno_ProcessStartInfo.RedirectStandardOutput = true
 dno_ProcessStartInfo.FileName = "svn"
 dno_ProcessStartInfo.Arguments = commandString
 ------------------------------------------------
 -- Process 적용 --------------------------------
 dnc_Process = dotNetClass "System.Diagnostics.Process"
 process = dnc_Process.Start dno_ProcessStartInfo
 process.WaitForExit()

------------------------------------------------

infoLine = process.StandardOutput.ReadLine()

-- infoLine : svn info 정보를 String으로 받아 볼 수 있음

 

dotNet Process를 사용해서 Dos 명령어를 실행 하는 방법입니다.

WaitForExit는 써주는 것이 좋은데요.

이걸 하지 않으면, Process가 끝나기 전에 MaxScript코드가 실행됩니다.

오류가 날 확률이 있으니 미리미리 방지해 봅니다.

 

 

 

3. User Name 찾기 

 

캐싱파일 분석하기 

SVN을 MaxScript로 만들다 보면 사용자 이름이 필요한 경우가 발생하는데요.

(사용자 정보를 수집할 때 필요하죠.)

SVN 명령어로 사용자 이름을 알 수는 없을 겁니다.

이럴 경우 캐싱 된 SVN파일을 열어 분석해줘야 하는데요.

 

SVN 사용자 정보

경로 : C:\Users\HwangGoon(개인마다 다름)\AppData\Roaming\Subversion\auth\svn.simple

안에 GUI로 되어 있는 파일이 있습니다.

이 파일을 텍스트 편집기에서 열어보면

다음과 같이 나오게 됩니다.

 

K 8
passtype
V 8
wincrypt
K 8
password
V 372
AQAAANCMnd8BFdERjHoAwE/ClK 15+.....
svn:realmstring
V 40
<http://100.100.100.100:80> VisualSVN Server
K 8
username
V 9
hwanggoon
END


 

svn:realmstring 값이 내가 사용하는 Url과 같은지 비교하는 것이 우선이 되겠죠.

(SVN을 2개 이상 사용하는 경우도 많기 때문에)

username 하위에 보시면 hwanggoon이 SVN username입니다.

 - K 8과 같은 코드는 무시하는 것이 좋습니다. 사용자마다 같다는 보장을 할 수 없어요.

 

  

3. SVN 설치 유무 알아내기 

1) TortoiseSVN 설치 알아내기 

특정 프로그램이 설치되어 있는지 확인하는 방법은 윈도우 레지스트리에서 찾을 수 있는데요. 

예제 코드를 보겠습니다.

dnc_Registry = dotNetClass "Microsoft.Win32.Registry"
registryKey = dnc_Registry.LocalMachine.OpenSubKey "SOFTWARE\\TortoiseSVN"

 

위와 같이 찾으면 TortoiseSVN이 설치 되어 있지 않다면 registryKey값은 undefined로 나오게 됩니다.

 

2) Command Line SVN 설치 알아내기 

TortoiseSVN이 설치되어 있어야 Command Line이 있을 수 있겠죠.

그렇다면 위에서 찾은 registryKey를 가지고 한번 더 하위를 찾아 봅니다.

 

dir = registryKey.GetValue "Directory"
svnFile = dir + "bin\svn.exe"

 

이제 svnFile이 있는지 여부만 판단하면 Command Line 설치를 확인이 가능해 지겠죠.

반응형
반응형

스크립트를 만들때 이름으로 서치하는 것은 매우 안좋은 습관이다.

하지만, 바이패드는 이름으로 서치하지 않으면 해당 오브젝트를 찾기 힘들다.

그래서 Script 헬프를 뒤져보니 바이패드의 고유 Node 넘버가 있는것을 확인했다.


biped.getNode $ #lArm link:4  라고 실행하면 아래 표에 따라 L Hand가 호출된다.


Index Limb Name Link Nodes in Link Index Order      
1 #larm L Clavicle L UpperArm L Forearm L Hand
2 #rarm R Clavicle R UpperArm R Forearm R Hand
3 #lfingers L Finger0 L Finger01 L Finger02 L Finger1
    L Finger11 L Finger12 L Finger2 L Finger21
    L Finger22 L Finger3 L Finger31 L Finger32
    L Finger4 L Finger41 L Finger42  
4 #rfingers R Finger0 R Finger01 R Finger02 R Finger1
    R Finger11 R Finger12 R Finger2 R Finger21
    R Finger22 R Finger3 R Finger31 R Finger32
    R Finger4 R Finger41 R Finger42  
5 #lleg L Thigh L Calf L HorseLink L Foot
6 #rleg R Thigh R Calf R HorseLink R Foot
7 #ltoes L Toe0 L Toe01 L Toe02 L Toe1
    L Toe11 L Toe12 L Toe2 L Toe21
    L Toe22 L Toe3 L Toe31 L Toe32
    L Toe4 L Toe41 L Toe42  
8 #rtoes R Toe0 R Toe01 R Toe02 R Toe1
    R Toe11 R Toe12 R Toe2 R Toe21
    R Toe22 R Toe3 R Toe31 R Toe32
    R Toe4 R Toe41 R Toe42  
9 #spine Spine Spine1 Spine2 Spine3
    Spine4      
10 #tail Tail Tail1 Tail2 Tail3
    Tail4      
11 #head Head      
12 #pelvis Pelvis      
13 #vertical Biped COM      
14 #horizontal Biped COM      
15 #turn Biped COM      
16 #footprints Footsteps      
17 #neck Neck Neck1 Neck2 Neck3
    Neck4      
18 #pony1 Ponytail1 Ponytail11 Ponytail12 Ponytail13
    Ponytail14      
19 #pony2 Ponytail2 Ponytail21 Ponytail22 Ponytail23
    Ponytail24      
20 #prop1 Prop1      
21 #prop2 Prop2      
22 #prop3 Prop3      
101 #lfArmTwist L ForeTwist L ForeTwist1 L ForeTwist2 L ForeTwist3
    L ForeTwist4 L ForeTwist5 L ForeTwist6 L ForeTwist7
    L ForeTwist8 L ForeTwist9    
102 #rfArmTwist R ForeTwist R ForeTwist1 R ForeTwist2 R ForeTwist3
    R ForeTwist4 R ForeTwist5 R ForeTwist6 R ForeTwist7
    R ForeTwist8 R ForeTwist9    
103 #lUparmTwist L UpTwist L UpTwist1 L UpTwist2 L UpTwist3
    L UpTwist4 L UpTwist5 L UpTwist6 L UpTwist7
    L UpTwist8 L UpTwist9    
104 #rUparmTwist R UpTwist R UpTwist1 R UpTwist2 R UpTwist3
    R UpTwist4 R UpTwist5 R UpTwist6 R UpTwist7
    R UpTwist8 R UpTwist9    
105 #lThighTwist L ThighTwist L ThighTwist1 L ThighTwist2 L ThighTwist3
    L ThighTwist4 L ThighTwist5 L ThighTwist6 L ThighTwist7
    L ThighTwist8 L ThighTwist9    
106 #rThighTwist R ThighTwist R ThighTwist1 R ThighTwist2 R ThighTwist3
    R ThighTwist4 R ThighTwist5 R ThighTwist6 R ThighTwist7
    R ThighTwist8 R ThighTwist9    
107 #lCalfTwist L CalfTwist L CalfTwist1 L CalfTwist2 L CalfTwist3
    L CalfTwist4 L CalfTwist5 L CalfTwist6 L CalfTwist7
    L CalfTwist8 L CalfTwist9    
108 #rCalfTwist R CalfTwist R CalfTwist1 R CalfTwist2 R CalfTwist3
    R CalfTwist4 R CalfTwist5 R CalfTwist6 R CalfTwist7
    R CalfTwist8 R CalfTwist9    
109 #lHorseTwist L HorseTwist L HorseTwist1 L HorseTwist2 L HorseTwist3
    L HorseTwist4 L HorseTwist5 L HorseTwist6 L HorseTwist7
    L HorseTwist8 L HorseTwist9    
110 #rHorseTwist R HorseTwist R HorseTwist1 R HorseTwist2 R HorseTwist3
    R HorseTwist4 R HorseTwist5 R HorseTwist6 R HorseTwist7
    RHorseTwist8 R HorseTwist9    

 

반응형
반응형

최근 다관절 셋팅을 하면서 컨트롤러 셋팅을 많이 하게 되는데, 맥스의 컨트롤러 뷰어는 불편한 점이 많아서 서포트 툴을 하나 제작하게 됐습니다.

특히 LookAtConstraint나 Orientation Controller같이 다른 헬퍼 본과 연계되서 사용할 경우 연계된 본이 어떤건지 구분하기도 힘들고 선택하기도 힘들어 자주쓰는 노드들과 연계하기 편하도록 제작해 봤습니다.


 


이번 툴을 제작하면서 공부한 내용

1. Struct로 따로 분리하여 기능 별로 함수 관리하기.

- 닷넷에 사용하는 트리뷰와 리스트뷰기능만을 구조체로 따로 뺀뒤 기능 함수를 호출해서 사용하는 방식에 대해서 공부하고 숙지했습니다.

기능 구현에만 집중해서 코딩하다 보면 나중에 손댈 수 없는 지저분한 코딩이 될 수 있어 미리미리 코드 정리하는 습관이 중요함을 알게됐습니다.

 

2. 재귀함수의 사용법 다시 한 번 숙지

- 아트직업군에 오래 머물러 있다보니 논리적 사고가 부족해 재귀함수의 흐름을 익히는데 어려움이 많이 있습니다.

지난번 페이스 셀렉트 툴에서도 여러번 익히며 사용법을 완전 숙지했다고 생각했으나 이번 툴을 만들면서 아직 개념이 들 잡혀있음을 알게 되었고, 좀더 연습할 수 있는 시간이었습니다. 좀 더 많은 코딩을 통해 계속해서 숙지해야 할 필요성을 느끼게 됐습니다.

 

ControllerNodeViewer2.mse

 

반응형
반응형

최근 회사에서 언리얼 마켓 플레이스에서 구매해 사용하는 데이터들이 점점 많아지다 보니 관리가 힘들어져 만든 스크립트입니다.

애니메이션 팩 같은 경우는 한번 사면 60개는 기본으로 들어 있더라구요.

이 데이터를 그대로는 못쓰기 때문에 맥스에서 불러온뒤 본 네이밍등을 변경해서 다시 저장해주는 스크립트입니다.

중간에 본 네이밍을 바꿔주는 내용은 저희 회사 규약에 맞춰져 있어서 빼고 사용하시면 됩니다.


1. 대상 FBX 파일들을 불러옴

2. 맥스에서 FBX를 임포트하여 MAX 파일로 변환 후 저장

3. 완료된 MAX 파일들 다시 일괄적으로 익스포트

 

FbxToMaxListBox.ms


1번을 통해 일괄 변환할 FBX 파일들을 선택하여 부르면 2번에 리스트가 나옵니다.

3번을 눌러 맥스파일을 저장할 경로를 선택하고,

4번을 누르면 일괄적으로 본 네임과 애니메이션 길이등을 자동으로 맞춰 맥스파일로 저장해줍니다.

그리고 5번을 눌러 배치익스포트를 불러 다시 일괄 익스포트를 하면 언리얼용 FBX 데이터로 변환됩니다.

 

반응형
반응형

기존에 제작한 은면제거 방식은 벡터의 내적이라는 수학 공식을 활용하여 카메라와 대치되는 각을 계산하여 면을 제거하는 방식이었습니다.

하지만 이 방식은 몇가지 단점이 존재합니다.


1. 각도를 계산해서 하다보니 카메라에 안잡히는 면도 각도조건만 맞으면 남아있게 된다.

2. 면이 깔끔하게 지워지지 않는다. 가령 면은 지워졌는데, 버텍스가 남는다던지..

 

등등.. 여러번 시뮬레이션을 돌려보면 금방 알 수 있는 단점들이 존재합니다.

하지만, 이번에 제작한 Hidden Surface 방식은 렌더링 된 G-Buffer의 값을 얻어와 지오메트리의 렌더링된 면을 메모리에 기억하여 삭제하는 방식이라 더 깔끔하게 면들을 정리해줍니다.

단, 계산시간이 오래 걸릴수 있다는 단점이 있습니다. 이 부분도 차후에 개선할수있도록 해보겠습니다.


이 스크립트의 구동방식을 간단히 살펴보면

1. 먼저 대상이 될 오브젝트의 면들을 전부 디테치 한 후 메모리에 저장한후 각 면마다 오브젝트를 생성해 줍니다.

-여기서 먼저 대상이 될 원본 오브젝트를 하이드 시켜 줍니다.(G-Buffer값 구할때 방해되는 요소)


 



2. 디테치된 면들의 렌더링 된 채널값에서 G-Buffer(지오메트리버퍼) 값을 구해온다.

G-Buffer의 개념 - http://en.wikipedia.org/wiki/Deferred_shading


3. 렌더링 버퍼의 값을 구해서 원본 모델링에 저장이 됐으면 이제 각 면들은 필요없어 졌으니 전부 지워버린다.


4. 원본 면의 페이스 정보들을 비트어레이에 담고 G-Buffer에 담긴 값들만 False로 선언해준다.

5. 이제 원본 오브젝트의 비트어레이에 담긴 면들을 삭제하라는 명령을 실행하면 false로 제외된 값들을 빼고 삭제를 하게 된다.



벡터의 내적 방식과 Hidden Surface 방식의 비교 샷


백페이스 방식- 면이 지저분하게 정리된다.  


 

 히든 서페이스 방식 - 면이 깔끔하게 정리된다.

 

 

이번 과제를 통해 알게 된 내용

1. G-Buffer의 개념과 렌더링에 대한 기초

2. 원본에 있는 면을 뜯어내서 메모리에 저장시킬 수 있는 기능

3. finditem을 이용하여 비트어레이의 값을 조절할수 있는 기능

반응형
반응형

이 스크립트는 최적화를 위한 툴로서 카메라에 보이지 않는 면들을 제거하여 카메라렌더링에 대한 연산을 최소화

시키지 위한 툴입니다.

 

이번 과제를 해결하기 위해서는 삼각함수의 기본 원리와 벡터의 내적을 구하는 공식에 대한
이해가 필요했습니다.

카메라와 오브젝트간 벡터의 내적이 0보다 큰 수의 면만 선택하여 삭제하는 공식을 이해하는데

많은 시간이 필요했습니다.

카메라가 A이고 오브젝트의 한 단면이 B 이고 살리고 싶은 면이 C일때

C = a b cos@를 이용한 벡터의 내적을 이용하여 cos@가 0보다 큰면은 카메라가 바라보는 방향과

같은 방향을 바라보기 때문에 카메라가 잡히지 않는 구간입니다.

따라서 0보다 작은 마이너스 구간을 살리고 0보다 큰 플러스 구간은 삭제하면 됩니다.

 

이 공식을 이용하여 스크립트를 짜게 되면 영상과 같은 결과가 출력됩니다.


 


스크립트

Global backFaceDeleter


--======================================================================================
-- DestroyDialog
--======================================================================================
try (DestroyDialog backFaceDeleter) catch()

--==========================================================================================================

-- rollout backFaceDeleter

--==========================================================================================================
rollout backFaceDeleter "백페이스 방식 삭제"
(
 local mainCamera  -- 메인 카메라 선언
 
 --======================================================================================
 -- struct
 --====================================================================================== 
 struct strt_objinfo   --max 스크립트는 변수 선언에 형식의 제한이 없다. 모든 값을 넣을 수 있음(오브젝트형식)
 (
  obj,     -- 오브젝트 정보
  faces = #(),    -- 전체 페이스 정보
  faceobjs = #()   --  참인 값의 페이스 정보
 )
 ------------------------------------------------------------------------
 -- CameraFilter
 ------------------------------------------------------------------------
 fn FilterCam cam =   --카메라 아니면 선택되지 않게 설정
 (
  if iskindof cam camera then
   return true
  else
   return false
 )
 --======================================================================================
 -- UI
 --======================================================================================
 pickbutton ptn_camera "Pick" filter:FilterCam
 button btn_BackFace "BackFace"
  
  
 --======================================================================================
 -- Fn
 --======================================================================================

 ------------------------------------------------------------------------
 -- FindBackface
 ------------------------------------------------------------------------ 
 fn BackFaceinfo obj camLookPos =     ---- 백페이스 정보와 오브젝트와 카메라의 바라보는 뷰를 변수 선언
 (
  local backFaces = #{}      ----백페이스 관련 좌표와 벡터값을 얻어내기 위해 비트 어레이 변수 선언
                                     
  faceNum = getNumFaces obj        --- 페이스 넘버는 곧 오브젝트의 페이스 넘버다
  for i = 1 to faceNum do                           ----- 1번부터 전체 페이스 넘버를 돌면서 아래를 실행
  (
   facePos = meshop.getFaceCenter obj i        ---- 한 페이스의 중앙 점 좌표를 camLookPos이라는 변수에 대입
   lookV = facePos - camLookPos                            ---- 위에서 구한 중앙 좌표에서 카메라의 위치값을 빼서 lookV에 넣는다. 그래야 벡터의 내적을 구하니까
   
   faceNormal = getFaceNormal obj i        --- 한 페이스가 바라보는 벡터값을 faceNormal 이라는 변수값에 대입
   if dot lookV faceNormal > 0 then       --- 그래서 페이스에서 카메라위치값을 뺀 벡터와 한 페이스의 벡터값을 뺀것의 내적이  0보다 클경우 참.  참인면을 최종적으로 지울것   바라보는 각을 지우고 반대쪽을 바라보는 각을 살리기 위해
    backfaces[i] = true                   --- 비트어레이 backfaces의 페이스 넘버의 참과 거짓을 가림
  )
  
  return backFaces     --- 백페이스 정보 리턴
 )
 
 --======================================================================================
 -- UI Control
 --======================================================================================
 ------------------------------------------------------------------------
 -- ptn_camera
 ------------------------------------------------------------------------ 
 on ptn_camera picked cam do    --- 카메라를 클릭했을때 이름 보여줌
 (
  ptn_camera.text = cam.name
  mainCamera = cam
 )
 
 ------------------------------------------------------------------------
 -- btn_DeleteBackface
 ------------------------------------------------------------------------
 on btn_BackFace pressed do
 (
  local meshObj = $
  local cams = mainCamera

  convertToMesh meshObj  ---메시 형태가 아니면 폴리 넘버를 알수 없다.
  backfaces = BackFaceinfo meshObj cams.pos  ---bacakfaces에 오브젝트와 카메라의 포지션을 넣는다.
  objinfo = strt_objinfo meshObj backfaces   --struct함수로 선언한 세 변수에 각각 값을 집어넣는다. obj에 선택한 오브젝트, face에 backfaces(참인 면)

  --obj : 선택한 오브젝트      faces : 참인 면들의 배열(비트어레이)
  
  print objinfo
  print  objinfo.faces
  
  if objinfo.faces.numberset < getNumFaces meshObj then   -- numberset은 비트어레이 배열안에 몇개의 수가 있는지 알려줌, struct안에 배열의 수가 선택한 메시 수보다 작을경우 선택한 메시의 struct 변수에 넣은
    meshop.deleteFaces meshObj objinfo.faces             ---참인면들을 지워라!
   
  deselect $
  select meshObj
 )
)

CreateDialog backFaceDeleter width:100 height:50

 

 

이번 과제는 저에게 큰 벽이었습니다. 중 고딩때 수학공부를 게을리한 내 자신이 이렇게 미울수가 없었네요..ㅠ

지난 한주간 용인 사는 누나댁을 오가며 열심히 원리를 깨우쳤습니다. 수학과 나온 누님이 저에게 도움 되는 날이

올줄 몰랐어요..ㅎㅎ   어렵지만, 이해하고 나니 정말 극 쾌감이 몰려오네요~^^ 

근데 백페이스 방식은 여러가지 단점이 있어 HIdden 방식을 써야 하는 경우가 생깁니다.

그 방식에 대해서는 다음에 다뤄보겠습니다.


참고 사이트 황군 - http://hwanggoon.tistory.com/118

반응형
반응형

상하체 분리 애니 적용시 상체가 중심축의 로테이션 값이 먹어 애니가 제대로 적용되지 않는 문제가 있었습니다.

그래서 담당 프로그래머 분이랑 같이 본 구조도 바꿔보고... 블렌드가 아닌 애디티브도 써보고 별짓을 다했는데아래처럼 정면을 제대로 바라보지 못하면서 모션이

 출력습니다.

 

 

 


이때 '본 마다 레이어로 블렌드 합니다'의 속성에서 아래 부분을 체크인 해줘야 합니다.

 

체크인 하면 아래처럼 정면을 바라보며 정상적으로 출력됩니다.

 

옵셔체크하나면 해결될 일이었는데, 문서공유되어 있는게 없어 한참을 헤맸네요..ㅠ

잊어버릴까봐 메모해 둡니다~

 

반응형
반응형

맥스 스크립트와 캐릭터 셋업의 정석인 이상원님의 '캐릭터 셋업 테크닉'을 오랜기간 정독중에 있습니다. 1차로 정리한 내용을 올려볼까 합니다.





캐릭터 셋업 책 리포트

Seccion1 . 기초다지기> 개념을 잡자!(34p~291p)

 

1. 축의 개념 - 뷰, 로컬, 월드, 페어런트의 정확한 개념 이해하기

           (1) 부모자식간의 개념 확실히 이해하기

           - 링크관계일때와 아닐때의 위치 좌표의 변화

           (2) 좌우 대칭이 되는 Point Helper 만들기

           - 모델링 맵핑과 마찬가지로 좌우 대칭의 개념을 아는 것은 매우 중요하다.

           로컬 트랜스폼에 대한 개념을 깨우치자.

 


2. 본에 대해서 숙지하기

           (1) 본 오브젝트는 위치, 회전, 스케일 정보만 가지고 있는 헬퍼라고 생각하는게 좋다.

           (2) 본의 Mirror와 일반 Mirror는 완전다르다. 일반 미러는 스케일값을 반전 시키기때문에

           Y혹은 Z축이 뒤집히게 되면서 다양한 문제를 발생시킨다.

           (3) scale형식과 squash형식 이해하기

           (4) Auto-Align 의 기능 살펴보기(자식본을 바라보느냐 안하느냐)

 


3. 오일러와 쿼터니언

           (1) Roll , Pitch, Yaw 숙지하기.

           (2) 짐벌락에 대해 이해하고, 짐벌락을 피해가는 방식을 고려해 본다.

           -가령 사람의 척추는 Y,Z축으로는 많이 움직이지만, X축움직임이 거의 없기 때문에

           YXZ ZXY로 회전순서를 설정하면 짐벌락의 현상을 최소화 시킬수 있다.

 (3) Script Controller에서 F(frame), NT(normalized time), S(secs), T(ticks) 의 개념 이해하기.

 (4) 쿼터니언은 3개의 방향을 가지고 있는 백터와 그 벡터의 바라보는 위치값을 결정하는 w값에 의해서 최종 회전 방향이 결정된다.

 

 

4. Pivot 관련 개념 잡기

           (1) Adjust Pivot, Working Pivot, Adjust Transform 개념 잡기

           (2) Link Info 개념잡기

           - Lock 롤아웃 : 애니메이터가 잘못된 축을 이용하지 못하도록 원천적으로 막아주는 기능.

           - Inherit 롤아웃 : Inherit의 개념 정확히 이해하기~ 상속의 개념

           (3) Reset Stretch

           - Max Script Stertch   = objectoffsetTM * stretchTM * nodeTM

 - 한글로 = 오브젝트의 트랜스폼 = 오프셋 값과 Stretch 값과 노드 값이 모두 반영되어서 결정됨

           - 상품의 가격 = 소매점 마진 + 유통 마진 + 생사자 원가


 

5. 본의 IK 이해하기

(1) HI Solver

- 캐릭터 애니나 길이가 긴 애니메이션 추천. 이 방식은 계층 구조 내에서 여러개의 IK Chain을 동시에 사용할 수 있는데,예를 들어서 캐릭터의 다리를 만들때 엉덩이로부터 발목까지를 하나의 체인으로 구성하고 뒤꿈치에서 발가락까지 또 다른 체인으로 구성할 수 있다.

전체 애니메이션 내용과 무관한 알고리즘으로 작동하기 때문에 애니메이션 길이가 얼마나 길게 만들어졌는지에 상관없이 빠른 연산 속도를 유지한다. , 전체 애니메이션 길이가 2000프레임으로 되어 있는 경우와 10프레임으로 되어 있는 경우가 모두 같은 속도로 작동한다. 또한 뷰포트에서 지글거리는 증세가 적고 안정적인다.

- HI IK Solver에는 IK Solver Plane이라는 개념이 사용되고 있는데 Swivel Angle이라는 값에 의해서 IK Solver Plane이 제어된다. Swivel Angel값은 직접 애니메이션 되거나 타깃 오브젝트를 통해서 애니메이션 되는 값이다.

 

(2) HD Solver

- HD Solver Interactive IK와 같은 기능이 있다. 그렇기 때문에 Hierachy 판넬의 IK 버튼에 각종 롤아웃의 기능들, Terminator 라던가 Bind to Folow 라던가 Precedence 등의 기능이 동일하다.

HD Solver Interactive는 대체로 기계를 움직일 때 적합한 방식이다. 특히 IK 애니메이션 특성에 의해서 미끄러지는 특성을 가진 기계에 적합하다.

(3) Ik Limb Solver

- 본이 두개인 경우에만 사용된다. 캐릭터의 팔과 다리에 쓰기에 적합한 방식. 이 녀석을 쓰기 위해서는 최소한 세 단계 이상의 본이나 오브젝트로 구성된 계층구조가 필요하다. 그 외에는 HI SOlver와 같은 방식으로 기능한다.

(4) Spline IK Solver

- Spline Ik Solver는 스플라인을 이용해서 여러개의 본이나 링크로 이어진 오브젝트를 부드럽게 휘어지도록 제어한다.

 

 

6. Controller 이해하기.

           -3DS MAX를 처음 설치 했을 때 오브젝트에 적용되는 Default Controller는 다음과 같다.

           위치 : Position XYZ

           회전 : Euler XYZ

           스케일 : Bezier Scale

           -맥스의 대부분의 애니메이션은 Bezier Controller에 의해서 제어된다.

  - Controller에 가능한 것들 : 애니메이션 키값 저장, 절차적인(Procedual) 애니메이션 설정 , 애니메이션 키 사이의 보간(Interpolation)

           - 트랙뷰에서 컨트롤러 접근이 가능하다.

           (1) 컨트롤러의 분류와 구조

           - Single-Parameter(단일) Controller : 단순히 한 가지 값이 애니메이션 되는 경우이다.

 - Compound Controller : 애니메이션 되는 값이 하나가 아니고 여러 개인 경우이다. 쉬운 예가 Euler XYZ Rotation Controller인데XYZ의 각 축 방향마다 서로 다른 Controller를 적용할 수 있다. 이런 경우 외에도 PRS, Transform Scrip, List Controller등 상위 레벨의 Controller 또한 Compound Controller 이다.

         (2) 일반적인 목적의 Controller

  - Bezier Controller : 가장 자주 사용되는 컨트롤러이고, 애니메이션 키와 키 사이사 보간할 때 스플라인 커브 방식으로 보간 된다Normilize Time 숙지 필요.

 - TCB Controller : 커브 기반의 애니메이션 컨트롤러지만 커브를 제어하기 위해서 탄젠트를 사용하지 않는다. 대신에 Tension, Continuity, Bias라는 값을 사용한다. Rotaion WindUP 기능에 대해서 아는게 좋음.(180도이상 돌지 못하는 TCB 360도까지 돌게 하는 기능. 하지만여러가지 문제가 많아 지향하는 방식은 아님)

          

 - Linear Controller : 애니메이션 키와 키 사이를 일정한 간격으로 보간(Interpolation)한다.

 - Noise Controller : 불규칙적이고 랜덤한 애니메이션 값을 계산적으로 만들어내는 컨트롤러. Ignore 방식은 전체 프레임에서 발동하고 Respect 방식은 보여주는 키프레임안에서만 발동한다.

          

- XYZ Controller :

1) Position XYZ : X,Y,Z축으로 분리되어 있어 각 축마다 서로 다른 Controller를 지정할 수 있다

 2) Euler XYZ : Position XYZ와 비슷하며, 회전을 제어하는 컨트롤러중에서는 유일하게 커브 편집이 가능하다.

           - Audio Controller

 

(3) 특수한 목적의 Controller

- List Controller : List Controller는 여러 개의 Controller를 혼합해서 최종 결과를 만들어 내는 Controller이다. 적용방향은 위에서부터 아래쪽으로 순차적으로 적용 된다.

리스트 컨트롤러의 세부조절 설명

    1. Editable Name Field : 그림의 빨간색 박스를 통해서 현재 활성화된 Controller의 이름을 변경할 수 있다.

    2. Set Active : 어떤 Controller가 활성화 되는지를 결정하는 버튼인데 Controller 이름에서 더블 클릭을 통해서도 활성화 지정이 가능하다.

    3. Delete : Controller를 삭제한다.

    4. Cut/Paste : 선택된 Controller를 삭제하고 클립보드에 기억시킨다.

    5. Weight : Controller의 효과가 과장되거나 작게 줄어들게 조절할 수 있다. 기본 값은 100인데 100이상의 값도 가능하다.

    6. Average Weight : 이 옵션은 Position List Scale List에만 있는 옵션이다. 이 옵션이 켜지면 모든 Weight값을 비율로써 계산하게 된다.

    7. Pose TO Pose : Rotation List에 쓰임. 예제 34 파일을 참고. 말로 설명이 어려움.

 

(4) Zero Transform

- Freeze Tranform이나 Freeze Rotation을 오브젝트에 적용한 뒤에 애니메이션 작업 도중에 Tranform to Zero 혹은 Rotation To Zero를 적용하면 Freeze를 했던 순간의 트랜스폼으로 되돌아가게 된다.

(5) Parameter Wiring

- Parameter Wire는 두 오브젝트간 Parameter가 연동되도록 연결하는 기능으로서 리깅 작업뿐 아니라 전반적인 3D 작업을 위해서 매우 요긴한 기능이다.

리깅을 예로 들어 새가 날개짓을 하는 애니메이션을 할 때 한 쪽 날개만 움직여도 다른 쪽 날개가 똑같이 움직이도록 연결하거나 페이셜 애니메이션을 위해서 표정제어를 위한 각종 Manipalutor를 설치해서 슬라이더 하나만 움직여도 다수의 본이 동시에 움직여서 웃는 표정을 짓는다거나 하는 작업에 활용될 수 있다.

    • 마우스 우클릭의 wire parameter를 이용하여 사용할 수 있고, Animation 메뉴를 통해서도 접근할 수 있다.

    • 과도하게 사용될 경우 CPU 연산 부하량이 많아 최대한 낮은 CPU 비용으로 간결하고 직관적으로 셋업하는 것이 훌륭한 셋업이다.

 

(6) Reaction Controller

- 오브젝트가 가까이 가면 자동으로 라이트가 켜진다거나 근육이 부풀어 오른다거나 공이 땅에 닿으면 가로로 찌그러진다거나 하는 설정을 할 수가 있다. 또한 파티클을 발생시키는 트리거로도 사용될 수 있고 몰핑의 퍼센트 조절을 해줄수도 있다.

Maya Set Driven Key 기능과 매우 유사하다.

, 버그가 미친듯이 많아서 사용을 권장하지는 않는다.

 

(7) 트랜스폼 제어

- Position , Rotation, Scale의 세정보가 합쳐져서 트랜스폼이 된다. 지금까지 설명했던 각종 Animation Controller는 모두 트랜스폼을 제어하는 Position / Rotation / Scale Controller의 하위 Controller였다.


1) Link Constraint - 0프레임은 월드에 1프레임은 오브젝트에 30프레임은 본오브젝트에 링크하듯이 프레임마다 다양한 속성으로 링크가 가능하다.

단점은, 애니메이션의 저장과 불러오기가 불가능하다.


2) Transform Script Controller

- 포지션,  로테이션, 스케일을 Script로 표현하는 Controller이다. 일반적인 Scrpit Controller와 대부분 동일하지만 리턴 값이 Matrix3 형태여야 하는 점이 다르다.

 

7. Animation Constrints(애니메이션 컨스트레인트)

           - 가장 대표적인 것으로는 LookAt Orientation Constraints가 있고 포지션에 대해서

           Path Position Constraint가 있다.

    • 모든 컨스트레인트는 다른 오브젝트를 참조해서 자신의 포지션이나, 로테이션 혹은 전체 트랜스폼을 결정하게 된다. 예를 들어 룩앳 컨스트레인트는 하나이상의 다른 오브젝트들을 바라봄으로써 자신의 로테이션이 결정된다.

(1) LookAt Constraint

    • 다른 물체를 바라보게 함으로써 자신의 Rotation이 결정되도록 하는 Controller.

(2) Orientation Contraint

    • 기본적인 목적은 다른 오브젝트의 Rotation을 그대로 따라하는 기능인데 여러 오브젝트를 지정해서 평균적인 회전 방향을 사용하거나 가중치를 다르게 지정하는 것도 가능하다.

(3) Path Constraint

    • Spline Path 를 이용해서 오브젝트의 위치를 제어하는 Contraint이다.

(4) Position Constraint

    • 다른 오브젝트의 위치를 참조해서 자신의 위치를 결정하는 역할을 하는데, 하나 이상의 오브젝트를 참조할 수 있기 때문에 두 오브젝트의 중간 위치를 얻어낼 때 자주 사용된다.

(5) Attachment Constraint

    • 오브젝트를 다른 오브젝트의 메쉬에 부착시키는 역할을 한다.

(6) Surface Constraint

    • 어태치먼트는 접착제로 부착하는 느낌이라면 Surface는 타깃 오브젝트의 표면을 미끄러지듯이 이동하기 위한 목적에 주로 사용된다. 매우 제한적으로 사용할 수 있고, 사용할 수 있는 오브젝트 타입도 제한적이다.

    • Sphere , Cone, Cylinder, Torus, Quad Patches, Loft object, NURBS object에만 사용할 수 있다. 이 오브젝트들의 공통점은 수학적으로 표현되는 오브젝트라는 점이다.

 

8. 기타 Controller


(1) Limit Controller

- 오브젝트의 움직임에 한계값을 지정하는 Controller이다. 예를 들어 손가락 방향으로는 90도 정도의 회전을 하지만 손등 방향으로는 거의 꺽이지 않는 한계 각도가 있다. 이런 특징을 가지고 있는 손가락 관절에 Limit Controller를 적용하게 되면 지정된 각도 이상으로 관절이 꺽이지 않도록 강제도 막아줄 수 있다.


(2) Spring Controller

- 마치 보이지 않는 고무줄에 매달려 있는 것처럼 탄력적으로 흔들리는 움직임으로 특성이 바뀐다. 이렇게 되기 위해서는 미리 Position Animation이 적용되어 있어야 하는데, 오브젝트 자신이 움직여도 되고 오브젝트 부모가 움직여도 된다.

그런데 현실에서의 Spring이나 고무줄 움직임을 시뮬레이션 하기에는 많이 부족한 기능이라서 본 오브젝트에 간단히 사용해서 응용하는 방향으로 주로 사용되며, 우리 회사에서도 세컨더리 애니메이션으로 많이 사용되고 있다.

    1. Mass : 오브젝트의 무게 설정. 이 값이 증가하면 모션이 과장된다.

    2. Drag : 공기 저항. 이 값을 높이면 물속에 있는 거처럼 큰 저항을 받게 된다.

    3. Add / Remove : Add 버튼에 의해서 다른 오브젝트를 Spring으로 추가할 수 있고, Remove 버튼에 의해서 제거할 수 있다. 하지만 Self Influence는 제거할 수 없다.

    4. Tension : 얼마나 팽팽하게 당겨지는지에 대한 강도를 조절한다. 이 값이 작아지면 잘 늘어는 고무줄이 되고 높아지면 뻣뻣해서 잘 늘어나지 않는 고무줄이 된다.

    5. Damping : 얼마나 빨리 안정화되는지를 결정한다. 탄력이 줄어드는 정도 혹은 감쇄되는 정도의 역할이다.

    6. Relative / Absolute : 이 선택에 의해서 달라지는 것은 Tension Damping의 값을 입력하는 방식이 달라지게 된다. Relative Absolute중에서 어떤 것을 선택하는가에 의해서 Spring 움직임에 직접적인 변화는 전혀없다.

    • 스프링 컨트롤러의 단점인 Loop가 안되는점을 보완하기 위해 지글 본 방식을 선호한다. 지글 본은 덜렁거리는 본인데 3ds max에서는 대부분 본이 Spring을 바라보게 해서 덜렁거리도록 리깅을 하는 경우가 많다.

    • 많이 사용하면 느려지는 문제가 있다. 이것을 보완하기 위해서 Spring Quick Edit 옵션을 켜면 Spring에 관련된 연산이 조금 빨라진다. 대신 연산의 정확도가 낮아진다.

    • X / Y / Z Effect 값을 Wire Parameter로 스위치에 연결해서 스위치를 켜면 전체 Spring Effect가 정상적인 값이 되고 스위치를 끄면 전체 Spring Effect 0의 값이 되도록 설정한다.

(3) Waveform Controller

- Wave 형태의 파형을 만들어주는 Controller 이다. 거의 쓰이지 않는다.


(4) LookAt Controller

- 룩앳 컨스트레인트와 매우 비슷한 룩앳 컨트롤러이다. 예를 들어 타깃 카메라 오브젝트를 생성하면 카메라는 자동으로 카메라 타깃을 바라보게 되는데 이 때 자동으로 지정되는 컨트롤러가 룩앤 컨트롤러이다.

(5) Smooth Rotationg Controller

- 키위 위치를 옮겨줌으로서 타이밍을 바꿔줄 수 있을 뿐인 컨트롤러이며, 자주 사용되지 않으며 설명할 내용도 없는 컨트롤러


(6) On / Off Controller, Boolean Controller

- 0이나 1 둘 중의 한 가지 값만 가질 수 있는 Controller이다.

(7) Layer Controller

- Animation Layers 툴 바(Tool bar)를 중심으로 작업되는 애니메이션 레이어 기능이다.

- 페이셜 리깅에 활용하기 좋다. 캐릭터의 얼굴에 표정 연출을 위한 다수 본들이 배치되어 있고, 그 본들의 웃는 표정을 위한 본들의 Transform(포지션, 로테이션, 스케일) 전체를 Smile이라는 이름으로 Animation Layer로 만들 수 있다.Smile Layer에는 Transform 값이 변하는 애니메이션 키는 적용되지 않지만 Transform 정보가 웃는 표정이기 때문에 Smile Layer Weight 값을 0에서 100으로 증가시킬수록 웃는 표정을 만들어 낼 수 있게 된다. 비슷한 방식으로 입을 벌린다거나 눈을 깜빡이는 등의 타깃 표정들을 Layer에 추가하면 다양한 표정들이 서로 자연스럽게 섞이는 표정 애니메이션이 가능하다.


- 캐릭터 리깅에 다수의 Animation Layer가 적용되면 3ds max가 생각 이상으로 느려지는 문제가 발생한다. 

 

반응형
반응형

역관절로 접히는 본셋팅을 만들면서 세가지 컨트롤러 장단점 정리.


구현 영상 

 


1.리액션 매니저(Reaction Manager) 방식

-결론부터 말하자면 별로 추천하지 않는 방식입니다.
셋팅을 하긴 하지만, 깔끔하지 않고 버그가 많으며 예외 상황 발생시 오류 수정이 힘듭니다.

**구현방식

구현 방식은 Master가 되주는 어미본과 Master의 움직임에 의해 반응하게 될 자식본들을 Slave로 설정합니다.

그리고 State1과 State2에서 Master가 몇도 돌아갈때 SLave들이 반응해서 몇도 돌아갈지 수동으로 설정해줍니다.

그런후 Slider에 연결해 주면 위 영상과 결과가 출력됩니다.


 

 

 

2. 와이어 파라미터(Wire Parameter) 방식

- 나쁘지 않은 방식이긴 하지만, 셋팅해야 하는 절차가 많고, 와이어를 잘못 연결했을때 수정이 쉽지 않다는 단점이 있습니다.

**구현방식

상관관계를 이룰 두 본을 와이어 파라미터(Wire Parameter)를 사용하여 서로 연결해 줍니다.

여기서는 마스터가 될 Z회전축과 슬래이브의 Z회전축을 서로 연결해 준 후 마스터 축 곱하기 마이너스 회전이 하도록 셋팅하여 역관절이

발생하도록 셋팅했습니다.

그 다음본도 똑같은 방식으로 와이어로 이어 셋팅해 주면 됩니다.



 

 

 

3. Expression(Script) 방식

가장 셋팅이 간단하고, 수정도 편해서 추천하는 방식입니다.

**구현방식

마스터본은 따로 손 볼 필요없이 슬레이브 본만 셋팅해 주면됩니다.

마스터본의 Z축을 'R'이라는 변수로 선언한뒤 그 변수에 마이너스로 적절한 값을 곱해주면 역관절이 일어납니다.

위에서 플레이 되는 영상이 Expression 방식으로 구현한 화면입니다.

 

 

반응형
반응형

어깨 트위스팅을 해결하기 위해 추가한 2가지 본

 

 

 

셋팅 방식 가이드

 


1.  먼저 세 종류의 보조 더미를 설치하여 방향을 보정하는데 도움을 받아야 합니다.

(1) 어깨 보조 더미를 설치하여 상박 중심 더미를 바라보게 하면서(LooKat Contraint) UpNode 는 어깨의 원본 뼈를 따라가도록 합니다.

(2) 상박 보조 더미를 설치하여 하박을 바라보게 하면서(LooKat Contraint)  UpNode는 어깨 보조 더미를 따라가도록 합니다.

(3) 상박 중심 더미는 상박의 중심에 위치하도록 하고 상박에 링크를 걸어 줍니다.

 

2. 더미설치가 끝나면 어깨 트위스트본과 상박 트위스트본을 만들어 주니다.

(1) 상박 트위스트본을 만들어 오리엔테이션 스크립트를 걸어주고 Biped 상박과 상박 포인트 더미에 각각 3 : 7로 영향을 받도록 셋팅해 줍니다.

- 좌우 측으로 회전 시킬때 회전각에 제한을 주기 위한 셋팅입니다.

(2) 어깨 트위스트본을 만들어 오리엔테이션 스크립트를 걸어주고 상박 트위스트본과 어깨 보조더미에 각각 4 : 6으로 영향을 받도록 셋팅합니다.

- 상하좌우 모든 축에 회전각에 제한을 주기 위한 셋팅입니다.

 

셋팅 완료후 링크 구조정리 - 링크 구조도 정상적으로 맞춰주지 않으면 셋팅이 엉키게 됩니다.




셋업 후 스샷



반응형
반응형

스크립트컨트롤러가 필요한 이유

게임계에 일하는 애니메이터라면 매일 봐야 하는 바이패드..
본으로 셋팅해야 하는 불편을 없애줘
인간형 애니를 잡을때는 정말 훌륭한 툴이지만 인간의 형태를 벗어날수록
한계점이 많은 녀석입니다..


 

 

예를 들면 켄타로우스 처럼 발은 사족이고 상체는 인간형 같은..

 

 

그런 한계점을 없애기 위해서는 바이패드를 여러개 사용하여 다양한 셋팅을 할수 있습니다.
하지만, 바이패드끼리 링크를 걸면 여러가지 버그가 많이 생깁니다.
링크걸린 바이패드가 위치값을 잘못계산하여 다른 위치로 튀는 현상이 매우 빈번히 발생합니다.
또한 링크된 두번째 바이패드에는 IK(Inverse Kinematic)애니를 줄수 없어 모션 작업이 어렵습니다.
(애니메이션 작업을 해보면 알수 있는..)

그 외에도 엄청나게 많은 문제들이 생깁니다.
바이패드 특성상 맥스와 좀 따로 노는 느낌이라 그런지 맥스에서 사용하는 기능들과 상충할때가 많습니다.

이러한 문제를 스크립트 컨트롤러를 활용하여 멀티 바이패드의 여러 문제를 해결할 수 있습니다.

 

스크립트 컨트롤러 셋팅한 바이패드



영상 

 

 

- 바이패드를 세개 이용하여 제작된 셋팅입니다. 뒷다리쪽이 bip01 , 몸통이 bip02, 추가팔이 bip03입니다.

서로 다른 바이패드끼리 한개의 바이패드처럼 작동이 됩니다.

 

위 그림에 셋팅된 스크립트 컨트롤러 정리

if bip01 != undefined and bip02 != undefined then
(
 if bip01.controller.figureMode then
 (
  bip02.controller.figureMode = true
  bip03.controller.figureMode = true
  
  biped.setTransform bip02 #pos dm.transform.pos false
  biped.setTransform bip02 #rotation dm.transform.rotation false
  biped.setTransform bip02 #scale dm.transform.scale false
  
  biped.setTransform bip03 #pos (biped.getTransform bip02 #pos) false
  biped.setTransform bip03 #rotation (biped.getTransform bip02 #rotation) false
  biped.setTransform bip03 #scale (biped.getTransform bip02 #scale) false
  
  biped.setTransform bip03Spine00 #pos (biped.getTransform bip02Spine00 #pos) false
  biped.setTransform bip03Spine00 #rotation (biped.getTransform bip02Spine00 #rotation) false
  biped.setTransform bip03Spine00 #scale (biped.getTransform bip02Spine00 #scale) false
  biped.setTransform bip03Spine01 #rotation (biped.getTransform bip02Spine01 #rotation) false
  biped.setTransform bip03Spine01 #scale (biped.getTransform bip02Spine01 #scale) false
  biped.setTransform bip03Spine02 #rotation (biped.getTransform bip02Spine02 #rotation) false
  biped.setTransform bip03Spine02 #scale (biped.getTransform bip02Spine02 #scale) false
  
 
 )
 else
 (
  bip02.controller.figureMode = false
  bip03.controller.figureMode = false
 )

 bip02.transform = dm.transform
 bip03.transform = bip02.transform
 bip03Spine00.transform = bip02Spine00.transform
 bip03Spine01.transform = bip02Spine01.transform
 bip03Spine02.transform = bip02Spine02.transform 
)

 

 

스크립트 콘트롤러 제어를 통해 배운점

1. 손으로만 가능할거라 생각했던 바이패드 셋팅을 스크립트를 활용한 특수 셋팅을 알게됐습니다.

2. 중간더미를 적절히 사용하지 않으면 여전히 오류가 발생할수 있습니다. 이것은 손으로 셋팅할때도 마찬가지였습니다.

 

반응형
반응형

이번에 만든 툴은 SpaceWarpToMorph(스페이스워프 투 모프)

라는 툴로서

맥스의 스페이스 워프 툴을 활용하여 물결치는 메시를 제작했지만, 엔진(유니티,언리얼)에는 들어가지지가 않습니다.

유니티나 언리얼에도 이런 애니를 넣도록 해주는 기능도 없습니다.

그럴때 맥스에서 제작된 스페이스 워프 애니를 모핑 애니데이터로 변경하여 버텍스애니를 적용하면

엔진에 불러올수 있습니다.

하지만, 이것을 수동으로 애니를 넣으려면 매프레임마다 오브젝트를 복사하여 키를 찍어주는 엄청난 노가다

작업을 해야하는데, 이 툴을 활용하면 버튼한방에 마무리됩니다.

 

 

 

문제의 발생과 피드백 상황

1. try( )catch( ) 명령어를 잘못사용하여 문제 발생
-catch 옆에 ( ) 안쳐서 버그 발생

2. 오브젝트에 모핑 모디파이를 추가하기 위해서는 반드시 오브젝트가 선택되어 있어야 하고
 모디파이 모드임을 알려줘야 하는데 빼먹었음.
max modify mode
select morpherObj

3. 모핑의 오브젝트를 등록하고도 Autoload 를 활성화 시키지 않으면 갱신이 안되는데 빼먹음

morpherObj.modifiers[#Morpher].Autoload_of_targets = 1

1값이면 true 0값이면 false

Default가 false라 발생한 문제

4. for문에서는 ( ) 를 한줄정도 생략이 가능한데, 어느 부분에서 쓰고 빼는지에 대해서 어려움을 느낌.

5. 버그가 엄청 발생했는데, print문을 활용하는 능력이 떨어져 버그 잡는데 많은 시간이 소요됨

 

 

본 공부를 통해 깨닫고 배운 내용

1. 함수 선언의 개념에 대해서 학습 - fn 을 통해 함수를 정의할 수 있고, 함수를 파일로 저장하여
include 명령어로 활용할수 있다.

2. for문과 if문에 대한 반복학습을 통해 개념 파악
- for문으로 곱하기 조차 어려워하던 수준인데.. 이제야 그 수준을 살짝 탈피해 가는거 같습니다..ㅠ

3. 레퍼런스 찾기 연습을 통해 버그나 코딩이 막힐때 해결방법에 대해 숙지
- 여전히 더 많은 훈련이 필요함.

4. 배열의 사용법과 append의 사용법 숙지

5. animationRange 활용법 숙지

6. print 문을 활용하여 버그 잡기

 


스크립트 코드



global g_MeshToMorph


try(destroydialog g_MeshToMorph)catch()


rollout g_MeshToMorph "버텍스애니를 모핑으로"
(
 --로컬로 픽 오브젝트 변수 선언--------------------------------------------------------- 
 local setMainObj
 ----------------------------------------------------------------------------------- 
 
 -- FilterMesh ---------------------------------------------------------------------------
 fn FilterMesh obj =
 (
  if iskindof obj PolyMeshObject or iskindof obj Editable_Mesh then
   return true
  else
   return false
 )

 -----------------------------------------------------------------------------------
 --레이아웃
 -----------------------------------------------------------------------------------
 pickbutton pkn_MeshButton "오브젝트 선택" witdh:180 Filter:FilterMesh
 spinner spn_StartFrame "시작프레임: " range: [-9999,9999,0] type:#integer
 spinner spn_EndFrame "끝프레임: " range: [-9999,9999,10] type:#integer
 button btn_make_morph "모핑시작"
 hyperLink hlnk_Frame "100f" color:(color 28 28 177) align:#left offset:[65,1]
 -----------------------------------------------------------------------------------
 
 -----------------------------------------------------------------------------------
 --한계치 넘어가면 색깔 변하게__
 -----------------------------------------------------------------------------------
 fn SetFrameHlink =
 (
  -- String --
  intervalFrame = spn_EndFrame.value - spn_StartFrame.value + 1
  hlnk_Frame.text = "" -- 한번 지워줘야 잔상이 생기지 않음
  hlnk_Frame.text = (intervalFrame as string) + "f"
  
  -- Color --
  if intervalFrame > 0 and intervalFrame < 101 then
   hlnk_Frame.color = color 28 28 177
  else
   hlnk_Frame.color = color 141 7 58
 )
 
 -----------------------------------------------------------------------------------
 --모핑버튼 활성화 조건--
 -----------------------------------------------------------------------------------
 fn IsValidMorpher =
 (
  startFrame = spn_startFrame.value
  endFrame = spn_endFrame.value
  
  if  startframe - endframe < 0 and abs(startFrame - EndFrame) <100 then
  (
   if SetMainObj != undefined then
    btn_make_morph.enabled =  true
   else
    btn_make_morph.enabled =  false
  )
  else
  (
   btn_make_morph.enabled =  false
  )
  
 )
 
 -----------------------------------------------------------------------------------
 --픽 버튼 누를때 
 -----------------------------------------------------------------------------------
 on pkn_MeshButton picked obj do
 (
  pkn_MeshButton.text = obj.name
  SetMainObj = obj
  
  IsValidMorpher()
  
 )
 -----------------------------------------------------------------------------------
 --시작프레임 수치는 아래 함수를 따른다
 -----------------------------------------------------------------------------------
 on spn_StartFrame changed val do
 (
  IsValidMorpher()
  SetFrameHlink()
  
 )
 -----------------------------------------------------------------------------------
 --끝프레임 수치는 아래 함수를 따른다 
 -----------------------------------------------------------------------------------
 on spn_EndFrame changed val do
 (
  IsValidMorpher()
  SetFrameHlink()
 )
 -----------------------------------------------------------------------------------
 --가장 중요한 모핑시작 버튼을 누를때의 반응설정--
 -----------------------------------------------------------------------------------
 on btn_make_morph pressed do
 (
  startFrame = spn_startFrame.value
  endFrame = spn_EndFrame.value
  
  --애니메이션 구간설정
  animationRange = interval startFrame endFrame
  
   
  targetObjs = #()  --복사될 오브젝트들을 배열로 변수 선언.  배열 번수는 복수형으로 쓰자
  objCount = 0
  
  --프레임 수 만큼 오브젝트 복사  
  for i = startFrame to endFrame do
  (
   slidertime = i
   objCount += 1
   newObj = snapshot SetMainObj
   append targetObjs newobj
   
   --복사된 오브젝트와 원본 오브젝트를 숨겨야 중간에 디버그하기가 편함
   newobj.ishidden = true
   setMainObj.ishidden = true
  )
  
  --모핑추가할 오브젝트 제어
  morpherObj = copy SetMainObj
  convertto morpherObj Editable_Poly
  addmodifier morpherObj(morpher())
  
  
  --모핑 리스트를 자동으로 갱신하기 위해서 필요한 명령어
  morpherObj.morpher.Autoload_of_targets = 1
 
   
  --모핑 오브젝트에 복사된 오브젝트 프레임순으로 등록
  for i=1 to targetObjs.count do  --모핑되는 인덱스를 반복문으로 설정하여 각 인덱스별로 오브젝트가 설정되도록 하기위한 반복문
  (
   WM3_MC_BuildFromNode morpherObj.morpher i targetObjs[i]  -- 모핑 오브젝트의 인덱스 i  그 인덱스에 들어갈 타겟 오브젝트 역시 i
  )
  
  --아래 두 명령어 없으면 실행 안됨
  max modify mode
  select morpherObj
  
  --적용된 모핑리스트들에 키 값 추가
  morpherCount = 0
  for i = startFrame to endFrame do
  (
   morpherCount += 1
   for k = -1 to 1 do
   addnewkey morpherObj.Morpher[morPherCount].controller.keys(i + k) --for문에 ()한개쯤은 생략할 수 있다.
   
    morpherObj.Morpher[morPherCount].controller.keys[2].value= 100
  )
  
  delete targetObjs
  delete SetMainObj
   
  
 )
    
   
)

createdialog g_MeshToMorph width:200 height:200

반응형
반응형
 바이패드를 박스모드로 변환시켜주는 툴입니다. 이 툴은 애니메이터들에게 필요한 툴로서 바이패드를 박스형태로

변환시켜 모델 원본을 보는데 방해를 받지 않고 애니메이션 작업을 할 수 있도록 하는 툴입니다.

 

1. 툴 화면


 

2. 전체 바이패드 전환


 

3. 선택 바이패드 전환


 

- 이 스크립트 제작을 통해 배운 내용

1. for문의 사용법 숙지(반복문)

2. 주석처리 방식 숙지

3. true와 false 수치를 글로별변수로 선언하여 제어하는 방법 숙지

4. 메크로 버튼을 만들어 나만의 메뉴를 생성하는 방식

 

코드 원문

--==========================================================================================================
--==========================================================================================================

-- 바이패드 박스 전환툴 : 바이패드를 박스모드로 변환해 해주는 Tool입니다.
-- 버그나 관련 내용 문의 요청 언제나 환영

-- 제작 : Taeyo

--==========================================================================================================
--=====================================================================================================


--박스모드와 플로터에 대한 글로벌변수 선언---------
Global BipedToBoxFloater
Global isBoxMode = true


--===========================================================================================================

---롤아웃지정------

--===========================================================================================================
rollout BipChange "바이패드 박스모드로 변환"
(

 --================================================================================== 
 -----버튼 지정----
 --================================================================================== 
 button BtnBipToBox1 "선택바이패드만전환"
 button BtnBipToBox3 "바이패드 박스모드전환"

 
 --================================================================================== 
 -----선택된 바이패드만 전환시킴-----
 --==================================================================================
 on BtnBipToBox1 pressed do
 (
  
  ----------------------------------------------------
  --SelObj선언---
  ----------------------------------------------------
  SelObj = $
  

  ----------------------------------------------------
  --선택된거 없을때---
  ----------------------------------------------------
  if selection.count == 0 then
   (
    messagebox "선택된게 없습니다."
    return 0
   )
  
  ----------------------------------------------------
  --for문을 통해 선택된 오브젝트가 무엇인지 판별----
  ----------------------------------------------------
    for SelObj in $selection do
   ( 
  
   if iskindof SelObj Biped_Object then
   (
    SelObj.boxmode = isBoxMode
   )
   else
   (
    SelObj.boxmode = isBoxMode
    messagebox "바이패드가 아닙니다."
    return 0
   )
  
   
  )
  
  ---------------------------------------------------------------------
  --isBoxMode로 선언된  글로벌변수를 통해 on/off를 지정할수 있는 함수--------------------------
  ---------------------------------------------------------------------
  if isBoxMode then
  (
   isBoxMode = false
  )
  else
  (
   isBoxMode = true
   return 0
  )
  clearselection()
 )
 
 --==================================================================================
 -------전체 씬을 뒤져서 바이패드만 골라 박스모드로 변환시켜줌------------------------
 --==================================================================================
 on BtnBipToBox3 pressed do
 (
  
  
  ----------------------------------------------------
  --for문을 통해 전체 씬의 오브젝트를 검색함--------------------------
  ----------------------------------------------------
  for obj in objects do
  (
   if iskindof obj Biped_Object then
    obj.boxmode = isBoxMode
  )
  
  ----------------------------------------------------
  --isBoxMode로 선언된  글로벌변수를 통해 on/off를 지정할수 있는 함수--------------------------
  ----------------------------------------------------  
  if isBoxMode then
  (
   isBoxMode = false
  )
   else
  (
   isBoxMode = true
   return 0
  )
   
 )
   
  
)

--===========================================================================================================

------재실행시 기존 창 지우기 위해 트라이 캐치 실행---------------------------------------------

--===========================================================================================================
try(CloseRolloutFloater BipedToBoxFloater) catch()


--===========================================================================================================

---실행창 생성--------------------------------------------

--===========================================================================================================

BipedToBoxFloater = newrolloutfloater "바이패드 박스로 변환툴" 200 130
addrollout BipChange BipedToBoxFloater

반응형
반응형

 

1.메쉬 LOD 변환툴


- LOD를 적용할 메쉬를 선택하여 수치를 정하여 메쉬를 변환시켜주는 툴입니다.

 

1. 툴 화면

 

2. 비대칭 실행시 적용화면 - 원본 오브젝트의 50퍼센트의 LOD를 적용하여 비대칭 메쉬를 새로 생성합니다.


 

 3. 대칭 실행시 적용 화면 - 원본 오브젝트의 50퍼센트의 LOD를 적용하여 대칭 메쉬를 새로 생성합니다.

 

- 이 스크립트 제작을 통해 배운 내용

1. if문의 사용법 숙지(조건문)

2. roll과 button을 사용하여 메뉴 창 생성하는 법

3. 오브젝트의 모디파이의 속성을 제어하는 방법

  

코드 원문

global TEST

rollout noskin "스킨없을때"
 
(
 spinner noskin1 "버텍스수치" range:[0,100,50] type:#integer
 button btn1 "비대칭"
 button btn2 "대칭"
 
 
 on btn1 pressed do
 (
  if selection.count != 1 then
  (
   messagebox "한개만 선택하세요"
   return 0
  )
  
  if $.modifiers[#skin] == undefined then
  
  (
   local VF = noskin1.value
   
   a= $
   copyobj = copy$
   select copyobj
   
   --modPanel.setCurrentObject $.baseObject
   modPanel.addModToSelection (MultiRes ()) ui:on
   $.modifiers[#MultiRes].reqGenerate = on
   $.modifiers[#MultiRes].vertexPercent = VF
   maxOps.CollapseNodeTo $ 1 off
   
   clearselection()
   
   delete a
   
   select copyobj
  )   
  else
  (
   messagebox "스킨없애시오"
   return 0
  )
  
 )
 ----------스킨 없고 대칭 일때-------------------
 on btn2 pressed do
 (
  if selection.count != 1 then
  (
   messagebox "한개만 선택하세요"
   return 0
  )
  
  if $.modifiers[#skin] == undefined then
  
  (
   local VF = noskin1.value
   
   
   a= $
   copyobj = copy$
      
   
   ---헬퍼박스 생성----
   Box lengthsegs:1 widthsegs:1 heightsegs:1 length:5000 width:5000 height:5000  pos:[0,0,0]  name:"Helper_Box"
   select $Helper_Box
   max rotate
   toolMode.coordsys #local
   rotate $(angleaxis -90 [0,1,0])
   move $ [-0.1,0,0]
   macros.run "Modifier Stack" "Convert_to_Poly"
   
  
   select copyobj
   
   modPanel.addModToSelection (Vol__Select ()) ui:on
   $.modifiers[#Vol__Select].level = 1
   $.modifiers[#Vol__Select].volume = 3
   $.modifiers[#Vol__Select].node = $Helper_Box
   modPanel.addModToSelection (Edit_Poly ()) ui:on
   subobjectLevel = 1
   max delete
   maxOps.CollapseNode $ off 
   modPanel.addModToSelection (MultiRes ()) ui:on
   $.modifiers[#MultiRes].reqGenerate = on
   $.modifiers[#MultiRes].vertexPercent = VF
   modPanel.addModToSelection (symmetry ()) ui:on
   $.modifiers[#Symmetry].threshold = 0
   maxOps.CollapseNode $ off
    
   clearselection()
   
   delete a 
   delete $Helper_Box
      
   select copyobj
  )   
  else
  (
   messagebox "스킨없애시오"
   return 0
  )
    
 )

)


----------------스킨있을때-------------------------------------

rollout yeskin "스킨있을때"
 
(
 spinner yeskin1 "버텍스수치" range:[0,100,50] type:#integer
 button btn3 "비대칭"
 button btn4 "대칭"
 
 on btn3 pressed do
 (
  if selection.count != 1 then
  (
   messagebox "한개만 선택하세요"
   return 0
  )
  
  if $.modifiers[#skin] != undefined then
  (
   local VF = yeskin1.value
   
   a= $
   copyobj = copy$
   select copyobj
   
   $.modifiers[#Skin].Enabled = off
   modPanel.setCurrentObject $.baseObject
   modPanel.addModToSelection (MultiRes ()) ui:on
   $.modifiers[#MultiRes].reqGenerate = on
   $.modifiers[#MultiRes].vertexPercent = VF
   maxOps.CollapseNodeTo $ 2 on
   $.modifiers[#Skin].Enabled = on
   
   clearselection()
   
   delete a
   
   select copyobj
  )  
 
  else
  (
   messagebox "스킨을 넣으세요"
  )
 
 )
  
 ------------스킨 있고 대칭 일때---------------------------------------------------------------
 on btn4 pressed do
 (
  if selection.count != 1 then
  (
   messagebox "한개만 선택하세요"
   return 0
  )
  
  if $.modifiers[#skin] != undefined then
  
  (
   local VF = yeskin1.value
   
   
   a= $
   copyobj = copy$
      
   
   ---헬퍼박스 생성----
   Box lengthsegs:1 widthsegs:1 heightsegs:1 length:5000 width:5000 height:5000  pos:[0,0,0]  name:"Helper_Box"
   select $Helper_Box
   max rotate
   toolMode.coordsys #local
   rotate $(angleaxis -90 [0,1,0])
   move $ [-0.1,0,0]
   macros.run "Modifier Stack" "Convert_to_Poly"
   
  
   select copyobj
   
   $.modifiers[#Skin].Enabled = off
   modPanel.setCurrentObject $.baseObject
   modPanel.addModToSelection (Vol__Select ()) ui:on
   $.modifiers[#Vol__Select].level = 1
   $.modifiers[#Vol__Select].volume = 3
   $.modifiers[#Vol__Select].node = $Helper_Box
   modPanel.addModToSelection (Edit_Poly ()) ui:on
   subobjectLevel = 1
   max delete
   maxOps.CollapseNodeTo $ 2 off
   modPanel.setCurrentObject $.baseObject
   modPanel.addModToSelection (MultiRes ()) ui:on
   $.modifiers[#MultiRes].reqGenerate = on
   $.modifiers[#MultiRes].vertexPercent = VF
   modPanel.addModToSelection (symmetry ()) ui:on
   $.modifiers[#Symmetry].threshold = 0
   maxOps.CollapseNodeTo $ 2 on
   $.modifiers[#Skin].Enabled = on
    
   clearselection()
   
   delete a 
   delete $Helper_Box
      
   select copyobj
  )   
  else
  (
   messagebox "스킨을 달라"
   return 0
  )
 )
  
)


TEST = newrolloutfloater "공부용 LOD시스템" 200 200

addrollout noskin TEST
addrollout yeskin TEST

 

반응형
반응형

언리얼 튜토리얼에 올라온 비헤이비어 트리 쿽스타트 가이드를 토대로

평소에는 천천히 돌아 다니다가 주인공을 만나면 속도를 내서 달려올수 있도록 함수를 추가해 봤습니다.

https://docs.unrealengine.com/latest/KOR/Engine/AI/BehaviorTrees/QuickStart/index.html

 

 

블루프린트 함수 추가 내용

1. AI 캐릭터 추가 내용 - 일반 속도를 60으로 규정하는 함수 추가. speed rate 값을 캐싱하여 속도 조절 가능

 

2. 일반이동 BTT 추가내용

-문서에서는 기본으로 제공하는 노드로 구성되어 있는데, 그 부분을 제거하고 아래 내용을 추가해주면 됩니다.

원본 - https://docs.unrealengine.com/latest/KOR/Engine/AI/BehaviorTrees/QuickStart/12/index.html

 

 

3.  주인공을 만났을때의 BTT 추가내용

원본 - https://docs.unrealengine.com/latest/KOR/Engine/AI/BehaviorTrees/QuickStart/10/index.html

원본BTT에 아래 내용만 추가하면 됩니다.

 

 

4. 원본에서 비헤이비어 트리 구조 변경

원본에는 기본 트리를 사용하기 때문에 여러가지 조건문이 붙지만, 함수안에 이동 조건을 걸어놨기 때문에

필요없는 부분들이 생겼습니다.

원본 구조 - https://docs.unrealengine.com/latest/KOR/Engine/AI/BehaviorTrees/QuickStart/12/index.html

변경 구조


 

 

완료영상

 

 

반응형
반응형

스켈레탈 메시를 처음 생성하면 피직스 에셋이 자동 생성됩니다.

자동 생성이 안됐어도 스켈레탈 메시를 누르고 피직스 추가를 하면 피직스를 새로 만들수 있습니다.

 

자동 생성된 피직스는 모양과 크기가 제대로 설정되어 있지 않아 시뮬레이션 결과가 엉망으로 나옵니다.

처음 생성했을때의 피직스 모양 - 모양과 크기가 엉망입니다..

피직스 셋팅이 안된 상태의 시뮬레이션 영상 -  아 흉해라.. 

 

이 상태로 게임에 쓸수 없기에 각 관절마다 피직스 셋팅을 해줘야 합니다.

 

설정가이드

1. 각 관절이 전부 Sphyl 형태로 되어 있는데, 계산이 많이 필요한 허벅지나 양쪽 팔등만 설정하고 나머지는 Box 형태로

설정해 줍니다.

 

2. 관절형태를 설정후 크기 및 방향등을 재설정해 줍니다.

-각 관절이 겹치게 될경우 물리 계산이 꼬이게 되므로 서로 겹치지 않도록 하고 사이즈가 너무 크지 않고 설정해 줍니다.

 


3. 각 관절별 사이즈 조절이 끝나면 컨스트레인트 각도 설정을 해줘야합니다.

- 관절 사이즈보다 컨스트레인드 각도와 위치가 더 큰영향을 끼치게 되므로 많은 테스트가 필요한 부분입니다.

여기서 각 관절이 얼마만큼 꺽이도록 할것인지 설정하고, 방향은 어느 쪽으로 향하는지 등을 설정할 수 있습니다.

여기서 주의할 점은 컨스트레인트는 한번 삭제하면 복구하기가 굉장히 까다롭기 때문에(거의 다시 만들어야함..)

삭제할때 신중을 기해야 합니다.

 

4. 새로 셋팅된 피직스형태

 

 

위와 같이 셋팅을 마치고 나면 아래처럼 시뮬레이션이 출력됩니다. 아직 완벽하진 않지만, 점점 좋아질것을 기대하며.. 

 

오늘 처음 해본거라 아직 셋팅이 완벽하지 않아 여전히 부족한 부분이 있지만, 앞으로 많은 테스트를 거치다 보면

이쁜 결과물을 충분히 만들어 낼수 있을거라 기대합니다.

앞으로 배포될 APK에 일단 주인공만 포함될 예정이며 좀더 연구해 본후 몬스터에도 적용시킬지 검토중입니다.

 

반응형
반응형

 

 

 

 

 

 

 

언리얼 파츠 작업시 유의사항

- 스켈레탈 메시인경우 맥스에서 여러개의 모델로 디테치가 되어 있어도 언리얼로 임포트를 하면 메시가 전부 컴바인되어 임포트 됩니다.(스태틱 메시는 나뉘어서 부르는게 가능)

따라서 파츠를 나눌 부분은 맥스에서 익스포트시 따로 선택하여 익스포트 한후 언리얼로 임포트 해 올때 원본 모델의 스켈레톤과 피직스를 공유 받으면 파츠별로 붙혔다 뗐다가 가능해 집니다.

- 그리고 모델링 주실때 링크 구조로 주셨는데, 모델링은 링크 구조 없이 주셔야 문제가 없습니다.

스켈레탈 메시를 링크구조로 익스포트 하면 제일 상위 메시만 익스포트 되고 나머지는 익스포트 되지 않습니다.

 

 

파츠 분리 익스포트 방식

1. 메인 바디가 될 부분을 먼저 익스포트 한다.

 

 

2. 파츠로 나뉘어질 모델과 메인 바디와 똑같은 본을 선택후 각각 익스포트 한다.

 


 

3. 메인 바디를 언리얼로 임포트 한다.

-원본 모델이므로 스켈레톤과 피직스를 새로 생성한다.

 

-임포트후 생기는 파일들 : 메시, 스켈레탈, 피직스, 메터리얼

 

 

4. 그리고 파츠모델들을 각각 임포트해 온다.

-임포트시 기존에 생성된 메인 바디와 스켈레탈과 피직스를 상속받도록 설정한후 임포트한다.

 

5. 그렇게 불러진 파츠 모델들은 아래 그림처럼 몸에 붙혔다 뗐다 하는것이 가능해집니다.


 

 

반응형
반응형

스켈레톤을 교체하게 된 원인 - 문제가 발생했던건 prop1의 위치였습니다,

발사 모션을 할때 Spine 본 아래로만 모션이 들어가도록 설정했는데,

prop1 본이 스파인본 보다 상위에 있어 발사 모션을 할때 총이 따라오지 않는 문제가 발생했습니다.

 

원본데이터를 바꿔버리면 쉽지만, 내부망에 이미 등록되어 있는 주인공 데이터의 원본 모델링 소스를 바꿔버리면

여기저기 미싱이 나기 때문에 스켈레톤만 교체하는 방법에 대해 공유합니다.

 

 

1. 맥스에서 다시 본위치를 설정후 메쉬와 애니메이션을 전부 다시 뽑습니다.


 

 

2. 그 후 뽑힌 모델링 파일의 이름을 원본이름과 다르게 설정해서 임포트 해 줍니다.

- 여기서 중요한 것은 애니 이름은 그대로 뽑고 원본 모델 소스 이름만 다르게 해줍니다.


 

3. 새로 뽑은 모델링 FBX 데이터(pawn_women2)를 언리얼에 임포트해 오면 세가지 파일이 생깁니다.

- 여기서 스켈레톤외의 파일들은 전부 제거해 줍니다. 필요없기 때문에...

 

 

4. 기존 원본 모델링 FBX 데이터(pawn_women)의 스켈레톤을 새로 뽑아서 생성된 스켈레톤 데이터로

다시 할당해 줍니다.


 

5. 새로 할당후 반드시 리임포트를 해줘야 정상적으로 변환됩니다.

- 리임포트를 해야 정상적으로 나온다는것을 뒤늦게 알게 되어 엄청 헤맸네요..ㅠㅠ

**여기서 중요한 사항은 기존에 임포트했던 원본 FBX 파일이 기억되어 있으면 새소스를 불러올수 없으니

기존 원본 fbx는 반드시 삭제해 줍니다.


 

6. 모델링 임포트가 끝나면 적용된 애니메이션들도 전부 리임포트 해줘야 정상적으로 모션이

출력됩니다.

- 리임포트를 해주지 않으면 모션이 전부 미싱나거나 깨져서 나오게 됩니다.

 

 

위 작업은 외부망에서 테스트 할때는 문제되는 내용이 아니지만, 내부망에서 프로그래머들과 협업시

원본 모델링 소스가 바뀔 경우 많은 데이터에 오류가 발생하므로 원본 모델링 데이터를 바꾸지 않고

스켈레톤을 바꾸기 위한 방법이었습니다.

쉽게 바꿀수 있을거라 생각하고 접근했다가 반나절을 날려 보냈네요..ㅠ

잊어버릴까봐 메모해 둡니다~

 

반응형

+ Recent posts