2012年1月31日火曜日

MAXScript ハイトマップからメッシュの作成(1)

Bmp, Jpeg画像のハイトマップから地形を作成するスクリプト

-- ビットマップ
gBitmap = undefined
-- 平面のサイズ
gPlaneSizeX = 500.0
gPlaneSizeY = 500.0
-- 平面のセグメント数
gNumSegX = 25
gNumSegY = 25
-- 最大の高さ
gHeightMax = 25.0

-- メッシュの作成
fn CreatePlaneMesh len wid segX segY = 
(
 m = mesh length:len width:wid lengthsegs:segY widthsegs:segX
 return m
)

-- セグメントのインデックスからピクセルのインデックスを取得
fn GetPixIdx segIdx segNum pixNum =
(
 segIdxF = segIdx as float
 segNumF = segNum as float
 
 f = segIdxF / segNumF
 pixIdx = f * (pixNum - 1)
 return pixIdx as integer
)

-- メッシュの指定したインデックスの頂点に高さをセット
fn SetHeight m idx height =
(
 v = patch.getVert m idx
 v.z = height
 patch.setVert m idx v
)

-- メッシュにハイトマップの高さをセット
fn Mesh_SetHeightMap m nSegX nSegY bm =
(
 -- 高さをセットするメッシュの頂点のインデックス
 idx = 1
 bmWidth = bm.width
 bmHeight = bm.height

 for y = 0 to nSegY do (
  pixY = GetPixIdx y nSegY bmHeight
  pixY = pixY as integer

  for x = 0 to nSegX do (
   pixX = GetPixIdx x nSegX bmWidth
   pixX = pixX as integer
   
   -- ビッドマップからピクセルの配列を取得
   pixArray = getPixels bm [pixX, pixY] 1
   
   -- 高さ
   h = pixArray[1].r / 255.0
   h = h * gHeightMax
   
   SetHeight m idx h
   idx = idx + 1
  )
 )
)

-- ハイトマップからメッシュを作成
fn CreateMeshFromHeightmap =
(
 -- ハイトマップを開く
 fPath = getOpenFileName caption:"Open Heightmap:" \
  types:"Bmp(*.bmp)|*.bmp|Jpeg(*.jpg)|*.jpg"
 if fPath == undefined then return -1

 gBitmap = openBitMap fPath
 format "w = % h = %\n" gBitmap.width gBitmap.height

 -- メッシュを作成
 m = CreatePlaneMesh gPlaneSizeX gPlaneSizeY gNumSegX gNumSegY
 
 -- パッチに変換
 convertTo m Editable_Patch
 
 -- 高さをセット
 Mesh_SetHeightMap m gNumSegX gNumSegY gBitmap
)
-- テスト
CreateMeshFromHeightmap()

MAXScript ビットマップの作成


-- ビットマップサイズ
gBitmapWidth = 256
gBitmapHeight = 8

-- グラデーションビットマップを作成
fn CreateGradBitmap =
(
 b_width = gBitmapWidth
 b_height = gBitmapHeight
 
 -- ビットマップを作成
 b = bitmap b_width b_height

 -- 列のループ
 for h = 0 to (b_height - 1) do
 (
  -- 行のピクセル配列を収集
  row = for w = 0 to (b_width - 1) collect
  (
   -- 補間係数
   t = w as float / (b_width - 1)
   
   -- rowにカラー値を追加
   if undefined != gSpline then
   (
    -- スプラインから座標を取得
    pos = interpCurve3D gSpline gSplineIdx t
    white * (pos.y / 100.0)
   )else (
    white * t
   )
  )
  -- 収集したピクセル配列をセット
  setpixels b [0, h] row
 )
 return b
)

-- ビットマップを作成
b = CreateGradBitmap()
-- ビットマップを表示
if undefined != b then display b

MAXScript ベジェ曲線の作成


gSpline = undefined
gSplineIdx = 0

