Изменение положения камеры без перерисовки

Автор Тема: Изменение положения камеры без перерисовки  (Прочитано 12016 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Леонид СеменовАвтор темы

  • ADN Club
  • Сообщений: 44
  • Карма: 2
  • Леонид Семенов. Ведущий инженер-программист
Здравствуйте.
У меня возникли сложности с плавным изменением параметров камеры.
Дело в том, что моя сторонняя программа постоянно передает моему плагину параметры положения камеры,
но проблема в том, что  даже в таймере, пока выполняется прорисовка вида в NavisWorks, все остальные команды просто накапливаются.
Считаю что было бы идеальным решением следующий принцип:
      1) Если пришла информация о новом положении камеры;
      2) прекратить рендеринг текущего вида;
      3) изменить параметры камеры.
(думаю что это возможно, ведь когда мы работаем с мышкой, именно так все и  происходит)
Помогите пожалуйста. Как можно это реализовать?
« Последнее редактирование: 17-08-2015, 17:08:58 от Виктор Чекалин »

Оффлайн Виктор Чекалин

  • Administrator
  • *****
  • Сообщений: 694
  • Карма: 111
  • Skype: chekalin-v
2) прекратить рендеринг текущего вида;
Не думаю что явно это возможно будет сделать. Эти действия должны быть на уровне ядра и/или API.

Сейчас видимо после того, как вы вызвали метод изменения позиции камеры, метод синхронно вызывает перерисовку вида и пока он не закончится, то следующий метод вызвать нельзя. Так?

Неплохо было бы код привести, где меняете позицию.

Оффлайн Леонид СеменовАвтор темы

  • ADN Club
  • Сообщений: 44
  • Карма: 2
  • Леонид Семенов. Ведущий инженер-программист
Сейчас видимо после того, как вы вызвали метод изменения позиции камеры, метод синхронно вызывает перерисовку вида и пока он не закончится, то следующий метод вызвать нельзя. Так?
На счет того, что пока происходит перерисовка вида, то следующий метод вызвать нельзя, это так.

Сторонняя программа может передавать параметры до нескольких десятков в секунду раз. Поэтому я в таймере интервалом 0,2 сек получаю последнее значение и вызываю метод изменения камеры
Сейчас отправлю код

Оффлайн Виктор Чекалин

  • Administrator
  • *****
  • Сообщений: 694
  • Карма: 111
  • Skype: chekalin-v
Сторонняя программа может передавать параметры до нескольких десятков в секунду раз. Поэтому я в таймере интервалом 0,2 сек
Ух... А зачем это все, если не секрет? Я полагаю в реальном времени идет передвижение по модели, но зачем? Даже если действительно нужно, то для чего так часто? Не удивительно что все тормозит.

Пара вопросов:
1) Navisworks используется в виде десктопного приложения или ActiveX Controlа? Если второе, то в вебе или в десктопном приложении?
2) Как вообще происходит взаимодействие с внешним приложением?

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

Еще тут подумал, а как вообще внешнее приложение может знать о том куда передвигать камеру? Сдается мне что вы  заранее записали в БД некий путь передвижения по модели и пытаетесь его воспроизвести.

Оффлайн Леонид СеменовАвтор темы

  • ADN Club
  • Сообщений: 44
  • Карма: 2
  • Леонид Семенов. Ведущий инженер-программист
Асинхронно получаю сообщение о смещении камеры
Код - C# [Выбрать]
  1. HubProxy.On<LocationEventArgs>  ("ChangeLocation", (message) => Parallel.Invoke((Action)(() => ChangeLocation_Do(message))));

Запоминаю последнее положение камеры
и запускаю в потоке плагина метод ChangeLocation

Код - C# [Выбрать]
  1. private void ChangeLocation_Do(LocationEventArgs e)
  2.         {
  3.             Camera.NewCamSettings = e;
  4.             this.Invoke((Action)(() => ChangeLocation(e)));
  5.         }

Код - C# [Выбрать]
  1. private void ChangeLocation(LocationEventArgs e)
  2.         {
  3.             if (timer == null)
  4.             {
  5.                 Data.TimerFree = true;
  6.                 timer = new Timer();
  7.                 timer.Interval = 100;
  8.                 timer.Tick += timer_Tick;
  9.                 timer.Start();
  10.             }
  11.         }
