Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2 3 4 5   Вниз
  Печать  
Автор Тема: Создать камеру в DirectX 9  (Прочитано 123362 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« : 29-06-2009 12:00 » 

Я создал класс камера, и подключил его к программе которая выводит тигра из х-файла, но почему-то камера не работает.

Вот какое управление:

1. W/S — передвижение вперед и назад;
2. A/D — сдвиг влево и вправо;
3. R/F — полет вверх и вниз;
4. Стрелки вверх/вниз — наклон камеры;
5. Стрелки влево/вправо — рыскание камеры;
6. N/M — вращение камеры.

К сожалению придётся прикрепить код в архиве, так как он слишком большой.


Я бы хотел узнать:

1. Почему не работает камера?
2. Как можно сделать лучше класс камеры если это возможно (оптимизация)?
3. Может надо что то дописать для класса камеры что бы он стал универсальный, тогда пожалуйста скажите чего не хватает?
4. Для работы с клавиатурой лучше использовать DirectInput или средства WinAPI?

* loadxfileCamera.rar (42.98 Кб - загружено 1136 раз.)
Записан
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #1 : 29-06-2009 12:36 » 

Всётаки ждя удобства привиду часть кода относящегося к камере

Класс камеры

Код:
#ifndef _CAMERA_H_
#define _CAMERA_H_

class Camera
{
public:
     // Множестао
     // LANDOBJECT позволяет перемещаться по соответствующей оси.
     // AIRCRAFT позволяет свободно перемещаться в пространстве и предоставляет шесть степеней свободы.
     enum CameraType {LANDOBJECT, AIRCRAFT};

     Camera();                      // Конструктор класса без параметров
     Camera(CameraType cameraType); // Конструктор с параметром
     ~Camera();                     // Диструктор класса

     void LeftRight(float units); // влево/вправо
     void UpDown(float units);    // вверх/вниз
     void FirstBack(float units); // вперед/назад

     void RollRightVector(float angle); // вращение относительно правого вектора
     void RollUpVector(float angle);    // вращение относительно верхнего вектора
     void RollFirstVector(float angle); // вращение относительно вектора взгляда

     // Вычисление матрицы вида, на основании заданных векторов камеры
     void getViewMatrix(D3DXMATRIX* V);
     // Установка типа камеры
     void setCameraType(CameraType cameraType);
     // Получение координат вектора нахождения камеры
     void getPosition(D3DXVECTOR3* pos);
     // Установка камеры в требуемом месте и на требуемой высоте
     void setPosition(D3DXVECTOR3* pos);
     // Получение координат правого вектора
     void getRight(D3DXVECTOR3* right);
     // Получение координат верхнего вектора
     void getUp(D3DXVECTOR3* up);
     // Получение координат вектора взгляда
     void getLook(D3DXVECTOR3* look);

private:
     CameraType  _cameraType; // Тип работы камеры
     D3DXVECTOR3 _right;      // Правый вектор камеры
     D3DXVECTOR3 _up;         // Верхний вектор камеры
     D3DXVECTOR3 _look;       // Передний вектор камеры
     D3DXVECTOR3 _pos;        // Вектор местоположения камеры
};
// Конструктор класса без параметров
Camera::Camera()
{
_cameraType = AIRCRAFT;

_pos   = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
_right = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
_up    = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
_look  = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
}

// Конструктор класса без параметров с параметрами
Camera::Camera(CameraType cameraType)
{
_cameraType = cameraType;

_pos   = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
_right = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
_up    = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
_look  = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
}

// Диструктор класса
Camera::~Camera()
{

}

// влево/вправо
void Camera::LeftRight(float units)
{
     // Для наземных объектов перемещение только в плоскости xz
     if(_cameraType == LANDOBJECT)
          _pos += D3DXVECTOR3(_right.x, 0.0f, _right.z) * units;

     if(_cameraType == AIRCRAFT)
          _pos += _right * units;
}

// вверх/вниз
void Camera::UpDown(float units)
{
     if(_cameraType == AIRCRAFT)
          _pos += _up * units;
}

// вперед/назад
void Camera::FirstBack(float units)
{
     // Для наземных объектов перемещение только в плоскости xz
     if(_cameraType == LANDOBJECT)
          _pos += D3DXVECTOR3(_look.x, 0.0f, _look.z) * units;

     if(_cameraType == AIRCRAFT)
          _pos += _look * units;
}

// вращение относительно правого вектора
void Camera::RollRightVector(float angle)
{
     D3DXMATRIX T;
     D3DXMatrixRotationAxis(&T, &_right, angle);

     // Поворот векторов _up и _look относительно вектора _right
     D3DXVec3TransformCoord(&_up,&_up, &T);
     D3DXVec3TransformCoord(&_look,&_look, &T);
}

// вращение относительно верхнего вектора
void Camera::RollUpVector(float angle)
{
     D3DXMATRIX T;

     // Для наземных объектов выполняем вращение
     // вокруг мировой оси Y (0, 1, 0)
     if(_cameraType == LANDOBJECT)
          D3DXMatrixRotationY(&T, angle);

     // Для летающих объектов выполняем вращение
     // относительно верхнего вектора
     if(_cameraType == AIRCRAFT)
          D3DXMatrixRotationAxis(&T, &_up, angle);

     // Поворот векторов _right и _look относительно
     // вектора _up или оси Y
     D3DXVec3TransformCoord(&_right, &_right, &T);
     D3DXVec3TransformCoord(&_look, &_look, &T);
}

// вращение относительно вектора взгляда
void Camera::RollFirstVector(float angle)
{
     // Вращение только для летающих объектов
     if(_cameraType == AIRCRAFT)
     {
          D3DXMATRIX T;
          D3DXMatrixRotationAxis(&T, &_look, angle);

          // Поворот векторов _up и _right относительно
          // вектора _look
          D3DXVec3TransformCoord(&_right, &_right, &T);
          D3DXVec3TransformCoord(&_up, &_up, &T);
     }
}

// Вычисление матрицы вида, на основании заданных векторов камеры
void Camera::getViewMatrix(D3DXMATRIX* V)
{
     // Делаем оси камеры ортогональными
     D3DXVec3Normalize(&_look, &_look);

     D3DXVec3Cross(&_up, &_look, &_right);
     D3DXVec3Normalize(&_up, &_up);

     D3DXVec3Cross(&_right, &_up, &_look);
     D3DXVec3Normalize(&_right, &_right);

     // Строим матрицу вида:
     float x = -D3DXVec3Dot(&_right, &_pos);
     float y = -D3DXVec3Dot(&_up, &_pos);
     float z = -D3DXVec3Dot(&_look, &_pos);

     (*V)(0, 0) = _right.x;
     (*V)(0, 1) = _up.x;
     (*V)(0, 2) = _look.x;
     (*V)(0, 3) = 0.0f;

     (*V)(1, 0) = _right.y;
     (*V)(1, 1) = _up.y;
     (*V)(1, 2) = _look.y;
     (*V)(1, 3) = 0.0f;

     (*V)(2, 0) = _right.z;
     (*V)(2, 1) = _up.z;
     (*V)(2, 2) = _look.z;
     (*V)(2, 3) = 0.0f;

     (*V)(3, 0) = x;
     (*V)(3, 1) = y;
     (*V)(3, 2) = z;
     (*V)(3, 3) = 1.0f;
}

// Установка типа камеры
void Camera::setCameraType(CameraType cameraType)
{
_cameraType = cameraType;
}

// Получение координат вектора нахождения камеры
void Camera::getPosition(D3DXVECTOR3* pos)
{
*pos = _pos;
}

// Установка камеры в требуемом месте и на требуемой высоте
void Camera::setPosition(D3DXVECTOR3* pos)
{
_pos = *pos;
}

// Получение координат правого вектора
void Camera::getRight(D3DXVECTOR3* right)
{
*right = _right;
}

// Получение координат верхнего вектора
void Camera::getUp(D3DXVECTOR3* up)
{
*up = _up;
}

// Получение координат вектора взгляда
void Camera::getLook(D3DXVECTOR3* look)
{
*look = _look;
}

#endif

В основной программе

Код:
// Глобальное объявление
#include "camera.h"
// Для того, что бы работала функция timeGetTime()
#pragma comment(lib, "winmm.lib")
Camera TheCamera(Camera::LANDOBJECT);

// Функция обработки нажатия клавиш  
bool EnterKey(float timeDelta)
{
if(pDirect3DDevice)
{
if (GetAsyncKeyState('W') & 0x8000f)
TheCamera.FirstBack(4.0f * timeDelta);

if (GetAsyncKeyState('S') & 0x8000f)
TheCamera.FirstBack(-4.0f * timeDelta);

if (GetAsyncKeyState('A') & 0x8000f)
TheCamera.LeftRight(-4.0f * timeDelta);

if (GetAsyncKeyState('D') & 0x8000f)
TheCamera.LeftRight(4.0f * timeDelta);

if (GetAsyncKeyState('R') & 0x8000f)
TheCamera.UpDown(4.0f * timeDelta);

if (GetAsyncKeyState('F') & 0x8000f)
TheCamera.UpDown(-4.0f * timeDelta);

if (GetAsyncKeyState(VK_UP) & 0x8000f)
TheCamera.RollRightVector(1.0f * timeDelta);

if (GetAsyncKeyState(VK_DOWN) & 0x8000f)
TheCamera.RollRightVector(-1.0f * timeDelta);

if (GetAsyncKeyState(VK_LEFT) & 0x8000f)
TheCamera.RollUpVector(-1.0f * timeDelta);

if (GetAsyncKeyState(VK_RIGHT) & 0x8000f)
TheCamera.RollUpVector(1.0f * timeDelta);

if (GetAsyncKeyState('N') & 0x8000f)
TheCamera.RollFirstVector(1.0f * timeDelta);

if (GetAsyncKeyState('M') & 0x8000f)
TheCamera.RollFirstVector(-1.0f * timeDelta);

// Обновление матрицы вида согласно новому
        //местоположению и ориентации камеры
D3DXMATRIX V;
TheCamera.getViewMatrix(&V);
pDirect3DDevice->SetTransform(D3DTS_VIEW, &V);
}
return true;
}

// Функция синхронизации перемещения камеры по прошедшему с прошлого кадра времени (timeDelta)
void EnterMsgLoop (bool (*ptr_display)(float timeDelta))
{
MSG msg;
ZeroMemory(&msg, sizeof(msg));

static float lastTime = (float)timeGetTime();

while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
        {
float currTime  = (float)timeGetTime();
float timeDelta = (currTime - lastTime)*0.001f;

ptr_display(timeDelta);
lastTime = currTime;

RenderingDirect3D();
        }
    }
}

