FireMonkey の 3D Object をコードで記述したい

解決


PENTA_MAX  2014-01-12 10:07:02  No: 45856

例えば、FireMonkey の、3D で新規作成します。
3D Scene の Dummy, ProxyObject、3D Shapes の Cube を
ツールパレットからフォームに配置するのではなく、
Dummy, ProxyObject, Cube をコードで記述し描画たいのですが
分かりません。(多数の 3D Object をコードで書いて描画したいのです)
Objectの樹形図の関係は、

Dummy
|
+-Cube
|
+-ProxyObject

で、ProxyObject に Cube を指定します。
Delphi XE5 付属のサンプルコードを見たのですが、
Cube または ProxyObject を1つだけ書く場合は、
分かりましたが、上の樹形図の場合の記述の仕方が
分かりません。(Webも調べてみました。Dockwikiも見ました)
(Light と LightMaterialSource は、ツールパレットからフォームに配置しています)

Dummy, ProxyObject, Cube をコードで記述する方法を教えて頂けないでしょうか。

詳しい方がいらっしゃいましたらご指導の程よろしくお願い致します。


PENTA_MAX  2014-01-25 20:52:40  No: 45857

まず Dummy と Cube(Object) だけで試してみました。
FireMonkey 3D で新規作成します。
フォームに Light と LightMaterialSource を配置します。
フォームをダブルクリックして、uses 節に FMX.Objects3D を手入力で追加します。
procedure と begin の間に、Dummy と Cube を以下のように定義します。
begin と end の間に以下のように書きました。
コンパイルはとおったのですが、Cube が表示されません。
何がいけないのでしょうか。
詳しい方がいらっしゃいましたらご指導の程よろしくお願い致します。

使用環境
  Delphi XE5 Pro Update2
  Win7 Pro 64bit SP1

procedure TForm1.Form3DCreate(Sender: TObject);
var
  Img_Dummy,Img_Cube: TControl3D;

begin
  Img_Dummy := TDummy.Create(nil);
  Img_Cube := TCube.Create(nil);
  Img_Cube.Parent := Img_Dummy;
  TCube(Img_Cube).MaterialSource := LightMaterialSource1;
  Img_Cube.SetSize(2, 2, 2);
  Img_Cube.Position.Point := Point3D(1, 1, 1);
end;


Mr.XRAY  2014-01-27 01:34:01  No: 45858

Delphi FireMonkey 3D アプリケーションですね.

ビジュアルなコンポーネントは Parent プロパティを設定しないと,表示場所が不定になってしまいます.
Parent で指定するコントロールは,もちろん,ビジュアルでなければ当然見えません.

動作確認は,Widows 7 U64(SP1) + Delphi XE5(UP2) - FireMonkey 3D アプリケーション

procedure TForm1.Form3DCreate(Sender: TObject);
var
  Img_Dummy : TDummy;  //ここも変更しました
  Img_Cube  : TCube;
begin
  //デフォルトの色だと画面で見えにくいので変更
  LightMaterialSource1.Diffuse := TAlphaColorRec.Green;

  Img_Dummy := TDummy.Create(nil);
  Img_Cube  := TCube.Create(nil);

  Img_Cube.Parent := Self;  // ここを変更(Selfは,ここではForm1のこと)
  TCube(Img_Cube).MaterialSource := LightMaterialSource1;
  Img_Cube.SetSize(2, 2, 2);
  Img_Cube.Position.Point := Point3D(1, 1, 1);
end;

他の方への参考です.(注: 今回のレス内容とは直接関係ありません)
FireMonkey は Delphi のバージョンよって少し違うところがあります.
詳しくは,以下の記事を参考にしてください.

[FireMonkey で使えるコンポーネントは? [Delphi Programming]]
http://ht-deko.minim.ne.jp/techf001.html


Mr.XRAY  2014-01-27 01:41:59  No: 45859

ゴメン,img_Dummy をつかうのね.

procedure TForm1.Form3DCreate(Sender: TObject);
var
  Img_Dummy : TDummy;
  Img_Cube  : TCube;
