Op API

Op API는 장면 그래프 조작 및 속성 수정을위한 강력한 C ++ 플러그인 인터페이스를 제공합니다. 모든 Katana배송 된 Op는 Op API로 작성됩니다. 이 API를 사용하면 장면 데이터를 임의로 작성하고 조작 할 수있는 플러그인을 작성할 수 있습니다. Op에는 여러 장면 그래프 입력이 제공 될 수 있으며 해당 입력에서 임의의 위치에있는 속성 데이터를 검사하고 현재 위치에서 속성을 작성, 삭제 및 수정할 수 있습니다. 운영 담당자는 자녀 위치를 생성 및 삭제하거나 자신을 삭제할 수도 있습니다.

다시 말해, 당신이 할 수있는 모든 것 Katana 노드를 사용하면 Op로 할 수 있습니다. Ops로 수행 할 수있는 작업의 예는 다음과 같습니다.

상황 인식 생성기 및 가져 오기 도구를 사용하여

고급 사용자 정의 병합 작업

계층 구조 인스턴스화

프래그먼트 파트로 네트워크 자료 구축

군중을위한 지오메트리 생성 처리.

노트 :  Op API는 장면 그래프 생성기 및 속성 수정 자 플러그인 API를 대신하기위한 것이지만 2.0v1 이후 버전에서는 계속 사용할 수 있습니다. Katana.

이 섹션에서는 Op API의 다음 요소를 다룹니다.

The cook interface, 그것이 무엇이며 Geolib3에 어떻게 적용되는지.

Op arguments 어린이에게 전달되는 인수를 수정합니다.

Scene graph creation 및 장면 그래프 위치를 생성 및 삭제하는 방법과 Op가 실행되는 위치를 제어하는 방법을 포함한 계층 구조 토폴로지 관리.

Reading scene graph input 잠재적으로 많은 입력과 관련 문제로부터

CEL 그리고 일반적인 작업을 수행하기 위해 Op 라이터로서 사용할 수있는 기타 유틸리티 기능.

Integrating your Op 노드 그래프와 함께.

위의 개념에 대한 구체적인 예는 $KATANA_HOME/plugins/Src/Ops 다수의 핵심 Ops에 대한 소스 코드가 유지되는 디렉토리. 다음은 이러한 Op 중 일부에 대한 간략한 개요와 현재 사용중인 위치의 예입니다.

AttributeCopy-SceneCopy의 한 지점에서 다른 지점으로 속성을 복사하는 AttributeCopy 노드에 대한 구현을 제공합니다.

AttributeSet-AttributeSet 노드의 백엔드로 들어오는 장면 그래프의 임의 위치에서 속성을 설정, 변경 및 삭제할 수 있습니다.

HierarchyCopy-AttributeSet Op와 마찬가지로 HierarchyCopy 노드의 백엔드이므로 장면 그래프 계층의 임의 부분을 장면 그래프의 다른 부분으로 복사 할 수 있습니다.

프룬-장면에서 제공 한 CEL 표현식과 일치하는 위치를 제거합니다.

StaticSceneCreate-제공하는 인수 세트를 기반으로 정적 계층을 생성합니다. 이 Op는 HierarchyCreate의 핵심이며 다른 Ops와 노드에서 광범위하게 사용되어 필요한 위치와 속성의 계층을 생성합니다. 예를 들어 CameraCreate 노드는 StaticSceneCreate Op를 사용하여 카메라 위치에 필요한 계층을 생성합니다.

쿡 인터페이스

쿡 인터페이스는 Geolib3가 Op의 기능을 구현하기 위해 제공하는 인터페이스입니다. 귀하의 Op가 cook() 메소드가 호출됩니다. 위에서 설명한 것처럼이 인터페이스는 인수를 조사하고 장면 그래프 토폴로지를 작성 또는 수정하고 장면 그래프 입력을 읽을 수있는 메소드를 제공합니다. cook 인터페이스에서 사용 가능한 메소드의 전체 목록을 찾을 수 있습니다. $KATANA_HOME/plugin_apis/include/FnGeolib/op/FnGeolibCookInterface.h.

옵션 인수

앞에서 설명한 것처럼 Ops에는 업스트림 Ops 및 Op 인수로 만든 장면 그래프 입력의 두 가지 입력 형식이 제공되는데, Ops는 동작 방식을 구성하기 위해 Op에 전달됩니다. 사용자 인수의 예로는 Op가 실행될 위치,로드해야하는 지오메트리 캐시를 가리키는 파일 경로 또는 Op가 작성해야하는 하위 위치의 목록을 설명하는 CEL 문이 있습니다.

