2008年3月26日水曜日

etc - 東京来てます

今週月曜から東京来てます。1日目、初のネカフェ難民を体験しました。
現在秋葉の満喫より。次回はBlenderとDirectXのがアニメーションまでできたら更新ってことで。

GAMERS本店。


秋葉原駅前のバーガー屋の。


友人が作ってたペーパークラフト。

2008年3月18日火曜日

blender - ファイルフォーマットを書き換えたい(14)

テクスチャでました!



頂点

法線
頂点カラー
マテリアルカラー
テクスチャ
------いまここ------
シェーダーと固定機能パイプライン
ボーンとアニメーション
完成&公開(Blenderのソースと実行ファイル、コンバーターの実行ファイル、DirectX読込みソース)

2008年3月13日木曜日

blender - ファイルフォーマットを書き換えたい(13)

マテリアル色出ました!


<検索用>
DirectX | Direct3D でマテリアル が 白くなる | 白くなって 色が出ない場合、
法線が正規化されてないことが考えられます。↓で直ります。
pDevice->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE);


なんか俺みたいな初心者特有の凡ミスな気がしますねorz

次はテクスチャ

-----------

ちょっと東京行ってくる!!!

-----------

東京来た。



------

シマパンにした記念に、ミクもリアルタイム@BlenderGEで動かしてみた。モーション同じだけど。
エンコがめんどいからムービーメーカーでwmv。なんかwmv発色悪いんだよなぁ・・・。本当はもうちょい鮮明で綺麗です。

http://render.jp/blender/uma.wmv
(6MB)

3体バージョン
http://render.jp/blender/uma3.wmv
(5MB)

2008年3月12日水曜日

blender - ファイルフォーマットを書き換えたい(12)

先人によると、頂点カラーは次のようになっているらしい。

T(ry退避予定地
http://d.hatena.ne.jp/kakk0u/

頂点カラーのAPI仕様みてるとどうもこいつもUVのように面単位で持ってるよう。
また頂点カラーだけのために頂点追加かと思ったが、面単位で頂点カラーを必要と
するケースも想像できないので同一頂点インデックス内で平均化してやることにした。


つまりこんな感じ↓


ちなみにBlender内部ではMColという構造体に色が入っているんだけど
typedef struct MCol {
char a, r, g, b;
} MCol;
とかなってるのに、実際は MCol.b = 赤、MCol.g = 緑、 MCol.r = 青、 MCol.a = アルファ
だった。

それと、MCol は実際の頂点数に関係なくtotface(全面数)x4個生成されている。

以上を踏まえた上で、エクスポートして、平均化してみたんだけど、なんかキレイにならなかった。

解決手段としては
1.面インデックスから頂点を共有する(頂点カラーはテクスチャにベイクとかで我慢)
2.面インデックスから頂点を共有しない


が考えられる。

面:1,2,3; 1,2,4; 5,6,7; の場合、
1だと、1,2の頂点が共有されるので 頂点は7個。
2だと、頂点は9個。

テクスチャ座標も面単位になってるし、面倒なので、2の頂点を共有しないほうで行こうと思う。データ量が増える(頂点数=面数x3になる)だけで、面数(=ポリゴン数)は同じなので、描画速度は変わらないと思うし。→やはり1で行くことに

----追記

というわけで、とりあえず共有はあきらめて、面数x3の頂点をぶち込んで、出来た。

Blenderでの表示


DirectXでの表示



1日悩んでいたのに、方針を変えたら20分で出来てしまった。(ファイルサイズは3.5倍になったが…)
しかも相当な勘違いをしていたことにも気づいた。頂点共有で、色の平均取る方法でもいけるかも。

----さらに追記

頂点共有でいけた!!!
色は平均とらなくても、ちゃんと全部同じになってるっぽい。

2008年3月10日月曜日

blender - ファイルフォーマットを書き換えたい(11)

自分は「プログラマかデザイナーか」と言われればプログラマだけど、絵を見なければ落ち着かない。
絵を見ると色々分かるし、結構ブログに貼り付けた後で見直して、良くバグを発見する。(昨日の画像、colorのbが明らかにおかしい、とか。)

そこで、何が何でも表示してやる!話はそれからだっ!
とDirectXがんばってみた。



おぉ!何か出た!www(ミクはデバッグ用の外部アプリです)

なんか明らかに面の張り方がおかしいけど、一応頂点はイケてるみたいだ。
やはりコンバーターに全てがかかってますね。がんばります。

----追記----



なんとかここまで。面数も頂点数も合ってるはずなんだが顔とかが無い・・・うーん

---さらに追記



ためしに読み込んだバッファの中身を一括で全部描画してみたら、普通にいけた。
つまり、(コンバーターの)Subset出力がおかしいらしい。

-----さらにさらに追記



Subsetがようやくまともになりました。
あと、法線の読込みがたぶん成功(画像)
頂点カラーは何か変になった(現在原因不明

それと、マテリアルの色が出ない。@DirectX

3つ同時にいじってると、どれが原因なのか特定するのが大変だったり。
今のところ、xml出力するBlenderは、まずまず鉄板。
コンバーター、ようやく安定してきた・・・か?
DirectXまだまだ全然わかってなくてダメダメ

2008年3月9日日曜日

blender - ファイルフォーマットを書き換えたい(10)

ここからは、BlenderというかDirectXの話になってくるので、向こうのブログに書こうかと思ったけど、
続きが分散するのは良くないってことでこっちに。

まず、手持ちの本(3D格闘ゲームプログラミング)によると、マテリアルの切り替えコストが結構かかるので、マテリアル毎にまとめて描画するのが通常らしい。

さらにDirectXの描画関数 DrawIndexedPrimitive は、パラメータで頂点バッファと(面の)インデックスバッファを指定できるようだ。指定できるんだから細かく指定したほうが早いはず。

つまり、
・マテリアル順に面のインデックスをソート
・その面の順に頂点座標と頂点カラーと法線をソート
・それぞれの要素に、要素数を含める。
・マテリアル毎にsubsetとして「面の開始index」「面数」「頂点の開始index」「頂点数」を含める。
・あとは必要なもの(色とかテクスチャ)をsubsetに突っ込む。


以上を考慮すると、こんな感じの構造になる。

<object name="">
  <vertex size=""> ... vertex list ... </vertex>
  <face size=""> ... face list ... </face>
  <normal size=""> ... normal list ... </normal>
  <col size=""> ... vertex color list ... </col>
  <subset firstvertex="" vertexcount="" firstface="" facecount="">
    <color r="" g="" b="" />
    <texture name="filename" />
  </subset>
</object>

まだアニメーションまで頭が回ってないが、この構造で出力できれば、とりあえず比較的楽に読み込め、高速(?)に描画できるはずだ。

で、早速Javaでジャバジャバ打ち込み、1000行弱ほど書いた。SAXで読み込んだので細かいところでバグが出まくって非常に疲れた。コピペ万歳な、かなり泥臭いプログラムを書いた気がする。

↓頂点とか


↓サブセット



余り試してないのでエラーで落ちる可能性大ですが、
↓作ったコンバーター(10KB。動作環境Java5以上)
http://render.jp/blender/xmlconverter01.jar

起動するとファイル選択の窓が出てきて、昨日うpしたBlenderで吐いたxmlを開く。
成功したら同じディレクトリにファイル名_.xmlが出来る。

2008年3月8日土曜日

blender - ファイルフォーマットを書き換えたい(9)

現状をうpしてみた↓(Blender2.45ベースの実行ファイル。8MBくらい)
普通に開いて保存したら、保存先ディレクトリに、ファイル名.xmlが出来ます。

http://render.jp/blender/blender245xml_01.zip


ソースファイル
http://render.jp/blender/writeXML.cpp



大体要りそうな部分は出力できた…かな?
後は何か必要になったら追加していく感じで。
それにしてもインデックス管理されてる部分が非常に厄介でした。
(マテリアルとか。なんでvertexにマテリアルのindexがあるんだ…?)

releaseビルドしたら、保存がかなり早くなりました。さすがVS2005。


全体の構成。ほぼBlenderの内部構造がベースになってます。
違う点としては、materialにmat_nr(マテリアルのインデックス)属性を追加しといたくらいか。


actionの出力。とりあえずIpoのベジエの点を吐いたけど、Poseも要るかな…?


armatureの出力。

2008年3月6日木曜日

blender - ファイルフォーマットを書き換えたい(8)

うまく重複を省いて出力するか、丸ごとドカっと出力するか、結構迷ったけど、
後々やってみようと思う人(いるのか!?)のためにも、なるべくそのままで出力することに。

で、

MCol
MVert
MEdge
MFace
MTface
bArmature


と実装中。MTfaceは、中にImageを持ってるので、Image丸ごと入れる代わりに、Imageのnameを入れた。
bArmatureは、色々あって、何が要るのか分からんので、とりあえず現在bone_matのみ出力。

右にうpしてるmiku.blendをぶっこんで、出来たのがこれだ!
(600KBくらいあるので注意。IE7での表示をお勧め)
http://render.jp/blender/test.xml

コードは現在こんな感じ。
http://render.jp/blender/writeXML.cpp

出力はDOMだけにメモリも時間も食いますねー。

あと、マテリアルと、アニメーションと、頂点グループを吐いて
慣れてるJavaでDirectXで使いやすいように整形するか。
といってもDirectX使うの初めてで、どういうのが使いやすいのか分からないorz

blender - ファイルフォーマットを書き換えたい(7)

しばらく眺めてみて、物量的に全部やると数ヶ月かかりそうなので、急遽要るやつだけ吐くことに。
普段の作業を思い出すんだ<俺。
いつも他の.blendファイルからキャラ持ってくるときは、objectと、armをappendして、
armをobjectのparentにする。

しかも、そのobjectはmeshタイプで、object自体にはmeshがリンクされてるだけで、
meshにマテリアルとかがリンクされてる。(outlinerの表示によると)

つまりmeshタイプのobjectとarmatureのtreeだけ出力すれば、大体何とかなりそう。
っていってもobjectには膨大なデータが入ってるんだが…。

今日は何とかMVertとMColの出力まで出来た。
途中 blo_split_main が未定義だというリンクエラーが出たので、
readfile.h(←プロジェクトに入ってなかったので探して追加した)にextern~を追加したらうまくいった。

コードは、こんな感じ。ヘッダは関数の定義1個書いてるだけだから省略。
http://render.jp/blender/writeXML.cpp

で、出力はこんな感じ。見やすいように後から手作業で改行入れた。
ノードの命名規則は、blenderの構造体||変数名を小文字にしただけ。

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<blenderxml endian="v" version="245">
<object name="OBCube">
<mesh>
<mvert flat="3" mat_nr="255">
<co>
1,1,-1;1,-1,-1;-1,-1,-1;-1,1,-1;1,0.999999,1;
0.999999,-1,1;-1,-1,1;-1,1,1;
</co>
<no>
18918,18918,-18918;18918,-18918,-18918;-18918,-18918,-18918;
-18918,18918,-18918;18918,18918,18918;18918,-18918,18918;
-18918,-18918,18918;-18918,18918,18918;
</no>
</mvert>
<mcol>
17,17,17,0;17,17,17,0;60,60,60,0;0,0,0,0;62,62,62,0;0,0,220,255;
29,29,29,0;251,251,251,255;
</mcol>
</mesh>
</object>
</blenderxml>

2008年3月5日水曜日

blender - ファイルフォーマットを書き換えたい(6)

滋賀に帰ってきました。ゴホゴホと咳が止まりません。

さて、早速やるかー。と思ってVS2005を開いて適当にそれっぽいところを探すと

あった。この量wwww

次、ファイル書き出してるところ特定。これはVS2005のおかげで一瞬だった。

そこから、Blenderの.blendファイルを保存した後に.xmlも保存することにしよう。こうすると、失敗しても.blendは、しっかり保存される…はず。

さあ後は書き出すだけだ!と思って、Javaで使ってたxercescのC++版を突っ込んでみたけど、初期化部分とか全然名前違って戸惑う。しかもmsxmlのDOMDocumentと名前が被ってやがる。で、何とか


<?xml version="1.0" encoding="UTF-8" standalone="no" ?>


という55バイト保存成功。第一歩を踏み出したのであった。ゴホゴホ。


-------

ああそうだ、3日で俺22歳になりました。
で、最初にレンダリングしたのが、これだっww

2008年3月3日月曜日

etc - Louis Vuittonのプロモが凄い

Louis Vuitton "Superflat Monogram" Japanese Cartoon


姉に教えてもらったんですが、これは凄い!!!

ニコニコの高画質版
http://www.nicovideo.jp/watch/sm547657

やっぱプロは凄いなー。

2008年3月2日日曜日

blender - おもちゃの街みたいなのが作りたい

超手抜き作業の例。

Add Cubeした後、Bebelでブロックぽくして、頂点色テキトーに塗ったあと、テキトーに並べます。



真ん中に持ってきて上から見ます。


これを押すと…


くるっと回ってこんなのが出来ます。


次、同じく適当に並べて、今度はちょっと凹ませたりしてみます。


すると、こんなんになります。うーん楽ちん。


上から見たときここを消しておくと効果的。


出来たやつをコピったり拡大したりして並べます。
最初のやつが「俺に旗を載せてくれ!」って感じの風貌だったので旗ぽいのつけました。


なんか、おもちゃの街っていうか、氷の町だな…。

blender - ファイルフォーマットを書き換えたい(5)

昨日実家に帰ってきたのでプログラミングも3Dもできなくて、
検索しまくって情報集めてました。

xml形式に書き換えたいということでしたが、やはり皆同じことを考えるようで
COLLADAというフォーマットが、まさにそのようなソフト間の違いを吸収して互換性を保つように設計されたxmlなフォーマットのようです。

しかし、先人によると、BlenderのCOLLADAエクスポーターは、やはりconstrain周りでうまくいかない模様。
くまりゅう日記
http://www.kumaryu.net/cgi-bin/diary/


やっぱ将来Blenderと付き合っていくことを考えると、小手先でpython exporterを書いてメンテするより
もっと根本的な.blendファイルの内部を把握していたほうが、大変だけど、安全かつ効果的だと思います。
というわけで、続投します!

---------

で、今日は自動車免許の更新に行ってきました。なんと俺免許持ってたんですね。とってから1回も乗ってないですけど。

3D作ってる人は、車かロボットが好きであることが多い
と思います。

例によって萌え3Dばっかりセコセコ作ってる俺ですが、実は車もロボットも好きです。
グランツーリスモ1、2、3全レース制覇+ほとんどの車種をコンプしてました。(好きな車種は少し昔のインプレッサ。でも環境指向なので、もし乗るならツインみたいなのでいいや。)
アーマードコアも大好きで、全ボタン使わないロボゲーなんてヌルイぜ!とか思ってしまいます。
まぁ結構前に卒業して、現在何もゲーム機持ってないんですが、アーマードコアのOPをよだれを垂らしながら見ています。いいなぁー。やりたいなぁ~。

2008年3月1日土曜日

blender - ファイルフォーマットを書き換えたい(4)

さすがに力尽きたorz
高校時代英語ずっと赤点で、大学も再々々履修くらいまでいったくらい苦手。

最後のSDNAの章は、適当に読んだけどさっぱり分からんかった。
移植性・可搬性(ポータビリティ)のためにSDNA機構というのがあるようだ。

結局ソース読まないと全然分からん。という結論になりました。

File saving and loading

File saving is in general just going over the the entire Main tree, and save all blocks with users to disk as a raw binary dump. Each block saved gets a header (struct BHead) where additional information is stored, such as the original address of this block in memory.

ファイル保存は、一般に、Main treeから入り、全てのユーザのブロックをバイナリ形式でディスクへ保存する。各ブロックは、メモリ内でのこのブロックの独自アドレスのような、追加情報が保存されているヘッダ(BHead構造体)を得て保存される。

File reading starts with reading the full the file in memory. The Blender reading code then goes over all BHeads and processes Library Data and Indirect data, creating full copies. So in the end the full file can be freed from memory again. (NB: writing and reading large data chunks is to prevent disk and network overhead).

ファイル読み込みは、ファイルの全てをメモリ内に読み込むことから始まる。
Blenderはコードを読み、それから、全てのBHeadsを通り、LibraryDataとIndirectDataへと進み、フルコピーを生成する。
そうして、全てのファイルの終わりに達すると、メモリを再び開放する。
(でかいデータチャンクの読み書きは、ディスクとネットワークのオーバヘッドを防がねばならない)

Writing dynamic linked library data

ダイナミックリンクされたLibrary dataの書き込み

Since Blenders Main tree just is another list-able struct, it uses multiple Mains to be able to save and write dynamic linked data efficiently. This is done by the function split_main(), which creates Main trees with all data separated per file it belongs to.


BlenderのMain treeは、ただ、他でもリスト可能な構造であるから、複数のMainを保存でき、ダイナミックリンクされたデ0タを効率的に保存することが可能である。これはsplit_main()関数によってなされ、ファイルの所属ごとに、全てのデータが分離されて、Main treeが生成される。

For saving, the current Main tree then can be normally processed. For the other Mains it then only saves all IDs (as type ID_ID), with a separator to denote which file it originated from (done by saving struct Library).


保存のために、現在のMain treeは、それから、普通のプロセスを踏める。他のMainは、全てのIDをID_ID型として保存し、それは(IDから)由来していることを意味しているセパレータである

It then calls join_main() to merge all into a single Main tree again.

それから再び1つのMain treeにマージするために、join_main()を呼ぶ

Reading dynamic linked library data

ダイナミックにリンクされたデータの読み込み

This goes a little more complex, also to allow recursion;

これは少し複雑で、再帰的でつ

1. While reading the data from a file, and Blender encounters a Library struct, it creates a new Main struct and remembers to store all subsequent ID_IDs there. These IDs get flagged LIB_READ.
2- it then goes over all new Main trees, checking for LIB_READ flagged blocks
3- if a LIB_READ block is found:
3.1- it checks if the file containing this data was already read, if not it loads the entire file in memory and stores this in the Main.
3.2- it then reads the block with the normal reading routine, linking all Direct Data to it. The new block is linked to the current Main tree, the old block removed.
3.3- depending on block type, it calls the expand_doit() function, which forces reading more blocks like in 3.2, or it detects the data already was read correctly. Note: when such expanded data is again from another file, it just reads the ID part, links it to the correct Main and flags it LIB_READ.
4. For as long as LIB_READ flagged blocks where found, it returns to step 2.
5. Only in the end, it joins the Mains and restores all correct Library Data pointers.


1. { ファイルからデータを読み込んでいる、BlenderがLibrary構造と出くわしている} 間、新しいMain構造を作り、それに続く全てのID_IDsを、そこへ蓄積する。これらのIDはLIB_READというフラグを得る。

2.それから全ての新しいMain treeを通過し、LIB_READフラグが立っているブロックをチェック

3. もしLIB_READフラグが立ったブロック見つかったら

3.1- そのファイルに、既に読んだデータが含まれているかチェックし、もし読んでなかったらファイルをメモリに入れて、このMainを蓄える

3.2- それから通常の読み込みルーチンでブロックを読み、全てのDirect Dataを、そのブロックにリンクする。新しいブロックは現在のaMain treeにリンクされ、古いブロックは消される。

3.3- ブロックの種類により、expand_doit()関数が呼ばれ、強制的に3.2のようなブロックが読み込まれるか、既に完全に読み込んだデータを決定する。Node: そのように広げられたデータが再び他のファイルにあったとい、ただID部分だけを読み、それを正しいMainにリンクし、LIB_READフラグを立てる。

4 LIB_READフラグが立ったブロックと同じ長さのブロックが見つかったため、ステップ2にもどる

5 終わりにきたので、Mainsと復旧した全ての現在のLibary Dataポインタを結合する。

As you can imagine, this system requires quite some pointer magic, where pointers have to be mapped to new pointers, and to new pointers again, only to end up with the correct pointer to the actual data as was allocated.

よくわからんから略。

blender - ファイルフォーマットを書き換えたい(3)

注意:TOEIC400点、英検3級レベルの人が訳しています。
誤訳があるなんて当たり前だと思ってみてください。
むしろ全部訳しなおしてくれる人がでることを祈っています。

http://www.blender.org/development/architecture/

Data block types

All blocks as stored in the Main tree are called Library blocks (sometimes called Libdata). Library blocks all start with the ID struct:

すべてのブロックはMain treeに蓄えられ、Libraryブロックと呼ばれる。(たまにLibdataと呼ばれる)
Libraryブロックは全てID構造体から始まる

// ここにID構造体のコード

Let's take a closer look at one of the Library blocks, the Mesh. Of course such a block is actually a collection of many more blocks, either in arrays or as a List. Here we store the vertices, faces, UV texture coordinates, and so on (blue in picture). These blocks are called Direct Data. Such data is meant to be a direct part of the Mesh block, and is always written together with a Mesh or read back from the file.

さあ、MeshのLibraryブロックをまじまじと見てみよう。
もちろん、このようなブロックは実際多くのブロックのコレクションであり、配列かリストである。
ここに私たちは頂点、面、UVテクスチャ座標などを蓄える。
これらのブロックはDirect Dataと呼ばれる。
このようなデータは、Meshブロックの直接的な部分ということを意味し、いつもMeshと一緒に保存されるか、ファイルから読み込まれるかする。

Apart from this - permanent - data, there's also temporal data that can be linked to the Mesh, as for example the Display Lists. This data always is generated on the fly, not written in a file, and set at NULL when read from a file. Since all Library and Direct data resides in files too, it is important to design it compact, and leave temporal data out of it.

これ(永続的なデータ)から区別して、Meshへリンクできる一時的なデータがある。例えばDisplayリスト。
このデータは、いつも飛ばされて、ファイルに書かれないし、ファイルから読み込まれてもNULLがセットされる。
すべてのLibraryとDirect dataはファイルにあるので、小さく収めることと、一時的なデータを(ファイルから)取り去ることが重要である。

We now get to a very important rule in Blender's design: the usage of pointers inbetween blocks in Blender is restricted to pointers to Library data. This means a pointer to any Object or Mesh is allowed anywhere (in a vertex for example), but a pointer to a specific vertex cannot be stored anywhere.

This rule ensures a coherent and predictable structure, which can be used by any part of Blender code (especially for database management and files). It also defines how to make a decision when something should become Library Data; when you want it to be crosslinked (re-used) everywhere within Blender.

私たちは今、とても重要なBlenderの設計を得た。Blenderのブロック中でのポインタの使用は、Libraryデータへのポインタに制限されている。これは、全てのObjectやMeshへのポインタが、どこへでも許されることを意味するが、具体的な頂点へのポインタは、どこにも蓄積されない。

When files get saved, the Direct Data always immediately follows its Library Data. Since saved data can contain pointers these have to be restored when reading back. The pointer rule here helps with quickly restoring the pointers to all Direct Data, since these pointers only exist within a single and relative small context. Only the pointers to Library data are stored in a global list, and all restored at once in one call (lib_link_***).

ファイルが保存されたとき、Direct Dataはいつも、即座にそのLibraryデータに従う。
保存されたデータはポインタを含めることができるので、これらは読み込んだとき復活する。
ポインタは全てのDirect Dataへのポンタを素早く復旧するのに役立ち、これらのポインタは1つで比較的小さいコンテキストに存在する。
Libraryデータへのポインタはグローバルリストに蓄えられ、全ての復旧に1度呼ぶだけで済む。(lib_link***).

(NB: when adding game logic to Blender - Sensors, Controllers, Actuators - it was originally decided to have it reside within the Object context as Direct Data. Later on the need arose for having Sensors on Objects triggering Controllers in other Objects. This feature actually should make it Library Data, which wasn't done. A quite ugly patch for this was in a rush added to the file reading code. Until now it is still a disputed design issue; potentially the Message Actuator and Message Sensor should have been used instead.)

Sensor、Controller、Actuatorといった、GameLogicで加えられたものは、独自に、Object内にDirectDataとして持つことが決定した。後に、Object上のScensorが他のObject内のControllerをトリガするといった必要が生じた。この特徴は、実際Libraryデータにするべきであった。このための凄く不細工なパッチがファイルへ猛烈に加えられた。現在これは未だに争点となっている設計問題であり、将来的に、MessageActuatorとMessageSensorは取り替えられるべき)

External Library Data

One of the design requirements was being able to import data from other files, or have it dynamically linked as a sort of templates. Evaluating other 3D programs at that time (Alias, Softimage) I noticed they use the actual OS filesystem for it; creating 'project' directories with a directory tree inside and a single file for each data block. Apart from it being very clumsy and complex to maintain, I suspected it to be quite slow too. :)

設計に要求されることに、他のファイルからのデータインポートや、それがテンプレートのソートのように、ダイナミックにリンクされることであった。そのとき他の3Dプログラムを評価していて(XSIとか)、私はそれらがOSのファイルシステムを使ってることに気づいた。
->あるディレクトリtreeの内側に、プロジェクトディレクトリを生成することと、data blockごとに1ファイルあること。
とてもぎこちなく複雑に保持することは別として、私はとてもじっくり、それを疑った。

Nevertheless, Blender should have at least the benefit of this approach. The usage of names for Blender data therefore closely resembles that of a filesystem, with a Blender file being a group of directories containing all of the individual files.

それでもやはり、Blenderはこのアプローチの恩恵を受けるべきであった。Blender dataの命名規則は、それゆえ、ファイルシステムととても似ていて、Blenderのファイルは、ディレクトリのグループに全ての独立したファイルを含んでいる。

When using data from other files (dynamic linking), it is evident that only the Library Data blocks can be linked to. Blender then automatically reads its associated Direct Data. However, to make reading from extern files more useful, it also expands its full linked tree. For example a linked Object will also invoke reading its attached Mesh and attached Materials and Textures. Such expanded data is called "Indirect". In the interface you can recognize this with a red colored library icon. When saving to a file, such expanded (Indirect) data is not written at all. This enables the editor of the external file to change links to the Object, like adding an Ipo or add another Material.

ダイナミックリンクにより、他のファイルからのデータを使うとき、LibraryDataブロック群がリンクできることだけを確かめる。 Blenderは、それから、自動的にその想定されたDirectDataを読み込む。
しかし、もっと便利に外部ファイルを読み込むために、それをフルリンクされたtreeに広める。 例えば、リンクされたObjectは、それに付けられたメッシュやマテリアル、テクスチャの読み込みを引き起こす。このような広げられたデータは、"Indirect"と呼ばれる。
インタフェースでは、あなたはこのことを、赤い色のlibraryアイコンで理解できる。
ファイルを保存するとき、このように広げられたデータは、すべて保存されない。
これは、エディタで、外部ファイルのオブジェクトのリンクを変更すること (Ipoを加えたり、他のマテリアルを追加したりするような)を可能にする。

A typical usage of this feature is dynamical linking a Scene from another file. Whatever is in that Scene always will be read.

この特徴の典型的な使用法は、他のファイルからSceneをダイナミックリンクすることである。
どんな中にあろうと、Sceneはいつも読み込まれる。

While saving linked Library data, only its ID component is written. This ID then contains a pointer to the used "Library" (= external file), and the fact IDs have unique names then guarantees the links always restore correctly.

リンクされたLibrary dataを保存する間、そのID componentは書き出される。
このIDは、それから、使用されているLibrary(=外部ファイル)へのポインタを含んでいて、
だからIDは、リンクから全ての復旧を正しく行うために、一意の名前を保障している。


---
ふぅ、あと2章か…