Tutorial (ii) - Converting Other Objects

 

Introduction

Once you have got to grips with the basic functions of Forester, you will probably want to try adding some new objects to your scenes. There are two options here: 1) Create objects from scratch using POV-Ray, or 2) Convert objects from other formats for use in POV-Ray and Forester. This tutorial looks at the second option, and deals with converting a 3D Studio Max object into a Forester-compatible POV-Ray format.

1. Find a suitable Object

You need to start by finding an object that you want to convert. I don't have access to 3D Studio myself, but I have found a suitable free object on the Avalon web-site which I will use for this tutorial. NOTE: Although the object does not appear to have any specific copyright notice, I am cautious about publishing it with this tutorial in case of any possible copyright infringement. Therefore, if you want to use this particular object yourself, download it from the Avalon site and follow this tutorial step by step.

The object that I am using is a model of an F18 fighter jet. It can be found on the Avalon site by following these links: Click the 'Avalon Meshes' link at the top, Select 'Aircraft' from the menu; select 'Planes'; select the 'F18 3DS' model and download it to your harddrive. Extract the f18.3ds file from the archive.

2. Convert Model to a POV-Ray file

The first step is to convert the 3DS file into a POV-Ray file. The POV-Ray file consists of a number of Mesh objects, defining the tiny triangles that make up the whole model. In this example I have used 3DWin to convert the file types. During the conversion I used the 'Normalise' function to modify the model so that the object lies within the bounding box (-1,-1,-1 to 1,1,1). 3DWin creates a number of POV-Ray include files from the initial 3DS file. These each contain different components of the scene (eg Material Definitions, Camera position, lighting, objects, etc) and are given different suffixes accordingly. We only need one of these files - the one ending in '_o' - this contains the mesh objects.

NOTE: I have also converted objects using Rhino, an excellent 3D NURBS modelling program. There is a downloadable demo version that is limited to 25 saves - use these sparingly! ;-)

3. Create Folder for new object

A new folder needs to be created to hold all of the necessary files. This should be created in the relevant sub-directory of the Forester/Libraries folder. As this particular model is an aeroplane, create a new folder within the Forester\Libraries\aircraft folder. Call it 'f18_01'. I like to use lower-case letters for consistency, although this is not necessary. I have also added the '_01' to ensure that the object has a unique name.

Copy the _o.inc file from step (2) into the new folder and rename it 'f18_mesh.inc'.

4. Begin editing the mesh file

Right, you should now have a single (huge) POV-Ray include file with 40 or so separate mesh objects that make up the F18 model. Each mesh object is defined as in the following example:

#declare V_P_OBJ40BoundMin = <-0.610671, 1.241659, 0.040392>;
#declare V_P_OBJ40BoundMax = <0.610671, 1.443086, 0.068976>;