먼저 인수를 심문하는 간단한 사례를 살펴본 다음, 재귀 적으로 인수를 하위 위치로 전달하는 일반적인 패턴을 살펴 보겠습니다.

인수 인수

인수는의 인스턴스로 Op에 전달됩니다. FnAttribute 수업. cook 인터페이스에는 Op 인수를 검색하기위한 다음 함수 호출이 있습니다.

FnAttribute::Attribute getOpArg(     const std::string& specificArgName = std::string()) const;

예를 들어 StaticSceneCreate Op는 GroupAttribute라는 a 지정된 위치에 설정할 값이 포함 된 속성 목록이 포함되어 있습니다. 이것은 다음과 같이 나타납니다.

StaticSceneCreate는 a 다음과 같이 인수 :

FnAttribute::GroupAttribute a = interface.getOpArg("a"); if (a.isValid()) {     for (int i = 0; i < a.getNumberOfChildren(); ++i)     {         interface.setAttr(a.getChildName(i), a.getChildByIndex(i));     } }

노트 :  속성을 사용하여 검색 한 후 속성의 유효성을 확인하는 것이 중요합니다. isValid() 요구. cook 인터페이스에서 속성을 반환 할 때마다 속성의 유효성을 확인해야합니다.

자식 위치에 인수 전달

Op가 실행되는 하위 위치로 인수를 전달하는 일반적인 재귀 접근 방식이 있습니다. StaticSceneCreate Op는이 패턴을 아주 잘 보여줍니다.

StaticSceneCreate는 전달 된 인수 중 하나의 값을 기반으로 속성을 설정하고 하위 위치의 계층 구조를 작성합니다. 이 인수는 각 위치에 대해 설명하는 GroupAttribute입니다.

a -속성 값

c -자녀 위치의 이름

x -해당 위치에서 추가 Op을 평가해야하는지 여부

생성 된 자식에게 인수를 전달하기 위해 하위 계층을 제거합니다. c 논쟁과 자식에게 전달합니다. 개념적으로 다음과 같이 고려할 수 있습니다 (세부 사항 ax 간결성을 위해 생략 됨) :

현재 위치에서 실행중인 Op가 읽습니다. a, c , x. 각 자식에 대해 c GroupAttribute의 이름 (예 : child1 / child2)으로 새 자식 위치를 만들고 GroupAttribute를 해당 위치의 인수로 전달합니다.

코드에서 자식을 만들면 다음과 같은 키 함수 호출이 사용됩니다.

void createChild(const std::string& name,                  const std::string& optype = "",                  const FnAttribute::Attribute& args = FnAttribute::Attribute(),                  ResetRoot resetRoot = ResetRootAuto,                  void* privateData = 0x0,                  void (*deletePrivateData)(void* data) = 0x0);

그만큼 createChild() 함수는 Op가 평가되는 위치의 하위를 작성합니다. 이 함수는 또한 런타임에서 실행해야하는 Op 유형을 런타임에 지시합니다 (기본적으로 호출 된 Op와 동일한 유형의 Op createChild()) 및 전달해야 할 인수. StaticSceneCreate에서 이것은 다음과 같습니다.

for (int childindex = 0; childindex < c.getNumberOfChildren(); ++childindex) {     std::string childName = c.getChildName(childindex);     FnAttribute::GroupAttribute childArgs = c.getChildByIndex(childindex);     interface.createChild(childName, "", childArgs); }

장면 그래프 생성

Op의 주요 작업 중 하나는 장면 그래프 위치 및 속성을 생성하는 것입니다. Op API는이를 위해 다양한 기능을 제공합니다. 장면 그래프 토폴로지를 수정하고 Op 실행을 제어하는 데 사용할 수있는 5 가지 주요 기능이 있습니다. 아래에서 설명합니다.

노트 :  여기에 설명 된 기능 세트와 설명 된 기능 세트의 차이점을 기억하는 것이 중요합니다. 씬 그래프 입력 읽기. 여기에 설명 된 모든 기능은 output of an Op at a given Scene Graph location. 에 설명 된 기능 씬 그래프 입력 읽기 씬 그래프 데이터를 읽는 것과 만 관련이 있습니다. input 주어진 씬 그래프 위치에서 Op의 값을 변경할 수 없습니다.

setAttr () 함수

void setAttr(const std::string& attrName,              const FnAttribute::Attribute& value,              const bool groupInherit = true);

그만큼 setAttr() 기능을 사용하면 현재 평가중인 위치에서 속성 값을 설정할 수 있습니다. 예를 들어 StringAttribute Op의 루트 위치에서 다음을 수행 할 수 있습니다.

