Created by Chris Colefax, 23 September 1998
Updated 22 January 1999: Added mesh_texture, mesh_textures, apply_mesh_textures options; Added bend_mesh () deformation macro; Added cylinder_mesh (), triangle_mesh () creation macros.
Updated 13 May 1999: Added support for bicubic patch surfaces; Added hair_wind_rotation, hair_wind_speed animation options; Removed triangle_mesh () and triangle_morph_meshes () macros.
Updated 20 May 1999: Updated for Warp's Mesh Compressor 1.2a
Updated 28 Dec 1999: Updated for Warp's Mesh Compressor 2.1, adding support for extra-compressed meshes to PCM.MCR and PCMHAIR.MCR
To install the complete Compressed Mesh Macro File package, copy the three *.MCR files (PCM.MCR, PCMHAIR.MCR, and PCMMORPH.MCR) to one of the include file directories (folders) in your POV-Ray library path. Normally, this is the INCLUDE subdirectory of the directory you installed POV-Ray in, eg. (on a Windows 9x system):
C:\Program Files\POV-Ray for Windows v3.1\Include
If you don't want to install the files directly in POV-Ray's directories, you can create a separate directory in which to install the files. In this case, you should add that directory's full drive and path to your main POV-Ray INI file, eg. if you installed the *.MCR files in D:\POVFILES\MACRO you would add the following line to POVRAY.INI:
Library_Path=D:\POVFILES\MACRO
The Compressed Mesh Macro File let you use triangle, smooth triangle, and bicubic patch surfaces compressed by Warp's POV-Ray Mesh Compressor. To read a compressed mesh file you first include the macro file (PCM.MCR) and then call the read_mesh macro with the filename, eg:
#include "PCM.MCR"
object {read_mesh ("MyMesh.pcm") pigment {rgb 1} scale 2.5}
If the mesh file contains more than one mesh you can replace the object keyword with a union. Note that to read extra mesh files, you don't need to include the macro file again - this file need only be included once at the beginning of the scene file.
Meshes created in this way can be used in exactly the same way as uncompressed mesh files. In addition, you can use the options listed below to deform the mesh in various ways (including animated deformations) or replace the triangles/patches with other objects (eg. blobs, cylinders). With the Hair Growth Macro File you can cover the mesh surface with fur, hair, grass, dew-drops, etc., and you can morph between different mesh surfaces with the Mesh Morphing Macro File.
A Note on Performance: The saving in disk space gained by using compressed mesh files does come at a cost - the time required for parsing the mesh files is increased. Using the more advanced features of the macros further increases parsing. As a general guide, using mesh deformations and mesh morphing is fastest with bicubic patch models, whereas mesh creation (including hair growth) is much faster to parse with triangle meshes (rather than patches which have to be subdivided into triangles first).
To use the following options you must define them with the desired values, before calling the read_mesh macro, eg:
#declare debug_progress = true;
#macro deform_mesh () wave_mesh (0.5, 5, clock*3) #end
#declare mesh_textures = array[2] {texture {FirstTexture}, texture {SecondTexture}}
read_mesh ("MyMesh.pcm")
#declare MeshObject = read_mesh ([FileName])
instead of the declare_only option. The default value is false.
object {}
wrapper) you can use this option to declare a texture for all the meshes in a file, eg:
#declare mesh_texture = texture {ShinyMetal}
read_mesh ("MyMesh.pcm")
You can also use this option within a compressed mesh file, so the texture is packaged with the mesh data. To do this, use #local mesh_texture = texture {...}
to declare the entire texture at the beginning of the compressed mesh file (before the "PCM1" line). Note that if the file contains multiple meshes this texture will be applied to all meshes until the end of the file. You can, however, declare separate textures before the start of each new mesh in the file (denoted by the "PCM1"). This also makes it possible to append compressed meshes and textures together, texturing each part of the mesh separately.
#local mesh_textures = array[...
at the beginning of a compressed mesh file to package the textures with the meshes.
object {}
or union {}
wrapper).
Version 1.2 of the POV-Ray Mesh Compressor adds support for the compression of bicubic patch surfaces, and all features of the Compressed Mesh Macro File have been updated as a result. Specifically, the following options have been added to allow you to override the patch properties stored in a compressed file:
pcm_patch_u_steps = 4;
and pcm_patch_v_steps = 2;
would divide the patch into 8 segments (16 triangles) for the mesh creation macros.
A compressed mesh file actually contains a list of all the vertices that make up the mesh surface. You can use the deform_mesh macro to manipulate these vertices in any way you like, including creating animated deformations. To set this option you actually define a macro with no parameters, inside of which you include the code to manipulate the mesh vertices. The Compressed Mesh Macro File includes the following such predefined deformation macros, which you can use like this (note the deform_mesh macro has no parameters, even though the inner macro does):
#macro deform_mesh () wave_mesh (0.3, 4, clock*5) #end
These predefined macros are:
To create your own deform_mesh macros, you actually need to program the macro to read the mesh vertices from the variable File, counting through PointCount X, Y, and Z values. These three float values can be manipulated as you like, before assigning them to a vector in the PointList array (the names of the three variables must be programmed exactly as shown), eg. for a simple displacement macro:
#macro deform_mesh ()
#local Counter = 0; #while (Counter < PointCount)
#read (File, X, Y, Z)
#declare PointList[Counter] = + [DisplacementAmount];
#local Counter = Counter+1; #end
#end
For more advanced examples see the deformation macros in PCM.MCR.
Similar to the deformation macros, you can define a create_mesh macro that uses the mesh vertex data to create and object or objects in place of triangles, smooth triangles, or bicubic patches, eg:
#macro create_mesh () spike_mesh (-1.75, .5) #end
The Compressed Mesh Macro File includes the following predefined mesh creation macros. Note that for bicubic patch models each patch is subdivided into triangles (as described above) before the objects are created as detailed below:
To design your own create_mesh macros, you need to define the macro to read from the File variable, and to support both triangle and bicubic patch mesh models you need to use the VerID value. A value of 1 indicates a triangle/smooth triangle model, for which you should count through three variables for TriangleCount triangles, and then six variables for SmoothTriangleCount smooth triangles. Each value you read from the file is actually the index of the PointList array vector to be used at the corner or normal of the triangle.
A value of 2 indicates a bicubic patch model, for which you should count through PatchCount patches. For each patch you should call the PCM_read_patch_options () macro to read the patch's options, and then sixteen variables indicating the indexes of the PointList array vector for the patch control points. If you store these control points in an array you can then use the PCM_get_patch_point ([Control Point Array], [U Coordinate], [V Coordinate]) macro in PCM.MCR to return the surface value at U, V (this is most useful when you want to place objects randomly on the surface of the patch). Alternatively, you can use the PCM_get_patch_grid ([MakePatch]) macro to read all the values for you, and then subdivide the patch into an array of surface points PCM_patch_grid[U][V] (the resolution set by the u_steps and v_steps values defined in the file or with the override options, saved as PU and PV). Calling PCM_get_patch_grid (true) will also create the patch itself.
As a guideline, the macro should look like:
#macro create_mesh ()
#local Counter = 0; #switch (VerID)
#case (1) // Triangle models
#while (Counter < (TriangleCount)
#read (File, P1, P2, P3)
// Code to create objects using PointList[P1], PointList[P2], and PointList[P3]
#local Counter = Counter+1; #end
#local Counter = 0; #while (Counter < SmoothTriangleCount)
#read (File, P1, N1, P2, N2, P3, N3)
// Code to create objects using PointList[P1], PointList[N1], PointList[P2], PointList[N2], PointList[P3], and PointList[N3]
#local Counter = Counter+1; #end
#break
#case (2) // Bicubic patch models
#while (Counter < PatchCount)
PCM_get_patch_grid (true)
#local U = 0; #while (U < PU) #local V = 0; #while (V < PV)
// Code to create objects using PCM_patch_grid[U][V], PCM_patch_grid[U+1][V], PCM_patch_grid[U+1][V+1], PCM_patch_grid[U][V+1]
#local V = V+1; #end #local U = U+1; #end
#local Counter = Counter+1;
#end
#end
For more detailed examples and guides, you can examine the predefined mesh creation macros in PCM.MCR.
To use the Hair Growth Macro File, include PCMHAIR.MCR before using the read_mesh macro in the usual way. Including this file will also include PCM.MCR if required, so it is not necessary to include both macro files. Also, including PCMHAIR.MCR will redefined any existing create_mesh macro.
transform {}
option will be applied to each and every hair object created. This is often faster to render than transforming the completed union of the mesh surface and hair objects.
You can also give each hair object a patterned pigment or texture by first calling the desired hair object macro and then modifying it as desired, eg:
#declare hair_thickness = 0.05;
smooth_triangles_hair_object ()
#declare hair_object = object {hair_object
pigment {gradient y color_map {[0 rgb 1] [1 rgb 0]}}
normal {bumps 0.1 scale <0.1, 1, 0.1>}}
Calling any of the following options will create a #declared hair_object option. This hair_object can then be used as is, or modified, combined with other objects, declared as part of a hair_objects array, etc.
The following options control the hair objects declared by the previous four macros, and so must be declared before calling the desired macro. Note that, as shown, not all the options apply to all the macros.
Only one of the following options will be used, in order of importance (ie. the second option overrides the first). Note that for bicubic patch models each patch is subdivided into triangles (as described above), after which these options are applied:
Vector values can also be used to control how much the hairs follow the normal along each axis, eg: #declare hair_rotate_to_surface = <1, 0, 1>;
would mean the orientation of the hairs along the x and z axes would change, but the orientation along the y axis would remain constant. Note that these rotations apply before any changes to the hair_sky option, ie. also using #declare hair_sky = -x;
would mean the rotations for the x and z axes would be applied first, and then each hair object would be rotated from +y to -x.
#declare hair_rotation_turb = <0.1, 1, 0>;
would mean slightly random rotation around the x-axis, and completely random rotation around the y-axis.
object {}
statement marked hollow (which also makes the mesh surface itself hollow).
To use the Mesh Morphing Macro File, include "PCMMORPH.MCR" and then call the morph_meshes macro as follows:
object {
morph_meshes ( [Mesh FileName List Array], [Current Morph Position] )
[object modifiers]
}
The first macro option is a single dimensional array of strings, listing the filenames of the compressed meshes to morph between. The same filename can be used multiple times in the list, and the standard POV-Ray rules about relative and library paths apply.
The second option is a float value specifying the morph position, with integer values corresponding to unmorphed meshes in the filename array, eg. a value of 0 would create the first mesh in the list, a value of 1.5 would create a mesh morphed halfway between the second and third meshes in the list. For animations this can be as simple as clock * [index of last file in list], or it can be a modified clock that cycles back and forward through the mesh file list.
For the morphing to work each file in the list must have:
Note that the actual number of vertices in each file (which has the greatest effect on its compressed size) is not important. Also, the morphing is calculated for each triangle/patch as it is encountered in the files to be morphed between, so the order of the triangles/patches in the mesh should also correspond for the desired result. Generally, if you have used the Mesh Compressor to compress meshes exported purposely from another program all these requirements will be met without problems.
#declare morph_mesh_texture = array[2][2] {
{ texture {pigment {White}}, texture {pigment {Black}} },
{ texture {pigment {Yellow}}, texture {pigment {Red}} }
If the first mesh file in the file list contained a sphere and box and the second contained a cone and cylinder, the result would be a white sphere morphing to a black cone, and a yellow box morphing to a red cylinder.
object {}
statement (or union {}
for multiple meshes).
As with the Compressed Mesh Macro File, it is possible to create macros that deform the mesh surface in various ways.
In the case of the Mesh Morphing Macro File, the macro you must define is deform_morph_meshes (). There are no such macros predefined in the macro file, but to create your own you should use the following syntax (with all variable names as shown):
#macro deform_morph_meshes ()
#read (File1, PointCount) #if (PointCount > 0)
#local PointList1 = array[PointCount]
#local Counter = 0; #while (Counter < PointCount)
#read (File1, X, Y, Z)
#local PointList1[Counter] = <X, Y, Z>;
// Code to deform mesh vertices
#local Counter = Counter+1; #end
#end
#read (File2, PointCount) #if (PointCount > 0)
#local PointList2 = array[PointCount]
#local Counter = 0; #while (Counter < PointCount)
#read (File2, X, Y, Z)
#local PointList2[Counter] = <X, Y, Z>;
// Code to deform mesh vertices
#local Counter = Counter+1; #end
#end
#end
Note that it is no longer necessary to also define a deform_mesh macro for handling single meshes when the deform_morph_meshes macro is defined.
The syntax for the create_morph_meshes macro is as follows (with all variable names as shown):
#macro create_morph_meshes ()
#local Counter = 0; #switch (VerID)
#case (1) // Triangle models
mesh { #while (Counter < TriangleCount)
#read (File1, P1, P2, P3) #read (File2, P4, P5, P6)
// Code to create objects using PointList1[P1]*Weight1 + PointList2[P4]*Weight2, PointList1[P2]*Weight1 + PointList2[P5]*Weight2, PointList1[P3]*Weight1 + PointList2[P6]*Weight2
#local Counter = Counter+1; #end
#local Counter = 0; #while (Counter < SmoothTriangleCount)
#read (File1, P1, N1, P2, N2, P3, N3) #read (File2, P4, N4, P5, N5, P6, N6)
// Code to create objects using PointList1[P1]*Weight1 + PointList2[P4]*Weight2, PointList1[N1]*Weight1 + PointList2[N4]*Weight2, PointList1[P2]*Weight1 + PointList2[P5]*Weight2, PointList1[N2]*Weight1 + PointList2[N5]*Weight2, PointList1[P3]*Weight1 + PointList2[P6]*Weight2, PointList1[N3]*Weight1 + PointList2[N6]*Weight2
#local Counter = Counter+1; #end }
#break
#case (2) // Bicubic patch models
union { #local PList = array[16] #while (Counter < PatchCount)
PCM_read_morph_patch_options ()
#declare Counter2 = 0; #while (Counter2 < 16)
#read (File1, P1) #read (File2, P2)
#local PList[Counter2] = PointList1[P1]*Weight1+PointList2[P2]*Weight2;
#declare Counter2 = Counter2+1; #end
#local U = .5; #while (U < PU) #local V = .5; #while (V < PV)
// Code to create objects based on PCM_get_patch_point (PList, U/PU, V/PV)
#local V = V+1; #end #local U = U+1; #end
#local Counter = Counter+1; #end }
#end
#end
As you can see, the triangle vertices and patch control points are linearly interpolated using Weight1 and Weight2. The create_morph_meshes macro can be used to create surfaces using objects other triangles and patches, and it can also be used to change the way the vertices are interpolated.
There is one morph mesh creation macro defined in PCMMORPH.MCR:
The Compressed Mesh Macro File, including PCM.MCR, PCMHAIR.MCR, PCMMORPH.MCR, all associated documentation, sample scenes, and animations, are copyright 1998-1999, Chris Colefax. Full permission is granted to the user to modify any or all of the files for his/her own use. If modified versions are to be distributed the user should make clear the modifications that have been made by him/herself.
The Compressed Mesh Macro File may be bundled with or without other software on CD-ROM collections, Bulletin Board systems and other file archives, providing that all associated files, including documentation and samples, are included. I would also request that persons intending to distribute the Compressed Mesh Macro File in this manner or otherwise would first contact me to ensure that they are in possession of the latest available version.
Further, no restrictions of any sort are placed on the usage of the macro file itself, and scene files or images created using the macro file remain entirely the property of the user or users who have created them. I claim no liability or responsibility for damages or loss resulting from usage of the macro file, or any part of the macro file package.
If you wish to contact me with bug reports, bug fixes, criticisms, comments, suggested improvements, questions, etc. you can reach me by email at:
or by regular mail at:
Chris ColefaxPOV-RayTM and Persistence of VisionTM are registered trademarks of the POV-Ray TeamTM