Изменение функциии WinMain

Функция WinMain когда не было камеры

Код:
// Функция которая является входной точкой приложения
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow)
{
    WNDCLASSEX windowsclass;
    HWND hwnd;
    MSG msg;
    hInstance = hInst;

    windowsclass.cbSize = sizeof(WNDCLASSEX);
    windowsclass.style = CS_DBLCLKS|CS_OWNDC|CS_HREDRAW|CS_VREDRAW;
    windowsclass.lpfnWndProc = MainWinProc;
    windowsclass.cbClsExtra = 0;
    windowsclass.cbWndExtra = 0;
    windowsclass.hInstance = hInst;
    windowsclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    windowsclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    windowsclass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
    windowsclass.lpszMenuName = NULL;
    windowsclass.lpszClassName = "WINDOWSCLASS";
    windowsclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if (!RegisterClassEx(&windowsclass))
        return 0;

    hwnd = CreateWindowEx(NULL, "WINDOWSCLASS", "Загрузка Х-файла с вращением", WS_OVERLAPPEDWINDOW|WS_VISIBLE,
        0, 0, 770, 500, NULL, NULL, hInst, NULL);
    if (!hwnd)
        return 0;

    if (SUCCEEDED(InitDirect3D(hwnd)))
    {
        if (SUCCEEDED(InitMesh()))
        {
            ShowWindow(hwnd, SW_SHOWDEFAULT);
            UpdateWindow(hwnd);

            ZeroMemory(&msg, sizeof(msg));
            while (msg.message != WM_QUIT)
            {
                if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
                {
                   TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
                else
                    RenderingDirect3D();
            }
        }
    }
    return (int)msg.wParam;
}

Функция WinMain когда появилась камера

Код:
// Функция которая является входной точкой приложения
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow)
{
    WNDCLASSEX windowsclass;
    HWND hwnd;
    MSG msg;
    hInstance = hInst;

    windowsclass.cbSize = sizeof(WNDCLASSEX);
    windowsclass.style = CS_DBLCLKS|CS_OWNDC|CS_HREDRAW|CS_VREDRAW;
    windowsclass.lpfnWndProc = MainWinProc;
    windowsclass.cbClsExtra = 0;
    windowsclass.cbWndExtra = 0;
    windowsclass.hInstance = hInst;
    windowsclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    windowsclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    windowsclass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
    windowsclass.lpszMenuName = NULL;
    windowsclass.lpszClassName = "WINDOWSCLASS";
    windowsclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if (!RegisterClassEx(&windowsclass))
        return 0;

    hwnd = CreateWindowEx(NULL, "WINDOWSCLASS", "Загрузка Х-файла с вращением", WS_OVERLAPPEDWINDOW|WS_VISIBLE,
        0, 0, 770, 500, NULL, NULL, hInst, NULL);
    if (!hwnd)
        return 0;

    if (SUCCEEDED(InitDirect3D(hwnd)))
    {
        if (SUCCEEDED(InitMesh()))
        {
            ShowWindow(hwnd, SW_SHOWDEFAULT);
            UpdateWindow(hwnd);

EnterMsgLoop(EnterKey);
        }
    }
    return (int)msg.wParam;
}
« Последнее редактирование: 29-06-2009 13:00 от zuze » Записан
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #2 : 29-06-2009 20:52 » 

