Модераторы: Rickert
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> События формы VS DirectInput, Что лучше в оконных неигровых 3-D app 
:(
    Опции темы
EgoBrain
Дата 30.11.2008, 09:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: 1
Всего: 2



Что лучше использовать в приложении при монипуляциях в сцене (например простой 3-D редактор) события формы или DirectInput? Спрашиваю потому что DirectInput незнаю, изучать времени нет. Может быть там есть какие-то координальные возможности из-за которых нет смысла строить программу на событиях формы? Ну задачи пока стандартные: перемещения объектов в пространстве мышью, возможно какой-то ввод с клавиатуры, например, то же самое перемещение и т.п.
PM MAIL ICQ Skype   Вверх
ValLer
Дата 1.12.2008, 16:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 30.11.2008
Где: Ростов-на-Дону

Репутация: нет
Всего: нет



Если простой редактор, то события формы подойдут. Ну а если тебя волнует производительность кода и точность манипуляций то DI. Кстати использовать DirectInput для получения данных от мыши и клавиатуры совсем не сложно. 
PM MAIL WWW ICQ   Вверх
EgoBrain
Дата 2.12.2008, 13:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: 1
Всего: 2



Помоему события формы типа MouseDown MouseMove и т.п. не очень подходят, так как в программе существует возможность вращения сцены, то есть изменение ракурса обзора (это я уже реализовал, хоть и криво, кстати по этому поводу тоже нада задать вопрос), значит взависимости от текущего ракурса соответствие плоскости формы плоскостям пространства разные. Короче проще говоря, на данный момент для меня, офигительно сложный алгоритм придется делать, для вычисления соответствий X Y-координаты мыши X Y Z-координатам пространства (например для реализации возможности выделения и перемещения объекта). Дайте пример  smile 

Это сообщение отредактировал(а) EgoBrain - 2.12.2008, 13:08
PM MAIL ICQ Skype   Вверх
ValLer
Дата 2.12.2008, 16:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 30.11.2008
Где: Ростов-на-Дону

Репутация: нет
Всего: нет



DI позволяет получать не конкретные координаты курсора на экране, а перемещение самой мыши, т.е. если курсор упрётся в границу экрана, ты всё равно будешь получать перемещение мыши. Может это тебе поможет... Вот мой класс на С++ для получения данных от мыши и клавиатуры под DI.

Код


#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>

class Input
{
    public:
        Input(void);
        ~Input(void);

        LPDIRECTINPUT8 lpInput;  // Объект DirectInput
        LPDIRECTINPUTDEVICE8 lpKeyboard;  
        LPDIRECTINPUTDEVICE8 lpMouse;

        char keyboard[256]; // Хранит состояние клавиатуры
        DIMOUSESTATE mouse; // Хранит состояние мыши

        int    InitInput(HINSTANCE); // Инициализация DirectInput
        int InitKeyboard(HWND); // Инициализация клавиатуры
        int InitMouse(HWND); // Инициализация мыши

        int ReadKeyboardState(void); // Чтение данных клавиатуры
        int ReadMouseState(void); // Чтение данных мыши

        int KeyDown(BYTE); // Проверка нажата ли клавиша

        int ReleaseKeyboard(void); // Освобождение клавиатуры
        int ReleaseMouse(void); // Освобождение мыши

};

//-----------------------------------------------------------------------------
// РЕАЛИЗАЦИЯ
//-----------------------------------------------------------------------------


// Конструктор
Input::Input(void)
{
    lpInput = NULL;
    lpKeyboard = NULL;
    lpMouse = NULL;
}

// Деструктор
Input::~Input(void)
{
    lpInput = NULL;
    lpKeyboard = NULL;
    lpMouse = NULL;
}


// Инициализация DirectInput
int Input::InitInput(HINSTANCE hInst)
{
    DirectInput8Create(hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**) &lpInput, NULL);
    return(1);
}


