Difference between revisions of "Texture test"

From The Foundry MODO SDK wiki
Jump to: navigation, search
(Implementations)
 
(4 intermediate revisions by one other user not shown)
Line 6: Line 6:
  
 
===Class declaration===
 
===Class declaration===
 +
 +
We want to create a custom value texture, so we inherit from CLxImpl_ValueTexture, which has all the methods for creating a value texture. We then redeclare most of the methods in the CLxImpl_ValueTexture class(they are the ones with the vtx prefixes) and customize the functions to our specifications. The first three functions set up and access the channels we want to use for our texture. The Evaluate function then evaluates the color of the function using the values of the channels that we have accessed. Finally, the cleanup function releases the cached state after the evaluate function is finished rendering.
 +
 +
We also want to customize and create a ui for our channels, so we inherit from CLxImpl_ChannelUI. We then redeclare three of the functions contained in CLxImpl_ChannelUI. They cui_Enabled function indicates that we turn on the channel ui. The DependencyCount and DependencyByIndex functions list the channels that affect a given target channel.
  
 
This has the basic ValueTexture interface to support simple multi-effect evaluations, plus the ChannelUI interface for enable states. The local RendData struct is used for storing values used for a specific texture evaluation.
 
This has the basic ValueTexture interface to support simple multi-effect evaluations, plus the ChannelUI interface for enable states. The local RendData struct is used for storing values used for a specific texture evaluation.
  
 +
<syntaxhighlight>
 
  class CTestTexture :
 
  class CTestTexture :
 
                 public CLxImpl_ValueTexture,
 
                 public CLxImpl_ValueTexture,
Line 40: Line 45:
 
         };
 
         };
 
  };
 
  };
 +
</syntaxhighlight>
  
 
===[[Server_Tags|Server Tags]]===
 
===[[Server_Tags|Server Tags]]===
Line 47: Line 53:
 
The tags here indicate that server has the name Test Value Texture with the internal name of val-texture.
 
The tags here indicate that server has the name Test Value Texture with the internal name of val-texture.
  
 +
<syntaxhighlight>
 
  LXtTagInfoDesc CTestTexture::descInfo[] = {
 
  LXtTagInfoDesc CTestTexture::descInfo[] = {
 
         { LXsSRV_USERNAME, "Test Value Texture" },
 
         { LXsSRV_USERNAME, "Test Value Texture" },
Line 52: Line 59:
 
         { 0 }
 
         { 0 }
 
  };
 
  };
 +
</syntaxhighlight>
  
 
===[[Initialize_(index)|Initialize]]===
 
===[[Initialize_(index)|Initialize]]===
Line 59: Line 67:
 
This function exports a server of the TEXTURE type dependent on the CTestTexture class with the ValueTexture, ChannelUI, and StaticDesc interfaces.
 
This function exports a server of the TEXTURE type dependent on the CTestTexture class with the ValueTexture, ChannelUI, and StaticDesc interfaces.
  
 +
<syntaxhighlight>
 
  void
 
  void
 
  Initialize()
 
  Initialize()
Line 69: Line 78:
 
         srv->AddInterface (new CLxIfc_StaticDesc  <CTestTexture>);
 
         srv->AddInterface (new CLxIfc_StaticDesc  <CTestTexture>);
 
         lx::AddServer (SRVs_TEXTURE, srv);
 
         lx::AddServer (SRVs_TEXTURE, srv);
  }
+
  }</syntaxhighlight>
  
 
===Helper Functions===
 
===Helper Functions===
  
Utilities for RGB/HSV conversion.
+
Utilities for RGB/HSV conversion. The second utility is used in the vtx_evaluate function.  
  
 +
<syntaxhighlight>
 
  #define MIN(a,b) ((a) < (b) ? (a) : (b))
 
  #define MIN(a,b) ((a) < (b) ? (a) : (b))
 
  #define MAX(a,b) ((a) < (b) ? (b) : (a))
 
  #define MAX(a,b) ((a) < (b) ? (b) : (a))