Прошу прощения что не пояснил почему не работает камера.

Как ты пришел к выводу что она не работает?

Пытаюсь нажимать на клавиши, но ничего не происходит. Клавиши которые я указал в начале первого сообщения, но что бы туда не смотреть привиду их ещё раз.

Вот какое управление:

1. W/S — передвижение вперед и назад;
2. A/D — сдвиг влево и вправо;
3. R/F — полет вверх и вниз;
4. Стрелки вверх/вниз — наклон камеры;
5. Стрелки влево/вправо — рыскание камеры;
6. N/M — вращение камеры.

Как проявляется?

Отображается только модель из x-файла.

Что оно делает вместо того, что бы работать?

Камера ничего не делает, как будто её нет вообще.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 30-06-2009 00:27 » 

zuze, в код я ещё не вникал, мысли по ходу дела:

насколько я понял, камера - понятие условное. Это комплекс действий:
1) установить матрицу проекции (SetTransform(D3DTS_PROJECTION))
2) установить матрицу вида (направление, положение) (SetTransform(D3DTS_VIEW))
3) отрендерить интересующую нас сцену в обратный буфер (обычная наша Render())
4) флипнуть нужный прямоугольник из обратного буфера на нужный прямоугольник экрана проекции(Present) .  А если вместо экрана проекции использовать в качестве назначеия некий полигон (портал, вроде бы называется), то получим зеркало Улыбаюсь Но как это делается - я ещё не знаю, не дошёл

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

