ORCAメモ

ORCAについて

公式Github https://github.com/hundredrabbits/Orca

何ができるのか

ちょっと特殊な命令を使ってコーディングすると音がなる(正確にはMIDIUDPでレコードを発射できる) コーディングはライブでできるのでエモい。

まずはインストール

Githubに書いてある通り

git clone https://github.com/hundredrabbits/Orca.git
cd Orca/desktop/
npm install
npm start

以上。

ORCA単体で音がなるわけではないのでDAWかなんか使いましょう。

Renoiseをインストールします。

あと loopMIDIもインストールします。

何はともあれ動かしてみる

  1. Renoiseを起動して、面倒なのでサンプルの曲を開く。(好きなのでOK)

  2. 次にloopMIDIも起動しておく。 f:id:icedaksan:20190414214254p:plain

こんな感じで一つMIDIポートを作るといいらしい。

  1. Renoiseに戻って、Midiポート(IN)とさっき開いたサンプル曲の好きなトラックを指定します。

    f:id:icedaksan:20190414214451p:plain

  2. npm startしてORCAを起動します。

  3. ORCAのサンプルoctave.orcaを開く。  ちなみに、bang.orcaMidiへのアウトプットが記述してないので音が出ないです。。。

これで ORCA -> loopMIDI -> Renoise とつながって音が鳴るはず。。。きっと。

あとは適当に命令とサンプル眺めてれば、Delayだったりはわかるはず。

変態譜面を作ろうとおもうとU(Uターン)とか使い始める。私にはわからない。

Houdini でShelf Toolを作る紹介(Python)

この記事は Akatsuki Advent Calendar 2018 の 9 日目の記事です。

HoudiniでShelf Tool(マクロ機能)がPythonで作れるのでその紹介です。

今回の目標はHoudini上でPythonを使う検証も兼ねて
Shelf ToolからPythonで作ったツールを呼び出す話になります。

Pythonを使わなくてもHoudiniは十分使えるツールなのですが、
開発で繰り返す作業等がある場合に有用かと思いますので調べました。

Houdini って?

f:id:icedaksan:20181209004552p:plain:w300

Houdini は SideFX社製のDigital Contents Creation ツールの一つです。
DCCツールとは、モデリング・アニメーション・レンダリング等ができるツールのことです。
Houdini自体の歴史は結構長く、映像業界でよく使われています。 参考

Houdiniの特徴はプロシージャルな制作フローです。
例えば、非破壊的にパラメータ変更でアセットのバリエーションを生み出したりすることができます。
そういう特徴から最近はゲーム業界でもアセットの効率的な生成などで活躍してたりで
ちょっと注目されるようになってきているようです。

例としては
レースゲームのコース制作やフィールドに草木やビルを配置する仕組みだったり、
エフェクト分野ではVertexAnimationTextureやVector Fieldの生成などに活躍の幅を利かせつつあるようです。

SideFXからもゲーム分野用の機能だけをまとめたGameDevelopmentToolsetが配信されてることも紹介しておきます。

ちなみに、 保存ファイル形式やレンダリング機能に制限がある
学習用エディションは無料でダウンロードできます。

Houdini でPythonが使えるところ

Houdiniでは、Pythonが使えます。
どのような箇所で使えるのかというのを列挙します。

  • Python SOP
  • Python Shell
  • Python Source Editor
  • Python Panel Editor
  • Shelf Tool
  • パラメータフィールド
  • HDA(Houdiniデジタルアセット)
  • Hython

以上の様に、色々な所で使えるのですがざっくりいうと
アセット制作の編集に直接使うこともできるし
Houdini上のツールやマクロも作ったりできるし
Houdiniの外部パイプラインからも使えるよと言う感じ。
エンジニアリングし甲斐ありますね。

Houdiniで使えるPythonバージョンについて

Houdini本体をインストールしているOS環境に依存します。

Macの場合

Mac でHoudiniを起動した場合、
Houdiniは /usr/bin/python を使います。
macOS High Sierra の場合 systemに入っている Python バージョンは 2.7.10 でした。

ちなみにですが、Python3が使えないのかと思いましたが使えないようです。
試しに pyenv を入れてpyenv global python3.*.* などとしてみましたが効きませんでした。
ですよね。。。

Windows の場合

Windowsの場合は、
Houdiniをインストールしたディレクトリ以下にpython27というフォルダがあり
そこにpythonがインストールされます。

Houdini 17 では、Pythonバージョンは2.7.5でした。

ちなみにpip は?

使えます。
※当然、配布目的があったりすると
使用者にも同じPythonモジュールを入れてもらう必要があるのでそれなりに手間ですが...

pip の詳しい紹介は割愛します。

Python Shell からPythonしてみる

f:id:icedaksan:20181204184152p:plain
Python Shell は Houdini を起動して
Window > Python Shell をクリックすると起動します。

さっそくなにか打ち込んでみます。

現在開いてるHoudiniFile(*.hip)のパスが表示してみる。

>>> hou.hipFile.path()
'/Users/yourusername/untitled.hip'

ジオメトリ(キューブ)を作ってみる。

>>> objNode = hou.node("obj/")
>>> geoNode = objNode.createNode("geo")
>>> geoNode.createNode("box")

hou.~~~というのがちらほら出てきますが
hou はHoudiniのモジュールで、ここから様々な機能を呼び出すことができます。 どんなものがあるかは以下が参考になります。

http://www.sidefx.com/docs/houdini/hom/hou/index.html

Shelf追加

