J3Editor: A 3D Graphics Object Editor for Jane's WWII Fighters

J3Editor



Introduction

The J3Editor is a utility that allows the user to view and modify Jane's ™ WWII Fighters' J3 object model files in a graphical 3D environment. It is not intended to be a general purpose 3D modeling tool and does not include many of the features you would expect to find in such a tool (features such as shape creation, extrusion and solids algebra), nor does it import or export data from/to other 3D formats. It is designed specifically to deal with the WWII Fighters' J3 object model files.

This document assumes familiarity with basic 3D modeling concepts. It is not a 3D modeling tutorial. If you come across a term or concept that you do not understand, please make an effort to read up on it. A web search on the term will likely turn up numerous resources.

Some familiarity with the various J3 object model formats is recommended in order to use the J3Editor effectively. While it is possible to use the editor with little or no knowledge of the J3 file formats, making any significant changes requires a solid understanding of how the files are put together. Without this background knowledge, the steps required to make meaningful changes will almost certainly seem cryptic and convoluted. To this end, a complete description of the J3 file types can be found in Appendix A at the end of this document.



Brief Description of the Various J3 Model File Types

WWII Fighters uses three different J3 file types, so called because of the name of file extensions: J3P, J3D and J3T. J3P and J3D files reside in the ww2.sqs data archive and contain data that describes the 3D model of aircraft and ground objects. J3T data files reside in the terrain.sqs data archive and describe the 3D model of terrain objects. The data contained in each file type is roughly the same but is organized differently. For example, J3T terrain files contain only one group with several sub-entities while J3D files contain many groups each having at most one sub-entity.

Each file type stores 3D data in an data hierarchy consisting of groups, sub-entities, faces and vertices. A vertex is a point in 3D space, together with a texture mapping coordinate pair; a face is a sequence of vertices forming a closed polygon; a sub-entity is a sequence of faces; finally, a group is a sequence of sub-entities. A group may contain either sub-groups or sub-entities but not both. In all J3 files, there is one and only one root group. The root group in J3T files has 1 to many sub-entities (and no sub-groups). The root group in J3P and J3D files has 1 to many sub-groups (and no direct sub-entities).

Faces in the J3 files are triangles, consisting of three vertices per face. Vertices may be shared between faces. Vertices and faces are not shared across sub-entities or groups; that is, a face/vertex belongs to one and only one sub-entity/group. Note: there may be situations in which a face/vertex is a member of no sub-entities/groups. These 'orphans' are culled by the J3Editor as it processes the object hierarchy.

Specifics about hierarchy organization vary from file type to file type. For example, J3T files consist of one group with one to many sub-entities. J3D files consist of one to many groups each of which can contain at most one sub-entity. J3P files also consist of one to many groups but groups can contain multiple sub-entities. These restrictions on the object hierarchy play an important role when modifying the J3 files. Some care has been taken to ensure that the J3Editor does not allow the user to create invalid object hierarchies. However, the user should always ensure that any changes they make result in a valid hierarchy.

Samples showing the differences in object hierarchy between the 3 file types follow:

Sample J3P Object Hierarchy (multiple sub-groups, multiple sub-entities)

	rootGroup
		-> subGroup1
			-> subGroup1A
				-> subEntity1A
					-> Face1
						-> Vertex1
						-> Vertex2
						-> Vertex3
		-> subGroup2
			-> subEntity2A
				-> Face1
					-> Vertex1
					-> Vertex2
					-> Vertex3
				-> Face2
					-> Vertex4
					-> Vertex5
					-> Vertex6
			-> subEntity2B
				-> Face3
					-> Vertex7
					-> Vertex8
					-> Vertex9
		-> subGroup3

Sample J3D File Object Hierarchy (multiple sub-groups, single sub-entity)

	rootGroup
		-> subGroup1
			-> subGroup1A
				-> subEntity1A
					-> Face1
						-> Vertex1
						-> Vertex2
						-> Vertex3
		-> subGroup2
			-> subEntity2A
				-> Face1
					-> Vertex1
					-> Vertex2
					-> Vertex3
				-> Face2
					-> Vertex4
					-> Vertex5
					-> Vertex6
		-> subGroup3

Sample J3T Object Hierarchy (single group, multiple sub-entities)

	rootGroup
		-> subEntity1
			-> Face1
				-> Vertex1
				-> Vertex2
				-> Vertex3
		-> subEntity2
			-> Face1
				-> Vertex1
				-> Vertex2
				-> Vertex3
			-> Face2
				-> Vertex4
				-> Vertex5
				-> Vertex6
		-> subEntity3


J3T Idiosyncracies

J3T files always contain an entity called "Jane's Terrain". This is an LOD (level of detail) used in the game to represent the terrain tile when seen from a distance. Unlike other objects, the "Jane's Terrain" sub-entity is textured using a fixed bitmap name that cannot be changed. For example, if the J3T file being worked on is named X037_Y011.J3T, the "Jane's Terrain" sub-entity is textured using the X037_Y011.BMP bitmap. Although the "Jane's Terrain" sub-entity can appear in any order within the J3T files, to simplify processing the J3Editor forces it to be the last sub-entity in the object hierarchy. This is transparent to the user and requires no special handling. However, it is mentioned here in case the user sees a disparity between the order in which sub-entities are specified in the J3T files and the order in which they appear in the object tree.

Coordinate System

The J3Editor uses a standard 3-dimensional object space with three mutually orthogonal axes, x, y and z, forming a right-handed coordinate system. The x-axis can be considered to map to "left/right", the y-axis to "up/down" and the z-axis to "in/out".

Distances and Lengths

The J3 files use a metre as the standard unit of measure; a length of 1 in object space corresponds to a length of 1 metre.

Orthogonal and Perspective Projections