Если последнее установленное положение камеры совпадает с Camera.NewCamSettings, то таймер останавливается и самоуничтожается
Код - C# [Выбрать]
  1. void timer_Tick(object sender, EventArgs e)
  2.         {
  3.             if (Camera.NewCamSettings.Equals(Camera.CamSettings))
  4.             {
  5.                 timer.Dispose();
  6.                 timer = null;
  7.                 Log.Send("Таймер выключен");
  8.             }
  9.             else
  10.                 Camera.SetCamera();
  11.         }
  12. public void SetCamera()
  13.         {
  14.             CamSettings = NewCamSettings;
  15.             Document oDoc = Autodesk.Navisworks.Api.Application.ActiveDocument;
  16.             Viewpoint CurVP = oDoc.CurrentViewpoint.CreateCopy();
  17.            
  18. . . . здесь всякие замудренные формулы, учитывающие тип Ортографика или Перспектива
  19.            
  20.             CurVP.Position = Position;
  21.             CurVP.PointAt(PointAt);
  22.             CurVP.AlignDirection(AlignDirection);
  23.             CurVP.AlignUp(AlignUp);
  24.             CurVP.FocalDistance = Math.Sqrt(Math.Pow(Position.X - PointAt.X, 2) + Math.Pow(Position.Y - PointAt.Y, 2) + Math.Pow(Position.Z - PointAt.Z, 2));
  25.             oDoc.CurrentViewpoint.CopyFrom(CurVP);
  26.         }
  27.  

Я использую класс SignalR для синхронной работы моего WinForm приложения и плагина на NavisWorks
« Последнее редактирование: 17-08-2015, 11:28:22 от Виктор Чекалин »

Оффлайн Виктор Чекалин

  • Administrator
  • *****
  • Сообщений: 694
  • Карма: 111
  • Skype: chekalin-v
Leo_fmf,
В общем что я думаю по этому поводу
1) Метода для остановки рендеринга нет (косвенное доказательство - http://forums.autodesk.com/t5/navisworks-api/api-control-for-autodesk-rendering-functionality/td-p/5114598). Даже если бы был, то мне кажется это не спасло бы ситуацию. Если камера меняется слишком часто, то в итоге получится что прорисовка осуществлялась бы в итоге только на последнем кадре.

2) Использование таймера в данном случае большой костыль. Правильнее было бы использовать Monitor.Pulse и Monitor.Exit. Но в данном случае вряд ли это является причиной тормозов.

3) Есть подозрение, что данный реализация метода изменения позиции камеры сама по себе в данном случае не совсем корректная. Она подходит для перехода на конкретный viewpoint, но не для плавного перемещения. Я имею ввиду метод oDoc.CurrentViewpoint.CopyFrom(CurVP); который по умолчанию вызывает синхронный рендеринг.

4) Возможно вот этот вариант поможет - http://forums.autodesk.com/t5/navisworks-api/viewpoint-manipulation-and-threading-in-2013-net-api/td-p/3698250 Тут предлагается использовать COM объект и с помощью него явно задавать позицию камеры. Возможно поведение будет совсем другое.
Код - C# [Выбрать]
  1. public override int Execute(params string[] parameters)
  2. {
  3.       System.Threading.Thread t = new System.Threading.Thread(this.moveCam);
  4.    t.Start();
  5.  
  6.    while (!t.IsAlive) ;
  7.    return 0;
  8.  }
  9.  
  10.       private void moveCam()
  11.       {
  12.           //Document doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
  13.  
  14.           //Viewpoint curVP = doc.CurrentViewpoint;
  15.           //Viewpoint copyVP = curVP.CreateCopy();
  16.  
  17.           //double inc = 1;
  18.  
  19.           //Point3D pos = new Point3D(copyVP.Position.X + inc,
  20.           //                             copyVP.Position.Y,
  21.           //                             copyVP.Position.Z);
  22.           //copyVP.Position = pos;
  23.  
  24.           //doc.CurrentViewpoint.CopyFrom(copyVP);
  25.  
  26.           ComApi.InwOpState10 state;
  27.           state = ComBridge.State;
  28.           ComApi.InwNvViewPoint NvViewPoint = state.CurrentView.ViewPoint;
  29.           ComApi.InwNvCamera NvCamera = NvViewPoint.Camera;
  30.           ComApi.InwLPos3f NvCamPos = NvCamera.Position;
  31.  
  32.           NvCamPos.SetValue(NvCamPos.data1 + 10, NvCamPos.data2 + 10, NvCamPos.data3);
  33.       }