f:id:icedaksan:20181209004338p:plain シェルフはクリック時に処理を実行するツール群のことです。所謂マクロです。
これをPythonで記述することで独自の便利機能が作れるという感じです。

上のスクショのように
Shelf Tool Setの右のをクリックしてNew Shelfを選びます。
保存先、名前、ラベルを指定してAcceptをクリックするとShelf Toolができます。

作ったShelf Toolが見当たらない場合は、
+をクリックし、その中に作ったShelfがあるので選択します。

自作Toolを追加するにはNew Tool...からツールを追加します。
保存先、名前、ラベルを入力して、Scriptの中にPythonコードを書けばツールになります。
f:id:icedaksan:20181207160318p:plain

実際になんかToolを書いてみる

【適当に画像を拾ってきて変形したキューブに貼り付けて並べる】 という謎のツールを作ってみます。
一応、今回はPythonスクリプトから
以下の機能を確認したかったという意図で思い付きでこんなのになりました。。。

  • pip で入れたモジュールが使えるか
  • ジオメトリの作成・ノードの連結・パラメータ変更
  • マテリアルの作成・割り当て

まずはpipでモジュールを入れます。

sudo pip install BeautifulSoup4

つぎに、ToolのScriptを書きます。

import bs4
import re
import urllib2
import urllib
import os
import json
import math

# 検索画像
search_query = "duck"
# 画像数
image_num = 20
# 保存先
path = os.path.dirname(hou.hipFile.path())

# スクレイピング画像保存用のディレクトリ作成
save_directory = path + '/' + search_query
if not os.path.exists(save_directory):
    os.makedirs(save_directory) 

# 画像をGoogleイメージ検索からスクレイピング
url="https://www.google.co.jp/search?q=" + search_query + "&source=lnms&tbm=isch"
header={"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36"}
soup = bs4.BeautifulSoup(urllib2.urlopen(urllib2.Request(url,headers=header)),'html.parser')
ActualImages=[]
TexturePathes=[]

for a in soup.find_all("div",{"class":"rg_meta"}):
    link , Type =json.loads(a.text)["ou"]  ,json.loads(a.text)["ity"]
    ActualImages.append((link,Type))
for i , (img , Type) in enumerate( ActualImages[0:image_num]):
    try:
        Type = Type if len(Type) > 0 else 'jpg'
        print("Downloading image {} ({}), type is {}".format(i, img, Type))
        raw_img = urllib.urlopen(img).read()
        texturePath = os.path.join(save_directory , "img_"+str(i)+"."+Type);
        f = open(texturePath, 'wb')
        f.write(raw_img)
        f.close()
        TexturePathes.append(texturePath)
    except Exception as e:
        print ("could not load : "+img)
        print (e)
        
texIdx = 0
texLen = len(TexturePathes)
for tex in TexturePathes:
    # マテリアルを作る
    mat = hou.node("mat");
    texMaterial = mat.createNode("texture::2.0")
    texMaterial.setMaterialFlag(True)
    texMaterial.setParms({"map":TexturePathes[texIdx]})
    
    # ノードを作る        
    objNode = hou.node("obj")
    geoNode = objNode.createNode("geo")
    boxNode = geoNode.createNode("box")
    transformNode = geoNode.createNode("xform")
    attribWrangle = geoNode.createNode("attribwrangle")
    uvNode = geoNode.createNode("uvquickshade")
    materialNode = geoNode.createNode("material")
    
    # Nodeを繋げる
    transformNode.setInput(0, boxNode)
    attribWrangle.setInput(0, transformNode)
    uvNode.setInput(0, attribWrangle)
    materialNode.setInput(0, uvNode)
    
    # Transform
    radius = 10
    r = -1.5 + .0 * float(texIdx)/float(texLen)
    xpos = 2.5 * math.sin(r)
    zpos = 2.5 * math.cos(r)
    transformNode.setParms({"tx":xpos, "tz":zpos})
    
    # PointWrangler ※WranglerはHoudiniで使えるスクリプト言語
    attribWrangle.setParms({"class":2, "snippet":"if (@ptnum > 3) { @P.x *= 0.5; @P.z *= 0.5; }"})
    
    # マテリアル設定
    materialNode.setParms({"shop_materialpath1":texMaterial.path()})
    materialNode.setRenderFlag(True)
    materialNode.setDisplayFlag(True)
    
    texIdx += 1

Scriptが書けたら、あとは作ったToolボタンをクリックすると実行されます。

ちなみにレンダリングしないとマテリアルがちゃんと表示されないです。
Render Viewレンダリングすると確認できます。

f:id:icedaksan:20181207174742p:plain

思ったこと

  • Houdiniの強力な機能と組み合わせればすごいことができそうではあるが...まだよくわからない...
  • MacだとHoudini Console出ないのどうにかならないのだろうか...
  • Pythonから作成したノードの表示が重なってしまう...
    • => moveToGoodPosition で解決
  • @P(箱の各点)がグローバル位置だということを今理解したw(つまりTransform順に影響する)
  • 機能の種類が多いので、パラメータを覚える・調べるのがちょっと大変
    • => PythonShellに調べたいノードのパラメータをD&Dするとパラメータのパスがわかったりする。またはノードのinfoも情報になる
  • アセット制作ルーチンはHDAにした方がいいよねというツッコミは無しでお願いします...

RTX 2080買った

とりあえずDX12のRaytracingサンプル落としてみてみる
DirectX-Graphics-Samples/Samples/Desktop/D3D12Raytracing at master · Microsoft/DirectX-Graphics-Samples · GitHub

動くまでのエラーとか

動いた f:id:icedaksan:20181028225641p:plain