ещё, сам наткнулся у себя, когда хочешь установить произвольные углы поворота вокруг нескольких осей (я сделал вокруг X,
 Y и Z), вызов подряд функций

D3DXMatrixRotationX
D3DXMatrixRotationY
D3DXMatrixRotationZ

 - не проканает, изменения в результирующей матрице поворота не накапливаются, устанавливается последнее только. Поэтому, нужно создать произведение нужных матриц и использовать эту результирующую матрицу поворота.
Ну а в случае только осей X, Y и Z можно применить

   D3DXMatrixRotationYawPitchRoll(&MxRotat,m_VcAngles.y,m_VcAngles.x,m_VcAngles.z);

« Последнее редактирование: 30-06-2009 00:35 от Алексей1153++ » Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #4 : 30-06-2009 01:15 » 

У меня подозрение, что я неправельно написал функцию EnterMsgLoop, она не ловит события (нажатия клавиш).   
Буду думать, если будут идеи Алексей1153++ пиши.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 30-06-2009 01:29 » 

ок, на работе гляну
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 30-06-2009 04:03 » 

в процедуру EnterKey точно попадаем

строчки в функции EnterKey
Код:
		// Обновление матрицы вида согласно новому
        //местоположению и ориентации камеры
D3DXMATRIX V;
TheCamera.getViewMatrix(&V);
pDirect3DDevice->SetTransform(D3DTS_VIEW, &V);


точно не нужны

надо