-- スプラインシェイプを作成
fn CreateSpline =
(
 if undefined != gSpline then return -1 
 
 -- シェイプの作成
 ss = splineShape()
 -- シェイプにスプライン曲線を追加
 idx = addnewSpline ss

 -- addKnotのパラメータ
 param3 = #bezier 
 param4 = #curve

 -- bezier曲線の制御点のイン、アウトベクトルの座標
 inPos0 = [0, 0, 0]
 outPos0 = [0, 0, 0]
 inPos1 = [30, 10, 0]
 outPos1 = [70, 40, 0]
 inPos2 = [100, 100, 0]
 outPos2 = [100, 100, 0]

 -- 制御点の追加
 addKnot ss idx param3 param4 [0, 0, 0] inPos0 outPos0
 addKnot ss idx param3 param4 [50, 20, 0] inPos1 outPos1
 addKnot ss idx param3 param4 [100, 100, 0] inPos2 outPos2
 
 -- シェイプの更新
 updateShape ss
 
 -- コピー
 gSpline = ss
 gSplineIdx = idx
 return 0
)

-- 形状データ取得テスト
fn GetShapeDataTest ss idx =
(
 -- セグメント数
 nSeg = numSegments ss idx
 format "nSeg %\n" nSeg
 
 -- 曲線の座標
 for t = 0.0 to 1.0 by 0.1 do
 (
  pos = interpCurve3D ss idx t
  format "t = % pos = %\n" t pos
 )
)

CreateSpline()
GetShapeDataTest gSpline gSplineIdx

2012年1月28日土曜日

MAXScript ルートボーンの移動アニメを変更してみる(2)

あるモデルのルートボーンの移動アニメを無効にしたい
/*
 選択したボーンの全フレームの座標変更
 pos: セットする座標

    使用方法
 トラックビュー選択ダイアログが表示されるので
 変更したいボーンの"Transform : Position/Rotation/Scale"
 を選択してOKボタンを押す
 */
fn SetSelectBonePosAllKey pos =
(
 -- ダイアログ表示オプション
 dlgOpt = 0
 dlgOpt = bit.set dlgOpt 1 true --アニメトラックのみ
-- dlgOpt = bit.set dlgOpt 3 true   --選択したノードのみ

 -- ダイアログを表示
 tvp = trackview.pickTrackDlg options:dlgOpt

 if tvp == undefined then return -1 -- 未選択
 
 format "tvp.name %\n" tvp.name -- 選択した項目の名前
 if "Transform" != tvp.name then return 1
 
 c0 = tvp.client -- 選択項目の親のMAXWrapper
 if c0 != undefined then
 (
  cname = getClassName c0
  format "c0.className %\n" cname
  if cname != "Bone" then return 2
 )
 
 -- 選択項目のサブアニメを取得
 subAni = tvp.anim
 if subAni == undefined  then return 3

 -- サブアニメ数
 format "subAni.numSubs %\n" subAni.numSubs
 ret = 4
 for i = 1 to subAni.numSubs do
 (
  -- サブアニメの名前
  n =  getSubAnimName subAni i
  format "subAnim name %\n" n

  -- Positionのみ変更
  if 0 != stricmp n "position" then continue
   
  -- コントローラーの取得
  c = subAni[i].Controller
  if c == undefined  then continue

  -- コントローラーからキーの配列を取得
  keys = c.keys
  -- キーフレーム数
  format "key_array count %\n" keys.count
    
  -- 全キーフレームの座標を変更
  for j = 1 to keys.count do
  (
   keys[j].value = pos
  )
  ret = 0
 )
 return ret
)

gPos = [0, 0, 0] -- セットする座標
SetSelectBonePosAllKey gPos

Android カメラデバイスを使用(1)


AndroidManifest.xmlのmanifestタグ内に以下の記述を追加
 <uses-permission android:name="android.permission.CAMERA" />
 <uses-feature android:name="android.hardware.camera" />

ActivityのonCreateでセットするコンテキストビューを変更
 //setContentView(R.layout.main);
 setContentView(new CameraPreview(this));

カメラプレビュー用のクラスを作成
 // カメラ数を取得 カメラが無いと0?
 int camNum = Camera.getNumberOfCameras();
 Log.d(LogTag, "nNumCamera = " + camNum);

 // カメラの作成
 int id = 0; // 0:Out, 1:Inカメラだった
 camera = Camera.open(id);

 // カメラにSurfaceHolderをセット
 camera.setPreviewDisplay(holder);

 // プレビューの開始
 camera.startPreview();

 // カメラの停止
 camera.stopPreview();
 camera.release();