// Инициализация клавиатуры
int Input::InitKeyboard(HWND hWnd)
{
 
   // Создание устройства клавиатуры
   lpInput -> CreateDevice(GUID_SysKeyboard, &lpKeyboard ,NULL);

   // Установка формата данных
   lpKeyboard->SetDataFormat(&c_dfDIKeyboard); 

   // Установка уровня взаимодействия
   lpKeyboard->SetCooperativeLevel(hWnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); 

    // Захват клавиатуры
    if (lpKeyboard) lpKeyboard->Acquire();

    return(1);
}


// Инициализация мыши
int Input::InitMouse(HWND hWnd)
{
    // Создание устройства мыши
    lpInput -> CreateDevice(GUID_SysMouse, &lpMouse ,NULL);

    // Установка формата данных
    lpMouse->SetDataFormat(&c_dfDIMouse); 

    // Установка уровня взаимодействия
    lpMouse->SetCooperativeLevel(hWnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); 

    // Захват мыши
    if (lpMouse) lpMouse->Acquire();

    return(1);
}


// Чтение данных клавиатуры
int Input::ReadKeyboardState()
{
   // Получаем состояние клавиатуры
   lpKeyboard->GetDeviceState(256,(LPVOID) &keyboard); 
   return(1);
}


// Чтение данных мыши
int Input::ReadMouseState()
{
   // Получаем состояние мыши
   lpMouse->GetDeviceState(sizeof(DIMOUSESTATE),(LPVOID) &mouse); 
   return(1);
}


// Проверка нажата ли клавиша
int Input::KeyDown(BYTE KeyCode)
{
    return( keyboard[KeyCode] & 0x80 );
    return(1);
}


// Освобождение клавиатуры
int Input::ReleaseKeyboard()
{
    if (lpKeyboard != NULL)
        lpKeyboard->Unacquire();

    if (lpKeyboard != NULL)
        lpKeyboard->Release();

    lpKeyboard = NULL;

    return(1);
}


// Освобождение мыши
int Input::ReleaseMouse()
{
    if (lpMouse != NULL)
        lpMouse->Unacquire();

    if (lpMouse != NULL)
        lpMouse->Release();

    lpMouse = NULL;

    return(1);
}

///////////////////////////////////////////////////////////////////////////////



g_hInst - нэндл экземпляра приложения
g_hWnd  - нэндл окна (формы)
Чтобы пользоваться достаточно создать экземпляр класса, инициализировать DI, клаву и/или мышь, в цикле читать состояние и получать данные, что и делает следующий код:


Код


Input I; // объявление объекта

// К примеру
int Program_Init()
{
                I.InitInput(g_hInst); // Инициализация DI

    I.InitKeyboard(g_hWnd);
    I.InitMouse(g_hWnd);

    return(1);
}

int Program_Close()
{
    I.ReleaseKeyboard();
    I.ReleaseMouse();

    return(1);
}

// Главный цикл
int Program_Loop()
{
                // Получение состояния клавиатуры и мыши
    I.ReadKeyboardState();
    I.ReadMouseState();

 
                // Проверка нажатой клавиши (DIK_ - DirectInputKey) в SDK DirectX'а есть полный список кодов клавиш
    if ( I.KeyDown(DIK_ESCAPE) )
        Exit();    


    I.mouse.lX;  // Значение перемещения по горизонтали
    I.mouse.lY;  // Значение перемещения по вертикали
    I.mouse.lZ;  // Значение перемещения колеса прокрутки

    I.mouse.rgbButtons[0];  // Левая кнопка
    I.mouse.rgbButtons[1];  // Правая кнопка
    I.mouse.rgbButtons[2];  // Средняя (колесо)
                            // и т.д. всего до 8 кнопок

    return(1);
}






PM MAIL WWW ICQ   Вверх
ValLer
Дата 2.12.2008, 20:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 30.11.2008
Где: Ростов-на-Дону

Репутация: нет
Всего: нет