Код:
// Установка матриц преобоазования
void Matrix(void)
{
....
....
// Устанавливаем видовую матрицу
D3DXMATRIX V;
TheCamera.getViewMatrix(&V);
pDirect3DDevice->SetTransform(D3DTS_VIEW, &V);
...
...

тогда всё работает, единственное - начальное положение камеры. Сначала приходиться отъезжать назад (S) некоторое время
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 30-06-2009 04:07 » 

D3DXMatrixPerspectiveFovLH по логике тоже надо перенести в класс камеры
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #8 : 30-06-2009 04:26 » 

Удалил строчки из функции EnterKey, как ты сказал и добавил их вот так

Код:
// Установка матриц преобоазования
void Matrix(void)
{
    ...
    ...
    ...
    pDirect3DDevice->SetTransform(D3DTS_WORLD, &MatrixWorld);

   // Обновление матрицы вида согласно новому
   // местоположению и ориентации камеры
   D3DXMATRIX V;
   TheCamera.getViewMatrix(&V);
   pDirect3DDevice->SetTransform(D3DTS_VIEW, &V);

    // Изменяем видовую матрицу
    D3DXMatrixLookAtLH(&MatrixView,                                  // полученная в итоге видовая матрица
                                      &D3DXVECTOR3(0.0f, 0.0f, 10.0f), // точка, из которой смотрим
                                      &D3DXVECTOR3(0.0f, 0.0f, 0.0f),   // куда смотрим
                                      &D3DXVECTOR3(0.0f, 1.0f, 0.0f)); // направление верха
    // Устанавливаем видовую матрицу
    pDirect3DDevice->SetTransform(D3DTS_VIEW, &MatrixView);
    ...
    ...
    ...
}

Но почему то не работает?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #9 : 30-06-2009 04:47 » 

так ты затираешь одну установку другой ))

вот так сделай
Код:
// Установка матриц преобоазования
void Matrix(void)
{
    ...
    ...
    ...
    pDirect3DDevice->SetTransform(D3DTS_WORLD, &MatrixWorld);

   // Обновление матрицы вида согласно новому
   // местоположению и ориентации камеры
   D3DXMATRIX V;
   TheCamera.getViewMatrix(&V);
   pDirect3DDevice->SetTransform(D3DTS_VIEW, &V);

/*
    // Изменяем видовую матрицу
    D3DXMatrixLookAtLH(&MatrixView,                                  // полученная в итоге видовая матрица
                                      &D3DXVECTOR3(0.0f, 0.0f, 10.0f), // точка, из которой смотрим
                                      &D3DXVECTOR3(0.0f, 0.0f, 0.0f),   // куда смотрим
                                      &D3DXVECTOR3(0.0f, 1.0f, 0.0f)); // направление верха
    // Устанавливаем видовую матрицу
    pDirect3DDevice->SetTransform(D3DTS_VIEW, &MatrixView);
*/
    ...
    ...
    ...
}
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 30-06-2009 04:49 » 

сделай ещё красивее:
Код:
   TheCamera.SetViewTransform(pDirect3DDevice);

Улыбаюсь
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #11 : 30-06-2009 04:59 » 

Спасибо, всё заработало, теперь надо буду улучшать этот класс.

На вопрос "Для работы с клавиатурой лучше использовать DirectInput или средства WinAPI?" я нашёл ответ

Ответ такой:

 В интерактивных играх часто используют DirectInput, но нет смысла его использовать в программе визуализации графиков, там заведомо удобнее будет обычная обработка клавиатуры.
Записан
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #12 : 30-06-2009 05:20 » 

А ещё лучше в место

Код:
if (GetAsyncKeyState(VK_LEFT) & 0x8000f)
  TheCamera.RollUpVector(-1.0f * timeDelta);

if (GetAsyncKeyState(VK_RIGHT) & 0x8000f)
  TheCamera.RollUpVector(1.0f * timeDelta);

Написать

Код:
if (GetAsyncKeyState(VK_LEFT) & 0x8000f)
  TheCamera.RollUpVector(1.0f * timeDelta);

if (GetAsyncKeyState(VK_RIGHT) & 0x8000f)
  TheCamera.RollUpVector(-1.0f * timeDelta);

Если этого не сделать, то если ты нажимаешь стрелку влево объект уезжает вправо, а если  ты нажимаешь стрелку вправо объект уезжает влево.

После изменений, если ты нажимаешь стрелку влево объект уезжает влево, а если  ты нажимаешь стрелку вправо объект уезжает вправо.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #13 : 30-06-2009 05:28 » 

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

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #14 : 30-06-2009 05:48 » 

Алексей1153++
Я не понял зачем это нужно делать, ведь это вроде уже сделанно клавишы N/M — вращение камеры.

Достаточно один из этих двух вариантов удалить, а в оставшимся вареанте вместо GetAsyncKeyState('N') или GetAsyncKeyState('M') написать GetAsyncKeyState(VK_RETURN) вот и всё.

Или ты имел что то другое?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #15 : 30-06-2009 05:55 » 

может я что то упустил, но не вижу такой функции ) Тигр движется только по осям. Ладно, это неважно, сделано, так сделано
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #16 : 30-06-2009 06:07 » 

А, понял тебя действительно такой функции нет.
Записан
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #17 : 30-06-2009 08:04 » 