2012年1月27日金曜日

ghostTown

街生成スクリプトが 0.31にバージョンアップしていた
以前のバージョンを実行、使い方が?? ど忘れ・・・

Show Guideボタンでガイド表示
平面などを配置して
Setupボタン -> Buildボタンで街生成

生成結果

エラーが出る場合、Materialタブの Update GTMatLibボタンを押す

描画結果

SQLiteのRTreeを使用してみる

sqliteからソースを取得
プリプロセッサの定義に SQLITE_ENABLE_RTREE を追加してライブラリを作成

#include <stdio.h>
#include <sqlite3.h>

// SELECTのコールバック関数
static int SelectCallbackFunc(void* option, int columnCount, char** columnValues, char** columnNames) {
    for(int i = 0; i < columnCount; ++i) {
        printf("| %s %s |", columnNames[i], columnValues[i]);
    }
    printf("\n");
    return 0;
}

// SQL文の実行
int ExecSQL(sqlite3* db, const char* sql, sqlite3_callback cb) {
    char* pStr = NULL;

    if(sqlite3_exec(db, sql, cb, NULL, &pStr) != SQLITE_OK) {
        fprintf(stderr, "Error %s %d: %s %s\n", __FILE__, __LINE__, pStr, sql);
        return -1;
    }
    return 0;
}

int main(int argc, char* argv[]) {
    sqlite3* pDB = NULL;

    const char* fname = ":memory:";     // メモリに作成
//  const char* fname = "data.db";      // ファイルに作成

    // DBを開く
    if(sqlite3_open(fname, &pDB)) {
        fprintf(stderr, "Error %s %d: %s\n", __FILE__, __LINE__, sqlite3_errmsg(pDB));
        sqlite3_close(pDB);
        return -1;
    }

    // テーブルの作成 RTreeを使用
    ExecSQL(pDB, "CREATE VIRTUAL TABLE tbl_index USING rtree( id, minX, maxX, minY, maxY, minZ, maxZ );", NULL);

    // テーブルにデータを追加
    ExecSQL(pDB, "INSERT INTO tbl_index VALUES( 1, -100.0, -50.0, 30.0, 50.0, -50.0, -20.0 );", NULL);
    ExecSQL(pDB, "INSERT INTO tbl_index VALUES( 2, -50.0, -10.0, 30.0, 31.35, -50.0, -40.0 );", NULL);
    ExecSQL(pDB, "INSERT INTO tbl_index VALUES( 3, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 );", NULL);
    ExecSQL(pDB, "INSERT INTO tbl_index VALUES( 4, 100.0, 110.0, 40.0, 56.2, -50.0, -20.0 );", NULL);
    ExecSQL(pDB, "INSERT INTO tbl_index VALUES( 5, 112.0, 119.0, 35.0, 36.51, 10.0, 18.0 );", NULL);

    // データの検索
    ExecSQL(pDB, "SELECT id FROM tbl_index WHERE minX>=100.0 AND maxX<=110.0;", SelectCallbackFunc);
    ExecSQL(pDB, "SELECT id FROM tbl_index WHERE minX>=-5.0 AND maxX<=5.0 AND minZ>=-5 AND minZ<=5;", SelectCallbackFunc);
    ExecSQL(pDB, "SELECT id FROM tbl_index WHERE minX>=150.0;", SelectCallbackFunc);

    // DBを閉じる
    sqlite3_close(pDB);

    return 0;
}

実行結果
| id 4 |
| id 3 |

2012年1月26日木曜日

MAXScript ノードの列挙


g_tabnum = 0    -- タブ数

-- タブ文字列を取得する num: タブ数
fn GetTab num = 
(
 t = ""
 for i = 1 to num do
 (
  t += "\t"
 )
 return t
)

-- 再帰関数でノードを列挙する
fn EnumNode n =
(
 t = GetTab g_tabnum
 g_tabnum += 1
 
 for n in n.children do
 (
  -- クラス名の取得
  cname = getClassName n
--  format "%className: %\n" t cname
  if cname == "Bone" then
  (
   -- ボーン名を出力する
   format "%boneName: %\n" t n.name
  )
  
  EnumNode n  -- 再帰処理
 )
 g_tabnum -= 1
)