The J3Editor provides two projections: orthogonal and perspective. Orthogonal projection preserves the distance and angle between points on the screen irrespective of the viewpoint; a square remains square on screen regardless of the viewpoint. Perspective projection uses foreshortening to give the illusion of depth but distance and angles are not preserved on screen; a square is rendered as a foreshortened rectangle on screen.

The projection can be toggled between perspective and orthogonal projections using the radio buttons in the toolbar at the side of the main display window. Orthogonal and perspective projection parameters such as field of vision and left, right, top, bottom, near and far clipping planes can be set in the Projection Properties window, which is described in detail later.

When setting the orthogonal projection parameters, care must be taken to ensure that the viewport isn't set such that the object is not visible on screen. The object is initially centred on (0, 0, 0), so the orthogonal projection should also be centred on that point.

When setting the perspective projection parameters, the viewport is always centred on (0, 0, 0) but care must be taken to ensure that the near and far clipping planes do not clip the object making it invisible. In particular, do not set the near clipping plane less than 0.1. A field of vision of 45 degrees renders the most natural appearing image.

The default view uses a perspective projection with a 45 degree field of view.

Face Winding

The direction in which a face "faces" is specified by its vertex winding. For exampe, the triangles specified by vertices {2 1 0} and {0 1 2} consist of the same vertices but face in opposite directions. Face winding is clockwise by default but can be changed for an individual face in the Attributes window (see the Attributes window section later in this document).






Using the J3Editor

The J3Editor control layout has been designed to work best at resolutions of 1024x768 and above. If your desktop resolution is smaller than 1024x768, the control layout will not work as expected. Please resize your desktop if needed. The J3Editor can be used with either large or small desktop fonts.

J3Editor



Getting Started

The J3Editor assumes that the files to be processed have already been extracted from the appropriate archive before the editor is started. It is up to the user to extract the necessary files from the archives before running the editor. Similarly, the J3Editor does not repack the modified files back into the archive. These steps need to be performed by the user explicitly using another application such as SQzip or Jean-Marc Graumann's SkinMaster. If you are unsure how to unpack/pack files from and to the WWII Fighters data archives, download the SQzip or SkinMaster utilities from http://ww2f.dogfighter.com and read the documentation included with those packages.

Always make sure that you have at least one, and preferably more, backups of the SQS files and the J3 files you will be working on. It's almost inevitable that something will go wrong somewhere in the process. If and when that happens and you find yourself without back-ups, you may end up having to reinstall the entire game. Been there, done that, it's not fun.

Loading a J3 File

To load a J3 file, click on the "Load J3 File" button. This opens a standard File Open window where the user can browse to the appropriate location to open the desired file. All of the texture bitmaps used by the file must reside in the same directory as the J3 file. If the J3Editor cannot open one or more of the textures, a warning message will be displayed to the screen and the load will abort.

When a J3 file has been successfully loaded, the J3Editor stores that file's location and uses that path as the default path on subsequent loads.

The J3Editor can load one J3 file at a time. Loading one J3 file purges the previously loaded J3 file, object tree and any copied objects from memory.

Note: The J3Editor saves the display state of an object when that object is saved. If the display state includes hidden objects, the next time that file is loaded the an information window is displayed reminding the user that some of the objects in the file are currently hidden. Display states and hidden objects are described in the Displaying/Hiding section below.

Saving a J3 File

To save a J3 file, click on the "Save J3 File" button. If there are any uncommitted changes, the user is prompted to commit the changes before proceeding. A standard File Save window is then opened allowing the user to browse to the appropriate location to save the file.

'Orphan' objects (i.e. those which have no valid parents) are automatically culled before the J3 file is saved. Relative indices and offsets as well as vertex normals are all generated by the program; the user doesn't have to worry about calculating these values.

Note: The display state of the object is also saved along with the rest of the data. Display states are described in the Displaying/ Hiding Objects section below.

Changing the Viewpoint

The viewpoint can be changed in one of three ways: rotation, translation and zooming.

To rotate the viewpoint, click on the "Rotate" button and then hold down the left mouse button while moving the mouse in the main window. Moving the mouse up/down on the screen rotates the viewpoint around the Y-axis. Moving the mouse left/right rotates the viewpoint around the X-axis. The rate at which the viewpoint is rotated can be changed in the Transforms window shown below. The Transform Properties window is displayed by clicking on the Transforms... button in the Properties area of the main toolbar. The Transform Properties window is described in detail later in this document.

To translate (move) the viewpoint, click on the "Move" button and then hold down the left mouse button while moving the mouse in the main window. Moving the mouse up/down translates the viewpoint in the Y-axis. Moving the mouse left/right translates the viewpoint in the X-axis. The rate at which the viewpoint is translated can be changed in the Transform Properties window.

To zoom the viewpoint in or out, click on the "Zoom" button and then hold down the left mouse button while moving the mouse in the main window. Moving the mouse up zooms the viewpoint out, moving the mouse down zooms the viewpoint in.

This ability to change the rate at which is the viewpoint is transformed is useful if, for example, you want large viewpoint transform rates for large terrain objects and smaller transform rates for the smaller aircraft and ground objects.

To centre the viewpoint along the X-axis, click on the "CentreX" button.

To centre the viewpoint along the Y-axis, click on the "CentreY" button.

To centre the viewpoint along the Z-axis, click on the "CentreZ" button.

Changing the Draw Mode: Solid, Wireframe or Textured

The draw mode can be changed by selecting one of the radio buttons in the Display Modes section of the main toolbar. Draw mode options are: solid, wireframe and textured. In solid draw mode, the object is rendered with all faces coloured in the same, flat colour. This shows the general shape of the object but the faces can occlude vertices, making them hard to see. In wireframe draw mode, the faces are transparent and lines are drawn between the vertices forming a wireframe mesh. This makes the vertices easy to see but the overall shape of the object is difficult to discern. Finally, in textured draw mode, the object is fully textured using the texture mapping values specified in the objects. Transparency is implemented, so textures that contain transparency masks will be rendered transparent in this mode. This view is more or less what the object will look like in-game.

