Embarcadero FireMonkey 3D завъртане и мащабиране на камерата

Търся пример за завъртане на камерата и мащабиране в FireMonkey 3D. Като използвате левия бутон на мишката, за да завъртите камерата около сцената и използвайте колелцето на мишката, за да увеличите и намалите мащаба.

Може ли някой да ми помогне?


person user706420    schedule 29.08.2012    source източник
comment
Едно нещо, за което трябва да следите, е, че може да се наложи да деактивирате тестването на удари на фонови обекти, за да може прозорецът за изглед да получава събитията от мишката.   -  person GrandmasterB    schedule 07.09.2018


Отговори (2)


Следният формуляр показва проста демонстрация на това, просто запазете .fmx и .pas файловете и добавете формуляра към FMX приложение. Ключовите части са камерата и вложеният светлинен обект на отделни оси X & Y спрямо DummyObject, който е целта на камерата. Наличието на X & Y като отделни фиктивни обекти прави въртенето вертикално и хоризонтално, което е желателно в някои ситуации. Можете също така да обедините обектите DummyX & DummyY в един обект DummyXY, което ще даде по-реален стил на въртене, но ще зависи от вашите нужди относно това кой е за предпочитане.

MainForm.pas:

unit MainForm;

interface

uses
  FMX.Forms, FMX.Materials, System.Math.Vectors, FMX.Types3D, FMX.Objects3D, FMX.Controls3D, FMX.Viewport3D,
  System.Classes, FMX.Types, FMX.Controls, FMX.Layouts, FMX.MaterialSources, System.Types, System.UITypes;

type

  TForm1 = class(TForm)
    Viewport3D: TViewport3D;
    DummyX: TDummy;
    DummyObject: TDummy;
    CameraZ: TCamera;
    Light1: TLight;
    LayoutMain: TLayout;
    DummyY: TDummy;
    Cone1: TCone;
    LightMaterialSource1: TLightMaterialSource;
    procedure Viewport3DMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
    procedure Viewport3DMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
    procedure Viewport3DMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; var Handled: Boolean);
  private
    FDown: TPointF;
    procedure DoZoom(aIn: Boolean);
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

const
  CAMERA_MAX_Z = -2;
  CAMERA_MIN_Z = -200;
  ZOOM_STEP = 2;

procedure TForm1.DoZoom(aIn: Boolean);
var
  newZ: Single;
begin
  if aIn then
    newZ := CameraZ.Position.Z + ZOOM_STEP
  else
    newZ := CameraZ.Position.Z - ZOOM_STEP;

  if (newZ < CAMERA_MAX_Z) and (newZ > CAMERA_MIN_Z) then
    CameraZ.Position.Z := newZ;
end;

procedure TForm1.Viewport3DMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
begin
  FDown := PointF(X, Y);
end;

procedure TForm1.Viewport3DMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
begin
  if (ssLeft in Shift) then
  begin
    DummyX.RotationAngle.X := DummyX.RotationAngle.X - ((Y - FDown.Y) * 0.3);
    DummyY.RotationAngle.Y := DummyY.RotationAngle.Y + ((X - FDown.X) * 0.3);
    FDown := PointF(X, Y);
  end;
end;

procedure TForm1.Viewport3DMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; var Handled: Boolean);
begin
  DoZoom(WheelDelta > 0);
end;

end.

MainForm.fmx:

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 592
  ClientWidth = 713
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  DesignerMasterStyle = 0
  object LayoutMain: TLayout
    Align = Client
    Size.Width = 713.000000000000000000
    Size.Height = 592.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 2
    object Viewport3D: TViewport3D
      Align = Client
      Camera = CameraZ
      Size.Width = 713.000000000000000000
      Size.Height = 592.000000000000000000
      Size.PlatformDefault = False
      UsingDesignCamera = False
      OnMouseDown = Viewport3DMouseDown
      OnMouseMove = Viewport3DMouseMove
      OnMouseWheel = Viewport3DMouseWheel
      object DummyX: TDummy
        Width = 1.000000000000000000
        Height = 1.000000000000000000
        Depth = 1.000000000000000000
        object DummyY: TDummy
          Width = 1.000000000000000000
          Height = 1.000000000000000000
          Depth = 1.000000000000000000
          object CameraZ: TCamera
            AngleOfView = 45.000000000000000000
            Target = DummyObject
            Position.Z = -20.000000000000000000
            Width = 1.000000000000000000
            Height = 1.000000000000000000
            Depth = 1.000000000000000000
            object Light1: TLight
              Color = claWhite
              LightType = Directional
              SpotCutOff = 180.000000000000000000
              Width = 1.000000000000000000
              Height = 1.000000000000000000
              Depth = 1.000000000000000000
            end
          end
        end
      end
      object DummyObject: TDummy
        Width = 1.000000000000000000
        Height = 1.000000000000000000
        Depth = 1.000000000000000000
        object Cone1: TCone
          Width = 1.000000000000000000
          Height = 1.000000000000000000
          Depth = 1.000000000000000000
          SubdivisionsCap = 3
          MaterialSource = LightMaterialSource1
        end
      end
    end
  end
  object LightMaterialSource1: TLightMaterialSource
    Diffuse = claWhite
    Ambient = xFF202020
    Emissive = claNull
    Specular = xFF606060
    Shininess = 30
    Left = 436
    Top = 56
  end
end

Извадих това от някъде демо, но работи чудесно за моите нужди. Трябва да работи за Delphi XE5 и по-нови.

person Rick Wheeler    schedule 04.04.2016

Можете да завъртите камерата с плъзгане и да увеличите с колело. Важното е, че въртенето по различни оси трябва да се обработва върху различни вложени обекти, така че изчислението на въртенето да се отразява едно на друго, както очакваме в реалния свят.

person mehmed.ali    schedule 20.11.2012
comment
@GlenMorse ето първоначално публикуваната връзка: delphiscience.wordpress.com/2012/11/14/ - person Andrew Barber; 31.07.2013
comment
Уау, отговор, който изобщо не помага. Какво ще кажете за малко код? Всеки идиот знае, че това трябва да бъде влачене и колелце на мишката. - person Flash Thunder; 08.06.2014