blender etc

URL:http://blendermoe.blogspot.com/
RSS:http://blendermoe.blogspot.com/feeds/posts/default

[変更]
最終更新日2017/12/02 22:21:00

タグ

blender 

記事

CyclesのDenoise

2017-12-02 22:21:00
この記事は Blender Advent Calendar 2017 2日目の記事です。 (注意)この記事は急いで調べながら書いているので、間違いを含んでいる可能性があります。違ったらすみません Blenderも気づけばバージョン2.79! CyclesにDenoiseも載りました。 今回はCyclesのDenoiseがどうなっているか、掘り下げていこうかと思います。 以下最初のシーンに適当なスザンヌとエリアライト追加してレンダーした結果です。 左がdenoise無し、右がdenoise有りです。 1spp 2spp 4spp 8spp 16spp 32spp フルHDで、denoiseに16~17秒掛かっていますが、低サンプル数でもかなり綺麗になっています。 速度については、OpenCLを使用してレンダーするようにすると、denoiseについても半分くらいの速度でレンダーできました。 設定方法は簡単で、ここにチェックを入れるだけです。 実際の使用例や説明については公式ヘルプをご参照ください →Blender 2.79: Cycles: Denoising(デノイズ) →また、インタラクティブに確認できるサンプルがこちらにあります それでは、Blenderのdenoiseがどうなっているのか、実装面見ていきます。 まずリポジトリをcloneしてきて、denois とかで検索すると それらしきファイルが出てきました。 これでしょうか? 中をみると bool DenoisingTask::run_denoising() { /* Allocate denoising buffer. */ なんか前処理っぽいコード /* Prefilter shadow feature. */ { なんかコード } /* Prefilter general features. */ { なんかコード } /* Copy color passes. */ { なんかコード } なんか後処理っぽいコード } となっており、それっぽいですね。 影と、それ以外の部分について、別々にフィルターをかけて、 最後にカラーパスにコピーしているようなコメントが見えます。 また変数としてnlm_temporary_1 などといったものが定義されており、 Non-local Means Filter が使用されているであろうことがわかります。 Blenderは各種バッファが個別に(ノードとかで)とれると思いますが、 それらのために、いっぱいNLMの計算をしているように見えます。 最後に、denoising_reconstructとかいう関数で、レンダリング結果を再構成(上書き)しているようです。 それらしい文字で検索してみると、 https://developer.blender.org/D2592 こちらのコミットでdenoise用のフィルター関数が追加されたようです。       REGISTER_KERNEL(filter_divide_shadow),       REGISTER_KERNEL(filter_get_feature),       REGISTER_KERNEL(filter_combine_halves),       REGISTER_KERNEL(filter_nlm_calc_difference),       REGISTER_KERNEL(filter_nlm_blur),       REGISTER_KERNEL(filter_nlm_calc_weight),       REGISTER_KERNEL(filter_nlm_update_output),       REGISTER_KERNEL(filter_nlm_normalize),       REGISTER_KERNEL(filter_construct_transform),       REGISTER_KERNEL(filter_nlm_construct_gramian),       REGISTER_KERNEL(filter_finalize), とか追加されていて、やはり主にNLMを使用しているようですが、 CPU用とCUDA用とOpenCL用が同時に追加されていますね。 さらにAVX用のファイルも中は空っぽいですが追加されていて、気合いを感じます。 いやー大変ですね。 CPU版の関数らしきものは blender/intern/cycles/device/device_cpu.cpp にあり、 bool denoising_non_local_means(device_ptr image_ptr, device_ptr guide_ptr, device_ptr variance_ptr, device_ptr out_ptr, DenoisingTask *task) こんな感じの関数が実際のフィルタ処理しているところのようです。 https://developer.blender.org/D2592 さて、実際に入ってるコードは上記チケットのコードですが、 以前のチケットを見たところ、最初に入れたいって言ってた人は別の人のようで、 上記チケットのレビューもしているようです。 最初は、この論文を実装したいと言っていたようです。 Adaptive Rendering based on Weighted Local Regression http://sglab.kaist.ac.kr/WLR/ 現在のdenoiseはGoogle SoCのプロジェクト https://wiki.blender.org/index.php/User:Lukasstockner97/GSoC_2016/Proposal によって、無事、上記論文の手法が実装されたっぽいです。 この手法は pbrt2 にも実装されているそうです。 実装した人、2016年当時、18歳です。すごいですね。 Blenderは優秀な若人によって日々成長しています。 すみません、で結局なんなの?というところの詳細まで終えてませんが、 ・kernelはNLMを使用している ・Weighted Local Regression(局所重み付き回帰)を使用している  たぶん http://sglab.kaist.ac.kr/WLR/ の論文相当が実装されている。 ということでした。 いつも通りBlender Artistsのスレッド読めば楽勝だぜ!と思っていましたが、 長すぎて挫折しました…(現在89ページも伸びている)。すみません Blender Advent Calendar 2017 3日目は  yuinore さんによる レンダーファームとか です。

Custom Renderer(1)

2016-12-11 00:00:00
本記事は、レイトレ Advent Calender 2016 10日目の記事です。 自作レンダラーをBlenderで使うためのあれこれです。 レイトレ自体とはあまり関係ないので恐縮です。 やりたいこと 前提として、この記事ではGPLライセンスは無視します。 成果物を公開する必要がない、Blenderを実験用DCCツールとして使いたい といったプログラマを想定しています。 ------------ 事前知識 BlenderにはCyclesというパストレのレンダラーが載っています。 このレンダラーが、モンテカルロ的な感じで、良い感じにジワジワとリアルな絵を レンダリングしてくれるのはご存知かと思います。 Cylcesはapacheライセンスで、オープンソースで公開されています。 レンダラーを作ってる人は、無料のBlenderに乗ってるCyclesみたいな感じで 本体に自分のレンダラーを組み込んでテストしたい!と思うはずです。 それを実際に商用ソフトで実践した例としてOctaneRender(for Blender)があります。 こちらは、まさにCyclesのようにノードを組み、シーンによりますがCyclesより速い速度で Blenderのレンダービューにレンダリング結果を表示します。 OctaneRenderでは、Blender本体を改造して、TCP通信によりローカルにインストールされたOctaneRenderServerと高速に通信を行っています。 一見リアルタイムに見えますが、裏でTCPでジオメトリやカメラ情報を送り、 送り返されたレンダリング結果画像をBlender上に表示しているというわけです。 通信を介することで、GPLライセンスの汚染を回避しています。 このOctaneRender(forBlender)による仕組みを利用できないか、と考えたこともありました。 しかし、このアプローチは本体改造のため、延々に本体の更新に合わせて サポートし続ける必要があり、趣味で週末にやるには厳しいものがあります。 そこで、Blender本体で、改造なしにできる、レンダラー組み込み方法を見ていきます。 レンダラ用API まず、Blender PythonでRender Engineというのがあります。 RenderEngine(bpy_struct) https://www.blender.org/api/blender_python_api_2_78a_release/bpy.types.RenderEngine.html?highlight=renderengine こちらにあるサンプルをBlenderのTextEditorに張り付けて実行します。 すると、Flat Color Rendererというレンダラーが追加されます。 続いて、F12を押してレンダリングしてみます。 このように青くなります。 先ほど張り付けたスクリプトでは、次のあたりで画像作ってるようです。 # In this example, we fill the full renders with a flat blue color. def render_scene(self, scene): pixel_count = self.size_x * self.size_y # The framebuffer is defined as a list of pixels, each pixel # itself being a list of R,G,B,A values blue_rect = [[0.0, 0.0, 1.0, 1.0]] * pixel_count # Here we write the pixel values to the RenderResult result = self.begin_result(0, 0, self.size_x, self.size_y) layer = result.layers[0].passes["Combined"] layer.rect = blue_rect self.end_result(result) ピクセルを書き込んでるようですね。無事画像は出せそうです! とは言っても、Pythonでレンダラー作ってる人なんて少数派なので、 これを別プロセスで走るC++などのレンダラーから行うことを考えます。 ---------------------- データの引き渡し レンダリングするには、Blender上のジオメトリやテクスチャ、カメラやノードなどのデータを、 自作レンダラーに引き渡さないといけません。 これを行うには複数の方法が考えられます (1) 自作レンダラーのPythonインタフェースをboost.pythonやpybind11等で作り、ダイナミックリンクさせ、Blenderと同一プロセスで自作レンダラーを動かす。 (2) TCPやwebsocketやnamedpipeでローカル通信を行う。 (3) メモリマップファイルを使用して一部のメモリを共有させる。 (2)を行うことで、OctaneのようにGPLライセンスの汚染を回避できたりしますが、 今回は最近やってみたかった(3)のメモリマップファイルというのを使ってみることにします。 ---------------------- メモリマップファイルで画像共有 マルチプロセスの環境では、直接メモリを参照できる(と思われる)メモリマップドファイルは、かなり有効な手段ではないかと思い、試してみます。 stbimageで1枚画像を読み込んで、メモリマップとして登録するC++コードはこんな感じです。 #define STB_IMAGE_IMPLEMENTATION #include &ltwindows.h&gt #include &ltstring&gt #include "stb_image.h" int main(int argc, char *argv[]) { if (argc <= 1) return -1; std::string file = argv[1]; int w, h, channels; unsigned char* data = stbi_load(argv[1], &w, &h, &channels, 4); HANDLE hmap = CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE, 0, w * h * 4, "testmmap"); if (hmap == NULL) { stbi_image_free(data); return -1; } if (GetLastError() == ERROR_ALREADY_EXISTS) { printf("ERROR_ALREADY_EXISTS\n"); } LPSTR mapview = (LPSTR)MapViewOfFile(hmap, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (mapview == NULL) { stbi_image_free(data); return -1; } // メモリマップに画像を転送. memcpy(mapview, data, w * h * 4); // TODO: ここでメモリマップドファイルをBlenderで読み込み表示させる // ここでメモリマップ削除される. UnmapViewOfFile(mapview); CloseHandle(hmap); stbi_image_free(data); return 0; } 続いて、python側でこれを表示させます。 とりあえずVCのデバッグで、UnmapViewOfFileのところでbreakで止めて render_sceneのところに以下のコードを埋めこんでレンダーしてみます。 画像サイズはとりあえず決め打ちです。 blue_rect = [[0 for i in range(4)] for j in range(pixel_count)] mm = mmap.mmap(-1, 240*240*4, tagname="testmmap") mm.seek(0, os.SEEK_END) mmsize = mm.tell() mm.seek(0) image = mm.read(mmsize) for i in range(int(mmsize / 4)): rgba = struct.unpack_from("4B", image, i*4) blue_rect[i][0] = rgba[0] / 255 blue_rect[i][1] = rgba[1] / 255 blue_rect[i][2] = rgba[2] / 255 blue_rect[i][3] = rgba[3] / 255 ふむ、逆になってますが、なんか出ました。結果画像はいけそうです。 ---------------------- データ共有 これが厄介です。 objで出力するコード部分にメモリマップで出すように仕込んだりしてみましたが、 objで出力する(Blender標準の)エクスポーターが遅い!!! 100万ポリゴン一瞬で出してくれないと困ります。 BlenderはAlembicに対応しましたが、Alembicの出力コードはpythonからは全くアクセスできず、 こちらも使えません。 また、各種自作レンダラーは、独自のシーンファイルを定義しないと動かなかったりして、なかなか厄介です。 すみませんここ考えてる途中で時間切れです!(続く) 明日は Ushio さんによる、”確率密度関数周りの何かを” です!

