
// 3dw386.cpp

#include "stdgfx.h"
#include "mpgui.h"
#include "mpg3d.h"
#include "dlgs.h"

#define MENU_FILE_OPEN  101
#define MENU_FILE_EXIT  102

#define MENU_DETAIL_FACE 210
  #define MENU_DETAIL_FACE_TEXTURE   211
  #define MENU_DETAIL_FACE_SOLID     212
  #define MENU_DETAIL_FACE_WIREFRAME 213

#define MENU_DETAIL_SHADE 220
  #define MENU_DETAIL_SHADE_GOURAUD  221
  #define MENU_DETAIL_SHADE_FLAT     222
  #define MENU_DETAIL_SHADE_NONE     223

#define MENU_MATERIAL_LOAD             310
  #define MENU_MATERIAL_LOAD_STATIC    311
  #define MENU_MATERIAL_LOAD_ANIMATED  312
  
#define MENU_MATERIAL_TRANSPARENCY      320
  #define MENU_MATERIAL_TRANSPARENCY_10 321  
  #define MENU_MATERIAL_TRANSPARENCY_20 322
  #define MENU_MATERIAL_TRANSPARENCY_30 323  
  #define MENU_MATERIAL_TRANSPARENCY_40 324  
  #define MENU_MATERIAL_TRANSPARENCY_50 325  
  #define MENU_MATERIAL_TRANSPARENCY_60 326  
  #define MENU_MATERIAL_TRANSPARENCY_70 327  
  #define MENU_MATERIAL_TRANSPARENCY_80 328  
  #define MENU_MATERIAL_TRANSPARENCY_90 329  
  #define MENU_MATERIAL_TRANSPARENCY_00 330
    
#define MENU_MATERIAL_AMBIENT           331 

#define MENU_ENVIRONMENT_BACKGROUND     
  #define MENU_ENVIRONMENT_BACKGROUND_LOAD    411
  #define MENU_ENVIRONMENT_BACKGROUND_STATIC  412
  
#define MENU_ENVIRONMENT_DEPTH_CUE   421
#define MENU_ENVIRONMENT_FOG         431

#define MENU_ROTATION_X  510
  #define MENU_ROTATION_X_INC          511
  #define MENU_ROTATION_X_DEC          512
  #define MENU_ROTATION_X_STOP         513
#define MENU_ROTATION_Y  520
  #define MENU_ROTATION_Y_INC          521
  #define MENU_ROTATION_Y_DEC          522
  #define MENU_ROTATION_Y_STOP         523
#define MENU_ROTATION_Z  530
  #define MENU_ROTATION_Z_INC          531
  #define MENU_ROTATION_Z_DEC          532
  #define MENU_ROTATION_Z_STOP         533

#define MENU_HELP_ABOUT              601

//************************************
//
// Main Frame Class
//
//************************************

class MAINFRAME : public GUIFRAME
  {
    protected :
      GUIMENU *Menu;
      G3DSYSTEM *G3D;
      G3DCAMERA *Camera;
      COLORTABLE *ShadeTable;
      COLORTABLE *HazeTable;
      COLORTABLE *BlendTable;
      RGBPALETTE *Pal;
      IMAGE *VScreen;
      IMAGE *BGImage;
      LONG BGColor;
      float NearClipZ;
      float ViewDistance;
      float MaxVisibleDistance;
      float U0,V0;
      float U1,V1;
      float U2,V2;
      float ObjPosX,ObjPosY,ObjPosZ;
      float ObjRotX,ObjRotY,ObjRotZ;
      float LightPosX,LightPosY,LightPosZ;
      INT AmbientRed,AmbientGreen,AmbientBlue;
      INT BGRed,BGGreen,BGBlue;
      LONG NumAnimatedFrames;
      LONG CurAnimatedFrame;
      
      BOOLEAN MapTexture;
      BOOLEAN Initialized;
      BOOLEAN TimerOn;
      BOOLEAN ObjectLoaded;
      BOOLEAN UseBG;
      BOOLEAN AnimatedTexture;

      BOOLEAN Init3D ();
      
      BOOLEAN Load3DFile ( STRING FileName );
      VOID OnFileLoad ();
      VOID OnFog ();
      VOID OnTransparent ( LONG Code );
      
      VOID OnDetail ( LONG Code );
      
      VOID OnLoadTextureStatic ();
      VOID OnLoadTextureAnimated ();
      VOID OnAmbient ();

      VOID OnLoadBG ();
      VOID OnBGStatic ();

      VOID OnDepthCue ();

      VOID OnRotation ( LONG Code );

      VOID OnAbout ();
      
      VOID HandleInput ();
      
      virtual LONG OnCreate ();
      virtual LONG OnCommand ( LONG Command );
      virtual LONG OnClose ();
      virtual LONG OnTimer ();
      virtual LONG OnPosChanging ( WINPOSCHANGE *WinPosChange );
      virtual LONG OnSize ( LONG Width, LONG Height );
      virtual LONG OnPaint ( HDISPLAY hDisplay );
      
    public :
      MAINFRAME ();        
      virtual ~MAINFRAME ();
  }; // Ebd of MAINFRAME

