Level Editing
by (27 September 1999)

Return to The Archives

Up until about six months ago, my biggest deterrent to writing 3D engines was the lack of test data. For example, once I had gotten my portal engine working with 2 cells and 2 portals working, I wanted to test the engine with a larger data set. I spent about four hours constructing (by hand) a level with around 15 cells and 30 portals. Once that was done I decided I REALLY needed to write a level editor. I started doing that, but soon became frustrated at the complexity of writing a good editor that was easy to use. So I went looking for some shareware or freeware editor capable of outputting cells and portals. Nothing I found worked the way I wanted.

My thought then was to use a quake editor to make a level, extract the polygons from the BSP, and then write a program to create cells and portals out of the set of polygons. This proved to be unnecessary since as a result of running qbsp.exe on a map file, I found a file with all the portals between leaves of the BSP-Tree was generated. Leaves of the BSP are convex by nature, so I had my set of cells and portals! Aw,Yeah. This worked well and I was able to make large data sets to test my engine. The only drawback was WAY to many polygons and non-optimal cell configurations, due to the bsp-ing.

Since my current engine is neither portal nor BSP, again I ran into the problem of needing test data. Again I looked to a quake editor, but instead of using the .bsp files, I used the .map files. The only problem was that map files are only used by qbsp.exe and other quake engine utilities. So I wrote a program to convert map files into just vertices and polygons.

So if youíre too lazy to write an editor like I am, I present a way to modify Worldcraft to be your custom editor.

The first thing you need is The Forge (http://www.planetquake.com/worldcraft/) - Everything you need is here, including all software downloads and tutorials that Iím going to talk about.

Downloading Worldcraft

Go to the Forge and select the Half-Life editing resource center. From there find the link to download Worldcraft 2.1. Itís easy. I promise. Once youíve downloaded all of its 8.4 Megs of greatness, install it.

Using Textures with Worldcraft

To get the 3D previews of what youíre building and to get output in the map files with correct texture names, you need to put your textures in a format that Worldcraft can use. This format is the Half-Life WAD3 format. Go once again the Forge main page and select The Forge. From there go to the Files section. Select Editing Utilities and then scroll down until you find Wally. This program will make texture packages for most games that use the quake engine, including Half-Life. Itís really easy to use. Just take your textures and put them in a Half-Life texture wad. The Wally documentation explains it all.

Configuring Worldcraft

The first time Worldcraft starts, you should get a message that says no texture packages have been selected. It will then bring up the setup dialog. If it doesnít bring up the setup dialog, you can do it manually by selecting Tools->Options. Under the ĎTexturesí tab, add the texture wad that you made using Wally.

For the ĎGeneralí, Ď2D Viewsí, and Ď3D Viewsí you can setup whatever way you like.

You need to make some changes under the ĎGame Configurationí tab. Since it has been a while since I installed my copy of Worldcraft I donít remember if the Half-Life game configuration is preinstalled, but in any case you can either remove it, modify it, or leave it alone and make a new game configuration.

What you need to do is select the game configuration file. These files have an extension of .fgd. Youíll probably want to make your own. What this file does is specify all the types of solid and point entities that you can put into your level. I personally use Worldcraft only as a model editor for models that donít have any entities in them, so I donít bother with the .fgd to often. Information on editing .fgd files can be found at the Forge, under the ĎAdd-onsí section.

Unless youíre going to be using external programs that process the map files, you can ignore the ĎBuild Programsí tab. Otherwise, you just need to substitute the paths and filenames of the programs you use to do builds.

Good To Go

At this point, you should be able the edit levels with your textures and entities within Worldcraft. If you have lots of problems getting Worldcraft setup, email me (hodorl@rpi.edu) with the problem and Iíll see if there is something I can do.

If you need help using Worldcraft or youíve never used it before, just go to the Forge or the Half-Life editing resource center. They are the most comprehensive sites for info on editing using Worldcraft. I figure most of you have tried making a quake level, so you probably know the basics.

Once youíve made your level there are two options on the file menu youíll want to use: Export DXF and Export MAP. Iíve never used the Export DXF, but itís there so it probably works. If you know DXF and like it go ahead and use it. If you export a MAP file, the output isnít exactly friendly, so Iíve writing a little program to convert a MAP file to a list of vertices and faces called MapCon.

Before you download it though, you must know about a few restrictions on the program. This is software that I wrote to be useful for me, and if it doesnít work for you, sorry, too bad. There is a limit of 10000 vertices and 10000 faces. If you have levels bigger than this then perhaps if you email me, I can change the program to handle more. The second thing is that the program does NOT handle entities. If you place any entities in the level, the program will probably crash terribly with either general protection faults or it will just hang. I know, bad coding to do this, please donít yell about it.

With that said, you can download MapCon, here (28k).

The output format is described in the readme.txt that is included with MapCon.

Because there are limitations, Iím going to show how it works, so that you can write your own. =)