begin
 //デフォルトの色だと画面で見えにくいので変更
  LightMaterialSource1.Diffuse := TAlphaColorRec.Green;

  Img_Dummy := TDummy.Create(nil);
  Img_Cube  := TCube.Create(nil);

  Img_Dummy.Parent:= Self;
  Img_Cube.Parent := Img_Dummy;

  TCube(Img_Cube).MaterialSource := LightMaterialSource1;
  Img_Cube.SetSize(2, 2, 2);
  Img_Cube.Position.Point := Point3D(1, 1, 1);
end;


Mr.XRAY  2014-01-27 02:54:45  No: 45860

今最初の質問の文章を読み直したら

>詳しい方がいらっしゃいましたらご指導の程よろしくお願い致します。

私は詳しくもないし,指導できる程の立場にもありません.
そういう者のレスであることを知っておいてくざい.

# Fire Monkey なんか,ほとんどの人が「初心者」に近いとは思いますが.


PENTA_MAX  2014-01-27 08:21:36  No: 45861

Mr.XRAY さん  ご指導ありがとうございました。

Cube が表示される事を確認しました。
今は、ProxyObject を追加し、自力で確認中です。


PENTA_MAX  2014-01-31 08:01:40  No: 45862

Proxy を追加して確認して見たのですが、
意図したものにならないのでご指導下さい。

下記のように、①②③④と Proxy を追加して、
Proxy の SourceObject を Cube にしています。
Cube と Proxy をずらして、2つの Cube が表示されるように
座標をずらしているのですが、F9 でコンパイルした場合、
10回中1回くらいは、2つの Cube(1つは Cube で、もう1つは、Proxy で Source した Cube  ) が表示され、
9回は、Proxy で記述した Cube が1つだけ表示されます。
(コンパイル後の exe を実行すると100% Proxy で記述した Cube が1つだけ表示されます。)

2つの Cube(1つは Cube で、もう1つは、Proxy で Source した Cube ) を
確実に表示するには、下記のコードをどう修正すればいいでしょうか。
今回は確認の為 Object の親子関係は、
下記のように Dummy ではなく、Self(3DForm)にしています。

Dummy
|
+-Cube
|
+-ProxyObject

分かる方がいらっしゃいましたら、ご指導の程よろしくお願い致します。

procedure TForm1.Form3DCreate(Sender: TObject);

  var
   Img_Dummy : TDummy;
   Img_Cube  : TCube;
//① Begin
   Img_Proxy : TProxyObject;
//① End

  begin

    LightMaterialSource1.Diffuse := TAlphaColorRec.Green;

    Img_Dummy := TDummy.Create(nil);
    Img_Cube  := TCube.Create(nil);
//② Begin
    Img_Proxy := TProxyObject.Create(nil);
//② End

    Img_Dummy.Parent := Self;
    Img_Cube.Parent  := Img_Dummy;

//③ Begin
    Img_Proxy.Parent := Self;
//③ End

    TCube(Img_Cube).MaterialSource := LightMaterialSource1;
    Img_Cube.SetSize(3, 3, 3);
    Img_Cube.Position.Point := Point3D(1, 1, 1);

//④ Begin
    TProxyObject(Img_Proxy).SourceObject := Img_Cube;
    Img_Proxy.SetSize(1, 1, 1);
    Img_Proxy.Position.Point := Point3D(5, 5, 1);
//④ End

  end;

作成手順

  ファイル
  新規作成
  FireMonkey デスクトップアプリケーション
  3D FireMonkey アプリケーション

  で作成します。

  フォームに Light と LightMaterialSource を配置します。
  フォームをダブルクリックして、uses 節に FMX.Objects3D を手入力で追加します。

使用環境
  Delphi XE5 Pro Update2
  Win7 Pro 64bit SP1


DEKO  2014-01-31 11:57:55  No: 45863

コード自体に問題があるようには思えませんね。

・お使いの Delphi は VM でなく実機で実行されていますか?
・ビデオカードのドライバは最新ですか?

もし、これでも直らないようであれば、
ふーさんが twitter でツイートしていた以下の件を試してみるとか。

[A unit to enable Direct2D in FireMonkey where possible]
http://itinerantdeveloper.blogspot.jp/2014/01/a-unit-to-enable-direct2d-in-firemonkey.html


