ソフトウェア開発したい日記

「面白い!」と思った頭の体操や、数学の問題を載せていきます
その他ロードバイクででかけた先の写真や、ソフト開発のメモ等

粒子法による流体シミュレータ作りたい

2010年06月20日 18時55分34秒 | ソフト開発日記
見た目はさほど変わってないけど、
以前のしょっぱい流体シミュレータからちょこっとだけ進化。

以前は粒子数を増やしても、粒子(球)が重なっていき
どんどん沈んでいっちゃってた。
粒子を3倍に増やしても、水面の高さは変わらず、っていう具合に。

今回は粒子の跳ね返り後の速度を、粒子の接近具合に依存させてみました。
調べてみると、これが一般的な手法のようでした。

すると水面が沈むことなく、粒子を増やせばどんどん高くなるようになりました。
ただ粒子の重なりは完全に防げず、下にいくにつれて重なりが激しくなっており、
図らずも色の濃さが圧力を表してる感じになってます。

粒子数は800で、リアルタイム計算でそこそこヌルヌル動きます。
あとでっかい球をドラッグできるようにしました。
(一般的な物理エンジンでよくあるあんな感じ)

ここまで計算を全て3次元ベクトルで行ってきたので、
z方向に初期速度を与えれば即3Dになる。はず。

今度はこれをC++に移植してOpenGLで3Dアニメーションにしてみたい。
Java3Dは一回挫折したけど、Java3Dでもやれたらやってみたい。

ベクトル演算してくれるヘッダー その2

2010年06月19日 23時50分31秒 | ソフト開発日記
よくよく考えたら、構造体同士で足し算とか引き算とかできましたね。
ということで、昨日書いたやつをもっと短くしたやつ。

//各種3次元ベクトル演算ヘッダー
//ベクトルの和
CVector vectorPlus(CVector v1, CVector v2){
  CVector v0;
  v0 = v1 + v2;
  return v0;
}

//ベクトルの差
CVector vectorMinus(CVector v1, CVector v2) {
  CVector v0;
  v0 = v1 - v2;
  return v0;
}

//ベクトルのスカラー倍
CVector vectorMult(CVector v1, double d) {
  CVector v0;
  v0 = v1 * d;
  return v0;
}

//ベクトルの長さ
double vectorScalar(CVector v0){
  double d;
  d = sqrt(v0.x*v0.x + v0.y*v0.y + v0.z*v0.z);
  return d;
}

//ベクトルの長さの二乗
double vectorScalar2(CVector v0){
  double d;
  d = v0.x*v0.x + v0.y*v0.y + v0.z*v0.z;
  return d;
}

//ベクトルの内積
double innerProduct(CVector v0, CVector v1){
  return(v0.x*v1.x + v0.y*v1.y + v0.z*v1.z);
}

//ベクトルの外積
CVector outerProduct(CVector v1, CVector v2){
  CVector v0;
  double x, y, z;
  x = v1.y*v2.z - v1.z*v2.y;
  y = v1.z*v2.x - v1.x*v2.z;
  z = v1.x*v2.y - v1.y*v2.x;

  v0.x = x;
  v0.y = y;
  v0.z = z;
  return v0;
}

後半3つは無理そうかなぁ。特に外積は・・。
内積とか距離はいけるかも、と思って
ベクトルの構造体同士を掛け算してみたけど、案の定ダメでした。

ちなみに、構造体はこんな感じ。
typedef struct vector{
  double x, y, z;
}CVector;

ベクトル演算してくれるヘッダー

2010年06月18日 22時26分40秒 | ソフト開発日記
探せばありそうだけど、以前Javaで作ったやつをC向けに作ってみた。
3次元ベクトルを表す構造体CVectorを用意して、後は以下のとおり。

//各種3次元ベクトル演算ヘッダー
//ベクトルの和
CVector vectorPlus(CVector v1, CVector v2){
  CVector v0;
  v0.x = v1.x + v2.x;
  v0.y = v1.y + v2.y;
  v0.z = v1.z + v2.z;
  return v0;
}

//ベクトルの差
CVector vectorMinus(CVector v1, CVector v2) {
  CVector v0;
  v0.x = v1.x - v2.x;
  v0.y = v1.y - v2.y;
  v0.z = v1.z - v2.z;
  return v0;
}

//ベクトルのスカラー倍
CVector vectorMult(CVector v1, double d) {
  CVector v0;
  v0.x = v1.x * d;
  v0.y = v1.y * d;
  v0.z = v1.z * d;
  return v0;
}

