Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Мультимедия, OpenGL/DirectX > Перемещения в OpenGL


Автор: Prolss 1.6.2011, 09:51
Здравствуйте, объясните как перемещать объекты в opengl. Какими способами можно это делать? Если можно выложите пример(часть кода) с перемещением хотя бы точки.

Автор: 5kill 1.6.2011, 15:28
Основной способ перемещения - перемещение системы координат и изображение объекта в этой новой системе координат.
Этот код нарисует повернутый на 90 градусов относительно оси Х и смещенный по Х на 60 и по Z на -24 конус.
Код

            Gl.glColor3f(1, 1, 0);
            Gl.glPushMatrix();
            Gl.glRotated(-90, 1, 0, 0);
            Gl.glTranslated(60, 0, -24);
            Glut.glutSolidCone(25, 50, 64, 64);
            Gl.glPopMatrix();


Автор: Prolss 1.6.2011, 19:09
5kill, ни чего не движется...

Автор: Vetos 1.6.2011, 20:11
Чтобы запрограммировать движение объекта (пусть это точка, выпуклый объект, загруженная модель) нужно ввести 3 переменные X,Y,Z. Чтоб его вращать - еще три угла по осям X,Y,Z;
Представим координаты объекта в ввиде структуры
Код

typedef struct _Position
{
      GLfloat X,Y,Z;
}TPosition;

TPosition Position;


Имея такую структуру, перепишем код отрисовки объекта:
Код

void Draw(void)
{
       glTranslate(Position.X,Position.Y,Position.Z);//передвинем объект на его координаты;
       //отрисовка объекта
       glTranslate(-Position.X,-Position.Y,-Position.Z);//вернем точку вывода в исходное состояние, 
       //это нужно для того чтобы следующий объект отрисовался там где надо;
}


Вводим новую переменую перемещения Move и перед отрисовкой изменяем позицию объекта:
Код

void RenderScene(void)
{
//обычные действия, очистка буфера цвета, настройка положения камеры
Move+=0.01;
Position.Z = Move;
Draw();
}

На экране ты должен увидеть как объект плавно отдаляется от тебя.
Существует много способов перемещения объектов, это самый простой

Автор: Prolss 1.6.2011, 20:39
Vetos, всё сложно.. не понимаю.. не чего не выходит..

Скажите кто нибудь, что не так.. чёрный экран и всё.. вот код:

Код

typedef struct _Position
{
      GLfloat X,Y,Z;
}TPosition;
TPosition Position;


GLvoid DrawGLScene(GLvoid)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // очистка Экрана и буфера глубины
    glLoadIdentity();               // Сброс просмотра
    glTranslatef(1.0,1.0,1.0);//передвинем объект на его координаты;                                
        glVertex3f( 0.0f, 1.0f, 0.0f);    // Вверх
        glVertex3f(-1.0f,-1.0f, 0.0f);    // Слева снизу
        glVertex3f(-1.0f,-1.0f, 0.0f);    // Справа снизу
    glEnd();

   glTranslatef(-1.0,-1.0,-Position.Z);//вернем точку вывода в исходное состояние, 
       //это нужно для того чтобы следующий объект отрисовался там где надо;
    

}

void RenderScene(void)
{
//обычные действия, очистка буфера цвета, настройка положения камеры
float Move=+0.01;
Position.Z = Move;
void Draw();
}

Автор: Prolss 1.6.2011, 23:53
Пробывал вот так, тоже чёрный экран.. помогите, вот:
Код

GLvoid DrawGLScene(GLvoid)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    glTranslatef(4.0, 5.0, 6.0);

    glBegin(GL_TRIANGLES);
        glVertex3f( 0.0f, 1.0f, 0.0f);    // Вверх
        glVertex3f(-1.0f,-1.0f, 0.0f);    // Слева снизу
        glVertex3f( 1.0f,-1.0f, 0.0f);    // Справа снизу
    glEnd();

    glRotatef(5.0, 1.0, 2.0, 3.0); 
    glTranslatef(-4.0, -5.0, -6.0); 

}

Автор: 5kill 2.6.2011, 08:45
Не понятно как у тебя происходит инициализация, можешь привести весь код, много у тебя быть не должно.

Автор: Prolss 2.6.2011, 14:17
Цитата(5kill @ 2.6.2011,  08:45)
Не понятно как у тебя происходит инициализация, можешь привести весь код, много у тебя быть не должно.

5kill, Ну например вот:
Код

#include <windows.h>        // Заголовочный файл для Windows
#include <gl\gl.h>            // Заголовочный файл для OpenGL32 библиотеки
#include <gl\glu.h>            // Заголовочный файл для GLu32 библиотеки
#include <gl\glaux.h>        // Заголовочный файл для GLaux библиотеки

static HGLRC hRC;        // Постоянный контекст рендеринга
static HDC hDC;            // Приватный контекст устройства GDI

BOOL    keys[256];        // Массив для процедуры обработки клавиатуры