Note: there is a bug in the transparencies in textured render mode. In order to draw transparencies correctly, the object must be rendered such that the objects furthest away from the current viewpoint are drawn first and objects closer to the viewpoint are drawn on top. This 'painter's algorithm' is reasonably involved and the object re-ordering required eats up the CPU cycles. I have a basic implementation in place but it doesn't always work properly, leading to some graphical artefacts (in which, for example, transparencies occlude the background). These are particularly noticable in the cockpit and wheel transparencies on aircraft. There is also a bug in the depth sorting algorithm that is most apparent when working with J3T files. Sometimes faces that are further from the viewpoint are drawn in front of closer faces. I am looking into these bugs and a fix should be in place for the next version.

Grids

The J3Editor provides grids in the XY, YZ and XZ planes. These can be individually enabled/disabled and are configured in the Grid Properties window. Since 1 unit in object space corresponds to a length of 1 metre, setting the grid spacing to 1, the minimum extent to -10 and the maximum extent to +10 will create a grid of 20m x 20m with gridlines every 1 metre. These grid dimensions are appropriate for the relatively small aircraft and ground objects in the J3P/J3D files. However, it is not an appropriate scale for terrain objects, which typically cover an area of 4000m x 4000m centred on the origin. When working with J3T files, the user should scale the grid dimensions appropriately.

The grids can be offset in each plane independently. This allows the user to shift the grids as they see fit; for example, the user may want the grid in the XY plane to intersect the object a certain distance along the fuselage. This is particularly useful when used in conjunction with the grid overlays described below.

Grid Overlays

The J3Editor provides the capability to overlay bitmap images on top of each of the three grid planes. This feature is useful if, for example, the user wants to superimpose bitmaps of an object on the scene to verify object dimensions or appearance. These overlays can be enabled/disabled and configured in the Grid Properties window. The opacity of the overlays can be configured fully opaque so that the overlay occludes the object, transparent so that the object can still be seen through the overlay, or any degree in between.

Grid overlays can be moved around the plane on which they lie independently of one another. This allows the user full control over where they are placed. This feature is useful when aligning an overlay with the 3D object. For example, the user may have three-view drawings of an object that they want to overlay on top of the object. Rather than having to use trial and error in an external graphics editor to resize and crop the overlay images to make sure they align with the object, the user can move the overlay images around on screen within the J3Editor itself.

Grid and grid overlay properties are specified in the Grid Properties window which is displayed when the user clicks on the "Grids..." button in the Properties section of the main toolbar. The Grid Properties window is described in detail in a later section.

Selecting an Object

Objects can be selected in one of two ways; either by clicking on it in the object tree list window, or by clicking on the "Pick Vertex" button in the Object Tree Hierarchy window and then clicking on a vertex in the main window. The first method can be used to select any object type, while the second method can only be used to select vertices. Selecting an object automatically updates the contents of the Attributes window. The Object Tree Hierarchy window and its associated button controls are show below and are described in detail in a later section.

Object Hierarchy Tree

In the main draw window, the currently selected object and the vertices contained within that object are painted a different colour than the other objects and vertices. The colours used can be configured in the Display Properties window. By default, unselected objects are painted grey, unselected vertices green, the currently selected object is painted pink and selected vertices dark red. The currently selected object is also highlighted in the object tree window.

When the user selects a vertex using the "Pick Vertex" method, only the specified vertex is selected. However, all of the faces that the selected vertex is a member of are highlighted in the highlight colour. This allows the user to see at a glance which faces will be affected if the selected vertex is transformed. The default highlight colour is a bright mauve and can be configured in the Display Properties window if desired.

All object transforms (Translate, Rotate, Scale, Stretch) operate on the currently selected object only. See the description in the "Manipulating an Object" section below.

Deselecting an Object

Clicking on the "Deselect" button in the Object Tree Hierarchy window deselects the currently selected object. If no objects are currently selected, the "Deselect" button is disabled.

Displaying/Hiding Objects

When working with an object that has a lot of faces and/or vertices, the screen can sometimes become quite cluttered with objects that the user is not particularly interested in. To overcome this problem, the J3Editor provides functionality that allows the user to toggle the hide/display state of each object in the object hierarchy.

Each object in the Object Hierarchy window contains a check box which controls whether the object is displayed or hidden in the main display window. Unchecking the check box hides the object (and its associated sub-objects) while checking the box displays the object (but not necessarily its associated sub-objects). Clicking on the "Hide All" button forces the display check box for all objects to be unchecked while clicking on the "Display All" button forces the display check box for all objects to be checked.

Hiding an object is not the same as deleting it. A hidden object still exists in the object hierarchy but is not displayed in the display window. Hiding an object does not affect its in-game appearance; no changes are made to its underlying attributes.

The display state of the object is saved when the user saves the file and is restored when the user reloads the file. If the display state contains hidden objects when the file is reloaded, an information window is displayed reminding the user that some of the objects are currently hidden.

Getting Information About an Object

The Attributes window shown below displays information about the currently selected object. The window is automatically updated when the selected object changes. The information presented depends on the type of the selected object. Group information includes group name and translate and rotate values. Sub-entity information includes information about that sub-entities parent group as well as data about which texture is used by the sub-entity. Face information includes face name, information about all three of that face's vertices as well as it's parent group and sub-entity. Finally, vertex information includes the vertex's X, Y and Z values, as well as its textureU and textureV texture coordinate pairs.

Attributes window

Unless otherwise indicated, the values presented in the attributes window can be edited. The attributes of the object in question will be updated when the user hits the "Apply" button. Some object attributes cannot be edited; for example, the "Jane's Terrain" sub-entity in J3T files cannot be renamed. In these cases, the edit fields for those attributes are set read-only, preventing the user from editing them.

The Attributes window is described in detail in a later section.

Manipulating an Object

