こねねこ
http://coneneko.sourceforge.jp/

Digital Mars D programming language 用3Dライブラリです、今のところ。
最終目標は汎用性の高い3Dライブラリです。
開発中につきインターフェース等を頻繁に変更しています。バージョン間の互換性はありません。
このライブラリはopengl, sdlを内包していますので、これらのメソッドの多くをそのまま利用できます。

ビデオカードの性能にpixel shader 2.0以降ぐらいを要求します。

コンパイル時に./lib/coneneko.libをリンクしてください。
インポートパスは./src ./src/opengl ./src/sdlです。
例)
dmd foo.d conenekoYMDD\lib\coneneko.lib \
	-IconenekoYMDD\src -IconenekoYMDD\src\opengl -IconenekoYMDD\src\sdl


・ライセンス
・ツール
・実装メモ
・TODO
・履歴


---------------------------------------------------------------
ライセンス

Copyright (C) 2005- hideki_i
このライブラリはGPLライセンス(v2)で配布しています。
詳細は./gpl.txtをご覧ください。

・ライセンス適用範囲
./srcディレクトリのファイルで、以下のディレクトリ以外のものです
./src/glew2glext/glew
./src/opengl
./src/sdl


・自分で書いてないコード、ライブラリ

glew
http://glew.sourceforge.net/
opengl拡張ヘッダ、BSDライセンス
glew/auto/extensions/ から ./src/glew2glext/glew/* に必要な分だけコピーしました。

opengl
http://shinh.skr.jp/d/porting.html
ライセンス(後で調べとく
./src/opengl/opengl.d
./src/opengl/openglu.d
./lib/opengl32.lib
./lib/glu32.lib
にそれぞれコピーしました。

sdl http://www.libsdl.org/index.php
http://shinh.skr.jp/d/porting.html
http://www.libsdl.org/download-1.2.php
http://www.libsdl.org/projects/SDL_mixer/
http://www.libsdl.org/projects/SDL_image/
http://www.libsdl.org/projects/SDL_ttf/
ライセンスLGPL
./src/sdl/*.d
./bin/*.dll
にそれぞれコピーしました。

libpng
ライセンスzlib
http://www.libpng.org/pub/png/libpng.html

zlib
ライセンスzlib
dmdのものを使用
dmd\src\phobos\etc\c\zlibで
make -fwin32.mak zlib.lib


・リソース

背景画像
ぐったりにゃんこのホームページ
http://guttari8.hp.infoseek.co.jp/

エフェクト
Detonation
http://www.vector.co.jp/soft/win95/art/se173882.html

効果音
ザ・マッチメイカァズ
http://osabisi.sakura.ne.jp/m2/


---------------------------------------------------------------
ツール

・to_nanami.exe
拡張子mqo, mkmのファイルから拡張子773のファイルを作成するツールです。
mqoはメタセコイアのモデルファイル、mkmはmikotoのモーションファイルです。
mqoをto_nanami.exeにドロップするとモーションを含まない773を作成できます。
mqoとmkmを一緒にto_nanami.exeにドロップするとモーションを含む773を作成できます。
データの定義が合わない場合には作成に失敗する場合もあります。
./resource/のmqo, mkmを参考にしてください。
///////////////////////////////
-mqoについて
sdef:subset[y][x]:
bdef:subset[y][x]:
それぞれmikotoのsdef: bdef:に対応します

0 <= x, 1 <= y
オブジェクト名の最初にsdef:subset[y][x]:を加えることでデータの一部をsubsetとして利用できます。
一つのsubsetには一つのテクスチャのみを設定できます。
y = 0はデフォルトで自動的に生成されるので使えません。
y = 1は表示、非表示の切り替えが可能なものを設定します。
y >= 2はモーフアイテムとして利用します。

例えば、"sdef:subset[1][0]:服0", "sdef:subset[1][1]:服1"というオブジェクトを作ると、
服0、服1の表示を制御できるようになります。

"sdef:subset[2][0]:口", "sdef:subset[2][9]:口"というオブジェクトを作ると、
subset[2][1]からsubset[2][8]までは補完され、subset[2]をモーフアイテムとして利用できます。

一つのオブジェクトで使えるテクスチャは一つだけなので注意してください。
オブジェクトでテクスチャを使わない場合は、そのオブジェクトに複数のマテリアルを利用できます。
///////////////////////////////
ビデオカードの性能に依存しますが、ボーン数が多くなると描画できません。
そういう場合はモデルを二つに分けてボーン数を減らすと描画できるかもしれません。
-クロスシミュレーション
to_nanami -cloth hoge.773
入力はリダイレクション可、頂点数制限ushort.max(65535)まで
・subset[1][n]選択
・fixingVertex(固定頂点)範囲 x0 y0 z0  x1 y1 z1
・spring(戻ろうとする力)
・resistance(抵抗力)[0.0, 1.0]


・nanami_viewer.exe
773を表示するツールです。
773をnanami_viewer.exeにドロップして使います。


・scene_editor.exe
SceneViewを見ながらテキスト編集できるテキストエディタです。
coneneko.sceneview.SceneViewクラスのビューを持っています。
エディタでコードを書いてF5でビューに反映させるというサイクルで開発することを想定しています。
./src/test/scene0.dはこのエディタで書きました。


・glew2glext.exe
glewのテキストをdのコードに変換するツールです。


---------------------------------------------------------------
実装メモ

他のライブラリをブラックボックス化しない
opengl以外の実装にできる限り影響を与えない
SDLのメソッドで対応できるものはラップしない

ツールなどで自動生成するデータ(コード含む)はコミットしない

カメラの値はcm単位ぐらい、メタセコイアで出力される座標もcm単位で扱う

黄金比 1:1.618
白銀比 1:1.414

テクスチャのサイズは2^n

頂点数は少ないほうがいい、ボーン数は限界まで少なく

アーキテクチャ選択の邪魔にならない程度に実装する
コントロールはライブラリにできるだけ含まない、外見の特化が難しくなる
特定のアーキテクチャにも依存することになる

t軸移動はTimeIteratorで実装、全体の速度を調整できるから
ライブラリ内でSDL_GetTicks()等を用いた実時間への依存は避ける

能動的オブジェクトでの実装

単純な図形でも頂点をケチらない、補完で正確な数値が出ない場合がある
/ wのタイミングがおかしい?
vertex shaderで行うと補完がうまくいかないのでpixel shaderでやるべき?

test.dにテストをまとめる、26まで使ったら似たものを統合してゆく

/resource わかりやすい名前をつけられない場合はa, b...と付ける
フリーズ前のmqoデータにはn_.mqo, フリーズ後はn.mqo

Object o;
assert(o);
でavが出るのでassert(o !is null)に変更、ただしif(o)は有効
可読性もあまりよくないしbool以外のif (n) or if (!n)の記述は使わない

SceneGraphをUnitにすると、内部検索にかからなくなる
利便性と、検索機能でメリットがあるなら選択する

opengl座標について
modelViewProjection / w後の可視座標範囲はxyz共に[-1, 1)で、zの-1が手前  (zだけは[-1, 1]の場合もある?)
fragment shaderに渡される値は左下座標(0, 0)の右上が正、sizeはwindowのクライアント領域のサイズ
viewportはこれが基準になる、z[0, 1)手前が0.0、wは1/w0(除算に使ったもの?)
テクスチャも同様、画像の左上座標(0, 0)が左下になる、上下逆なのでファイルへの読み書き時には注意

Vector.w Matrixの扱いに注意、同次座標


---------------------------------------------------------------
TODO

ボーン数制限、今のところ34ぐらいが限界、そのうち制限なしに使えるように, 40ぐらいまでは使えるらしい?

クロスシミュ 障害物からの押し出し(加速度加算なし)、normal

エラーはクラス名とメッセージを明確に書けば__LINE__, __FILE__は不要?

cleanでできる限り初期状態に戻るように修正

framebufferobject 四つ同時にレンダリングできるように、必要なら

TimerやThreadはアーキテクチャに影響を与える場合が多いのでライブラリ内部で使わない

リソース系のクラスにはできるだけcloneをそのクラスのdecoratorで, dupはデフォルトの配列と混乱するので使わない
libをリリースとデバッグの二つに分けておく
invariant()等を利用して実行時エラー以外はassertで追い出す

液体の表現

shadow bufferとtoonの影を混ぜてaに、hsvをaで影響を受けて、ハイライトも これらをできるだけ少ないパスで繋ぐ

必要なリソースはリアルタイムに生成、Serializer派生でファイルに書き出せる

型は隠す意味がないのでopenglそのままでかまわない、無理になおさない

font textureのflyweight

font.defaultSizeはそのうち64に

rgba32fはalphablend時にものすごく時間がかかる?alphablend offの場合はあまり重くはならない
alphablend off時にrendertargetにalpha値を描ける、普通のピクセル扱い
fragment shaderのtexture読み書きは、[0, 1]clampかからずにfloatとして使えるようだ、-も使える
vertexからfragmentへの要素は[0, 1]clampされる、rendertargetのフォーマットは関係なし

structをclassに
structとして使えるメリットよりもデメリットの方が多い
interface, 継承、コンストラクタが使えない、など
op演算子が使えるので特に不便なこともない
class Color : Vectorもできるし
MqoNormalの*sは取る、Mqoから派生して使う
ただ、Vector, Matrixは影響範囲が多いのでもう少し考えてから
逆にstructのメリットはnewしないで使えること
あと記述量の問題、new White() or white()でnewなしの方が短い
定数にできる部分から定数化するのが優先か?
x 変えない、バリューのままの方がコピーで混乱がない、ライブラリを探す方が優先

Vector, Matrixを扱うライブラリを探す

ddocで生成するリファレンスは最小限、利用するのに必要な分だけ、内部のものは隠す
情報量が多くなると探すのに時間がかかるので必要のない情報は見えない方がいい
必要ならば別のリファレンスとして追加する
もう少し考えてから、リファレンスを参照するメリットが最大限大きくなるには?

morphをshaderで合成、テクスチャはmodel単位で共有
[index, t] indexは1以上, 0はデフォルト, tはmorph用で省略できる
0はpnct or pnctmw, 1以上はpnct or cloth or pnctp
subset(pnct), wm付き(pnctmw), morph(pnctp), cloth(pnct+a?)を属性(class?)にして配列でまとめる
ボーンつきの場合、mw以外には近くのboneのworldを設定する, boneIndexが必要?
vertexからmatrixindex, weight, pnctをmodel(又は別のファイル)に
pnctData, pnctmwData, pnctpData, pnct, pnctmw, pnctpに分ける
属性ごとにshaderを決定できるのでmodelにshaderを入れる
表情の変化やモーションの順番なども考慮する
subset毎に分けることも可能?scenegraphでの扱いを考えると分けない方がいい
mqoのフリーズや合成はmikoto前で終わらせておく方が無難?resourceはフリーズ前後の二つ、a.mqo, a_.mqo

Modelでsubset指定でモザイク(or 特定のフィルタ)がかかるように

toonshaderのtexture1を削除して、pixelshader側で処理した方がいい?
toonshaderのエッジは法線で出すx smoothでない場合にうまくいかない、リアルタイムに出すよりもモデリングでやったほうがきれいに出る

container.indexOfのis, ==の区別がつきにくい、削除した方がいい?

viewportはRenderTarget.drawの引数にした方がいいかも、or Camera
textureSizeの問題はハードかドライバ側で解決されるのでもう少し待つ?
しばらくの間は、viewport固定で512x512 or 1024x512をデフォルトのウィンドウサイズにした方が面倒がない?

noise生成をもう少し速く?noiseはglsl側が対応するので、これ以上自力でやる必要はない

頂点をフルに使った描画を最小限にして
テクスチャに情報を載せた状態で、それらを組み合わせるのが多分速い

serializerについてまとめる, ModelData周辺も?
TODOで必要ないのを削除
実装メモはまとめてwikiの方に移す

key downイベントでウィンドウ切り替えが発生すると、key upイベントを受け取れない
フォーカスが戻っても、キー状態が押されたままなのでクリアしておく

一つのsubsetに複数のtextureを使うとデメリットが多い
subset { vertices, texture }にした方がいいかも
他のフォーマットを見てから考える

model_viewer、3dをセーブした時、たまに位置がずれる
多分world変換後の位置でセーブされている
serialize直前に、world arrayを初期化すればいい

コードの階層化
interfaceと依存関係をベースに置く、特化した実装はサブディレクトリに
もう少し複雑になったら
依存関係は多単、単多など複雑になって階層化するのは難しいので
分類程度にしておく
-units
-collections
...
分類方法を少し調べる、うまく分類できないようならこのまま
分類するほど規模も大きくないし、今は考えなくてもよさそうphobosよりも規模が大きくなったら考える
ロジック層とユーザーインターフェース層でサブディレクトリ、共有して使うのはルート
まだ規模が小さいので分けない

Model.shaderをModelShaderからModelShader[]に変更して複数パスでできるように?
rendertarget回りも、もう少し考えてから

quaternionの補完をまともに
長いmkm読み込みでkeyframeがずれている可能性が高い

物理演算等に任意時間(delta)を引数として与えるようにする
描画と演算の時間は分離する、描画に時間は必要ないので削除

ddoc用のコードコメントを少しまじめに書く

Window.updateはdraw, sleep(1), doEventsぐらいで、簡単なテストを書くときに便利なので残す
updateはdraw, flip, sleep, doEventsで
fpsの同期はWindowから出す
x Window.drawでSDL_GL_SwapBuffers();を行うべき
x Window.rgbaをglReadBuffer(GL_BACK);GL_FRONTに変更する必要がある?

draw時にflipすると連続で書き込む手がなくなるのでなんとかしたい
Window has BackBufferでdrawをdraw, flipに分割
BackBuffer.rgbaはGL_BACKで
flipはRenderTargetをWindowに描画する、backbufferならswap
BackBufferはSDL依存しないように実装できる?
backbuffer.d sdlへの依存がないので可能
RenderTarget.width, height, flipがあった方がいいのだろうか?
flip(RenderTarget)?、又は近い処理があった方が

RgbaとRenderTargetを統合できればいいけど
バッファのフォーマットが問題になっている

scenegraph.d
FSAA、ShadowBufferなどは
SceneGraphの派生としてまとめる
rendertarget to rendertargetはscenegraph to rendertargetになっているから
fbo.draw(new Fsaa());

viewportはRenderTargetに持たせた方がいいか?
sizeの制限がなくなったらviewportを使う機会はなくなるだろうか?

tree -> plane
plane + plane -> plane
tree + plane -> plane
入力の選択肢が多数存在している、どれが最適なのか判断するにはサンプルが足りない
shader単体で意味のあるクラスと、
shader+他の処理というscenegraphで意味のあるクラスに分けられる

文字のサイズは画面サイズに対する相対的な大きさであることが望ましい
planeや、mouse.posの単位を合わせる
wndサイズへの依存がなくなるメリット
planeは左下から右上の範囲を使う
全体の座標範囲は[-1, 1)
文字列も左下座標から、width, heightの範囲に書く
文字列自体はその範囲の左上から書く
modelViewProjectionで扱いやすいので範囲は[-1, 1)で行うのがいいだろう
PlaneImageの座標も左下から、画像データは左上から
plane camera, plane render state破棄
plane*はtextboard, imageboardに戻す
相対的な値で扱う、wnd.size, renderState.sizeへの依存を切る
文字列ではtextureサイズ制限が実装を難しくしているので、制限がなくなってから
文字列はtextureに対して描画する、後はimageと同様に扱う
TextBoard(string, p, size, color, texsize, font)

重要なクラスは独立性を高く、他のクラスへの依存を抑える(内包は別)
データ定義用のクラスは受動的に
translatorやcloth頂点計算クラスなどは能動的に

Fiberのテスト

コンストラクタでいろいろなデータを設定すると可読性が低い
プロパティを用意してそれで設定すると、プロパティ名が可読性を高める。
両方でできるように書く、ある程度みきわめることができたら一方だけに。
fluent interfaceで書くと、コンストラクタ引数をなしにできる。
それ以外にも引数の数が多いメソッドは一考の余地がある。
コード修正時に可読性が高い場合はリファレンスを参照する必要がなくなる。
ためしに、コンストラクタの引数を削除して、置き換えてみる?
派生したreturn this;も問題なく動作するらしい
fluent interface, Unitの派生クラスでは使いやすい、それ以外では慎重に

当分の間は、引数の削除はしない、追加と修正だけ

MatrixはclassにしてLookAt : MatrixやPerspective : Matrixにした方が利便性が高い
又はclass Matrix2, decoratorとしての実装
fluent interfaceにできる、Matrixからプロパティ値への変換ができない?

ModelShader周りの実装をもっと簡潔にするか、この辺り全てをブラックボックス化

perspectiveFovのnearを小さく設定しすぎると、zの幅がうまく取れないときがある

gl_FragCoord.z[0.0, 1.0] 多分視点からの距離、nearに近いほど0.0, farに近いほど1.0
w除算済みの数値が入ってるみたいなので、除算しなくていい

一回のupdateで全てをレンダリングしない前提でupdateは使わない方がいい

dsl
シーンをツールで作る、シーンプロパティへのアクセスでシーンに干渉する
ツールは作るか、既存を使うか、必要な部分だけを作るか

テストフォルダ作って、testを小さく分割して独立
htmlとrdmdで起動できるようにしておく?又は、簡単なテストランチャを作る
サンプルは小さい方がいいけど、一通りテストする時間がかかるようになるので、後回し


---------------------------------------------------------------
履歴(大きな変更だけ) ymdd

7b05 dmd v1.023
7b04 to_nanamiの変換処理をライブラリにほぼ移動終了, rename nanami_viewer model_viewer
7829 scene_viewer破棄
7708 repositoryをcvsからsubversionへ
7323 scene_editor削除、代わりにscene_viewer
6a14 release
6a14 ライセンスをGPLv2に変更
6a13 dmd v0.169
6929 visual_editor削除
6921 glew, opengl, sdlの外部ライブラリをリポジトリに追加
6911 dmd v0.166に対応
6909 アルファ前
