imrShaderTranslation.h

Go to the documentation of this file.
00001 /*==============================================================================
00002 
00003   file:     imrShaderTranslation.h
00004 
00005   author:   Daniel Levesque
00006 
00007   created:  10feb2003
00008 
00009   description:
00010 
00011     Defition of the mental ray shader translation interface.
00012 
00013   modified: 
00014 
00015     [dl] 28 April 2004. Added advanced translation of parameters, incremented
00016     interface IDs to distinguish between the old (MAX 6) interface and the new (MAX 7)
00017     interface.
00018 
00019 (c) 2004 Autodesk
00020 ==============================================================================*/
00021 #pragma once
00022 
00023 #include "..\maxheap.h"
00024 #include "..\strbasic.h"
00025 #include "..\baseinterface.h"
00026 #include "..\ifnpub.h"
00027 #include "..\plugapi.h" // for classdesc
00028 #include "imrAdvancedTranslation.h"
00029 
00030 // forward declarations
00031 class imrShader;
00032 class imrShaderCreation;
00033 class Texmap;
00034 class imrMaterialCustAttrib;
00035 class ReferenceTarget;
00036 class Point3;
00037 
00038 #define IMRSHADERTRANSLATION_INTERFACE_ID Interface_ID(0x1c396abd, 0x5f964e0c)
00039 #define IMRMTLPHENTRANSLATION_INTERFACE_ID Interface_ID(0x5f970a9c, 0x65e75de4)
00040 #define IMRGEOMSHADERTRANSLATION_INTERFACE_ID Interface_ID(0x31882a12, 0x2102a73)
00041 #define IMRSHADERTRANSLATION_CLASSINFO_INTERFACE_ID Interface_ID(0x17a76fd6, 0x5ab32bcd)
00042 
00043 //==============================================================================
00044 // class imrShaderTranslation
00045 //
00046 // Interface to be implemented by the MAX plugin which translates to a mental
00047 // ray shader. Materials do not use this interface. Instead, they use the
00048 // imrMaterialTranslation interface.
00049 //
00050 // For example:
00051 //      A 3rd party implements a MAX texmap pluggin for a brick effect. By default,
00052 //  the mental ray translator does not support this texture and will be unable to
00053 //  render it. If the 3rd party has also implemented a mental ray shader for this
00054 //  effect, then this interface may be used to tell the mental ray translator 
00055 //  which shader is to be used.
00056 //==============================================================================
00057 class imrShaderTranslation : public BaseInterface {
00058 
00059 public:
00060 
00061     // List of requirements that may be queried on this translation interface
00062     enum Requirement {
00063         // This shader requires tangent basis vectors.
00064         // The tangent basis vectors will be translated for the object on which
00065         // this shader is used. 
00066         // Return true if the vectors are needed, false otherwise. 
00067         // The 't', and 'valid' parameters are not used.
00068         // The 'arg' variable is a pointer to an 'int', to which to map channel
00069         // to be used should be assigned.
00070         kReq_TangentBasisVectors = 0,
00071     };
00072 
00073     struct AdditionalDependency : public MaxHeapOperators {
00074 
00075         AdditionalDependency(ReferenceTarget* rt, bool assign = true) : refTarg(rt), assignAsChild(assign) {}
00076 
00077         // The reference target that is to be translated as a dependency
00078         ReferenceTarget* refTarg;
00079         // This should be true in all but exceptional cases where the translator
00080         // could run into potential problems with reference looping.
00081         bool assignAsChild;
00082     };
00083 
00084     typedef Tab<AdditionalDependency> AdditionalDependencyTable;
00085 
00086     // Called by the mental ray translator to get the mental ray shader which
00087     // is to be used. The method may return a shader which was already created,
00088     // or create a new one via the imrShaderCreation interface.
00089     // This method will never be called more than once per render.
00090     virtual imrShader* GetMRShader(imrShaderCreation& shaderCreation) = 0;
00091 
00092     // This may be called when rendering is finished to discard the mental ray shaders.
00093     // If the derived class holds a reference to the shader created by the call to GetMRShader(),
00094     // then it may release that reference in this call. This is not an obligation,
00095     // but it can free memory and/or resolve issues such as the "Make Unique"
00096     // button always being enabled in the material editor.
00097     virtual void ReleaseMRShader() = 0;
00098 
00099     // Should the translator automatically copy the parameters based on the param
00100     // block 2 system?
00101     // NOTE: The metnal ray translator will correctly handle automatic translation
00102     // of the parameters IF the 3rd party plugin's parameters all use the ParamBlock2
00103     // system AND if the names & types of the parameters match the shader definition
00104     // (names are not case sensitive).
00105     // If this returns 'true', then the automatic translation will take place
00106     // after the call to TranslateParameters().
00107     virtual bool NeedsAutomaticParamBlock2Translation() = 0;
00108 
00109     // Translates the parameters of this plugin to the mental ray shader. Called
00110     // for the first frame, and for each subsequent frame that is not in the
00111     // validity interval. The method must store the validity interval of the
00112     // translated parameters in 'valid'.
00113     // **The parameters must be stored in the shader at time 0.
00114     virtual void TranslateParameters(imrTranslation& translationInterface, imrShader* shader, TimeValue t, Interval& valid) = 0;
00115 
00116     // If this class needs any ReferenceTarget to be translated, but which are not
00117     // sub-references or within a parameter block of the plugin class, then these
00118     // ReferenceTarget's may be given here. The mental ray translator will automatically
00119     // create a dependency between the plugin and the given ReferenceTarget's.
00120     virtual void GetAdditionalReferenceDependencies(AdditionalDependencyTable& refTargets) = 0;
00121 
00122     // This method is meant for advanced users for whom TranslateParameters() either is not
00123     // sufficient or causes performance issues.
00124     // Whereas TranslateParameters() translates parameters using the ParamBlock2 system,
00125     // this method is used to send parameters directly to mental ray, bypassing the ParamBlock2 system.
00126     // If TranslateParameters() is enough for you, or if you do not understand why you would need
00127     // this advanced translation method, then do not implement this method.
00128     // See the documentation of class imrAdvancedTranslation for more details.
00129     virtual void TranslateParameters_Advanced(imrAdvancedTranslation& advancedTranslation, TimeValue t, Interval& valid);
00130 
00131     // This method is meant to query specific requirements from the translation interface.
00132     // Look at the documentation for each requirement flag for more information.
00133     // Note that 'arg' may or may not be used, depending on the requirement.
00134     virtual bool HasRequirement(Requirement requirement, TimeValue t, Interval& valid, void* arg = NULL);
00135 
00136     // -- from BaseInterface
00137     virtual Interface_ID GetID();
00138 };
00139 
00140 inline imrShaderTranslation* GetIMRShaderTranslation(InterfaceServer* iserver) {
00141 
00142     return static_cast<imrShaderTranslation*>(iserver->GetInterface(IMRSHADERTRANSLATION_INTERFACE_ID));
00143 }
00144 
00145 //==============================================================================
00146 // class imrMaterialPhenomenonTranslation
00147 //
00148 // A material plugin that wishes to have a custom translation to a material
00149 // phenomenon must derive from this interface. The interface is identical to 
00150 // imrShaderTranslation, except that:
00151 // - the interface ID is different
00152 // - only material phenomenon may be created via the imrShaderCreation interface.
00153 //
00154 // SPECIAL CASE: Using the mental ray material directly.
00155 // To translate a material to a mental ray material directly, without actually
00156 // using a phenomenon of your own, create an instance of the phenomenon called
00157 // "max_default_mtl_phen". Even though this is a phenomenon, it is not translated
00158 // as one, but instead it is translated as a material. NOTE, however, that this
00159 // particular phenomenon does NOT support the automatic ParamBlock2 translation,
00160 // so NeedsAutomaticParamBlock2Translation() should return false.
00161 //==============================================================================
00162 class imrMaterialPhenomenonTranslation : public imrShaderTranslation {
00163 
00164 public:
00165     
00166     // Returns whether this material supports the 'mental ray connection' custom
00167     // attributes rollup. This rollup allows users to override any of the 10 shaders
00168     // on the material. Note that only materials that translate to the default
00169     // material phenomenon ("max_default_mtl_phen") may return true here, since
00170     // the translator needs that phenomenon to translate the shader overrides.
00171     // If the material does not return the default material phenomenon but still
00172     // wishes to support the overrides, then it will have to do so itself.
00173     virtual bool SupportsMtlOverrides() = 0;
00174 
00175     // Initializes the mtl overrides custom attribute, if necessary. Only called
00176     // if SupportsMtlOverrides() returned true.
00177     // All that this function should do is enable/disable the shader locks of the custom
00178     // attribute.
00179     // A material may simply do nothing here, or it may disable some of the shader locks
00180     // that don't apply.
00181     virtual void InitializeMtlOverrides(imrMaterialCustAttrib* mtlCustAttrib) = 0;
00182 
00183     // -- from BaseInterface
00184     virtual Interface_ID GetID();
00185 };
00186 
00187 inline imrMaterialPhenomenonTranslation* GetIMRMaterialPhenomenonTranslation(InterfaceServer* iserver) {
00188 
00189     return static_cast<imrMaterialPhenomenonTranslation*>(iserver->GetInterface(IMRMTLPHENTRANSLATION_INTERFACE_ID));
00190 }
00191 
00192 //==============================================================================
00193 // class imrGeomShaderTranslation
00194 //
00195 // A geometry object plugin that wishes to have a custom translation to a mental
00196 // ray shader must derive from this interface. The interface is used to retrieve
00197 // an instance of the geometry shader to be used.
00198 // Derive your GeomObject or ShapeObject from this class to have it translated
00199 // to a geometry shader.
00200 //==============================================================================
00201 class imrGeomShaderTranslation : public BaseInterface {
00202 
00203 public:
00204 
00205     // Returns the geometry shader to be used with this object. The ReferenceTarget
00206     // returned by this method should be a Texmap plugin that translates to a mental
00207     // ray geometry shader. You may need to implement your own Texmap plugin that
00208     // uses the imrShaderTranslation interface to translate itself to a mental ray
00209     // shader.
00210     virtual ReferenceTarget* GetGeomShader() = 0;
00211 
00212     // Returns a scale for the geometry shader, to be applied on the instance transform.
00213     // This is useful in the case that a geometry shader produces objects of a fixed
00214     // size (e.g. the mib_geo_* shaders), but you still want to be able to expose
00215     // a size parameter in the UI.
00216     // If you don't care about scaling, just return a scale of (1,1,1).
00217     virtual void GetScale(Point3& scale) = 0;
00218     
00219     // -- from BaseInterface
00220     virtual Interface_ID GetID();
00221 };
00222 
00223 inline imrGeomShaderTranslation* GetIMRGeomShaderTranslation(InterfaceServer* iserver) {
00224 
00225     return static_cast<imrGeomShaderTranslation*>(iserver->GetInterface(IMRGEOMSHADERTRANSLATION_INTERFACE_ID));
00226 }
00227 
00228 //==============================================================================
00229 // class imrShaderCreation
00230 //
00231 // Interface used to create new shader instances.
00232 //
00233 // A reference to this interface is passed to the "GetMRShader()" method of the
00234 // imrShaderTranslation interface. If one tries to create a shader which does
00235 // nto exist, CreateShader() outputs an error in the mental ray message window
00236 // and returns NULL.
00237 //
00238 // IMPORTANT: If the implementation of this interface holds a pointer to
00239 // a shader, to avoid re-creating it every time, then it MUST make a reference
00240 // to that shader. Otherwise, the shader will be deleted when the render ends.
00241 //==============================================================================
00242 class imrShaderCreation: public MaxHeapOperators {
00243 
00244 public:
00245 
00246     // Creates an instance of a shader with the given name. The name must be as it
00247     // appears in the .mi declaration.
00248     // This method may return NULL if the shader is not found, and the caller
00249     // should check for NULL values.
00250     virtual imrShader* CreateShader(
00251         const MCHAR* declarationName,
00252         const MCHAR* mtlName        // The material's name is used when reporting errors. 
00253                                     // (Tip: Pass the result of MtlBase::GetFullName())
00254                                     // Passing NULL suppresses error messages.
00255     ) = 0;
00256 };
00257 
00258 //==============================================================================
00259 // class imrShaderTranslation_ClassInfo
00260 //
00261 // IMPLEMENTATION INSTRUCTIONS:
00262 //
00263 //   To be subclassed by a ClassDesc or ClassDesc2 of a Texmap plugin.
00264 //   The subclass HAS TO call Init(*this) from its constructor.
00265 //
00266 // DESCRIPTION:
00267 //
00268 // This class is used to provide additional 'ApplyType' information for texmaps
00269 // that translate to a custom shaders.
00270 //
00271 // All mental ray shaders have an 'apply' type. This type classifies shaders into
00272 // different categories (e.g. texture shader, light shader, environment shader, etc.).
00273 // The apply type restricts where and how a shader may be used. By default, if
00274 // this interface is not implemented, a Texmap plugin will have the 
00275 // imrShaderClassDesc::kApplyFlag_Default apply type. If this is incorrect, then
00276 // this interface should be implemented - otherwise it may be impossible to use
00277 // the shader and crashes could occur if the shader is not used correctly.
00278 //==============================================================================
00279 class imrShaderTranslation_ClassInfo : public FPStaticInterface {
00280 
00281 public:
00282 
00283     // Initialization method. MUST be called from the constructor of the subclass. i.e. "Init(*this);".
00284     void Init(
00285         ClassDesc& classDesc
00286     );
00287 
00288     // Get the types to which this shader may be applied (combination of 
00289     // imrShaderClassDesc::ApplyFlags values).
00290     virtual unsigned int GetApplyTypes() = 0;
00291 };
00292 
00293 //==============================================================================
00294 // class imrShaderTranslation_ClassInfo inlined methods
00295 //==============================================================================
00296 
00297 // Given the class descriptor of a Mtl/Texmap plugin, this returns its compatibility interface (if it exists).
00298 inline imrShaderTranslation_ClassInfo* Get_imrShaderTranslation_ClassInfo(ClassDesc& mtlBaseClassDesc) {
00299 
00300     return static_cast<imrShaderTranslation_ClassInfo*>(mtlBaseClassDesc.GetInterface(IMRSHADERTRANSLATION_CLASSINFO_INTERFACE_ID));
00301 }
00302 
00303 //==============================================================================
00304 // class imrShaderTranslation inlined methods
00305 //==============================================================================
00306 
00307 inline Interface_ID imrShaderTranslation::GetID() {
00308 
00309     return IMRSHADERTRANSLATION_INTERFACE_ID;
00310 }
00311 #pragma warning(push)
00312 #pragma warning(disable:4100)
00313 inline void imrShaderTranslation::TranslateParameters_Advanced(imrAdvancedTranslation& advancedTranslation, TimeValue t, Interval& valid) {
00314 
00315     // Default implementation does nothing
00316 }
00317 
00318 inline bool imrShaderTranslation::HasRequirement(Requirement, TimeValue t, Interval& valid, void* arg) {
00319 
00320     // Default implementation has no requirements
00321     return 0;
00322 }
00323 #pragma warning(pop)
00324 //==============================================================================
00325 // class imrMaterialPhenomenonTranslation inlined methods
00326 //==============================================================================
00327 
00328 inline Interface_ID imrMaterialPhenomenonTranslation::GetID() {
00329 
00330     return IMRMTLPHENTRANSLATION_INTERFACE_ID;
00331 }
00332 
00333 //==============================================================================
00334 // class imrGeomShaderTranslation inlined methods
00335 //==============================================================================
00336 
00337 inline Interface_ID imrGeomShaderTranslation::GetID() {
00338 
00339     return IMRGEOMSHADERTRANSLATION_INTERFACE_ID;
00340 }
00341 
00342 //==============================================================================
00343 // class imrShaderTranslation_ClassInfo inlined methods
00344 //==============================================================================
00345 
00346 inline void imrShaderTranslation_ClassInfo::Init(ClassDesc& classDesc) {
00347 
00348     LoadDescriptor(IMRSHADERTRANSLATION_CLASSINFO_INTERFACE_ID, _M("imrShaderTranslation_ClassInfo"), 0, &classDesc, 0, end);
00349 }
00350