ПрограммированиеФорумИИ

Камера от 3-го лица

Страницы: 1 2 Следующая »
#0
17:10, 27 мар 2009

Необходимо создать камеру от 3-го лица, как это можно сделать?
Думаю нужно чтобы камера всегда была направлена на игрока, но как узнать координаты камеры?
Если не ошибаюсь то угол между камерой и игроком можно ухнать по этой формуле:
  result := ArcTan2(y2 - y1, x2 - x1) * (180 / PI);

Помогите пожалуста!

#1
17:15, 27 мар 2009

Код благополучно был уведён от куда-то, не помню откуда, автор отзовись, спасибо за код.
OpenGL сначала код был под вид от первого лица, ну ту  всё просто, ибо я пишу на кривом диалекте(подчти бейсик).


class CCamera
{
  public:
    Vector3D mPos;             
    Vector3D mView;             
    Vector3D mUp;

    static float currentRotX;
    static float lastRotX;

    void Rotate_Position(float angle, float x, float y, float z);
    void Move_Camera(float speed);
    void Mouse_Move(int wndWidth, int wndHeight);
    void Rotate_View(float speed);
    void Position_Camera(float pos_x,  float pos_y,  float pos_z,
              float view_x, float view_y, float view_z,
              float up_x,  float up_y,  float up_z);
};

void CCamera::Position_Camera(float pos_x,  float pos_y,  float pos_z,
                float view_x, float view_y, float view_z,
                float up_x,  float up_y,  float up_z)
{
  mPos  = Vector3D(pos_x,  pos_y,  pos_z ); // set position
  mView  = Vector3D(view_x, view_y, view_z); // set view
  mUp    = Vector3D(up_x,  up_y,  up_z  ); // set the up vector 
}

void CCamera::Move_Camera(float speed)
{
  Vector3D vVector = mView - mPos;  // Get the view vector
 
  // forward positive camera speed and backward negative camera speed.
  mPos.x  = mPos.x  + vVector.x * speed;
  mPos.z  = mPos.z  + vVector.z * speed;
  mView.x = mView.x + vVector.x * speed;
  mView.z = mView.z + vVector.z * speed;
}

void CCamera::Rotate_View(float speed)
{
  Vector3D vVector = mView - mPos;  // Get the view vector

  mView.z = (float)(mPos.z + sin(speed)*vVector.x + cos(speed)*vVector.z);
  mView.x = (float)(mPos.x + cos(speed)*vVector.x - sin(speed)*vVector.z);
}

void CCamera::Rotate_Position(float angle, float x, float y, float z)

  Vector3D vVector = mPos - mView;
  Vector3D AVector;

  float SinA = sin(angle);
  float CosA = cos(angle);

// Найдем новую позицию X для вращаемой точки
  AVector.x  = (CosA + (1 - CosA) * x * x)* vVector.x;
  AVector.x += ((1 - CosA) * x * y - z * SinA)* vVector.y;
  AVector.x += ((1 - CosA) * x * z + y * SinA)* vVector.z;

  // Найдем позицию Y
  AVector.y  = ((1 - CosA) * x * y + z * SinA)* vVector.x;
  AVector.y += (CosA + (1 - CosA) * y * y)* vVector.y;
  AVector.y += ((1 - CosA) * y * z - x * SinA)* vVector.z;

  // И позицию Z
  AVector.z  = ((1 - CosA) * x * z - y * SinA)* vVector.x;
  AVector.z += ((1 - CosA) * y * z + x * SinA)* vVector.y;
  AVector.z += (CosA + (1 - CosA) * z * z)* vVector.z;

  mPos.x = mView.x + AVector.x;
  mPos.y = mView.y + AVector.y;
  mPos.z = mView.z + AVector.z;
}

void CCamera::Mouse_Move( int wndWidth, int wndHeight )
{
  POINT mousePos; 
  int mid_x = wndWidth  >> 1; 
  int mid_y = wndHeight >> 1; 
  float angle_y  = 0.0f;       
  float angle_z  = 0.0f;
  currentRotX = 0.0f;
 
  GetCursorPos(&mousePos);  // Get the mouse cursor 2D x,y position         
 
  if( (mousePos.x == mid_x) && (mousePos.y == mid_y) ) return;

  SetCursorPos(mid_x, mid_y);  // Set the mouse cursor in the center of the window           

  // Get the direction from the mouse cursor, set a resonable maneuvering speed
  angle_y += (float)( (mid_x - mousePos.x) ) / 1000;   
  angle_z += (float)( (mid_y - mousePos.y) ) / 1000;

  lastRotX = 0.0f;
  lastRotX = currentRotX;    // Сохраняем последний угол вращения
          // и используем заново currentRotX

  // Если текущее вращение больше 1 градуса, обрежем его, чтобы не вращать слишком быстро
  if(currentRotX > 1.0f)
  {
    currentRotX = 1.0f;

    // врощаем на оставшийся угол
    if(lastRotX != 1.0f)
    {
      // Чтобы найти ось, вокруг которой вращаться вверх и вниз, нужно
      // найти вектор, перпендикулярный вектору взгляда камеры и
      // вертикальному вектору.
      // Это и будет наша ось. И прежде чем использовать эту ось,
      // неплохо бы нормализовать её.
      Vector3D vAxis = Cross(mView - mPos, mUp);
      vAxis.Normalize();

      // Вращаем камеру вокруг нашей оси на заданный угол
      Rotate_Position(1.0f - lastRotX, vAxis.x, vAxis.y, vAxis.z);
    }
  }
 
  // Если угол меньше -1.0f, убедимся, что вращение не продолжится
  else if(currentRotX < -1.0f)
  {
    currentRotX = -1.0f;
    if(lastRotX != -1.0f)
    {
      // Опять же вычисляем ось
      Vector3D vAxis = Cross(mView - mPos, mUp);
      vAxis.Normalize();

      // Вращаем
      Rotate_Position( -1.0f - lastRotX, vAxis.x, vAxis.y, vAxis.z);
    }
  }
  // Если укладываемся в пределы 1.0f -1.0f - просто вращаем
  else
  {
    Vector3D vAxis = Cross(mView - mPos, mUp);
    vAxis.Normalize();
    Rotate_Position(angle_z, vAxis.x, vAxis.y, vAxis.z);
  }

  // Всегда вращаем камеру вокруг Y-оси
  Rotate_Position(angle_y, 0, 1, 0);
}