blender - MMDボーン名をLRにする

2016-08-03 00:05:00
絶対誰か作ってるだろうと思うけど、それ探して入れるより書いたほうが圧倒的に速い気がしたので、 ちゃちゃっと作成。 to_blender 右~→~.R 左~→~.L to_mmd ~.R→右~ ~.L→左~ となります 使い方: テキストエディタに張り付けてメッシュとボーンを全部選択して実行。 元に戻すときは、最後のあたりを #to_blender() to_mmd() にして実行。 免責事項: 数分で書いたかき捨てスクリプトなので必ず保存してから実行してください どうなっても責任とれません # -*- coding: utf-8 -*- import bpy def to_blender(): for obj in bpy.context.selected_objects: if (obj.type == "ARMATURE"): for bone in obj.data.bones: if ("右" in bone.name): bone.name = bone.name[1:] + ".R" if ("左" in bone.name): bone.name = bone.name[1:] + ".L" if (obj.type == "MESH"): for group in obj.vertex_groups: if ("右" in group.name): group.name = group.name[1:] + ".R" if ("左" in group.name): group.name = group.name[1:] + ".L" def to_mmd(): for obj in bpy.context.selected_objects: if (obj.type == "ARMATURE"): for bone in obj.data.bones: if (".R" in group.name): bone.name = "右" + bone.name[0:-2] if (".L" in group.name): bone.name = "左" + bone.name[0:-2] if (obj.type == "MESH"): for group in obj.vertex_groups: if (".R" in group.name): group.name = "右" + group.name[0:-2] if (".L" in group.name): group.name = "左" + group.name[0:-2] to_blender() #to_mmd()

blender - 軸を変えずにボーンの長さを変更する技

2016-07-25 01:05:00
以下 twitterで教えてもらった手法(@tarava777 さんありがとうございます) 1. ボーン編集モードで、マニピュレータをノーマルにして、左のやつをアクティブ要素にします 2. 長くしたいボーンのヘッドと、その子ボーンすべてを選択します。 違う軸のマニピュレーターが出てしまった場合は、 ヘッドの丸ぽち目がけてshift押しながらマウス右クリックを何回か押すとうまく選択できたりします。 3. マニピュレーターでy軸方向に移動させます。 以上です。 以下古い手法 結構悩んでたどり着いた技。 (わかりやすいように、ちょっとオーバーにしてます) これではMMDのモーションが同じように適用できない! そこで全てのユーザトランスフォームをリセットした状態で、 ポーズモードで、スケールを継承のチェックを外し、 ポーズモードで、スケールさせます。 Ctrl + A で、デフォルトのポーズに適用します これでようやく軸を維持したままボーンの長さを変えることができます。めんどい

etc - URL変わりました

2016-06-23 23:00:00
www.blenderburger.com

blender - ディフュージョンフィルタ

2016-05-08 01:52:00
アニメ表現を目指す上で欠かせない(?)、ディフュージョンフィルタを試してみました。 元ネタはググったらいっぱい出てきます。 元画像 ノード 結果画像 それっぽいですね! ちなみにDiffusionって書いてあるフレームの中だけだとこんな感じ。 フレームの外の部分は、参考にしたブログの人がこんな感じにしてたのでやってます。 見比べてみると、フレームの中だけのほうが良いかな…。

Blender - Blenderバーガーオフ2

2015-12-06 23:15:00
Blender Advent Calender 2015 12月6日の記事です。 みなさん、そろそろ忘年会シーズンですが、いかがお過ごしでしょうか?? さて、本日、2年ぶりに、Blenderバーガーオフ!を開催したので、その模様をお伝えしたいと思います。 Blenderバーガーオフ会とは Blender使いが集まってハンバーガーを食べるオフ会です。 なぜハンバーガーなのか? 主催者がハンバーガー好きだからです。 Blenderと関係あるのか? バーガーは、パーティクル(ゴマ)、ソフトボディ(バンズ)、弾性/流体計算(チーズ)、サブサーフェススキャタリング(パティ/レタス) などの様々なCG要素で構成されています。 かの有名なビルゲイツですらハンバーガーを食べながら仕事をしていたと言われています。 また、Blenderを通じて、以下のような様々なバーガーに対するアプローチが行われています。 ・http://blenderartists.org/forum/showthread.php?351419-Burger ・http://gman20999.deviantart.com/art/Blender-cycles-3D-model-burger-render-568035930 ・http://real3d.fr/3rd-day-with-blender-food/ ・https://inevitablecrafts.wordpress.com/2012/06/01/blender-camera-t-r-a-c-k-i-n-g/ みなさんもCGをやる傍ら、バーガーを食べて健康を保ちましょう! Blenderバーガーオフ2の模様 こちらがバーガーオフの模様です! とても美味しそうですね! やはりこの魅力は静止画だけでは伝え切れません。 そこで動画を撮ってみました。こちらです! (酔っ払っていて微妙な撮り具合ですみません) どうでしょうか。おいしいハンバーガーを食べたくなってきましたでしょうか? 一旦Blenderの手を止めて美味しいバーガーを食べましょう! Blenderで行き詰っていた問題が解決するかもしれません!! さて、明日12/7のBlender Advent Calenderは、@psi_ni_phi さんです!

Blender - Animation Nodes

