VRED Pro용 Python의 스크립팅에 대해 알아보고, 고유한 스크립트 개발을 시작하는 데 도움이 되는 몇 가지 예를 살펴보십시오.
동영상 캡션: 안녕하세요. VRED Pro를 위한 Python 스크립팅 튜토리얼 시리즈에 오신 것을 환영합니다. 저는 이 튜토리얼의 진행자인 크리스토퍼라고 합니다. 이번 동영상에서는 VRED에서 개발할 때 알고 있어야 할 몇 가지 Python 기본 사항에 대해 소개하고 자체 스크립트 개발을 시작하는 데 유용한 몇 가지 예제도 보여드리겠습니다.
Python은 플러그인 개발에 널리 사용되는 해석 프로그래밍 언어입니다. Python 인터페이스를 제공하는 다른 CGI 도구도 많이 있으며, 이는 단순한 우연이 아닙니다. Python은 매우 표현적인 언어이며 배우기 쉬운 것으로 알려져 있습니다. C++, C#, Java 등의 프로그래밍 언어와 달리 컴파일할 필요가 없으므로 코드를 작성한 후 실행을 누르기만 하면 지시한 동작을 코드가 즉시 수행합니다. Python은 C++와도 훌륭히 연동되며, VRED에서 C++도 사용한다는 점에서 반가운 얘기입니다. 관련된 이야기를 한 가지 말씀드리면
오토데스크에서 API 버전 2를 도입하면서 Python 2.7에서 Python 3으로 전환했습니다. 2020년 1월에 Python 2.7에 대한 공식 지원이 종료되었기 때문에 내려진 조치였습니다. 하지만 Python 2.7을 사용하는 스크립트를 사용하고 계신 경우에도 걱정하지 마십시오. VRED에는 Python 2.7을 Python 3으로 자동 변환하는 옵션이 있습니다.
Python과 VRED에 대해 더 말씀드릴 수 있는 것은 VRED는 자체 통합 Python 3 해석기를 사용한다는 점입니다. 이러한 방식으로 VRED API를 해당 Python 환경에 직접 주입할 수 있습니다.
이것이 우리에게 의미하는 것은 무엇일까요? Python은 모든 기능을 모듈 형태로 제공하며 모듈은 클래스와 함수의 모음입니다. VRED API도 별반 다르지 않습니다. 모듈의 모음이죠. 보통, 이러한 모듈을 사용하려면 직접 가져와야 합니다. 예를 들어 vrNodeUtils 모듈을 사용하려는 경우 "import vrNodeUtils"를 입력하여 이를 가져와야 합니다. 그러나 VRED에서는 이러한 모듈을 모두 이미 추가해 두었으므로 이 작업을 수행할 필요가 없습니다. 따라서 VRED에서의 스크립팅이 훨씬 더 읽기가 쉬우며 추가되는 코드의 양이 많이 줄어듭니다.
외부 모듈 또는 스크립트 플러그인을 개발할 때에는 주의를 기울여야 합니다. VRED API를 명시적으로 가져와야 하지만 API 버전 1만 명시적으로 가져와야 합니다. 이에 대해서는 다른 동영상에서 좀 더 자세히 설명하겠습니다.
그러면 몇 가지 실제 예를 살펴보겠습니다. 너무 복잡하게는 들여다 보지 않을 것이며 맛보기로 살짝만 살펴보겠습니다. 많은 스크립트에서는 어떤 방식으로든 장면 그래프에 액세스해야 합니다. 장면 그래프는 3D 그래픽의 중심적인 부분으로 형상, 라이트, 변환 등에 대한 모든 정보를 포함합니다. 이는 루트 노드에서 시작하여 장면을 변환 노드, 그룹 노드 또는 스위치 노드로 나누고 형상 자체로 이어지는 계층 구조입니다. 일반적인 스크립트에서는 노드나 형상을 장면 그래프에 추가하거나, 노드를 한 위치에서 다른 위치로 이동하거나, 장면 그래프에서 노드를 찾아 조작할 수 있습니다.
첫 번째 예제에서는 장면 그래프에서 노드를 검색하는 것으로 시작해 보겠습니다. 메뉴 막대의 편집 아래에 있는 스크립트 편집기를 열고 스크립트를 입력합니다. 먼저 vrNodeService를 사용하여 장면의 루트와 카메라 노드를 검색합니다. 카메라 노드는 장면 그래프에서 볼 수 있듯이 Perspective라고 합니다.
일반적으로 노드는 장면 그래프에서 해당 이름으로 참조됩니다. 이 작업의 결과를 변수로 저장하므로 이제 vrdNode 유형의 객체를 보유합니다. vrdNodes는 API 버전 2에서 정의됩니다. 실행 버튼을 눌러 스크립트를 실행하고 터미널에 출력된 메시지에 표시되는 결과를 확인할 수 있습니다. 이 메시지는 두 변수가 보유하게 된 객체 유형을 알려줍니다.
다음으로, 새 노드를 생성하여 장면 그래프에 추가합니다. 여기서는 Group 유형의 노드를 생성합니다. 설명서를 보면 생성할 수 있는 모든 노드 유형을 확인할 수 있습니다. 첫 번째 매개변수로 노드 유형을 정의하고 두 번째 매개변수로 이름을 설정하고, 세 번째 매개변수로 새 노드의 상위 노드가 되는 노드를 지정해 createNode 함수를 사용하여 노드를 생성합니다. 이 경우에는 새 노드가 장면의 루트 아래에 배치되도록 하겠습니다. 그런 다음 updateSceneGraph 모듈에서 vrSceneGraph 함수를 호출합니다. 이 명령을 실행하면 장면 그래프의 변경 사항이 바로 표시됩니다.
이제 형상을 생성하고 새 그룹 노드에 추가해 보겠습니다. 이 작업은 원형(primitive) 형상을 자동으로 생성하는 함수 집합을 사용하여 수행할 수 있습니다. 여기서는 createPlane 함수와 createBox 함수를 사용해 보겠습니다.
입력을 시작할 때 사용 가능한 함수를 편집기에서 어떻게 제안하는지 살펴보십시오. 이 기능은 스크립트를 작성할 때 매우 유용합니다. 입력을 시작하면 바로 사용 가능한 함수를 확인할 수 있습니다. 다만 이 기능은 사용해야 하는 매개변수를 알려주지는 않으므로 설명서를 확인해야 합니다. 그 부분은 아쉽게 생각합니다.
처음 몇 개의 매개변수는 평면 및 상자의 크기를 정의하고, 다음 세 개의 매개변수는 해상도를 정의하며, 마지막 세 개의 숫자는 색상, 즉 100% 흰색을 정의합니다. 스크립트를 실행할 때마다 이전 그룹 노드를 제거하기 위해 두 함수도 추가했습니다. 이 함수를 추가하지 않으면 장면 그래프가 이전 그룹 노드로 인해 어수선해지게 됩니다.
다음으로, 각 형상의 이름을 추가하고 setTranslation 함수를 사용하여 장면에서 해당 변환을 설정합니다. 이 함수는 장면에서의 위치를 정의하는 x, y, z 구성요소를 받습니다. 이 setTranslation 함수는 API 버전에서 작성되었으며 벡터 표현 대신 이전 매개변수 집합을 사용합니다.
마지막 단계로, 이 두 형상을 그룹 노드에 추가합니다. 그렇지 않으면 형상이 메모리 어딘가에 부동 상태로 유지되고 장면 그래프에 연결되지 않습니다. 실행을 누르면 장면에 새 형상이 표시됩니다.
노드를 해당 상위 노드에서 다른 노드로 이동할 수도 있습니다. 먼저, "Another node"라는 이름의 다른 노드를 생성해 보겠습니다. 이번에는 typeTransform 노드를 사용합니다. 이렇게 하면 노드를 생성한 후 setTranslation 함수를 사용하여 변환할 수 있습니다.
첫 번째 예제에서와 같이 이름을 사용하여 두 형상을 찾습니다. 그런 다음 새 변환 노드에 대해 addChild 함수를 사용합니다. 이런 식으로 그룹 노드에서 노드를 제거하고 변환 노드에 추가합니다. 형상이 이제 위로 약간 이동한 것을 볼 수 있습니다.
다음으로, 새 카메라를 생성하겠습니다. 여기서는 vrCameraService를 사용합니다. 또한 장면 내 카메라의 위치를 설정하고 이 카메라가 바라보는 위치를 정의하겠습니다. 카메라에 대해 vrCameraFromAtUp 함수를 사용하며, 이 함수에는 setFromAtUp 유형의 객체가 필요합니다. 생성자를 사용하여 이 객체를 생성하고 카메라 위치, 카메라가 바라보는 위치, 장면에서 어느 면이 "위"를 향할지를 정의하는 세 벡터를 입력합니다. 마지막으로 새 카메라를 활성화하고 장면에서 카메라가 변경된 것을 확인하겠습니다.
또한, 현재 카메라 위치에서 아주 쉽게 뷰 포인트를 생성할 수 있습니다. 이 작업은 vrCameraService를 사용하여 수행합니다. 여기에는 createViewpoint 함수가 있으며, 이 함수에는 입력으로 이름만 필요합니다. 이렇게 하면 장면에서 카메라를 이동하고 카메라 메뉴에서 액세스할 수 있는 뷰포인트를 캡처할 수 있습니다.
다음 예제에서는 자체 재질을 생성하겠습니다. createMaterial 함수를 사용하여 두 가지 새 재질을 생성해 보겠습니다. 재질 유형을 지정해야 하며, 이러한 유형은 설명서에 설명되어 있습니다.
여기에서는 기본 퐁(phong) 재질을 생성합니다. 재질의 색상을 설정하려면 fieldAccess를 사용해야 합니다. 이는 노드에 저장된 모든 데이터를 읽고 조작할 수 있는 특별한 모듈 유형입니다.
fieldAccess에 대해서는 다른 튜토리얼에서 더 자세히 설명하겠습니다. 여기서는 분산 채널에서 빨간색 및 녹색 재질을 정의하는 데 사용합니다. 스크립트를 실행하고 재질 편집기를 열면 두 개의 새로운 재질이 표시됩니다. 변경 내용을 표시하려면 재질 편집기를 닫았다가 다시 열어야 할 수 있습니다.
물론 이러한 재질을 새 형상에 추가할 수도 있습니다. 다시 한 번 장면에서 형상을 찾은 다음 setMaterial 함수를 사용하여 재질을 변경합니다.
마지막 예제에서는 새 변형 세트를 생성하겠습니다. 이 작업은 createVariantSet 함수를 사용하여 수행할 수 있으며, 이 함수에는 입력으로 새 변형 세트의 이름이 필요합니다. 또한 getVariantSet 함수에 변형 세트의 이름을 매개변수로 사용하여 변형 세트를 찾을 수도 있습니다. 물론, 변형 세트에 스크립트를 추가할 수도 있습니다. 여기에 표시된 예는 Python 스크립트를 새 변형 세트에 추가할 수 있는 방법을 보여주는 간단한 예입니다.
이는 Python으로 스크립팅할 때 여러 가능한 작업 중 일부에 불과합니다. 장면 플레이트 관리, 애니메이션 만들기 등 소개해 드릴 것이 더 많습니다. 이것은 관심을 가지실 만한 몇 가지 예에 불과합니다.
VRED의 예제 섹션에 많은 예제가 있으므로 여기서 원하는 작업에 대한 솔루션을 찾아보실 수 있습니다. 예를 들어, VRED 장면에 메뉴를 추가하려는 경우 이에 대한 모든 기본 사항을 알려주는 이 메뉴 예제를 살펴볼 수 있습니다.
오늘은 이것으로 마치겠습니다. VRED에서의 기본 Python 스크립팅을 소개해드린 오늘의 동영상이 유익했기를 바랍니다. 참여해 주셔서 감사하며 다음에 뵙겠습니다.
튜토리얼 2: Python을 사용하여 VRED를 위한 스크립트를 작성하는 방법 동영상과 함께 제공되는 예제 Python 스크립트입니다.
이러한 파일을 압축하여 다운로드하려면 여기를 클릭하십시오.
결과를 확인하려면 VRED 스크립트 편집기에 코드 조각을 복사해서 붙여넣어 Python 예제를 실행하고 실행을 누르십시오.
groupNode = vrNodeService.findNode("Group Node")
deleteNode(groupNode)
# Example 1.0:
# Finding nodes in the screnegraph
root = vrNodeService.findNode('Root')
camera = vrNodeService.findNode('Perspective')
print(root)
print(camera)
# Example 1.1:
# Creating new nodes
print()
print('---------------')
groupNode = createNode('Group', 'Group Node', root)
print(groupNode)
updateScenegraph(True)
# Example 1.2:
# Creating geometry and add them to the scenegraph
print()
print('---------------')
planeNode = createPlane(1000, 1000, 1, 1, 1, 1, 1)
planeNode.setName('Plane Geometry')
planeNode.setTranslation(100, 200, 10)
groupNode.addChild(planeNode)
boxNode = createBox(500, 500, 500, 1, 1, 1, 1, 1, 1)
boxNode.setName('Box Geometry')
boxNode.setTranslation(-100, -200, 10)
groupNode.addChild(boxNode)
# Example 1.3:
# Move nodes in the scenegraph
print()
print('---------------')
anotherNode = createNode('Transform', 'Another Node', root)
anotherNode.setTranslation(0, 0, 500)
planeNode = vrNodeService.findNode('Plane Geometry')
boxNode = vrNodeService.findNode('Box Geometry')
anotherNode.addChild(planeNode)
anotherNode.addChild(boxNode)
# Example 2.0:
# Create a new camera
camera = vrCameraService.createCamera("New Camera")
cameraFrom = QVector3D(2000, 2000, 5000)
cameraAt = QVector3D(0, 0, 0)
cameraUp = QVector3D(0, 0, 1)
fromAtUp = vrCameraFromAtUp(cameraFrom, cameraAt, cameraUp)
camera.setFromAtUp(fromAtUp)
camera.activate()
# Create a camera viewpoint from the current camera
viewpointName = 'New Viewpoint'
viewpoint = vrCameraService.createViewpoint(viewpointName)
# Example 3.0:
# Create a basic phong material
materialA = createMaterial("UPhongMaterial")
materialA.setName("Material A")
materialA.fields().setVec("diffuseColor", [1, 0, 0])
materialB = createMaterial("UPhongMaterial")
materialB.setName("Material B")
materialB.fields().setVec("diffuseColor", [0, 1, 0])
# Example 3.1:
# Create a material switch and add the newly created materials
materialSwitch = createMaterial("SwitchMaterial")
materialSwitch.setName("Material Switch")
materialSwitch.addMaterial(materialA)
materialSwitch.addMaterial(materialB)
# Example 3.2:
# Apply the material to geometry
plane = findNode("Plane Geometry")
box = findNode("Box Geometry")
materialA = findMaterial("Material A")
materialB = findMaterial("Material B")
plane.setMaterial(materialA)
box.setMaterial(materialB)
# Example 4.0
# Create a variant set
variantSetName = 'New Variant Set'
createVariantSet(variantSetName)
variantSet = getVariantSet(variantSetName)
# Example 4.1
# Add stuff to the variant set
variantSet.addScript("print('Hello World!')")
variantSet.addView(vrCameraService.getViewpoint('New Viewpoint'))