• 0
Авторизация  
SerhioUser

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

Вопросы

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 ответ на этот вопрос

  • 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

Авторизация  

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

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