Войти
ПрограммированиеФорумГрафика

Реализация тулов редактора (2 стр)

Страницы: 1 2 3 Следующая »
#15
22:58, 18 ноя. 2011

Со вторым тоже разобрался, спасибо haper.
Сделал как у него, псевдокод:

screenpos = project(objectpos)
screenpos.z = моя глубина, на которой тул будет всегда
toolpos = unproject(screenpos);

UPD: Первое чот не всегда хорошо работает, буду разбираться.


#16
23:24, 18 ноя. 2011

Executor
> screenpos.z = моя глубина, на которой тул будет всегда
тест глубины просто отключить?
toolpos = screenpos.xy

#17
12:35, 19 ноя. 2011

clc
> тест глубины просто отключить?

Ну вы что ниразу редактор не видели чтоли? Причём тут тест глубины?

#18
15:18, 20 ноя. 2011

Executor
> Ну вы что ниразу редактор не видели чтоли? Причём тут тест глубины?
ну я его отключаю

#19
16:09, 20 ноя. 2011

EvilSpirit
И что? Как это поможет сделать тул одинакового размера?

#20
18:55, 20 ноя. 2011

Executor
> И что? Как это поможет сделать тул одинакового размера?
это поможет тому, чтобы тул не заслонялся.
я просто проецирую позицию объекта, который двигаем, в плоскость, лежащую на одинаковом расстоянии от камеры.
выделение и рисование тула происходит в этих координатах, обработка осей - в координатах объекта.

#21
19:24, 20 ноя. 2011


1 - перемещение, 2 - вращение. 3 - размер

void Controller::moveSelect()
{
  if( sost != s_MoveObject )
    return;

  SceneNode *controller_node = controller->getNode();
  Camera *cam = controller_node->getCreator()->getCamera();
  float dist_to_cam = ( cam->GetPos() - controller_node->GetPos() ).length();
  
  // Напровление выделеной оси с учетом поворота всей конструкции
  Vec3 dir_control = Vec3(X,Y,Z);
  Vec3 pos = raysaster_pos - start_move_offset;

  // Изначальное напровление
  Vec3 start_click_dir = start_move_offset.normalisedCopy();
  // Напровление куда кликнула машь
  Vec3 dir_to_mouse = ( raysaster_pos - start_move_pos ).normalisedCopy();


  Vec3 direction_begin, direction_end;

  if( global_li == false )
    dir_control = controller_node->GetRot() * dir_control;

  if ( tip == 1 )
  {  
    direction_begin = start_move_pos;
    direction_end = controller_node->GetPosW();

    // Если выделена пара
    if( (X&&Y) || (Y&&Z) || (Z&&X) )
      controller_node->SetPos( pos );
    else{
      float len = ((pos -start_move_pos) * dir_control).length();
      Vec3 move = (pos -start_move_pos).normalisedCopy();

      if( dir_control.dotProduct( move ) < 0 )
        len = -len;
      
      Vec3 move_vec = controller_node->GetRot() * (Vec3( X,Y,Z ) * len) ;
      controller_node->SetPos( start_move_pos + move_vec );
    }
  }
  else if( tip == 2 )
  {
    direction_begin = controller_node->GetPosW();
    direction_end = raysaster_pos;
    select_node->SetRot( start_move_rot );

    float step = 2.5 * (3.14159265358979f / 180.0f);  //переводим 5 градусов в радианы

    // Получаем угол между стартовым кликом, и тем что сейчас
    float dot_ang = start_click_dir.dotProduct( dir_to_mouse );
    float ange = floorf( Math::ACos(dot_ang).valueRadians() / step ) * step;
    
    Vec3 cross = start_click_dir.crossProduct( dir_to_mouse ) ;
    if( ( X && cross.x < 0.0f ) || ( Y && cross.y < 0.0f ) || ( Z && cross.z < 0.0f )   ) 
      ange = -ange;

    if( global_li )
      select_node->Rotate( Quat( Radian(ange), Vec3(X,Y,Z) ), Node::TS_WORLD );
    else
      select_node->Rotate( Quat( Radian(ange), Vec3(X,Y,Z) ) );
  }
  else if ( tip == 3 )
  {  
    direction_begin = start_move_pos + start_move_offset;
    direction_end = raysaster_pos;

    // Если выделена пара
    float len = ((pos -start_move_pos) * dir_control).length() * 0.5;

    Vec3 cur_dir  = ( raysaster_pos - direction_begin  ).normalisedCopy();
    if( start_click_dir.dotProduct( cur_dir )  < 0 )
      len = -len;

    if( X && Y && Z )
      len = ( mouse_click.y - mouse.y ) * dist_to_cam * 0.1;
    
    select_node->SetScale( start_move_scale + dir_control * len );
  }


  node_rot_dir->SetVisible( true );
  node_rot_dir->SetPos( direction_begin );
  node_rot_dir->setDirection( direction_begin - direction_end, Node::TS_WORLD, Vec3(0,0,-1) );
  node_rot_dir->SetScale( Vec3( dist_to_cam * 0.005, dist_to_cam * 0.005, ( direction_begin - direction_end ).length() *0.1 ) );

}
#22
20:04, 20 ноя. 2011