MAINFRAME::MAINFRAME ()
  {
    Menu = new GUIMENU ();
    AddClassStyle ( CS_OWNDC );
    G3D = NULL;
    Camera = NULL;
    ShadeTable = NULL;
    BlendTable = NULL;
    HazeTable = NULL;
    BGImage = NULL;

    NearClipZ = (float)10;
    ViewDistance = (float)200;
    MaxVisibleDistance = (float)3000;

    U0 = (float)0; V0 = (float)0;
    U1 = (float)0; V1 = (float)0.5;
    U2 = (float)0.5; V2 = (float)0.5;

    ObjPosX = (float)0;
    ObjPosY = (float)0; 
    ObjPosZ = (float)500;

    ObjRotX = (float)3;
    ObjRotY = (float)3;
    ObjRotZ = (float)3;

    LightPosX = (float)0;
    LightPosY = (float)0;
    LightPosZ = (float)0;

    AmbientRed = 255;
    AmbientGreen = 0;
    AmbientBlue = 0;
    
    BGRed = 128;
    BGGreen = 128;
    BGBlue = 128;
    
    TimerOn = FALSE;
    MapTexture = FALSE;
    ObjectLoaded = FALSE;
    Initialized = FALSE;
    UseBG = FALSE;

    BGColor = 0;

    NumAnimatedFrames = 0;
    CurAnimatedFrame = 0;
    AnimatedTexture = FALSE;
  } // End of Constructor for MAINFRAME

MAINFRAME::~MAINFRAME ()
  {
    if (G3D!=NULL)
      delete G3D;
    G3D = NULL;

    if (Camera!=NULL)
      delete Camera;
    Camera = NULL;
    
    if (ShadeTable!=NULL)
      delete ShadeTable;
    ShadeTable = NULL;

    if (VScreen!=NULL)
      delete VScreen;
    VScreen = NULL;

    if (BGImage!=NULL)
      delete BGImage;
    BGImage = NULL;    
  } // End of Destructor for MAINFRAME

BOOLEAN MAINFRAME::Init3D ()
  {
    G3D = new G3DSYSTEM ();
    Camera = new G3DCAMERA ();
    
    ShadeTable = new COLORTABLE ();  
    BlendTable = new COLORTABLE ();  
    HazeTable = new COLORTABLE ();
    VScreen = new IMAGE ( IMAGE_BOTTOMUP );

    if (ShadeTable->Load ( "..\\data\\color.tbl" )==FAILURE)
      {
        ShowMessageBox("Error", "Error loading Shade Table", MB_OK);
        return FAILURE;
      } // End if
    if (BlendTable->Load ( "..\\data\\blend.tbl" )==FAILURE)
      {
        ShowMessageBox("Error", "Error loading Blend Table", MB_OK);
        return FAILURE;
      } // End if
    if (HazeTable->Load ( "..\\data\\whaze.tbl" )==FAILURE)
      {
        ShowMessageBox("Error", "Error loading Haze Table", MB_OK);
        return FAILURE;
      } // End if

    Pal = ShadeTable->GetPalette ();
    RGBCOLOR Col;
    Col.Red = (BYTE)BGRed;
    Col.Green = (BYTE)BGGreen;
    Col.Blue = (BYTE)BGBlue;
    BGColor = Pal->GetClosestColor ( Col );
    
    G3D->SetBlendTable ( BlendTable );
    G3D->SetHazing ( FALSE, (float)100, HazeTable );
    G3D->SetNearClipZ ( NearClipZ );
    G3D->SetViewDistance ( ViewDistance );

    G3DMATERIALLIB *MaterialLib = new G3DMATERIALLIB ();
    MaterialLib->CreateTextures ( 1 );
    MaterialLib->CreateMaterials ( 1 );    
    G3D->SetMaterialLib ( MaterialLib );
    
    // Add Material to this Material Library
    G3DMATERIAL *Material;
    Material = MaterialLib->GetMaterial ( 0 );
    Material->SetID ( 0 );
    RGBCOLOR AmbientColor;
    AmbientColor.Red = (BYTE)AmbientRed;
    AmbientColor.Green = (BYTE)AmbientGreen;
    AmbientColor.Blue = (BYTE)AmbientBlue;
    Material->Transparency = 0;
    Material->Ambient = Pal->GetClosestColor ( AmbientColor );

    // Add Texture to this Material
    MaterialLib->LoadTexture ( 0, "..\\data\\checker.pcx", TEXTURE_STATIC, ShadeTable->GetPalette() );      
    Material->SetTexture ( MaterialLib->GetTexture(0) );

    // Set Camera
    Camera->SetPosition ( (float)0, (float)0, (float)0 );
    Camera->SetAngle ( (float)0, (float)0, (float)0 );

    Initialized = TRUE;
    return SUCCESS;
  } // End of Init3D for MAINFRAME

