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 |