• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

VS2010 - MD2 animation

Started by Patrice Terrier, August 26, 2010, 11:45:51 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Patrice Terrier

In my effort to learn C++, i have translated my PB's MD2 animation to work with VS2010.

And here is the result:

//+--------------------------------------------------------------------------+
//|                                                                          |
//|                               GDImageMD2                                 |
//|                              Version 1.00                                |
//|                                                                          |
//|      OpenGL project using the GDImage flat API to create on the fly      |
//|             MD2 object with smooth shading and ambient light.            |
//|                                                                          |
//|             The MD2 engine is based on Petr Schreiber's work             |
//|                           psch.thinbasic.com                             |
//|                                                                          |
//|          The GDImage.dll unregistered version has no limitation,         |
//|             and all features of the API are fully functional.            |
//|                                                                          |
//|       Buying a commercial license removes the copyright nag screen.      |
//|                                                                          |
//+--------------------------------------------------------------------------+
//|                                                                          |
//|                         Author Patrice TERRIER                           |
//|                           copyright (c) 2010                             |
//|                                                                          |
//|                        pterrier@zapsolution.com                          |
//|                                                                          |
//|                          www.zapsolution.com                             |
//|                                                                          |
//+--------------------------------------------------------------------------+
//|                  Project started on : 08-23-2010 (MM-DD-YYYY)            |
//|                        Last revised : 08-26-2010 (MM-DD-YYYY)            |
//+--------------------------------------------------------------------------+

#include <windows.h>  // Search along the path.
#include <windowsx.h>  // Search along the path.
//#include <stdlib.h>   // Search along the path.
//#include <tchar.h>    // Search along the path.
//#include <stdio.h>    // Search along the path.
#include <gl\GL.h>
#include <gl\GLU.h>
#pragma comment( lib, "opengl32.lib" )    // Search For OpenGL32.lib While Linking.
#pragma comment( lib, "glu32.lib" )       // Search For GLu32.lib While Linking.

#include <iostream>   // Search along the path.
#include <string.h>   // Search along the path.
using namespace std;

#include "zTrace.h"   // Search in the same directory of the current file.
#include "WinLIFT.h"  // Search in the same directory of the current file.
#include "GDImage.h"
#include "MD2ex.h"

#define _SCL_SECURE_NO_WARNINGS // No warning message when using sprintf, strcopy, etc.

#define NM_FIRST            0
#define NM_AUDIOCOMPLETION  NM_FIRST - 80
#define NM_MOVIEPLAYING     NM_FIRST - 81

#define TBS_AUTOTICKS       0x0001
#define TBS_HORZ            0x0000
#define TBS_VERT            0x0002
#define TBS_BOTTOM          0x0000
#define TBM_GETPOS          WM_USER
#define TBM_SETPOS          WM_USER + 5
#define TBM_SETRANGE        WM_USER + 6
#define TBM_SETTICFREQ      WM_USER + 20
#define TBM_SETPAGESIZE     WM_USER + 21
#define TBM_SETLINESIZE     WM_USER + 23

#define MyWindowWidth       668
#define MyWindowHeight      532

#define IDC_GLCTRL          -100
#define IDC_ZOOM            -101
#define IDC_LABEL           -102
#define IDC_CLOCK           -103
#define IDC_LOGO            -104
#define IDC_TIMER           -105

typedef struct {
    float radius;
    float barsize;
    float xoff;
    float yoff;
    float zoff;
    float xrot;
    float yrot;
    float xcpy;
    float ycpy;
    int move;
    int xdown;
    int ydown;
    int mouseDown;
    int listIndex;
} THISOBJECT;

// Global variables
HINSTANCE g_hInst;    // Current instance
HWND g_hGLcontrol, g_hMain;
WNDPROC g_hGLproc;
THISOBJECT glObj;
GLUquadric* g_quadObj;
ZGLTEXTURE_EX mt[10];
ZGLFONT g_UseFont;
float g_fUseFrame;
int g_MaxFrame, g_mtCount;
string g_sResource;