PENTA_MAX  2014-02-01 20:23:36  No: 45864

>・お使いの Delphi は VM でなく実機で実行されていますか?
Mac上のVMではなく、Win7の実機で確認しています。

>・ビデオカードのドライバは最新ですか?
最新のものにしています。

もう一度よく下記のXE5付属のサンプルコードを確認してみます。
C:\Users\Public\Documents\RAD Studio\12.0\Samples\FireMonkey\Cubes


DEKO  2014-02-01 20:55:40  No: 45865

> もう一度よく下記のXE5付属のサンプルコードを確認してみます。
いえ、恐らくコード自体に問題はありません。

意図しているのは中央に緑の立法体、
その右横に小さな緑の立法体が表示されるというものですよね?

先のリンクの件は、
"要件を満たしていても Direct2D が選択されず GDI+ で描画されてしまう事がある" 
というのを回避する Tips です (XE4 / XE5)。

1.アーカイブをダウンロード
https://dws-terapixel-explorer.googlecode.com/archive/0d299dfd8af347bc469319441dffc8b1ba28c9b8.zip

2.自分のプロジェクトに FMXDirect2DFix.pas を追加。

3.プロジェクトファイル (*.dpr) の上に以下のコードを記述。
  FMXDirect2DFix.TryUseDirect2D;
  
これを試したらどうなりますか?


PENTA_MAX  2014-02-02 06:53:39  No: 45866

>意図しているのは中央に緑の立法体、
>その右横に小さな緑の立法体が表示されるというものですよね?

はい。そうです。

自分のプロジェクトのフォルダに FMXDirect2DFix.pas をコピペで追加し、
*.dpr の上に下記のように追加して見たのですが、エラーになってしまいます。

恐れ入りますがご指導の程よろしくお願い致します。

以下は、*.dpr の中身です。

FMXDirect2DFix.TryUseDirect2D;  // <------追加

program Project1;

uses
  FMX.Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.


PENTA_MAX  2014-02-02 09:35:32  No: 45867

すいません。失礼しました。訂正します。

教えて頂いた URL を確認して、

FMXDirect2DFix.pas をプロジェクトのフォルダにコピペし、

*.dpr を下記のように修正しました。

すると下記のエラーメッセージが出ます。
何がいけないのでしょうか。
恐れ入りますがご指導の程よろしくお願い致します。

[dcc32 エラー] Project1.dpr(12): E2029 宣言 が必要な場所に 識別子 'FMXDirect2DFix' があります
[dcc32 エラー] Project1.dpr(19): E2003 未定義の識別子 : 'FMXDirect2DFix'
[dcc32 エラー] Project1.dpr(19): E2066 演算子またはセミコロン (';') が必要です

program Project1;

uses
  FMX.Forms,
  Unit1 in 'Unit1.pas' {Form1};

//追加 Begin
  FMXDirect2DFix in 'C:\Users\adamoste\Desktop\TEST_Dummy_Cube_Proxy\FMXDirect2DFix.pas';
  ^^^^^^^^^^^^^^
//追加 End

{$R *.res}

begin

//追加 Begin
  FMXDirect2DFix.TryUseDirect2D;
                 ^^^^^^^^^^^^^^
//追加 End

  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.


DEKO  2014-02-02 09:49:30  No: 45868

メニューの [プロジェクト | プロジェクトに追加] で  FMXDirect2DFix.pas を追加してください。

  FMX.Forms,
  Unit1 in 'Unit1.pas' {Form1}; <- ここはカンマです
  FMXDirect2DFix in 'FMXDirect2DFix.pas';

uses のトコがカンマじゃなくてセミコロンで終了しちゃってます。


PENTA_MAX  2014-02-02 18:32:53  No: 45869

すいません。失礼しました。

ご指導して頂いたように修正して確認したのですが、

物体が2つ表示されず、ProxyObject の物体1つだけが表示されます。

*.dpr の中身