BOOLEAN MAINFRAME::Load3DFile ( STRING FileName )
  {      
    G3DWORLD *World = new G3DWORLD;            
    if (World==NULL)
      return FAILURE;
    
    LINKEDLIST<G3DOBJECT*> *ObjectList = new LINKEDLIST<G3DOBJECT*> ();
    if (G3D->Load3DFile ( FileName, ObjectList, FALSE, 1.0 )==FAILURE)
      {
        ShowMessageBox("Error loading 3D", "Error occured at loading this file", MB_OK);
        delete ObjectList;
        delete World;
        return FAILURE;
      } // End if
      
    G3DLIGHT *Light = new G3DLIGHT ();

    Light->SetName ( "Light01" );
    Light->SetPosition ( LightPosX, LightPosY, LightPosZ );
    Light->SetShadeTable ( ShadeTable );
    Light->SetMaxIntensity ( (float)63 );
    Light->SetMinIntensity ( (float)0 );

    World->AddObject ( Light );

    G3DMATERIAL *Material = G3D->FindMaterialByIndex ( 0 );
    
    LISTOBJECT<G3DOBJECT*> *ObjectNode;
    G3DOBJECT *Object;
    G3DPOLYHEDRON *PolyObject;
    
    ObjectNode = ObjectList->GetHead ();
    while (ObjectNode!=NULL)
      {
        Object = ObjectNode->Data;
        
        if (Object->GetObjectType()==OBJECT_TYPE_POLYHEDRON)
          {
            Object->SetMaxVisibleDistance ( MaxVisibleDistance );
            Object->SetPosition ( ObjPosX, ObjPosY, ObjPosZ );
            Object->SetID ( 1 );

            PolyObject = (G3DPOLYHEDRON*)Object;  
            PolyObject->SetLightSource ( Light );

            PolyObject->SetShadeFlags ( MAX_DETAIL, SHADE_GOURAUD );
            PolyObject->SetFaceFlags ( MAX_DETAIL, FACE_TEXTURE );
            PolyObject->ComputeCenter ();
            PolyObject->ComputeRadius ();

            float Radius;
            float ScaleFactor;
            Radius = PolyObject->GetRadius ();
            if (Radius==0)
              Radius = (float)1;
            ScaleFactor = (float)(250 / Radius);
            PolyObject->SetScaleFactor ( ScaleFactor );
            PolyObject->SetMaterial ( Material );
            if (PolyObject->TextureMapped!=TRUE)
              PolyObject->MapTexture ( U0, V0, U1, V1, U2, V2 );
            
            World->AddObject ( PolyObject );
            ObjectNode->Data = NULL;
            break;
          } // End if
        ObjectNode = ObjectNode->NextObject;  
      } // End while
      
    ObjectList->ClearAllNode ();  
    delete ObjectList;

    G3D->SetWorld ( World, TRUE );
    G3D->Init ();
    return SUCCESS;
  } // End of Load3DFile for MAINFRAME 