// Declaration of the functions being used in this module:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK glWndProc(HWND, UINT, WPARAM, LPARAM);
string  FullExeName();
string  ExePath();
void    ComboSelectPlus (HWND hCombo, int nSelected);
int     GetStaticValue(string sUseString);
void    SetStaticValue(string sUseString, int nValue);
void    UseThisZoom(int nPos);
void    UseThisPhoto(string sUsePhoto, int bReset);
void    InitializeGL();

int WINAPI WinMain(HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPTSTR lpCmdLine,
                    int nCmdShow) {

    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    char szWindowClass[] = "ZMD2DISPLAY";

    //HANDLE hMutex = CreateMutex(NULL, 0, szWindowClass);
    //if (hMutex) {
    //   if (GetLastError() == ERROR_ALREADY_EXISTS) {
    //   }
    //}

    // Load WinLIFT.dll and GDImage.dll.
    if (LoadDLL_WinLIFT()) {
       if (LoadDLL_GDImage()) {
          // We must initialize GDImage using the private key
          ZI_LoadDLL(""); }
       else {
          //Error("Unable to start GDImage")
          return GetLastError();
       }
       LoadDLL_MD2ex(); }
    else {
       //Error("Unable to start WinLIFT")
       return GetLastError();
    }

    // Declaration of local variables
    MSG msg;
    int K = 0;
    int nRet = 0;
    int IsInitialized = 0;
    WNDCLASSEXA wcx;
    POINT p;
    RECT lpr;
    //TCHAR szWindowClass[] = _T("ZHUDPLUS");
    //TCHAR szTitle[] = _T("HUD window");
    string sTitle = "GDImage control "; sTitle += ZI_Version(); sTitle += " - MD2 demo";
    char szTitle[260] =  ""; strncpy_s(szTitle, sTitle.c_str(), sTitle.size());

    // Register the main window class
    wcx.cbSize = sizeof(wcx);
    IsInitialized = GetClassInfoExA(hInstance, szWindowClass, &wcx);
    if (!IsInitialized)
    {
       wcx.style         = CS_HREDRAW | CS_VREDRAW;
       wcx.lpfnWndProc   = WndProc;
       wcx.cbClsExtra    = 0;
       wcx.cbWndExtra    = 0;
       wcx.hInstance     = hInstance;
       wcx.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
       wcx.hCursor       = LoadCursor(NULL, IDC_ARROW);
       wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
       wcx.lpszMenuName  = NULL;
       wcx.lpszClassName = szWindowClass;
       wcx.hIconSm       = LoadIcon(wcx.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
       if (RegisterClassExA(&wcx))
       {
          IsInitialized = -1;
       }
    }

    if (IsInitialized) {

       g_hInst = hInstance; // Stocke le handle d'instance dans la variable globale

       DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
       DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
       SetRect(&lpr, 0, 0, MyWindowWidth, MyWindowHeight);
       AdjustWindowRectEx(&lpr, dwStyle, FALSE, dwExStyle);

       int w = lpr.right - lpr.left;
       int h = lpr.bottom - lpr.top;
       int x = max((GetSystemMetrics(SM_CXSCREEN) - w) / 2, 0);
       int y = max((GetSystemMetrics(SM_CYSCREEN) - h) / 2, 0);

       g_hMain    = CreateWindowExA(
                    dwExStyle,                      // Optional window styles.
                    szWindowClass,                  // Window class
                    szTitle,                        // Window text
                    dwStyle,                        // Window style

                    // Size and position
                    x, y, w, h,

                    NULL,       // Parent window
                    NULL,       // Menu
                    hInstance,  // Instance handle
                    NULL        // Additional application data
                    );

       if (g_hMain) {

          g_hGLcontrol = CreateWindowExA(0, GLImageClassName, NULL,
                                         WS_CHILD | WS_VISIBLE,
                                         10, 10, 512, 512,
                                         g_hMain, (HMENU) IDC_GLCTRL,
                                         hInstance, NULL);
          // Subclass the OpenGL control
          if (g_hGLcontrol) {
             g_hGLproc = (WNDPROC) SetWindowLongPtr(g_hGLcontrol, GWL_WNDPROC, (LONG) glWndProc);
          }
          ZI_SetAnchorMode(g_hGLcontrol, ANCHOR_HEIGHT_WIDTH); // Anchor the control (make it a resizable)

          HWND hCtrl   = CreateWindowExA(0, "MSCTLS_TRACKBAR32", NULL,
                                         WS_CHILD | WS_VISIBLE | WS_TABSTOP | TBS_HORZ | TBS_BOTTOM | TBS_AUTOTICKS,
                                         537, 457, 120, 16,
                                         g_hMain, (HMENU) IDC_ZOOM,
                                         hInstance, NULL);
          ZI_SetAnchorMode(hCtrl, ANCHOR_BOTTOM_RIGHT);
          // Setup the trackbar parameters.
          SendMessage(hCtrl, TBM_SETPAGESIZE, 0, 1);
          SendMessage(hCtrl, TBM_SETLINESIZE, 0, 1);
          SendMessage(hCtrl, TBM_SETTICFREQ, 0, 1);
          SendMessage(hCtrl, TBM_SETRANGE, 1, MAKELONG(1, 100)); // Set the zoom range
          SendMessage(hCtrl, TBM_SETPOS, 1, 50);

          string sExePath = ExePath();
          g_sResource = sExePath; g_sResource += "Resource\\";
          g_mtCount = 2; // sizeof(mt) / sizeof(mt[0]);
          string str;
          str = g_sResource; str += "Background.jpg"; strcpy_s(mt[0].szFullName, str.c_str()); mt[0].ID = 1; mt[0].nSquare = 0;
          str = g_sResource; str += "Dragon.png";     strcpy_s(mt[1].szFullName, str.c_str()); mt[1].ID = 2; mt[1].nSquare = 0;


          MD2_MakeMultipleTexture(mt, g_mtCount);
          for (K = 1; K < g_mtCount; K++) { str = mt[K].szFullName; str = str.substr(0, str.rfind(".")); str += ".md2"; strcpy_s(mt[K].szFullName, str.c_str()); }

          InitializeGL();

          strcpy_s(g_UseFont.fontName, "Pristina");
          g_UseFont.fontHeight = 14;
          g_UseFont.fontWeight = FW_BOLD;
          g_UseFont.fontHandle = 0;
          ZI_BuildGLfont(ZI_GetGLDC(g_hGLcontrol), g_UseFont); // Build OpenGL font for our OpenGL window

          string SkinTheme = ExePath(); SkinTheme += "Sony.sks";
          if (skInitEngine (SkinTheme, "")) {

             skSkinWindow(g_hMain, "Dock|Undock|Minimize|Maximize|Restore|Close");

             // Add a skinned border around the GDImage control.
             GetWindowRect(g_hGLcontrol, &lpr);
             p.x = lpr.left; p.y = lpr.top;
             ScreenToClient(g_hMain, &p);
             skBorder(g_hGLcontrol, p.x - 1, p.y - 1, lpr.right - lpr.left + 2, lpr.bottom - lpr.top + 2, 0, 1);

             // Add a clock control.
             string sResource = g_sResource; sResource += "Clock_09_92.png";
             hCtrl = skClockCtrl(g_hMain, sResource, p.x + lpr.right - lpr.left + 28, p.y, 0, 0, IDC_CLOCK, 0x7FCB0000, 0x7F8F8F8F, 0);
             skSetAnchorCtrl(hCtrl, ANCHOR_RIGHT);           // Anchor control
             skCreateToolTip(hCtrl, "WinLIFT clock widget"); // Add tooltip.

             // Add a static control to display the help text.
             GetClientRect(g_hMain, &lpr);
             char szMessage[] = "Mouse buttons\n\nLeft: rotation, and view angle.\n\nRight: new X,Y location.";
             hCtrl = CreateWindowExA(0, "STATIC", szMessage, WS_CHILD | WS_VISIBLE | SS_CENTER | WS_BORDER,
                                     lpr.right - (129 + 8), 10 + (22 + 5) * 5 + 5, 129, 135, g_hMain, (HMENU) IDC_LABEL, hInstance, NULL);
             // Skin the static control on the fly.
             skSkinChildCtrl(hCtrl, 0);
             ZI_SetAnchorMode(hCtrl, ANCHOR_RIGHT);
             // Use a custom font with the static control.
             skSetLabelFont(hCtrl, "TREBUCHET MS", 15, skARGB(200, 255,255,255), FontStyleBold);

             // Diplay the GDImage logo.
             sResource = g_sResource; sResource += "GDImage.png";
             hCtrl = skStaticImage(g_hMain, sResource, lpr.right - (129 + 6), 350, 124, 45, IDC_LOGO);
             ZI_SetAnchorMode(hCtrl, ANCHOR_BOTTOM_RIGHT);

             ShowWindow(g_hMain, nCmdShow);
             SetForegroundWindow(g_hMain);
             SetFocus(g_hMain);

             // Main message loop
             SetTimer(g_hMain, IDC_TIMER, 0, 0);
             while (GetMessage(&msg, NULL, 0, 0)) {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
             }
             KillTimer(g_hMain, IDC_TIMER);
             nRet = msg.wParam;

          }

          // Free OpenGL resources.
          if (g_quadObj) { gluDeleteQuadric(g_quadObj); }  // OpenGL quadric onject
          if (g_mtCount) {
             for (K = 1; K < g_mtCount; K++) { MD2_Delete(K); }
             MD2_DestroyTexture (mt, g_mtCount);
          }

       }
    }

    return nRet;
}

void InitObject() {

    glObj.xoff = 0.0;  // Initial x location.
    glObj.yoff = 0;    // Initial y location.
    glObj.zoff = -4;   // Initial zoom factor.

    glObj.xrot = 45.0;
    glObj.yrot = -30.0;

    glObj.radius = 2.0;

}

void InitializeGL() {

    InitObject();
    glEnable(GL_TEXTURE_2D);
    glDepthFunc(GL_LESS);
    glEnable(GL_DEPTH_TEST);
    glShadeModel(GL_SMOOTH);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

    g_quadObj = gluNewQuadric();
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);
    glEnable(GL_LINE_SMOOTH);
    gluQuadricNormals(g_quadObj, GLU_SMOOTH);

    GLfloat LightDiffuse[] = { 1.0f, 1.0f, -0.8f, 1.0f };
    GLfloat LightAmbient[] = { 0.3f, 0.3f, -1.3f, 1.0f };
    GLfloat LightPosition[] = { -50.0f, 150.0f, -100.0f, 1.0f };

    glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);    // Setup the Diffuse Light
    glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);    // Setup the Ambient Light
    glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);  // Position the Light

    glMaterialfv(GL_FRONT, GL_SPECULAR, LightDiffuse);

    GLfloat red_emission[] = { 50.0f, -0.0f, 0.0f, 0.0f }; glMaterialfv(GL_FRONT, GL_EMISSION, red_emission);
    GLfloat low_shininess[] = { 5.0f }; glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);

    glEnable(GL_LIGHT1);                                    // Enable Light ONE

    glEnable(GL_LIGHTING);                                  // Enable Lighting
    glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
    glEnable(GL_COLOR_MATERIAL);                            // Enable Coloring Of Material

    MD2_Load(1, mt[1].szFullName, mt[1].nTexture, mt[1].nWidth, mt[1].nHeight);
    g_MaxFrame =  MD2_GetFrameCount(1);
    g_fUseFrame = 1.0f;

}