Objects can be manipulated in several ways. They can be: translated in each of the X, Y, Z dimensions; rotated about the X, Y and Z axis; scaled in the X, Y and Z axis; and stretched in the X, Y and Z axis. [Note: stretch transforms have been disabled in the current version pending some bugs in the implementation being ironed out. They will be re-enabled in subsequent versions]

Transforms occur in one dimension at a time, since this allows for greater placement control. I had originally intended to allow the user to transform objects in two or three dimensions at once but user feedback during beta testing indicated that this made object placement difficult; there are insufficient depth cues to tell the user where the object really is in object space. Transforming objects in one dimension at a time is more cumbersome but affords greater control. If a better way of transforming objects in more than one dimension at a time is found, it will be added into subsequent versions of the J3Editor.

Only the currently selected object is transformed.

To translate or rotate an object, click on the desired transform in the upper right corner of the toolbar. In the main display window, click the left mouse button and drag the mouse across the screen. The further the mouse is dragged, the more the object is transformed. Note that the object is not placed where the mouse is on the screen, the movement of the mouse simply indicates how much the object is transformed. Releasing the mouse button or moving the mouse out of the main draw window ends the transform.

To scale an object in a given dimension, click on the desired Scale button in the main toolbar. The selected object is scaled by the factor specified for that dimension in the Transforms window. There is no function to scale the selected object in all three dimensions at once; the user must scale the object in each dimension individually.

Transforms are applied to the object immediately, and the results are seen in the main display window. The Attributes window is also updated dyamically as the object is transformed.

This process will seem awkward at first but you soon become used to it.

Deleting an Object

Objects can be deleted by selecting an object as described above and then clicking on the "Delete" button in the Object Tree Hierarchy window. The currently selected object (and it's children) will be deleted. Not all objects can be deleted; for example, the root group cannot be deleted, the "Jane's Terrain" sub-entity in J3T files cannot be deleted. If the currently selected object cannot be deleted, the "Delete" button is disabled.

Because vertices can belong to more than one face, deleting them can be problematic. Consequently, the J3Editor does not allow vertices to be explicitly deleted by the user. Instead, 'orphan' vertices (i.e. those that no longer belong to any faces) are automatically culled by the program as it processes the hierarchy.

Deleted objects are not immediately removed from the object tree; instead, they are flagged as having been deleted and removed from the display. They will not be permanently removed from the object hierarchy until the user commits changes by clicking on either the "Commit Changes" or "Save J3 File" buttons and accepts the prompts. This deferred deletion allows the user to undelete objects if required. Objects that have been deleted are flagged in the Object Tree with a trailing '(*)' until the changes are committed, at which point the objects are permanently removed from the object hierarchy.

Undeleting an Object

When an object is deleted, it is not immediately removed from the object hierarchy. Instead, it is flagged as having been deleted and removed from the display. This allows the object to be undeleted at a later point if required. To undelete an object, select it from the object tree window and click on the "Undelete" button. The "Delete" button toggles into the "Undelete" button and vice versa depending on the state of the currently selected object.

Copying an Object

Clicking on the "Copy" button will copy the currently selected object into the copy buffer. This object can then be pasted into another object using the "Paste" button as described below. If the currently selected object cannot be copied, the "Copy" button is disabled.

If the object that is currently in the copy buffer is deleted, either in whole or in part, that will be reflected in subsequent paste operations. For example, if the user copies a groupA which consists of sub-entities sA1 and sA2 into the copy buffer, and then deletes sub-entity sA1, subsequent paste operations will paste groupA and sub-entity sA2 into the currently selected object but sub-entity sA1 will not be copied.

Pasting an Object

If the copy buffer contains an object, that object can be pasted into other objects. The J3Editor doesn't allow objects to be pasted if doing so will result in an invalid object hierarchy. Whether a paste operation is valid depends on the type of the copied object, the type of the currently selected object and the type of the object model file currently being processed. If a paste operation is invalid in the current context, the "Paste" button is disabled.

The paste operation does not clear the contents of the copy buffer; the copied object can be pasted into as many other objects as desired.

Adding a New Group

A new group can be added to the currently selected object by clicking on the "New Group" button. The J3Editor doesn't allow groups to be added if doing so will result in an invalid object hierarchy. For example, groups can only be added to other groups. A new group cannot be added to a group if the target group already contains one or more sub-entities. New groups cannot be added under any circumstances to a J3T file. If adding a new group to the currently selected object is inappropriate in the current context, the "New Group" button is disabled. Othwrwise, clicking on the "New Group" button adds a new group with the name "New Group" to the currently selected object.

Adding a New SubEntity

A new sub-entity can be added to the currently selected object by clicking on the "New SubEntity" button. The J3Editor doesn't allow sub-entities to be added if doing so will result in an invalid object hierarchy. For example, sub-entities can only be added to groups. A new sub-entity cannot be added to a group if the target group already contains sub-groups. In J3D files, groups can contain only one sub-entity. If adding a new sub-entity to the currently selected object is inappropriate in the current context, the "New SubEntity" button is disabled. Otherwise, clicking on the "New SubEntity" button adds a new sub-entity with the name "New SubEntity" to the currently selected object.

When working with J3T files, the new sub-entity will always be added in front of the "Jane's Terrain" sub-entity. This simplifies internal processing.

Adding a New Face

A new face can be added to the currently selected object by clicking on the "New Face" button. The J3Editor doesn't allow faces to be added if doing so will result in an invalid object hierarchy. For example, faces can only be added to sub-entities. If adding a new face to the currently selected object is inappropriate in the current context, the "New Face" button is disabled. Otherwise, clicking on the "New Face" button will open the New Face window shown below.

New Face window

The New Face window contains a series of controls that allow the user to choose the vertices that make up the new face. Each face consists of three vertices. The vertices may either already exist, in which case they can be selected using the drop down list, or can be created by clicking on the "New Vertex" button. The X, Y, Z, TextureU and TextureV attributes of the vertices are displayed in the text boxes.

The New Face window is described in detail in a later section.

Textures

The J3Editor allows the user to manipulate the textures associated with the currently loaded J3 file in three ways; the user can add and remove textures to and from the object, textures can be renamed and textures can be moved up and down in the texture list. Since the texture used to texture an object is specified in the J3 files as an index into the texture list, reordering the textures in the list affects the way the object is textured. These changes take effect immediately in the main display window.

Textures can be added to the object by opening the Textures window and clicking on the "New Texture" button. This opens a file open window box which prompts the user to select a texture to add. Textures are always BMP bitmap files. It is up to the user to ensure that the newly added bitmap is contained in the appropriate SQS archive (ww2.sqs for J3P/J3D and terrain.sqs for J3T).

Texture List

Textures can be deleted from the object by clicking on the "Delete Texture" button immediately below the texture list window. When this button is clicked, the currently selected texture is removed from the object. If no textures are selected, the "Delete Texture" button is disabled.

Textures can be renamed by clicking on the "Rename Texture" button.

Vertex texture mapping indices are not automatically updated when textures are added and/or removed, so great care must be taken by the user to ensure that all texture mapping values are manually updated as required.

Commiting/Discarding Changes

The J3Editor has built-in functionality to commit and discard changes. Discarding changes undoes any changes made to the object hierarchy since the last commit. Changes are commited by clicking on the "Commit Changes" button and discarded by clicking on the "Discard Changes" button. Changes can be discarded and commited as often as the user wants; the changes are written to file on a commit and restored from file on a discard. These buttons are enabled/disabled as appropriate.





The Main Control Windows

The following section describes the main control windows in detail.

Object Tree Hierarchy Window

Texture List

The Object Tree Hierarchy window displays the object hierarchy of the J3 file being processed and contains a series of controls that allow the user to manipulate the objects in the hierarchy. This window is automatically opened when the J3Editor is launched. The reason this window is undocked from the main window is to allow the user to resize it and place it as they see fit. User feedback during beta testing showed that users spend a lot of time in this window and like to be able to resize and place it as desired.

The Object Tree Hierarchy Window consists of a tree list control on the left side of the window and a series of control buttons on the right. The tree list control is similar to that found in Windows Explorer and allows the user to expand or collapse the tree hierarchy by clicking on the + and - buttons beside the objects. Each object also contains a check box that controls whether the object is hidden or displayed in the main display window. If an object is hidden (i.e. check box is empty) all of its child objects are also hidden.

The currently selected object is shown highlighted in the tree list control. An object can be selected either by clicking on it in the tree control or by clicking on the Pick Vertex button and selecting a vertex by clicking on it in the main display window. The tree control is automatically updated to display the currently selected object. Since a vertex can belong to more than one face, if a vertex is selected using the Pick Vertex button, all of the faces to which it belongs to are expanded in the tree list control. Selecting an object automatically updates the main display window.

Clicking on Display All sets the display check for all objects in the tree list and updates the main display window accordingly.

Clicking on Hide All unsets the display check for all objects in the tree list and updates the main display window accordingly. This may seem pointless but is useful is the user wants to hide all but a select few objects they are interested in.

The remaining controls on the right all operate on the currently selected object.

Deselect deselects the currently selected object.

Add Group adds a new group to the currently selected object. The newly created group is called "New Group" and can be renamed in the Attributes window. Groups can only be added to other groups that don't already contain a sub-entity child. In addition, J3T files do not support more than one group. The Add Group button is disabled unless it is valid to add a new group to the currently selected object.

Add SubEntity adds a new sub-entity to the currently selected object. The newly created sub-entity is called "New SubEntity" can can be renamed in the Attributes window. Sub-entities can only be added to a group that does not already contain sub-groups. In addition, J3D files do not allow more than one sub-entity per group. The Add SubEntity button is disabled unless it is valid to add a new sub-entity to the currently selected object.

Add Face adds a new face to the currently selected object. The New Face window is displayed, allowing the user to specify which vertices the new face uses. The New Face window is described in detail below. Faces can only be added to sub-entities. The Add Face button is disabled unless it is valid to add a new face to the currently selected object. The newly created face and any vertices created along with it are given appropriate names, typically an index value.

Delete deletes the currently selected object (and it's children). Not all objects can be deleted; for example, the root group cannot be deleted, the "Jane's Terrain" sub-entity in J3T files cannot be deleted. If the currently selected object cannot be deleted, the "Delete" button is disabled.

Because vertices can belong to more than one face, deleting them can be problematic. Consequently, vertices cannot be explicitly deleted by the user. Instead, 'orphan' vertices (i.e. those that no longer belong to any faces) are automatically culled by the program as it processes the hierarchy.

Deleted objects are not immediately removed from the object tree; instead, they are flagged as having been deleted and removed from the display. They will not be permanently removed from the object hierarchy until the user commits changes by clicking on either the "Commit Changes" or "Save J3 File" buttons in the main window and accepts the prompts. This deferred deletion allows the user to undelete objects if required. Objects that have been deleted are flagged in the Object Tree with a trailing '(*)' until the changes are committed, at which point the objects are permanently removed from the object hierarchy.

When an object is deleted, it is not immediately removed from the object hierarchy. Instead, it is flagged as having been deleted and removed from the display. This allows the object to be undeleted at a later point if required. To undelete an object, select it from the object tree window and click on the "Undelete" button. The "Delete" button toggles into the "Undelete" button and vice versa depending on the state of the currently selected object.

Clicking on the "Copy" button copies the currently selected object into the copy buffer. This object can then be pasted into another object using the "Paste" button as described below. If the currently selected object cannot be copied, the "Copy" button is disabled.

If the object that is currently in the copy buffer is deleted, either in whole or in part, that will be reflected in subsequent paste operations. For example, if the user copies a groupA which consists of sub-entities sA1 and sA2 into the copy buffer, and then deletes sub-entity sA1, subsequent paste operations will paste groupA and sub-entity sA2 into the currently selected object but sub-entity sA1 will not be copied.

If the copy buffer contains an object, that object can be pasted into other objects. The J3Editor doesn't allow objects to be pasted if doing so will result in an invalid object hierarchy. Whether a paste is appropriate depends on the type of the currently copied object, the type of the currently selected object and the type of the object model file currently being processed. If a paste operation is inappropriate in the current context, the "Paste" button is disabled.

The paste operation does not clear the contents of the copy buffer. i.e. the copied object can be pasted into as many other objects as desired.

Close closes the Object Tree Hierarchy window. It can be opened again by clicking on the Objects... button in the main window.

New Face Window

Texture List

The New Face window is opened when the user clicks on Add Face in the Object Tree Hierarchy window. The New Face window contains a series of controls that allow the user to create a new face and specify which vertices the newly created face is to use. Each face uses three vertices, which can either be selected from a list of existing vertices within the sub-entity or newly created. To use existing vertices, select them from the appropriate drop down list under the Use Existing label. The attributes of the selected vertex are displayed in the corresponding attribute fields to the right of the drop down list. The attributes of existing vertices cannot be modified in the New Face window; the attribute fields of these vertices are set read-only. To modify the attributes of these vertices use the Attributes window which is described below. To use entirely new vertices, click on the New Vertex button at the right of the window. This will create a new vertex with default attributes. The attribute fields can then by edited by hand.

The winding of the face can be changed by clicking on the Change Winding button. This simply swaps the location of the first and third vertex.

None of the changes made take effect until the Apply button is clicked. Clicking on Close discards all changes and no new face or vertices are created. Once the Apply button is pressed, changes take immediate effect and the main display window is updated accordingly.

Textures Window

Texture List

The Textures window displays the list of textures used by the J3 file and contains a number of controls that allow the user to manipulate those textures. The textures used to texture an object in a J3 file are specified as an index into the texture list, so changing the entries in the texture list changes the appearance of the object. The order in which textures appear in the list is important.

The textures in the list are prefixed by a number in brackets indicating that texture's index in the list. If the texture is moved up or down the list, the index changes. Textures are selected in the list by left clicking on them using the mouse.

Add Texture adds a texture to the bottom of the list. The texture is selected by the user using a standard File Open dialog. Textures can be added to the list at any time.

Remove Texture removes the currently selected texture from the list and moves any textures that were below it up the list.

Rename Texture opens a window that allows the user to rename the currently selected texture. The user must ensure that the newly specified texture (a) exists and (b) is included in the ww2.sqs or terrain.sqs archive, otherwise the game will crash when the modified J3 file is installed.

The Up and Down buttons allow the user to move the currently selected texture up and down in the texture list.

Changes made to the texture list take immediate effect and are reflected in the main display window.

Display Properties Window

Texture List

The Display Properties window contains a series of edit controls that allow the user to customize the light and colour properties used by the J3Editor. The ambient, diffuse and specular fields allow the user to specify the colour and intensity of light in the scene. Background allows the user to specify the background colour. Solid, selected, point and highlight allow the user to specify the colours used to paint the object in various states and the Light0 fields control the placement of the single light source used to light the scene. R, G, B and A fields stand for red, green, blue and alpha respectively and should be specified in the range 0.0 .. 1.0. Light0 placement is specified as a coordinate in object space. Light placement appropriate for aircraft or ground objects is probably not appropriate for terrain tiles. For terrain tiles, place the light source at least a couple of thousand metres above the origin. The best way to figure out what the settings do is to experiment with them.

Transform Properties Window

Texture List

The Transform Properties window contains a series of edit controls that allow the user to specify the scaling factors for object placement and viewpoint transforms. These scaling factors allow the user to specify how much to transform objects and the viewpoint in response to mouse movement. The larger the scaling factor, the larger the transform. Changes made to these values do not take effect until the user clicks on the Apply button. Changes are discarded if the Close button is clicked. Clicking on the Save button saves the specified transform properties and restores them the next time the J3Editor is launched.

The Scale scaling factors specify how much the currently selected object is scaled in each of the 3 dimensions when the user clicks on the Scale buttons in the main toolbar. Be sure not to set these values too small otherwise the object will be scaled down to miniature level.

The Translate scaling factors specify how much the currently selected object is moved in each of the three dimensions when the user translates it. Setting any of these values to 0 will lock the object in place in that dimension.

The Rotate scaling factor controls the rate at which the currently selected object is rotated when the user rotates it. Rotation is scaled by the same amount in all dimensions.

The Viewpoint scaling factors behave similarly and should be self-explanatory.

Grid Properties Window

Texture List

The Grid Properties window contains a series of controls that allow the user to control the properties of the grids and grid overlays displayed in the main draw window. Grids and grid backdrops/overlays can be specified independently for each of the three planes XY, YZ and XZ. These grids and overlays can be turned on and off by using the check boxes provided. Changes do not take effect until the Apply button is clicked. Clicking on Close discards all changes. Clicking on Save saves the specified grid properties and restores them the next time the J3Editor is launched.

The interval, min and max edit controls allow the user to specify the minimum and maximum extent of the grids as well as the spacing between grid lines. All values are specified in metres. For example, Min -10, Max 10 and interval 2 (as shown above) results in a 20x20m grid with gridlines every 2m.

The Offset fields allow the user to specify how many metres the grid (and grid overlay) is offset in the specified plane. Values can be either positive or negative and are specified in metres. For example, an offset of -3 in the XZ plane would move the grid (and grid overlay) 3 metres behind the origin in the XZ plane.

The R, G and B fields allow the user to control the colour used to draw the gridlines. R, G and B stand for red, green and blue respectively. Values should be specified in the range 0.0 .. 1.0.

The Backdrop edit fields allow the user to specify a bitmap to overlay on top of the grid in the specified plane. Overlays must be bitmaps and must have an aspect ratio of 1.0 (i.e. width = height). The specified overlay is stretched over the grid. The "..." buttons open a Windows Explorer session allowing the user to browse for bitmap overlays.

The Move button allows the user to move the bitmap overlay in the main display window. Click on the move button for the desired overlay and then move the mouse to the main display window. Left click the mouse button and hold it down while dragging the mouse across the display. The overlay will move with the mouse, allowing the user to place the overlay where desired on screen. This is useful to fine tune overlay placement to align it with an object. This move feature works best in conjunction with the CentreX/Y/Z buttons in the main toolbar. First centre the object on screen using the Centre buttons then move the overlays.

Projection Properties Window

Texture List

The Projection Properties Window contains a series of edit controls that allow the user to customize the projection properties used when rendering the object in the main display window. Two projection modes are provided: perpsective and orthogonal.

The Orthogonal edit controls allow the user to specify the left/right, top/bottom and near/far clipping planes of the projection frustum. The left/right clipping planes are controlled by the XMin and XMax controls, the top/bottom clipping planes by the YMin and YMax controls and the near/far clipping planes by the ZMin and ZMax controls respectively. Care must be taken to ensure that the specified frustum is valid and yields a useful view of the object. For example, setting the near and far clipping planes too close to the viewpoint may result in clipping the object out of the view frustum entirely. By default, the viewing frustum is specified with an aspect ratio of 1.3333 to yield the best, least distorted image on screen. Setting the clipping frustum with a different resultant aspect ratio will result in a distorted image.

The Perspective edit controls allow the user to specify the field of view (FoV, in degrees) and near and far clipping planes for perspective projections. Again, care must be taken to ensure that the near and far clipping planes are set such that the resulting view is useful. Fields of view between 45 and 60 degrees yield the best results. Values outside that window distort the image (e.g. fisheye lens effect).

Changes made to the controls do not take effect until the Apply button is clicked. Clicking on the Close button discards any changes. Clicking on the Save button saves the specified projection properties and will restore them the next time the J3Editor is launched.

Attributes Window

Texture List

The Attributes window contains a series of controls that display information about the currently selected object and allow the user to edit that information. The information displayed depends on the type of the currently selected object. The Attributes window is automatically updated when a new object is selected. Any changes made to the attributes are applied when the user clicks on the Apply button, or discarded when the user clicks on the Close button.

The GroupName edit control displays the name of the selected group, if the currently selected object is a group, or the name of the selected object's immediate parent group otherwise. This control can be edited to change the name of the group. Certain group names cannot be edited (e.g. "Jane's Terrain" in J3T files), in which case this field is set read-only.

The SubEntityName edit control displays the name of the selected sub-entity. If the currently selected object is a group, the SubEntityName field is blank. If the current selected object is a sub-entity, or the name of the selected object's parent sub-entity otherwise. This control can be edited to change the name of the sub-entity.

The FaceName list control displays the name of the selected face. If the currently selected object is a group or a sub-entity, the FaceName control is blank. The edit control can be edited to change the name of the face. When the selected object is a vertex, the FaceName control contains a list of that vertex's parent faces; the user can select a specific face by choosing it from the drop down list and clicking on the Select button.

The Bitmap control displays the bitmap texture associated with the currently selected object. Textures are specified at the sub-entity level, so this control is blank if the selected object is a group. The bitmap control contains a drop down list showing all of the textures used in the J3 file. The bitmap associated with the sub-entity can be changed by choosing a different entry from the drop-down list and clicking on Apply.

The Translate fields display the group's translate x, y and z values. These values can be edited.

The Rotate fields display the group's rotate x, y and z values, specified in radians. These values can be edited.

The Absolute fields display the group's location in absolute object space. Since object translate and rotate values are specified relative to their parent group, knowing where an object is located in absolute object space can become quite confusing. For example, if groupA has translate values of (1.0, 2.0, 1.0) and it's child groupB has translate values of (0.0, 1.0, -2.0), any children of groupB would have an origin of (1.0, 3.0, -1.0) in absolute object space. Things become even more confusing when dealing with nested rotations.

The vertex controls display information about the currently selected vertex or about the child vertices of the currently selected face. If the currently selected object is a group or sub-entity, these controls are blank. The vertex list control displays the name of the vertex. Vertex names cannot be edited; any edits in this field are ignored. If the currently selected object is a face, the vertices used in that face can be changed by choosing new vertices from the vertex drop down lists. The vertex x, y, z and textureU and textureV coordinate pairs are also displayed and can be edited.

If the currently selected object is a face, the winding of the vertices can be changed by clicking on the Change Winding button. This simply swaps the location of the first and third vertices.






Afterword

All of this is probably quite overwhelming for the novice user who probably just wants to start modifying the 3D objects and doesn't quite know where to start. My advice is to not feel overly intimidated, don't be afraid to try things out and see what happens. The worst that can happen is that the resulting J3 file doesn't work.






Acknowledgements

My heartfelt thanks go out to Ed, Hammerd and Hemingway for their patience and perseverance in beta testing the J3Editor and for the valuable feedback they provided. Many of the features you see in the editor are the result of their feedback. Any errors that remain are my sole responsibility.






Appendix A: Description of the J3 Object Model Files



Structure of Terrain (J3T) files

Vertex::
Field		bytes	Data type	Notes
-----		-----	---------	-----
x		4	float		in metres; offset from the centre of the tile
y		4	float		in metres  altitude
z		4	float		in metres; offset from the centre of the tile
normalX		4	float		vertex normal x
normalY		4	float		vertex normal y
normalZ		4	float		vertex normal z
textureU	4	float		x-offset into texture (percentage)
textureV	4	float		y-offset into texture (percentage)

Notes: 
1) Terrain grid has origin in the bottom left corner.  i.e. X001_Y001 is in the southwest
corner of the map, X058_Y030 is in the northeast corner of the map.  
2) "Jane's Terrain" entities describe the tile when seen from a distance.
3) "Jane's Terrain" appears as the first entity in some files, and the last in others.  Object
order doesn't seem to matter.
4) Numbers following the ??: tag have an unknown function and should NOT be changed.  Changing them
during testing corrupted the terrain.sqs archive.
5) Faces MUST have three vertices only (i.e. faces are triangles)
6) The number of vertices and faces for the record can be changed but the numFaces and numVertices 
counters MUST be updated accordingly.  
7) The texture used is given in the Record: field at the start of each record.
8) The texture used for the "Jane's Terrain" entities are stored separately; if the terrain tile is
X001_Y012.J3D, the "Jane's Terrain" entity uses the X001_Y012.BMP bitmap texture.
9) Preliminary testing shows that planes collide properly with modified terrain.  I did run one
test where the collision detection didn't work and the plane flew straight through a steep cliff,
so be aware that it can happen.  I haven't been able to isolate the conditions under which the
collision detection succeeds/fails though.  It seems to work most of the time.
10) Preliminary testing also shows that the game interprets blue-tinted terrain textures as water, 
and generates the appropriate ripple and splash effects for bullet hits and crashes.  However, ground
objects can still move around and planes can still land on these "water" textures.


Structure of Object (J3P) files


Entity::
Field		bytes	Data type	Notes
-----		-----	---------	-----
name		32 	char 		left justified, null padded
x		4 	float	
y		4	float
z		4	float	
separator	4	float		unused
rotateX		4	float		in radians
rotateY		4	float		in radians
rotateZ		4	float		in radians
sibling		4	int		ID of immediate sibling (if any)
parent		4	int		ID of immediate parent (if any)
child		4	int		ID of immediate child (if any)
numFaces	2	short		total faces for this entity, including all sub-entities*
numVertices	2	short		total vertices for this entity, including all sub-entities*
textured	2	short		flag indicating whether entity is textured
cFaces		2	short		cumulative face count
cVertices	2	short		cumulative vertex count
numSubs		2	short		number of sub-entities* of this entity
mode??		2	short		unknown (may indicate draw-mode)
terminator	2	short		static value -5141 (0xEB 0xEB)

* a sub-entity is a series of vertex/face values

Notes:
1) Names should not be modified (for now), and the colon at the end of names MUST not be
removed.  During testing, I discovered that if any trailing blanks were removed from some 
names (e.g. in P47COCKPIT.J3P) the game would crash during initialization.  This leads me 
to believe that the game looks for specific names.
2) If the number of faces/vertices is changed for a particular entity, great care must be 
taken to ensure that all of the face/vertex counts are updated accordingly, including
the cumulative face/vertext counts.
3) Both J3D and J3P object models use an entity hierarchy.  Vertices are specified relative to
their parent entity, and the parent entity coordinates are specified relative to its parent
entity and so on.  Parent entities often, though not always, have "GRP" at the end of their name.
Since entity coordinates are relative to their parent, changing the x,y,z coordinates of the parent 
entity results in all of its children being translated by the same amount.
4) The Bitmap: field specifies the index of the bitmap used to texure this entity.  A value of -1
indicates no bitmap and the object will be "painted" plain white.