VOID MAINFRAME::OnFileLoad ()
  {
    if (TimerOn)
      KillTimer ();
        
    GUIFILEDIALOG *FileDialog;
    FileDialog = new GUIFILEDIALOG ( FD_OPEN );
    FileDialog->CreateExtensions ( 5 );
    FileDialog->SetExtension ( 0, "*.3DS", "Autodesk 3D Studio files (*.3DS)" );
    FileDialog->SetExtension ( 1, "*.ASC", "ASCII files (*.ASC)" );
    FileDialog->SetExtension ( 2, "*.GEO", "View Space files (*.GEO)" );
    FileDialog->SetExtension ( 3, "*.GEM", "Geometry files (*.GEM)" );
    FileDialog->SetExtension ( 4, "*.*", "All files (*.*)" );

    LONG Result;    
    Result = FileDialog->Execute ( this, "File Open" );
    if (Result)
      {
        CHAR FileName[128];
        FileDialog->GetFileName ( FileName );  
        if (Load3DFile ( FileName )==SUCCESS)
          {
            TimerOn = TRUE;
            ObjectLoaded = TRUE;
            SetTimer ( 0 );  
          } // End if
      } // End if
      
    delete FileDialog;
  } // End of Load3DFile for MAINFRAME

VOID MAINFRAME::OnDetail ( LONG Code )
  {
    switch (Code)
      {
        case MENU_DETAIL_FACE_TEXTURE :
          G3D->SetFaceFlags ( FACE_TEXTURE );
          break;  
        case MENU_DETAIL_FACE_SOLID :
          G3D->SetFaceFlags ( FACE_SOLID );
          break;  
        case MENU_DETAIL_FACE_WIREFRAME :
          G3D->SetFaceFlags ( FACE_WIREFRAME );
          break;  

        case MENU_DETAIL_SHADE_GOURAUD :
          G3D->SetShadeFlags ( SHADE_GOURAUD );
          break;  
        case MENU_DETAIL_SHADE_FLAT :
          G3D->SetShadeFlags ( SHADE_FLAT );
          break;  
        case MENU_DETAIL_SHADE_NONE :
          G3D->SetShadeFlags ( SHADE_NONE );
          break;  
      } // End switch  
  } // End of OnDetail for MAINFRAME

VOID MAINFRAME::OnLoadTextureStatic ()
  {
    if (TimerOn)
      KillTimer ();
        
    GUIFILEDIALOG *FileDialog;
    FileDialog = new GUIFILEDIALOG ( FD_OPEN );
    FileDialog->CreateExtensions ( 4 );
    FileDialog->SetExtension ( 0, "*.BMP", "Windows BMP (*.BMP)" );
    FileDialog->SetExtension ( 1, "*.GIF", "CompuServ GIF (*.GIF)" );
    FileDialog->SetExtension ( 2, "*.PCX", "Z Soft PCX (*.PCX)" );
    FileDialog->SetExtension ( 3, "*.*", "All files (*.*)" );

    LONG Result;    
    Result = FileDialog->Execute ( this, "File Open" );
    if (Result)
      {
        CHAR FileName[128];
        FileDialog->GetFileName ( FileName );

        G3DMATERIALLIB *MaterialLib = G3D->GetMaterialLib ();
        
        // Add Texture to this Material
        if (MaterialLib->LoadTexture ( 0, FileName, TEXTURE_STATIC, Pal )==SUCCESS)
          {
            AnimatedTexture = FALSE;    
            NumAnimatedFrames = 0;
            CurAnimatedFrame = 0;
          } // End if
        else  
          {
            ShowMessageBox ( "Error", "Can not load this Texture!", MB_OK );
          } // End else
      } // End if
      
    if (TimerOn)
      SetTimer ( 0 );  
    delete FileDialog;      
  } // End of OnLoadTextureStatic for MAINFRAME

VOID MAINFRAME::OnLoadTextureAnimated ()
  {
    if (TimerOn)
      KillTimer ();
        
    GUIFILEDIALOG *FileDialog;
    FileDialog = new GUIFILEDIALOG ( FD_OPEN );
    FileDialog->CreateExtensions ( 3 );
    FileDialog->SetExtension ( 0, "*.FLI", "Autodesk FLI (*.FLI)" );
    FileDialog->SetExtension ( 1, "*.FLC", "Autodesk FLC (*.FLC)" );
    FileDialog->SetExtension ( 2, "*.*", "All files (*.*)" );

    LONG Result;    
    Result = FileDialog->Execute ( this, "File Open" );
    if (Result)
      {
        CHAR FileName[128];
        FileDialog->GetFileName ( FileName );

        G3DMATERIALLIB *MaterialLib = G3D->GetMaterialLib ();
        
        // Add Texture to this Material
        if (MaterialLib->LoadTexture ( 0, FileName, TEXTURE_FLIC, Pal )==SUCCESS)
          {
            AnimatedTexture = TRUE;    
            NumAnimatedFrames = (MaterialLib->GetTexture(0))->GetNumFrames();
            CurAnimatedFrame = 0;
          } // End if
        else  
          {
            ShowMessageBox ( "Error", "Can not load this Texture!", MB_OK );
          } // End else
      } // End if
      
    if (TimerOn)
      SetTimer ( 0 );  
    delete FileDialog;      
  } // End of OnLoadTextureAnimated for MAINFRAME