//ベクトルの長さ
double vectorScalar(CVector v0){
  double d;
  d = sqrt(v0.x*v0.x + v0.y*v0.y + v0.z*v0.z);
  return d;
}

//ベクトルの長さの二乗
double vectorScalar2(CVector v0){
  double d;
  d = v0.x*v0.x + v0.y*v0.y + v0.z*v0.z;
  return d;
}

//ベクトルの内積
double innerProduct(CVector v0, CVector v1){
  return(v0.x*v1.x + v0.y*v1.y + v0.z*v1.z);
}

//ベクトルの外積
CVector outerProduct(CVector v1, CVector v2){
  CVector v0;
  double x, y, z;
  x = v1.y*v2.z - v1.z*v2.y;
  y = v1.z*v2.x - v1.x*v2.z;
  z = v1.x*v2.y - v1.y*v2.x;

  v0.x = x;
  v0.y = y;
  v0.z = z;
  return v0;
}

モノクロメータってどうなってるの

2010年06月17日 22時02分12秒 | 科学
連続X線(白色X線)を単色化する、モノクロメータについて
その原理や汎用性に関するメモ。

単色化の原理
連続X線をSi等の単結晶(回折格子)に当てると、連続X線は回折する。
このときの回折角は、Braggの法則に従い波長に依存する。
すなわち、特定の波長を持ったX線は、特定の回折角を示す。
X線を回折することで、特定の波長を取り出すことができる。
モノクロメータは回折格子を回転させ、到達するX線の波長を制御。
これがモノクロメータの原理。分光器とも。こんな感じだろうか。

回折格子の材料はとても高価らしいけど、
この技術が蛍光X線分析以外であまり普及しないのはなんでだろう。

X線CT装置に利用すれば、ビームハードニングとか低減されて
良くなると思うんだけど、研究論文が全然ない気がする。

回折することで単色化はされるけど、強度が著しく低下とかしちゃうのかな。
モノクロメータにより単色化されたX線でのCT撮影とかの論文は
Spring8使ってし・・。うーん。

OpenGLで作ったものを、他環境でも動く実行ファイルにしたい

2010年06月16日 20時05分58秒 | ソフト開発日記
他のPCでも動くexeファイルにしたいけど、VC++では何故かうまくいかない。
とりあえず今のところ、書式はほとんどC言語なので、
拡張子を「.c」にしてcygwinでやってみるテスト。
(bool型の変数は普通に使ってたけれど、stdbool.h読み込んだら解決。)

環境はWindows7と最新のcygwin

まず「winglut.tar.gz」を検索してダウンロードして解凍。
「libglut32.a」を「C:cygwin\home\lib」に
「GL」フォルダを「C:cygwin\usr\include」にぶちこみます。
(上書き保存する前に、念のためバックアップをとっとく。)

「glut32.dll」を「C:Windows\System32」に入れる必要もありますが、
VC++でOpenGL使えるようにしたときにこれは終わってます。

そんでもって、次のように実行

「gcc -o test test.c -DWIN32 -lglut32 -lopengl32 -lglu32」

無事コンパイルできました。
「./test」と実行すると、ちゃんと動きました。

ただ、できたexeファイルを外から実行しようとすると

「cygwin1.dllが見つからなかったため、このアプリケーションを
開始できませんでした。アプリケーションをインストールしなおすと
この問題は解決される場合があります。」

というエラーが。
調べてみると、-mno-cygwinオプションつければcygwin1.dllに依存しない
実行ファイルできるようなので、
「gcc -mno-cygwin -o test test.c -DWIN32 -lglut32 -lopengl32 -lglu32」
と試してみると、

「The -mno-cygwin flag has been removed; use a mingw-targeted cross-compiler.」

というエラーメッセージが・・。
mingwでクロスコンパイルすればいいそうなので、調べてやってみることに。

とりあえずmingwをダウンロードしてインストール。
マイコンピュータ右クリック⇒システムの詳細設定⇒環境変数
で、ユーザの環境変数に「PATH」を新規作成(或いは編集)し、
変数値に「%PATH%;C:\MINGW\BIN;C:\CYGWIN\BIN」を追加。
-mno-cygwinオプション無しで、
「gcc -o test test.c -DWIN32 -lglut32 -lopengl32 -lglu32」
でいけました。exeファイルも外から動きました。

最終的なコマンドは、起動時にコンソール画面を出したくないので
-mwindowsをつけて↓こんな感じになりました。

「gcc -o test test.c -DWIN32 -lglut32 -lopengl32 -lglu32 -mwindows」

今後毎回これを入力するのは面倒なので、
「auto.sh」ファイルを作成し、上記コマンドを記入。
「./auto.sh」で実行していくことにします。