Я так понял в классе должно быть viewing frustum (усечённая пирамида) и функции пересечения точки, куба, сферы, мэша с усечённой пирамидой.
Эти все функции возвращают значения false (ложь) или true (истина).

А зачем это надо я не понимаю, поясните пожалуйста?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #18 : 30-06-2009 08:19 » 

Цитата
так понял в классе должно быть viewing frustum (усечённая пирамида) и функции пересечения точки, куба, сферы, мэша с усечённой пирамидой.
а кто это сказал ? Я вот тоже так сразу не могу придумать применение
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #19 : 30-06-2009 08:21 » 

а, ну я понял, это при рендере можно использовать, чтоб не рисовать невидимое (то есть то, что вне призмы видимости)
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #20 : 30-06-2009 17:54 » 

Алексей1153++

Это понятно, но у меня загвостка в другом.

1. Вот я построю в классе камера усечённую пирамиду;
2. Напишу функции проверки пересечения точки, куба, сферы, мэша с усечённой пирамидой;
3. А как их применять в своих программах я не понимаю, т.е. использовать эти функции (что писать в коде)?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #21 : 30-06-2009 18:18 » 

ну, например, такая схема:

Код:

class My3DDevice;

class CMy3DObject
{
  ...
    RenderMe(My3DDevice* pDev);
};

class CCamera
{
   ...
   bool IsObjVisible(CMy3DObject* pObj);//
};

class My3DDevice
{
IDirect3DDevice9* m_pDI;
D3DPRESENT_PARAMETERS m_PresParams;

  ....
   RenderArrayOfObjects(CCamera* pCam,CMy3DObject* Arr,int Count);
   SetCurrentCamera(CCamera* pCam);
   
};

//-------------------------------------------

#define def_objnum 5;
CMy3DObject Arr[def_objnum];