2015-12-05 02:16:00
Blender Advent Calender 2015 12月5日の記事です。 最近リリースされたBlenderのアドオンで、Animation Nodes という凄そうなものがあります。 今回はAnimation Nodesについて、導入から、何が出来るかまで調べていきたいと思います。 まずAnimation Nodesを使うとどのような表現が可能か? こちらに良くまとまった動画があるようなのでご覧ください! かっこいいですね! インストール Blenderにインストールを行います。この記事でインストールする環境は以下のとおりです。 ・Windows7 (64bit) ・Blender2.76b 1. まずGitHubのサイトから animation_nodes.zip をダウンロードします https://github.com/JacquesLucke/animation_nodes/releases 2. BlenderのUserPreferencesを開いて、Addonsのページで、Install from File..で、先ほどダウンロードしたzipファイルを選択して開きます。 3. 読み込まれたアドオンにチェックを入れて使用可能にします 4. 重要:File タブの「Auto Run Python Scripts」にチェックを入れ、問題無さそうならSave User Settingsを押して設定を保存します。 5. 以上でインストール完了となります。ノードエディタを開くと Animation Nodes が追加されています。 使ってみる 早速使っていこうと思います。 ノード主体でいじるので、画面構成は、Compositingのレイアウトがお勧めです。 1. Newのボタンを押して新規ノードツリーを作成します。 2. addメニューからノードを追加します。 ・Object → Transforms Output ・Animation → Time Info を追加してください 3. ObjectTransformsOutputのRotationのXにチェックを入れます。 ObjectTransformsOutputのオブジェクト入力ボックスで Cube を選択します。 TimeInfoのFrameを、ObjectTransFormsOutputのRotationに繋ぎます。 4. すると以下のように Combine Euler というノードが間に現れます。これは、種類(=色)の違うノードを接続しようとしたため、Animation Nodesが両者を変換するノードを間に挿入してくれているようです。 5. ノードが出来ましたので、Alt + A キーを押してアニメーションさせるか、タイムラインをドラッグしてください。 結果、ボックスが x軸中心 で回転します! 6. 何が起こっているのか?  ・TimeInfoノードは、現在のフレームを入力するノードです。   タイムラインをドラッグすると"Frame" の端子に、1、2、3、4・・・と次々にフレーム番号が入ってくるわけですね。   Blenderでは標準のコンポジットノードに、Timeというノードがありますが、そちらは0~1に正規化された値が入ってくるので若干違います。  ・TransformsOutputノードは、オブジェクトのトランスフォームを出力するノードです。   指定したオブジェクトの、移動、回転、拡縮を入力できるます。   今回x軸回転を有効にしましたが、"Rotation"の端子はオイラー(Euler)角での入力になるので、3.14…で1回転ですね。   なので上記のフレーム数を入れるとなんだか良く分からない回転になっていたわけです。 7. おまけ Propertiesパネルの、Inputs/Outputsでノードの端子の表示非表示や、並び替えなどが出来るようですね。 今回はx軸以外使っていないので、以下のようにy、zを非表示にすると若干見やすくなります。 ノード一覧 さて、基本的な使い方がなんとなく分かったので、片っ端からノードの性質を調べていきます。 カレンダー当日に初めて触りながら作ってるので間違いがあったらすみません。ご指摘ください。 Number Integer 整数(Integer)を入力するノードです。 Float 浮動少数(Float)を入力するノードです。 Integer List Integerノードを複数入力し、リスト形式で出力します。 Float List Floatノードを複数入力し、リスト形式で出力します。 Integer Range StartからStepごとにAmount個の要素のリストを作って出力します。 画像の状態では、リスト [0, 1, 2, 3, 4] が出力されます。 Float Range 同上. Randomize Seed(乱数の種)を元に、Min~Maxの範囲内の値をランダムに作って出力します。 Node Seedは、ノードを複製したときに全く同じ乱数が生成されないようにするための値です。 ノードを複製すると、Node Seedは自動的に違う値になります。 Wiggle ぷるぷるする値を出力するノードです。 パーリンノイズベースで漸進計算を行い、ある程度周期性のある値を出力します。 Evolutionには通常の使用ではフレーム番号を入れることが多いようです。たぶんEvolutionの値が近いほど近い値になります。 Seed(種)、Evolution(世代数?)、Amplitude(どのくらい動くか)、Octaves(パーリンノイズの係数)、Persistence(パーリンノイズの係数) OctavesはノイズのMipMapみたいなものでしょうか。 Evolution間のでのノイズ変化のマップをどの程度作りこむかと言う値で、大きくするとEvalutionが近くても細かく変化するようになりますが、処理時間が増えます。 Persistenceは、Octaveの影響をどの程度拾うかで、大きいほど細かい変化(=Octaveの大きいマップ)を良く拾うようになります。 なんだか良く分からないので、使用している動画を探してみました(動画ではVectorのWiggleですが)。 Mix Floatの値、A、Bを、Factorによって合成します。 A * Factor + B * (1.0 - Factor)ですかね。 ClampFactorにチェックを入れると、Factorが0~1以外であれば0か1に丸め込まれます。 MapRange Output = ((Value - InputMin) / (InputMax - InputMin)) * (OutputMax - OutputMin) + OutputMin です。 Clamp ValueをMin-MaxでClampします。たとえば画像の状態では、 入力Value = -1 なら 出力Value = 0、入力Value = 0.5 なら 出力Value = 0.5、入力Value = 1.5 なら 出力Value = 1 となります。 ConvertAngle DegreeをRadianに変換します。たとえば、 Degree = 90(90度)なら、Radian = π/4 となります。 Convert Float To Integer 浮動少数を整数に変換します。割と自動で挿入されます。 Round number を小数点以下 Decimals桁で丸めた浮動小数点数の値を出力します。 Math 数学関数がいろいろ使えるノードです。 List Math Mathノードを、リスト形式の入力に対して使えます。 Vector Separate Vectorを x, y, z の数値に分解します。 Combine x, y, zをVectorに統合します。 Float Value ValueをVector(value, value, value)に変換します。 List 複数のVectorをリスト形式で出力します。 Randomize Number-Randomizeを参照. Wiggle Number-Wiggleを参照. Mix Number-Mixを参照. Length Vectorの長さ√(vector^2)を出力します。 Distance Vectorの距離 Length(B-A) を出力します。 Math 数学関数がいろいろ使えるノードです。 Transform Vector VectorをMatrixによりトランスフォームします。移動、回転、拡縮要素が入ったMatrixを入れることで任意の変換が行えます。 Transform Vector List VectorのリストをMatrixによりトランスフォームします。 Rotation 回転の各種型変換。 Combine Euler Combine Quaternion Direction to Rotation Euler to Quaternion Quaternion to Euler Quaternion to Matrix Matrix to Quaternion Euler to Matrix Matrix to Euler Euler to Vector Vector to Euler Matrix Decompose Matrixを移動、回転、拡縮のVectorに分解します。性質上、可逆ではないです。 Compose 移動、回転、拡縮のVectorを合成してMatrixを作って出力します。 List Matrixのリストを作ります。 Translation Matrixを移動させて出力します。 Rotation Matrixを回転させて出力します。 Scale Matrixをスケーリングして出力します。 Combine Matrixのリストを合成して1つのMatrixにして出力します。使いどころあるのか謎。 Mix 複数の行列を合成します。使いどころあるのか謎。 Invert 逆行列を出力します。 Math 各種行列計算するノードです。ってMultiplyしか無いですが… Text Input Text入力ノードです。 List 複数のテキストをリスト形式で出力するノードです。 Randomize Charaの文字列中からランダムなテキストを生成して出力します。 Characters 指定した文字列セットを出力します。たとえばLowerCaseは"a, b, c ... z"といった小文字の文字セットを全部返すと言う具合です。 Randomizeなどの入力(Chara)用だと思われます。 Split TextをSplitByの文字列で分割してリスト形式で出力します。 Join リスト形式のTextをSeparaterの文字列を区切り文字として結合し、1つのテキストとして出力します。 Replicate TextをAmount個複製して1つのテキストとして出力します。 Replace Text中の文字列Oldを文字列Newに置換して、出力します。 Trim Text TextのStart文字目からEnd文字目までの文字列を出力しいます。 Fill TextをLength文字になるように、指定方向をFillの文字列で埋めます。 たとえば、方向:Left、Length = 5、Text = abc、Fill = piyoの場合 "piabc"が出力されます。 Length Textの長さを出力します。 Object Separate Sourceで選択したTextオブジェクトの指定したマテリアルの文字列を、 Text、Curve、またはMeshとして、1文字1文字分割します。 Block Reader TextBlock(Text Editorに読み込んでるテキスト)をTextとして出力します Block Writer 入力されたTextを指定したText Blockに出力します。 Sequence Output ??? Object Output 指定したオブジェクトに入力されたText, Size, Extrudeを適用します。 □のトグルボタンを押しておかないと反映されない点に注意です。 Boolean Booleanとは、true(真)かfalse(偽)かを表す型です。 Boolean Booleanを入力します。チェックを付ければtrue、チェックが無ければfalseが出力されます。 Invert Booleanを逆にします。 Compare A、Bに、指定したTypeの比較演算を行い、Booleanを出力します。 Logic 2つのBooleanに論理演算を行い、Booleanを出力します。 Switch Conditionに入力したBooleanがtrueの場合、if Trueの値が出力されます。 Conditionに入力したBooleanがfalseの場合、if Falseの値が出力されます。 Boolean to Integer Booleanを整数 0 (false) または 1 (true)に変換して出力します。 Color Choose Color カラーピッカーでColorを選択して出力します。 Combine Color RGBAなど、それぞれの値を結合して1つのColorにして出力します。 Separate Color ColorをRGBAなどの値に分割して出力します。 Mix 複数のColorをFactorにより合成して出力します。 Set Vertex Color 指定したオブジェクトの頂点カラーをセットします。 List Create 入力値をListにして出力します Combine 複数のListを結合します Append Listに要素を追加して出力します Search Listから値を検索し、見つかった最初のIndex(First Index)、全てのIndexリスト(All Indices)、見つかった要素数(Occurrences)を出力します。 Get Element Listの指定したIndexの要素を出力します Get Length Listの長さを出力します Shuffle ListをSeedによる乱数によって並び替えて出力します Reverse Listを逆順にして出力します Slice ListをStartインデックスからEndインデックスまで切り取って出力します たとえば[ 1, 2, 3, 4 ]というリストに対して、Start = 1、End = 3とすると、[ 2, 3 ]が出力されます Object Create 指定したNameのObjectを新規作成します Input Objectを選択して入力します List Objectのリストを作成して出力します From Group 指定したGroupからObjectのリストを取得します。 Transform Input 指定したObjectの位置(Location)、回転(Roatation)、拡縮(Scale)のプロパティを取得します Transform Output 指定したObjectに位置(Location)、回転(Roatation)、拡縮(Scale)のプロパティを出力します Matrix Input 指定したObjectのWorld Matrixを取得します。 Matrix Output 指定したObjectに指定したTypeのMatrixを設定します。 Attribute Input 指定したObjectの指定したAttributeの値を取得します。 Attribute Output 指定したObjectに指定したAttributeの値を設定します。 Visibility Input 指定したObjectのShow/Hide状態を取得します。 Visibility Output 指定したObjectにShow/Hide状態を設定します。 Data Path Output 指定したObjectのDataPathに値を設定します。 DataPathというのは、Objectを選択した状態で、Object内に保存されてそうな値のGUIの入力ボックスを、右クリックして、Copy Data Pathで取得できます。 Object ID Key Animation Nodes上で、あるObject(A)に関連付けて作成したObject(B)がある場合、 このノードで(B)を選択することにより、(A)の情報が取り出せる模様。 たとえば、Text - Object Separateで、あるTextを分割した場合など。 Copy Object Data Fromで選択したObjectのObject DataをToのObjectにコピーする。 Set Keyframes 指定したObjectの指定したプロパティに、キーフレームを設定する。 Animation Nodesで作ったアニメーションをキーフレームにベイクできるようだ。 http://blendersushi.blogspot.jp/2015/11/an-intermediate-procedural-animation.html Layer Visibility Output Objectの表示レイヤーを変更できる Utils - Move Objectを移動させる Utils - Transform ObjectをMatrixによりトランスフォームさせる Utils - Update Matrix Objectのupdate()を行う. Utils - Reset Transformation Objectのトランスフォームをリセットする Utils - Copy Transformation Objectのトランスフォームを指定したオブジェクトにコピーする. Utils - Get Bounding Box ObjectのBounding Boxを取得する。 Mesh Object Mesh Data 指定したObjectのMesh Dataを取得します Separate Mesh DataをVertex Locations/Edge Indices/Polygon Indicesに分割します Combine Vertex Locations/Edge Indices/Polygon IndicesをMeshDataに結合をします Generators - Line Lineを生成します。 Generators - Grid Gridを生成します。 Operators - Find Close Vertices 頂点群のうち、Min/Max Distanceを元に近い頂点を探し、指定した数のClusterに分割し、入力した接続数のEdgeリストを作って出力します パーティクルと組み合わせて次のようなことができるようです。 http://www.local-guru.net/blog/2015/11/20/Animation-Node-experiment---curve-cluster Operators - Edge to Planes 頂点リスト、辺リストを元に、ポリゴンを生成します。 Operators - Create Edge Indices 頂点インデックスからEdgeを生成します。 Operators - Create Polygon Indices 頂点インデックスリストからポリゴンインデックスを生成します。 Operators - Edge to Polygons ポリゴンインデックスリストからエッジリストを取得します。 Operators - Transform Polygons ポリゴンをMatrixによりトランスフォームさせます Mesh Data from Polygons ポリゴンリストからMesh Dataを取得します。 BMesh from Mesh Data Mesh DataからBMeshを取得します Tools - Remove Doubles 入力されたBMeshのうち、Distanceで指定した距離範囲内の頂点を重複頂点とみなして1つにして出力します Tools - Recalculate Normals 入力されたBMeshの法線を再計算したBMeshを出力します Tools - Shader Object Smooth 指定したObjectのスムージングの有効/無効を設定します。 Vertex Locations 指定したObjectの頂点位置をVerticesを元に設定します。 Mesh Data 指定したObjectのMesh Dataを設定します。 BMesh 指定したObjectのBMeshを設定します。 Spline Get from Object 指定したObjectからSplineリストを取得します Create from Points ポイントリストからSplineを生成します Create from Edges エッジリストからSplineを生成します List 複数のSplineを1つのリストとして出力します。 Append Point 指定したSplineにポイントを追加します Smooth Bezier 指定したベジェSplineをスムースにします Transform 指定したSplineをMatrixによりトランスフォームします Connect 指定したSplineリストを接続します Trim 指定したSplineをStart~Endの範囲で切り取ります。 Start, Endは、Splineの始点から終点を0~1としたときの値です。 Make Cyclic 指定したSplineの始点と終点をつなげてCyclicにします Info 指定したSplineの情報を取り出します Evaluate 指定したSplineの、(始点から終点を0~1としたときの)Parameter位置での、LocationとTangentベクトルを出力します。 Project 指定したLocationから、指定したSpline上のもっとも近い点のPosition、Tangent、Spline Parameterを出力します(たぶん Get Length SplineのStart~EndまでのLengthを出力します。 Get Samples Spline上の、StartからEndまでの区間のうちAmount個の点のPositionリストとTangentリストを出力します Set on Object 指定したObjectに指定したSplineを設定します Curve Object Output 指定したCurve ObjectをBevel,Extrudeなどのパラメータを元にShape/Geometry(PropertiesパネルのDataタブ参照)を設定します Loft ???(調査中 Revolve Spline ???(調査中 Animation Time Info 現在のフレームを出力します Delay (Time - Delay) が出力されます。 Repeat Type=Loopの場合、TimeをRateで割った余りが出力されます。Rateは0.0001以下であれば0.0001に丸め込まれます。 Type=PingPongの場合、Timeの増加に応じて、0~Rateの間でいったり来たりする値が出力されると思われます Animate Number 入力したStart、Endの値を期間Durationで、指定した補間方法で補間し、Resultとして出力する。 どうやらTimeは0から始まるのを前提としているらしく、図の例では0~20の間にTimeの値が入ったときResultが変化し、 0以下の値を入れるとResult = Startであり、Duration以上の値を入れるとResult = Endとなる。 出力値のTimeは、Animateノードを連続して繋げることを想定しているようで、(入力Time - Duration)が出力Timeとして出力される。 以下のような使ってる動画があったけど、慣れないと使うのきつそう。 Animate Vector 同上. 2つのVectorを補間する Animate Color 同上. 2つのColorを補間する Animate Matrix 同上. 2つのMatrixを補間する Interpolation Construct 補間方法を入力します。 From Curve Mapping 補間の具合をカーブで指定します。 From FCurve FCurveから設定されている補間方法を取得します Evaluate 0~1の値をpositionに入力すると、指定した補間方法で補間された値が出力されます。 0以下、または1以上の値を入力すると、0または1入力されたとみなされます Mix 2つの補間をFactorにより合成します。 Material Cycles Material Output 指定したCycles Materialの指定したプロパティに値をセットできるようです 以下のリンクの一番したのほうに使用例があります。 http://blender.stackexchange.com/questions/26388/can-i-refer-to-another-objects-properties-from-a-cycles-node-shader-drivers-i Viewport Color 指定したMaterialのViewport Color(CyclesRenderのときにMaterial->Settingsにあるやつです)を設定できるようです Particles System Input Particleオブジェクトを入力し、Particle Systemのリストと、activeなParticle Systemを出力します。 Get Particles Particle SystemからParticleリストを取得します。 Particles from Object 指定したObjectからParticleリストを取得します State Filter ParticleのStateによりフィルタリングしたParticleリストを取得します Particle List Info ParticleリストからLocationリストを取得します Particle Info ParticleからLocationとRotatonを取得します FCurve From Object 指定したObjectからFCurveリストを取り出します。 Evaluate FCurveの指定したフレームでの値を取得します Info FCurveのData PathとArray Indexを取得します Keyframes FCurveのキーフレームリストと、値リストを取得します Sound Bake Sound Sound from Sequences Get All Sequences Sequences from Channel Evaluate Sound KDTree Construct VectorのリストからKDTree(空間構造の1つです)を構築します。 Blender Standard ModuleのKDTreeを使用していると思われます。 http://www.blender.org/api/blender_python_api_2_76_2/mathutils.kdtree.html Find Nearest KDTreeにより、入力した座標から最も近い点を探し、その座標(Vector)、距離(Distance)、Indexを出力します。 Find Amount KDTreeにより、入力した座標から近い点をAmount個探し、その座標リスト(Vectors)、距離リスト(Distances)、Indexリストを出力します。 Find in Radius KDTreeにより、入力した座標から半径Radiusの範囲内にある点を探し、その座標リスト(Vectors)、距離リスト(Distances)、Indexリストを出力します。 Subprograms Invoke Subprogram Group Input Group Output Loop Script MyScript MyGroup MyLoop Debug デバッグ用ノード。詳細不明。使わないのが吉。 ところで、expressionノードとか無いの? ノードを繋げてコードや数式を作るというのは、大変な作業です。 直接数式かコード書けるノードは無いのか?まず最初にこれが気になりました。 ざっとみた感じ、無いです…。 Pythonスクリプトを参照するノードではなくて、HoudiniのWrangleみたいに、ノードの中にコードか数式が書きたいんです。 sin(frame-floor(frame)) * 20 とかどう考えても数式で書いたほうが効率良いです。 ・・・。作るか・・・・・・ ちなみにここに新しいノードの作り方が書いてあります http://animation-nodes-manual.readthedocs.org/en/latest/dev_guide/getting_started/first_node.html さて、作ろうかと思っていたところ、なんと!発見しました!! Add(またはShift-A)→Search→"expression"!!! 隠しノードですかね??? さて、明日12/6のカレンダーは uimacさんによるBlenderバーガーオフ2 です!