На счёт перемещения мышью в 3D, вопрос меня заинтересовал...  В 2D это сделать несложно (простая тригонометрия)... А вот в 3D... Предположим, реализовать перемещение подобное 3DMax'у. Т.е. существуют 3 оси, и можно перемещать объект отдельно по каждой оси, причём сцена может быть повёрнута как угодно. Решение этой задачи можно свести к двухмерному, если представить эти оси, например, как единичные векторы, затем найти их проекции на плоскость (экран). Получим что все три вектора x y z лежат в одной плоскости. Допустим хотим переместить объект по оси OZ. После проецирования этот вектор стал иметь координаты (x1,y1). Перемещаем мышь, к примеру, на (dx,dy) которые получаем через DI или извращаясь с помощью событий. 
Теперь можно переместить сам объект: z +=  x1*dx + y1*dy
Задача по-моему решаема, но не так проста как хотелось бы. Ещё подумаю...
PM MAIL WWW ICQ   Вверх
EgoBrain
Дата 3.12.2008, 05:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: 1
Всего: 2



Спасибо за инфу. Хотелось бы продолжения smile Написанный на С++ класс же можно в С# проект подключить?
PM MAIL ICQ Skype   Вверх
ValLer
Дата 3.12.2008, 19:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 30.11.2008
Где: Ростов-на-Дону

Репутация: нет
Всего: нет



На C# ещё проще, используя управляемый DirectX. Добавляешь в проект ссылки:
Microsoft.DirectX
Microsoft.DirectX.DirectInput

Затем
using Microsoft.DirectX;
using Microsoft.DirectX.DirectInput;

Класс немного изменился (особенности управляемого DX). По большому счёту можно было бы и без класса обойтись, в управляемом DX и так всё компактно и удобно  smile :

Код

public class Input
    {
        public Device deviceKeyboard;  // Объект Клавиатура
        public Device deviceMouse;  // Объект Мышь

        // Состояние Мыши
        public MouseState mstate;
        public byte[] mbuttons;


        // Инициализация клавиатуры
        public void InitKeyboard()
        {
            // Создание устройства клавиатуры
            deviceKeyboard = new Device(SystemGuid.Keyboard);

            // Установка уровня взаимодействия
            deviceKeyboard.SetCooperativeLevel(Form1.ActiveForm, CooperativeLevelFlags.Background |
                                                     CooperativeLevelFlags.NonExclusive);
            // Захват клавиатуры
            deviceKeyboard.Acquire();
        }

        // Инициализация мыши
        public void InitMouse()
        {
            // Создание устройства мыши
            deviceMouse = new Device(SystemGuid.Mouse);

            // Установка уровня взаимодействия
            deviceMouse.SetCooperativeLevel(Form1.ActiveForm, CooperativeLevelFlags.Background |
                                                     CooperativeLevelFlags.NonExclusive);
            // Захват мыши
            deviceMouse.Acquire();
        }

        // Чтение данных мыши
        public void ReadMouseState()
        {
            mstate = deviceMouse.CurrentMouseState;
            mbuttons = mstate.GetMouseButtons();
        }

    }


Чтобы пользовать:

Код


 Input I = new Input(); // Объект DI


 //--------------------- Затем где-нибудь инициализировать
            // Инициализация клавиатуры и мыши
            I.InitKeyboard();
            I.InitMouse();
//----------------------------------------------------------------------


// И наконец получать данные. Можно таймером

private void timer1_Tick(object sender, EventArgs e)
        {
            // Проверка нажатия клавиш клавиатуры
            foreach (Key k in I.deviceKeyboard.GetPressedKeys())
            {
                // Клавиша вправо?
                if (k == Key.Right)
                    //......................

                // Клавиша влево?
                if (k == Key.Left)
                      //......................         
            }


            // Получения данных о мыши
            I.ReadMouseState();

            // Получение перемещения мыши
            I.mstate.X; 
            I.mstate.Y; 
            //..........................

            // Нажата ли левая, правая кнопка мыши, колесо?
            if (Convert.ToBoolean(I.mbuttons[0] & 128)) 
               // ................................

            if (Convert.ToBoolean(I.mbuttons[1] & 128))
                // ................................

            if (Convert.ToBoolean(I.mbuttons[2] & 128))
               // ................................
        }



