習作として、それっぽいモノを作ってみました。
jillさんの言う
>1.先ず画像の4辺のサイズ変更が出来るかどうか現時点で分からないので、
>3D関係でテクスチャとして貼り付けてみる。
>2.マウス位置を取得して、カメラのアングルが変わるようにしてみる。
はできてます。
が、3、4については、当たり判定云々が非常に面倒くさいので省略。スイマセン。
まあ、各所にコメント残してますんで、パワーアップさせたければどうぞ。
;http://www.airtightinteractive.com/projects/tiltviewer/app/ っぽいサンプル
;表示できる画像の最大数は9個
;10個以降は上書きされる
;スペースキーorエンターキーで画像ファイルを開く
#uselib "user32.dll"
#func ScreenToClient "ScreenToClient" int, int, int
#include "hgimg3.as"
; 初期設定
;
#define sX 640 ;クライアントエリアxサイズ
#define sY 480 ;クライアントエリアyサイズ
#define sL sX ;クラアントエリアの長辺の長さを指定
; #define radLimit 0.785398 ;限界角度(マウスがクライアントエリアの端にあるときの角度)(π/4=45°)
#define radLimit 1.047198 ;限界角度(π/3=60°)
; #define radLimit 1.570796 ;限界角度(π/2=90°)(お好みでどれでも)
#define disCam 25.0 ;原点からのカメラ距離
cposX = 0.0 ;カメラx位置(初期=0)
cposY = 0.0 ;カメラy位置(初期=0)
cposZ = disCam ;カメラz位置(初期=原点からのカメラ距離)
iPic = 0 ;表示した画像の数(初期=0)
iPic_backup = 0 ;iPicのバックアップ(初期=0)
count = 0 ;表示アニメーションのフレームカウント(初期=0)
; ウインドウ初期化
;
screen 0, sX, sY, 0
title "3D画像ビューワ"
cls 4 ;背景は黒
; hgimg3初期化
;
hgini
; カメラ初期化
;
setpos HGOBJ_CAMERA, cposX, cposY, cposZ
cammode CAM_MODE_LOOKAT ;カメラを注視モードに設定(デフォルトで座標(0,0,0)を注視する)
*main
; メインルーチン
;
; フレーム描画
;
hgdraw ;描画
hgsync 15 ;時間待ち
; マウス位置からカメラ位置設定
;
POINT = ginfo_mx, ginfo_my ;スクリーン座標をPoint構造体に格納
ScreenToClient hwnd, varptr(POINT) ;クライアントエリア座標へ変換
if (Point.0<0) | (Point.0>sX) | (Point.1<0) | (Point.1>sY) {
;マウスがクライアントエリア外ならカメラを初期位置に戻す
cposX = 0.0
cposY = 0.0
cposZ = disCam
} else {
;マウスの座標から極座標を設定し、直交座標に変換
cposX = disCam*sin(double(Point.0-sX/2)/double(sL/2)*radLimit)*cos(double(Point.1-sY/2)/double(sL/2)*radLimit)
cposY = disCam*sin(double(Point.1-sY/2)/double(sL/2)*radLimit)
cposZ = disCam*cos(double(Point.0-sX/2)/double(sL/2)*radLimit)*cos(double(Point.1-sY/2)/double(sL/2)*radLimit)
}
setpos HGOBJ_CAMERA, cposX, cposY, cposZ ;カメラ位置設定
; 表示アニメーション
;
if iPic_backup = iPic {
stick key
if (key&16) | (key&32) : gosub *onOpenFile ;スペースキーまたはエンターキーでファイルを開くサブルーチンへ
} else : gosub *onDisplay ;表示アニメーションのサブルーチンへ
goto *main
*onOpenFile
; ファイルを開くサブルーチン
;
buffer 1
dialog "bmp;*.jpg;*.gif;*.ico", 16
if stat = 0 : return ;キャンセルされたらreturn
picload refstr ;いったんbufferに読み込んで画像サイズを取得
sPicX = double(ginfo(12))
sPicY = double(ginfo(13))
gsel 0, 2 ;これをしないとhwndがID1のウィンドウのものになってしまう(ScreenToClientに支障が出る)
gsel 0, 1
texload refstr ;テクスチャをロード
if sPicX < sPicY { ;縦長画像の場合
addplate idMdl, 0, 4.0/sPicY*sPicX, 4.0, 0, 0, sPicX, sPicY, stat
} else { ;横長画像の場合
addplate idMdl, 0, 4.0, 4.0/sPicX*sPicY, 0, 0, sPicX, sPicY, stat
}
if iPic < 9 { ;表示画像が9個以下ならオブジェクトを登録
regobj idObj.iPic, idMdl, 0
} else { ;表示画像10個目以降はオブジェクトの表示モデルを変えるだけでよい
setobjmodel idObj.(iPic\9), idMdl
}
setpos idObj.(iPic\9), ((iPic\9)\3-1)*5, ((iPic\9)/3-1)*5, 5 ;座標設定
setefx idObj.(iPic\9), 0
iPic ++ ;カウントをインクリメント
return
*onDisplay
;表示アニメーションのサブルーチン
;
if count = 0 : count = 25 ;カウント設定
addpos idObj.(iPic_backup\9), 0, 0, -0.2 ;座標加算
addefx idObj.(iPic_backup\9), 10.24 ;アルファ合成値加算
count -- ;カウントをデクリメント
if count = 0 : iPic_backup = iPic ;カウント終了でiPic_backupを更新
return
構想に一日、製作に一日。長い?短い?
問題点は、
モデルを削除できないので、ファイルを開くたびにメモリを食ってる気がする。
hgimg3のevent関係の命令がわからない(汗)
あとはもちろん当たり判定です。
蛇足ですが…、
作っていて、正直、hgimg3に極座標計算を実装してほしいと思いました。