Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Решение проблемы перемещения вершин GLScene под курсор мыши

Delphi , Графика и Игры , OpenGL

В статье рассматривается решение проблемы перемещения вершин в приложении 3D-моделирования, созданном с использованием библиотеки GLScene. Пользователь хочет перемещать вершины под курсором мыши, но сталкивается с проблемой, когда вершина не движется правильно.

Для решения этой проблемы автор кода предложил использовать подход, основанный на решении уравнения линии-плоскости. Чтобы найти точку пересечения, необходимо определить нормаль плоскости, точку на плоскости, начало луча и направление луча.

Нормаль плоскости можно получить из направления камеры, а точку на плоскости можно найти, преобразовав вершину из локальных координат в абсолютные. Начало луча может быть положением камеры или точкой на плоскости ближнего обзора, а направление луча может быть проекцией направления мыши.

После нахождения точки пересечения ее необходимо преобразовать обратно в локальные координаты.

Автор кода также отмечает, что возможно существуют более простые способы решения этой задачи в GLScene, но он не знаком с этой библиотекой.

Пример кода на Object Pascal (Delphi) для перемещения вершины под курсором мыши:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Math,
  GLWin32Viewer, GLCrossPlatform, GLBaseClasses, GLScene, GLColor, GLCanvas,
  GLVectorFileObjects, GLObjects, GLVectorTypes,
  GLCoordinates, GLFileObj, GLVectorGeometry;

type
  TForm1 = class(TForm)
    GLSceneViewer: TGLSceneViewer;
    GLScene1: TGLScene;
    GLLightSource1: TGLLightSource;
    GLCamera: TGLCamera;
    GLDummyCube1: TGLDummyCube;
    FreeForm: TGLFreeForm;
    GLLightSource2: TGLLightSource;
    procedure FormCreate(Sender: TObject);
    procedure GLSceneViewerMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure GLSceneViewerMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    procedure GLSceneViewerMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure GLSceneViewerPostRender(Sender: TObject);
  private
    IsVertexDragging: Boolean;
    MouseX, MouseY: Integer;
    VertexIndexToDrag: Integer;
    CenterPosition, LastPosition: TVector3f;
    function FindClosestPointIndex(Point: TVector3f): Integer;
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  FreeForm.LoadFromFile('E:\test2\Sphere.obj');
end;

function TForm1.FindClosestPointIndex(Point: TVector3f): Integer;
var
  i: Integer;
  NewPoint: TVector3f;
  BestDistance, TempDistance: Single;
begin
  BestDistance := 100000000000000;
  for i := 0 to FreeForm.MeshObjects[0].Vertices.Count - 1 do
  begin
    NewPoint := FreeForm.MeshObjects[0].Vertices[i];
    TempDistance := VectorDistance(Point, NewPoint);
    if TempDistance <= BestDistance then
    begin
      BestDistance := TempDistance;
      Result := i;
    end;
  end;
end;

procedure TForm1.GLSceneViewerMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  Vertex: TVector3f;
begin
  MouseX := X;
  MouseY := Y;
  if (ssLeft in Shift) and not (ssCtrl in Shift) then
  begin
    IsVertexDragging := True;
    Vertex := GLSceneViewer.Buffer.PixelRayToWorld(X, Y);
    Vertex := FreeForm.AbsoluteToLocal(Vertex);
    VertexIndexToDrag := FindClosestPointIndex(Vertex);
    CenterPosition := GLSceneViewer.Buffer.ScreenToWorld(X, Y);
  end;
end;

procedure TForm1.GLSceneViewerMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
  delta: TVector3f;
  i: Integer;
begin
  if (ssLeft in Shift) and (ssCtrl in Shift) then
    GLCamera.MoveAroundTarget(0.5 * (MouseY - Y), 0.5 * (MouseX - X))
  else
  if (ssLeft in Shift) and not (ssCtrl in Shift) and IsVertexDragging then
  begin
    LastPosition := GLSceneViewer.Buffer.ScreenToWorld(X, Y);
    delta.X := RoundTo(LastPosition.X - CenterPosition.X, -5);
    delta.Y := RoundTo(LastPosition.Y - CenterPosition.Y, -5);
    delta.Z := RoundTo(LastPosition.Z - CenterPosition.Z, -5);
    Caption := delta.Z.ToString;
    CenterPosition := LastPosition;
    FreeForm.MeshObjects[0].Vertices.TranslateItem(VertexIndexToDrag, Delta);
    FreeForm.TransformationChanged;
  end;
  MouseX := X;
  MouseY := Y;
end;

procedure TForm1.GLSceneViewerMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  IsVertexDragging := False;
end;

procedure TForm1.GLSceneViewerPostRender(Sender: TObject);
var
  glc: TGLCanvas;
begin
  if IsVertexDragging then
  begin
    glc := TGLCanvas.Create(GLSceneViewer.Width, GLSceneViewer.Height);
    glc.PenWidth := 2;
    glc.PenColor := clLime;
    glc.Ellipse(MouseX, MouseY, 5, 5);
    glc.Free;
  end;
  GLSceneViewer.Invalidate;
end;

end.

В коде используются процедуры обработки событий мыши для начала, движения и окончания перемещения вершины под курсором мыши. В процедуре FindClosestPointIndex находиться индекс ближайшей вершины к текущей позиции курсора мыши. В процедуре GLSceneViewerMouseDown начинается перемещение вершины, а в процедуре GLSceneViewerMouseMove осуществляется само перемещение. В процедуре GLSceneViewerPostRender отображается окружность в точке курсора мыши, если происходит перемещение вершины.

Создано по материалам из источника по ссылке.

В статье рассматривается решение для перемещения вершин в приложении 3D-моделирования, созданном с использованием библиотеки GLScene, где пользователь хочет перемещать вершины под курсором мыши, но сталкивается с проблемой некорректного движения вершины.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: OpenGL ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-02-05 18:45:21/0.00376296043396/0