On PlanetQuakeís quake reference (http://www.planetquake.com/qref/bsps/index.html) you can get the document that describes the format of the map files. Basically itís lists of planes that define convex solids. Hereís the algorithm I use for converting the list into a list of polygons. This particular code hasnít been tested, as itís an adaptation of the code Iím using. Lots more is going on in my code in terms of face properties and vertex sharing, so I apologize if I screwed something up. If you notice anything, please contact me and let me know.

#define MAX_BOUNDS 16384    //this is the abs(max point in data set)

//Planes is an array of planes that define a convex area in space
//which has been loaded from the map file
//NumPlanes is the number of planes in the list

CFace* FacesFromPlaneList(CPlane *Planes, int NumPlanes)
    //you need at least 4 planes to make a solid
    if(NumPlanes < 4)
        return 0;

//allocate some memory for the new faces CFace *NewFaces = new CFace[NumPlanes];

//need to make faces that lie on the planes of the solid that //extend to the bounds of the data set. for(int i = 0; i < NumPlanes; i++) { //the vertex count for each inital face will be 4 NewFaces[i].VertexCount = 4;

//check to see if the plane is x-axis oriented if(abs(Planes[i].x) >= abs(Planes[i].y) && abs(Planes[i].x) >= abs(Planes[i].z)) { //set the bounds of the polygon, using y and z axis NewFaces[i].Vertex[0].Set(0, -MAX_BOUNDS, -MAX_BOUNDS); NewFaces[i].Vertex[1].Set(0, -MAX_BOUNDS, MAX_BOUNDS); NewFaces[i].Vertex[2].Set(0, MAX_BOUNDS, MAX_BOUNDS); NewFaces[i].Vertex[3].Set(0, MAX_BOUNDS, -MAX_BOUNDS);

//calculate the x value of each vertex on the plane for(int j = 0; j < 4; j++) { NewFaces[i].Vertex[j].x = Planes[i].d - Planes[i].z * NewFaces[i].Vertex[j].z - Planes[i].y * NewFaces[i].Vertex[j].y ) / Planes[i].x; } } //check to see if the plane is y-axis oriented else if(abs(Planes[i].y) >= abs(Planes[i].x) && abs(Planes[i].y) >= abs(Planes[i].z)) { //set the bounds of the polygon using the x and z axis NewFaces[i].Vertex[0].Set(-MAX_BOUNDS, 0, -MAX_BOUNDS); NewFaces[i].Vertex[1].Set(-MAX_BOUNDS, 0, MAX_BOUNDS); NewFaces[i].Vertex[2].Set(MAX_BOUNDS, 0, MAX_BOUNDS); NewFaces[i].Vertex[3].Set(MAX_BOUNDS, 0, -MAX_BOUNDS); //calculate the y value of each vertex on the plane for(int j = 0; j < 4; j++) { NewFaces[i].Vertex[j].y = ( Planes[i].d - Planes[i].z * NewFaces[i].Vertex[j].z - Planes[i].x * NewFaces[i].Vertex[j].x ) / Planes[i].y; } } //plane must be z-axis oriented else { //set the bounds of the polygon using the x and y axis NewFaces[i].Vertex[0].Set(-MAX_BOUNDS, -MAX_BOUNDS, 0); NewFaces[i].Vertex[1].Set(-MAX_BOUNDS, MAX_BOUNDS, 0); NewFaces[i].Vertex[2].Set(MAX_BOUNDS, MAX_BOUNDS, 0); NewFaces[i].Vertex[3].Set(MAX_BOUNDS, -MAX_BOUNDS, 0);

//calculate the z of each vertex on the plane for(int j = 0; j < 4; j++) { NewFaces[i].Vertex[i].z = ( Planes[i].d - Planes[i].y * NewFaces[i].Vertex[j].y - Planes[i].x * NewFaces[i].Vertex[j].x ) / Planes[i].z; } } }

//now for each face, we clip it against the planes of all the other faces //since it is convex, after all the clipping the face will be the original //as seen in the editor //NOTE: Depending on how you calculated your plane equations, you may need //to flip the plane before you clip the faces, since the wrong side of the //face will be clipped. And you will end up with faces with no vertices. for(i = 0; i < NumPlanes; i++) for(int j = 0; j < NumPlanes; j++) if(i != j) ClipFaceWithPlane(NewFaces[i], Planes[j]);

return NewFaces; }


Thatís about it. I hope this helps some of you so that you donít need to waste time a lot of time creating test data so you can get straight to 3D coding. =)

If anyone wants to work directly with Quake 1 BSP files, I have a document with the specifications of the BSP. I donít remember where I got it and I couldnít find the url. If you want it email me and I can hook you up. Luke Hodorowicz (hodorl@rpi.edu)

Until next time...


Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.