program Project1;

 uses
   FMX.Forms,
   Unit1 in 'Unit1.pas' {Form1}, //<--- ;を,に修正

 //追加 Begin
   FMXDirect2DFix in 'FMXDirect2DFix.pas'; //<--- 修正
 //追加 End

 {$R *.res}

 begin

 //追加 Begin
   FMXDirect2DFix.TryUseDirect2D;
 //追加 End

   Application.Initialize;
   Application.CreateForm(TForm1, Form1);
   Application.Run;
 end.


DEKO  2014-02-02 19:57:43  No: 45870

> 物体が2つ表示されず、ProxyObject の物体1つだけが表示されます。
無関係でしたか...。

他にやれる事と言ったら 

・Repaint してみる。
・TCamera を貼ってみる。

このくらいですかね?

[TCamera (Delphi FireMonkey Tips)]
http://ht-deko.minim.ne.jp/techf001_3d_scene.html#TCamera


PENTA_MAX  2014-02-03 08:43:07  No: 45871

解決しました。
完全コードではないかもしれませんが、
exe を実行すると、意図するものが100%再現しました。

今まで回答してくださった皆様ありがとうございました。

C:\Users\Public\Documents\RAD Studio\12.0\Samples\FireMonkey\Cubes の
For 文を正確に展開していれば正解でした。
(「For 文を正確に展開できてないね」と言われても仕方がありません。恥ずかしいです。)

Object を Create としたら Create と *.Position.Point := Point3D(x, x, x) の間に
他の Object の記述をすると NG のようです。

(DockWiki にもここまでの解説が欲しいなぁ。ユーザーの力不足と言われれば反論はできませんが・・・
MSのVSよりユーザー数が少ないぶんもうちょっとでいいから DockWiki に丁寧な解説が欲しいです。
DockWiki という事は、ユーザーが確認した事をユーザーの手で DockWiki に追加できるのでしょうか?
どこのHPでもいいので、ユーザーが確認した事をユーザーの手で記入できると便利ですね。
他人まかせのようで気が引けるのですが、小生はWEB作成の能力がないので、
Embarcadero さんか「Delphi ユーザー会」さんに対応して頂くと助かります。)

解決しましたので作成手順から書きます。

作成内容
  FireMonkey 3D デスクトップのフォームに、Dummy と ProxyObject を
  コードを記述して Cube を2個表示する。

作成手順

  ファイル
  新規作成
  FireMonkey デスクトップアプリケーション
  3D FireMonkey アプリケーション

  で作成。

  
  フォームに ツールパレットから、Light と LightMaterialSource を配置します。
  フォームをダブルクリックして、uses 節に FMX.Objects3D を手入力で追加します。

  ツールパレットから Dummy,Cube,ProxyObject を 3DForm に配置せず、
  コードを記述して作成描画する。

  Dummy,Cube,ProxyObject の親子関係。

  Dummy
  |
  +-Cube
  |
  +-ProxyObject

procedure TForm1.Form3DCreate(Sender: TObject);

var

   Img_Dummy : TDummy;
   Img_Cube  : TCube;
   Img_Proxy : TProxyObject;

begin

    LightMaterialSource1.Diffuse := TAlphaColorRec.Green;

    Img_Dummy := TDummy.Create(nil);
    Img_Dummy.Parent := Self;

    Img_Cube := TCube.Create(nil);
    Img_Cube.Parent := Img_Dummy;
    TCube(Img_Cube).MaterialSource := LightMaterialSource1;
    Img_Cube.SetSize(3, 3, 3);
    Img_Cube.Position.Point := Point3D(0, 0, 0);

    Img_Proxy := TProxyObject.Create(nil);
    Img_Proxy.Parent := Img_Dummy; // Self は NG
    TProxyObject(Img_Proxy).SourceObject := Img_Cube;
    Img_Proxy.SetSize(1, 1, 1);
    Img_Proxy.Position.Point := Point3D(5, 5, 1);

end;

使用環境
  Delphi XE5 Pro Update2
  Win7 Pro 64bit SP1


PENTA_MAX  2014-02-03 08:50:05  No: 45872

作成内容は、下記の内容に訂正します。

作成内容
  FireMonkey 3D デスクトップのフォームに、Cube を2個表示する。
  Dummy,Cube,ProxyObject は、コードで記述する。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加