VOID MAINFRAME::OnAmbient ()
  {
    AMBIENTDLG *AmbientDlg;

    if (TimerOn)
      KillTimer ();
      
    AmbientDlg = new AMBIENTDLG ();
    if (AmbientDlg->Execute ( this, "AMBIENT_DLG" ))
      {
        RGBCOLOR Col;
        AmbientDlg->GetRGB ( &Col );
        G3DMATERIAL *Material = G3D->FindMaterialByID ( 0 );
        
        Material->Ambient = Pal->GetClosestColor ( Col );  
      } // End if
      
    if (TimerOn)
      SetTimer (0);
      
    delete AmbientDlg;
  } // End of OnAmbient for MAINFRAME

VOID MAINFRAME::OnTransparent ( LONG Code )
  {
    LONG Transparency;
    G3DMATERIAL *Material = G3D->FindMaterialByID ( 0 );

    if (Material==NULL)
      return;
      
    if (Code==MENU_MATERIAL_TRANSPARENCY_00)
      {
        Material->Attributes &= ~MATERIAL_TRANSPARENT;
      } // End if
    else
      {
        Transparency = Code - MENU_MATERIAL_TRANSPARENCY;

        Material->Attributes |= MATERIAL_TRANSPARENT;
        Material->Transparency = Transparency;  
      } // End else  
  } // End of OnTransparent for MAINFRAME

VOID MAINFRAME::OnFog ()
  {
    FOGDLG *FogDlg;

    if (TimerOn)
      KillTimer ();
      
    FogDlg = new FOGDLG ();
    if (FogDlg->Execute ( this, "FOG_DLG" ))
      {
        G3D->SetHazing ( FogDlg->IsFogOn (), FogDlg->GetFogScale(), HazeTable );
        RGBCOLOR Col;
        Col.Red = 255;
        Col.Green = 255;
        Col.Blue = 255;
        BGColor = Pal->GetClosestColor ( Col );
        if (FogDlg->IsFogOn())
          UseBG = FALSE;
        else
          {
            if (BGImage!=NULL)
              UseBG = TRUE;
            else
              {
                RGBCOLOR Col;
                Col.Red = (BYTE)BGRed;
                Col.Green = (BYTE)BGGreen;
                Col.Blue = (BYTE)BGBlue;
                BGColor = Pal->GetClosestColor ( Col );  
              } // End else  
          } // End else  
      } // End if
      
    if (TimerOn)
      SetTimer (0);
      
    delete FogDlg;
  } // End of OnFog for MAINFRAME

VOID MAINFRAME::OnLoadBG ()
  {
    if (TimerOn)
      KillTimer ();

    if (BGImage==NULL)
      BGImage = new IMAGE ( IMAGE_TOPDOWN );
          
    GUIFILEDIALOG *FileDialog;
    FileDialog = new GUIFILEDIALOG ( FD_OPEN );
    FileDialog->CreateExtensions ( 4 );
    FileDialog->SetExtension ( 0, "*.BMP", "Windows BMP (*.BMP)" );
    FileDialog->SetExtension ( 1, "*.GIF", "CompuServ GIF (*.GIF)" );
    FileDialog->SetExtension ( 2, "*.PCX", "Z Soft PCX (*.PCX)" );
    FileDialog->SetExtension ( 3, "*.*", "All files (*.*)" );

    LONG Result;    
    Result = FileDialog->Execute ( this, "File Open" );
    if (Result)
      {
        CHAR FileName[128];
        FileDialog->GetFileName ( FileName );

        // Add Texture to this Material
        RGBPALETTE *NewPal = new RGBPALETTE ();
        if (Grafix.LoadImage ( FileName, BGImage, NewPal )==SUCCESS)
          {
            UseBG = TRUE;  
            HDISPLAY hDisplay = GetDisplay ( hClient );  
            Grafix.AdjustImageSize ( BGImage, Grafix.GetWidth(hDisplay), Grafix.GetHeight(hDisplay) );                                   
            ReleaseDisplay ( hClient, hDisplay );

            if (Pal->IsIdentical(NewPal)!=TRUE)
              {
                COLORTABLE *MatchTable = new COLORTABLE ();
                MatchTable->CopyPalette ( Pal );            
                MatchTable->CreateMatchTable ( NewPal );
                Grafix.ConvertImage ( BGImage, MatchTable );
                delete MatchTable;
              } // End if
          } // End if
        else  
          {
            ShowMessageBox ( "Error", "Can not load this Image!", MB_OK );
          } // End else
        delete NewPal;  
      } // End if

    if (TimerOn)
      SetTimer ( 0 );
    delete FileDialog;      
  } // End of OnLoadBG for MAINFRAME