5) Если последний вариант не поможет, то придется пересматривать логику приложения. Т.е. игнорировать сообщения камеры, если предыдущий рендеринг еще не выполнился (не с помощью таймера, разумеется). Это придется делать в любом случае. Далее, можно, например, не перемещать камеру, если ее положение изменилось на небольшое расстояние от текущего положения камеры и в течении n секунд не было изменения позиции камеры. Расстояние и время подбирается опытным путем.

Оффлайн Леонид СеменовАвтор темы

  • ADN Club
  • Сообщений: 44
  • Карма: 2
  • Леонид Семенов. Ведущий инженер-программист
Спасибо большое за советы.
Буду просматривать варианты, пока у меня остался один вопрос, есть ли параметр в NavisWorks, который определял бы: выполнился ли предыдущий рендеринг или еще нет? Или мне самому использовать какой-нибудь флаг?

Оффлайн Леонид СеменовАвтор темы

  • ADN Club
  • Сообщений: 44
  • Карма: 2
  • Леонид Семенов. Ведущий инженер-программист
Виктор, пример, который вы предоставили для меня отлично подходит, только теперь у меня осталась одна проблема, как при помощи COM API установить такие параметры камеры, как PointAt, AlignDirection и AlignUp. Или может мне лучше открыть новую тему?

Оффлайн Виктор Чекалин

  • Administrator
  • *****
  • Сообщений: 694
  • Карма: 111
  • Skype: chekalin-v
есть ли параметр в NavisWorks, который определял бы: выполнился ли предыдущий рендеринг или еще нет? Или мне самому использовать какой-нибудь флаг?
Я думаю не уместно говорить о свойстве, которое показывало бы статус предыдущего рендеринга. Это в принципе не верно. Возможно есть свойство, определяющее "занят" ли в данный момент Navisworks или нет. Занят он может быть как ренденрингом, так и чем-нибудь другим.
Но, честно говоря, не знаю.
В вашем случае можно было перед методом установки камеры задать значение какой-либо переменной в true, а после выполнения - в false. Это примитивно. ЛУчше через Monitor и блокировку объектов.
Но в связи с тем, что предложенный вариант помог, то этот вопрос снимается с повестки дня:)

Оффлайн Виктор Чекалин

  • Administrator
  • *****
  • Сообщений: 694
  • Карма: 111
  • Skype: chekalin-v
как при помощи COM API установить такие параметры камеры, как PointAt, AlignDirection и AlignUp. Или может мне лучше открыть новую тему?
Рад, что помогло.
Сделал немного проще. переименовал эту тему. Так что необходимости в новой нет.

А вы в справку смотрели? наверняка там есть подобные методы. Или неглядя спросили?:)

Оффлайн Леонид СеменовАвтор темы

  • ADN Club
  • Сообщений: 44
  • Карма: 2
  • Леонид Семенов. Ведущий инженер-программист
А вы в справку смотрели? наверняка там есть подобные методы. Или неглядя спросили?
Я определил два вектора и точку
Код - C# [Выбрать]
  1.             ComApi.InwOpState10 state;
  2.             state = ComBridge.State;
  3.             ComApi.InwNvViewPoint NvViewPoint = state.CurrentView.ViewPoint;
  4.             ComApi.InwNvCamera NvCamera = NvViewPoint.Camera;
  5.             ComApi.InwLPos3f NvCamPos = NvCamera.Position;
  6.  
  7.             var NvPointAt = (ComApi.InwLPos3f)state.ObjectFactory(ComApi.nwEObjectType.eObjectType_nwLPos3f, null, null);
  8.             NvPointAt.data1 = PointAt.X;
  9.             NvPointAt.data2 = PointAt.Y;
  10.             NvPointAt.data3 = PointAt.Z;
  11.  
  12.             var axis = (ComApi.InwLUnitVec3f)state.ObjectFactory(ComApi.nwEObjectType.eObjectType_nwLUnitVec3f, null, null);
  13.             axis.SetValue(AlignDirection.X, AlignDirection.Y, AlignDirection.Z);

но когда я их устанавливаю:
Код - C# [Выбрать]
  1. NvCamera.Rotation.SetValue(axis, 0);
  2. NvCamera.PointAt(NvPointAt);
  3. NvCamPos.SetValue(Position.X, Position.Y, Position.Z);
ощущение, что вид обновляется на изменение каждого параметра (то есть три раза). Но кажется я нашел решение, завтра разберусь и отпишусь
« Последнее редактирование: 17-08-2015, 21:47:24 от Александр Ривилис »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Leo_fmf
Не забывай про правильное форматирование кода на форуме (смотри у меня в подписи).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение