CUmmObject 4 - Drive_n_GL - управление игровой моделью.
1) Краткое описание. Изменения с прошлых версий.
2) Новые функции (управление).
3) Применение OpenGL.
4) Пример решения - Drive_n_GL.
1) Краткое описание. Изменения с прошлых версий.
С предыдущих версий реализация CUmmObject претерпела следующие изменения :
1) Программая реализация класса теперь разбита на следующие файлы :
- cumm_file.h - определения класса, используемые константы и стуктуры.
- cumm_file.cpp - основные функции - загрузка, анимирование, математика .
- cumm_draw.cpp - отрисовка объекта с помощью USMMain141.dll.
- cumm_opengl.cpp - функции инициализации и отрисовки с помощью OpenGL .
- cumm_grarray.cpp - функции иниациализации графических массивов при работе с USMMain141.dll или данных OpenGL.
2) Изменен заголовок функции LoadObject - теперь в нее передаются (и затем хранятся внутри объекта) параметры о формате цвета и дополнительной длине строки плоскости вывода.
3) Добавлен ряд новых функций (см. ниже).
2) Новые функции (управление).
Новые функции представляют возможность устанавливать дополнительные повороты для сочленений скелета и получать информацию о состоянии сочленения (adb-функции), а также устанавливать "коэффициент масштабирования" - относительную скорость анимаций (ITS-функции).
Отрывки непосредственно из определения класса в файле usm_file.h:
//----------------------------------------------------------------------------------- // adb - функции //получить номер joint с указанным именем (-1, если такого нет) int adbCatchBone (char* name) ; //поставить пределы добавок BOOL adbSetMinMax (int ijoint, BOOL amm, float ammmin, float ammmax, BOOL mmm, float mmmmin, float mmmmax) ; //изменить/получить значение угла BOOL adbSetAngle (int ijoint, float val, int type) ; float adbGetAngle (int ijoint) ; //изменить/получить значение удлиннения BOOL adbSetMul (int ijoint, float val, int type) ; float adbGetMul (int ijoint) ; //получить матрицу поворота и текущее положение кости BOOL adbGetJointData (int ijoint, MATRIX* m, POINT3d& p) ; //----------------------------------------------------------------------------------- // ITS - функции //установить границы коэффициента масштабирования void SetITSMinMax (BOOL bset, float tmin, float tmax) ; //изменить коэффициент масштабирования void SetITS (float its, int type) ; //получить значение коэффициента масштабирования float GetITS () {return itimescale;} ; //----------------------------------------------------------------------------------- // OpenGL //отрисовать через OpenGL void glDraw (int cx, int cy) ; //инициализация / деинициализация объекта для OpenGL BOOL InitForOpenGL () ; void DeInitForOpenGL () ;Все неясности разбираются ниже, в примере.
![]() |
CUMDrawData drawdata ; //данные проецирования CUmmObject *c_niva = NULL ; //машина CUmmObject *c_opfor = NULL ; //человечек int opfor_j ; //это - int car_j [6] ; // индексы сочлелений скелета BOOL move = FALSE ; //флаги BOOL stop = FALSE ; BOOL shot = FALSE ; //после анимации остановки машины void StopCar (void) { if (!move) c_niva -> Stop () ; else c_niva -> SetAnimation (AT_SKELETON, "move", AF_ENDFRAME, 0, StartCar) ; stop = FALSE ; } //после анимации старта машины void StartCar (void) { if (move) c_niva -> SetAnimation (AT_SKELETON, "move", AF_CYCLED, 0, NULL) ; else c_niva -> SetAnimation (AT_SKELETON, "stop", AF_ENDFRAME, 0, StopCar) ; } //после анимации выстрела человечка void ManShot (void) { if (shot) c_opfor -> SetAnimation (AT_SKELETON, "shot", AF_ENDFRAME, 0, ManShot) ; else c_opfor -> SetAnimation (AT_SKELETON, "idle", AF_CYCLED, 0, NULL) ; } //----------------------------------------------------------
void InitObject () { //загрузить джип c_niva = new CUmmObject () ; c_niva -> LoadObject ((bpajero) ? "pj.mod" : "tlc.mod", LOAD_ALL, cumm_bit1516, global_pitch) ; c_niva -> SetDrawData (drawdata) ; c_niva -> SetBaseState () ; c_niva -> SetITSMinMax (TRUE, 0.5f, 4.0f) ; //получить номера нужных сочленений car_j [0] = c_niva -> adbCatchBone ("lf_joint") ; car_j [1] = c_niva -> adbCatchBone ("lb_joint") ; car_j [2] = c_niva -> adbCatchBone ("rf_joint") ; car_j [3] = c_niva -> adbCatchBone ("rb_joint") ; car_j [4] = c_niva -> adbCatchBone ("prodol_j") ; car_j [5] = c_niva -> adbCatchBone ("man_place") ; //установить пределы изменений c_niva -> adbSetMinMax (car_j [0], TRUE, -1.0f, 1.0f, FALSE, 0, 0) ; c_niva -> adbSetMinMax (car_j [2], TRUE, -1.0f, 1.0f, FALSE, 0, 0) ; c_niva -> adbSetMinMax (car_j [4], TRUE, -0.06f, 0.06f, FALSE, 0, 0) ; //то же для человечка c_opfor = new CUmmObject () ; c_opfor -> LoadObject ("opfor.mod", LOAD_ALL, cumm_bit1516, global_pitch) ; c_opfor -> SetDrawData (drawdata) ; c_opfor -> SetAnimation (AT_SKELETON, "idle", AF_CYCLED, 0, NULL) ; opfor_j = c_opfor -> adbCatchBone ("main") ; c_opfor -> adbSetMinMax (opfor_j, TRUE, -1.0f, 1.0f, FALSE, 0, 0) ; //ежли OpenGL - проинициализировать if (opengl_enabled) { c_opfor -> InitForOpenGL () ; c_niva -> InitForOpenGL () ; } }
case WM_KEYDOWN : switch (LOWORD (wParam)) { case VK_UP : //увеличить скорость if (!move) { move = TRUE ; c_niva -> SetAnimation (AT_SKELETON, "start", AF_ENDFRAME, 0, StartCar) ; } else { c_niva -> SetITS (0.2f, ADB_COMPAREIT) ; } break ; case VK_DOWN : //затормозить if (move) { c_niva -> SetITS (-2.0f, ADB_COMPAREIT) ; if (c_niva -> GetITS () <= 1.0f) { c_niva -> SetITS (1.0f, ADB_ABSOLUTE) ; move = FALSE ; stop = TRUE ; c_niva -> SetAnimation (AT_SKELETON, "stop", AF_ENDFRAME, 0, StopCar) ; } } break ; case VK_LEFT : //поворот влево c_niva -> adbSetAngle (car_j [0], 0.05f, ADB_COMPAREIT) ; c_niva -> adbSetAngle (car_j [2], 0.05f, ADB_COMPAREIT) ; c_niva -> adbSetAngle (car_j [4], 0.003f, ADB_COMPAREIT) ; c_opfor -> adbSetAngle (opfor_j, -0.05f, ADB_COMPAREIT) ; break ; case VK_RIGHT : //поворот вправо c_niva -> adbSetAngle (car_j [0], -0.05f, ADB_COMPAREIT) ; c_niva -> adbSetAngle (car_j [2], -0.05f, ADB_COMPAREIT) ; c_niva -> adbSetAngle (car_j [4], -0.003f, ADB_COMPAREIT) ; c_opfor -> adbSetAngle (opfor_j, 0.05f, ADB_COMPAREIT) ; break ; case VK_CONTROL : //стрелять shot = TRUE ; c_opfor -> SetAnimation (AT_SKELETON, "shot", AF_ENDFRAME, 0, ManShot) ; break ; case VK_ESCAPE : SendMessage (hwnd, WM_CLOSE, 0, 0) ; break ; } return 0 ;
void DrawAll () { static MATRIX rot_matrix, matrix, matrix2 ; //определить время int the_time = GetTickCount () ; int delta = the_time - time ; time = the_time ; //------------------------------------------------------------ if (move) { //колеса дергаются вверх и вниз c_niva -> adbSetMul (car_j [0], (rand () % 10) * (0.02f), ADB_ABSOLUTE) ; c_niva -> adbSetMul (car_j [1], (rand () % 10) * (0.02f), ADB_ABSOLUTE) ; c_niva -> adbSetMul (car_j [2], (rand () % 10) * (0.02f), ADB_ABSOLUTE) ; c_niva -> adbSetMul (car_j [3], (rand () % 10) * (0.02f), ADB_ABSOLUTE) ; } //------------------------------------------------------------ if (move || stop) //общий поворот сцены по y оси mouse_b -= c_niva-> GetITS () * 0.0005f * delta * c_niva -> adbGetAngle (car_j [0]) ; //установить матрицы машины SetMRotateG (&rot_matrix, mouse_g) ; SetMRotateB (&matrix, mouse_b) ; rot_matrix = *MulMatrix (&rot_matrix, &matrix) ; c_niva -> IdentityMatrix () ; c_niva -> SetMatrix (&rot_matrix, TRUE) ; c_niva -> Tick (delta, FALSE) ; c_niva -> UseMatrixSettings () ; //установить матрицы человечка c_opfor -> IdentityMatrix () ; //повернуть модель человечка на 90' (в файле она ориентирована не так, как надо :) SetMRotateB (&matrix, -1.57f) ; c_opfor -> SetMatrix (&matrix, TRUE) ; //получить данные о нужном сочленении машины и применить их к человечку POINT3d p ; if (c_niva -> adbGetJointData (car_j [5], &matrix, p)) { c_opfor -> SetMatrix (&matrix, TRUE) ; SetMMove (&matrix, p.x, p.y, p.z) ; c_opfor -> SetMatrix (&matrix, FALSE) ; } SetMRotateG (&rot_matrix, mouse_g) ; SetMRotateB (&matrix, mouse_b) ; rot_matrix = *MulMatrix (&rot_matrix, &matrix) ; c_opfor -> SetMatrix (&rot_matrix, TRUE) ; c_opfor -> Tick (delta, FALSE) ; c_opfor -> UseMatrixSettings () ; //------------------------------------------------------------- // отрисовка if (opengl_enabled) { float* pf = GetR_G_Bfloat (clr_color) ; glClearColor (pf [0], pf [1], pf [2], 1.0f) ; glClear(GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT); c_opfor -> glDraw (cxV, cyV) ; c_niva -> glDraw (cxV, cyV) ; glFlush(); SwapBuffers(wglGetCurrentDC()); } else { CleareBuffers () ; c_opfor -> dxDraw (dbuffer, zbuffer, cxV, cyV) ; c_niva -> dxDraw (dbuffer, zbuffer, cxV, cyV) ; int dsize = cxV*cyV*video_byte + cyV*global_pitch ; SetBitmapBits (hbmp, dsize, dbuffer) ; HDC hdc = GetDC (Ghwnd) ; BitBlt (hdc, 0, 0, cxV, cyV, memdc, 0, 0, SRCCOPY) ; ReleaseDC (Ghwnd, hdc) ; } }