TouchDesigner의 라이프 게임

11710 단어 TouchDesigner
TouchDesigner의 피드백 CHOP를 사용하여 라이프 게임을 구현해 봅니다.

전체 네트워크는 다음과 같습니다.

컴퍼넌트의 색 마다 대략 다음의 처리를 실시하고 있습니다.
  • 블루 : 라이프 게임의 초기 상태 설정
  • 오렌지 : 라이프 게임의 다음 상태 계산
  • 노란색: 각 셀의 위치와 색상 계산
  • 블루 : 인스턴싱을 사용하여 그리기

  • 여기에서는 각 처리마다 자세한 내용을 살펴 보겠습니다.

    라이프 게임의 초기 상태 설정




    셀을 격자에 정렬하기 위해 Grid CHOP을 사용하여 각 셀의 위치를 ​​찾습니다. 종횡 각각의 셀의 수는 라이프 게임의 다음 상태의 계산에서도 필요하므로 Constant CHOP로 관리하고 있습니다.

    각 셀의 초기 상태를 유지하는 Channel을 Noise CHOP 및 Expression Chop에서 작성합니다. Noise CHOP에서 셀 수와 같은 크기의 Channel을 작성해, Expression Chop에서 값이 0·1의 2치가 되도록 하고 있습니다. 이번 구현에서는 0이 '죽음', 1이 '생' 상태를 나타냅니다.


    라이프 게임의 다음 상태 계산




    Feedback CHOP에서 각 셀의 상태를 프레임을 통해 관리하도록 하고 Script CHOP에서 다음 상태를 계산하고 있습니다. Feedback CHOP의 제 1 입력에 Script CHOP의 출력을 연결하고, 제 2 입력에는 방금 작성한 초기 상태의 출력을 연결하고 있습니다. Feedback CHOP의 Reset 파라미터의 「Pulse」를 누르면, 제2 입력의 상태에 기초하여 시뮬레이션이 실행됩니다.

    Script CHOP는 다음과 같은 상태를 계산하는 Python 스크립트를 설명합니다. onCook 함수 내에서 실제 계산이 수행되었습니다. 또한 가로 세로 셀 수를 설정하기 위해 onSetupParameters 함수 내에서 매개 변수를 추가합니다.
    # me - this DAT
    # scriptOp - the OP which is cooking
    
    # press 'Setup Parameters' in the OP to call this function to re-create the parameters.
    def onSetupParameters(scriptOp):
        page = scriptOp.appendCustomPage('Custom')
        p = page.appendInt('Width', label='width')
        p = page.appendInt('Height', label='height')
        return
    
    # called whenever custom pulse parameter is pushed
    def onPulse(par):
        return
    
    def onCook(scriptOp):
        scriptOp.clear()
    
        input = scriptOp.inputs[0]
        prev_chan = input.chan(0)
    
        chan = scriptOp.appendChan(prev_chan.name)
        width = scriptOp.par.Width.eval()
        height = scriptOp.par.Height.eval()
        for w in range(width):
            for h in range(height):
                left = w - 1 if w != 0 else width - 1
                right = w + 1 if w != width - 1 else 0
                down = h - 1 if h != 0 else height - 1
                up = h + 1 if h != height - 1 else 0
    
                alives \
                    = prev_chan[left + up * width] \
                    + prev_chan[left + h * width] \
                    + prev_chan[left + down * width] \
                    + prev_chan[w + up * width] \
                    + prev_chan[w + down * width] \
                    + prev_chan[right + up * width] \
                    + prev_chan[right + h * width] \
                    + prev_chan[right + down * width]
    
                idx = w + h * width
                state = prev_chan[idx]
    
                chan[idx] = 1 if \
                    ((state == 0 and alives == 3) or\
                    (state == 1 and (alives == 2 or alives == 3))) else 0
    
        return
    

    추가한 파라미터에는 세로/가로 각각의 셀수를 넣도록 합니다.


    각 셀의 위치와 색상 계산




    각 셀의 위치와 색상을 계산합니다. 위치는 SOP to CHOP에서 작성한 것을 그대로 이용하고 있습니다. 색은 Lookup CHOP를 이용해 0일 때는 검정, 1일 때는 녹색이 할당되도록 하고 있습니다.

    인스턴스화를 사용한 드로잉




    인스턴스화를 활성화하여 이전에 만든 각 채널을 위치와 색상을 매개 변수에 할당합니다. 여기 이후는 통상의 인스턴싱을 이용한 묘화와 같으므로 설명을 할애합니다.


    끝에



    Feedback CHOP을 사용하여 라이프 게임을 구현해 보았습니다. Feedback CHOP와 Script CHOP를 사용하는 방법은 다른 시뮬레이션에서도 유효할 것 같습니다.

    다만, Operator Snippets의 「GLSL TOP」의 샘플로서 GLSL TOP와 Feedback TOP를 사용한 라이프 게임의 실장이 있으므로, 실용적으로는 그쪽을 참고로 하는 편이 좋다고 생각합니다, GPU로 계산하는 편이 효율이 좋을 것이므로.

    좋은 웹페이지 즐겨찾기