My3DDevice::Render(CCamera* pCam,CMy3DObject* Arr,int Count);
{
   m_pDI->BeginScene();
   {

    SetCurrentCamera(pCam);

      for(int i=0; i<def_objnum; i++)
     {
         if(pCam->IsObjVisible(&Arr[i])
        {
             Arr[i].RenderMe(this); 
         }
      }
      m_pDI->EndScene();
   }
   m_pDI->Present();
}
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #22 : 30-06-2009 22:59 » 

Вот то что мне предложили по улучшению класса:

1. Хранить матрицу проекций и вида в самой камере (сделать в классе);

2. Хранить угол обзора, aspect, zNear, zFar с методами получения и установки данных параметров в самой камере (сделать в классе);

3. Сделать viewing frustum или Frustum c его пересчетом, ну и методы видимости бокса, сферы точки и т.д., но в отдельном классе
тогда будет удобно написать что-то подобное
if (camera.IsVisible(boundingBox)) {
//
}

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

5. Добавить метод блокировки камеры как поворотов так и перемещения отдельно, который запрещает изменения матрицы.

6. У камеры возможно должно быть имя и идентификатор, к примеру для менеджер камер, который будет искать по
имени/идентификатору камеру, работать с разными камерами. Тогда можно подменять текущую камеру заранее
загруженную/созданную откуда либо. И смотреть на сцену с разных позиций.

7. Работа камеры с треками движения, записанными в файл или еще куда-то.

8. Сделать в классе установку поворота и сброс поворота.

9. Хранить ориентацию камеры в виде матрицы плохо - она будет накапливать погрешность. Лучше хранить
в кватернионе или углах Эйлера (удобны для 3д-шутеров), и конвертировать в матрицу по необходимости.

Хотя я не знаю зачем делать 9 пункт, ведь у меня происходит сдедующие, я делал по книге автора Франк Луна.

После нескольких поворотов из-за погрешности округления в операциях с плавающей точкой оси камеры могут стать неортогональными. Поэтому каждый раз при вызове данной функции мы заново вычисляем верхний и правый вектор на основании вектора взгляда, чтобы гарантировать, что все три вектора будут ортогональными. Новый ортогональный верхний вектор вычисляется по формуле up = look * right. Затем вычисляется новый ортогональный правый вектор по формуле right = up * look.

Как думаешь может что не правельно или о что nj забыли предложить?
« Последнее редактирование: 30-06-2009 23:02 от zuze » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #23 : 01-07-2009 03:29 » 

Цитата
1. Хранить матрицу проекций и вида в самой камере (сделать в классе);

2. Хранить угол обзора, aspect, zNear, zFar с методами получения и установки данных параметров в самой камере (сделать в классе);
- это само собой

Цитата
3. Сделать viewing frustum или Frustum c его пересчетом, ну и методы видимости бокса, сферы точки и т.д., но в отдельном классе
тогда будет удобно написать что-то подобное
if (camera.IsVisible(boundingBox)) {
//
}
я бы в камере сделал эту функцию. И назвал всё же CanISeeThisObject и сделал бы перегрузку для разных объектов

Цитата
4. можно добавить два флага/режима, для поворота и перемещения, учитывающий что камера изменилась,
что-бы не пересчитывать матрицу камеры каждый кадр.
не вижу смысла, не так уж долго пересчитать матрицу один раз за одно перемещение Улыбаюсь Перерисовка одного кадра всё равно гораздо больше времени занимает

Цитата
5. Добавить метод блокировки камеры как поворотов так и перемещения отдельно, который запрещает изменения матрицы.
не понимаю назначения, это нафиг не нужно. Не хочешь - не меняй положение, да и всё Отлично

Цитата
6. У камеры возможно должно быть имя и идентификатор, к примеру для менеджер камер, который будет искать по
имени/идентификатору камеру, работать с разными камерами. Тогда можно подменять текущую камеру заранее
загруженную/созданную откуда либо. И смотреть на сцену с разных позиций.
может только имя камеры, хотя смысла не вижу: всё равно будет массив объектов "камера", а этот массив уже будешь менеджерить. Если уж очень нужно - унаследуешь от класса камеры и приделаешь нужные свойства

Цитата
7. Работа камеры с треками движения, записанными в файл или еще куда-то.
тут я вижу так: камера отдельно, хранилище координат трека отдельно, проигрыватель отдельно. Проигрыватель берёт поток координат и управляет камерой, равномерно по времени передавая ей координаты.

Цитата
8. Сделать в классе установку поворота и сброс поворота.
поясни?

Цитата
9. Хранить ориентацию камеры в виде матрицы плохо - она будет накапливать погрешность. Лучше хранить
в кватернионе или углах Эйлера (удобны для 3д-шутеров), и конвертировать в матрицу по необходимости.
я храню в виде
Код:
struct s_1153_3DCamera
{
private:
D3DXVECTOR3 m_Eye;
D3DXVECTOR3 m_LookPoint;
D3DXVECTOR3 m_Up;

FLOAT m_zOfNearViewPlane;
FLOAT m_zOfFarViewPlane;
FLOAT m_fovy;

//m_fovy - Aspect ratio, defined as view space width divided by height. This value will nearly always be D3DX_PI/4.

//m_zOfNearViewPlane - Z value of the near view plane. This value will usually be 1.0f.

//m_zOfFarViewPlane - This value indicates how far into the distance the camera can see. Objects beyond
//             this distance will be considered beyond the horizon and will not be drawn

public:
s_1153_3DCamera();
void GetView(D3DXMATRIX* pvm)const;
void GetProjection(D3DXMATRIX* prm,FLOAT Aspect);
};
погрешности накапливать неоткуда Улыбаюсь Если камерой управляет игрок - то он всегда скорректирует любую погрешность незаметно для себя, а если это запись положений камеры, то погрешности браться просто неоткуда - устанавливаешь одно за другим и всё.

Цитата
Как думаешь может что не правельно или о что nj забыли предложить?
а ОНИ - это кто ? )
« Последнее редактирование: 01-07-2009 03:31 от Алексей1153++ » Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #24 : 01-07-2009 03:42 » 

На счёт этого

8. Сделать в классе установку поворота и сброс поворота.

Я понимаю так что нужна возможность установки и сброса положения камеры, то есть устанавливать и сбрасывать угол камеры под которым она находится, а у меня только "Установка камеры в требуемом месте и на требуемой высоте" есть.

Так надо это делать или ненадо?

Цитата: Алексей1153++
а ОНИ - это кто ? )

Это участники одного форума, не буду писать какого, а то получится реклама))).
По DirectX я сразу сижу где то на 3-4 форумах, скорее на 3 так как на четвёртом всё очень скудно.

И ещё я писал вот это "aspect, zNear, zFar" ты не мог бы по русски написать что они означают?

Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #25 : 01-07-2009 03:52 » 

Цитата
Так надо это делать или ненадо?
как хочешь. Приспичит - добавишь эту функцию Улыбаюсь


Цитата
//m_fovy - Aspect ratio, defined as view space width divided by height. This value will nearly always be D3DX_PI/4.