Vertex::
Field		bytes	Data type	Notes
-----		-----	---------	-----
x		4	float		relative to parent
y		4	float		relative to parent
z		4	float		relative to parent
separator	4	float		unused
normalX		4	float		vertex normal X
normalY		4	float		vertex normal Y
normalZ		4	float		vertex normal Z
separator	4	float		unused
textureU	4	float		x-offset into texture (percentage)
textureV	4	float		y-offset into texture (percentage)


Face::
Field		bytes	Data type	Notes
-----		-----	---------	-----
a		2	short		face A
b		2	short		face B
c		2	short		face C

Notes:
1) Faces are triangles


Structure of Object (J3D) files

Vertex::
Field		bytes	Data type	Notes
-----		-----	---------	-----
x		4	float		relative to parent
y		4	float		relative to parent
z		4	float		relative to parent
separator	4	float		unused
normalX		4	float		vertex normal x
normalY		4	float		vertex normal y
normalZ		4	float		vertex normal z
separator	4	float		unused
textureU	4	float		x-offset into texture (percentage?)
textureY	4	float		y-offset into texture (percentage?)

Face::
Field		bytes	Data type	Notes
-----		-----	---------	-----
a		2	short		vertex A
b		2	short		vertex B
c		2	short		vertex C
bitmapIndex	1	unsigned char	index of bitmap used by this face