void DrawBackground() {
    glBindTexture(GL_TEXTURE_2D, mt[0].nTexture);
    glBegin(GL_QUADS);
       glTexCoord2f(0.0, 0.0); glVertex3f(-80,-40,-80.0); // Bottom Left Of The Texture And Quad
       glTexCoord2f(1.0, 0.0); glVertex3f( 80,-40,-80.0); // Bottom Right Of The Texture And Quad
       glTexCoord2f(1.0, 1.0); glVertex3f( 80, 40,-80.0); // Top Right Of The Texture And Quad
       glTexCoord2f(0.0, 1.0); glVertex3f(-80, 40,-80.0); // Top Left Of The Texture And Quad
    glEnd();
}

void SetZoom(int Zoom) {
    ZI_SetGLzoom(g_hGLcontrol, Zoom);
    ZI_ResizeGLWindow(g_hGLcontrol);
}

void RenderOpenGL() {
    int K, ZoomIs;
    static int TextColor;

    // Save current zoom, then switch to a fixed zoom for the background.
    ZoomIs = ZI_GetGLzoom(g_hGLcontrol);
    SetZoom(50);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    // Draw fixed background image
    DrawBackground();

    // Restore the previously saved zoom.
    SetZoom(ZoomIs);

    glTranslatef(glObj.xoff, glObj.yoff, glObj.zoff);

    glRotatef(glObj.xrot, 1.0f, 0.0f, 0.0f);
    glRotatef(glObj.yrot, 0.0f, 1.0f, 0.0f);


    glPushMatrix();
        glScalef(0.025f, 0.025f, 0.025f);
        for (K = 1; K < g_mtCount; K++) {
            MD2_Draw(K, g_fUseFrame);
        }
    glPopMatrix();

    glTranslatef(2.0f * glObj.radius, 0.0f, 0.0f);
    glTranslatef(-2.0f * glObj.radius, 0.0f, 2.0f * glObj.radius + 0.5f);

    // Display the x,y location, and the current zoom value
    if (TextColor == 0) { TextColor = ZD_ColorARGB(255, RGB(247, 225, 125)); }
    char zString[64];
    sprintf_s(zString,"Horizontal  %.2f", glObj.xoff);
    ZI_DrawGLText(g_hGLcontrol, g_UseFont, 7, 10, zString, TextColor);
    sprintf_s(zString, "Vertical  %.2f", glObj.yoff + 12);
    ZI_DrawGLText(g_hGLcontrol, g_UseFont, 23, 10 + g_UseFont.fontHeight, zString, TextColor);
    sprintf_s(zString, "Zoom  %d", 100 - ZoomIs);
    ZI_DrawGLText(g_hGLcontrol, g_UseFont, 41, 10 + g_UseFont.fontHeight * 2, zString, TextColor);
    sprintf_s(zString, "Frame  %.0f / %d", g_fUseFrame, g_MaxFrame);
    ZI_DrawGLText(g_hGLcontrol, g_UseFont, 33, 10 + g_UseFont.fontHeight * 3, zString, TextColor);

    // Update the display
    ZI_UpdateGLWindow(g_hGLcontrol);

}