VOID MAINFRAME::OnBGStatic ()
  {
    BGCOLORDLG *BGColorDlg;

    if (TimerOn)
      KillTimer ();
      
    BGColorDlg = new BGCOLORDLG ();
    if (BGColorDlg->Execute ( this, "BGRGB_DLG" ))
      {
        if (BGImage!=NULL)
          delete BGImage;
        BGImage = NULL;
        UseBG = FALSE;
        RGBCOLOR Col;
        BGColorDlg->GetRGB ( &Col );
        BGRed = Col.Red;
        BGGreen = Col.Green;
        BGBlue = Col.Blue;
        BGColor = Pal->GetClosestColor ( Col );  
      } // End if
      
    if (TimerOn)
      SetTimer (0);
      
    delete BGColorDlg;
  } // End of OnBGStatic for MAINFRAME

VOID MAINFRAME::OnDepthCue ()
  {
    DEPTHDLG *DepthDlg;

    if (TimerOn)
      KillTimer ();
      
    DepthDlg = new DEPTHDLG ();
    if (DepthDlg->Execute ( this, "DEPTH_DLG" ))
      {
        G3D->SetDepthCueing ( DepthDlg->IsDepthCueOn (), DepthDlg->GetDepthCueScale() );  
      } // End if
      
    if (TimerOn)
      SetTimer (0);
      
    delete DepthDlg;
  } // End of OnDepthCue for MAINFRAME
  
VOID MAINFRAME::OnRotation ( LONG Code )
  {
    switch (Code)
      {
        case MENU_ROTATION_X_INC :
          ObjRotX += (float)1.0;
          break;  
        case MENU_ROTATION_X_DEC :
          ObjRotX -= (float)1.0;
          break;  
        case MENU_ROTATION_X_STOP :
          ObjRotX = (float)0;
          break;
          
        case MENU_ROTATION_Y_INC :
          ObjRotY += (float)1.0;
          break;          
        case MENU_ROTATION_Y_DEC :
          ObjRotY -= (float)1.0;
          break;  
        case MENU_ROTATION_Y_STOP :
          ObjRotY = (float)0;
          break;
          
        case MENU_ROTATION_Z_INC :
          ObjRotZ += (float)1.0;
          break;  
        case MENU_ROTATION_Z_DEC :
          ObjRotZ -= (float)1.0;
          break;  
        case MENU_ROTATION_Z_STOP :
          ObjRotZ = (float)0;
          break;  
      } // End switch
  } // End of OnRotation for MAINFRAME

VOID MAINFRAME::OnAbout ()
  {
    if (TimerOn)
      KillTimer ();
      
    ABOUTDLG *AboutDlg;
    AboutDlg = new ABOUTDLG ();
    AboutDlg->Execute ( this, "ABOUT_DLG" );
    
    if (TimerOn)
      SetTimer (0);
      
    delete AboutDlg;  
  } // End of OnAbout for MAINFRAME

LONG MAINFRAME::OnCreate ()
  {
    Menu->Load ( "MAIN_MENU" );
    SetMenu ( Menu );

    if (Init3D()!=SUCCESS)
      {
        ShowMessageBox("Error Initializing 3D", "Error occured at initialization", MB_OK);
        ExitApplication (-1);
      } // End if
    return 0;  
  } // End of OnCreate for MAINFRAME