if (interface.atRoot()) {     interface.setAttr("myAttr", FnAttribute::StringAttribute("Val")); }

현재 평가중인 지역 이외의 지역에서는 속성을 설정할 수 없습니다. 전화하면 setAttr() 동일한 위치에서 주어진 속성 이름에 대해 여러 번 마지막으로 호출 된 이름이 사용됩니다. 그만큼 groupInherit 매개 변수는 속성이 해당 하위 항목에 의해 상속되어야하는지 여부를 판별하는 데 사용됩니다.

노트 :  이후 setAttr() Op의 출력에 값을 설정하는 동안 getAttr() 호출시 주어진 입력에서 불변 값을 읽고 있음 setAttr() 바로 뒤에 getAttr(), 결과는 여전히 setAttr().

createChild () 함수

void createChild(const std::string& name,                  const std::string& optype = "",                  const FnAttribute::Attribute& args = FnAttribute::Attribute(),                  ResetRoot resetRoot = ResetRootAuto,                  void* privateData = 0x0,                  void (*deletePrivateData)(void* data) = 0x0);

그만큼 createChild() 이 기능을 사용하면 Op가 평가되는 장면 그래프 위치에서 하위를 만들 수 있습니다. 가장 간단한 경우 생성 할 위치의 이름과 해당 위치에서 평가되는 Op에 전달해야하는 인수가 필요합니다. 예를 들면 다음과 같습니다.

interface.createChild(childName, "", childArgs);

optype을 빈 문자열로 지정하면 create child라는 동일한 Op가 자식 위치에서 평가됩니다. 그러나 다른 optype을 지정할 수 있으며 대신 실행됩니다.

노트 :  여러 번 전화 createChild() 동일한 명명 된 하위 위치에 대해 마지막으로 지정된 optype이 사용됩니다. 즉, createChild() 이전 통화를 마스크하십시오.

그만큼 resetRoot 매개 변수는 다음 세 가지 값 중 하나를 사용합니다.

ResetRootTrue -새 위치에서 평가 된 Op의 루트 위치가 새 위치 경로로 재설정됩니다.

ResetRootAuto (기본값)-optype이 Op 호출과 다른 경우에만 루트 위치가 재설정됩니다. createChild().

ResetRootFalse -새 위치에서 평가 된 Op의 루트 위치는 호출 된 Op에서 상속됩니다. createChild().

이 매개 변수는 rootLocation 하위 위치에서 실행될 때 Op를 위해.

execOp () 함수

void execOp(const std::string& opType,             const FnAttribute::GroupAttribute& args);

Geolib3 런타임이 OpTree를 평가할 때까지 정적이며 고정되어 있습니다. 쿡 인터페이스는 다양한 기능을 제공하므로 OpTree를 구성 할 때 선언되지 않은 Ops를 OpTree의 평가 시간 동안 실행하도록 요청할 수 있습니다.

우리는 이미 어떻게 보았습니다 createChild() 하위 위치에서 실행할 Op를 지정하여이를 수행 할 수 있습니다. 그만큼 execOp() 이 기능을 사용하면 Op가 다른 Op의 실행을 직접 호출하여 원래 OpTree에서 직접 선언되지 않은 Ops를 평가하는 다른 메커니즘을 제공 할 수 있습니다. 이것은와 다릅니다 createChild() 다음을 포함하여 여러 가지 방법으로 하위 위치에서 실행되도록 다른 Op를 선언합니다.

다른 Op의 원샷 실행으로 생각해야합니다.

에 지정된 Op execOp() 호출은 발신자와 동일한 루트 위치를 가진 동일한 위치에서 실행되는 것처럼 평가됩니다.

너는 볼 수있어 execOp() StaticSceneCreate Op에서 작동합니다. 여기서 Op 유형은 x 논의:

// Exec some ops? FnAttribute::GroupAttribute opGroups = interface.getOpArg("x"); if (opGroups.isValid()) {     for (int childindex = 0; childindex < opGroups.getNumberOfChildren();          ++childindex)     {          ...          if (!opType.isValid() || !opArgs.isValid())          {              continue;          }          interface.execOp(opType.getValue("", false), opArgs);      } }

deleteSelf () 함수

void deleteSelf();

지금까지 장면 그래프에 데이터를 추가하는 메커니즘 만 보았지만 deleteSelf() 기능 및 관련 기능 deleteChild() 장면 그래프에서 위치를 제거 할 수 있습니다. 그들의 행동은 자명하지만 부작용은 덜 직관적이며 완전히 설명되어 있습니다. 씬 그래프 입력 읽기. 그러나 현재로서는 Prune Op가 deleteSelf() 함수 호출은 다음과 같습니다.