#2
17:26, 27 мар 2009

Спасибо!
Буду разбиратся в коде!

#3
18:56, 27 мар 2009

ну по хорошему камера сперва нужно составить список требований, к примеру было такое в моей практике:

- не должна проваливаться в стены - обладать физ. объемом
- не терять игрока из виду, трассировать видимость между объемом камеры и боксом игрока
- при определенном удалении смотреть на его bbox, при приближении к игроку смотреть на нужную часть тела
- демпфировать и игнорировать дрожание и прыжки игрока
- демпфировать скольжение объема камеры по поверхности и резкие препятствия возникающие между камерой и игроком
- в специальных случаях приближаться - удаляться(типа присел, прыгнул, залез на лестницу, и.т.д)
- поведение в катсценах
- дрожание при стрельбе от первого лица
- дрожание когда рядом чего то рушится
- и.т.д

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

#4
20:30, 27 мар 2009

А как кстати делают, хотя нигде не видел, но наверно все же делают, чтоб при движении персонажа по лестнице камера не прыгала?

#5
21:06, 27 мар 2009

redbox, обычное сглаживание - новая позиция камеры вычисляется, но не присваивается, а делается что-то вроде
camPos *= 0.9;
camPos += (1 - 0.9)*newPos;

#6
21:31, 27 мар 2009

Внутри темы пока вопрос, вы бы хоть прокомментировали код который я дал.

#7
21:59, 27 мар 2009

PlatinumKiller
>>Внутри темы пока вопрос, вы бы хоть прокомментировали код который я дал.
Крутой код, полюбому. Пацан! :)

xDimka
+1

И вообще, мне кажется, что камера от третьего лица - дело неблагодарное.

Кстати, не забываем и про прицеливание ;)
1. Куда летит снаряд,
2. Где находится изображение снаряда (иногда модель смещают относительно положения прожектайла)

#8
23:15, 27 мар 2009

Logmh
окей, спасибо.

#9
1:29, 28 мар 2009

PlatinumKiller

Сперва надо бы разобраться с названием класса, и его назвать не CCamera, а скажем ClientView.
Под камерой все же, правильнее понимать класс в renderer, который содержит в себе матрицу вида, проекционную матрицу, данные для отсечения геометрии, и.т.д. Он бы у меня использовался и для вида от третьего лица, и для вида от первого лица, и для рендеринга отражений, мониторов наблюдения, и прочих вещей для которых перед рендерингом необходимо установить камеру.

ClientView - это взгляд некоего Client. Клиентом может быть игрок, npc, игрок через сеть, и.т.д, который владеет им, готовит для него данные и управляет им.

ClientView же из себя представляет собой некоторое количество функций для реализации п.3, как то: screen shakers, screen demphers, world collision, change 1st - 3rd view, и.т.д

Оптимальнее всего реализовать управление этим классом через lua-скрипт, а настройку отдельных настроечных величин вывести в консольные переменные.

#10
14:37, 28 мар 2009

xDimka
Спасибо, рассмотрю, но пока учиться надо.

Прошло более 6 месяцев
#11
21:26, 28 сен 2009

знаю,что тема избитая,но у меня есть достаточно неплохой сорц

void CameraUpdate(ISceneNode* mesh)
{   
  scene::ISceneManager* sm = device->getSceneManager();
  scene::ICameraSceneNode* camera = sm->getActiveCamera();

  core::vector3df start = mesh->getPosition();
  core::vector3df end = (camera->getTarget() - start);
  end.normalize();
  start -= end*100.0f;//100-это дистанция от обьекта до камеры
    camera->setPosition(start);
}

mesh  - это меш,вокруг которого должно производится вращение
чтобы использовать его,вызывайте его вместо метода camera->setPosition тогда,когда меш должен менять позицию
пример использования скоро можно будет увидеть на irrphysx.at.ua (ближайшие 2-3 дня)

#12
22:09, 3 фев 2010

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

#13
22:58, 3 фев 2010

и что такое Vector3D - vector3df?

#14
23:10, 3 фев 2010

Traffic Magician
это
class Vector3D
{
public:
  float x,y,z;
};

в моём коде.

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

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