LONG MAINFRAME::OnCommand ( LONG Command )
  {
    switch (Command)
      {
        case MENU_FILE_OPEN :
          OnFileLoad ();
          break;  
        case MENU_FILE_EXIT :
          SendMessage ( hWindow, WM_CLOSE, 0, 0 );
          break;

        case MENU_DETAIL_FACE_TEXTURE :
        case MENU_DETAIL_FACE_SOLID :
        case MENU_DETAIL_FACE_WIREFRAME :
        case MENU_DETAIL_SHADE_GOURAUD :
        case MENU_DETAIL_SHADE_FLAT :
        case MENU_DETAIL_SHADE_NONE :
          OnDetail ( Command );
          break;
                    
        case MENU_MATERIAL_LOAD_STATIC :
          OnLoadTextureStatic ();
          break;  
        case MENU_MATERIAL_LOAD_ANIMATED :          
          OnLoadTextureAnimated ();
          break;
          
        case MENU_MATERIAL_TRANSPARENCY_10 :          
        case MENU_MATERIAL_TRANSPARENCY_20 :          
        case MENU_MATERIAL_TRANSPARENCY_30 :          
        case MENU_MATERIAL_TRANSPARENCY_40 :          
        case MENU_MATERIAL_TRANSPARENCY_50 :          
        case MENU_MATERIAL_TRANSPARENCY_60 :          
        case MENU_MATERIAL_TRANSPARENCY_70 :          
        case MENU_MATERIAL_TRANSPARENCY_80 :          
        case MENU_MATERIAL_TRANSPARENCY_90 :          
        case MENU_MATERIAL_TRANSPARENCY_00 :
          OnTransparent ( Command );
          break;

        case MENU_MATERIAL_AMBIENT :
          OnAmbient ();
          break;
          
        case MENU_ENVIRONMENT_BACKGROUND_LOAD :
          OnLoadBG ();
          break;  
        case MENU_ENVIRONMENT_BACKGROUND_STATIC :
          OnBGStatic ();
          break;  
        case MENU_ENVIRONMENT_DEPTH_CUE :
          OnDepthCue ();
          break;  
        case MENU_ENVIRONMENT_FOG :
          OnFog ();
          break;

        case MENU_ROTATION_X_INC :
        case MENU_ROTATION_X_DEC :
        case MENU_ROTATION_X_STOP :
        case MENU_ROTATION_Y_INC :
        case MENU_ROTATION_Y_DEC :
        case MENU_ROTATION_Y_STOP :
        case MENU_ROTATION_Z_INC :
        case MENU_ROTATION_Z_DEC :
        case MENU_ROTATION_Z_STOP :
          OnRotation ( Command );
          break;
        case MENU_HELP_ABOUT :
          OnAbout ();
          break;  
      } // End switch  
    return 0;  
  } // End of OnCommand for MAINFRAME

LONG MAINFRAME::OnClose ()
  {
    if (TimerOn)      
      KillTimer ();  
      
    if (ShowMessageBox("Exit Demo", "Exit this demo?", MB_OKCANCEL)==IDOK)
      {
        return 0;
      } // End if
      
    if (TimerOn)
      SetTimer (0);
      
    return SKIPDEFPROC;  
  } // End of OnClose for MAINFRAME

VOID MAINFRAME::HandleInput ()
  {
    BOOLEAN IsShift;
    IsShift = Input.IsKeyDown(SC_LSHIFT) || Input.IsKeyDown(SC_RSHIFT);
    
    float SpeedRatio = (float)1.0;
    if (IsShift)
      {
        SpeedRatio = (float)2.0;  
      } // End if
    
    COLLIDEDATA CollideList[5];
    FLPVECTOR3D Position,EndPt;
    FLPVECTOR3D Dir;

    Position = Camera->GetWorldPosition();
    
    if (Input.IsKeyDown(SC_RIGHT))
      {
        Camera->Rotate ( (float)0, (float)(-3*SpeedRatio), (float)0 );  
      } // End if       
    if (Input.IsKeyDown(SC_LEFT))
      {
        Camera->Rotate ( (float)0, (float)(3*SpeedRatio), (float)0 );  
      } // End if
    if (Input.IsKeyDown(SC_UP))
      {
        Camera->Rotate ( (float)(-3*SpeedRatio), (float)0, (float)0 );  
      } // End if       
    if (Input.IsKeyDown(SC_DOWN))
      {
        Camera->Rotate ( (float)(3*SpeedRatio), (float)0, (float)0 );  
      } // End if

    LONG CollisionCount;
      
    if (Input.IsKeyDown(SC_A))
      {
        Dir.x = (float)0;
        Dir.y = (float)0;
        Dir.z = (float)(1*20);

        EndPt = G3D->ComputeNextPos ( Position, Camera->GetAngle(), Dir );
        CollisionCount = G3D->CheckCollision ( Position, EndPt, CollideList, (LONG)5, 
                                                                             (float)1.6, (float)10 );
        if (CollisionCount==0)
          Camera->Move ( EndPt.x-Position.x, EndPt.y-Position.y, EndPt.z-Position.z );
      } // End if       
    if (Input.IsKeyDown(SC_Z))
      {
        Dir.x = (float)0;
        Dir.y = (float)0;
        Dir.z = (float)(-1*20);

        EndPt = G3D->ComputeNextPos ( Position, Camera->GetAngle(), Dir );  
        CollisionCount = G3D->CheckCollision ( Position, EndPt, CollideList, (LONG)5, 
                                                                             (float)1.6, (float)10 );
        if (CollisionCount==0)
          Camera->Move ( EndPt.x-Position.x, EndPt.y-Position.y, EndPt.z-Position.z );
      } // End if
  } // End of HandleInput for MAINFRAME

LONG MAINFRAME::OnTimer ()
  {
    if (ObjectLoaded)
      {
        G3DMATERIALLIB *MaterialLib = G3D->GetMaterialLib();
        ANIMIMAGE *Texture = MaterialLib->GetTexture ( 0 );

        if ((BGImage!=NULL)&&(UseBG))
          {
            Grafix.CopyImage ( BGImage, 0, 0, BGImage->GetWidth(), BGImage->GetHeight(),
                               VScreen, 0, 0 );
          } // End if
        else
          {
            VScreen->Clear ( BGColor );
          } // End else
          
        G3DOBJECT *Object = G3D->FindObjectByID ( 1 );
        if (Object!=NULL)
          {
            Object->Rotate ( ObjRotX, ObjRotY, ObjRotZ );
            if (AnimatedTexture)
              {
                Texture->SetFrame ( CurAnimatedFrame );  
                CurAnimatedFrame++;
                if (CurAnimatedFrame>=NumAnimatedFrames)
                  CurAnimatedFrame = 0;
              } // End if
          } // End if
        HandleInput ();  
        G3D->ShowView ( Camera );
        HDISPLAY hDisplay = GetDisplay ( hClient );
        Grafix.DisplayImage ( hDisplay, VScreen, 0, 0, VScreen->GetWidth(), VScreen->GetHeight(),
                              0, 0 );
        ReleaseDisplay ( hClient, hDisplay ); 
      } // End if  
    return 0;  
  } // End of OnTimer for MAINFRAME

LONG MAINFRAME::OnPosChanging ( WINPOSCHANGE *WinPosChange )
  {
    LONG Wd;
    Wd = WinPosChange->Width;
    Wd = ((Wd+3)/4)*4;
    WinPosChange->Width = Wd;  
    return 0;  
  } // End of OnPosChanging for MAINFRAME

LONG MAINFRAME::OnSize ( LONG Width, LONG Height )
  {
    if (Width&&Height)
      {}  
    if (Initialized)
      {
        HDISPLAY hDisplay = GetDisplay ( hClient );
        Grafix.SetPalette ( hDisplay, Pal );  
        VScreen->Create ( hDisplay, IMAGE_8BIT,
                          Grafix.GetWidth(hDisplay), Grafix.GetHeight(hDisplay) );
        G3D->SetDestination ( VScreen );
        G3D->SetScreenCenter ( VScreen->GetWidth()/2, VScreen->GetHeight()/2 );
        if (BGImage!=NULL)
          {
            Grafix.AdjustImageSize ( BGImage, Grafix.GetWidth(hDisplay), Grafix.GetHeight(hDisplay) );                                   
          } // End if
        ReleaseDisplay ( hClient, hDisplay ); 
      } // End if  
    return 0;  
  } // End of OnWinPosChanging for MAINFRAME

LONG MAINFRAME::OnPaint ( HDISPLAY hDisplay )
  {
    Grafix.SetPalette ( hDisplay, Pal );  
    return 0;      
  } // End of OnPaint for MAINFRAME

//************************************
//
// Main Program
//
//************************************

MAINPROGRAM
  BEGIN
    MAINFRAME *MainFrame = new MAINFRAME ();
    MainFrame->Create ( "Multi-Platform 3D Demo", WINPOS_DEFAULT, WINPOS_DEFAULT,
                        WINPOS_DEFAULT, WINPOS_DEFAULT, GUI_DESKTOP );
    DISPLAYDATA Data;
    Data.UseDirectDraw = FALSE;
    Data.hMainWindow = MainFrame->GetHandle ();

    GUIAPP DemoApp;
    DemoApp.Run ( &Data, MainFrame );
    return 0;
  END // End of Main Program

  
  
