Vertex Map Object Agents

 

The constructor for VMap Object Agents is called VMap(), and in most cases it can be used globally.

vmap = VMap(<VMap Type>);

This constructor returns a VMap Object Agent. VMaps can be identified by name string or by integer index of a particular VMap type. These VMap types are described below:

VMSELECT                     "select"

VMWEIGHT                     "weight"

VMSUBPATCH                "subpatch"

VMTEXTURE                   "texture"

VMMORPH                     "morph"

VMSPOT                        "spot"

VMRGB                          "rgb"

VMRGBA                       "rgba"

VMap() will return 'nil' if no Vertex Maps of that type exist in the system. Invoking VMap() without a specific Vertex Map type argument will cause VMap() to return the first Vertex Map it encounters in the system. From this starting Vertex Map, you can iterate through all other maps with the next() method. The next() method disregards type boundaries, so if you want to process specific types of Vertex Maps, you must watch for them.

The VMap Object Agent can also create user-defined vertex maps in Modeler. The method used is nearly identical to the method for creating a new vertex map from a pre-defined type. To generate a custom vertex map, you must provide a custom map type instead of a pre-defined type identifier. Custom map types are a unique four-character sequence, housed in an initialization block.

For example, to generate a vertex map of type NMBK, named my_normals, with two data elements per point, you use the following code:

@define VMAP_NMBK @'N','M','B','K'@

normMap = VMap(VMAP_NMBK,"my_normals",2);

Be aware that custom vertex maps will not appear anywhere in the application's interface. Because the types are not known to the application, no allocation is made for them. They will, however, be stored into the object file when it is saved, and will continue to be transported within the object file.

The VMap() constructor will return 'nil' if it fails to generate the new vertex map, regardless of its mode (custom or pre-defined).

The LScript VMap Object Agent constructor was lacking any mechanism for directly accessing custom VMaps defined in an object.  This has been rectified by allowing custom type identities to be used when referencing a VMap either by index:

        @define VMAP_PVOT  @'P','V','O','T'@
        ...
        map = VMap(VMAP_PVOT,1);

  or by type:

        map = VMap(VMAP_PVOT);

  In addition, a Vertex Map (pre-defined or custom) can now be referenced by both
  its type and its name:

        map = VMap(VMAP_PVOT,"theMap");

  or just by name:

        map = VMap("theMap")

The currently selected Weight, Texture or Morph vertex map can now be acquired in Modeler by providing an index value of zero (0) to the VMap() constructor when specifying one of the three vertex map types:

vmap = VMap(VMWEIGHT,0) || error("Select a Weight map so I have something to do!");

Data Members

name
name is the name of the Vertex Map associated with the Object Agent.

dimensions
dimensions represent the number of values associated with each vertex in the map. This value can be zero (0).

type
type is the type of the Vertex Map associated with the Object Agent. It will be one of the constant values defined above (VMSELECT, VMWEIGHT, etc.).

Methods

count()
count() returns the total number of Vertex Maps of the Object Agent type found in the current environment.

isMapped(<point>[,<polygon])
isMapped(<point>) reports whether or not the specified point identifier exists in the map. The return value is true or false.isMapped() now accepts an optional second argument which should be the polygon for which the discontinuous UV values for the indicated point should be checked.

getValue(<point>[,<polygon>[,<index>]])
getValue(<point>[,<index>]) returns the value(s) associated with the specified point identifier in the Vertex Map. If a specific value index is not provided, the count of items returned will be equal to the value contained in the 'dimensions' data member. If the point does not exist in the Vertex Map, or the dimensions of the Vertex Map are zero (0), then 'nil' is returned (use isMapped() and/or the 'dimensions' data member to avoid these situations).getValue() processes a second argument that indicates the polygon for
which discontinuous UV values should be retrieved.  an <index> value can also be specified to limit the retrieval to a specific value index.

setValue(<point>,<value>|<array>[,<polygon[,<index>]]) (MODELER ONLY)
setValue(<point>,<value>|<array>[,<index>]) sets the value(s) of a specified point identifier in the Vertex Map. If an individual value is provided, then that value is placed into the first value slot for the point. A <polygon> can now be included in the setValue() argument list to allow values to be assigned to a polygon's per-vertex (discontinuous) UV. An optional index value will position the individual value into that value slot for the point.

An array of values can also be provided as the values for the point identifier. If no optional index is included, then each element in the array will be placed into the corresponding value slot for the point identifier in the Vertex Map. If an index is provided, then elements in the array will begin populating the values for the point identifier at the indicated index offset.

Modification of a Vertex Map using the setValue() method is considered mesh editing, and can only be performed within Modeler LScript. Consequently, this method does not exist in Object Agents generated from Layout LScripts. Further, you must be within an initiated Mesh Data Edit session before you can successfully invoke this method.

Examples:

The following is an example Modeler LScript that allows the user to select an existing Weight VMap, and will then apply a scaling factor uniformly to each of its values:

@version 2.1
@warnings

main
{
    vmap = VMap(VMWEIGHT) || error("No weight maps in mesh!");
    while(vmap && vmap.type == VMWEIGHT)
    {
         vmapnames += vmap.name;
         vmap = vmap.next();
    }
    reqbegin("Scale Weight VMap",true);
         c1 = ctlpopup("VMap",1,vmapnames);
         c2 = ctlnumber("Scale by (%)",50.0);
         return if !reqpost();

         vndx = getvalue(c1);
         amount = getvalue(c2) / 100.0;
    reqend();

     vmap = VMap(vmapnames[vndx]) || error("Could not instance
VMap '",vmapnames[vndx],"'!");

     selmode(USER);
    moninit(editbegin());

     foreach(p,points)
    {
         if(vmap.isMapped(p))
         {
              values = vmap.getValue(p);
              for(x = 1;x <= vmap.dimensions;x++)
                  values[x] *= amount;
              vmap.setValue(p,values);
         }
         monstep();
    }
    monend();
    editend();
}