Вот рабочий проект на MS 2008:



Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  DI.rar 30,02 Kb
PM MAIL WWW ICQ   Вверх
EgoBrain
Дата 5.12.2008, 14:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: 1
Всего: 2



Спасибо. С таким пользовательским классом будет проще smile Таймер каждый раз обновляет state устройства в экземпляре класса, я правильно понял, получается там же (в таймере) и надо обработку событий устройства писать?
PM MAIL ICQ Skype   Вверх
ValLer
Дата 5.12.2008, 15:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 30.11.2008
Где: Ростов-на-Дону

Репутация: нет
Всего: нет



Ты понял правильно, событие timer_Tick вызывается постояно с интервалом ~30мс, что при наилучшем раскладе равносильно 1000/30 = 33fps. И каждый раз при возникновении события ты получаешь инфу от устройства. На сколько я знаю ты работаешь с 3d графикой в MDX и используешь события, например, OnVertexBufferCreate, OnLostDevice. Так вот сдесь тоже самое, просто вместо timer_Tick, ты возможно используешь Form_Paint, или ещё что.
PM MAIL WWW ICQ   Вверх
EgoBrain
Дата 7.12.2008, 11:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: 1
Всего: 2



Я вначале идею использования таймера воспринял ни как пример а в буквальном смысле, имхо так даже будет проще. А еще лучше наверное юзать DXTimer, у него разрешение выше. Я к тому, что привязываться к ФПС не стоит, так как на разных компах мышка по разному будет работать smile По поводу перемещения объектов, наверняка задача уже много раз решена так как подход очень популярен 
Цитата

Предположим, реализовать перемещение подобное 3DMax'у
 Простая идея - это манипуляция положением объекта через кнопки GUI, но это как то... ну в общем не серьезно и убого, да и пользователю в конченом счете удовольствие не из приятных. Ваша идея про проекции осей в плоскость помоему подходит только частных случаях: вид спереди, вид с боку, вид с верху и т.п. а при перспективном виде, когда можно задействовать все оси как быть?
У меня есть два примера, на которых можно посмотреть решение данной задачи (3-D Max и еще одна неизвестная прога Pro100). В максе пользователь визуально выбирает вектор или плоскость в которой будет движение, но такое решение тоже далеко не из простых: необходимо рисовать векторы и плоскости для выбора на объекте и расчитывать что из них выбрал пользователь (думаю все видели 3-D Max smile ). В программе Pro100 плоскость перемещения объекта определяется углом обзора (как мне кажется), то есть если обзор под углом ~ больше 45 градусов от "пола" сцены (камера смотрит вниз), то перемещение происходит в плоскости xz. Думаю я выберу второй подход smile У меня есть два параметра вращения сцены: 1). Угол в радианах определяющий поворот сцены вокруг оси x; 2). - вокруг оси y. Соответственно можно проверять это значения в зависимости от него уже определять плоскость перемещения...
PM MAIL ICQ Skype   Вверх
ValLer
  Дата 7.12.2008, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 30.11.2008
Где: Ростов-на-Дону

Репутация: нет
Всего: нет



На счёт DXTimer... Он используется в программах, например играх )), где требуется повышенная точность, например для просчётов физики. Конечно его ничто не мешает вам его использовать. smile 

Цитата

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

На самом деле нет. После проецирования векторов на экран получим, что все векторы лежат в одной плоскости (XY, там где мышь обитает))).
user posted image
Заметьте, когда вы в максе перемещаете объект по какой-либо оси, вы перемещаете курсор по направлению этой оси, будь-то x,y или z.


Теперь можно определять расстояние курсора до каждого вектора (это "длинна перпендикуляра" из точки Cursor.x, Cursor.y на вектор), и проверять какая ось была выбранна. Затем по уже придуманному мной алгоритму перемещать объект. Я недавно писал прогу, которая определяет расстояние от точки до отрезка. Правдо на Delphi... может пригодиться.