#declare P_OBJ40 = mesh // OBJ40
{
	smooth_triangle {<-3.326415, 24.568954, 0.885406>, <-0.994576, 0.004278, -0.103924>, ...

  etc ...

We now have to do a bit of editing to 'clean up' the file for use in Forester. To start with, the variable declarations for ...BoundMin and ...BoundMax are not needed so can be safely deleted (you will need to scroll down through the file deleting every occurrence).

Next, the remaining mesh object variables need to be renamed to avoid any possible confusion with other Forester objects. Therefore, they should each be given a descriptive name, which includes the main object name. eg: f18_01_wings or f18_01_canopy, etc. There is obviously a bit of a problem here - how do we know what each of the objects actually are? After all, they only have numbers to differentiate them. There are a number of ways around this. One way is to guess the names, and then experiment at a later stage by swapping the textures for the different parts around and performing test renders to see which material affects which part of the aircraft. (More on textures later). This method is obviously a bit of a hassle. The method I used was to open the model in Rhino and select each part in turn to see what name it had. In this way I was able to ascertain the different parts quite quickly. The results are as follows:

P_OBJ1 : f18_01_nosetip
P_OBJ2 : f18_01_nosecone
P_OBJ3 : f18_01_nosevent1
P_OBJ4 : f18_01_nosevent2
P_OBJ5 : f18_01_nosehatch
P_OBJ6 : f18_01_canopy
P_OBJ7 : f18_01_canopyframe1
P_OBJ8 : f18_01_canopyframe2
P_OBJ9 : f18_01_fuselagetop
P_OBJ10 : f18_01_vents1
P_OBJ11 : f18_01_fuselagebotton
P_OBJ12 : f18_01_vents2
P_OBJ13 : f18_01_vents3
P_OBJ14 : f18_01_vents4
P_OBJ15 : f18_01_engine1
P_OBJ16 : f18_01_engine2
P_OBJ17 : f18_01_engine3
P_OBJ18 : f18_01_engine4
P_OBJ19 : f18_01_wings1
P_OBJ20 : f18_01_engine5
P_OBJ21 : f18_01_engine6
P_OBJ22 : f18_01_enginebase
P_OBJ23 : f18_01_tail1
P_OBJ24 : f18_01_tail2
P_OBJ25 : f18_01_rockettip1
P_OBJ26 : f18_01_rocketpart1
P_OBJ27 : f18_01_rocketbody1
P_OBJ28 : f18_01_rocketfin
P_OBJ29 : f18_01_engineexhaust1
P_OBJ30 : f18_01_engineexhaust2
P_OBJ31 : f18_01_rudder1
P_OBJ32 : f18_01_rudder2
P_OBJ33 : f18_01_rudder3
P_OBJ34 : f18_01_rockettip2
P_OBJ35 : f18_01_rocketbody2
P_OBJ36 : f18_01_vents5
P_OBJ37 : f18_01_wings2
P_OBJ38 : f18_01_wingflaps
P_OBJ39 : f18_01_wings3
P_OBJ40 : f18_01_wingstruts

Rename each declaration using the names in the above table. For example, the following line:

#declare P_OBJ40 = mesh // OBJ40

becomes:

#declare f18_01_wingstruts = mesh 

etc...

5. Create the textures

Now that the individual mesh components are correctly named we can create some basic textures to apply to them. The following code uses a simple POV-Ray #if...#then...#else statement to test the Forester_RedObjects variable to decide whether the current render should use the proper textures for a standard image or whether it should use the 'AllRedTexture' for a mask render.

Copy the following code to the end of the mesh file.

#if (Forester_RedObjects=true)

  #declare f18_01_lightgreymetal = Forester_AllRedTexture
  #declare f18_01_darkgreymetal = Forester_AllRedTexture
  #declare f18_01_bluishmetal = Forester_AllRedTexture
  #declare f18_01_yellowmetal = Forester_AllRedTexture
  #declare f18_01_glass = Forester_AllRedTexture

#else

  #declare f18_01_lightgreymetal =
    texture {
      pigment {
        color rgb < 0.9, 0.9, 0.9 >
        }        
      normal {
        granite, 0.01                
        }
      finish {
        ambient  0.2
        diffuse  1.0
        specular 0.5
        roughness 0.1  
        metallic
        reflection 0.05       
        }
      }

  #declare f18_01_darkgreymetal =
    texture {
      pigment {
        color rgb < 0.7, 0.7, 0.7 >
        }
      normal {
        granite, 0.005                
        }        
      finish {
        ambient  0.2
        diffuse  1.0
        specular 0.8
        roughness 0.15       
        }
      } 

  #declare f18_01_bluishmetal =
    texture {
      pigment {
        color rgb < 0.4, 0.4, 0.45 >
        }
      normal {
        granite, 0.02                
        }        
      finish {
        ambient  0.2
        diffuse  1.0
        specular 0.8
        roughness 0.15
        metallic        
        }
      }      

  #declare f18_01_yellowmetal =
    texture {
      pigment {
        color rgb < 0.6, 0.6, 0 >
        }        
      finish {
        ambient  0.4
        diffuse  0.8
        specular 1.0
        roughness 0.2        
        }
      }

  #declare f18_01_glass =
    texture {
      pigment {
        color rgbt < 0.3, 0.3, 0.3, 0.5>
        }
      finish {
        ambient  0.1
        diffuse  1.0
        specular 1.0
        roughness 0.01
        reflection 0.4
        }
      }

#end

6. Create the Complete Object

Now that the models components and textures have been defined, they need to be brought together in a single object which can be manipulated by Forester. This is done by the following code: (Copy and paste this to the end of the file)

#declare f18_01_entirity =
  union {
    object { f18_01_nosetip texture { f18_01_yellowmetal } }
    object { f18_01_nosecone texture { f18_01_darkgreymetal } }
    object { f18_01_nosevent1 texture { f18_01_bluishmetal } }
    object { f18_01_nosevent2 texture { f18_01_yellowmetal } }
    object { f18_01_nosehatch texture { f18_01_lightgreymetal } }
    object { f18_01_canopy texture { f18_01_glass } interior { ior 1.5 } }
    object { f18_01_canopyframe1 texture { f18_01_darkgreymetal } }
    object { f18_01_canopyframe2 texture { f18_01_darkgreymetal } }
    object { f18_01_fuselagetop texture { f18_01_lightgreymetal } }
    object { f18_01_vents1 texture { f18_01_darkgreymetal } }
    object { f18_01_fuselagebottom texture { f18_01_lightgreymetal } }
    object { f18_01_vents2 texture { f18_01_darkgreymetal } }
    object { f18_01_vents3 texture { f18_01_bluishmetal } }
    object { f18_01_vents4 texture { f18_01_bluishmetal } }
    object { f18_01_engine1 texture { f18_01_bluishmetal } }
    object { f18_01_engine2 texture { f18_01_darkgreymetal } }
    object { f18_01_engine3 texture { f18_01_darkgreymetal } }
    object { f18_01_engine4 texture { f18_01_bluishmetal } }
    object { f18_01_wings1 texture { f18_01_darkgreymetal } }
    object { f18_01_engine5 texture { f18_01_lightgreymetal } }
    object { f18_01_engine6 texture { f18_01_bluishmetal } }
    object { f18_01_enginebase texture { f18_01_bluishmetal } }
    object { f18_01_tail1 texture { f18_01_lightgreymetal } }
    object { f18_01_tail2 texture { f18_01_lightgreymetal } }
    object { f18_01_rockettip1 texture { f18_01_yellowmetal } }
    object { f18_01_rocketpart1 texture { f18_01_lightgreymetal } }
    object { f18_01_rocketbody1 texture { f18_01_darkgreymetal } }
    object { f18_01_rocketfin texture { f18_01_darkgreymetal } }
    object { f18_01_engineexhaust1 texture { f18_01_bluishmetal } }
    object { f18_01_engineexhaust2 texture { f18_01_darkgreymetal } }
    object { f18_01_rudder1 texture { f18_01_lightgreymetal } }
    object { f18_01_rudder2 texture { f18_01_lightgreymetal } }
    object { f18_01_rudder3 texture { f18_01_darkgreymetal } }
    object { f18_01_rockettip2 texture { f18_01_bluishmetal } }
    object { f18_01_rocketbody2 texture { f18_01_darkgreymetal } }
    object { f18_01_vents5 texture { f18_01_bluishmetal } }
    object { f18_01_wings2 texture { f18_01_lightgreymetal } }
    object { f18_01_wingflaps texture { f18_01_lightgreymetal } }
    object { f18_01_wings3 texture { f18_01_lightgreymetal } }
    object { f18_01_wingstruts texture { f18_01_darkgreymetal } }
    }   

Because the individual components now have descriptive names it is easy to change textures around by changing the definition after the 'texture {' statement. Try experimenting by adding/reassigning textures to change the look of the aircraft.

7. Create the Forester Object Definition

Start Forester and open the Object Library Editor (Tools menu). Click on the Aircraft section and click Add Object. Name it 'F18_01' (The same name as the folder containing the mesh file). The new object will be placed in the list - expand the object to reveal its first component. Set the 'Object .INC File' to f18_mesh.inc and both the 'Object Name' and 'Red version' to f18_01_entirity:

Next, select the whole object and enter the figures as shown below. There are a few points to note about these values:

NOTE: I have noticed a strange bug when creating new objects that sometimes produces a POV-Ray error when performing the first Preview render. There is a simple work-around: Once the object folder has been created and the object created in the Object Library Editor, close the Object Library Editor (accept the dialogue box to save changes) and then re-open it. This should force Forester to accept the new object.

8. Test the new object