Line 92: Line 102:
 
         LXtFVector hsv)
 
         LXtFVector hsv)
 
  {
 
  {
         double min, max, delta;
+
         ...
+
        min = MIN (MIN (_R, _G), _B);
+
        max = MAX (MAX (_R, _G), _B);
+
        delta = max - min;
+
+
        _V = max;
+
        if (max)
+
                _S = delta / max;
+
        else {
+
                _S = 0.0;
+
                _H = 0.0; // black: hue undefined
+
                return;
+
        }
+
+
        if (delta) {
+
                if (_R == max)
+
                        _H = (_G - _B) / delta; // between yellow & magenta
+
                else if (_G == max)
+
                        _H = (_B - _R) / delta + 2.0; // between cyan & yellow
+
                else
+
                        _H = (_R - _G) / delta + 4.0; // between magenta & cyan
+
        }
+
        else
+
                _H = 0;
+
+
        _H *= (float) (PI / 3.0);
+
        if (_H < 0)
+
                _H += (float) TWOPI;
+
 
  }
 
  }
 
   
 
   
Line 128: Line 110:
 
         LXtFVector rgb)
 
         LXtFVector rgb)
 
  {
 
  {
        double f, p, q, t;
+
    ...
        int i;
+
+
        if (_S < DBL_EPSILON) {
+
                _R = _G = _B = _V; // grey
+
                return;
+
        }
+
+
        f = _H * 3.0 / PI;
+
        while (f < 0.0)
+
                f += 6.0;
+
        while (f >= 6.0)
+
                f -= 6.0;
+
+
        i = floor (f); // sector 0 to 5
+
        f = f - i; // factorial part of Hue
+
        p = _V * (1.0 - _S);
+
        q = _V * (1.0 - _S *        f);
+
        t = _V * (1.0 - _S * (1.0 - f));
+
+
        switch (i) {
+
            case 0:
+
                _R = _V;
+
                _G =  t;
+
                _B =  p;
+
                break;
+
+
            case 1:
+
                _R =  q;
+
                _G = _V;
+
                _B =  p;
+
                break;
+
+
            case 2:
+
                _R =  p;
+
                _G = _V;
+
                _B =  t;
+
                break;
+
+
            case 3:
+
                _R =  p;
+
                _G =  q;
+
                _B = _V;
+
                break;
+
+
            case 4:
+
                _R =  t;
+
                _G =  p;
+
                _B = _V;
+
                break;
+
+
            default:
+
                _R = _V;
+
                _G =  p;
+
                _B =  q;
+
                break;
+
        }
+
 
  }
 
  }
 +
</syntaxhighlight>
  
 
===Implementations===
 
===Implementations===
Line 191: Line 118:
 