EvilSpirit
> это поможет тому, чтобы тул не заслонялся.

Такой проблемы у меня и не было.

#23
20:07, 20 ноя. 2011

FDsagizi
Что такое start_move_offset, start_move_pos и raysaster_pos?

#24
21:58, 20 ноя. 2011

Executor
> Что такое start_move_offset, start_move_pos и raysaster_pos?

// Это позиция стрелок
start_move_pos = controller->getNode()->GetPos();

// Это позиция куда кликнули ( на стрелке ) - позиция самих стрелок
start_move_offset = raysaster_pos - start_move_pos;

raysaster_pos - Это самое интересное, после того, как зажата кнопка перемещения, происходит рейкаст по плоскости
плоскости обычно 2, но может быть и одна если перемещение происходит в двух степенях свободы, к примеру по X и Z сразу
вот код рей каста по плоскостям  ( X, Y, Z - это bool'ы, которые говорят, какие стрелочки выделены, могут быть сразу 2.
Могут и 3, если это масштабирование  по всем осям. )

void Controller::up_reycaster()
{
  // Нужна ли вторая плоскость
  need_2_plane = false;
  // Определяем ку должа быть направелна
  if( X && Z )    dir[0] = Vec3::UNIT_Y;
  else if( X && Y )  dir[0] = Vec3::UNIT_Z;
  else if( Y && Z )  dir[0] = Vec3::UNIT_X;
  else if( tip == 1 || tip == 3 ){
    // Если это позиционирование или изменение размера и выделен один из X Y Z 
    dir[0] = Vec3( Z, X, Y ); 
    dir[1] = Vec3( Y, Z, X );
    need_2_plane = true; 
  }    
  // Если это вращение
  else if( tip == 2 )
    dir[0] = Vec3( X, Y, Z ); 

  // Рейкастим по плоскости
  Ray ray = SceneManager::current()->getCamera()->getRay( mouse.x , mouse.y); 
  float last_max_dist = 0;

  for( int i =0; i < (need_2_plane ? 2:1) ; ++i )
  {
    Plane plane( dir[i], controller->getNode()->GetPosW() );

    std::pair<bool, float> hit = ray.intersects(plane); 
    
    if (hit.first &&( last_max_dist == 0 || last_max_dist < hit.second ) ){
      raysaster_pos = ray.getPoint( hit.second );
      last_max_dist = hit.second; 
    }
  }
}
Прошло более 1 года
#25
10:39, 20 мая 2013

Как лучше сделать тул для вращения? У меня кольца рисуются линиями, но с пересечением проблема., так как невозможно мышкой попасть. Можно ли делать так:
Считаем точку пересечение(А) линии кольца с плоскостю , на которой лежит луч курсора.
Потом считаем расстояние между точкой А и ближайшей точкой луча?

#26
12:27, 20 мая 2013

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

#27
15:08, 20 мая 2013

RmzVoid
Спасибо, скрывание курсора действительно хорошо влияет (визуально).

#28
13:49, 21 мая 2013

Ну раз тема создана, спрошу.
Есть тулза которая вращает модель в редакторе. Модель имеет собственный BoundingBox, который ориентирован вдоль осей глобальной системы координат. При повороте модели, нужно корректно пересчитать размеры BBox-a. Пока реализовано так: после поворота на некий угол заново пробегаю по позициям всех вершин модели, нахожу "крайние" точки, и строю новый бокс. Работает правильно но медленно, если у модели дофига вершин. Может можно как-то красивее решить задачку. Принимаются любые идеи.
Спасибо.

#29
14:13, 21 мая 2013

Misanthrope
В у тебя ББ структурой хранится?

У меня ББ хранился как куб, и я его поворачивал как и модель.

Страницы: 1 2 3 Следующая »
ПрограммированиеФорумГрафика

Тема в архиве.