1  /**********************************************************************
2  *<
3    FILE: matte.cpp
4 
5    DESCRIPTION:  A Matte material
6 
7    CREATED BY: Dan Silva
8 
9    HISTORY:  1/13/98 Updated to Param2 by Peter Watje
10 
11  *>   Copyright (c) 1994, All Rights Reserved.
12  **********************************************************************/
13 
14 #include "mtlhdr.h"
15 #include "mtlres.h"
16 #include "mtlresOverride.h"
17 #include "notify.h"
18 #include "iparamb2.h"
19 #include "iparamm2.h"
20 #include "stdmat.h" // standard texmap ids
21 #include "shaders.h" // HAS_MATTE_MTL
22 #include "buildver.h"
23 #include "toneop.h"
24 
25 #include "3dsmaxport.h"
26 
27 #ifndef NO_MTL_MATTESHADOW
28 
29 extern HINSTANCE hInstance;
30 
31 static Class_ID matteClassID(MATTE_CLASS_ID,0);
32 
33 static TCHAR* shadowIllumOutStr = "shadowIllumOut";
34 
35 class Matte;
36 /*
37 class MatteDlg : public ParamDlg {
38    public:
39       HWND hwmedit;
40       IMtlParams *ip;
41       Matte *theMtl;
42       HWND hPanel;
43       BOOL valid;
44       BOOL isActive;
45       ISpinnerControl *iAmb;
46       ISpinnerControl *iReflAmt;
47       IColorSwatch *cs;
48       BOOL creating;
49       TexDADMgr dadMgr;
50       ICustButton *iReflBut;
51 
52       MatteDlg(HWND hwMtlEdit, IMtlParams *imp, Matte *m);
53       ~MatteDlg();
54 
55       void EnableAlpha(HWND hWnd);
56       INT_PTR WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
57       void Invalidate();
58       void UpdateSubTexNames();
59       void SetDepthRadios();
60       void UpdateMtlDisplay() { ip->MtlChanged();     }
61 
62       // methods inherited from ParamDlg:
63       void ReloadDialog();
64       Class_ID ClassID() {return matteClassID;}
65       BOOL KeyAtCurTime(int id);
66       void SetThing(ReferenceTarget *m);
67       ReferenceTarget* GetThing() { return (ReferenceTarget *)theMtl; }
68       void DeleteThis() { delete this;  }
69       void SetTime(TimeValue t) {Invalidate();}
70       void ActivateDlg(BOOL onOff) { cs->Activate(onOff); }
71       int FindSubTexFromHWND(HWND hw) {
72          return  (hw == iReflBut->GetHwnd())? 0: -1;
73          }
74    };
75 */
76 
77 #define PB_REF    0
78 #define REFLMAP_REF     1
79 
80 //#define PB_AMB  0
81 //#define PB_COL  1
82 //#define PB_REFLAMT 2
83 
84 
85 enum { matte_params, };  // pblock ID
86 // grad_params param IDs
87 enum
88 {
89    matte_opaque_alpha,
90    matte_apply_atmosphere, matte_atmosphere_depth,
91    matte_receive_shadows, matte_affect_alpha,
92    matte_shadow_brightness, matte_color,
93    matte_reflection_amount, matte_reflection_map,
94    matte_use_reflection_map, matte_additive_reflection
95 };
96 
97 
98 
99 static Color black(0,0,0);
100 static Color white(1,1,1);
101 
102 class Matte : public Mtl, public IReshading
103 {
104    public:
105 //    MatteDlg *dlg;
106       IParamBlock2 *pblock;   // ref #0
107       Texmap *reflmap;  // ref #1
108       IParamBlock *savepb;   // for saving pblock when saving Max R2 files
109       Interval ivalid;
110       ReshadeRequirements mReshadeRQ; // mjm - 06.02.00
111       float amblev,reflAmt;
112       Color col;
113       BOOL fogBG;
114       BOOL useReflMap;
115       BOOL shadowBG;
116       BOOL opaque;
117       BOOL shadowAlpha;
118       BOOL fogObjDepth;
119       BOOL additiveReflection;
120       int version;
121 
122       Matte(BOOL loading);
123       ~Matte();
NotifyChanged()124       void NotifyChanged() {NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);}
125       void SetAmbLev(float v, TimeValue t);
126       void SetReflAmt(float v, TimeValue t);
SetShadColor(Color c,TimeValue t)127       void SetShadColor(Color c, TimeValue t){  col= c;  pblock->SetValue(matte_color, t, c); }
128 
129 
130       // From MtlBase and Mtl
SetAmbient(Color c,TimeValue t)131       void SetAmbient(Color c, TimeValue t) {}
SetDiffuse(Color c,TimeValue t)132       void SetDiffuse(Color c, TimeValue t) {}
SetSpecular(Color c,TimeValue t)133       void SetSpecular(Color c, TimeValue t) {}
SetShininess(float v,TimeValue t)134       void SetShininess(float v, TimeValue t) {}
135 
GetAmbient(int mtlNum=0,BOOL backFace=FALSE)136       Color GetAmbient(int mtlNum=0, BOOL backFace=FALSE) { return black; }
GetDiffuse(int mtlNum=0,BOOL backFace=FALSE)137        Color GetDiffuse(int mtlNum=0, BOOL backFace=FALSE) { return white; }
GetSpecular(int mtlNum=0,BOOL backFace=FALSE)138       Color GetSpecular(int mtlNum=0, BOOL backFace=FALSE) { return black; }
GetXParency(int mtlNum=0,BOOL backFace=FALSE)139       float GetXParency(int mtlNum=0, BOOL backFace=FALSE){ return 0.0f; }
GetShininess(int mtlNum=0,BOOL backFace=FALSE)140       float GetShininess(int mtlNum=0, BOOL backFace=FALSE){ return 0.0f; }
GetShinStr(int mtlNum=0,BOOL backFace=FALSE)141       float GetShinStr(int mtlNum=0, BOOL backFace=FALSE){ return 1.0f; }
142 
143       void EnableStuff();
144       ParamDlg* CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
145 
146       void Shade(ShadeContext& sc);
147       void Update(TimeValue t, Interval& valid);
148       void Init();
149       void Reset();
150       Interval Validity(TimeValue t);
151 
ClassID()152       Class_ID ClassID() {return matteClassID; }
SuperClassID()153       SClass_ID SuperClassID() {return MATERIAL_CLASS_ID;}
GetClassName(TSTR & s)154       void GetClassName(TSTR& s) {s=GetString(IDS_DS_MATTE_SHADOW);}
155 
DeleteThis()156       void DeleteThis() {delete this;}
157 
LocalRequirements(int subMtlNum)158       ULONG LocalRequirements(int subMtlNum) {
159 #if 1
160          ULONG flags  =  fogBG  ?  ( fogObjDepth ? 0 : MTLREQ_NOATMOS )  :  MTLREQ_NOATMOS;
161 
162          // > 10/9/02 - 2:38pm --MQM--
163          // if the tone operator is active, we need to match it's
164          // "process background" flag for our material requirements.
165          // otherwise we will have a matte-plane that gets tone-op'd
166          // hovering over a background plane that doesn't.
167          ToneOperatorInterface* toneOpInterface = static_cast<ToneOperatorInterface*>( GetCOREInterface(TONE_OPERATOR_INTERFACE) );
168          if ( toneOpInterface )
169          {
170             ToneOperator *pToneOp = toneOpInterface->GetToneOperator();
171             if ( pToneOp )
172             {
173                if ( !pToneOp->GetProcessBackground() )
174                   flags |= MTLREQ_NOEXPOSURE;   // <-- new MTLREQ flag to disable toneop
175             }
176          }
177 
178          return flags;
179 #else
180          return fogBG  ?  ( fogObjDepth ? 0 : MTLREQ_NOATMOS )  :  MTLREQ_NOATMOS;
181 #endif
182          }
183 
184 
185       // Methods to access texture maps of material
NumSubTexmaps()186       int NumSubTexmaps() { return 1; }
GetSubTexmap(int i)187       Texmap* GetSubTexmap(int i) { return reflmap; }
SetSubTexmap(int i,Texmap * m)188       void SetSubTexmap(int i, Texmap *m) {
189          ReplaceReference(REFLMAP_REF,m);
190 //       if (dlg) dlg->UpdateSubTexNames();
191          mReshadeRQ = RR_NeedPreshade;
192 //       NotifyChanged();
193          }
GetSubTexmapSlotName(int i)194       TSTR GetSubTexmapSlotName(int i) {
195          return TSTR(GetString(IDS_DS_MAP));
196          }
NumSubs()197       int NumSubs() {return 2;}
198       Animatable* SubAnim(int i);
199       TSTR SubAnimName(int i);
SubNumToRefNum(int subNum)200       int SubNumToRefNum(int subNum) {return subNum;}
201 
202       // From ref
NumRefs()203       int NumRefs() {return GetSavingVersion()==2000?1:2;}
204       RefTargetHandle GetReference(int i);
205       void SetReference(int i, RefTargetHandle rtarg);
206 
207       IOResult Save(ISave *isave);
208       IOResult Load(ILoad *iload);
209 
210       RefTargetHandle Clone(RemapDir &remap = DefaultRemapDir());
211       RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
212          PartID& partID, RefMessage message);
213 
214 // JBW: direct ParamBlock access is added
NumParamBlocks()215       int   NumParamBlocks() { return 1; }               // return number of ParamBlocks in this instance
GetParamBlock(int i)216       IParamBlock2* GetParamBlock(int i) { return pblock; } // return i'th ParamBlock
GetParamBlockByID(BlockID id)217       IParamBlock2* GetParamBlockByID(BlockID id) { return (pblock->ID() == id) ? pblock : NULL; } // return id'd ParamBlock
218 
219 // begin - ke/mjm - 03.16.00 - merge reshading code
SupportsRenderElements()220       BOOL SupportsRenderElements(){ return TRUE; }
221 //    BOOL SupportsReShading(ShadeContext& sc);
GetReshadeRequirements()222       ReshadeRequirements GetReshadeRequirements() { return mReshadeRQ; } // mjm - 06.02.00
223       void PreShade(ShadeContext& sc, IReshadeFragment* pFrag);
224       void PostShade(ShadeContext& sc, IReshadeFragment* pFrag, int& nextTexIndex, IllumParams* ip);
225 // end - ke/mjm - 03.16.00 - merge reshading code
226 
227       bool IsOutputConst( ShadeContext& sc, int stdID );
228       bool EvalColorStdChannel( ShadeContext& sc, int stdID, Color& outClr);
229       bool EvalMonoStdChannel( ShadeContext& sc, int stdID, float& outVal);
230 
231       void* GetInterface(ULONG id);
232 
233    };
234 
235 class MatteClassDesc:public ClassDesc2 {
236    public:
IsPublic()237    int         IsPublic() {return GetAppID() != kAPP_VIZR;}
Create(BOOL loading)238    void *         Create(BOOL loading) {return new Matte(loading);}
ClassName()239    const TCHAR *  ClassName() {return GetString(IDS_DS_MATTE_SHADOW_CDESC); } // mjm - 2.3.99
SuperClassID()240    SClass_ID      SuperClassID() {return MATERIAL_CLASS_ID;}
ClassID()241    Class_ID       ClassID() {return matteClassID;}
Category()242    const TCHAR*   Category() {return _T("");}
243 // JBW: new descriptor data accessors added.  Note that the
244 //      internal name is hardwired since it must not be localized.
InternalName()245    const TCHAR*   InternalName() { return _T("Matte"); } // returns fixed parsable name (scripter-visible name)
HInstance()246    HINSTANCE      HInstance() { return hInstance; }         // returns owning module handle
247    };
248 static MatteClassDesc matteCD;
GetMatteDesc()249 ClassDesc* GetMatteDesc() {return &matteCD;}
250 
251 
252 //--- MatteDlg ------------------------------------------------------
253 /*
254 static INT_PTR CALLBACK PanelDlgProc(
255       HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
256    {
257    MatteDlg *dlg;
258    if (msg==WM_INITDIALOG) {
259       dlg = (MatteDlg*)lParam;
260       DLSetWindowLongPtr(hWnd, lParam);
261       }
262    else {
263        if ( (dlg = DLGetWindowLongPtr<MatteDlg *>(hWnd) ) == NULL )
264          return FALSE;
265       }
266    dlg->isActive = TRUE;
267    int   res = dlg->WndProc(hWnd,msg,wParam,lParam);
268    dlg->isActive = FALSE;
269    return res;
270    }
271 
272 
273 MatteDlg::MatteDlg(HWND hwMtlEdit, IMtlParams *imp, Matte *m)
274    {
275    dadMgr.Init(this);
276    hwmedit = hwMtlEdit;
277    ip      = imp;
278    theMtl  = m;
279    valid   = FALSE;
280    iAmb  = NULL;
281    iReflAmt  = NULL;
282    creating = TRUE;
283    iReflBut = NULL;
284    hPanel = ip->AddRollupPage(
285       hInstance,
286       MAKEINTRESOURCE(IDD_MATTE),
287       PanelDlgProc,
288       GetString(IDS_DS_MATTE_SHADOW_PAR),
289       (LPARAM)this);
290    creating = FALSE;
291    }
292 
293 MatteDlg::~MatteDlg()
294    {
295    theMtl->dlg = NULL;
296    ReleaseISpinner(iAmb);
297    ReleaseISpinner(iReflAmt);
298    ReleaseIColorSwatch(cs);
299    ReleaseICustButton(iReflBut);
300    iReflBut = NULL;
301    DLSetWindowLongPtr(hPanel, NULL);
302    }
303 
304 void MatteDlg::EnableAlpha(HWND hWnd) {
305    EnableWindow(GetDlgItem(hWnd,IDC_MATTE_SHADALPHA), !theMtl->opaque);
306    }
307 
308 BOOL MatteDlg::WndProc(
309       HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
310    {
311    switch (msg) {
312       case WM_INITDIALOG:
313          iAmb= SetupFloatSpinner(hWnd, IDC_MATTE_AMB_SPIN, IDC_MATTE_AMB_EDIT, 0.0f,1.0f, 0.5f,.01f);
314          SetCheckBox(hWnd,IDC_MATTE_FOGBG, theMtl->fogBG);
315          SetCheckBox(hWnd,IDC_MATTE_SHADOW, theMtl->shadowBG);
316          SetCheckBox(hWnd,IDC_MATTE_OPAQUE, theMtl->opaque);
317          SetCheckBox(hWnd,IDC_MATTE_SHADALPHA, theMtl->shadowAlpha);
318          SetDepthRadios();
319          EnableAlpha(hWnd);
320          iReflBut = GetICustButton(GetDlgItem(hWnd,IDC_MATTE_REFL_MAP));
321          iReflBut->SetDADMgr(&dadMgr);
322          iReflAmt= SetupFloatSpinner(hWnd, IDC_MATTE_REFLAMT_SPIN, IDC_MATTE_REFLAMT_EDIT, 0.0f, 9999.0f, 1.0f,.01f);
323          cs = GetIColorSwatch(GetDlgItem(hWnd, IDC_SHAD_COLOR),
324                   theMtl->col, GetString(IDS_DS_SHAD_COLOR));
325          iReflAmt->Enable(theMtl->reflmap?1:0);
326          break;
327 
328       case WM_PAINT:
329          if (!valid) {
330             valid = TRUE;
331             ReloadDialog();
332             }
333          return FALSE;
334 
335       case WM_COMMAND:
336          if (creating) break;
337          switch (LOWORD(wParam)) {
338             case IDC_MATTE_FOGBG:
339                theMtl->fogBG = GetCheckBox(hWnd,IDC_MATTE_FOGBG);
340                break;
341             case IDC_MATTE_SHADOW:
342                theMtl->shadowBG = GetCheckBox(hWnd,IDC_MATTE_SHADOW);
343                break;
344             case IDC_MATTE_SHADALPHA:
345                theMtl->shadowAlpha = GetCheckBox(hWnd,IDC_MATTE_SHADALPHA);
346                break;
347             case IDC_MATTE_OPAQUE:
348                theMtl->opaque = GetCheckBox(hWnd,IDC_MATTE_OPAQUE);
349                EnableAlpha(hWnd);
350                break;
351             case IDC_MATTE_FOG_BGDEPTH:
352                theMtl->fogObjDepth = 0;
353                SetDepthRadios();
354                break;
355             case IDC_MATTE_FOG_OBJDEPTH:
356                theMtl->fogObjDepth = 1;
357                SetDepthRadios();
358                break;
359             case IDC_MATTE_REFL_MAP:
360                PostMessage(hwmedit,WM_TEXMAP_BUTTON, 0 ,(LPARAM)theMtl);
361                break;
362             }
363          break;
364 
365 
366       case CC_COLOR_BUTTONDOWN:
367          theHold.Begin();
368          break;
369       case CC_COLOR_BUTTONUP:
370          if (HIWORD(wParam)) theHold.Accept(GetString(IDS_DS_PARAMCHG));
371          else theHold.Cancel();
372          break;
373 
374       case CC_COLOR_CHANGE: {
375          int id = LOWORD(wParam);
376          int buttonUp = HIWORD(wParam);
377          if (buttonUp) theHold.Begin();
378          theMtl->SetShadColor(cs->GetColor(),ip->GetTime());
379          cs->SetKeyBrackets(KeyAtCurTime(PB_COL));
380          if (buttonUp) {
381             theHold.Accept(GetString(IDS_DS_PARAMCHG));
382             UpdateMtlDisplay();
383             theMtl->NotifyChanged();
384             }
385          break;
386          }
387 
388 
389       case CC_SPINNER_CHANGE:
390          if (!theHold.Holding()) theHold.Begin();
391          switch (LOWORD(wParam)) {
392             case IDC_MATTE_AMB_SPIN: {
393                ISpinnerControl *spin = (ISpinnerControl*)lParam;
394                theMtl->SetAmbLev(spin->GetFVal(),ip->GetTime());
395                spin->SetKeyBrackets(KeyAtCurTime(PB_AMB));
396                break;
397                }
398             case IDC_MATTE_REFLAMT_SPIN: {
399                ISpinnerControl *spin = (ISpinnerControl*)lParam;
400                theMtl->SetReflAmt(spin->GetFVal(),ip->GetTime());
401                spin->SetKeyBrackets(KeyAtCurTime(PB_REFLAMT));
402                break;
403                }
404             }
405          break; // DS 4/11/96
406       case CC_SPINNER_BUTTONDOWN:
407          theHold.Begin();
408          break;
409       case WM_CUSTEDIT_ENTER:
410       case CC_SPINNER_BUTTONUP:
411          if (HIWORD(wParam) || msg==WM_CUSTEDIT_ENTER) theHold.Accept(GetString(IDS_DS_PARAMCHG));
412          else theHold.Cancel();
413          break;
414 
415       default:
416          return FALSE;
417       }
418    return TRUE;
419    }
420 
421 void MatteDlg::Invalidate()
422    {
423    valid = FALSE;
424    isActive = FALSE;
425    Rect rect;
426    rect.left = rect.top = 0;
427    rect.right = rect.bottom = 10;
428    InvalidateRect(hPanel,&rect,FALSE);
429    }
430 
431 void MatteDlg::UpdateSubTexNames() {
432    TSTR nm;
433    if (theMtl->reflmap)  nm = theMtl->reflmap->GetFullName();
434    else nm = GetString(IDS_DS_NONE);
435    iReflBut->SetText(nm.data());
436    }
437 
438 void MatteDlg::SetDepthRadios() {
439    int id = theMtl->fogObjDepth?IDC_MATTE_FOG_OBJDEPTH:IDC_MATTE_FOG_BGDEPTH;
440    CheckRadioButton(hPanel,IDC_MATTE_FOG_BGDEPTH,IDC_MATTE_FOG_OBJDEPTH,id);
441    }
442 
443 void MatteDlg::SetThing(ReferenceTarget *m) {
444    theMtl = (Matte*)m;
445    if (theMtl) theMtl->dlg = this;
446    ReloadDialog();   //DS 11/9/96
447    }
448 
449 BOOL MatteDlg::KeyAtCurTime(int id) {
450    return theMtl->pblock->KeyFrameAtTime(id,ip->GetTime());
451    }
452 
453 void MatteDlg::ReloadDialog()
454    {
455    Interval valid;
456    theMtl->Update(ip->GetTime(), valid);
457    iAmb->SetValue(theMtl->amblev,FALSE);
458    iReflAmt->SetValue(theMtl->reflAmt,FALSE);
459    cs->SetColor(theMtl->col);
460    SetCheckBox(hPanel,IDC_MATTE_FOGBG, theMtl->fogBG);
461    SetCheckBox(hPanel,IDC_MATTE_SHADOW, theMtl->shadowBG);
462    SetCheckBox(hPanel,IDC_MATTE_SHADALPHA, theMtl->shadowAlpha);
463    SetCheckBox(hPanel,IDC_MATTE_OPAQUE, theMtl->opaque);
464    cs->SetKeyBrackets(KeyAtCurTime(PB_COL));
465    iAmb->SetKeyBrackets(KeyAtCurTime(PB_AMB));
466    iReflAmt->SetKeyBrackets(KeyAtCurTime(PB_REFLAMT));
467    iReflAmt->Enable(theMtl->reflmap?1:0);
468 
469    SetDepthRadios();
470    UpdateSubTexNames();
471    }
472 */
473 
474 
475 // shader rollout dialog proc
476 class MatteDlgProc : public ParamMap2UserDlgProc
477    {
478    public:
DlgProc(TimeValue t,IParamMap2 * map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)479       INT_PTR DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { return FALSE; }
SetThing(ReferenceTarget * m)480       void SetThing(ReferenceTarget *m) {
481          Matte *mtl = (Matte *)m;
482          if (mtl) mtl->EnableStuff();
483          }
DeleteThis()484       void DeleteThis() { }
485    };
486 
487 static MatteDlgProc matteDlgProc;
488 
489 class MattePBAccessor : public PBAccessor
490 {
491 public:
Set(PB2Value & v,ReferenceMaker * owner,ParamID id,int tabIndex,TimeValue t)492    void Set(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)    // set from v
493    {
494       Matte* p = (Matte*)owner;
495       if (p!=NULL) {
496          IParamMap2 *map = p->pblock->GetMap();
497          if (map) {
498             switch (id) {
499                case matte_opaque_alpha:
500                   map->Enable(matte_affect_alpha, v.i? FALSE: TRUE);
501                   break;
502                case matte_reflection_map:
503                      map->Enable(matte_reflection_amount, v.r?TRUE: FALSE);
504                   break;
505                }
506             }
507          }
508 
509    }
510 };
511 
512 static MattePBAccessor matte_accessor;
513 
514 
515 
516 static ParamBlockDesc2 matte_param_blk ( matte_params, _T("parameters"),  0, &matteCD, P_AUTO_CONSTRUCT + P_AUTO_UI, PB_REF,
517    //rollout
518    IDD_MATTE, IDS_DS_MATTE_SHADOW_PAR, 0, 0, &matteDlgProc,
519    // params
520    matte_opaque_alpha,  _T("opaqueAlpha"), TYPE_BOOL,       0,          IDS_PW_OALPHA,
521       p_default,     FALSE,
522       p_ui,       TYPE_SINGLECHEKBOX, IDC_MATTE_OPAQUE,
523       p_accessor,    &matte_accessor,
524       end,
525 
526    matte_apply_atmosphere, _T("applyAtmosphere"), TYPE_BOOL,         0,          IDS_PW_APPLYATMOS,
527       p_default,     FALSE,
528       p_ui,       TYPE_SINGLECHEKBOX, IDC_MATTE_FOGBG,
529       end,
530    matte_atmosphere_depth, _T("atmosphereDepth"), TYPE_INT,          0,          IDS_PW_ATMOSDEPTH,
531       p_default,     0,
532       p_range,    0, 1,
533       p_ui,       TYPE_RADIO, 2, IDC_MATTE_FOG_BGDEPTH, IDC_MATTE_FOG_OBJDEPTH,
534       end,
535    matte_receive_shadows,  _T("receiveShadows"), TYPE_BOOL,       0,          IDS_PW_RECEIVESHADOWS,
536       p_default,     TRUE,
537       p_ui,       TYPE_SINGLECHEKBOX, IDC_MATTE_SHADOW,
538       end,
539    matte_affect_alpha,  _T("affectAlpha"), TYPE_BOOL,       0,          IDS_PW_AFFECTALPHA,
540       p_default,     TRUE,
541       p_ui,       TYPE_SINGLECHEKBOX, IDC_MATTE_SHADALPHA,
542       p_enabled,     FALSE,
543       end,
544    matte_shadow_brightness,   _T("shadowBrightness"), TYPE_FLOAT,       P_ANIMATABLE,  IDS_DS_SHADOW_BRITE,
545       p_default,     0.0,
546       p_range,    0.0, 1.0,
547       p_ui,          TYPE_SPINNER, EDITTYPE_FLOAT, IDC_MATTE_AMB_EDIT, IDC_MATTE_AMB_SPIN, 0.1,
548       end,
549    matte_color, _T("color"),  TYPE_RGBA,           P_ANIMATABLE,  IDS_DS_SHAD_COLOR,
550       p_default,     Color(0,0,0),
551       p_ui,       TYPE_COLORSWATCH, IDC_SHAD_COLOR,
552       end,
553    matte_reflection_amount,   _T("amount"), TYPE_PCNT_FRAC, P_ANIMATABLE,  IDS_DS_REFLAMT,
554       p_default,     0.5,
555       p_range,    0.0, 100.0,
556       p_ui,          TYPE_SPINNER, EDITTYPE_FLOAT, IDC_MATTE_REFLAMT_EDIT, IDC_MATTE_REFLAMT_SPIN, 0.1,
557 
558       end,
559    matte_reflection_map, _T("map"),    TYPE_TEXMAP,         P_OWNERS_REF,  IDS_DS_MAP,
560       p_refno,    REFLMAP_REF,
561       p_subtexno,    0,
562       p_ui,       TYPE_TEXMAPBUTTON, IDC_MATTE_REFL_MAP,
563       p_accessor,    &matte_accessor,
564 
565       end,
566    matte_use_reflection_map,  _T("useReflMap"), TYPE_BOOL,     0,  IDS_DS_USEREFL,
567       p_default,     TRUE,
568       p_ui,       TYPE_SINGLECHEKBOX, IDC_MATTE_USEREFL,
569       end,
570    matte_additive_reflection, _T("additiveReflection"), TYPE_INT,       0,  IDS_DS_USEREFL,
571       p_default,     TRUE,
572       p_ui,       TYPE_SINGLECHEKBOX, IDC_MATTE_ADDITIVE_REFL,
573       end,
574 
575 
576    end
577    );
578 
579 //--- Matte Material -------------------------------------------------
580 
581 
582 static ParamBlockDescID pbdesc0[] = {
583    {TYPE_FLOAT, NULL, TRUE,matte_shadow_brightness }};   // ambient light level
584 
585 
586 static ParamBlockDescID pbdesc1[] = {
587    {TYPE_FLOAT, NULL, TRUE,matte_shadow_brightness },
588    {TYPE_RGBA, NULL, TRUE ,matte_color }
589    };
590 
591 static ParamBlockDescID pbdesc[] = {
592    {TYPE_FLOAT, NULL, TRUE,matte_shadow_brightness },
593    {TYPE_RGBA,  NULL, TRUE,matte_color },
594    {TYPE_FLOAT, NULL, TRUE,matte_reflection_amount }
595    };
596 
597 #define MATTE_VERSION 3
598 #define NUM_OLDVERSIONS 3
599 #define NPARAMS 3
600 
601 // Array of old versions
602 static ParamVersionDesc versions[NUM_OLDVERSIONS] = {
603    ParamVersionDesc(pbdesc0,1,0),
604    ParamVersionDesc(pbdesc1,2,1),
605    ParamVersionDesc(pbdesc,3,2)
606    };
607 
608 
609 //static ParamVersionDesc curVersion(pbdesc,NPARAMS,MATTE_VERSION);
610 
611 // Code for saving Max R2 files -------------------
612 /*
613 static void NotifyPreSaveOld(void *param, NotifyInfo *info) {
614    Matte *mt = (Matte *)param;
615    if (GetSavingVersion()==2000) {
616       mt->savepb = mt->pblock;
617       mt->pblock = UpdateParameterBlock(pbdesc,3,mt->savepb,pbdesc1,2,1);
618       }
619    }
620 
621 static void NotifyPostSaveOld(void *param, NotifyInfo *info) {
622    Matte *mt = (Matte *)param;
623    if (mt->savepb) {
624       mt->pblock->DeleteThis();
625       mt->pblock = mt->savepb;
626       mt->savepb = NULL;
627       }
628    }
629    */
630 //----------------------------------------------------------------
631 
Matte(BOOL loading)632 Matte::Matte(BOOL loading) : mReshadeRQ(RR_None) // mjm - 06.02.00
633    {
634 // dlg = NULL;
635    pblock = NULL;
636    savepb = NULL;  // for saving pblock when saving Max R2 files
637    reflmap = NULL;
638    ivalid.SetEmpty();
639    fogBG = FALSE;    // DS 11/9/96
640    shadowBG = FALSE;
641    shadowAlpha = FALSE;
642    opaque = FALSE;
643    fogObjDepth = FALSE;
644    additiveReflection = FALSE;
645 // RegisterNotification(NotifyPreSaveOld, (void *)this, NOTIFY_FILE_PRE_SAVE_OLD);
646 // RegisterNotification(NotifyPostSaveOld, (void *)this, NOTIFY_FILE_POST_SAVE_OLD);
647 
648    matteCD.MakeAutoParamBlocks(this);  // make and intialize paramblock2
649    Init();
650    }
651 
~Matte()652 Matte::~Matte() {
653 //  UnRegisterNotification(NotifyPreSaveOld, (void *)this, NOTIFY_FILE_PRE_SAVE_OLD);
654 // InRegisterNotification(NotifyPostSaveOld, (void *)this, NOTIFY_FILE_POST_SAVE_OLD);
655    }
656 
Init()657 void Matte::Init()
658    {
659    SetAmbLev(0.0f,0);
660    SetShadColor(Color(0.0f,0.0f,0.0f), TimeValue(0));
661    fogBG = FALSE;
662    shadowBG = FALSE;
663    shadowAlpha = FALSE;
664    opaque = TRUE;
665    fogObjDepth = FALSE;
666    additiveReflection = TRUE;
667    }
668 
Reset()669 void Matte::Reset()
670    {
671    matteCD.Reset(this, TRUE); // reset all pb2's
672    Init();
673    }
674 
GetInterface(ULONG id)675 void* Matte::GetInterface(ULONG id)
676 {
677    if( id == IID_IReshading )
678       return (IReshading*)( this );
679    else if ( id == IID_IValidityToken )
680       return (IValidityToken*)( this );
681    else
682       return Mtl::GetInterface(id);
683 }
684 
SetAmbLev(float v,TimeValue t)685 void Matte::SetAmbLev(float v, TimeValue t) {
686     amblev= v;
687    pblock->SetValue( matte_shadow_brightness, t, v);
688    }
689 
SetReflAmt(float v,TimeValue t)690 void Matte::SetReflAmt(float v, TimeValue t) {
691     reflAmt= v;
692    pblock->SetValue( matte_reflection_amount, t, v);
693    }
694 
695 
EnableStuff()696 void Matte::EnableStuff() {
697    if (pblock) {
698       IParamMap2 *map = pblock->GetMap();
699       if (map) {
700          map->Enable(matte_reflection_amount, reflmap?TRUE:FALSE);
701          map->Enable(matte_affect_alpha, opaque?FALSE:TRUE);
702          }
703       }
704    }
705 
CreateParamDlg(HWND hwMtlEdit,IMtlParams * imp)706 ParamDlg* Matte::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
707    {
708    // create the rollout dialogs
709    IAutoMParamDlg* masterDlg = matteCD.CreateParamDlgs(hwMtlEdit, imp, this);
710 
711    EnableStuff();
712 
713    return masterDlg;
714 
715 // dlg = new MatteDlg(hwMtlEdit, imp, this);
716 // return dlg;
717    }
718 
719 /* moved to shade context 6.13.00
720 Color DiffuseIllum(ShadeContext &sc) {
721    Point3 N = sc.Normal();
722    Point3 P = sc.P();
723    Color diffwk(0,0,0);
724    Color lightCol;
725    for (int i = 0; i<sc.nLights; i++) {
726       LightDesc* l = sc.Light(i);
727       register float dot_nl,diffCoef;
728       Point3 L;
729       if (!l->Illuminate(sc, N, lightCol, L, dot_nl,diffCoef))
730          continue;
731       if (dot_nl>0.0f)
732          diffwk += diffCoef*lightCol;
733       }
734    return diffwk;
735    }
736 */
737 
738 static Color blackCol(0.0f,0.0f,0.0f);
739 
740 #define CLAMP(x) (((x)>1.0f)?1.0f:((x)<0.0f)?0.0f:(x))
741 
Clamp(Color & c)742 static inline void Clamp(Color &c) {
743    c.r = CLAMP(c.r);
744    c.g = CLAMP(c.g);
745    c.b = CLAMP(c.b);
746    }
747 
748 // begin - ke/mjm - 03.16.00 - merge reshading code
749 //BOOL Matte::SupportsReShading(ShadeContext& sc)
750 //{
751 // BOOL result = TRUE;
752 // return result;
753 //}
754 
Clamp(float & val)755 inline void Clamp( float& val ){
756    if( val < 0.0f ) val = 0.0f;
757    else if( val > 1.0f ) val = 1.0f;
758 }
759 
LBound(Color & c,float min=0.0f)760 inline void LBound( Color& c, float min = 0.0f )
761 {
762    if( c.r < min ) c.r = min;
763    if( c.g < min ) c.g = min;
764    if( c.b < min ) c.b = min;
765 }
766 
767 // returns shadow fraction & shadowClr
768 // move this util to shade context at first opportunity
IllumShadow(ShadeContext & sc,Color & shadowClr)769 float IllumShadow( ShadeContext& sc, Color& shadowClr )
770 {
771    IlluminateComponents illumComp;
772    IIlluminationComponents* pIComponents;
773    Color illumClr(0,0,0);
774    Color illumClrNS(0,0,0);
775    shadowClr.Black();
776    Point3 N = sc.Normal();
777 
778    // scale the sums so we don't overflow
779 // float scaleFactor = 1.0;
780 // if( sc.nLights )
781 //    scaleFactor = 1.0f / float( sc.nLights );
782 
783    // > 9/24/02 - 2:30pm --MQM--
784    // poke flag to let Light Tracer/Radiosity so they will
785    // separate out the shadow value.
786    int oldXID = sc.xshadeID;
787    sc.xshadeID |= SHADECONTEXT_GUESS_SHADOWS_FLAG;
788 
789    for (int i = 0; i < sc.nLights; i++) {
790       LightDesc* l = sc.Light( i );
791       pIComponents = (IIlluminationComponents*)l->GetInterface( IID_IIlluminationComponents );
792       if( pIComponents ){
793          // use component wise illuminate routines
794          if (!pIComponents->Illuminate( sc, N, illumComp ))
795             continue;
796 
797 //       illumClr += (illumComp.finalColor - illumComp.shadowColor ) * illumComp.geometricAtten * scaleFactor;
798          LBound( illumComp.shadowColor );
799          illumClr += (illumComp.finalColor - illumComp.shadowColor ) * illumComp.geometricAtten;
800 //       illumClrNS += illumComp.finalColorNS * illumComp.geometricAtten * scaleFactor;
801          illumClrNS += illumComp.finalColorNS * illumComp.geometricAtten;
802          if( illumComp.rawColor != illumComp.filteredColor ){
803             // light is filtered by a transparent object, sum both filter & user shadow color
804             shadowClr += illumComp.finalColor * illumComp.geometricAtten; //attenuated filterColor
805          } else {
806             // no transparency, sum in just the shadow color
807             shadowClr += illumComp.shadowColor * illumComp.geometricAtten;
808          }
809 
810       } else {
811          // no component interface, shadow clr is black
812          Color lightCol;
813          Point3 L;
814          register float NL, diffCoef;
815          if (!l->Illuminate(sc, N, lightCol, L, NL, diffCoef))
816             continue;
817          if (diffCoef <= 0.0f)
818             continue;
819 //       illumClr += diffCoef * lightCol * scaleFactor;
820          illumClr += diffCoef * lightCol;
821 
822          if( sc.shadow ){
823             sc.shadow = FALSE;
824             l->Illuminate(sc, N, lightCol, L, NL, diffCoef);
825 //          illumClrNS += diffCoef * lightCol * scaleFactor;
826             illumClrNS += diffCoef * lightCol;
827             sc.shadow = TRUE;
828          } else {
829             illumClrNS = illumClr;
830          }
831       }
832    }// end, for each light
833 
834    // > 9/24/02 - 2:31pm --MQM--
835    // restore xshadeID
836    sc.xshadeID = oldXID;
837 
838    float intensNS = Intens(illumClrNS);
839 // Clamp( intensNS );
840    float intens = Intens(illumClr);
841 // Clamp( intens );
842    float atten = (intensNS > 0.01f)? intens/intensNS : 1.0f;
843    if (atten > 1.0f)
844       atten = 1.0f/atten;
845 
846    return atten;
847 }
848 
849 static BOOL  gUseLocalShadowClr = FALSE;
850 
851 #ifdef _DEBUG
852 static int stopX = -1;
853 static int stopY = -1;
854 #endif
855 
856 // if this function changes, please also check SupportsReShading, PreShade and PostShade
857 // end - ke/mjm - 03.16.00 - merge reshading code
858 // [attilas|29.5.2000] if this function changes, please also check EvalColorStdChannel
Shade(ShadeContext & sc)859 void Matte::Shade(ShadeContext& sc)
860 {
861    Color c,t, shadowClr;
862    float atten;
863    float reflA;
864 
865    // > 6/15/02 - 11:12am --MQM--
866    // for renderer prepass, we need to at least call
867    // illuminate so that Light Tracer can cache shading
868    if ( SHADECONTEXT_IS_PREPASS( sc ) )
869    {
870       Color    lightCol;
871       Point3   L;
872       float    NL, diffCoef;
873       LightDesc *l;
874       for ( int i = 0;  i < sc.nLights;  i++ )
875       {
876          if ( l = sc.Light( i ) )
877             l->Illuminate( sc, sc.Normal(), lightCol, L, NL, diffCoef );
878       }
879       return;
880    }
881 
882 #ifdef _DEBUG
883    IPoint2 sp = sc.ScreenCoord();
884    if ( sp.x == stopX && sp.y == stopY )
885       sp.x = stopX;
886 #endif
887 
888    if (gbufID) sc.SetGBufferID(gbufID);
889    IllumParams ip( 1, &shadowIllumOutStr);
890    IllumParams ipNS(0, NULL);
891    ip.ClearInputs(); ip.ClearOutputs();
892    ipNS.ClearInputs(); ipNS.ClearOutputs();
893    ip.hasComponents = ipNS.hasComponents = HAS_MATTE_MTL;
894 
895    // get background color & transparency
896    if (!opaque) sc.Execute(0x1000); // DS: 6/24/99:use black bg when AA filtering (#192348)
897    sc.GetBGColor(c, t, fogBG&&(!fogObjDepth) );
898    if (!opaque) sc.Execute(0x1001); // DS: 6/24/99:use black bg when AA filtering (#192348)
899 
900    if (shadowBG && sc.shadow) {
901       /********
902       sc.shadow = 0;
903       Color col0 = sc.DiffuseIllum();
904       sc.shadow = 1;
905       Color scol = sc.DiffuseIllum();
906       float f = Intens(col0);
907       atten = (f>0.0f)?Intens(scol)/f:1.0f;
908       if (atten>1.0f) atten = 1.0f/atten;
909       ********/
910       atten = IllumShadow( sc, shadowClr );
911       atten = amblev + (1.0f-amblev) * atten;
912 
913       // key on black user-set shadow clr
914       if( gUseLocalShadowClr || col.r != 0.0f || col.g != 0.0f || col.b != 0.0f )
915             shadowClr = col;
916 
917       ipNS.finalC = ipNS.diffIllumOut = c;
918       c *= atten;
919       ip.diffIllumOut = c;
920 
921       shadowClr *= 1.0f - atten;
922       ip.finalC = sc.out.c = c + shadowClr;
923 
924       ip.SetUserIllumOutput( 0, shadowClr );
925 
926       if (shadowAlpha)
927          t *= atten;
928    } else {
929       sc.out.c  =
930       ipNS.finalC = ipNS.diffIllumOut = ip.finalC = ip.diffIllumOut = c;
931    }
932 
933 
934    // add the reflections
935    if (reflmap && useReflMap) {
936       AColor rcol;
937       if (reflmap->HandleOwnViewPerturb()) {
938          sc.TossCache(reflmap);
939          rcol = reflmap->EvalColor(sc);
940       } else
941          rcol = sc.EvalEnvironMap(reflmap, sc.ReflectVector());
942 
943       Color rc;
944       rc = Color(rcol.r,rcol.g,rcol.b)*reflAmt;
945       ip.reflIllumOut = ipNS.reflIllumOut = rc;
946 
947       if( additiveReflection ) {
948          // additive compositing of reflections
949          sc.out.c += rc; ip.finalC += rc; ipNS.finalC += rc;
950       } else {
951          reflA = Intens( rc );
952          // over compositing of reflections
953          sc.out.c = (1.0f - reflA) * sc.out.c + rc;
954          ip.finalC = (1.0f - reflA) * ip.finalC + rc;
955          ipNS.finalC = (1.0f - reflA) * ipNS.finalC + rc;
956       }
957    }
958 
959    // render elements
960    Clamp( t );
961    Clamp( reflA );
962    ip.finalT = ipNS.finalT = sc.out.t = opaque ? black: additiveReflection? t : Color(reflA,reflA,reflA) ;
963    int nEles = sc.NRenderElements();
964    if( nEles != 0 ){
965       ip.pShader = ipNS.pShader = NULL; // no shader on matte mtl
966       ip.stdIDToChannel = ipNS.stdIDToChannel = NULL;
967       ip.pMtl = ipNS.pMtl = this;
968       ip.finalAttenuation = ipNS.finalAttenuation = 1.0f;
969 
970       for( int i=0; i < nEles; ++i ){
971          IRenderElement* pEle = sc.GetRenderElement(i);
972          if( pEle->IsEnabled() ){
973             MaxRenderElement* pMaxEle = (MaxRenderElement*)pEle->GetInterface( MaxRenderElement::IID );
974             if( pEle->ShadowsApplied() )
975                pMaxEle->PostIllum( sc, ip );
976             else
977                pMaxEle->PostIllum( sc, ipNS );
978          }
979       }
980    }
981 
982 }
983 
984 
PreShade(ShadeContext & sc,IReshadeFragment * pFrag)985 void Matte::PreShade(ShadeContext& sc, IReshadeFragment* pFrag)
986 {
987    // save reflection texture
988    if ( reflmap ){
989       AColor rcol;
990       if (reflmap->HandleOwnViewPerturb()) {
991          sc.TossCache(reflmap);
992          rcol = reflmap->EvalColor(sc);
993       } else
994          rcol = sc.EvalEnvironMap(reflmap, sc.ReflectVector());
995       pFrag->AddColorChannel( rcol );
996    }
997 }
998 
PostShade(ShadeContext & sc,IReshadeFragment * pFrag,int & nextTexIndex,IllumParams *)999 void Matte::PostShade(ShadeContext& sc, IReshadeFragment* pFrag, int& nextTexIndex, IllumParams*)
1000 {
1001    Color c,t;
1002    float atten;
1003 
1004    if (!opaque)
1005       sc.Execute(0x1000); // DS: 6/24/99:use black bg when AA filtering (#192348)
1006 
1007    sc.GetBGColor(c,t,fogBG && !fogObjDepth);
1008    if (!opaque)
1009       sc.Execute(0x1001); // DS: 6/24/99:use black bg when AA filtering (#192348)
1010 
1011    if (shadowBG && sc.shadow)
1012    {
1013 //    sc.shadow = 0;
1014 //    Color col0 = sc.DiffuseIllum();
1015 //    sc.shadow = 1;
1016 //    Color scol = sc.DiffuseIllum();
1017 //    float f = Intens(col0);
1018 //    atten = (f>0.0f)?Intens(scol)/f:1.0f;
1019 //    if (atten>1.0f) atten = 1.0f/atten;
1020 //    atten = amblev+(1.0f-amblev)*atten;
1021 //    sc.out.c = c*atten + (1.0f-atten)*col;
1022       Color shadowClr;
1023       atten = IllumShadow( sc, shadowClr );
1024       atten = amblev + (1.0f-amblev) * atten;
1025 
1026       // key on black user-set shadow clr
1027       if( gUseLocalShadowClr || col.r != 0.0f || col.g != 0.0f || col.b != 0.0f )
1028             shadowClr = col;
1029 
1030       c *= atten;
1031       shadowClr *= 1.0f - atten;
1032 
1033       sc.out.c = c + shadowClr;
1034 
1035       if (shadowAlpha)
1036          t *= atten;
1037    } else
1038       sc.out.c  = c;
1039 
1040    sc.out.t = opaque ? black : t;
1041    Clamp(sc.out.t);
1042 
1043    // code for compositing: -1 for opaque , else -2
1044    sc.out.ior = (opaque) ? -1.0f : -2.0f;
1045    if( reflmap ){
1046       if( useReflMap ){
1047          Color rc = pFrag->GetColorChannel( nextTexIndex++ );
1048          sc.out.c += rc * reflAmt;
1049       } else {
1050          nextTexIndex++;   // skip
1051       }
1052    }
1053 }
1054 
Update(TimeValue t,Interval & valid)1055 void Matte::Update(TimeValue t, Interval& valid)
1056    {
1057    ivalid = FOREVER;
1058    pblock->GetValue(matte_shadow_brightness,t,amblev,ivalid);
1059    pblock->GetValue(matte_color,t,col,ivalid);
1060    pblock->GetValue(matte_reflection_amount,t,reflAmt,ivalid);
1061 
1062 
1063    pblock->GetValue(matte_opaque_alpha,t,opaque,ivalid);
1064    pblock->GetValue(matte_apply_atmosphere,t,fogBG,ivalid);
1065    pblock->GetValue(matte_receive_shadows,t,shadowBG,ivalid);
1066    pblock->GetValue(matte_affect_alpha,t,shadowAlpha,ivalid);
1067    pblock->GetValue(matte_atmosphere_depth,t,fogObjDepth,ivalid);
1068    pblock->GetValue( matte_use_reflection_map,t, useReflMap, ivalid);
1069    pblock->GetValue( matte_additive_reflection,t, additiveReflection, ivalid);
1070 
1071    if (reflmap&&useReflMap)
1072       reflmap->Update(t,ivalid);
1073    EnableStuff();
1074 
1075    valid &= ivalid;
1076    }
1077 
Validity(TimeValue t)1078 Interval Matte::Validity(TimeValue t)
1079    {
1080    Interval valid = FOREVER;
1081    Update(t,valid);
1082    return valid;
1083    }
1084 
SubAnim(int i)1085 Animatable* Matte::SubAnim(int i)
1086    {
1087    switch (i) {
1088       case 0: return pblock;
1089       case 1: return reflmap;
1090       default: return NULL;
1091       }
1092    }
1093 
SubAnimName(int i)1094 TSTR Matte::SubAnimName(int i)
1095    {
1096    switch (i) {
1097       case 0: return GetString(IDS_DS_PARAMETERS);
1098       case 1: return GetString(IDS_DS_MAP);
1099       default: return _T("");
1100       }
1101    }
1102 
GetReference(int i)1103 RefTargetHandle Matte::GetReference(int i)
1104    {
1105    switch (i) {
1106       case 0: return pblock;
1107       case 1: return reflmap;
1108       default: return NULL;
1109       }
1110    }
1111 
SetReference(int i,RefTargetHandle rtarg)1112 void Matte::SetReference(int i, RefTargetHandle rtarg)
1113    {
1114    switch (i) {
1115       case 0: pblock = (IParamBlock2*)rtarg; break;
1116       case 1: reflmap = (Texmap*)rtarg;
1117 //       matte_param_blk.InvalidateUI();
1118 
1119          break;
1120       }
1121    }
1122 
Clone(RemapDir & remap)1123 RefTargetHandle Matte::Clone(RemapDir &remap)
1124    {
1125    Matte *mtl = new Matte(FALSE);
1126    *((MtlBase*)mtl) = *((MtlBase*)this);  // copy superclass stuff
1127    mtl->ReplaceReference(PB_REF,remap.CloneRef(pblock));
1128    mtl->fogBG = fogBG;
1129    mtl->shadowBG = shadowBG;
1130    mtl->shadowAlpha = shadowAlpha;
1131    mtl->opaque = opaque;
1132    mtl->fogObjDepth = fogObjDepth;
1133    mtl->useReflMap = useReflMap;
1134    if (reflmap)
1135       mtl->ReplaceReference(REFLMAP_REF,remap.CloneRef(reflmap));
1136    BaseClone(this, mtl, remap);
1137    return mtl;
1138    }
1139 
NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget,PartID & partID,RefMessage message)1140 RefResult Matte::NotifyRefChanged(
1141       Interval changeInt,
1142       RefTargetHandle hTarget,
1143       PartID& partID,
1144       RefMessage message)
1145    {
1146    switch (message) {
1147       case REFMSG_CHANGE:
1148          if (hTarget = pblock)
1149             {
1150             ivalid.SetEmpty();
1151          // see if this message came from a changing parameter in the pblock,
1152          // if so, limit rollout update to the changing item and update any active viewport texture
1153             ParamID changing_param = pblock->LastNotifyParamID();
1154             matte_param_blk.InvalidateUI(changing_param);
1155             if( (changing_param == matte_receive_shadows)
1156                ||(changing_param == matte_shadow_brightness)
1157                ||(changing_param == matte_color)
1158                ||(changing_param == matte_reflection_amount)
1159                ||(changing_param == matte_use_reflection_map))
1160             {
1161                mReshadeRQ = RR_NeedReshade;
1162             } else if (changing_param == -1)
1163                mReshadeRQ = RR_NeedPreshade;
1164              else
1165                mReshadeRQ = RR_None;
1166          }
1167 
1168          if (hTarget != NULL) {
1169 
1170             switch (hTarget->SuperClassID()) {
1171                case TEXMAP_CLASS_ID: {
1172                      mReshadeRQ = RR_NeedPreshade;
1173                } break;
1174 //             default:
1175 //                mReshadeRQ =RR_NeedReshade;
1176 //             break;
1177             }
1178 
1179          }
1180          break;
1181 
1182       case REFMSG_SUBANIM_STRUCTURE_CHANGED:
1183 //       if (partID == 0)
1184 //          mReshadeRQ = RR_None;
1185 //       else {
1186 //          mReshadeRQ = RR_NeedPreshade;
1187 //          NotifyChanged();
1188 //       }
1189          break;
1190 
1191    }
1192    return REF_SUCCEED;
1193 }
1194 
1195 
1196 #define MTL_HDR_CHUNK 0x4000
1197 #define FOGBG_CHUNK 0x0001
1198 #define SHADOWBG_CHUNK 0x0002
1199 #define MATTE_VERSION_CHUNK 0003
1200 #define OPAQUE_CHUNK 0x0004
1201 #define FOG_OBJDEPTH_CHUNK 0x0005
1202 #define SHADALPHA_CHUNK 0x0010
1203 
Save(ISave * isave)1204 IOResult Matte::Save(ISave *isave) {
1205    ULONG nb;
1206    isave->BeginChunk(MTL_HDR_CHUNK);
1207    IOResult res = MtlBase::Save(isave);
1208    if (res!=IO_OK) return res;
1209    isave->EndChunk();
1210 /*
1211    if (fogBG) {
1212       isave->BeginChunk(FOGBG_CHUNK);
1213       isave->EndChunk();
1214       }
1215    if (shadowBG) {
1216       isave->BeginChunk(SHADOWBG_CHUNK);
1217       isave->EndChunk();
1218       }
1219    if (shadowAlpha) {
1220       isave->BeginChunk(SHADALPHA_CHUNK);
1221       isave->EndChunk();
1222       }
1223    if (opaque) {
1224       isave->BeginChunk(OPAQUE_CHUNK);
1225       isave->EndChunk();
1226       }
1227    if (fogObjDepth) {
1228       isave->BeginChunk(FOG_OBJDEPTH_CHUNK);
1229       isave->EndChunk();
1230       }
1231 */
1232    int vers = 2;
1233 
1234    isave->BeginChunk(MATTE_VERSION_CHUNK);
1235    isave->Write(&vers, sizeof(vers), &nb);
1236    isave->EndChunk();
1237 
1238    return IO_OK;
1239    }
1240 
1241 //watje
1242 class MattePostLoadCallback:public  PostLoadCallback
1243 {
1244 public:
1245    Matte      *s;
MattePostLoadCallback(Matte * r)1246    MattePostLoadCallback(Matte *r) {s=r;}
1247    void proc(ILoad *iload);
1248 };
1249 
1250 
proc(ILoad * iload)1251 void MattePostLoadCallback::proc(ILoad *iload)
1252 {
1253 
1254    s->pblock->SetValue(matte_opaque_alpha,0,s->opaque);
1255    s->pblock->SetValue(matte_apply_atmosphere,0,s->fogBG);
1256    s->pblock->SetValue(matte_receive_shadows,0,s->shadowBG);
1257    s->pblock->SetValue(matte_affect_alpha,0,s->shadowAlpha);
1258    s->pblock->SetValue(matte_atmosphere_depth,0,s->fogObjDepth);
1259 
1260    delete this;
1261 
1262 }
1263 
1264 
1265 
Load(ILoad * iload)1266 IOResult Matte::Load(ILoad *iload) {
1267    ULONG nb;
1268    int id;
1269    version = 0;
1270    IOResult res;
1271 
1272    opaque = FALSE;
1273 
1274    while (IO_OK==(res=iload->OpenChunk())) {
1275       switch(id = iload->CurChunkID())  {
1276          case MTL_HDR_CHUNK:
1277             res = MtlBase::Load(iload);
1278             ivalid.SetEmpty();
1279             break;
1280          case FOGBG_CHUNK:
1281             fogBG = TRUE;
1282             break;
1283          case SHADOWBG_CHUNK:
1284             shadowBG = TRUE;
1285             break;
1286          case SHADALPHA_CHUNK:
1287             shadowAlpha = TRUE;
1288             break;
1289          case OPAQUE_CHUNK:
1290             opaque = TRUE;
1291             break;
1292          case FOG_OBJDEPTH_CHUNK:
1293             fogObjDepth = TRUE;
1294             break;
1295          case MATTE_VERSION_CHUNK:
1296             iload->Read(&version,sizeof(int), &nb);
1297             break;
1298          }
1299       iload->CloseChunk();
1300       if (res!=IO_OK)
1301          return res;
1302       }
1303 
1304    if (version  < 2)
1305       {
1306 
1307    // JBW: register old version ParamBlock to ParamBlock2 converter
1308       ParamBlock2PLCB* plcb = new ParamBlock2PLCB(versions, NUM_OLDVERSIONS, &matte_param_blk, this, PB_REF);
1309       iload->RegisterPostLoadCallback(plcb);
1310 
1311       MattePostLoadCallback* matteplcb = new MattePostLoadCallback(this);
1312       iload->RegisterPostLoadCallback(matteplcb);
1313       }
1314 
1315 
1316 // iload->RegisterPostLoadCallback(
1317 //    new ParamBlockPLCB(versions,NUM_OLDVERSIONS,&curVersion,this,PB_REF));
1318    return IO_OK;
1319 
1320    }
1321 
1322 //-----------------------------------------------------------------------------
1323 
1324 
1325 //������������������������������������������������������������������������
1326 //  Only the Reflection channel could not be constant
1327 //
IsOutputConst(ShadeContext & sc,int stdID)1328 bool Matte::IsOutputConst
1329 (
1330    ShadeContext& sc, // describes context of evaluation
1331    int stdID            // must be ID_AM, ect
1332 )
1333 {
1334    if ( stdID == ID_RL ) // Reflection (value 9)
1335    {
1336          if ( reflmap &&
1337                 useReflMap &&
1338                 reflmap->IsOutputMeaningful(sc) )
1339             return false;
1340    }
1341 
1342    return true;
1343 }
1344 
1345 //������������������������������������������������������������������������
1346 // The stdID parameter doesn't really have a meaning in this case.
1347 //
EvalColorStdChannel(ShadeContext & sc,int stdID,Color & outClr)1348 bool Matte::EvalColorStdChannel
1349 (
1350    ShadeContext& sc, // describes context of evaluation
1351    int stdID,           // must be ID_AM, ect
1352    Color& outClr        // output var
1353 )
1354 {
1355    switch ( stdID )
1356    {
1357       case ID_BU: // Bump (value 8)
1358       case ID_RR: // Refraction (value 10)
1359       case ID_DP: // Displacement (value 11)
1360       case ID_SI: // Self-illumination (value 5)
1361       case ID_FI: // Filter color (value 7)
1362          return false;
1363          break;
1364 
1365       case ID_RL: // Reflection (value 9)
1366          if ( sc.doMaps &&
1367                 reflmap &&
1368                 useReflMap &&
1369                 reflmap->IsOutputMeaningful(sc) )
1370          {
1371             AColor rcol;
1372             rcol.Black();
1373             if ( reflmap->HandleOwnViewPerturb() )
1374             {
1375                sc.TossCache(reflmap);
1376                rcol = reflmap->EvalColor(sc);
1377             }
1378             else
1379             {
1380                rcol = sc.EvalEnvironMap( reflmap, sc.ReflectVector() );
1381             }
1382             Color rc;
1383             rc = Color(rcol.r,rcol.g,rcol.b)*reflAmt;
1384             outClr += rc;
1385          }
1386          else
1387             return false;
1388 
1389       case ID_AM: // Ambient (value 0)
1390          outClr = GetAmbient();
1391          break;
1392 
1393       case ID_DI: // Diffuse (value 1)
1394          outClr = GetDiffuse();
1395          break;
1396 
1397       case ID_SP: // Specular (value 2)
1398          outClr = GetSpecular();
1399          break;
1400 
1401       case ID_SH: // Shininess (value 3).  In R3 and later this is called Glossiness.
1402          outClr.r = outClr.g = outClr.b = GetShininess();
1403          break;
1404 
1405       case ID_SS: // Shininess strength (value 4).  In R3 and later this is called Specular Level.
1406          outClr.r = outClr.g = outClr.b = GetShinStr();
1407          break;
1408 
1409       case ID_OP: // Opacity (value 6)
1410          outClr.r = outClr.g = outClr.b = GetXParency();
1411          break;
1412 
1413       default:
1414          // Should never happen
1415          //DbgAssert( false );
1416          return false;
1417          break;
1418    }
1419    return true;
1420 }
1421 
1422 //������������������������������������������������������������������������
1423 // The stdID parameter doesn't really have a meaning in this case.
1424 //
EvalMonoStdChannel(ShadeContext & sc,int stdID,float & outVal)1425 bool Matte::EvalMonoStdChannel
1426 (
1427    ShadeContext& sc, // describes context of evaluation
1428    int stdID,           // must be ID_AM, ect
1429    float& outVal        // output var
1430 )
1431 {
1432    switch ( stdID )
1433    {
1434       case ID_BU: // Bump (value 8)
1435       case ID_RR: // Refraction (value 10)
1436       case ID_DP: // Displacement (value 11)
1437       case ID_SI: // Self-illumination (value 5)
1438       case ID_FI: // Filter color (value 7)
1439          return false;
1440          break;
1441 
1442       case ID_RL: // Reflection (value 9)
1443          if ( sc.doMaps &&
1444                 reflmap &&
1445                 useReflMap &&
1446                 reflmap->IsOutputMeaningful(sc) )
1447          {
1448             if ( reflmap->HandleOwnViewPerturb() )
1449             {
1450                sc.TossCache(reflmap);
1451                outVal = reflmap->EvalMono(sc);
1452             }
1453             else
1454             {
1455                AColor rcol;
1456                rcol = sc.EvalEnvironMap( reflmap, sc.ReflectVector() );
1457                Color rc;
1458                rc = Color(rcol.r,rcol.g,rcol.b)*reflAmt;
1459                outVal = Intens(rc);
1460             }
1461          }
1462          else
1463             return false;
1464       break;
1465 
1466       case ID_AM: // Ambient (value 0)
1467          outVal = Intens( GetAmbient() );
1468          break;
1469 
1470       case ID_DI: // Diffuse (value 1)
1471          outVal = Intens( GetDiffuse() );
1472          break;
1473 
1474       case ID_SP: // Specular (value 2)
1475          outVal = Intens( GetSpecular() );
1476          break;
1477 
1478       case ID_SH: // Shininess (value 3).  In R3 and later this is called Glossiness.
1479          outVal = GetShininess();
1480          break;
1481 
1482       case ID_SS: // Shininess strength (value 4).  In R3 and later this is called Specular Level.
1483          outVal = GetShinStr();
1484          break;
1485 
1486       case ID_OP: // Opacity (value 6)
1487          outVal = GetXParency();
1488          break;
1489 
1490       default:
1491          // Should never happen
1492          //DbgAssert( false );
1493          return false;
1494          break;
1495    }
1496    return true;
1497 }
1498 #endif // NO_MTL_MATTESHADOW
1499