GLvoid InitGL(GLsizei Width, GLsizei Height)    // Вызвать после создания окна GL
{
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
                            // Очистка экрана в черный цвет
    glClearDepth(1.0);        // Разрешить очистку буфера глубины
    glDepthFunc(GL_LESS);    // Тип теста глубины
    glEnable(GL_DEPTH_TEST);// разрешить тест глубины
    glShadeModel(GL_SMOOTH);// разрешить плавное цветовое сглаживание
    glMatrixMode(GL_PROJECTION);// Выбор матрицы проекции
    glLoadIdentity();        // Сброс матрицы проекции
    gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
                            // Вычислить соотношение геометрических размеров для окна
    glMatrixMode(GL_MODELVIEW);// Выбор матрицы просмотра модели
}

GLvoid ReSizeGLScene(GLsizei Width, GLsizei Height)
{
    if (Height==0)        // Предотвращение деления на ноль, если окно слишком мало
        Height=1;

    glViewport(0, 0, Width, Height);
        // Сброс текущей области вывода и перспективных преобразований

    glMatrixMode(GL_PROJECTION);// Выбор матрицы проекций
    glLoadIdentity();            // Сброс матрицы проекции

    gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
        // Вычисление соотношения геометрических размеров для окна
    glMatrixMode(GL_MODELVIEW);    // Выбор матрицы просмотра модели
}
//######################################################################
GLvoid DrawGLScene(GLvoid)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    
    glLoadIdentity();    
    glTranslatef(-1.5f,0.0f,-6.0f);    
    glBegin(GL_TRIANGLES);
        glVertex3f( 0.0f, 1.0f, 0.0f);    // Вверх
        glVertex3f(-1.0f,-1.0f, 0.0f);    // Слева снизу
        glVertex3f( 1.0f,-1.0f, 0.0f);    // Справа снизу
    glEnd();

}

LRESULT CALLBACK WndProc(
                HWND    hWnd,
                UINT    message,
                WPARAM    wParam,
                LPARAM    lParam)
{
    RECT    Screen;        // используется позднее для размеров окна
    GLuint    PixelFormat;
    static    PIXELFORMATDESCRIPTOR pfd=
    {
        sizeof(PIXELFORMATDESCRIPTOR),    // Размер этой структуры
        1,                // Номер версии (?)
        PFD_DRAW_TO_WINDOW |// Формат для Окна
        PFD_SUPPORT_OPENGL |// Формат для OpenGL
        PFD_DOUBLEBUFFER,// Формат для двойного буфера
        PFD_TYPE_RGBA,    // Требуется RGBA формат
        16,                // Выбор 16 бит глубины цвета
        0, 0, 0, 0, 0, 0,// Игнорирование цветовых битов (?)
        0,                // нет буфера прозрачности
        0,                // Сдвиговый бит игнорируется (?)
        0,                // Нет буфера аккумуляции
        0, 0, 0, 0,        // Биты аккумуляции игнорируются (?)
        16,                // 16 битный Z-буфер (буфер глубины)  
        0,                // Нет буфера траффарета
        0,                // Нет вспомогательных буферов (?)
        PFD_MAIN_PLANE,    // Главный слой рисования
        0,                // Резерв (?)
        0, 0, 0            // Маски слоя игнорируются (?)
    };
    switch (message)    // Тип сообщения
    {
        case WM_CREATE:
        hDC = GetDC(hWnd);    // Получить контекст устройства для окна
        PixelFormat = ChoosePixelFormat(hDC, &pfd);
            // Найти ближайшее совпадение для нашего формата пикселов
        if (!PixelFormat)
        {
            MessageBox(0,"Can't Find A Suitable PixelFormat.","Error",MB_OK|MB_ICONERROR);
            PostQuitMessage(0);
            // Это сообщение говорит, что программа должна завершится
            break;    // Предтовращение повтора кода
        }
        if(!SetPixelFormat(hDC,PixelFormat,&pfd))
        {
            MessageBox(0,"Can't Set The PixelFormat.","Error",MB_OK|MB_ICONERROR);
            PostQuitMessage(0);
            break;
        }
        hRC = wglCreateContext(hDC);
        if(!hRC)
        {
            MessageBox(0,"Can't Create A GL Rendering Context.","Error",MB_OK|MB_ICONERROR);
            PostQuitMessage(0);
            break;
        }
        if(!wglMakeCurrent(hDC, hRC))
        {
            MessageBox(0,"Can't activate GLRC.","Error",MB_OK|MB_ICONERROR);
            PostQuitMessage(0);
            break;
        }
        GetClientRect(hWnd, &Screen);
        InitGL(Screen.right, Screen.bottom);
        break;

        case WM_DESTROY:
        case WM_CLOSE:
        ChangeDisplaySettings(NULL, 0);

        wglMakeCurrent(hDC,NULL);
        wglDeleteContext(hRC);
        ReleaseDC(hWnd,hDC);

        PostQuitMessage(0);
        break;

        case WM_KEYDOWN:
        keys[wParam] = TRUE;
        break;

        case WM_KEYUP:
        keys[wParam] = FALSE;
        break;

        case WM_SIZE:
        ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));
        break;

        default:
    return (DefWindowProc(hWnd, message, wParam, lParam));
    }
    return (0);
}

