home *** CD-ROM | disk | FTP | other *** search
/ Freelog Special Freeware 25 / FreelogHS25.iso / Dessin / ArtOfIllusion2.2.1 / Scripts / Objects / Fur.bsh < prev    next >
Text File  |  2005-06-11  |  6KB  |  200 lines

  1. /*
  2. <?xml version='1.0' standalone='yes' ?>
  3. <!-- xml header for scripts & plugin manager --> 
  4. <script>
  5.     <name>Fur</name>
  6.     <author>Peter Eastman (peastman@users.sourceforge.net)</author>
  7.     <version>1.7</version>
  8.     <date>04/03/2004</date>
  9.     <description>
  10. This script creates short fur over the surface of an object. It does this by creating a series
  11. of concentric "shells" around the object, each one mapped with a semi-transparent texture to
  12. simulate the appearance of fur. The fur texture (available in a separate file which accompanies
  13. this script) must have already been imported into the scene. 
  14.  
  15. Before creating an object with this script, you must first apply the fur texture to the "base"
  16. object you want to create fur on. This is for three purposes: 
  17.  
  18. 1. So that you can set up how the fur is mapped to the object. After adjusting the scale of the
  19. texture (a value of 0.02 for the x, y, and z scales is a good starting point), enable the
  20. "Bind Texture Coordinates to Surface" option. Otherwise, this script will not work correctly. 
  21.  
  22. 2. So that you can set the value of the "length" texture parameter, which determines the length
  23. of the fur. It may be set per-object or per-vertex, allowing the length to vary over the surface
  24. of the object. 
  25.  
  26. 3. So that you can set the value of the "thickness" texture parameter, which determines the
  27. thickness of each hair. This, too, may be set per-object or per-vertex. 
  28.  
  29. If you modify the fur texture and add other parameters to it, their values will also be preserved
  30. on the shells of fur. For example, you could use a parameter to vary the color of the fur over
  31. the surface of the object. 
  32.  
  33. It is not necessary that the fur texture actually be visible on the "base" object, only that it
  34. be present so the mapping and texture parameters can be defined. For example, you can use a layered
  35. texture for the base object, with fur as the bottom layer and another opaque texture on top of
  36. it. The base object can even be hidden. For example, if you want fur over only part of an object,
  37. you could duplicate it, trim away the portions of the duplicate where you do not want fur, hide the
  38. trimmed object, and use it as the fur generator.
  39.     </description>
  40.     <comments>
  41.     Uses the texture file Fur.aoi, located in AoIFolder/Scripts/Objects next to the script.
  42.     </comments>
  43.     <fileset>
  44.         <file>Fur.aoi</file>
  45.     </fileset>
  46. </script>
  47. */
  48.  
  49. if (script.isPreview())
  50.   return;
  51. scene = script.getScene();
  52.  
  53. // The following line gets the object (which must be a triangle mesh or spine mesh) to add fur to.
  54.  
  55. info = scene.getObject("furry");
  56.  
  57. // The following line gets the fur texture.
  58.  
  59. fur = scene.getTexture("fur");
  60.  
  61. // This sets the number of shells to use.  More shells will give better looking fur, but also take
  62. // more time and memory to render.  When rendering, be sure to set the maximum ray tree depth (in
  63. // the advanced raFur.bshytracer options window) to be greater than the number of shells.  Otherwise, the
  64. // raytracer will not get through all of the shells.
  65.  
  66. shells = 10;
  67.  
  68. // This is a force which pulls on the hair, usually downward.  It can also be animated to simulate
  69. // wind or similar effects.
  70.  
  71. gravity = new Vec3(0.0, -0.4, 0.0);
  72. script.getCoordinates().toLocal().transformDirection(gravity);
  73.  
  74. // Everything from here on you should not need to modify, unless you are making significant changes
  75. // to the way the script works.
  76.  
  77. // Check various inputs to make sure they're ok.
  78.  
  79. if (info == null)
  80. {
  81.   print("Could not find object to apply fur to");
  82.   return;
  83. }
  84. if (fur == null)
  85. {
  86.   print("Could not find fur texture");
  87.   return;
  88. }
  89.  
  90. // Find the mapping used for the fur texture.
  91.  
  92. map = null;
  93. obj = info.getDistortedObject(0.1);
  94. if (obj instanceof artofillusion.animation.Actor)
  95.   obj = obj.getObject();
  96. if (!(obj instanceof Mesh))
  97. {
  98.   print("Fur can only be applied to a mesh");
  99.   return;
  100. }
  101. if (obj.getTexture() == fur)
  102.   map = obj.getTextureMapping();
  103. else if (obj.getTextureMapping() instanceof LayeredMapping)
  104. {
  105.   layered = obj.getTextureMapping();
  106.   for (i = 0; i < layered.getNumLayers(); i++)
  107.     if (layered.getLayer(i) == fur)
  108.     {
  109.       map = layered.getLayerMapping(i);
  110.       break;
  111.     }
  112. }
  113. if (map == null)
  114. {
  115.   print("The fur texture has not been assigned to the object.");
  116.   return;
  117. }
  118.  
  119. // This function finds the texture parameter with a given name.
  120.  
  121. findParam(String name)
  122. {
  123.   params = obj.getParameters();
  124.   for (i = 0; i < params.length; i++)
  125.     if (params[i].owner == fur && params[i].name.equals(name))
  126.       return params[i];
  127.   return null;
  128. }
  129.  
  130. // This function finds the value of a texture parameter at each vertex.
  131.  
  132. findParamValues(String name)
  133. {
  134.   param = findParam(name);
  135.   if (param == null)
  136.     return param;
  137.   value = obj.getParameterValue(param);
  138.   if (value instanceof VertexParameterValue)
  139.     return value.getValue();
  140.   avg = value.getAverageValue();
  141.   vertValue = new double [obj.getVertices().length];
  142.   for (int j = 0; j < vertValue.length; j++)
  143.     vertValue[j] = avg;
  144.   return vertValue;
  145. }
  146.  
  147. // Look up the values of the thickness and length parameters.
  148.  
  149. thicknessParam = findParam("thickness");
  150. if (thicknessParam == null)
  151. {
  152.   print("Could not find texture parameter 'thickness'");
  153.   return;
  154. }
  155. furThickness = obj.getParameterValue(thicknessParam);
  156. furLength = findParamValues("length");
  157. if (furLength == null)
  158. {
  159.   print("Could not find texture parameter 'length'");
  160.   return;
  161. }
  162.  
  163. // This is the main loop that generates the shells.
  164.  
  165. heightScale = 1.0/shells;
  166. for (i = 0; i < shells; i++)
  167. {
  168.   newobj = obj.duplicate();
  169.   norm = newobj.getNormals();
  170.   vert = newobj.getVertices();
  171.   for (j = 0; j < vert.length; j++)
  172.   {
  173.     disp = norm[j].plus(gravity);
  174.     disp.normalize();
  175.     disp.scale(furLength[j]*heightScale);
  176.     vert[j].r.add(disp);
  177.   }
  178.   newobj.setTexture(fur, map.duplicate());
  179.   
  180.   // Taper the ends of the hairs.
  181.   
  182.   if (i > shells*0.75)
  183.   {
  184.     thicknessScale = 4.0*(shells-i)/shells;
  185.     if (furThickness instanceof VertexParameterValue || furThickens instanceof FaceParameterValue)
  186.     {
  187.       newThickness = furThickness.duplicate();
  188.       val = newThickness.getValue();
  189.       for (j = 0; j < val.length; j++)
  190.         val[j] *= thicknessScale;
  191.       newThickness.setValue(val);
  192.       newobj.setParameterValue(thicknessParam, newThickness);
  193.     }
  194.     else
  195.       newobj.setParameterValue(thicknessParam, new ConstantParameterValue(thicknessScale*furThickness.getAverageValue()));
  196.   }
  197.   script.addObject(newobj, info.coords.duplicate());
  198.   obj = newobj;
  199. }
  200.