blender - Bezier曲線を生成する(2)

2015-01-08 22:51:00
進捗 2015年になりました 前回、一続きの頂点群を与えて、それにフィットするようなBezier曲線を1つ(=アンカー2点+ハンドル2点)作成できるようになりました。 しかし、複数の曲線を生成してないので、かなり結果がしょぼいです。 複数の曲線を生成するのは簡単で、単に頂点群を適当に分割して、それにフィットさせれば良いだけです。 [オリジナルのfitcurve.cの場合] 1. 全ての頂点に対して、曲線を1回フィットさせます(前回の記事) 2.1 誤差が許容範囲であれば終わります。 2.2 誤差が許容範囲よりちょい大きいくらいであれば、   任意の頂点 P に対応する t 軸上の点(前回の記事)をニュートン法で変更しつつ許容範囲に収まらないか調べます。   2.2.1 許容範囲に収まったら終わります。 2.3 誤差が許容範囲外であれば、一番誤差が大きい点で分割し、深さ優先で再帰させます。 この方法で同じように実装して検証してみたところ、確かに 2.2 によって早く収束します。 2.2 によって収束した場合は、その部分の曲線が許容誤差ぎりぎりになってしまいます。 2.2 を行わないほうが、どんどん曲線を増やしながら分割していくので、線の数は増えますが、かなりぴったりの曲線になりました。 また、2.3で、一番誤差が大きい点をアンカーにして分割していくのは、確かに効果的な気がします。 が、実際にやってみたところ、点群のインデックスを半分に分割していったほうが、曲線が少ない場合に良い結果が得られました。 Bezier曲線は、自由度が高いので、細かい範囲で使うよりも、ある程度大きな範囲で使ったほうが、効果的なのかもしれません さらに、今回自分が考えている用途では、指定した曲線数で近似する、という機能も欲しいため、 2.3 で、深さ優先ではなく、幅優先で再帰させ、分割数をカウントしていくようにしました まとめると、 [uimacの場合] 1. 全ての頂点に対して、曲線を1回フィットさせます(前回の記事) 2.1 分割数が指定数に達していれば終わります。 2.2 誤差が許容範囲であれば終わります。 2.3 分割数をインクリメントします 2.4 誤差が許容範囲外であれば、頂点群のインデックスの半分で分割し、幅優先で再帰させます。 結果的に、オリジナルで実装されていたニュートン法は要りませんでした。 文字ばっかりですみませんが、そろそろプラグイン化して配布を予定しています。

blender - 彼女をプロシージャル生成したかった

2014-12-24 02:13:00
この記事は Blender Advent Calender 2014/12/24 の記事の 前半 です。 9割くらいが僕の妄想でできている記事です。 言い換えると、どっかの頭沸いてるプログラマがクリスマスの予定が無いから書いた記事です。 品質についてはご了承ください。 あと、進捗ですが、全然できてないです。1%くらいです。 --------------------- 3Dの彼女をプログラムで作りたいです。 最初は、3Dのキャラクターをモデリングして、かわいくできるだけで満足していたのですが、 ここ最近、皆さまのモデリング力向上は目を見張るものがあり、 もはや、プログラマーである自分がモデリングしなくても、誰かの作ったものを見るだけで満足してしまっています。 しかし、一つだけ残念なのは、「このキャラはワシが作った(育てた)!」と言えないところです。 偶然にも自分はプログラマーなので、全てのスキルを使ってかわいい3Dキャラをプログラムで作りたいと思っています。 --------------------- 彼女の作り方 彼女の作り方について考えてみます。 ①Blenderでキャラクターを作りたい人は、まず書店で、 「キャラクターをつくろう! 3DCG日和。 vol.3 -Blenderでつくる、ポリゴンキャラクター」 を購入します(当然持ってますよね:D) 世の中に出回っている書籍のとおり、3Dモデリングでキャラクターをつくるときの 基本的な手続き(プロシージャ)は、大体同じような感じだと思います。 さらに、出来上がるメッシュについても、かわいいキャラのメッシュの流れについては類似している点が多いです。 だいたい似てるので、あらかじめ何かいい感じのを用意しておけば良い気がしてきました。 なんかいけそうな気がしてきます。 ②次に、何を作りたいかを、まず考えます。 汎用的な3Dキャラが作りたいわけではないです。 俺好みのかわいい3Dキャラクターができればそれでいいのです。 ちょっと趣向がバレるのであまり書けませんが、 ぽっちゃりはご遠慮願いたいし、よくある爆乳とか興味ないし… などとぼんやり考えます。 これらは、彼女を作るうえでの制約条件ということにします。 ②は制約条件をガシガシ関数にしていくとして、 ①はちょっと曖昧すぎます。 ①についてもう少し考えてみます。 メッシュの流れ類似性については、あらかじめ解析して、関数か何かに落とし込みたいです。 モデリングはそんなに上手くないので、例としては微妙ですが、実際に参考にするときは このような感じで注目して、目で見てなんとなく覚えるかと思います。 しかしこれをプログラミングで覚えるとすると結構大変です 頂点が面の情報を100個くらい保存しておいても全く役立ちません! 目で見てなんとなく覚えるときは、この"流れ"を曲面的な感じで捉えていると思うので、 曲面にしようかと考えましたが、曲面は難しいので、デザイナーご用達ツール"ベジェ曲線"にできないかと考えました。 ベジェ曲線はBlenderにありますが、これを手作業で合わせるのは大変なので、 GreasePencilで"流れ"に沿って線を引いて、それをBezierに変換してみました。 ・・・。 ・・・・・。 これじゃねえぇぇぇぇ!!!! これじゃないです。もっとInkScapeとかイラレみたいな綺麗な変換してくれよ! ということで、後半戦 「Bezier曲線を生成する」に続きます。