-- ノードの列挙
EnumNode rootNode

MAXScript ファイルにバイナリ形式のデータを書き出す


-- Floatの大きな値
BIG_FLOAT = 1.0e32

-- AABB
struct AABB
(
 vMin,
 vMax
)

-- AABBを取得
fn GetAABB =
(
 local v = AABB()
 v.vMin = [ BIG_FLOAT, BIG_FLOAT, BIG_FLOAT ]
 v.vMax = [-BIG_FLOAT, -BIG_FLOAT, -BIG_FLOAT]
 return v
)

-- binStreamにPoint3を書き込む
fn WritePoint3 bstream v =
(
 WriteFloat bstream v.x
 WriteFloat bstream v.y
 WriteFloat bstream v.z
)

-- ファイルにAABBの値を書き込む
fn WriteAabbToFile filePath aabb =
(
 file = fopen filePath "wb"
 
 WritePoint3 file aabb.vMin
 WritePoint3 file aabb.vMax 
 
 fclose file
)


-- ファイルにデータを書き込むテスト
fname = "test.bin"   -- ファイル名
fdir = (GetDir #export)  -- ファイルを書き込むディレクトリ

fpath = fdir + "\\" + fname

aabb = GetAABB()

aabb.vMin.x = 8.0
aabb.vMax.z = 0.0

WriteAabbToFile fpath aabb

2012年1月25日水曜日

MAXScript ルートボーンの移動アニメを変更してみる


/*
    トラック内のキーの値を変更してみるテスト
 */
fn Test_TrackView =
(
 format "Test start\n"

 -- トラック選択ダイアログを表示する
 theInt = 0    -- ダイアログのオプション用変数
 theInt = bit.set theInt 1 true       --animated tracks only
-- theInt = bit.set theInt 3 true       --display selected nodes only

 -- Track View Pick Dialogを表示
 tvp = trackview.pickTrackDlg options:theInt

 if tvp == undefined then return undefined

 -- 選択ノードのsubAnimを取得
 a = tvp.anim 
 if a == undefined  then return undefined


 -- Transformを選択してOKクリックだと3 Transform/Positionを選択した場合0
 format "a.numSubs %\n" a.numSubs -- 選択ノードの子ノード数が返った

 for i = 1 to a.numSubs do
 (
  -- 子ノードの名前の取得
  n =  getSubAnimName a i
  format "name %\n" n

  -- コントローラーの取得
  c = a[i].Controller
  if c != undefined  then
  (
   -- コントローラーからキーの配列を取得
   k = c.keys
   --kp = k[#position]      -- ERROR
   --format "kp %\n" kp[3].value

   format "k.count %\n" k.count   -- キーフレーム数が返った

   -- MAXKey
   --format "MaxKey %\n" k[2]

   --if n == "#position" then
--   if 0 == stricmp n "#position" then  -- 実行されない
   if 0 == stricmp n "position" then  -- #がいらない
   (
    format "POSITION\n"
    -- 移動アニメを無効にしてみるテスト  変更できた
    for j = 1 to k.count do
    (
     k[j].value.z = 0.0
    )
   )

   format "key value %\n" k[2].value  -- キーの値が出力された
  )
 )

 format "tvp.name %\n" tvp.name  -- 選択したオブジェクトの名前?

 format "tvp.subNum %\n" tvp.subNum -- subAnimの数

 format "Test end\n"
)

-- Test関数の実行
Test_TrackView()


Unity キーフレームアニメ


 // 空のアニメーションカーブを作成
 AnimationCurve animCurve = new AnimationCurve();

 // キーフレームの追加
 animCurve.AddKey( new Keyframe(0.0f, 1.0f) );
 animCurve.AddKey( new Keyframe(2.0f, 0.1f) );

 // アニメーションカーブの値を取得
 print(animCurve.Evaluate(0.0f)); // 1.0
 print(animCurve.Evaluate(1.25f)); // 0.3847657
 print(animCurve.Evaluate(2.0f)); // 0.1
 print(animCurve.Evaluate(2.5f)); // 0.1


KeyframeのinTangentとoutTangentの値は0