Перейти к содержанию
Fire Monkey от А до Я
  • 0

Z-Order для 3D-объектов с ZWrite=false


SerhioUser

Вопрос

Как задать Z-последовательность 3d-объектов, например TImage3D, у которых ZWrite=false. Пробовал менять Position.Z - не помогает. Картинка становится маленькая и "далеко", но если она была поверх другой, то так сверху и остается.

Как уже где-то писали BringToFront и SendToBack не работают. Но OpenGL ведь отрисовывает их последовательно. Значит где-то есть этот порядок. Как до него добраться?

Ссылка на комментарий

Рекомендуемые сообщения

  • 0

Так. Сорцекопание выявило, что за сортировку 3d-объектов отвечает класс TRenderingCompare и код находится в методе TCustomForm3D.RebuildRenderingList.

procedure TCustomForm3D.RebuildRenderingList;
var
  I: Integer;
  CompareFunc: TRenderingCompare;
begin
  if Assigned(Children) and (Children.Count > 0) and (FUpdating = 0) then
  begin
    if Not Assigned(FRenderingList) then
      FRenderingList := TList<TControl3D>.Create;
    FRenderingList.Clear;

    for I := 0 to Children.Count - 1 do
      if (Children[i] is TControl3D) then
        FRenderingList.Add(Children[I] as TControl3D);

    CompareFunc := TRenderingCompare.Create;
    try
      FRenderingList.Sort(CompareFunc);
    finally
      CompareFunc.Free;
    end;
  end;
end;

Никаких условий - просто сортировка без вариантов.

А вот код, собственно, проверки для сортировки:

function TRenderingCompare.Compare(const Left, Right: TControl3D): Integer;
var
  V1, V2: TPoint3D;
begin
  Result := Integer(Left.GetMaterialForSorting) - Integer(Right.GetMaterialForSorting);
  if (Result = 0) and Left.ZWrite and Right.ZWrite then
  begin
    if (Left.Opacity < 1) and (Right.Opacity >= 1) then
      Result := 1
    else if (Left.Opacity >= 1) and (Right.Opacity < 1) then
      Result := -1
    else if (Left.Context <> nil) and (Right.Context <> nil) then
      begin
        V1 := TPoint3D(Left.AbsolutePosition) - TPoint3D(Left.Context.CurrentCameraMatrix.M[3]);
        V2 := TPoint3D(Right.AbsolutePosition) - TPoint3D(Left.Context.CurrentCameraMatrix.M[3]);
        Result := Trunc(V2.Length - V1.Length);
      end;
  end;
end;

Как видно если ZWrite = false, 3D-объекты НЕ СОРТИРУЮТСЯ и находятся в порядке создания на форме. Список находится в приватной переменной FRenderingList, к которой мы не можем получить доступ даже сделав наследника от TForm3D.

Ладно. FRenderingList заполняется из списка TFmxChildrenList.Children, до которого мы можем достучаться. Но его массив Items[] доступен только на чтение. Посему повлиять на его порядок мы тоже не можем.

Пока что единственный выход, который я нашел - подключать к проекту копию исходника "FMX.Forms3D.pas" и корректировать его под свои нужды. (Под Mac OS X такой финт не работает - берется стандартный "FMX.Forms3D.pas")

А ведь достаточно было бы сделать RebuildRenderingList виртуальной и хотя-бы в protected секции.

Ну а лучше, думаю, было бы кустомизировать TRenderingCompare класс.

Может кто знает лучший вариант?

Изменено пользователем SerhioUser
Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...