blender - Bezier曲線を生成する

2014-12-24 02:13:00
この記事は Blender Advent Calender 2014/12/24 の記事の 後半 です。 ちょっと待て!彼女を生成するってやつはどうなったんだ? って人は、前半をご参照ください。 ウェブアプリを作ろうと思って、気づいたらOS作ってた とか、 3Dアプリを開発しようと思って、気づいたらサーバー組んでた とか、 3Dで彼女をプロシージャル生成しようと思って、気づいたら最適化数学で曲線をフィッティングしていた とか、 我々プログラマには良くあることです。 ------------------------------ ペンやマウスで描画すると、自動的にきれいなベジェ曲線にしてくれるドローアプリでは、 Blender使いご用達のInkScapeというアプリがあります。 このような、ある頂点群(たとえばペンで描画した描画点や、メッシュ上の選択した頂点)に対して、 ベジェ曲線をフィッティングする問題を考えます。 といってもそんな頭良くないので、InkScapeの実装の元ネタである Graphics Gems 1 の 「An Algorithm for Automatically Fitting Digitized Curves」を理解しつつ実装することにします。 このアルゴリズムは、2つの手法から成り立っています。 1. ニュートン法 ( Newton-Raphson method ) 2. 最小二乗法 ( least squares method ) このうち、2のほうがメインのフィッティング処理です。 というわけで2のほうだけやります。 ------------------------------ といっても難しいので、まずは2次元で考えます。 こんな感じで2D平面上に頂点があるとき、全頂点にできるだけ近い直線を引くような問題を解くのが最小二乗法です。 具体的には、直線と各点の距離(誤差)の二乗の合計が、最小になるような直線を求めます。 直線を y = ax + b として、x上のある値 xα での、頂点を yα とすると、 yαと、xαでの直線上の点との差分は、 yα-(axα + b) です。 距離の二乗和は、 となり、この式が最小になるような、a、bを求めます。 求め方ですが、上記の∑の式の中身は距離なので、a, bをそれぞれ変化させたときに、それぞれ極小値があります。 よって、上記の∑の式を J と置くと、 となります。 これを計算していくと、最後に連立一次方程式となり、解くことができます。 このあたりの詳細は、参考文献(1)が詳しいです。この辺は、結構ウェブでもあります。 ------------------------------ 次にベジェ曲線を、ベジェ曲線について、少し書きます。 ベジェ曲線は、3次のものしか使わないので、ここでは3次とします。 3次のベジェ曲線は、アンカー2つと、その間のハンドル2つでなります。 ベジェ曲線の数式は、次のように定義されています。 ここで Vi は i番目のベジェ制御点で、実際には3Dなので V(xi, yi, zi) のようなベクトルになります。 i は、0から n まで入ります。 また、Biは、バーンスタイン基底関数とか呼ばれている、0以上1以下の変数 t の関数です。 この変数 t に 0から1までの数を次々に入れると、ベジェ曲線ができます。 n はベジェ曲線の次数で、2次だったら、アンカー2点とハンドル1つ、3次だったらアンカー2つとハンドル2つとなりますが、 今回は3次なので、nに3を入れておきます。 上から、B0, B1, B2, B3 と置いて、pythonの関数で書くと、こうなります。 def B0(t): return (1.0-t) * (1.0-t) * (1.0-t) def B1(t): return 3 * t * (1.0-t) * (1.0-t) def B2(t): return 3 * t * t * (1.0-t) def B3(t): return t * t * t また、今回実装予定のアルゴリズムでは、ハンドルはアンカーの接線上に配置します。 そうすることで、曲線の連続性が得られ、前後で滑らかに繋がります。 ------------------------------ さて、ベジェ曲線は、ご覧のとおり、t による関数なので、直線のときみたいに x とか y とかを使って最小二乗法するわけには行きません。 また、何を最小にするかも一工夫必要です。 任意の頂点群にできるだけ近いベジェ曲線の、ベジェ制御点 V0, V1, V2, V3を求めたいわけですが、 V0とV3については、頂点群がペンでの描画と考えた場合、最初と最後の点で良さそうです。 残るは、V1, V2ですが、 上で、ハンドルはアンカーの接線上に配置するという制約を付けたので、アンカー接線上にあります。 V0、V3の、アンカー接線の単位ベクトルを T0、T3とすると、 V1、V2は、T0、T3の定数倍をV0, V3に足すことで表させます。 つまり、 V1 = V0 + a T0 (aは定数) V2 = V3 + b T3 (bは定数) となります。 また、最小にする値は、頂点群のうちの、任意の頂点 P に対応する t 軸上の点を tαとしたとき、 ベジェ曲線上の点 Q(tα) と頂点 P との距離になります。 任意の頂点 P に対応する t 軸上の点を tα は、どうやって出すかというと、 たぶん 0から1の値をとる t を、適当に頂点群の個数で割った値、とかにしてもいいと思うんですが、 この実装では、 tα = 頂点群の最初から頂点Pまで繋げた長さ / 頂点群を最初から最後まで繋げた全体の長さ としているようです。適当に割るよりは良さそうです。 さて、以上をまとめると、最小二乗法の最小にしたい式が出来ます。 この式が最小になるような、アンカー接線上の点 V1, V2 を求めるんですが、 上に書いた通り、V1, V2 は 単位接線ベクトルの定数倍なので、その定数 a, bを求めれば、求まります。 a, b を変化させることにより、J、つまり距離(誤差)の二乗和の合計が変化し、それぞれ極小値があるので、 が成り立ちます。 で、例によってこの先は計算の嵐なので、省略しますが、最終的に2次の場合と同じく、 連立一次方程式が出来て、その解を求めることで、a、b が求まります。 この辺余力があれば書こうと思ったんですが、もう時間無いので、残りの式が気にある方は自分で出すか、 Graphics Gems 1 を入手してください。 ------------------------------ このように最小二乗法によるベジェフィッティングを理解しつつ、 Graphics Gems1 のソースコード(Public Domain)の、最小二乗法のところだけ抜き出して移植したのがこちら。 とりあえずGreasePencilで描いたもの一番最後のやつを変換するようにしてますが、今回のアルゴリズムだけでは カーブは1個しかできないので、あまり使い物にならないです。 そこで次回 1. ニュートン法による近似 を実装して、マシになる予定です… あと、特殊な場合については無視してるので場合によっては変換上手くいかないです。 GreasePencilのストロークは、最初の点とその次の点で接線を出そうとしたところ、常に(0,1,0)とかになって 最初と最後付近の頂点が変な感じになってることが判明したので、適当に2,3個の点から作ってる程度にやっつけです。 import bpy from mathutils import Vector def make_curve(bezier_list): curvedata = bpy.data.curves.new("curve", type='CURVE') curvedata.dimensions = '3D' objectdata = bpy.data.objects.new("bezier", curvedata) bpy.context.scene.objects.link(objectdata) polyline = curvedata.splines.new('BEZIER') polyline.bezier_points.add(len(bezier_list)-1) for i, (anchor, h1, h2) in enumerate(bezier_list): #print("bezier",,anchor, h1, h2) point = polyline.bezier_points[i] point.co = anchor point.handle_left = h1 point.handle_right = h2 def get_points(): points = [] pencil = bpy.data.grease_pencil[-1] for i, stroke in enumerate(pencil.layers[-1].active_frame.strokes): for p in stroke.points: #print(p.co.x, p.co.y, 0) points.append(Vector((p.co.x, p.co.y, p.co.z))) return points def B0(t): return (1.0-t) * (1.0-t) * (1.0-t) def B1(t): return 3 * t * (1.0-t) * (1.0-t) def B2(t): return 3 * t * t * (1.0-t) def B3(t): return t * t * t def generate_bezier(points, U, tanL, tanR): # calculate A A = [] for u in U: print(u) A.append([tanL * B1(u), tanR * B2(u)]) # calculate C, X C0 = 0.0 C1 = 0.0 C2 = 0.0 C3 = 0.0 X0 = 0.0 X1 = 0.0 for i, u in enumerate(U): C0 = C0 + A[i][0].dot(A[i][0]) C1 = C1 + A[i][0].dot(A[i][1]) C2 = C1 C3 = C3 + A[i][1].dot(A[i][1]) PB0 = points[0] * B0(u) PB1 = points[0] * B1(u) PB2 = points[len(points)-1] * B2(u) PB3 = points[len(points)-1] * B3(u) print(PB0, PB1, PB2, PB3) P = points[i] - (PB0 + PB1 + PB2 + PB3) X0 = X0 + A[i][0].dot(P) X1 = X1 + A[i][1].dot(P) det_C0_C1 = C0 * C3 - C2 * C1 det_C0_X = C0 * X1 - C2 * X0 det_X_C1 = X0 * C3 - X1 * C1 alpha_l = det_X_C1 / det_C0_C1 alpha_r = det_C0_X / det_C0_C1; if det_C0_C1 == 0: alpha_l = 0 alpha_r = 0 p0 = points[0] p3 = points[len(points)-1] return [(p0, p0, p0 + tanL * alpha_l), (p3, p3 + tanR * alpha_r, p3)] def create_relative_length_list(points): u = [0] for i, p in enumerate(points[1:]): #print(i, u[i], p, points[i]) u.append( u[i] + (p - points[i]).length ) for i, v in enumerate(u): u[i] = v / u[len(u)-1] return u def fit_curve(points, is_gpen): if len(points) < 5: return points[0] = points[1] U = create_relative_length_list(points) tanL = (points[1] - points[0]).normalized() tanR = (points[len(points)-2] - points[len(points)-1]).normalized() if is_gpen: tanL = (points[2] - points[1]).normalized() tanR = (points[len(points)-4] - points[len(points)-3]).normalized() print("tanL", tanL) print("tanR", tanR) bezier_list = generate_bezier(points, U, tanL, tanR) make_curve(bezier_list) fit_curve(get_points(), True) ------------------------------ 結果 ------------------------------ 参考文献: (1) 金谷 健一 (2005)「これなら分かる最適化数学―基礎原理から計算手法まで」(共立出版) (2) Andrew S. Glassner (1990) 「Graphics Gems (Graphics Gems - IBM)」(Morgan Kaufmann) (3) Philip J. Schneider 「fit_curve.c」 from "Graphics Gems", Academic Press, 1990 ------------------------------ Blender Advent Calender 2014 25日は blug.jp さんで、「Blenderドリル・クリスマスVer.(解答付き)」です☆