// Use CEL Utility function to evaluate CEL expression FnAttribute::StringAttribute celAttr = interface.getOpArg("CEL"); if (!celAttr.isValid())     return;   Foundry::Katana::MatchesCELInfo info; Foundry::Katana::MatchesCEL(info, interface, celAttr);   if (!info.matches)     return; // Otherwise, delete myself interface.deleteSelf();   return;

stopChildTraversal () 함수

void stopChildTraversal();

그만큼 stopChildTraversal() function은 Op가 실행되는 위치를 제어 할 수있는 기능 중 하나입니다. 평가중인 현재 위치의 모든 하위에서이 Op의 실행을 중지합니다. 예를 들어 설명하는 것이 가장 좋습니다.

입력 장면이 있다고 가정 해보십시오.

/root

/world

/light

우리가 원하는 것은 다음과 같습니다.

/root

/world

/geo

/taco

/light

따라서 StaticSceneCreate Op를 사용하여 시작 위치 / root / world에이 추가 계층을 만듭니다.

/geo

/taco

그러나 우리가 전화하지 않으면 stopChildTraversal() StaticSceneCreate Op가있을 때 /root/world 이 Op는 둘 다에서 실행됩니다 /root/world/root/world/light, 를 야기하는:

/root

/world

/geo

/taco

/light

/geo

/taco

요약, stopChildTraversal() 입력에 존재하는 하위 위치에서 Op가 자동으로 평가되지 않도록합니다. 가장 일반적인 사용 stopChildTraversal() 효율성을위한 것입니다. 예를 들어 CEL 표현식을보고이 Op가 현재 계층보다 더 깊은 계층 구조에 영향을 미치지 않는다고 판단 할 수 있으면 호출하는 것이 좋습니다. stopChildTraversal() 하위 위치에서는이 Op를 호출하지 않습니다.

씬 그래프 입력 읽기

업스트림 Ops에 의해 생성 된 입력 장면 그래프를 읽는 다양한 기능이 있습니다. 이 모든 기능은 읽기 기능 만 허용합니다. 입력 장면은 변경할 수 없습니다.

getNumInputs () 함수

int getNumInputs() const;

Op는 다른 여러 Ops의 출력을 입력으로 가질 수 있습니다. 이에 대한 분명한 사용 사례는 서로 다른 OpTree에서 생성 된 여러 장면 그래프를 단일 장면 그래프로 병합하거나 두 장면 그래프 상태의 속성 값을 비교하거나 한 장면 그래프를 다른 장면 그래프로 복사하려는 경우입니다. 그만큼 getNumInputs() 이 기능을 사용하면 입력으로 보유한 Op 수를 결정할 수 있으며 이는 장면 그래프 데이터에 대해 OpTree의 다른 분기를 조사하기위한 전조입니다.

경고:  Geolib3의 지연 처리 모델을 고려할 때 다음과 같은 "get"함수는 getAttr(), getPotentialChildren() , doesInputExist() 아직 계산되지 않은 장면 그래프 정보를 요청할 수 있습니다.

이 경우 요청 된 위치가 준비되면 Op의 실행이 중단되고 (예외 사용) 일정이 재조정됩니다. 따라서 Op 작성자는 "(...)"를 사용하여 모든 예외를 맹목적으로 잡으려고 시도하지 않아야하며, 예외 안전 코드를 작성해야합니다.

사용자 Op가 실수로 이러한 예외 중 하나를 발견하면 런타임에서이를 감지하고 결과가 유효하지 않은 것으로 간주하여 장면 그래프에 오류가 발생합니다.

Op가 기본 입력 위치 (및 색인) 또는 상위 항목에서만 읽는 경우 "리쿡"이 발생할 가능성이 적습니다. 그러나 입력 위치 경로 나 입력 인덱스에서 분산 액세스 쿼리의 경우 "리쿡"이 발생할 수 있습니다. Op가 불행한 성능 특성을 갖는 여러 위치에서 분산 액세스 쿼리를 수행해야하는 경우 API 호출- prefetch() -사용 가능하며 나중에 자세히 설명합니다.

getAttr () 함수

FnAttribute::Attribute getAttr(     const std::string& attrName,     const std::string& inputLocationPath = std::string(),     int inputIndex = kFnKatGeolibDefaultInput) const;