Добавлено через 7 минут и 34 секунды
С прогой Pro100 не работал, но предпологаю что в максе манипулировать удобнее))  smile 

Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  __________________________.rar 159,71 Kb
PM MAIL WWW ICQ   Вверх
EgoBrain
Дата 8.12.2008, 13:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: 1
Всего: 2



Цитата

Заметьте, когда вы в максе перемещаете объект по какой-либо оси, вы перемещаете курсор по направлению этой оси, будь-то x,y или z.

Ну в Max-е на самом деле проще, все сводится к банальному "больше следующая x-координата мыши предыдущей или нет?", то бишь влево двигаем объект уходит по оси в минус, вправо - в плюс. 
А пример на GDI+ как расчитывает расстояние, по теоремам линейной алгебры, или какие-то свои алгоритмы (я просто не люблю в чужых кодах капаться)?  smile  В общем по итогу поставленной проблемы: щас есть более приоритетные дела, возьмусь конкретно за данный вопрос наверное в след. году (хотя кто знает, может и раньше). Но пока мне неMax-совкский алгоритм больше нравится  smile

Добавлено через 10 минут и 52 секунды
В общем пока что-то как-то расплывчато представляется преимущество DI перед событиями формы... Я так просмотрел ваш проект DI.sln, класс очень удобный а вот программа имеет минус - координаты кнопки меняются не пропорционально координатам мыши, то есть местами последняя обгоняет кнопку.
PM MAIL ICQ Skype   Вверх
ValLer
Дата 8.12.2008, 15:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 30.11.2008
Где: Ростов-на-Дону

Репутация: нет
Всего: нет



Цитата

Ну в Max-е на самом деле проще, все сводится к банальному "больше следующая x-координата мыши предыдущей или нет?", то бишь влево двигаем объект уходит по оси в минус, вправо - в плюс.


Точно! Что-то я перемудрил...)))) А для того чтобы по плоскости перемещать, то ещё по Y включается!!! Всё гениальное просто)))))) Сделаю себе такую возможность. 

Цитата

А пример на GDI+ как расчитывает расстояние, по теоремам линейной алгебры, или какие-то свои алгоритмы (я просто не люблю в чужых кодах капаться)?  


Да просто я сейчас в универе аналитическую геометрию изучаю, поэтому это первое что пришло в голову. На счёт чужого кода - сам ненавижу разбираться)))))), интересно, а кто любит?

Цитата

программа имеет минус - координаты кнопки меняются не пропорционально координатам мыши, то есть местами последняя обгоняет кнопку.


Возможно, я как-то не правильно его (DI) использую, а может в microsoft решили, что и не требуется такое соответствие?

PM MAIL WWW ICQ   Вверх
EgoBrain
Дата 16.12.2008, 14:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: 1
Всего: 2



ValLer, у вас есть готовые решения долгообсуждаемой проблему перемещения объектов (программа, проект)?
PM MAIL ICQ Skype   Вверх
ValLer
Дата 16.12.2008, 17:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 30.11.2008
Где: Ростов-на-Дону

Репутация: нет
Всего: нет



Пока что нет, времени не хватает ((( Когда что-нибудь сделаю, сообщу.
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Программирование игр, графики и искуственного интеллекта"
Rickert

НА ЗЛОБУ ДНЯ: Дорогие посетители, прошу обратить внимание что новые темы касающиеся новых вопросов создаются кнопкой "Новая тема" а не "Ответить"! Любые оффтопиковые вопросы, заданные в текущих тематических темах будут удалены а их авторы, при рецедиве, забанены.

  • Литературу, связанную с программированием графики, обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы связанные с программированием графики и мультимедии на языках С++ и Delphi
  • Вопросы по реализации алгоритмов рассматриваются здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rickert.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Программирование игр, графики и искусственного интеллекта | Следующая тема »


 




[ Время генерации скрипта: 0.0910 ]   [ Использовано запросов: 20 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.