blender etc 忘年会 2014

2014-12-03 00:07:00
Blender Advent Calender 2014 12月3日の記事です こんにちわ、uimacこと八田です。 突然ですが、今まで年に1、2回ほど、突発的にオフ会を開いてきました。 ----------------- 渋谷で夜、焼き肉を食べていたところ、折角休み(GW)だから明日大阪でオフ会開こう! という話をしていて、それから帰宅して寝て起きて、参加者を募りつつ大阪に行ってプチオフ会を開きました。 さらに、年末あたりに実家に帰るときに途中下車して、 Blenderのショートカットキーを呟く某Botの握手会を開こう! と思い立ち、ぶれんだちゃん握手会 を開きました。 そして、今年、ハンバーガーが大好きなので、Blender使いにバーガーを食べてもらうオフ会を開こう! と思い立ち、Blender バーガーオフ を開きました。 --------------------------------- そして、今年年末、2014年12月27日に blender etc 忘年会を大阪で開きます。 blender etcとは何か。 そう、このブログのタイトルです。 つまりこの忘年会はblenderの忘年会と見せかけた、うちのブログの忘年会なのです…! といってもそんなことは関係ありません。 実態は単なる飲み会です。 それだけです。今回は、残念ながら、何のひねりありません…! 費用は5000円を予定しています。 イベント募集ページの都合上最初に入力してないと後から無料/有料を変更できないため、上の方に無料って出てますが、飲み代はかかります。 そろそろ締め切りますので、 Blenderを肴に飲みたいという方は、即、即登録してください。 年末は結構混んでいるようで、そろそろ予約入れないとヤバそうです。 また、既に参加登録してる方で、やっぱやめた!という方は、即、キャンセルお願いします。 もうすぐ、今日にでも、店に予約入れる勢いです! 登録、登録変更はこちら! http://www.zusaar.com/event/9717003 ------------------------------------------------------ さて、Blender Advent Calender 2014 12/4 は、Hideki Saitoさんです!! よろしくお願いします!

blender - 選択したものを丸くする

2014-11-14 00:08:00
import bpycontext = bpy.contextif (context.active_object != None):    object = bpy.context.active_object    bpy.ops.object.mode_set(mode='OBJECT')       bpy.ops.object.duplicate()    object = bpy.context.active_object    verts_length = []       if (object.type == "MESH"):        me = object.data        vertices = me.vertices        for i, v in enumerate(vertices):            len = v.co.length            verts_length.append(len)            v.select = True            v.co = v.co.normalized()        me.update() 単に正規化するだけのスクリプトです。 テキストエディタに張り付けてなんかメッシュ選択してrunscriptすると、真ん中の丸いやつができます。 どんなメッシュに対しても同様の半径の球状に丸まります。 逆にいうと、半径1の球に対してshrinkwrap モデファイアしたようなもんです。 これを人の作ったかわいいキャラの複数の顔に対して実行し、ぼんやりながめて、この丸いやつからこんなかわいいキャラができるなんて…などと妄想にふけって時間を消費したので載せときます。

Blender - Blenderバーガーオフ1回目

2014-10-05 01:15:00
今更ですが、先月Blenderバーガーオフというのを開催しました。 Blenderバーガーオフ1回目まとめ Blender使いが集まってバーガーを食べるだけのイベントです。 前回の「ぶれんだちゃん握手会」に続いて、またも変化球ですが、 今後もこのような変なイベントを開催していきたいと思います。 私の現時点のお勧めのバーガーランキングです。 第1位: クアアイナ チェーン店なのに安定しておいしいです。 バーガーの写真写りも抜群に良いです。 第2位: イーストヴィレッジ(池袋) 実は東京に住んでるのに余りバーガー店回ってないので もっとおいしいバーガーいっぱいあるはずですが、 食べた中ではここはちょっと高いけどおいしかったです。 ただ、店が狭いのが難点。 第3位:  SUNS こちら都内何店舗かあるカフェで、今回のバーガーオフの会場でした。 バーガーは撮影に気を取られて、ちょっと冷めてから食べてしまったのですが 肉がかなりおいしかったです。 バーガー店でオフ会を開くのは人数の関係もあり大変難しいのですが こちらだと部屋代取られるけど個室で予約可能です…!(これにより点数が上がり3位に) (バーガー専門ではないので、事前にバーガーを注文すると伝えといたほうが安全です) さて、このように無事第1回を開催できたバーガーオフですが 第2回に使えそうなバーガー店があればご連絡お待ちしております。 都内で他に行ったことあるバーガー: BLACOWS(恵比寿)、ヴィレッジヴァンガード ダイナー(荻窪、下北沢)、 J.S.BURGERCAFE(新宿)、ホーミーズ(高田馬場)、 アームズピクニック(新宿)

blender - ブログのアドレス

2014-08-22 23:10:00
ブログのアドレスが blendermoe.blogspot.com ↓ www.blender.moe になりました。 最近投稿が滞っているので月1、2回くらいは更新したいところです。。

blender - 頂点法線転写ハック

2014-07-05 00:01:00
頂点法線転写アドオン  http://blenderartists.org/forum/showthread.php?259554-Addon-EditNormals-Transfer-Vertex-Normals/  がありますが、エディットモードに入るとBlenderは頂点法線が強制的に再計算する仕様のようで 折角いじった法線がキャンセルされます。 そこで、スクリプトをちょろっと改造して、カスタムデータとして法線と頂点インデックスを保存します。(注意:この記事は人柱向けです) def joinBoundaryVertexNormals(self, context, destobjs,                               INFL=0.0, MAXDIST=0.01):     '''     Average smoothing over boundary verts, usually same-location.     destobjs = list, generally context.selected_objects     INFL = float, influence strength     MAXDIST = float, distance to influence... probably not necessary     '''     bms = {}     bmsrc = bmesh.new()     scene = context.scene       for obj in destobjs:         # These type != 'MESH' checks could be alleviated by removing         #  non-mesh objects in execute(), but, may wish to         #  support non-mesh objects one day         if obj.type != 'MESH':             continue         bms[obj.name] = bmesh.new()         bm = bms[obj.name]         bm.from_mesh(obj.to_mesh(scene, False, 'PREVIEW'))         bm.transform(obj.matrix_world)         destverts = bm.verts               for otherobj in destobjs:             if otherobj.type != 'MESH' or obj == otherobj:                 continue             gatherSourceVerts(bmsrc, otherobj, scene, 'ONLY')             sourceverts = bmsrc.verts                       indices = []            normals = []             for vert in destverts:                 near = nearestVertexNormal(sourceverts, vert, MAXDIST)                 if near:                     offset = near * INFL                     vert.normal = (vert.normal + offset) * 0.5                     vert.normal.normalize()                     indices.append(vert.index)                     normals.append(vert.normal[0])                    normals.append(vert.normal[1])                    normals.append(vert.normal[2])                       otherobj["trans_normal_index"] = indices            otherobj["trans_normal"] = normals             bmsrc.clear()       for name in bms:         # Everything's been modified by everything else's original state,         #  time to apply the modified data to the original objects         bm = bms[name]         for obj in destobjs:             if obj.name == name:                 bm.transform(obj.matrix_world.inverted())                 bm.to_mesh(obj.data)                 bm.free()     bmsrc.free() def transferVertexNormals(self, context, src, destobjs,                           INFL=0.0, MAXDIST=0.01, BOUNDS='IGNORE'):     '''     Transfer smoothing from one object to other selected objects.     src = source object to transfer from     destobjs = list of objects to influence     INFL = influence strength     MAXDIST = max distance to influence     BOUNDS = ignore/include/only use boundary edges     '''     bm = bmesh.new()     bmsrc = bmesh.new()     scene = context.scene     gatherSourceVerts(bmsrc, src, scene, BOUNDS)     sourceverts = bmsrc.verts       for obj in destobjs:         if obj.type != 'MESH' or obj == src:             continue         bm.from_mesh(obj.to_mesh(scene, False, 'PREVIEW'))         bm.transform(obj.matrix_world)         destverts = bm.verts               indices = []        normals = []                  for vert in destverts:             near = nearestVertexNormal(sourceverts, vert, MAXDIST)             if near:                 offset = near                 #if INFL < 0.0:                 #    offset = offset * -1                 #vert.normal = vert.normal.lerp(offset,abs(INFL))                 vert.normal = offset * INFL                 vert.normal.normalize()                 indices.append(vert.index)                 normals.append(vert.normal[0])                normals.append(vert.normal[1])                normals.append(vert.normal[2])              obj["trans_normal_index"] = indices        obj["trans_normal"] = normals         bm.transform(obj.matrix_world.inverted())         bm.to_mesh(obj.data)         bm.clear()       bm.free() で、以下のような感じの、エディットモードに入った瞬間に保存したデータに上書きするような スクリプトを作って、 エディットモードに入って法線が元に戻される前に、テキストエディタから手動実行させます。 1回実行すると裏で常駐します。 なお、これらのコードはどちらも書き捨てコードなので、基本的に通常使用に耐えないものと認識しておいてください…。データ重くなりますし、トポロジ変更された場合などは考慮されていません。特に設定保存などしないでください。試した後は丸ごと元に戻すくらいの勢いでお願いします。。 import bpy import bmesh import mathutils pre_mode = bpy.context.mode def draw_normal_handler(scene):     global pre_mode     if pre_mode != bpy.context.mode:         print("mode changed", bpy.context.mode)         pre_mode = bpy.context.mode               if bpy.context.mode == "EDIT_MESH":             obj = bpy.context.active_object             if "trans_normal_index" in obj and "trans_normal" in obj:                 vi_list = obj["trans_normal_index"]                 no_list = obj["trans_normal"]                                   bm = bmesh.from_edit_mesh(obj.data)                 for i, vi in enumerate(vi_list):                 bm.verts[vi].normal = mathutils.Vector((\                         no_list[i * 3 + 0],\                         no_list[i * 3 + 1],\                         no_list[i * 3 + 2])) def remove_draw_normal_handler():     for handle in bpy.app.handlers.scene_update_post:         if handle.__name__ == "draw_normal_handler":             bpy.app.handlers.scene_update_post.remove(handle)             break       #remove_draw_normal_handler() bpy.app.handlers.scene_update_post.append(draw_normal_handler) エディットモードに入っても、こんな感じで法線が確認できます。 でもこのハック…大変重いのです… もうちょっと洗練して公開予定でしたが、ちょっと重すぎなので別のアプローチに移行中です… (法線マップにベイクしたい) -------------------------------------------------------------------------------- もうちょっと詳しい手順を張っておきます(あくまで人柱向けです) 転写プラグインは、転写先、転写元の順で選択してから、実行するっぽい 一番近い頂点の法線が転写されるだけっぽいので、転写元のほうはちょっと細かくしといたほうがよいかも(これはやりすぎた) 実行すると、なんか(4)に出てくる。このとき、上記改造をしていると非常ーーーーに重いので注意。influenceをそっと"1.0"にしよう。あとdistanceは良く分からんのでだいたいBlender Unit何個分くらい離れてるか程度入れとけばよいのでは。。 それからエディットモードにする前に、上記の下のほうのスクリプトを実行する。最初から実行していても問題ないです。一度実行するとずっと裏で動いてる系のスクリプトなのです。。解除するときは、コメントアウトしている#remove_draw_normal_handler()のほうを有効にして、(最後の行はコメントアウトして)実行すると解除されます でこの場合はこんな感じに。ちょっと斜めの奴がいますが、まぁなんとなくいけてるんじゃなかろうか…(訳:これ俺のバグじゃないです)