다른 속성에 저장된 결과에 따라 일부 작업을 수행하거나 값을 계산해야하는 경우가 종종 있습니다. 그만큼 getAttr() 이 기능을 사용하면 속성 이름과 장면 그래프 위치 경로 (절대 또는 상대)를 제공하여 들어오는 장면 그래프의 일부를 조사 할 수 있습니다. 또한 특정 입력 색인을 지정하여 속성 값을 얻을 수 있습니다.이 값은 다음의 결과보다 작아야합니다. getNumInputs(). getAttr은 항상 입력에 표시된 값을 Op에 반환합니다. 자신 또는 execOp로 호출 된 다른 Op에 의해 이미 작성된 setAttrs를 고려하려면 getOutputAttr을 사용해야합니다.

다음 다이어그램은 이것의 미묘한 부분을 보여 주며, 가장 중요한 것은 execOp Op에서 getAttr이 쿼리 위치가 현재 위치 일 때 호출 Op의 결과 만 봅니다. 그렇지 않으면 호출 Op의 슬롯에 대한 입력이 표시됩니다. Op 그래프에서 '.

getPotentialChildren () 함수

FnAttribute::StringAttribute getPotentialChildren(     const std::string& inputLocationPath = std::string(),     int inputIndex = kFnKatGeolibDefaultInput) const;

장면 그래프 생성 함수 deleteSelf() 이러한 부름의 결과는 처음 나타난 것보다 더 미묘하다는 점을 지적하면서 소개되었다. 업스트림 Op가 평가되어 하위 항목을 생성 할 때 다운 스트림 Ops가이를 삭제하는 기능이있는 경우 업스트림 Op는 하위 하위 Op가 해당 하위 위치에서 평가 된 후 해당 하위 항목이 잠재적으로 존재할 수 있다고 진술 할 수 있습니다. . 이는 Op가 그러한 위치에서 평가 될 때 다운 스트림 Op가 무엇을 할 수 있는지 알지 못하기 때문입니다. 그 정도까지 getPotentialChildren() Op의 입력에서 주어진 위치의 모든 자식 목록을 반환합니다.

prefetch () 함수

void prefetch(const std::string& inputLocationPath = std::string(),               int inputIndex = kFnKatGeolibDefaultInput) const;

Op 's cook 함수의 코드에서 가능한 빨리 prefetch ()를 사용하여 좋은 코드 연습을 유지하십시오.

prefetch () 함수는 장면 그래프 위치 간의 종속성을 나타내는 데 사용할 수 있습니다. 예를 들면 다음과 같습니다.

/root/world/geo/a may call prefetch() for /root/world/geo/b because during the processing of /root/world/geo/a, attributes present at ./b 필요합니다.

CEL 및 유틸리티

다음과 같이 Ops가 자주 수행해야하는 여러 가지 작업이 있습니다.

위치 계층 구조 생성

CEL 표현식 인수를 기반으로 Op를 실행해야하는지 결정

장면 그래프를 통해 사용자에게 오류보고

경계 상자와 같이 사용하기 쉬운 형식으로 잘 알려진 속성 값을 가져옵니다.

현재이 유틸리티의 헤더는 다음에서 찾을 수 있습니다.

$ KATANA_HOME / plugin_apis / include / FnGeolib / op / FnGeolibCookInterface.h

$ KATANA_HOME / plugin_apis / include / FnGeolib / util / *

유틸리티 구현은 다음에 있습니다.

$ KATANA_HOME / plugin_apis / src / FnGeolib / op / FnGeolibCookInterfaceUtils.cpp

$ KATANA_HOME / plugin_apis / src / FnGeolib / util / *

이러한 유틸리티 중 다수는 자체 문서화되며 유사한 패턴을 따릅니다. 다음 예는 CEL 일치 유틸리티 사용을 보여줍니다.

// Should we run here? If not, return. FnAttribute::StringAttribute celAttr = interface.getOpArg("CEL"); if (!celAttr.isValid())     return; Foundry::Katana::MatchesCELInfo info; Foundry::Katana::MatchesCEL(info, interface, celAttr); if (!info.canMatchChildren) {     interface.stopChildTraversal(); } if (!info.matches)     return;

위의 예에서 몇 가지 사항이 달성되었습니다.

1.   CEL 표현식이 어떤 하위 항목과도 일치 할 수 있는지 확인하고, 그렇지 않은 경우 하위 위치에서이 Op를 평가하지 않도록 런타임에 지시합니다.
2.   우리는이 위치에서 달려야하는지 여부를 결정하고 그렇지 않으면 일찍 돌아옵니다.

Ops를 작성할 때 생산성을 높일 수 있으므로 사용 가능한 다양한 유틸리티 기능을 자유롭게 탐색하십시오.