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