最近のグラフィックソフトのかっこいい新機能について(2)

2013-12-14 14:12:00
パーティクル系も挙げておく。 このソフトは、パーティクルオブジェクトの原点(または特徴点)を2D平面上で操作できる。操作用ピボットからマウスアップすると、その時点から時間が進み始め、パーティクルが動き出す。正直この勝手に時間進むのが大変使い辛い。時間方向の編集ができると見た目はかっこいいが、よく設計されてないと使い辛い。 Invert Remove from sparta on Vimeo. こちらは、パーティクルをスカルプトできるソフトである。シミュレーションで生成することが多いパーティクルに対して、空間方向の編集を手描きで行える画期的なソフトウェアである。こちらはスカルプトでの空間方向への操作であり、上のと比べて断然使いやすい。 やはり時間方向の編集は、現実の時間と同期が取れないので、使い辛いのかもしれない。 では現実の時間と同期を取った機能をつけたらどうなるだろうか ここで満を持して、Blender登場である。 これがまさに現実の時間と同期を取った編集機能。 かっこいい。 こういうのってDTMでいう録音、あるいは録画機能に近い。 しかし、ペンインタフェースではないのがちょっと残念。 ユーザーの操作を録画するペンインタフェースのソフト。 といえば、2D方面では既にある。 noughts (録画型お絵かき掲示板) http://noughts.jp/ これはユーザーの操作を録画するお絵かき掲示板である。 でも出来上がるものがあくまで2D絵なので、時間方向の機能の効果が薄い。 閲覧者に1枚の2D絵が出来上がる過程を見せることになるが、 結果だけ見れれば良い人が多い気がする。 このようなものをサーベイした上で作成中のソフトウェアCabbageは、 キャベツの作画崩壊シーンを作るために、 ・時間方向への編集ができる ・空間方向への編集ができる ・3Dソフトである ・出来上がるものが画像1枚ではなく動画かシーケンシャルジオメトリである といったことを全体にしてかっこいいソフトにしたい。

最近のグラフィックソフトのかっこいい新機能について

2013-12-11 03:44:00
PoMo: Ink Flow on a Surface PoMo: Ink Flow on a Surface from Nelson Chu on Vimeo. Substance Painter Video Teaser "普遍"とは時間・空間を越えるものを表す。 最近のペイントソフトウェア、または、ペンインタフェースを想定したグラフィックソフトウェアのかっこいい機能は、総じて、時間または空間に対する編集を、ソフトウェアで補っているように思う。 上のPoMoでは、ユーザーのペン入力時間を越えて、水彩が徐々ににじむという物理的な挙動をしているし、 下のSubstancePainterでは、ユーザーのペン入力に対して、空間を越えてパーティクルを3Dオブジェクトに散布している。 現在趣味で作っているCabbageというソフトウェアでも、このような時間・空間を越えるような 編集方法を提供して、かっこいいソフトウェアであると認定されたい。 今のところ思いついてる限りでは、時間方向の編集を強化したようなものを考えている。 時間については、PoMoのように入力前後のシミュレーションという手もあるが、 ユーザーがペンで入力している間の実時間を使用すると面白いのではないかと思っている。 空間方向の編集については、3DCGソフトウェアでは、スカルプトツールを筆頭に進化してきているが、 時間方向の編集については、これまであまり行われてこなかったように思う。 逆にDAWなどの音楽制作用ソフトウェアでは、MIDIキーボードなどの専用ハードウェアもあるためか、 かなり進化している気がする。 このあたりから何か次世代のツールが発掘できないか悶々とする日々である。

blender - Another Autodesk FBX Importer(4)

2013-01-01 01:50:00
Mac版ができない・・・。 画像の上のほうがMac版のBlender2.65本体のライブラリ依存関係で、 真ん中はMac版のインポータがBlenderを介さないPythonインタラクティブシェルからの実行で成功している様子。 一番下が、Mac版インポータのライブラリ依存関係(大体static linkしているのでほとんどない)。 これで、Blenderからimport BLするといきなり落ちる。 落ちている場所はboost::python::init_module、たぶんエントリポイント。 ビルドはユニバーサルバイナリで作ってるし、後試すとしたらPythonのlibのstatic版を作ってくっつけるくらいか・・・と思い、Pythonのstatic版も作ったけど駄目だった。 落ちたときのレポートをよく見たら、libsystem_c.dylib関連で落ちている。じゃあlibsystem_cもstatic版作るか・・・ってそんなことできるのか!?

blender - QUMARION用可動モデルの作り方

2012-12-28 01:40:00
QUMARION用可動モデルの作り方(モデラー向け) ついにBlender向け自作FBXインポータ/エクスポータが半分完成したので、記念に。 注意:こちらは簡単なほうじゃなくて難しいほうの作り方です。モデリングできる人向け。 まずミクさんを用意します。 用意しました。こちらは、ボーンとか入ってないけど、MMD用のボーンを入れるために腕がハの字になっているミクさん。まだ修理中だったため、色々とおかしいです。靴下とか。 次に、別のレイヤーに某所で配布されているモデルを、 Another Blender FBX Importer/Exporter で読み込みます。使用許諾的にはは出来たものをうpればOKのようです。 読み込みました。 この女子学生から、骨だけ頂きます。 ミクさん小さいです。いや、骨がでかいです。仕方ないので、ミクさんを(47メートルくらい)巨大化させます。 巨大化させました。しかし腕がT字では無くハの字になっているため、何とかしかければいけません。 ここで、骨のほうをハの字にしてはいけません。 骨を回転させてしまうと、これまでの苦労が水の泡です。あくまで骨は女子学生のものを使います。 面倒ですが、メッシュのほうをT時にします。 薄々気付いていましたが、うちのミクは手が短すぎるようです。女学生は逆にちょっと長い気がするので、間くらいまで腕を伸ばします。 同時に、ポーズモードでボーンを選択してSキーで拡大縮小させることで、全く回転させずにボーンの長さだけ調節します。 はい、重要です。これが今回最も重要です。QUMARIONが何もせずに反応するボーンは可動モデルなんとかガイドに書いてあるボーン名と、ボーンの軸の角度がピッタリあってることが必要なようです。 (角度は書いてないし、書いてあったとしてもBlenderでは調節できないのでどうしようもない。) このように長さだけ調節することで、軸の角度を全く変えずにボーンを編集することができるのです。 長さをとことん変えた後は、Ctrl+Aで、Apply Pose as Rest Poseを行って、エディットモードのボーンも同じ状態にしてください。 で、まぁあとは作るだけです。 作って作って作りまくって、最後にFBXで出力します。 出力するときは必ず、 Another Blender FBX Importer/Exporter で、次のオプションを有効にして出力してください。 export imported node propertiesは、Blender上のボーンの位置/角度情報などを一切無視して、読み込んだままの位置/角度情報を出力します。 fit node lengthは、Blender上のボーンの位置/角度情報などを無視する場合でも、ボーンの長さのみ、反映させるというオプションです。 これら2つを有効にすることで、読み込んだ女学生と同様にQUMARIONで設定なしに動かせるFBXが出来上がります。 と書いたものの、作りながらやってるのでまだ出来てません。出来次第、完成画像載せます。 あと、エクスポータのほうで重要な行を1行コメントアウトしてしまっていのたで、明日修正します…

blender - Another Autodesk FBX Importer(3)

2012-12-04 01:51:00
今までBlenderには技術的かつ宗教的な理由で、 FBXのまともなプラグインは存在しなかったので、 既に我ながらかなり満足しているが、 ついでに行くとこまで行くよ! インポート時のボーンの軸を維持したまま、 ポーズモードでスケールをかけて、軸に沿ってボーンの長さを変え、 それを出力することに成功した。 画像左のように、軸がてきとーなBlenderのリグでも、インポートしたときの軸情報を覚えていて、 かつ長さを変更した場合は、エクスポート時に軸に沿った方向に長さを変更するので、 右のように、QUMARION対応状態でボーン長さ調整ができる。 この機能は、QUMARIONだけでなく、ゲーム用とかDCCツール用のモデルを扱ってる人には、かなり有効なのではないだろうか。 こんなことしなくても、ボーンなしのメッシュに、モーションシェルとかいうのを入れるとさくっとQUMARIONで動くんだけど、 Unityとか他のソフトでも使えるというのは大きい。 Unityとか他のソフトでも使えるというのは大きい。 あとGUIとメニュー付けたらいつでもリリースできる感じだけど、 Blender 2.65がリリース間近とのことなので、それ出るまで待つかも。

blender - Another Autodesk FBX Importer(2)