This function creates the channels for the item type using the methods of an [[Package_(lx-package.hpp)#.2815.29_SDK:_ILxAddChannel_interface method|AddChannel]] object.
 
This function creates the channels for the item type using the methods of an [[Package_(lx-package.hpp)#.2815.29_SDK:_ILxAddChannel_interface method|AddChannel]] object.
  
 +
<syntaxhighlight>
 
  LxResult
 
  LxResult
 
  CTestTexture::vtx_SetupChannels (
 
  CTestTexture::vtx_SetupChannels (
Line 196: Line 124:
 
  {
 
  {
 
       ...
 
       ...
  }
+
  }</syntaxhighlight>
  
 
This function attaches the channels to channel evaluation. This gets indices for the channels in attributes through the AddChan method of a [[Action_(lx-action.hpp)#.2822.29_User_Class:_Evaluation_method|User Evaluation]] object.
 
This function attaches the channels to channel evaluation. This gets indices for the channels in attributes through the AddChan method of a [[Action_(lx-action.hpp)#.2822.29_User_Class:_Evaluation_method|User Evaluation]] object.
  
 +
<syntaxhighlight>
 
  LxResult
 
  LxResult
 
  CTestTexture::vtx_LinkChannels (
 
  CTestTexture::vtx_LinkChannels (
Line 206: Line 135:
 
  {
 
  {
 
         ...
 
         ...
  }
+
  }</syntaxhighlight>
  
 
This function reads channel values which may have changed. These are stored in the allocated data for later evaluation.
 
This function reads channel values which may have changed. These are stored in the allocated data for later evaluation.
  
 +
<syntaxhighlight>
 
         LxResult
 
         LxResult
 
  CTestTexture::vtx_ReadChannels (
 
  CTestTexture::vtx_ReadChannels (
Line 216: Line 146:
 
  {
 
  {
 
       ...
 
       ...
  }
+
  }</syntaxhighlight>
  
Evaluate the color at a spot using cached values.
+
Evaluate the value and\or color at the current shading spot using cached values. This is the core of the texture value plugin, the place where actual values are computed and passed down to the texture engine. The role of the texture plugin is to set tOut->value, this value is then applied as a texture effect.  
  
 +
For example if the texture effect is 'displacement', the value will be transformed into a displacement distance by multiplying the value by the displacement amplitude. This is not the job of texture value plugin however, all the texture needs to do is provide the value (between 0 and 1).
 +
 +
For color effects, the texture can either set the color indirectly by setting a value that interpolates the 2 base colors, or directly by setting the color (tOut->color[0]) and setting tOut->direct to 1. Most procedural textures use the first method: they compute a value and that interpolates 2 base colors (tOut->color[0], tOut->color[1]), but other textures such as image maps set the color directly because the result of their computation is a color.
 +
 +
<syntaxhighlight>
 
  void
 
  void
 
  CTestTexture::vtx_Evaluate (
 
  CTestTexture::vtx_Evaluate (
Line 227: Line 162:
 
  {
 
  {
 
         ...
 
         ...
  }
+
  }</syntaxhighlight>
  
 
Release the cached state after rendering is complete using the RendData class defined in our CTestTexture class.
 
Release the cached state after rendering is complete using the RendData class defined in our CTestTexture class.
  
 +
<syntaxhighlight>
 
  void
 
  void
 
  CTestTexture::vtx_Cleanup (
 
  CTestTexture::vtx_Cleanup (
Line 236: Line 172:
 
  {
 
  {
 
         ...
 
         ...
  }
+
  }</syntaxhighlight>
  
 
Release the cached state after rendering is complete using the [[LXa_SCENESERVICE_(index)#Item_Types|SceneService]] object.
 
Release the cached state after rendering is complete using the [[LXa_SCENESERVICE_(index)#Item_Types|SceneService]] object.
  
 +
<syntaxhighlight>
 
         LXtItemType
 
         LXtItemType
 
  CTestTexture::MyType ()
 
  CTestTexture::MyType ()
 
  {
 
  {
 
         ...
 
         ...
  }
+
  }</syntaxhighlight>
  
 
Utility to get the type code for this item type, as needed.
 
Utility to get the type code for this item type, as needed.
  
 +
<syntaxhighlight>
 
  LXtItemType
 
  LXtItemType
 
  CTestTexture::MyType ()
 
  CTestTexture::MyType ()
 
  {
 
  {
 
       ...
 
       ...
  }
+
  }</syntaxhighlight>
  
 
Test if a given channel is enabled. We're going to disable the saturation channel if both the high and low are set to zero. I'm using common message 99, which just repeats its string argument, but normally this would be defined in a dedicated message table.
 
Test if a given channel is enabled. We're going to disable the saturation channel if both the high and low are set to zero. I'm using common message 99, which just repeats its string argument, but normally this would be defined in a dedicated message table.
  
 +
<syntaxhighlight>
 
  LxResult
 
  LxResult
 
  CTestTexture::cui_Enabled (
 
  CTestTexture::cui_Enabled (
Line 265: Line 204:
 
         ...
 
         ...
 
  }
 
  }
 +
</syntaxhighlight>
  
 
Dependency count/byIndex list the channels that affect a given target channel. In our case the saturation channel is affected by changes to the low and high channels of this same item type.
 
Dependency count/byIndex list the channels that affect a given target channel. In our case the saturation channel is affected by changes to the low and high channels of this same item type.
  
 +
<syntaxhighlight>
 
  LxResult
 
  LxResult
 
  CTestTexture::cui_DependencyCount (
 
  CTestTexture::cui_DependencyCount (
Line 284: Line 225:
 
  {
 
  {
 
       ...
 
       ...
  }
+
  }</syntaxhighlight>
 +
 
 +
[[Category: SDK Examples]]

Latest revision as of 10:09, 28 June 2014

Texture_test is a basic example plugin. This wiki page is intended as a walkthrough of the code in order to help you better understand the SDK.

This plugin is a test of plugin value textures, essentially a type of procedural.

Code Walkthrough

Class declaration

We want to create a custom value texture, so we inherit from CLxImpl_ValueTexture, which has all the methods for creating a value texture. We then redeclare most of the methods in the CLxImpl_ValueTexture class(they are the ones with the vtx prefixes) and customize the functions to our specifications. The first three functions set up and access the channels we want to use for our texture. The Evaluate function then evaluates the color of the function using the values of the channels that we have accessed. Finally, the cleanup function releases the cached state after the evaluate function is finished rendering.

We also want to customize and create a ui for our channels, so we inherit from CLxImpl_ChannelUI. We then redeclare three of the functions contained in CLxImpl_ChannelUI. They cui_Enabled function indicates that we turn on the channel ui. The DependencyCount and DependencyByIndex functions list the channels that affect a given target channel.

This has the basic ValueTexture interface to support simple multi-effect evaluations, plus the ChannelUI interface for enable states. The local RendData struct is used for storing values used for a specific texture evaluation.

 class CTestTexture :
                public CLxImpl_ValueTexture,
                public CLxImpl_ChannelUI
 {
    public:
        static LXtTagInfoDesc		 descInfo[];
 
        CTestTexture ();
 
        LxResult		vtx_SetupChannels (ILxUnknownID addChan);
        LxResult		vtx_LinkChannels  (ILxUnknownID eval, ILxUnknownID item);
        LxResult		vtx_ReadChannels  (ILxUnknownID attr, void **ppvData);
        void			vtx_Evaluate      (ILxUnknownID vector, LXpTextureOutput *tOut, void *data);
        void			vtx_Cleanup       (void *data);
 
        LxResult		cui_Enabled           (const char *channelName, ILxUnknownID msg, ILxUnknownID item, ILxUnknownID read);
        LxResult		cui_DependencyCount   (const char *channelName, unsigned *count);
        LxResult		cui_DependencyByIndex (const char *channelName, unsigned index, LXtItemType *depItemType, const char **depChannelName);
 
        LXtItemType		MyType ();
 
        CLxUser_PacketService	pkt_service;
        unsigned		idx_sat, idx_lo, idx_hi;
        unsigned		tin_offset;
        LXtItemType		my_type;
 
        class RendData {
            public:
                float		f_sat, f_base, f_mult;
        };
 };

Server Tags

Servers tags are examined when the server is initialized, and give information about the server. We set the tags in this case by taking descinfo[] arrays and associating the relevant data with the corresponding flags.

The tags here indicate that server has the name Test Value Texture with the internal name of val-texture.

 LXtTagInfoDesc	 CTestTexture::descInfo[] = {
        { LXsSRV_USERNAME,	"Test Value Texture" },
        { LXsSRV_LOGSUBSYSTEM,	"val-texture"	},
        { 0 }
 };

Initialize

Servers are extensible set of features that we add to modo, usually through plugins. Intialize is called when we add the plugin to modo, and is the utility that exports the server.

This function exports a server of the TEXTURE type dependent on the CTestTexture class with the ValueTexture, ChannelUI, and StaticDesc interfaces.

 void
 Initialize()
 {
        CLxGenericPolymorph		*srv;
 
        srv = new CLxPolymorph<CTestTexture>;
        srv->AddInterface (new CLxIfc_ValueTexture<CTestTexture>);
        srv->AddInterface (new CLxIfc_ChannelUI   <CTestTexture>);
        srv->AddInterface (new CLxIfc_StaticDesc  <CTestTexture>);
        lx::AddServer (SRVs_TEXTURE, srv);
 }

Helper Functions

Utilities for RGB/HSV conversion. The second utility is used in the vtx_evaluate function.

 #define MIN(a,b)	((a) < (b) ? (a) : (b))
 #define MAX(a,b)	((a) < (b) ? (b) : (a))
 #define PI		3.14159265
 #define TWOPI		(2 * PI)
 
 #define _R		rgb[0]
 #define _G		rgb[1]
 #define _B		rgb[2]
 #define _H		hsv[0]
 #define _S		hsv[1]
 #define _V		hsv[2]
 
        static void
 RGB2HSV (
        const LXtFVector	 rgb,
        LXtFVector		 hsv)
 {
        ...
 }
 
        static void
 HSV2RGB (
        const LXtFVector	 hsv,
        LXtFVector		 rgb)
 {
    ...
 }

Implementations

This function creates the channels for the item type using the methods of an AddChannel object.

 LxResult
 CTestTexture::vtx_SetupChannels (
        ILxUnknownID		 addChan)
 {
       ...
 }

This function attaches the channels to channel evaluation. This gets indices for the channels in attributes through the AddChan method of a User Evaluation object.

 LxResult
 CTestTexture::vtx_LinkChannels (
        ILxUnknownID		 eval,
        ILxUnknownID		 item)
 {
        ...
 }

This function reads channel values which may have changed. These are stored in the allocated data for later evaluation.

        LxResult
 CTestTexture::vtx_ReadChannels (
        ILxUnknownID		 attr,
        void		       **ppvData)
 {
       ...
 }

Evaluate the value and\or color at the current shading spot using cached values. This is the core of the texture value plugin, the place where actual values are computed and passed down to the texture engine. The role of the texture plugin is to set tOut->value, this value is then applied as a texture effect.

For example if the texture effect is 'displacement', the value will be transformed into a displacement distance by multiplying the value by the displacement amplitude. This is not the job of texture value plugin however, all the texture needs to do is provide the value (between 0 and 1).

For color effects, the texture can either set the color indirectly by setting a value that interpolates the 2 base colors, or directly by setting the color (tOut->color[0]) and setting tOut->direct to 1. Most procedural textures use the first method: they compute a value and that interpolates 2 base colors (tOut->color[0], tOut->color[1]), but other textures such as image maps set the color directly because the result of their computation is a color.

 void
 CTestTexture::vtx_Evaluate (
        ILxUnknownID		 vector,
        LXpTextureOutput	*tOut,
        void			*data)
 {
        ...
 }

Release the cached state after rendering is complete using the RendData class defined in our CTestTexture class.

 void
 CTestTexture::vtx_Cleanup (
         void			*data)
 {
        ...
 }

Release the cached state after rendering is complete using the SceneService object.

        LXtItemType
 CTestTexture::MyType ()
 {
        ...
 }

Utility to get the type code for this item type, as needed.

 LXtItemType
 CTestTexture::MyType ()
 {
       ...
 }

Test if a given channel is enabled. We're going to disable the saturation channel if both the high and low are set to zero. I'm using common message 99, which just repeats its string argument, but normally this would be defined in a dedicated message table.

 LxResult
 CTestTexture::cui_Enabled (
        const char		*channelName,
        ILxUnknownID		 msg,
        ILxUnknownID		 item,
        ILxUnknownID		 read)
 {
        ...
 }

Dependency count/byIndex list the channels that affect a given target channel. In our case the saturation channel is affected by changes to the low and high channels of this same item type.

 LxResult
 CTestTexture::cui_DependencyCount (
        const char		*channelName,
        unsigned		*count)
 {
       ...
 }
 
        LxResult
 CTestTexture::cui_DependencyByIndex (
        const char		*channelName,
        unsigned		 index,
        LXtItemType		*depItemType,
        const char	       **depChannelName)
 {
       ...
 }