int WINAPI WinMain(
        HINSTANCE hInstance,
        HINSTANCE hPrevInstance, 
        LPSTR lpCmdLine,
        int nCmdShow)
{
    MSG        msg;    // Структура сообщения Windows
    WNDCLASS    wc; // Структура класса Windows для установки типа окна
    HWND        hWnd;// Сохранение дискриптора окна

    wc.style            = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc.lpfnWndProc        = (WNDPROC) WndProc;
    wc.cbClsExtra        = 0;
    wc.cbWndExtra        = 0;
    wc.hInstance        = hInstance;
    wc.hIcon            = NULL;
    wc.hCursor            = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground    = NULL;
    wc.lpszMenuName        = NULL;
    wc.lpszClassName    = "OpenGL WinClass";

    if(!RegisterClass(&wc))
    {
    MessageBox(0,"Failed To Register The Window Class.","Error",MB_OK|MB_ICONERROR);
    return FALSE;
    }

    hWnd = CreateWindow(
    "OpenGL WinClass",
    "Jeff Molofee's GL Code Tutorial ... NeHe '99",    // Заголовок вверху окна

    WS_POPUP |
    WS_CLIPCHILDREN |
    WS_CLIPSIBLINGS,

    0, 0,            // Позиция окна на экране
    640, 480,        // Ширина и высота окна

    NULL,
    NULL,
    hInstance,
    NULL);

    if(!hWnd)
    {
    MessageBox(0,"Window Creation Error.","Error",MB_OK|MB_ICONERROR); 
        return FALSE;
    }

    DEVMODE dmScreenSettings;            // Режим работы

    memset(&dmScreenSettings, 0, sizeof(DEVMODE));    // Очистка для хранения установок
    dmScreenSettings.dmSize    = sizeof(DEVMODE);        // Размер структуры Devmode
    dmScreenSettings.dmPelsWidth    = 640;            // Ширина экрана
    dmScreenSettings.dmPelsHeight    = 480;            // Высота экрана
    dmScreenSettings.dmFields    = DM_PELSWIDTH | DM_PELSHEIGHT;    // Режим Пиксела
    ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
    // Переключение в полный экран

    ShowWindow(hWnd, SW_SHOW);
    UpdateWindow(hWnd);
    SetFocus(hWnd);

    while (1)
    {
        // Обработка всех сообщений
        while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
        {
            if (GetMessage(&msg, NULL, 0, 0))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            else
            {
                return TRUE;
            }
        }

        DrawGLScene();                // Нарисовать сцену
        SwapBuffers(hDC);            // Переключить буфер экрана
        if (keys[VK_ESCAPE]) SendMessage(hWnd,WM_CLOSE,0,0);    // Если ESC - выйти
    }
}



 PS: это простой урок от NeHe, а как передвинуть например в право этот треугольник..

Автор: Vetos 2.6.2011, 16:48
Преписываешь так:
Код

GLvoid DrawGLScene(GLvoid)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    
    glLoadIdentity();    
    glTranslatef(-1.5f+Move,0.0f,-6.0f);    
    glBegin(GL_TRIANGLES);
        glVertex3f( 0.0f, 1.0f, 0.0f);    // Вверх
        glVertex3f(-1.0f,-1.0f, 0.0f);    // Слева снизу
        glVertex3f( 1.0f,-1.0f, 0.0f);    // Справа снизу
    glEnd();
Move+=0.1f;
}

Move делаешь глобальной
Код

GLfloat Move = 0.0f;

Автор: Prolss 2.6.2011, 17:05
Vetos5kill,   спасибо вам что подсказали алгоритм движения.. У меня получилось когда я уменьшил скорость движения до 0.0007, после этого увидел как на экране промелькнул объект smile

PS: кто ещё, какие знает способы перемещения?

Автор: Prolss 2.6.2011, 23:40
Vetos , Если я тебя ещё не "достал", ты говорил:  Ну это можно сделать обычными glRotate, просто вначале нужно перенести центр координат в точку другого объекта вокруг которого ты будешь вращать, если по сферическим координатам, т.е. 2 угла то через синус и косинус.  Пожалуйсто если можно, чуть-чуть по-подробней, а то мне эта запись не даёт покоя  smile)

Автор: Vetos 3.6.2011, 20:15
Ну смотри, допустим один объек стоит у тебя в точке 2,3,2.
Код

glTranslatef(2,3,2);
draw();//рисуешь первый объект.

Далее ты крутишь второй еще не нарисованный объект на какойто угол вокруг оси Y:
Код

glRotatef(30,0.0f,1.0f,0.0f);


Далее ты смещаешь второй объект относительно первого, допустим влево(хотя если ты поворачиваешь на угол 180, то объект фактически будет находится справа):
Код

glTranslatef(-5.0f, 0.0f, 0.0f);
draw();//рисуешь второй объект


Вот и все! Если ты неможешь понять как это работает, то тебе остается только эксперементировать smile 

Автор: Prolss 4.6.2011, 20:06
Цитата(Vetos @ 3.6.2011,  20:15)
Вот и все! Если ты неможешь понять как это работает, то тебе остается только эксперементировать smile

Vetos, Благодарю в 102 раз, я разобрался... 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)