void PaintMain(HWND hWin) {
    PAINTSTRUCT ps;
    BeginPaint(hWin, &ps);
    EndPaint(hWin, &ps);

    RenderOpenGL();
}

// Main winproc
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {

    int nRet;

    switch (uMsg) {

    case WM_SIZE:
         ZI_ResizeGLWindow(g_hGLcontrol);
         RenderOpenGL();
         break;

    case WM_HSCROLL:
         nRet = GetDlgCtrlID((HWND) lParam);
         if (nRet == IDC_ZOOM) {
            SetZoom(101 - SendMessageA((HWND) lParam, TBM_GETPOS, 0, 0)); // Do not use nPosition, because it could be NULL.
            RenderOpenGL();
         }
         break;

    case WM_TIMER:
         static DWORD nTempo;
         if (nTempo < GetTickCount()) {
            g_fUseFrame += 0.25; if (g_fUseFrame > g_MaxFrame) { g_fUseFrame = 1; }
            nTempo = GetTickCount() + 30; // 33 FPS ~= 30 ticks
            RenderOpenGL();
         }
         return 0;

    case WM_PAINT:
         PaintMain(hWnd);
         return 0;

    case WM_DESTROY:
         ZI_DeleteGLFont(g_UseFont);
         PostQuitMessage(0);
         return 0;
    }

    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

string FullExeName() {
    string sResult;
    char exepath[MAX_PATH];
    if (GetModuleFileNameA(0, exepath, sizeof(exepath))) {
       sResult = exepath;
    }
    return sResult;
}

string ExePath() {
    string sResult;
    char exepath[MAX_PATH];
    if (GetModuleFileNameA(0, exepath, sizeof(exepath))) {
       sResult = exepath;
       sResult = sResult.substr( 0, sResult.rfind("\\"));
       sResult += "\\";
    }
    return sResult;
}

LRESULT CALLBACK glWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    RECT lpr;
    int x, y, dx, dy;
    static int LeftMousing, RightMousing, wasLX, wasLY, wasRX, wasRY;

    switch (uMsg) {

    case WM_PAINT:
         RenderOpenGL();
         break;

    case WM_LBUTTONDOWN:
         if (!LeftMousing) {
            x = GET_X_LPARAM(lParam); y = GET_Y_LPARAM(lParam);
            glObj.xcpy = glObj.xrot;
            glObj.ycpy = glObj.yrot;

            glObj.xdown = x;
            glObj.ydown = y;
            LeftMousing = TRUE;
         }
         if (GetFocus() != hWnd) { SetFocus(hWnd); }
         break;

    case WM_LBUTTONUP:
         LeftMousing = FALSE;
         break;

    case WM_RBUTTONDOWN:
         if (!RightMousing) {
            x = GET_X_LPARAM(lParam); y = GET_Y_LPARAM(lParam);
            glObj.xcpy = glObj.xoff;
            glObj.ycpy = glObj.yoff;

            glObj.xdown = x;
            glObj.ydown = y;
            RightMousing = TRUE;
         }
         if (GetFocus() != hWnd) { SetFocus(hWnd); }
         break;

    case WM_RBUTTONUP:
         RightMousing = FALSE;
         break;

    case WM_MOUSEMOVE:
         x = GET_X_LPARAM(lParam); y = GET_Y_LPARAM(lParam);
         if (!ZI_IsLButtonDown()) {
            LeftMousing = FALSE; }
         else {
            if ((wasLX != x) | (wasLY != y)) {
               if (LeftMousing) {
                  dx = x - glObj.xdown; glObj.yrot = glObj.ycpy + dx / 2.0f;
                  dy = y - glObj.ydown; glObj.xrot = glObj.xcpy + dy / 2.0f;
               }
               RenderOpenGL();
            }
            wasLX = x; wasLY = y;
         }

         if (!ZI_IsRButtonDown()) {
            RightMousing = FALSE; }
         else {
            if ((wasLX != x) | (wasLY != y)) {
               if (RightMousing) {
                   GetClientRect(g_hGLcontrol, &lpr);
                   dx = x - glObj.xdown; glObj.xoff = glObj.xcpy - (-45 * dx) / (12.0f * lpr.right);  // Use 12.0 instead of 2.0 to reduce sensitivity
                   dy = y - glObj.ydown; glObj.yoff = glObj.ycpy + (-45 * dy) / (12.0f * lpr.bottom); // Use 12.0 instead of 2.0 to reduce sensitivity
               }
               RenderOpenGL();
            }
            wasRX = x; wasRY = y;
         }


         break;
    }

    return CallWindowProc(g_hGLproc, hWnd, uMsg, wParam, lParam);
}


As you can see on the attached screen shot, the C++ version looks exactly the same than the PB's.

C++, is a real challenge for me, i did from my best with my current knowledge of the language, but if you think that my code could be optimized, please let me know (as i am still learning) thank you!

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

#1
Here is another MD2 demo running 3 animations altogether.

This one is provided with the latest header files for MD2ex, WinLIFT, and GDImage.

It does use the WinLIFT's theme "Gray.sks".

The complete VS2010 project is provided with the ZIP file attached to this post.

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

All the attachements have been updated, to fix the ZIP file corruption caused by the "Server Collapse".

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com