前回に引き続き、UC-win/Road SDKに収録されているサンプルプログラムについて、ソースコードを用いた解説を行います。今回は、モデルのインポートやシミュレーションでのインタラクション、カスタムイベントアクションと、メイン入力画面の編集などといった項目を扱います。
|
|
モデルのインポート ModelImportPlugin |
|
この例では、UC-win/Roadで3Dモデルを作成する方法について説明します。モデルの各頂点に対する位置情報、法線ベクトル、テクスチャ座標をテキストファイルで読み込んで、その情報を基にモデルを作成し、シーン上へ配置します。最後にそれを上空から俯瞰します。
ツールメニューから「Import Simple Model...」を選択すると、テクスチャなしのモデルをインポートします。また、「ImportTextures
Model...」を選択すると、テクスチャ付きモデルを読み込みます。
■1:3Dモデルの構成
3Dモデルは、ポリゴン(多角形の平面データ)から構成されています。
3Dモデルは、この三角形ポリゴンの各頂点の3D座標の集合体によって構成されています。UC-win/Roadでは、ポリゴンの座標を左回りに設定しています。
■2:テクスチャを含む場合
テクスチャを含む場合は、三角形ポリゴンの各頂点に、3次元座標以外に法線ベクトル、テクスチャ座標を設定します。
図ではそれぞれ(1)が頂点座標、(2)が法線ベクトル【注7】、(3)がテクスチャ座標【注8】を表します。
■3:モデルの読み込み
UC-win/Road に3Dモデルを読み込むには、プロジェクトに新規に3Dモデルのオブジェクトを生成してからポリゴン情報を追加します。
関連するインタフェースは以下の通りです。
//3Dモデルのオブジェクト生成
function IF8ProjectForRoad.CreateThreeDModel :
IF8ThreeDeeStudio;
//グループの追加(ポリゴン情報を追加する際のグループとして使用する)
function IF8ThreeDeeStudio.AddGroup : integer;
//ポリゴン情報の追加(テクスチャがない場合)
procedure IF8ThreeDeeStudio.AddTrianglesGroup
(groupIndex : integer; triangles :
F8TriangleArrayType{*});
groupIndex : 追加するポリゴンが属するグループ(部品、レイヤ)
triangles : ポリゴン座標情報
//ポリゴン情報の追加(テクスチャがある場合)
procedure IF8ThreeDeeStudio.AddTexturedTrianglesGroup
(groupIndex : integer;triangles :
F8TexturedTriangleArrayType{*});
groupIndex : 追加するポリゴンが属するグループ(部品、レイヤ)
triangles : ポリゴン座標情報
F8TriangleArrayType
F8TriangleArrayType = arrau of F8TriangleType;
F8TriangleType = array[1..3] of GLPointType;
F8TexturedTriangleArrayType
F8TexturedTriangleArrayType = array of F8TexturedTriangle;
F8TexturedTriangle = record
vertex: F8TriangleType;
normal: F8TriangleType;
textureUV: F8TriangleType;
end; |
■4:追加した3Dモデルの配置
UC-win/Roadへ登録したモデルを配置するには、配置するモデルのインスタンスを生成して座標情報を設定します。
使用するインタフェースは以下の通りです。
function IF8ProjectForRoad.MakeModel(currentModel :
IF8ThreeDeeStudio;
xx: double; yy : double) : IF8ModelInstance;
currentModel : これから配置するモデル
xx : 配置するモデルのX座標(東西方向、東向き+)
yy : 配置するモデルのZ座標(南北方向、南向き+) |
|
インタラクションの例 InteractionSamplePlugin |
|
このサンプルでは、のシミュレーションやユーザによる相互作用についての例を示します。ツールメニューから「Display
Logs…」を選択すると、運転時のログが取得できます。「Display userinputs…」を選択すると、メイン画面におけるマウス、キーボード、ゲームコントローラのイベント取得が可能です。
まず、以下のインタフェースにより道路に縦断線形を追加します。
■1:モデル、道路クリック時のコールバック関数の登録
メイン画面上のモデルや道路をクリックしたときに処理するコールバック関数を登録します。モデルをクリックしたときはそのインスタンスが、道路をクリックしたときはその道路やクリックした位置の情報がコールバック関数を通して返ってきます。
var
method : Tmethod;
ApplicationService : IF8ApplicationService;
begin
//モデルクリック用コールバック関数の登録
FormMainModelClickFunc(method) := ModelClick;
ApplicationService.RegisterEventHandler
( _plgFormMainModelClick, method);
//道路クリック用コールバック関数の登録
FormMainRoadClickFunc(method) := RoadClick;
ApplicationService.RegisterEventHandler
( _plgFormMainRoadClick, method);
end;
//モデルクリック時のコールバック関数
function ModelClick
(modelInstance: IF8Instance): boolean;
modelInstance : クリックしたモデルのインスタンス{*}
//道路クリック時のコールバック関数
function RoadClick
( c o n s t r o a d : I F 8 R o a d ; c o n s t d i s t a n c e , offset:
double;const leftSide,carriageway: boolean): boolean;
road : クリックした道路
distance : 線形上起点からの距離
offset : 断面方向端部からのオフセット
leftSide : True : 道路左側 、 False : 道路右側
carriageway : True : 車道をクリック、 False : 車道以外を
クリック |
■2:ログ出力
ログ出力するには、ログ出力を制御するLogServerにアクセスする必要があります。
取得したlogServerにログデータ取得用のコールバック関数を登録します。このOnLogがフレームごとに呼ばれます。
var
applicationSerive : IF8ApplicationServices;
logServer : IF8LogServer;
begin
logServer := applicationService.GetLogServer;
end; |
OnLogServerPushLogProc(method) := OnLog;
logServer.RegisterOnLogProcedure(method);
//コールバック関数
procedure OnLog(dTimeInSeconds: double; instance:
IF8DBObject; group: TlogExportOption);
dTimeInSeconds:フレーム間隔
instance :ログオブジェクト
group :オブジェクトのタイプ
_leoUsersVehicle :ユーザ運転車両
_leoDriverInFront:ユーザと同じ車線を走行している前方車両
_leoSurroundingMovingObjects :ユーザ運転車両とある範囲内に有る車両
_leoOtherMovingObjects :上記範囲外に有るログターゲットの車両 |
OnTimeStep
フレーム描画直前に発生するイベントです。このコールバック関数によりOnLogが呼ばれるときの現在の時間がわかります。
TimeStepProc(method) := OnTimeStep;
ApplicationService.RegisterEventHandler( _plgTimeStep, method);
procedure OnTimeStep(dTimeInSeconds: double);
var
t : TLargeInteger;
begin
if logging then
begin
QueryPerformanceCounter(t);
currentTime := (t - startTime) / frequency;
end;
end; |
ログ開始、終了
ログ出力を開始、終了するインタフェースは以下の通りです。
var
logServer : IF8LogServer;
begin
//ログ出力開始
logServer.StartLogs;
//ログ出力終了
logServer.StopLogs;
end; |
ログ取得の実際
以下にログ取得の例を示します。
procedure TFormLogDisplay.OnLog(dTimeInSeconds:
double; instance: IF8DBObject; group: TLogExportOption);
var
vehicleLogs : IF8VehicleLogs;
movingModel : IF8InstanceLogs;
logRecord : PLogRecordType;
begin
logRecord := nil;
//instanceがIF8VehicleLogs(車輌)の場合にvehicleLogs変数でログ情報にアクセス
if Supports(instance, IF8VehicleLogs, vehicleLogs)
then
begin
logRecord := NewLogRecord;
logRecord.time := currentTime;
// OnTimeStep()で取得したフレーム間隔
..
logRecord.yawAngle := vehicleLogs.yawAngle;
logRecord.pitchAngle := vehicleLogs.pitchAngle;
logRecord.rollAngle := vehicleLogs.rollAngle;
logRecord.direction := vehicleLogs.direction;
...
//ログ取得終了後、外部ファイル等へ出力
...
end;
end; |
|
カスタムWaypoint・カスタムイベントアクション |
|
このサンプルでは、運転シミュレーションログ出力とカスタムWaypoint、シナリオにおけるカスタムイベントアクションの例を示します。ここではWayPointにしぼって解説します。
■1:WayPoint(動作制御点)とは?
Waypointとは、運転、走行する車両が設定した位置を通過した際、指定した車両、可動モデルのコマンドを実行させる点のことです。
車両の速度を変更したり、任意の動作を実行します。
■2:コマンドの追加
〜 TwaypointCommandAttribute構造体
任意のコマンドを追加するには、TWaypointCommandAttribute型の構造体に必要項目を定義し、所定の手続きによってUC-win/Roadへ登録します。この構造体は、「動作制御点の編集」画面で追加したコマンドを選択した際、コマンド以外の各項目へのアクセス許可を設定します。
コマンド名 |
説明 |
isDirectionEditable |
True:「方向」にアクセス可能。
False:「方向」にアクセス不可能 |
isLaneEditable |
True:「車線」にアクセス可能。
False:「車線」にアクセス不可能 |
isInstanceEditable |
True:「対象」にアクセス可能。
False:「対象」にアクセス不可能 |
isActivateEditable |
True:「機能」にアクセス可能。
False:「機能」にアクセス不可能 |
isArg1Editable |
True:「備考1」にアクセス可能。
False:「備考1」にアクセス不可能 |
isArg2Editable |
True:「備考2」にアクセス可能。
False:「備考2」にアクセス不可能 |
Arg1Min |
備考1の最小値 |
Arg1Max |
備考1の最大値 |
Arg2Min |
備考2の最小値 |
Arg2Max |
備考2の最大値 |
コマンドの追加方法
コマンド追加は、以下のApplicationService のインタフェースを使用します。
procedure IF8ApplicationService.AddCommandForWaypo
intEditor(Item : PWaypointCommandAttribute);
ここで、
PwaypointCommandAttribute = ^TwaypointCommandAttribute; |
■3:コールバック関数の追加
追加したWaypointコマンドを動作制御点の編集画面で選択したときのコールバック関数を登録します。
この登録したイベントハンドラはプラグイン終了時に開放しなければなりません。
//動作制御点の編集画面で追加したときのコマンドに反応するイベントハンドラ
procedure ActivateWayPointCommand(waypointCommands
Info : WaypointCommandInfoArray※12);
//登録方法
var
method : Tmethod;
begin
...
//イベントハンドラの登録
ActivateWayPointCommandProc(method) :
= ActivateWayPointCommand;
ApplicationSerivice.RegisterEventHandler(_plgWayPo
intDoOneCommand,method);
...
end;
//イベントハンドラの登録解除
ActivateWayPointCommandProc(method) :
= ActivateWayPointCommand;
ApplicationSerivice.UnRegisterEventHandler(_plgWay
PointDoOneCommand,method); |
WaypointCommandInfoArray
WaypointCommandInfoArray
= array of WaypointCommandInfoType;
WaypointCommandInfoType = record
//Waypointが追加される道路
curve: IF8DBObject;
//コマンドを有効にするインスタンスのタイプID
instanceID: Integer;
//起点からWaypointまでの距離
distance: double;
//コマンド名称
command: WideString;
//コマンドを有効にした実際のオブジェクトへのポインタ
recipient: ISupportWaypointCommands;
end; |
|
メイン入力画面の編集StationPointEditorPlugin |
|
このサンプルでは、UC-win/Roadの画面編集を行います。
■1:画面に任意のコントロールを追加する
編集画面が表示される際に発生するコールバック関数を利用して画面に任意のコントロールを追加できます。
任意のコントロールを追加するには、対象となる画面の基準となるコントロールを探し、追加するコントロールの表示位置などを設定します。
目的のコントロールのLeft、Top、Width、Height から、必要サイズ分
TForm のWidth、Height を広げる |
|
■2:コントロールの探索
コントロールの探索は大まかに以下のように記述します。
procedure FormRoadSideSignEditorShow( form :
TForm; theObject : IF8Sign );
var
i : integer;
ctrl : TControl;
pageControl: TPageControl;
tabSheet : TTabSheet;
begin
Assert(form.name = 'FormSignEditor');
pageControl := nil;
//TFormに直接貼られたコントロールを探索
for i := 0 to form.ControlCount - 1 do
begin
ctrl := form.Controls[i]; //探索がTPageControlだったら
そのポインタを取得して探索を抜ける。
if (ctrl is TPageControl) and (ctrl.Name =
'PageControl') then
begin
pageControl := ctrl as TPageControl;
break;
end;
end;
tabSheet := nil;
if Assigned(pageControl) then
begin
//目的のページを探索
for i := 0 to pageControl.PageCount - 1 do
begin
//目的のページだったら、そのSheetを取得する。
end;
...//以下目的のコントロールにたどり着くまで、順々に繰り返す。
...//コントロールにたどり着いたら、必要なサイズ分TFormのWidth、Heightを広げる。
...//追加するコントロールを貼り付け、必要なプロパティ、イベントハンドラを設定する。 |
このサンプルでは、道路縦断変化点、断面、道路付属物の位置設定なども扱っていますので、詳細はぜひ『土木建築エンジニアのプログラミング入門』でご覧下さい(Amazonでも購入可能です)。
体験セミナーのお知らせ
|
|
(Up&Coming '12 新年号掲載) |
|
|
>> 製品総合カタログ
>> プレミアム会員サービス
>> ファイナンシャルサポート
|