//m_zOfNearViewPlane - Z value of the near view plane. This value will usually be 1.0f.

//m_zOfFarViewPlane - This value indicates how far into the distance the camera can see. Objects beyond
//             this distance will be considered beyond the horizon and will not be drawn

//m_fovy - коэффициент, определённый как отношение ширины просмотра к высоте. (мне собственный перевод не нравится, тем более, что величина - в радианах Улыбаюсь Я для себя понимаю это как угол обзора. Ументшаешь угол - получается оптический прицел, увеличиваешь - широкоугольная камера. Или так: угол усечённой призмы обзора )

//m_zOfNearViewPlane - Z-координата передней плоскости обзора(верх призмы). Всё, что ближе к камере - не рисуется

//m_zOfFarViewPlane - Z-координата дальней плоскости обзора(дно призмы) Определяет, как далеко камера "видит". Объекты далее этой  плоскости считаются "за горизонтом" и не отображаются


Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #26 : 01-07-2009 03:57 » 

А, понял ведь это параметры функции для матрицы проекции.

Спасибо за пояснение!!!
Записан
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #27 : 01-07-2009 06:16 » 

В итоге от предложенных улучшений и их анализа, оставляю следующие:

1. Хранить матрицу проекций и вида в самой камере (сделать в классе);
2. Хранить угол обзора, aspect, zNear, zFar с методами получения и установки данных параметров в самой камере (сделать в классе);
3. Сделать viewing frustum или Frustum c его пересчетом, ну и методы видимости бокса, сферы точки и т.д. с перегрузкой для объектов;
if (camera.IsVisible(boundingBox)) {
//
}
4. Работа камеры с треками движения, записанными в файл или еще куда-то.

По ходу доделывания класса я буду сюда выкладывать код.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #28 : 01-07-2009 06:19 » 

ага, давай. Я потом тоже свои классы вывалю )
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #29 : 01-07-2009 11:04 » 

Во всех примерах эта функция немного разная, вот вроде её аптимальный вариант.

Код:
// Создание усечённой пирамиды
void Camera::CreatePyramid(void)
{
        D3DXMatrixMultiply(Matrix Matrix, MatrixView, MatrixProjection);

        // Левая плоскость
        mPlanes[0].a = Matrix._14 + Matrix._13;
        mPlanes[0].b = Matrix._24 + Matrix._23;
        mPlanes[0].c = Matrix._34 + Matrix._33;
        mPlanes[0].d = Matrix._44 + Matrix._43;

        // Правая плоскость
        mPlanes[1].a = Matrix._14 - Matrix._13;
        mPlanes[1].b = Matrix._24 - Matrix._23;
        mPlanes[1].c = Matrix._34 - Matrix._33;
        mPlanes[1].d = Matrix._44 - Matrix._43;
                           
        // Верхняя плоскость
        mPlanes[2].a = Matrix._14 + Matrix._11;
        mPlanes[2].b = Matrix._24 + Matrix._21;
        mPlanes[2].c = Matrix._34 + Matrix._31;
        mPlanes[2].d = Matrix._44 + Matrix._41;

        // Нижняя плоскость
        mPlanes[3].a = Matrix._14 - Matrix._11;
        mPlanes[3].b = Matrix._24 - Matrix._21;
        mPlanes[3].c = Matrix._34 - Matrix._31;
        mPlanes[3].d = Matrix._44 - Matrix._41;
       
        // Ближняя плоскость
        mPlanes[4].a = Matrix._14 + Matrix._12;
        mPlanes[4].b = Matrix._24 + Matrix._22;
        mPlanes[4].c = Matrix._34 + Matrix._32;
        mPlanes[4].d = Matrix._44 + Matrix._42;
       
        // Дальняя плоскость
        mPlanes[5].a = Matrix._14 - Matrix._12;
        mPlanes[5].b = Matrix._24 - Matrix._22;
        mPlanes[5].c = Matrix._34 - Matrix._32;
        mPlanes[5].d = Matrix._44 - Matrix._42;

        // Нормализация плоскостей
        for (int i = 0; i < 6; i++)
D3DXPlaneNormalize(&mPlanes[i], &mPlanes[i]);
}

Но вот как правельно задать  mPlanes я пока не понял?

В интернете видел примеры такие:

1. В виде класса, но мне тогда надо писать новый класс;
2. В виде структуры.

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

Помогите пожалуйста задать mPlanes?
Записан
Страниц: [1] 2 3 4 5   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines