• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece!🔗 Click here to enter!

Tutorial: How to import a terrain height map?

Status
Not open for further replies.
Level 15
Joined
Nov 30, 2007
Messages
1,202
Hey folks,

Can't seem to find a good tutorial on how to import a terrain height map into the world editor, I'm wondering if someone could point me to a good tutorial on the subject?

I saw step by step guide on the tool Terrain 1.0 but I didn't know what tool to use to convert a grey scale .tga image into a .w3e file.
 
Level 23
Joined
Jan 1, 2009
Messages
1,610
If you just want to import existing terrain from one map to another - if they have the same dimensions - you can copy the file with an mpq editor.
If you want to convert a 2d image heightmap to wc3 terrain, that's not a native function and you need to convert the texture with an external tool like Terrain 1.0, but iirc that doesnt work correctly anymore.
Then put it into the map with an mpq editor.
 
Level 15
Joined
Nov 30, 2007
Messages
1,202
I was looking for 2D image to map conversion, but don't know any tools for converting from tga to w3e.

Was looking at the source code of Terrain 1.0, can't say it made me much wiser.

JASS:
#include "StdAfx.h"
#include ".\mapterrain.h"

CMapTerrain::CMapTerrain(void)
: nbMapFiles(0)
, W3eSource(NULL)
{
}

CMapTerrain::~CMapTerrain(void)
{
}

//    Name: LoadAndConvertTGA
//    in:
//        char* TGAPath       -- the path of the TGA
//    return:
//        true   -- if there wasn't any problem
//        false  -- if there was a problem
//    Discription:
//        First this function load the TGA-File with the CxImage-Class,
//        then it gets every pixel, converts the pixelcolor into the 
//        height of a mappoint and store it into a MapPoint-Class.
bool CMapTerrain::LoadAndConvertTGA(char* TGAPath)
{
    RGBQUAD ColorBuffer;
    int Height;
    int Width;
    int MapPointsNum;

    //Thats the TGA
    CxImage File(TGAPath, CXIMAGE_SUPPORT_TGA);
    //Get the height...
    Height = File.GetHeight();
    //...and width
    Width = File.GetWidth();
    if(!Height || !Width)
    {
        return false;
    }
    /*
    * The number of points in a map is always
    * Height (min. 33) * Width (min. 33) - 1
    * the height (width) of the bmp is always
    * mapheight (mapwidth) + 1
    */
    MapPointsNum = Height*Width-1;

    //That are the points of the map
    Points = new MapPoint[MapPointsNum];
   
    //The counter for the mappoints
    int Counter = 0;
    for(int y = 1; y <= Height; y++)
    {
        for(int x = 1; x <= Width; x++)
        {
            int Red;
            int Green;
            int Blue;
            int Color;
            //Get the pixel color
            ColorBuffer = File.GetPixelColor(x, y, false);
            //...and convert it into red, green and blue
            Red = ColorBuffer.rgbRed;
            Green = ColorBuffer.rgbGreen;
            Blue = ColorBuffer.rgbBlue;
            //Get the gray color
            Color = (Red + Blue + Green)/3;
            //Convert the color into height
            Points[Counter].Hight = Color*25+8192;
            Counter++;
        }
    }
    return true;
}



//    Name: CreatePoints
//    in:
//        char* szInhalt       -- the value of the file
//        int FileSize       -- the size of the file
//        char* TGAPath       -- the path of the TGA
//        char* MapFilePath  -- the path of the new w3e
//    return:
//        true   -- if there wasn't any problem
//        false  -- if there was a problem
//
//    Discription:
//        First this function calls the LoadAndConvert-Function.
//        Then it read the header of the sourcefile (69 byte).
//        After that it reads the mappoints and replace the height
//        with the height of the MapPoint-Class.
//        If this is done the function calls the WriteW3e-Function.
bool CMapTerrain::CreatePoints(char* szInhalt, int FileSize, char* TGAPath, char* MapFilePath)
{
    char* InhaltBuffer = new char[FileSize];
    InhaltBuffer = szInhalt;

    CMapTerrain::LoadAndConvertTGA(TGAPath);

    //Make a new buffer for the new file
    char* Buffer = new char[FileSize];
    for(int i = 0; i < 69; i++)
    {
        Buffer[i] = InhaltBuffer[i];
    }
    //Set the counter to 0
    //and use it for the 
    int Counter = 0;
    int PointCounter = 0;
    for(int i = 69; i < FileSize; i++)
    {
        switch(Counter)
        {
        case 1:
            {
                Buffer[i] = (Points[PointCounter-1].Hight & 0xFF00) / 0x0100;
                //I don't now why, but if it wasn't here, the editor would get an error ;)
                Counter++;
                break;
            }   
        case 0:
            {
                Points[PointCounter].Hight;
                Buffer[i] = (Points[PointCounter].Hight & 0xFF00);
                PointCounter++;
                break;
            }
        default:
            {
                Buffer[i] = szInhalt[i];
                break;
            }
        }
        if(Counter < 7)
        {
            Counter++;
        }
        else
        {
            Counter = 0;
        }
    }

    CMapTerrain::WriteW3e(Buffer, MapFilePath, FileSize);

    return true;
}



//    Name: CreatePoints
//    in:
//        char* szInhalt       -- the value of the file
//        int FileSize       -- the size of the file
//        char* MapFilePath  -- the path of the new w3e
//    return:
//        true   -- if there wasn't any problem
//        false  -- if there was a problem
//
//    Discription:
//        This function writes the value szInahlt into a file.

bool CMapTerrain::WriteW3e(char* szInhalt, char* MapFilePath, int FileSize)
{
    //Create the file and write the buffer into it
    HANDLE hWrite;
    DWORD w;

    hWrite = CreateFile(MapFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
    if(!hWrite)
        return false;

    WriteFile(hWrite, szInhalt, FileSize, &w, NULL);
    CloseHandle(hWrite);

    //CMapTerrain::ImportW3e(MapFilePath, "D:\\Testmap.w3m");

    return true;
}

//    Name: GetPathOfModule
//    in:
//        char* szModulePath         -- The pointer to your char
//    return:
//        true   -- if there wasn't any problem
//        false  -- if there was a problem
//    Discription:
//        Gets the path of the tool
bool CMapTerrain::GetPathOfModule(char* szModulePath)
{
    char szCompletePath[MAX_PATH] = "";
    char szPath[MAX_PATH] = "";
    LPSTR pFileName = "";

    *szModulePath = '\0';

    GetModuleFileName(NULL, szCompletePath, MAX_PATH);
    GetFullPathName(szCompletePath, sizeof(szCompletePath), szPath, &pFileName);

    szPath[pFileName - szPath] = '\0';
    strcat(szModulePath, szPath);

    return true;
}

//Don't used... is bugged
//    Name: ExportTemp
//    in:
//        char* Wc3Map       -- the path of the map
//        char* TempPath     -- the path of temp diretory
//    return:
//        true   -- if there wasn't any problem
//        false  -- if there was a problem
//    Discription:
//        Exports all files of a map to a temp directory.
//        First it opens a map. Then it get the size of 
//        the hash-table and create a new FILELISTTRY.
//        After that it egts all files, store them into
//        the CMapList-Class and write them in a file.
bool CMapTerrain::ExportTemp(char* Wc3Map, char* TempPath)
{
    MPQHANDLE hMPQ = NULL;
    DWORD dwPriority = 666;
    if(SFileOpenArchive(Wc3Map, dwPriority, SFILE_OPEN_HARD_DISK_FILE, &hMPQ) == true)
    {
        //Get the size of the hash-table
        DWORD dwHashTableSize = SFileGetFileInfo(hMPQ, SFILE_INFO_HASH_TABLE_SIZE);
        FILELISTENTRY *lpListBuffer = new FILELISTENTRY[dwHashTableSize];

        //A tempfile
        char ListFilePath[MAX_PATH] = "";
        strcpy(ListFilePath, TempPath);
        strcat(ListFilePath, "FileList.txt");

        SFileListFiles(hMPQ, ListFilePath, lpListBuffer, SFILE_LIST_ONLY_KNOWN);
       
        nbMapFiles = dwHashTableSize;

        for(int i = 0; i < dwHashTableSize; i++)
        {
            if(lpListBuffer[i].dwFileExists != 0)
            {
                //Create the winpath
                char WinBuffer[MAX_PATH] = "";
                strcpy(WinBuffer, TempPath);
                strcat(WinBuffer, CMapTerrain::GetWinFileName(lpListBuffer[i].szFileName));

                //Add file to the filelist
                Files.AddFile(WinBuffer, lpListBuffer[i].szFileName);

                MPQHANDLE hFile;
                HANDLE hWrite;
                DWORD w;
                hWrite = CreateFile(WinBuffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);

                SFileOpenFile(lpListBuffer[i].szFileName, &hFile);
                if(hFile)
                {
                    //Create a buffer for the file
                    char szBuffer[0x10000];
                    DWORD dwBytes = 1;
                    while ( dwBytes > 0 )
                    {
                        SFileReadFile(hFile, szBuffer, sizeof(szBuffer), &dwBytes, NULL);
                        if ( dwBytes > 0 )
                        {
                            //Write the file
                            WriteFile(hWrite, szBuffer, dwBytes, &dwBytes, NULL);
                        }
                    }
                }
                else {
                    //If error, then exit
                    return false;
                }
                CloseHandle(hWrite);
                SFileCloseFile(hFile);

            }
        }
    }
    else {
        //If error, then exit
        return false;
    }

    SFileCloseArchive(hMPQ);

    return true;
}

//Don't used... is bugged
//    Name: ImportW3e
//    in:
//        char* MapFilePath       -- that's the w3e-file
//        char* Wc3Map           -- the path of the map
//    return:
//        true   -- if there wasn't any problem
//        false  -- if there was a problem
//    Discription:
//        First at all the function create a temp directory
//        and export all files of the map into it. After
//        that the function opens the map for a update and
//        import all temp files into it, even the new w3e.
bool CMapTerrain::ImportW3e(char* MapFilePath, char* Wc3Map)
{
    MPQHANDLE hMPQ = NULL;
    char Path[MAX_PATH] = "";
    CMapTerrain::GetPathOfModule(Path);
    strcat(Path, "Temp\\");

    //For the temp-files
    CreateDirectory(Path, 0);
    CMapTerrain::ExportTemp(Wc3Map, Path);

    hMPQ = MpqOpenArchiveForUpdate(Wc3Map, MOAU_CREATE_ALWAYS | MOAU_MAINTAIN_LISTFILE , 0x800);
    if(hMPQ == NULL) {
        //If the file does not exist, exit.
        return false;
    }

    for(int i = 0; i < nbMapFiles; i++)
    {
        bool IsW3e = CMapTerrain::CompareChar("war3map.w3e", Files.GetWc3Path(i));
        if(IsW3e == false)
        {
            //Import all exported files
            MpqAddFileToArchiveEx(hMPQ, Files.GetWinPath(i), Files.GetWc3Path(i), MAFA_COMPRESS2, MAFA_COMPRESS_DEFLATE, Z_BEST_COMPRESSION);
        }
        else
        {
            char MapFilePath[MAX_PATH] = "";
            strcat(MapFilePath, Path);
            strcat(MapFilePath, "war3map_temp.w3e");
            MpqAddFileToArchiveEx(hMPQ, MapFilePath, Files.GetWc3Path(i), MAFA_COMPRESS2, MAFA_COMPRESS_DEFLATE, Z_BEST_COMPRESSION);
        }
    }
    //Compact and Close
    MpqCompactArchive(hMPQ);
    MpqCloseUpdatedArchive(hMPQ, 0);
    return true;
}

//    Name: GetWinFileName
//    in:
//        char* FilePath       -- the path that should be converted
//    return:
//        char*   -- the windows path
//    Discription:
//        This small function get the filename without
//        the path and return it. For an example:
//        In: Test\Bla\Huhu\Dumdidum.w3g
//        Out: Dumdidum.w3g
char* CMapTerrain::GetWinFileName(char* FilePath)
{

    if(FilePath == "")
    {
        CMapTerrain::ErrorMessage("Filepath is to small!");
    }

    int Max = 0;
    std::string StringBuffer = FilePath;
    int Pos = StringBuffer.find_last_of("\\");
    StringBuffer = StringBuffer.substr(Pos+1, StringBuffer.length());

    char* Buffer = new char[StringBuffer.length()];
    strcpy(Buffer, StringBuffer.c_str());

    return Buffer;
}

//    Name: ErrorMessage
//    in:
//        char* Message       -- the message...
//    return:
//        nothing
//    Discription:
//        This function is used in the devlopment.
void CMapTerrain::ErrorMessage(char* Message)
{
#ifdef CONSOLE
    std::cout << "Error: " << Message << std::endl;
#endif
#ifdef WINDOW
    MessageBox(NULL, Message, "Error", MB_ICONERROR);
#endif

}

//    Name: CompareChar
//    in:
//        char* Sourcechar       -- the source char
//        char* CompareableChar  -- a char that should be compareable
//    return:
//        true               -- if the chars are compareable
//        false               -- if the chars are'nt compareable 
//    Discription:
//        This function compares 2 char's.
bool CMapTerrain::CompareChar(char* SourceChar, char* CompareableChar)
{
    std::string Buffer1 = SourceChar;
    std::string Buffer2 = CompareableChar;
    for(int i = 0; i < Buffer2.length(); i++)
    {
        if(Buffer1[i] != Buffer2[i])
        {
            return false;
        }
    }
    return true;
}

//    Name: ExportSourceW3e
//    in:
//        char* Wc3Map       -- thats the path of the map
//    return:
//        true               -- if there was no problem
//        false               -- if thete was a problem
//    Discription:
//        This function export the source w3e form a
//        map. Firstit opens the map an create a new
//        w3e file. Then it opens the w3e in the mpq
//        and read the file. After that it writes
//        the readed byes into the new w3e file.
bool CMapTerrain::ExportSourceW3e(char* Wc3Map)
{
    MPQHANDLE hFile;
    HANDLE hWrite;
    DWORD w;
    MPQHANDLE hMPQ = NULL;
    DWORD dwPriority = 666;

    SFileOpenArchive(Wc3Map, dwPriority, SFILE_OPEN_HARD_DISK_FILE, &hMPQ);

    char SourcePath[MAX_PATH] = "";
    GetPathOfModule(SourcePath);
    strcat(SourcePath, "war3map.w3e");

    hWrite = CreateFile(SourcePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);

    SFileOpenFile("war3map.w3e", &hFile);
    if(hFile)
    {
        //Create a buffer for the file
        char szBuffer[0x10000];
        DWORD dwBytes = 1;
        while ( dwBytes > 0 )
        {
            SFileReadFile(hFile, szBuffer, sizeof(szBuffer), &dwBytes, NULL);
            if ( dwBytes > 0 )
            {
                //Write the file
                WriteFile(hWrite, szBuffer, dwBytes, &dwBytes, NULL);
            }
        }
    }
    else {
        //If error, then exit
        return false;
    }
    CloseHandle(hWrite);
    SFileCloseFile(hFile);
    SFileCloseArchive(hMPQ);

    W3eSource = SourcePath;
    return true;
}
 
Last edited:
Status
Not open for further replies.
Top