2012-11-30 03:17:00
Blenderはボーンの軸の+Yがtail方向で、変更できないので、インポートしてエクスポートすると多くの場合再現不能と思う。 しかもZupだ。仮に変換できるとしても一筋縄でいかない。 公式のエクスポータみたいにローカル軸を気にせず適当に90度回転させれば、位置だけは合うんだけど、軸がどうやっても合わない。 rollとかで多少いじれるけど、rollは軸周りの回転しかできない。軸が逆向きだったりするとどうしようもない。 そこで、読み込み時のローカルのTrans/Rot/ScaleをCustomPropertiesに保存しておくようにした。 これをエクスポートのときにオプションによってはそのまま出力する。 これを行うことで、Blender上での軸や、編集結果を無視して、確実に軸を変更せずに出力できるので、Unityとかのゲーム向けモデルとか、QUMARION向けモデルとかで便利なはずである。 この問題が一番の難関だったけど、上記方法で上手くいったため、多分速ければ今週末くらいにインポータ・エクスポータともに割とまともなものを公開できると思います。

blender - Another Autodesk FBX Importer(1)

2012-11-29 01:38:00
FBX Importer作り始めました。 とりあえずなんか読み込める程度のテスト版が出来たので テスト公開してしまいます。 バイナリのFBXファイル一応読めます。 バイナリのFBXファイル一応読めます。 現在の対応状況:頂点、法線、UV、マテリアル、テクスチャ、ウェイト、ボーン 今後の予定:ボーンの軸の改良、頂点カラー、シェイプ、カメラ、多角形ポリゴン DownloadHere! あ、スーパー人柱バージョンだからね!勘違いしないでよねっ! http://blenderfbx.render.jp/ エクスポータもあわせて年内に出すよ!

etc - QUMARION to Blender(1)

2012-11-29 00:40:00
QUMARIONのSDKが学術目的または評価目的で使用するユーザ向けに、 無償で公開されました! ただしC++用です! https://www.clip-studio.com/quma/ 早速Pythonで使えるか、Blenderで使えるかを評価するためハックを始めましょう! この技術情報は、SDKを入手する前に知り得た情報であるので、公開しても問題ないであろうと思いますが、問題あった場合は直ちに公開停止されることでしょう。 Blenderから使うには、Pythonからアクセスできねばなりません。 Pythonから使うには、Pythonのctypeを使ってネイティブのDLLにアクセスするとか、 Boost.Pythonを使ってラップしたDLLを作る(最近覚え中)などがあります。 では、早速dependencywalkerでDLLを開きます。 開きました。これはなにやらシンプルな記述の関数がならんでいますね。 これはctypeでさくっといけそうな感じです。 しかしこれはちょっとシンプルすぎて使えません。右クリックして「Undecorate C++ Functions」のチェックを外しましょう 外しました。 これです!これが必要らしいのです。ctypeとかいうやつには。 早速QmPdkDll.dllがある場所でコンソールでPythonを開き、以下のように打ち込みます。 なんとかInitとかいう初期化っぽいのを呼んでみました。 「0」が返ってきました。ちょっと成功したのか分からんですね。 まぁそういうときはヘッダがあるのでヘッダファイルを見ます。 すると、どうやら成功しているようです。 といった感じでゴリゴリ書いていきます。 折角なのでクラス化しておきましょう。 class QmPdk: def __init__(self): """ The constructor. """ qmpdk = CDLL("QmPdkDll.dll") self.QmPdkCalibratePose = \ getattr(qmpdk, "?QmPdkCalibratePose@@YAHH@Z") self.QmPdkCharacterCreate = \ getattr(qmpdk, "?QmPdkCharacterCreate@@YAHPAHH0PAPBD@Z") self.QmPdkCharacterDestroy = \ getattr(qmpdk, "?QmPdkCharacterDestroy@@YAHH@Z") self.QmPdkCharacterGetHandle = \ getattr(qmpdk, "?QmPdkCharacterGetHandle@@YAHHPAH@Z") self.QmPdkCharacterGetLocalMatrix = \ getattr(qmpdk, "?QmPdkCharacterGetLocalMatrix@@YAHHHQAY03M@Z") self.QmPdkCharacterGetName = \ getattr(qmpdk, "?QmPdkCharacterGetName@@YAHHHPADH0H@Z") self.QmPdkCharacterGetNumOfHandle = \ getattr(qmpdk, "?QmPdkCharacterGetNumOfHandle@@YAHPAH@Z") self.QmPdkCharacterGetQumaHandle = \ getattr(qmpdk, "?QmPdkCharacterGetQumaHandle@@YAHHPAH@Z") self.QmPdkCharacterGetRotate = \ getattr(qmpdk, "?QmPdkCharacterGetRotate@@YAHHHQAY03M@Z") self.QmPdkCharacterMemorizeInitialPose = \ getattr(qmpdk, "?QmPdkCharacterMemorizeInitialPose@@YAHH@Z") self.QmPdkCharacterRecallInitialPose = \ getattr(qmpdk, "?QmPdkCharacterRecallInitialPose@@YAHH@Z") self.QmPdkCharacterSetLocalMatrix = \ getattr(qmpdk, "?QmPdkCharacterSetLocalMatrix@@YAHHHQAY03M@Z") self.QmPdkCharacterSetRotate = \ getattr(qmpdk, "?QmPdkCharacterSetRotate@@YAHHHQAY03M@Z") self.QmPdkCopyPose = \ getattr(qmpdk, "?QmPdkCopyPose@@YAHH@Z") self.QmPdkEnable = \ getattr(qmpdk, "?QmPdkEnable@@YAHHH@Z") self.QmPdkEnableAccelerometer = \ getattr(qmpdk, "?QmPdkEnableAccelerometer@@YAHHH@Z") self.QmPdkFinal = \ getattr(qmpdk, "?QmPdkFinal@@YAHXZ") self.QmPdkGetVersionStr = \ getattr(qmpdk, "?QmPdkGetVersionStr@@YAHPADPAH@Z") self.QmPdkInit = \ getattr(qmpdk, "?QmPdkInit@@YAHXZ") self.QmPdkIsEnable = \ getattr(qmpdk, "?QmPdkIsEnable@@YAHHPAH@Z") self.QmPdkLoadCalibrationDataFile = \ getattr(qmpdk, "?QmPdkLoadCalibrationDataFile@@YAHHPBD@Z") self.QmPdkNnbCreateGroup = \ getattr(qmpdk, "?QmPdkNnbCreateGroup@@YAHHHPAH@Z") self.QmPdkNnbIsValid = \ getattr(qmpdk, "?QmPdkNnbIsValid@@YAHHPAH@Z") self.QmPdkNnbLoadFromFile = \ getattr(qmpdk, "?QmPdkNnbLoadFromFile@@YAHHPBD0@Z") self.QmPdkNnbLoadFromMem = \ getattr(qmpdk, "?QmPdkNnbLoadFromMem@@YAHHPBDH@Z") self.QmPdkNnbOpenMappingWindow =\ getattr(qmpdk, "?QmPdkNnbOpenMappingWindow@@YAHHI@Z") self.QmPdkNnbSaveToFile = \ getattr(qmpdk, "?QmPdkNnbSaveToFile@@YAHHHPBD@Z") self.QmPdkNnbSaveToMem = \ getattr(qmpdk, "?QmPdkNnbSaveToMem@@YAHHHPADPAH@Z") self.QmPdkNnbSetGroup = \ getattr(qmpdk, "?QmPdkNnbSetGroup@@YAHHHHPAHH0@Z") self.QmPdkQumaAttachInitPoseModel = \ getattr(qmpdk, "?QmPdkQumaAttachInitPoseModel@@YAHHH@Z") self.QmPdkQumaDetachModel = \ getattr(qmpdk, "?QmPdkQumaDetachModel@@YAHH@Z") self.QmPdkQumaGetButtonState = \ getattr(qmpdk, "?QmPdkQumaGetButtonState@@YAHHHPAH@Z") self.QmPdkQumaGetHandle = \ getattr(qmpdk, "?QmPdkQumaGetHandle@@YAHHPAH@Z") self.QmPdkQumaGetNumOfHandle = \ getattr(qmpdk, "?QmPdkQumaGetNumOfHandle@@YAHPAH@Z") self.QmPdkQumaIsPoseChanged =\ getattr(qmpdk, "?QmPdkQumaIsPoseChanged@@YAHHPAH@Z") self.QmPdkSaveCalibrationDataFile = \ getattr(qmpdk, "?QmPdkSaveCalibrationDataFile@@YAHHPBD@Z") ひたすらコピーペーストしていくだけの簡単かつ面倒な作業です。 まぁこれ↑実はSDK公開前にせこせこmaya用についてたDLLをハックしてたやつなので、今の関数と違うかもしれませんが、それは(2)とか(3)とかで直していきます。ではまた後日!

etc - L-System適当メモ

2012-07-31 05:25:00
教科書: The Algorithmic Beauty of Plants http://algorithmicbotany.org/papers/#abop 上記書籍の簡易解説pdf. http://natcomp.liacs.nl/CSA/slides/CSA7.pdf 以下は読みながら適当にメモったものであり、 内容の正当性については保証できないので、本気出す人は上記書籍を参照してください。 --------------------------------------------------------- DOL-System(deterministic and context-free,L-System) →コンテキストは自由に与えることが出来、コンテキストごとの結果は一意に定まる(ランダムに結果が変動したりしない)ようなL-System --------------------------------------------------------- 方法1:上から書いていく方法 ω(axiom)=初期状態(n=0) n=何回実行したか。ωにp1~pNを全てm回適用したらmである。 p1=rule1 p2=rule2 p3=rule3 ・ ・ ・ pN=ruleN 方法2:turtleインタプリタ。亀が2次元で動く 方法1の定義に加え、亀用に以下の定義を導入 δ(angle)=回る角度 F=前に距離dだけ一歩進む、移動中描画する f=前に距離dだけ一歩進む、移動中描画しない +=左にδ回転 -=右にδ回転 --------------------------------------------------------- DOL-Systemの合成 高い木を作るには、ランダムな変更が必要であるが、 プログラムでは配列や構造体操作でL-Systemが表現される というインタフェース上の問題がある。 1990年以前高い木をモデリングするには非常に制限された方法であるが、 turtleインタプリタに2つの操作モードを導入する方法が考案された。 edge rewritingとnode rewritingである。(グラフ理論に由来する用語らしい) Edge RewritingとNode Rewritingについては、 http://www.selcukergen.net/ncca_lsystems_research/lsystems.html の図が分かりやすい (読み終わるまで続く)