Notes:
1) bitmapIndex MUST be the index of one of the bitmaps specified later in the file. i.e. if there
are 10 bitmaps, the bitmapIndex values MUST lie in the range 0-9


Entity::
Field		bytes	Data type	Notes
-----		-----	---------	-----
name		32	char	 
x		4	float
y		4	float
z		4	float
separator	4	float
rotateX		4	float		in radians
rotateY		4	float		in radians
rotateZ		4	float		in radians
sibling		4	int		ID of immediate sibling (if any)
separator	4	int		unused
parent		4	int		ID of immediate parent (if any)
child		4	int		ID of immediate child (if any)
numFaces	2	short		number of faces in this entity
firstFace	2	short		ID of first face
numVertices	2	short		number of vertices in this entory
firstVertex	2	short		ID of first vertex
??		4	int		unknown (binary flag?)
??		4	int		unknown (binary flag?)
??		4	int		unknown (binary flag?)

Notes:
1) The colon at the end of the name MUST not be removed.
2) Both J3D and J3P object models use an entity hierarchy.  Vertices are specified relative to
their parent entity, and the parent entity coordinates are specified relative to its parent
entity and so on.  Parent entities often, though not always, have "GRP" at the end of their name.
Since entity coordinates are relative to their parent, changing the x,y,z coordinates of the parent 
entity results in all of its children being translated by the same amount.