1 /**********************************************************************
2 *<
3 FILE: stdmtl.cpp
4
5 DESCRIPTION: default material class
6
7 CREATED BY: Dan Silva
8
9 HISTORY:
10
11 *> Copyright (c) 1994, All Rights Reserved.
12 **********************************************************************/
13
14
15 #include "buildver.h"
16 #include "mtlhdr.h"
17 #include "mtlres.h"
18 #include "mtlresOverride.h"
19 #include "stdmtl.h"
20 #include "gport.h"
21 #include "hsv.h"
22 #include "iColorMan.h"
23
24 #include "3dsmaxport.h"
25
26 static Shader *GetShader(int s);
27
28 #define HITHRESH 0.5f
29 #define LOTHRESH 0.1f
30
31
32 #if 1
33 // Quadratic
Soften(float r)34 static inline float Soften(float r) {
35 return r*(2.0f-r);
36 }
37 #else
38 // Cubic
Soften(float r)39 static inline float Soften(float r) {
40 return r*r*(3.0f-2.0f*r);
41 }
42 #endif
43
44 struct SIllumParams {
45 ULONG flags;
46 float sh_str, ph_exp, shine, softThresh;
47 Color amb,diff,spec;
48 Point3 N,V;
49 Color diffIllum,specIllum,ambIllum;
50 };
51
52 // Parameter block indices
53 #define PB_AMBIENT 0
54 #define PB_DIFFUSE 1
55 #define PB_SPECULAR 2
56 #define PB_SHININESS 3
57 #define PB_SHIN_STR 4
58 #define PB_SELFI 5
59 #define PB_OPAC 6
60 #define PB_OPFALL 7
61 #define PB_FILTER 8
62 #define PB_WIRESZ 9
63 #define PB_IOR 10
64 #define PB_BOUNCE 11
65 #define PB_STATFRIC 12
66 #define PB_SLIDFRIC 13
67 #define PB_DIMLEV 14
68 #define PB_DIMMULT 15
69 #define PB_SOFTEN 16
70
71 //#define OLDFILTER // scaling instead of additive
72
73 #define IDT_MYTIMER 1010
74 #define DRAGTHRESH 6
75 #define DITHER_WHEN_INACTIVE // avoids palette conflict probs
76 #define BUMP_DEF_AMT .30f
77
78 #define NCOLBOX 4
79 static int colID[NCOLBOX] = { IDC_STD_COLOR1, IDC_STD_COLOR2, IDC_STD_COLOR3, IDC_STD_COLOR4 };
80
81 // >>>> must become dynamic shader table
82 extern HINSTANCE hInstance;
83 static int shadeNameID[] = { IDS_DS_CONSTANT, IDS_DS_PHONG, IDS_DS_BLINN, IDS_DS_METAL };
84
GetPoint(LPARAM lp)85 static IPoint2 GetPoint(LPARAM lp) {
86 IPoint2 p;
87 MAKEPOINT(lp,p);
88 return p;
89 }
90 #define SET_HSV 1
91 #define SET_RGB 2
92 #define SET_BOTH (SET_HSV|SET_RGB)
93
94 #ifdef USE_STDMTL2_AS_STDMTL
95 static Class_ID stdmtlClassID(DMTL2_CLASS_ID,0);
96 #else
97 static Class_ID stdmtlClassID(DMTL_CLASS_ID,0);
98 #endif
99
100 int numStdMtls = 0;
101 class StdMtlClassDesc:public ClassDesc {
102 public:
IsPublic()103 int IsPublic() { return GetAppID() != kAPP_VIZR; }
Create(BOOL loading)104 void * Create(BOOL loading) { return new StdMtl(loading); }
ClassName()105 const TCHAR * ClassName() { return GetString(IDS_DS_STANDARD_CDESC); } // mjm - 2.3.99
SuperClassID()106 SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; }
ClassID()107 Class_ID ClassID() { return stdmtlClassID; }
Category()108 const TCHAR* Category() { return _T(""); }
109 };
110
111 static StdMtlClassDesc stdmtlCD;
112
GetStdMtlDesc()113 ClassDesc* GetStdMtlDesc() { return &stdmtlCD; }
114
115 static HIMAGELIST hLockButtons = NULL;
116
IsButtonChecked(HWND hWnd,int id)117 static BOOL IsButtonChecked(HWND hWnd,int id)
118 {
119 ICustButton *iBut;
120 BOOL res;
121 iBut = GetICustButton(GetDlgItem(hWnd,id));
122 res = iBut->IsChecked();
123 ReleaseICustButton(iBut);
124 return res;
125 }
126
CheckButton(HWND hWnd,int id,BOOL check)127 static void CheckButton(HWND hWnd,int id, BOOL check) {
128 ICustButton *iBut;
129 iBut = GetICustButton(GetDlgItem(hWnd,id));
130 iBut->SetCheck(check);
131 ReleaseICustButton(iBut);
132 }
133
SetupLockButton(HWND hWnd,int id,BOOL check)134 static void SetupLockButton(HWND hWnd,int id, BOOL check)
135 {
136 ICustButton *iBut;
137 iBut = GetICustButton(GetDlgItem(hWnd,id));
138 iBut->SetImage(hLockButtons,0,1,0,1,16,15);
139 iBut->SetType(CBT_CHECK);
140 ReleaseICustButton(iBut);
141 }
142
SetupPadLockButton(HWND hWnd,int id,BOOL check)143 static void SetupPadLockButton(HWND hWnd,int id, BOOL check) {
144 ICustButton *iBut;
145 iBut = GetICustButton(GetDlgItem(hWnd,id));
146 iBut->SetImage(hLockButtons,2,2,2,2,16,15);
147 iBut->SetType(CBT_CHECK);
148 ReleaseICustButton(iBut);
149 }
150
LoadStdMtlResources()151 static void LoadStdMtlResources()
152 {
153 static BOOL loaded=FALSE;
154 if (loaded) return;
155 loaded = TRUE;
156 HBITMAP hBitmap, hMask;
157
158 HINSTANCE hInst = hInstance;
159 hLockButtons = ImageList_Create(16, 15, TRUE, 2, 0);
160 hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_DMTL_BUTTONS));
161 hMask = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_DMTL_MASKBUTTONS));
162 ImageList_Add(hLockButtons,hBitmap,hMask);
163 DeleteObject(hBitmap);
164 DeleteObject(hMask);
165 }
166
167
PcToFrac(int pc)168 static inline float PcToFrac(int pc) {
169 return (float)pc/100.0f;
170 }
171
FracToPc(float f)172 static inline int FracToPc(float f) {
173 if (f<0.0) return (int)(100.0f*f - .5f);
174 else return (int) (100.0f*f + .5f);
175 }
176
177
178 static LRESULT CALLBACK HiliteWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );
179
180 #define NMBUTS 8
181 static int texMButtons[NMBUTS] = {
182 IDC_MAPON_AM, IDC_MAPON_DI, IDC_MAPON_SP, IDC_MAPON_FI,
183 IDC_MAPON_SH, IDC_MAPON_SS, IDC_MAPON_SI, IDC_MAPON_TR,
184 };
185
186 // This array gives the text map number for given MButton number
187 static int texmapFromMBut[NMBUTS] = { 0, 1, 2, 7, 3, 4, 5, 6 };
188
189 // This array gives the MButton number for given Texmap number
190 static int mButFromTexmap[NTEXMAPS] = { 0, 1, 2, 4, 5, 6, 7, 3, -1, -1, -1, -1 };
191
192 // >>>> these maps either need to be dynamic or allocated w/ a hard maximum.
193
194 static int texAmtID[NTEXMAPS] = {
195 IDC_AMT_AM, IDC_AMT_DI, IDC_AMT_SP, IDC_AMT_SH, IDC_AMT_SS,
196 IDC_AMT_SI, IDC_AMT_OP, IDC_AMT_FI, IDC_AMT_BU, IDC_AMT_RL, IDC_AMT_RR, IDC_AMT_DP
197 };
198
199 static int texOnID[NTEXMAPS] = {
200 IDC_USEMAP_AM, IDC_USEMAP_DI, IDC_USEMAP_SP, IDC_USEMAP_SH, IDC_USEMAP_SS,
201 IDC_USEMAP_SI, IDC_USEMAP_OP, IDC_USEMAP_FI, IDC_USEMAP_BU, IDC_USEMAP_RL, IDC_USEMAP_RR, IDC_USEMAP_DP
202 };
203
204 static int texSpinID[NTEXMAPS] = {
205 IDC_SPIN_AM, IDC_SPIN_DI, IDC_SPIN_SP, IDC_SPIN_SH, IDC_SPIN_SS,
206 IDC_SPIN_SI, IDC_SPIN_OP, IDC_SPIN_FI, IDC_SPIN_BU, IDC_SPIN_RL, IDC_SPIN_RR, IDC_SPIN_DP
207 };
208
209 static int texMapID[NTEXMAPS] = {
210 IDC_MAP_AM, IDC_MAP_DI, IDC_MAP_SP, IDC_MAP_SH, IDC_MAP_SS,
211 IDC_MAP_SI, IDC_MAP_OP, IDC_MAP_FI, IDC_MAP_BU, IDC_MAP_RL, IDC_MAP_RR, IDC_MAP_DP
212 };
213
214 static int texNameID[NTEXMAPS] = {
215 IDS_DS_AMBIENT, IDS_DS_DIFFUSE, IDS_DS_SPECULAR, IDS_DS_SHININESS, IDS_DS_SHIN_STR,
216 IDS_DS_SELFI, IDS_DS_TRANS, IDS_DS_FILTER, IDS_DS_BU, IDS_DS_RL, IDS_DS_RR, IDS_DS_DP
217 };
218
219 // which edit control enum
220 enum EditControl {Hc, Sc, Vc, Rc, Gc, Bc};
221
222
223 //-----------------------------------------------------------------------------
224 // Texmaps
225 //-----------------------------------------------------------------------------
226 /*******
227 //#define TEXMAPS_CLASS_ID 0x001200
228
229 //#ifdef USE_STDMTL2_AS_STDMTL
230 //#define TEXMAPS_CLASS_ID 0x001200+33
231 //#else
232 #define TEXMAPS_CLASS_ID 0x001200
233 //#endif
234
235 static Class_ID texmapsClassID(TEXMAPS_CLASS_ID,0);
236
237 class OldTexmapsClassDesc:public ClassDesc {
238 public:
239 int IsPublic() { return 0; }
240 void * Create(BOOL loading) { return new Texmaps(NULL); }
241 const TCHAR * ClassName() { return GetString(IDS_DS_CLASSTEXMAPS); }
242 SClass_ID SuperClassID() { return REF_MAKER_CLASS_ID; }
243 Class_ID ClassID() { return texmapsClassID; }
244 const TCHAR* Category() { return _T(""); }
245 };
246
247
248 class TexmapsClassDesc:public ClassDesc {
249 public:
250 int IsPublic() { return 0; }
251 void * Create(BOOL loading) { return new Texmaps(NULL); }
252 const TCHAR * ClassName() { return GetString(IDS_DS_CLASSTEXMAPS); }
253 // SClass_ID SuperClassID() { return REF_MAKER_CLASS_ID; }
254 SClass_ID SuperClassID() { return TEXMAP_CONTAINER_CLASS_ID; }
255 Class_ID ClassID() { return texmapsClassID; }
256 const TCHAR* Category() { return _T(""); }
257 };
258
259 TexmapSlot::TexmapSlot() {
260 amount = 1.0f;
261 map = NULL;
262 mapOn = FALSE;
263 amtCtrl=NULL;
264 }
265
266 void TexmapSlot::Update(TimeValue t,Interval& ivalid) {
267 if (IsActive())
268 map->Update(t,ivalid);
269 if (amtCtrl) {
270 amtCtrl->GetValue(t,&amount,ivalid);
271 }
272 }
273
274 float TexmapSlot::GetAmount(TimeValue t) {
275 Interval v;
276 float f;
277 if (amtCtrl) {
278 amtCtrl->GetValue(t,&f,v);
279 return f;
280 }
281 else return amount;
282 }
283
284 Texmaps::Texmaps() {
285 loadingOld = FALSE;
286 client = NULL;
287 }
288
289
290 Texmaps::Texmaps(MtlBase *mb) {
291 loadingOld = FALSE;
292 client = mb;
293 }
294
295
296 static TexmapsClassDesc texmapsCD;
297
298 ClassDesc* GetTexmapsDesc() { return &texmapsCD; }
299
300 static OldTexmapsClassDesc oldtexmapsCD;
301
302 ClassDesc* GetOldTexmapsDesc() { return &oldtexmapsCD; }
303
304 Class_ID Texmaps::ClassID() { return texmapsClassID; }
305
306 int Texmaps::NumSubs() { return NTEXMAPS*2; }
307
308 Animatable* Texmaps::SubAnim(int i) {
309 if (i&1)
310 return txmap[i/2].map;
311 else
312 return txmap[i/2].amtCtrl;
313 }
314
315 TSTR Texmaps::SubAnimName(int i) {
316 if (i&1)
317 return client->GetSubTexmapTVName(i/2);
318 else {
319 TSTR nm;
320 nm = GetString(texNameID[i/2]);
321 nm += TSTR(GetString(IDS_DS_AMOUNT));
322 return nm;
323 }
324 }
325
326 RefTargetHandle Texmaps::GetReference(int i) {
327 if (i&1)
328 return txmap[i/2].map;
329 else
330 return txmap[i/2].amtCtrl;
331 }
332
333 void Texmaps::SetReference(int i, RefTargetHandle rtarg) {
334 if (loadingOld)
335 txmap[i].map = (Texmap*)rtarg;
336 else {
337 if (i&1)
338 txmap[i/2].map = (Texmap*)rtarg;
339 else
340 txmap[i/2].amtCtrl = (Control*)rtarg;
341 }
342 }
343
344 void Texmaps::DeleteThis() { delete this;}
345
346 RefResult Texmaps::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
347 PartID& partID, RefMessage message ) {
348 switch (message) {
349 case REFMSG_GET_PARAM_DIM: {
350 GetParamDim *gpd = (GetParamDim*)partID;
351 gpd->dim = defaultDim;
352 break;
353 }
354 case REFMSG_GET_PARAM_NAME: {
355 GetParamName *gpn = (GetParamName*)partID;
356 return REF_STOP;
357 }
358 }
359 return(REF_SUCCEED);
360 }
361
362 void Texmaps::RescaleWorldUnits(float f) {
363 if (TestAFlag(A_WORK1))
364 return;
365 SetAFlag(A_WORK1);
366 // This code will be replaced in particular implementations
367 for (int i=0; i<NumRefs(); i++) {
368 if ( (i&1) ==0)
369 continue; // skip the amount controllers
370 ReferenceMaker *srm = GetReference(i);
371 if (srm) {
372 srm->RescaleWorldUnits(f);
373 }
374 }
375
376 }
377
378 RefTargetHandle Texmaps::Clone(RemapDir &remap) {
379 Texmaps *tm = new Texmaps(NULL);
380 for (int i = 0; i<NTEXMAPS; i++) {
381 tm->txmap[i].amount = txmap[i].amount;
382 tm->txmap[i].mapOn = txmap[i].mapOn;
383 tm->txmap[i].map = NULL;
384 if (txmap[i].amtCtrl)
385 tm->ReplaceReference(2*i,remap.CloneRef(txmap[i].amtCtrl));
386 if (txmap[i].map)
387 tm->ReplaceReference(2*i+1,remap.CloneRef(txmap[i].map));
388 }
389 BaseClone(this, tm, remap);
390 return tm;
391 }
392
393 #define TEX_OLD_ONOFF_CHUNK 0x5002
394 #define TEX_ONOFF_CHUNK 0x5003
395 #define TEX_AMT0 0x5100
396 #define TEX_AMT1 0x5101
397 #define TEX_AMT2 0x5102
398 #define TEX_AMT3 0x5103
399 #define TEX_AMT4 0x5104
400 #define TEX_AMT5 0x5105
401 #define TEX_AMT6 0x5106
402 #define TEX_AMT7 0x5107
403 #define TEX_AMT8 0x5108
404 #define TEX_AMT9 0x5109
405 #define TEX_AMTA 0x510A
406
407 IOResult Texmaps::Save(ISave *isave) {
408 isave->BeginChunk(TEX_ONOFF_CHUNK);
409 ULONG nb,f=0;
410 for ( int i=0; i<NTEXMAPS; i++)
411 if (txmap[i].mapOn) f|= (1<<i);
412 isave->Write(&f,sizeof(f),&nb);
413 isave->EndChunk();
414
415 for ( i=0; i<NTEXMAPS; i++) {
416 if (txmap[i].amount!=1.0f) {
417 isave->BeginChunk(TEX_AMT0+i);
418 isave->Write(&txmap[i].amount,sizeof(float),&nb);
419 isave->EndChunk();
420 }
421 }
422 return IO_OK;
423 }
424
425 class TexmapsPostLoad : public PostLoadCallback {
426 public:
427 Texmaps *tm;
428 TexmapsPostLoad(Texmaps *b) {tm=b;}
429 void proc(ILoad *iload) { tm->loadingOld = FALSE; delete this; }
430 };
431
432
433 IOResult Texmaps::Load(ILoad *iload) {
434 ULONG nb;
435 int id;
436 IOResult res;
437 while (IO_OK==(res=iload->OpenChunk())) {
438 switch(id = iload->CurChunkID()) {
439 case TEX_OLD_ONOFF_CHUNK:
440 iload->SetObsolete();
441 iload->RegisterPostLoadCallback(new TexmapsPostLoad(this));
442 loadingOld = TRUE;
443 case TEX_ONOFF_CHUNK:
444 {
445 ULONG f;
446 res = iload->Read(&f,sizeof(f), &nb);
447 for (int i=0; i<NTEXMAPS; i++)
448 txmap[i].mapOn = (f&(1<<i))?1:0;
449 }
450 break;
451 case TEX_AMT0: case TEX_AMT1:
452 case TEX_AMT2: case TEX_AMT3:
453 case TEX_AMT4: case TEX_AMT5:
454 case TEX_AMT6: case TEX_AMT7:
455 case TEX_AMT8: case TEX_AMT9:
456 case TEX_AMTA:
457 res = iload->Read(&txmap[id-TEX_AMT0].amount,sizeof(float), &nb);
458 break;
459 }
460 iload->CloseChunk();
461 if (res!=IO_OK)
462 return res;
463 }
464 return IO_OK;
465
466 }
467 //-----------------------------------------------------------------------------
468 **************/
469 //-----------------------------------------------------------------------------
470 //class StdMtlDlg;
471
472
473 //-----------------------------------------------------------------------------
474 // StdMtlDlg
475 //-----------------------------------------------------------------------------
476 class StdMtlDlg: public ParamDlg {
477 public:
478 HWND hwmedit; // window handle of the materials editor dialog
479 IMtlParams *ip;
480 StdMtl *theMtl; // current mtl being edited.
481 HWND hPanelBasic; // Rollup panel
482 HWND hPanelExtra; // Rollup panel
483 HWND hPanelTexmap; // Rollup panel
484 HWND hPanelDynam; // Rollup panel
485 HWND hwHilite; // the hilite window
486 HPALETTE hOldPal;
487 TimeValue curTime;
488 int instCopy;
489 int iStart;
490 Rect texRect;
491 int isActive;
492 IPoint2 pDown,pDrag;
493 IPoint2 pLast;
494 BOOL dragging,dragAbort;
495 Rect colBox[NCOLBOX];
496 IColorSwatch *cs[NCOLBOX];
497 BOOL animPalOn;
498 BOOL valid;
499 int editingColor; //0= amb,1= diff,2= spec, 3 = filterCol
500 DWORD curRGB;
501 int H,S,V;
502 ISpinnerControl *hSpin,*sSpin,*vSpin;
503 ISpinnerControl *rSpin,*gSpin,*bSpin;
504 ISpinnerControl *softSpin;
505 ISpinnerControl *shSpin, *ssSpin, *siSpin, *trSpin, *tfSpin, *wireSizeSpin, *iorSpin;
506 ISpinnerControl *dimSpin, *dimMultSpin;
507 ISpinnerControl* texAmtSpin[NTEXMAPS];
508 ISpinnerControl *iBounce, *iStatFrict, *iSlidFrict;
509 ICustButton* texMBut[NMBUTS];
510 ICustButton *iBut[NTEXMAPS];
511 TexDADMgr dadMgr;
512
513 StdMtlDlg(HWND hwMtlEdit, IMtlParams *imp, StdMtl *m);
514 ~StdMtlDlg();
515 void BuildDialog(); // put up the dialog
516 void Invalidate();
517 INT_PTR BasicPanelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );
518 INT_PTR ExtraPanelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );
519 INT_PTR TexmapPanelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );
520 INT_PTR DynamPanelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );
521 void ActivateDlg(BOOL onOff);
522 void LoadDialog(BOOL draw); // stuff params into dialog
523 void SetEditColor(int i); //0=amb, 1=diff, 2=spec, 3=filterColor
524 void SetRGB(DWORD rgb);
525 void UpdateColFromSpin(HWND hwndDlg,int indx, ISpinnerControl *spin );
526 void UpdateColControls( int which);
527 void UpdateColSwatches();
528 void AnimPalette(HDC hdc);
529 Color MtlColor(int i);
530 TCHAR *ColorName(int i);
531 void SetMtlColor(int i, Color c);
532 void UpdateMBut(int i);
533 void ReloadDialog();
534 void EnablePhongStuff();
535 void DrawHilite(HDC hdc, Rect& rect);
536 void GenDrawHilite(HDC hdc, Rect& rect, SShader &sh);
537 void UpdateHilite();
538 void SetLockAD(BOOL lock);
539 void UpdateLockADTex();
540 void SetLockDS(BOOL lock);
541 void SetLockADTex(BOOL lock);
542 void UpdateMtlDisplay();
543 void UpdateTexmapDisplay(int i);
544 void UpdateTexmaps();
545 void FixFilterButtons();
546 void UpdateControlFor(int np);
547 void UpdateColorStuff();
KeyAtCurTime(int id)548 BOOL KeyAtCurTime(int id) { return theMtl->KeyAtTime(id,curTime); }
549 // methods inherited from ParamDLg:
ClassID()550 Class_ID ClassID() {return stdmtlClassID; }
551 void SetThing(ReferenceTarget *m);
GetThing()552 ReferenceTarget* GetThing() { return (ReferenceTarget*)theMtl; }
DeleteThis()553 void DeleteThis() { delete this; }
554 void SetTime(TimeValue t);
555 int FindSubTexFromHWND(HWND hw);
556 };
557
558 static int PB_ID[4] = { PB_AMBIENT, PB_DIFFUSE, PB_SPECULAR, PB_FILTER };
559
FindSubTexFromHWND(HWND hw)560 int StdMtlDlg::FindSubTexFromHWND(HWND hw) {
561 for (int i=0; i<NTEXMAPS; i++) {
562 if (hw == iBut[i]->GetHwnd())
563 return i;
564 }
565 for (int i=0; i<NMBUTS; i++) {
566 if (hw == texMBut[i]->GetHwnd())
567 return texmapFromMBut[i];
568 }
569 return -1;
570 }
571
572
573 //-------------------------------------------------------------------
574
575
StdMtlDlg(HWND hwMtlEdit,IMtlParams * imp,StdMtl * m)576 StdMtlDlg::StdMtlDlg(HWND hwMtlEdit, IMtlParams *imp, StdMtl *m) {
577 dadMgr.Init(this);
578 hwmedit = hwMtlEdit;
579 hPanelBasic = hPanelExtra = hPanelTexmap = hPanelDynam = NULL;
580 hOldPal = NULL;
581 theMtl = m;
582 ip = imp;
583 valid = FALSE;
584 editingColor = 1; // default to diffuse
585 animPalOn = 1;
586 isActive = 0;
587 instCopy = FALSE;
588 for (int i=0; i<NTEXMAPS; i++) iBut[i] = NULL;
589 }
590
591
592
Invalidate()593 void StdMtlDlg::Invalidate()
594 {
595 valid = FALSE;
596 InvalidateRect(hPanelBasic,NULL,0);
597 InvalidateRect(hPanelExtra,NULL,0);
598 InvalidateRect(hPanelTexmap,NULL,0);
599 #ifndef NO_MTL_DYNAMICS_PARAMETERS
600 InvalidateRect(hPanelDynam,NULL,0);
601 #endif
602 }
603
AnimPalette(HDC hdc)604 void StdMtlDlg::AnimPalette(HDC hdc) {
605 #if 0
606 if (animPalOn) {
607 GetGPort()->PlugPalette(hdc);
608 GetGPort()->AnimPalette(hdc);
609 }
610 #endif
611 }
612
613 static TCHAR blnk[] = _T(" ");
614 static TCHAR lcm[] = _T("m");
615 static TCHAR ucm[] = _T("M");
616
UpdateMBut(int j)617 void StdMtlDlg::UpdateMBut(int j) {
618 int i = mButFromTexmap[j];
619 if (i<0) return;
620 TCHAR* s = (*theMtl->maps)[j].map?((*theMtl->maps)[j].mapOn?ucm:lcm):blnk;
621 texMBut[i]->SetText(s);
622 Texmap *t = (*theMtl->maps)[j].map;
623 TSTR nm;
624 if (t) nm = t->GetFullName();
625 else nm = GetString(IDS_DS_NONE);
626 texMBut[i]->SetTooltip(TRUE,nm);
627 }
628
ReloadDialog()629 void StdMtlDlg::ReloadDialog() {
630 Interval v;
631 theMtl->Update(ip->GetTime(),v);
632 LoadDialog(FALSE);
633 }
634
FixFilterButtons()635 void StdMtlDlg::FixFilterButtons() {
636 BOOL b = (theMtl->flags&STDMTL_FILT_TRANSP)?1:0;
637 EnableWindow(GetDlgItem(hPanelBasic,IDC_FILT), b);
638 EnableWindow(GetDlgItem(hPanelBasic,IDC_MAPON_FI), b);
639 }
640
SetTime(TimeValue t)641 void StdMtlDlg::SetTime(TimeValue t) {
642 if (t!=curTime) {
643 curTime = t;
644 Interval v;
645 theMtl->Update(ip->GetTime(),v);
646 LoadDialog(TRUE);
647 }
648 }
649
650
651 // >>>> SelfIllum Color ?????
MtlColor(int i)652 Color StdMtlDlg::MtlColor(int i) {
653 switch(i) {
654 case 0: return theMtl->GetAmbient();
655 case 1: return theMtl->GetDiffuse();
656 case 2: return theMtl->GetSpecular();
657 case 3: return theMtl->GetFilter();
658 default: return Color(0,0,0);
659 }
660 }
661
ColorName(int i)662 TCHAR *StdMtlDlg::ColorName(int i) {
663 switch(i) {
664 case 0: return GetString(IDS_DS_AMBIENT);
665 case 1: return GetString(IDS_DS_DIFFUSE);
666 case 2: return GetString(IDS_DS_SPECULAR);
667 default: return GetString(IDS_DS_FILTER);
668 }
669 }
670
SetMtlColor(int i,Color c)671 void StdMtlDlg::SetMtlColor(int i, Color c) {
672 switch(i) {
673 case 0:
674 theMtl->SetAmbient(c,curTime);
675 if (theMtl->GetFlag(STDMTL_LOCK_AD)) {
676 theMtl->SetDiffuse(c,curTime);
677 cs[1]->SetColor(MtlColor(1));
678 if (theMtl->GetFlag(STDMTL_LOCK_DS)) {
679 theMtl->SetSpecular(c,curTime);
680 cs[2]->SetColor(MtlColor(2));
681 }
682 }
683 break;
684 case 1:
685 theMtl->SetDiffuse(c,curTime);
686 if (theMtl->GetFlag(STDMTL_LOCK_AD)) {
687 theMtl->SetAmbient(c,curTime);
688 cs[0]->SetColor(MtlColor(0));
689 }
690 if (theMtl->GetFlag(STDMTL_LOCK_DS)) {
691 theMtl->SetSpecular(c,curTime);
692 cs[2]->SetColor(MtlColor(2));
693 }
694 break;
695 case 2:
696 theMtl->SetSpecular(c,curTime);
697 if (theMtl->GetFlag(STDMTL_LOCK_DS)) {
698 theMtl->SetDiffuse(c,curTime);
699 cs[1]->SetColor(MtlColor(1));
700 if (theMtl->GetFlag(STDMTL_LOCK_AD)) {
701 theMtl->SetAmbient(c,curTime);
702 cs[0]->SetColor(MtlColor(0));
703 }
704 }
705 break;
706 case 3:
707 theMtl->SetFilter(c,curTime);
708 break;
709 }
710
711 }
712
~StdMtlDlg()713 StdMtlDlg::~StdMtlDlg() {
714 int i;
715 for (i=0; i<NCOLBOX; i++) {
716 ReleaseIColorSwatch(cs[i]);
717 }
718 if (hPanelBasic) {
719 HDC hdc = GetDC(hPanelBasic);
720 GetGPort()->RestorePalette(hdc, hOldPal);
721 ReleaseDC(hPanelBasic,hdc);
722 }
723
724 theMtl->SetFlag(STDMTL_ROLLUP1_OPEN,ip->IsRollupPanelOpen(hPanelBasic));
725 theMtl->SetFlag(STDMTL_ROLLUP2_OPEN,ip->IsRollupPanelOpen(hPanelExtra));
726 theMtl->SetFlag(STDMTL_ROLLUP3_OPEN,ip->IsRollupPanelOpen(hPanelTexmap));
727 #ifndef NO_MTL_DYNAMICS_PARAMETERS
728 theMtl->SetFlag(STDMTL_ROLLUP4_OPEN,ip->IsRollupPanelOpen(hPanelDynam));
729 #endif
730 theMtl->rollScroll = ip->GetRollupScrollPos();
731
732 theMtl->SetParamDlg(NULL);
733 for (i=0; i<NTEXMAPS; i++)
734 ReleaseISpinner(texAmtSpin[i]);
735
736 for (i=0; i<NMBUTS; i++)
737 ReleaseICustButton(texMBut[i]);
738
739 for (i=0; i<NTEXMAPS; i++) {
740 ReleaseICustButton(iBut[i]);
741 iBut[i] = NULL;
742 }
743
744 ReleaseISpinner(hSpin);
745 ReleaseISpinner(sSpin);
746 ReleaseISpinner(vSpin);
747 ReleaseISpinner(rSpin);
748 ReleaseISpinner(gSpin);
749 ReleaseISpinner(bSpin);
750 ReleaseISpinner(softSpin);
751 ReleaseISpinner(shSpin);
752 ReleaseISpinner(ssSpin);
753 ReleaseISpinner(siSpin);
754 ReleaseISpinner(trSpin);
755 ReleaseISpinner(tfSpin);
756 ReleaseISpinner(wireSizeSpin);
757 ReleaseISpinner(iorSpin);
758 ReleaseISpinner(dimSpin);
759 ReleaseISpinner(dimMultSpin);
760 #ifndef NO_MTL_DYNAMICS_PARAMETERS
761 ReleaseISpinner(iBounce);
762 ReleaseISpinner(iStatFrict);
763 ReleaseISpinner(iSlidFrict);
764 #endif
765
766 DLSetWindowLongPtr(hPanelBasic, NULL);
767 DLSetWindowLongPtr(hPanelExtra, NULL);
768 DLSetWindowLongPtr(hPanelTexmap, NULL);
769 #ifndef NO_MTL_DYNAMICS_PARAMETERS
770 DLSetWindowLongPtr(hPanelDynam, NULL);
771 #endif
772 hPanelBasic = hPanelExtra = hPanelTexmap = hPanelDynam = NULL;
773 }
774
775
UpdateColorStuff()776 void StdMtlDlg::UpdateColorStuff() {
777 curRGB = MtlColor(editingColor).toRGB();
778 RGBtoHSV(curRGB, &H, &S, &V);
779 UpdateColControls(SET_HSV|SET_RGB);
780 }
781
UpdateControlFor(int np)782 void StdMtlDlg::UpdateControlFor(int np) {
783 Point3 p;
784 Interval v;
785 TimeValue t = ip->GetTime();
786 theMtl->Update(t, v);
787 switch(np) {
788 case PB_AMBIENT:
789 UpdateColSwatches();
790 if (editingColor==0)
791 UpdateColorStuff();
792 cs[0]->SetKeyBrackets(theMtl->KeyAtTime(PB_AMBIENT,curTime));
793 break;
794 case PB_DIFFUSE:
795 UpdateColSwatches();
796 if (editingColor==1)
797 UpdateColorStuff();
798 cs[1]->SetKeyBrackets(theMtl->KeyAtTime(PB_DIFFUSE,curTime));
799 break;
800 case PB_SPECULAR:
801 UpdateColSwatches();
802 if (editingColor==2)
803 UpdateColorStuff();
804 cs[2]->SetKeyBrackets(theMtl->KeyAtTime(PB_SPECULAR,curTime));
805 break;
806 case PB_SHININESS:
807 shSpin->SetValue(FracToPc(theMtl->GetShininess()),FALSE);
808 shSpin->SetKeyBrackets(theMtl->KeyAtTime(PB_SHININESS,curTime));
809 break;
810 case PB_SHIN_STR:
811 ssSpin->SetValue(FracToPc(theMtl->GetShinStr()),FALSE);
812 ssSpin->SetKeyBrackets(theMtl->KeyAtTime(PB_SHIN_STR,curTime));
813 break;
814 case PB_SOFTEN:
815 softSpin->SetValue(theMtl->GetSoftenLevel(curTime),FALSE);
816 softSpin->SetKeyBrackets(theMtl->KeyAtTime(PB_SOFTEN,curTime));
817 break;
818
819 // >>>>
820 case PB_SELFI:
821 siSpin->SetValue(FracToPc(theMtl->GetSelfIll()),FALSE);
822 siSpin->SetKeyBrackets(theMtl->KeyAtTime(PB_SELFI,curTime));
823 break;
824 case PB_OPAC:
825 trSpin->SetValue(FracToPc(theMtl->GetOpacity()),FALSE);
826 trSpin->SetKeyBrackets(theMtl->KeyAtTime(PB_OPAC,curTime));
827 break;
828 case PB_OPFALL:
829 tfSpin->SetValue(FracToPc(theMtl->GetOpacFalloff()),FALSE);
830 tfSpin->SetKeyBrackets(theMtl->KeyAtTime(PB_OPFALL,curTime));
831 break;
832 case PB_FILTER:
833 UpdateColSwatches();
834 if (editingColor==3)
835 UpdateColorStuff();
836 cs[3]->SetKeyBrackets(theMtl->KeyAtTime(PB_FILTER,curTime));
837 break;
838 case PB_WIRESZ:
839 wireSizeSpin->SetValue( theMtl->WireSize(),FALSE);
840 wireSizeSpin->SetKeyBrackets(theMtl->KeyAtTime(PB_WIRESZ,curTime));
841 break;
842 case PB_IOR:
843 iorSpin->SetValue( theMtl->GetIOR(),FALSE);
844 iorSpin->SetKeyBrackets(KeyAtCurTime(PB_IOR));
845 break;
846 #ifndef NO_MTL_DYNAMICS_PARAMETERS
847 case PB_BOUNCE:
848 iBounce->SetValue(theMtl->GetDynamicsProperty(curTime,0,DYN_BOUNCE),FALSE);
849 iBounce->SetKeyBrackets(KeyAtCurTime(PB_BOUNCE));
850 break;
851 case PB_STATFRIC:
852 iStatFrict->SetValue(theMtl->GetDynamicsProperty(curTime,0,DYN_STATIC_FRICTION),FALSE);
853 iStatFrict->SetKeyBrackets(KeyAtCurTime(PB_STATFRIC));
854 break;
855 case PB_SLIDFRIC:
856 iSlidFrict->SetValue(theMtl->GetDynamicsProperty(curTime,0,DYN_SLIDING_FRICTION),FALSE);
857 iSlidFrict->SetKeyBrackets(KeyAtCurTime(PB_SLIDFRIC));
858 break;
859 #endif
860 case PB_DIMLEV:
861 dimSpin->SetValue( theMtl->GetDimIntens(curTime),FALSE);
862 dimSpin->SetKeyBrackets(KeyAtCurTime(PB_DIMLEV));
863 break;
864 case PB_DIMMULT:
865 dimMultSpin->SetValue( theMtl->GetDimMult(curTime),FALSE);
866 dimMultSpin->SetKeyBrackets(KeyAtCurTime(PB_DIMMULT));
867 break;
868 }
869 }
870
871
HiliteWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)872 static LRESULT CALLBACK HiliteWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) {
873 LONG_PTR id = GetWindowLongPtr(hwnd,GWLP_ID);
874 HWND hwpar = GetParent(hwnd);
875 StdMtlDlg *theDlg = DLGetWindowLongPtr<StdMtlDlg *>(hwpar);
876 if (theDlg==NULL) return FALSE;
877 switch (msg) {
878 case WM_COMMAND:
879 break;
880 case WM_MOUSEMOVE:
881 break;
882 case WM_LBUTTONUP:
883 break;
884 case WM_PAINT:
885 {
886 PAINTSTRUCT ps;
887 Rect rect;
888 HDC hdc = BeginPaint( hwnd, &ps );
889 if (!IsRectEmpty(&ps.rcPaint)) {
890 GetClientRect( hwnd, &rect );
891 theDlg->DrawHilite(hdc, rect);
892 }
893 EndPaint( hwnd, &ps );
894 }
895 break;
896 case WM_CREATE:
897 case WM_DESTROY:
898 break;
899 }
900 return DefWindowProc(hwnd,msg,wParam,lParam);
901 }
902
ColIDToIndex(int id)903 int ColIDToIndex(int id) {
904 switch (id) {
905 case IDC_STD_COLOR1: return 0;
906 case IDC_STD_COLOR2: return 1;
907 case IDC_STD_COLOR3: return 2;
908 case IDC_STD_COLOR4: return 3;
909 default: return 0;
910 }
911 }
912
913
ShadeFromListID(int i)914 static int ShadeFromListID( int i) {
915 switch (i) {
916 case 0: return SHADE_CONST;
917 case 1: return SHADE_PHONG;
918 case 2: return SHADE_BLINN;
919 case 3: return SHADE_METAL;
920 default: return SHADE_PHONG;
921 }
922 }
923
ListIDFromShade(int i)924 static int ListIDFromShade( int i) {
925 switch (i) {
926 case SHADE_CONST: return 0;
927 case SHADE_PHONG: return 1;
928 case SHADE_BLINN: return 2;
929 case SHADE_METAL: return 3;
930 default: return 1;
931 }
932 }
933
BasicPanelProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)934 INT_PTR StdMtlDlg::BasicPanelProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam ) {
935 int id = LOWORD(wParam);
936 int code = HIWORD(wParam);
937 switch (msg) {
938 case WM_INITDIALOG:
939 {
940 int i;
941
942 HDC theHDC = GetDC(hwndDlg);
943 hOldPal = GetGPort()->PlugPalette(theHDC);
944 ReleaseDC(hwndDlg,theHDC);
945
946 for (i=0; i<NCOLBOX; i++) {
947 cs[i] = GetIColorSwatch(GetDlgItem(hwndDlg, colID[i]),
948 MtlColor(i), ColorName(i));
949 }
950
951 hwHilite = GetDlgItem(hwndDlg, IDC_HIGHLIGHT);
952 DLSetWindowLongPtr( hwHilite, HiliteWndProc);
953
954 HWND hwndShading = GetDlgItem(hwndDlg, IDC_SHADING);
955 for (i=0; i<NSHADES; i++)
956 SendMessage(hwndShading, CB_ADDSTRING, 0, (LPARAM)GetString(shadeNameID[i]));
957
958 hSpin = SetupIntSpinner(hwndDlg, IDC_H_SPIN, IDC_H_EDIT, 0,255, 0);
959 sSpin = SetupIntSpinner(hwndDlg, IDC_S_SPIN, IDC_S_EDIT, 0,255, 0);
960 vSpin = SetupIntSpinner(hwndDlg, IDC_V_SPIN, IDC_V_EDIT, 0,255, 0);
961
962 rSpin = SetupIntSpinner(hwndDlg, IDC_R_SPIN, IDC_R_EDIT, 0,255, 0);
963 gSpin = SetupIntSpinner(hwndDlg, IDC_G_SPIN, IDC_G_EDIT, 0,255, 0);
964 bSpin = SetupIntSpinner(hwndDlg, IDC_B_SPIN, IDC_B_EDIT, 0,255, 0);
965
966 shSpin = SetupIntSpinner(hwndDlg, IDC_SH_SPIN, IDC_SH_EDIT, 0,100, 0);
967 ssSpin = SetupIntSpinner(hwndDlg, IDC_SS_SPIN, IDC_SS_EDIT, 0,999, 0);
968 siSpin = SetupIntSpinner(hwndDlg, IDC_SI_SPIN, IDC_SI_EDIT, 0,100, 0);
969 trSpin = SetupIntSpinner(hwndDlg, IDC_TR_SPIN, IDC_TR_EDIT, 0,100, 0);
970
971 for (int j=0; j<NMBUTS; j++) {
972 texMBut[j] = GetICustButton(GetDlgItem(hwndDlg,texMButtons[j]));
973 texMBut[j]->SetRightClickNotify(TRUE);
974 texMBut[j]->SetDADMgr(&dadMgr);
975 }
976
977 softSpin = SetupFloatSpinner(hwndDlg, IDC_SOFT_SPIN, IDC_SOFT_EDIT, 0.0f,1.0f,0.0f,.01f);
978
979 SetupLockButton(hwndDlg,IDC_LOCK_AD,FALSE);
980 SetupLockButton(hwndDlg,IDC_LOCK_DS,FALSE);
981 SetupPadLockButton(hwndDlg,IDC_LOCK_ADTEX, TRUE);
982 return TRUE;
983 }
984 break;
985 case WM_COMMAND:
986 {
987 for ( int i=0; i<NMBUTS; i++) {
988 if (id == texMButtons[i]) {
989 PostMessage(hwmedit,WM_TEXMAP_BUTTON, texmapFromMBut[i],(LPARAM)theMtl);
990 goto exit;
991 }
992 }
993 }
994 switch (id) {
995 case IDC_SHADING: {
996 if (code==CBN_SELCHANGE) {
997 int newshade = ShadeFromListID(SendMessage( GetDlgItem(hwndDlg,IDC_SHADING), CB_GETCURSEL, 0, 0 ));
998 int oldshade = theMtl->GetShaderId();
999 if ( oldshade != newshade ) {
1000 theMtl->SetShaderId( newshade );
1001 softSpin->Enable(theMtl->shading!=SHADE_METAL);
1002 UpdateMtlDisplay();
1003 }
1004 }
1005 break;
1006 }
1007
1008 case IDC_AMB:
1009 case IDC_DIFF:
1010 case IDC_SPEC:
1011 case IDC_FILT:
1012 // >>>> SELFI
1013 SetEditColor(id-IDC_AMB);
1014 break;
1015
1016 case IDC_WIRE:
1017 theMtl->SetFlag(STDMTL_WIRE, GetCheckBox(hwndDlg, IDC_WIRE));
1018 theMtl->NotifyChanged();
1019 UpdateMtlDisplay();
1020 break;
1021
1022 case IDC_FACE_MAP:
1023 theMtl->SetFlag(STDMTL_FACEMAP, GetCheckBox(hwndDlg, IDC_FACE_MAP));
1024 UpdateMtlDisplay();
1025 theMtl->NotifyChanged();
1026 break;
1027
1028 case IDC_2SIDE:
1029 theMtl->SetFlag(STDMTL_2SIDE, GetCheckBox(hwndDlg, IDC_2SIDE));
1030 theMtl->NotifyChanged();
1031 UpdateMtlDisplay();
1032 break;
1033
1034 case IDC_SUPER_SAMP:
1035 theMtl->SetFlag(STDMTL_SSAMP, GetCheckBox(hwndDlg, IDC_SUPER_SAMP));
1036 break;
1037
1038 case IDC_SOFTEN:
1039 theMtl->SetFlag(STDMTL_SOFTEN, GetCheckBox(hwndDlg, id));
1040 theMtl->NotifyChanged();
1041 UpdateMtlDisplay();
1042 break;
1043
1044 // case IDC_OLDSPEC:
1045 // theMtl->SetFlag(STDMTL_OLDSPEC, GetCheckBox(hwndDlg, id));
1046 // theMtl->NotifyChanged();
1047 // UpdateMtlDisplay();
1048 // break;
1049
1050 case IDC_LOCK_AD:
1051 SetLockAD(IsButtonChecked(hwndDlg, IDC_LOCK_AD));
1052 break;
1053 case IDC_LOCK_DS:
1054 SetLockDS(IsButtonChecked(hwndDlg, IDC_LOCK_DS));
1055 break;
1056 case IDC_LOCK_ADTEX:
1057 SetLockADTex(IsButtonChecked(hwndDlg, IDC_LOCK_ADTEX));
1058 break;
1059 }
1060 break;
1061 case CC_COLOR_SEL:
1062 {
1063 int id = LOWORD(wParam);
1064 SetEditColor(ColIDToIndex(id));
1065 }
1066 break;
1067 case CC_COLOR_DROP:
1068 {
1069 int id = LOWORD(wParam);
1070 SetEditColor(ColIDToIndex(id));
1071 }
1072 break;
1073 case CC_COLOR_BUTTONDOWN:
1074 theHold.Begin();
1075 break;
1076 case CC_COLOR_BUTTONUP:
1077 if (HIWORD(wParam)) theHold.Accept(GetString(IDS_DS_PARAMCHG));
1078 else theHold.Cancel();
1079 break;
1080 case CC_COLOR_CHANGE:
1081 {
1082 int id = LOWORD(wParam);
1083 int buttonUp = HIWORD(wParam);
1084 int n = ColIDToIndex(id);
1085 if (buttonUp) theHold.Begin();
1086 SetRGB(cs[n]->GetColor());
1087 SetMtlColor(n,Color(curRGB));
1088 UpdateColControls(SET_BOTH);
1089 theMtl->NotifyChanged();
1090 if (buttonUp) {
1091 theHold.Accept(GetString(IDS_DS_PARAMCHG));
1092 UpdateMtlDisplay();
1093 }
1094 }
1095 break;
1096 case WM_PAINT:
1097 if (!valid) {
1098 valid = TRUE;
1099 ReloadDialog();
1100 }
1101 return FALSE;
1102 case WM_CLOSE:
1103 break;
1104 case WM_DESTROY:
1105 break;
1106 case CC_SPINNER_CHANGE:
1107 if (!theHold.Holding()) theHold.Begin();
1108 switch (id) {
1109 case IDC_R_SPIN: UpdateColFromSpin(hwndDlg, Rc, rSpin); break;
1110 case IDC_G_SPIN: UpdateColFromSpin(hwndDlg, Gc, gSpin); break;
1111 case IDC_B_SPIN: UpdateColFromSpin(hwndDlg, Bc, bSpin); break;
1112 case IDC_H_SPIN: UpdateColFromSpin(hwndDlg, Hc, hSpin); break;
1113 case IDC_S_SPIN: UpdateColFromSpin(hwndDlg, Sc, sSpin); break;
1114 case IDC_V_SPIN: UpdateColFromSpin(hwndDlg, Vc, vSpin); break;
1115 case IDC_SH_SPIN:
1116 theMtl->SetShininess(PcToFrac(shSpin->GetIVal()), curTime);
1117 UpdateHilite();
1118 break;
1119 case IDC_SS_SPIN:
1120 theMtl->SetShinStr(PcToFrac(ssSpin->GetIVal()),curTime);
1121 UpdateHilite();
1122 break;
1123
1124 // >>>>
1125 case IDC_SI_SPIN:
1126 theMtl->SetSelfIllum(PcToFrac(siSpin->GetIVal()),curTime);
1127 //UpdateColControls(0); // makes redraw smoother (black magic)
1128 break;
1129
1130 case IDC_TR_SPIN:
1131 theMtl->SetOpacity(PcToFrac(trSpin->GetIVal()),curTime);
1132 //UpdateColControls(0); // makes redraw smoother (black magic)
1133 break;
1134 case IDC_SOFT_SPIN:
1135 theMtl->SetSoftenLevel(softSpin->GetFVal(),curTime);
1136 break;
1137 }
1138 break;
1139 case CC_SPINNER_BUTTONDOWN:
1140 theHold.Begin();
1141 break;
1142 case WM_CUSTEDIT_ENTER:
1143 case CC_SPINNER_BUTTONUP:
1144 if (HIWORD(wParam) || msg==WM_CUSTEDIT_ENTER)
1145 theHold.Accept(GetString(IDS_DS_PARAMCHG));
1146 else
1147 theHold.Cancel();
1148 UpdateMtlDisplay();
1149 break;
1150
1151 }
1152 exit:
1153 return FALSE;
1154 }
1155
ExtraPanelProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)1156 INT_PTR StdMtlDlg::ExtraPanelProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam ) {
1157 int id = LOWORD(wParam);
1158 int code = HIWORD(wParam);
1159 switch (msg) {
1160 case WM_INITDIALOG:
1161 wireSizeSpin = SetupFloatSpinner(hwndDlg, IDC_WIRE_SPIN, IDC_WIRE_EDIT, 0.0f, 10000.0f, 1.0f);
1162 wireSizeSpin->SetAutoScale();
1163 tfSpin = SetupIntSpinner(hwndDlg, IDC_TF_SPIN, IDC_TF_EDIT, 0,100, 0);
1164 iorSpin = SetupFloatSpinner(hwndDlg, IDC_IOR_SPIN, IDC_IOR_EDIT, 0.0f,10.0f,1.5f,.01f);
1165 dimSpin = SetupFloatSpinner(hwndDlg, IDC_DIM_AMTSPIN, IDC_DIM_AMT, 0.0f,1.0f,1.0f,.01f);
1166 dimMultSpin = SetupFloatSpinner(hwndDlg, IDC_DIM_MULTSPIN, IDC_DIM_MULT, 0.1f,10.0f,1.0f,.01f);
1167 SetCheckBox(hwndDlg,IDC_DIM_REFL,theMtl->dimReflect);
1168 break;
1169 case WM_COMMAND:
1170 switch (id) {
1171 case IDC_TR_ADD:
1172 case IDC_TR_SUB:
1173 case IDC_TR_SUB2:
1174 CheckRadioButton( hwndDlg, IDC_TR_ADD,IDC_TR_SUB2,id);
1175 theMtl->SetFlag(STDMTL_ADD_TRANSP, id==IDC_TR_ADD);
1176 theMtl->SetFlag(STDMTL_FILT_TRANSP, id==IDC_TR_SUB2);
1177 FixFilterButtons();
1178 theMtl->NotifyChanged();
1179 break;
1180
1181 case IDC_TF_IN:
1182 case IDC_TF_OUT:
1183 CheckRadioButton( hwndDlg, IDC_TF_IN,IDC_TF_OUT,id);
1184 theMtl->SetFlag(STDMTL_FALLOFF_OUT, id==IDC_TF_OUT);
1185 theMtl->NotifyChanged();
1186 break;
1187
1188 case IDC_PIXELS:
1189 case IDC_UNITS:
1190 CheckRadioButton( hwndDlg, IDC_PIXELS,IDC_UNITS,id);
1191 theMtl->SetFlag(STDMTL_WIRE_UNITS, id==IDC_UNITS);
1192 if (theMtl->GetFlag(STDMTL_WIRE)) {
1193 UpdateMtlDisplay();
1194 theMtl->NotifyChanged();
1195 }
1196 break;
1197 case IDC_DIM_REFL:
1198 theMtl->dimReflect = GetCheckBox(hwndDlg,IDC_DIM_REFL);
1199 theMtl->NotifyChanged();
1200 break;
1201 }
1202 break;
1203 case WM_PAINT:
1204 if (!valid) {
1205 valid = TRUE;
1206 ReloadDialog();
1207 }
1208 return FALSE;
1209 case WM_DESTROY: break;
1210 break;
1211 case CC_SPINNER_CHANGE:
1212 if (!theHold.Holding()) theHold.Begin();
1213 switch(id) {
1214 case IDC_WIRE_SPIN:
1215 theMtl->SetWireSize(wireSizeSpin->GetFVal(),curTime);
1216 break;
1217 case IDC_TF_SPIN: theMtl->SetOpacFalloff(PcToFrac(tfSpin->GetIVal()),curTime);
1218 break;
1219 case IDC_IOR_SPIN:
1220 theMtl->SetIOR(iorSpin->GetFVal(),curTime);
1221 break;
1222 case IDC_DIM_AMTSPIN:
1223 theMtl->SetDimIntens(dimSpin->GetFVal(),curTime);
1224 break;
1225 case IDC_DIM_MULTSPIN:
1226 theMtl->SetDimMult(dimMultSpin->GetFVal(),curTime);
1227 break;
1228 }
1229 break;
1230 case CC_SPINNER_BUTTONDOWN:
1231 theHold.Begin();
1232 break;
1233 case WM_CUSTEDIT_ENTER:
1234 case CC_SPINNER_BUTTONUP:
1235 if (HIWORD(wParam) || msg==WM_CUSTEDIT_ENTER)
1236 theHold.Accept(GetString(IDS_DS_PARAMCHG));
1237 else
1238 theHold.Cancel();
1239 UpdateMtlDisplay();
1240 break;
1241 default:
1242 return FALSE;
1243 }
1244 return FALSE;
1245 }
1246
1247 //----------------------------------------------------------------------------
1248 // --- Drag-and-drop for Texture Maps ----
1249 //----------------------------------------------------------------------------
1250
1251
TexmapPanelProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)1252 INT_PTR StdMtlDlg::TexmapPanelProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam ) {
1253 int id = LOWORD(wParam);
1254 int code = HIWORD(wParam);
1255 switch (msg) {
1256 case WM_INITDIALOG:{
1257 for (int i=0; i<NTEXMAPS; i++) {
1258 if (i==ID_BU||i==ID_DP)
1259 texAmtSpin[i] = SetupIntSpinner(hwndDlg, texSpinID[i],texAmtID[i], -999,999, 0);
1260 else
1261 texAmtSpin[i] = SetupIntSpinner(hwndDlg, texSpinID[i],texAmtID[i], 0,100, 0);
1262 HWND hw = GetDlgItem(hwndDlg, texMapID[i]);
1263 // WNDPROC oldp = DLGetWindowProc(hw);
1264 // DLSetWindowLongPtr( hw, TexSlotWndProc);
1265 // DLSetWindowLongPtr( hw, oldp);
1266 iBut[i] = GetICustButton(GetDlgItem(hwndDlg, texMapID[i]));
1267 iBut[i]->SetDADMgr(&dadMgr);
1268 }
1269 SetupPadLockButton(hwndDlg,IDC_LOCK_ADTEX, TRUE);
1270 }
1271 break;
1272 case WM_COMMAND:
1273 {
1274 for (int i=0; i<NTEXMAPS; i++) {
1275 if (id == texOnID[i]) {
1276 theMtl->EnableMap(i,GetCheckBox(hwndDlg, id));
1277 UpdateMBut(i);
1278 goto exit;
1279 }
1280 if (id == texMapID[i]) {
1281 PostMessage(hwmedit,WM_TEXMAP_BUTTON, i ,(LPARAM)theMtl);
1282 goto exit;
1283 }
1284 }
1285 }
1286
1287 switch (id) {
1288 case IDC_LOCK_ADTEX:
1289 SetLockADTex(IsButtonChecked(hwndDlg, IDC_LOCK_ADTEX));
1290 break;
1291 }
1292 break;
1293 case WM_PAINT:
1294 if (!valid) {
1295 valid = TRUE;
1296 ReloadDialog();
1297 }
1298 return FALSE;
1299 case WM_DESTROY: break;
1300 case CC_SPINNER_CHANGE:
1301 {
1302 if (!theHold.Holding()) theHold.Begin();
1303 for (int i=0; i<NTEXMAPS; i++) {
1304 if (id == texSpinID[i]) {
1305 theMtl->SetTexmapAmt(i,PcToFrac(texAmtSpin[i]->GetIVal()), curTime);
1306 texAmtSpin[i]->SetKeyBrackets(theMtl->AmtKeyAtTime(i,curTime));
1307 break;
1308 }
1309 }
1310 }
1311 break;
1312 case CC_SPINNER_BUTTONDOWN:
1313 theHold.Begin();
1314 break;
1315 case WM_CUSTEDIT_ENTER:
1316 case CC_SPINNER_BUTTONUP:
1317 if (HIWORD(wParam) || msg==WM_CUSTEDIT_ENTER)
1318 theHold.Accept(GetString(IDS_DS_PARAMCHG));
1319 else
1320 theHold.Cancel();
1321 UpdateMtlDisplay();
1322 break;
1323 default:
1324 return FALSE;
1325 }
1326 exit:
1327 return FALSE;
1328 }
1329
1330
DynamPanelProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)1331 INT_PTR StdMtlDlg::DynamPanelProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam ) {
1332 int id = LOWORD(wParam);
1333 int code = HIWORD(wParam);
1334 switch (msg) {
1335 case WM_INITDIALOG:
1336 iBounce = SetupFloatSpinner(hwndDlg, IDC_BOUNCE_SPIN, IDC_BOUNCE_EDIT, 0.0f,1.0f,1.0f,.01f);
1337 iStatFrict = SetupFloatSpinner(hwndDlg, IDC_STATFRIC_SPIN, IDC_STATFRIC_EDIT, 0.0f,1.0f,0.0f,.01f);
1338 iSlidFrict = SetupFloatSpinner(hwndDlg, IDC_SLIDFRIC_SPIN, IDC_SLIDFRIC_EDIT, 0.0f,1.0f,0.0f,.01f);
1339 break;
1340 case WM_COMMAND:
1341 break;
1342 case WM_DESTROY: break;
1343 case CC_SPINNER_CHANGE:
1344 {
1345 if (!theHold.Holding()) theHold.Begin();
1346 switch(id) {
1347 case IDC_BOUNCE_SPIN:
1348 theMtl->SetDynamicsProperty(curTime,0,DYN_BOUNCE,iBounce->GetFVal());
1349 break;
1350 case IDC_STATFRIC_SPIN:
1351 theMtl->SetDynamicsProperty(curTime,0,DYN_STATIC_FRICTION,iStatFrict->GetFVal());
1352 break;
1353 case IDC_SLIDFRIC_SPIN:
1354 theMtl->SetDynamicsProperty(curTime,0,DYN_SLIDING_FRICTION,iSlidFrict->GetFVal());
1355 break;
1356 }
1357 }
1358 break;
1359 case CC_SPINNER_BUTTONDOWN:
1360 theHold.Begin();
1361 break;
1362 case WM_CUSTEDIT_ENTER:
1363 case CC_SPINNER_BUTTONUP:
1364 if (HIWORD(wParam) || msg==WM_CUSTEDIT_ENTER)
1365 theHold.Accept(GetString(IDS_DS_PARAMCHG));
1366 else
1367 theHold.Cancel();
1368 break;
1369 default:
1370 return FALSE;
1371
1372 }
1373 return FALSE;
1374 }
1375
BasicPanelDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)1376 static INT_PTR CALLBACK BasicPanelDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
1377 StdMtlDlg *theDlg;
1378 if (msg==WM_INITDIALOG) {
1379 theDlg = (StdMtlDlg*)lParam;
1380 theDlg->hPanelBasic = hwndDlg;
1381 DLSetWindowLongPtr(hwndDlg, lParam);
1382 }
1383 else {
1384 if ( (theDlg = DLGetWindowLongPtr<StdMtlDlg *>(hwndDlg) ) == NULL )
1385 return FALSE;
1386 }
1387 BOOL res;
1388 theDlg->isActive = 1;
1389 res = theDlg->BasicPanelProc(hwndDlg,msg,wParam,lParam);
1390 theDlg->isActive = 0;
1391 return res;
1392 }
1393
ExtraPanelDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)1394 static INT_PTR CALLBACK ExtraPanelDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
1395 StdMtlDlg *theDlg;
1396 if (msg==WM_INITDIALOG) {
1397 theDlg = (StdMtlDlg*)lParam;
1398 theDlg->hPanelExtra = hwndDlg;
1399 DLSetWindowLongPtr(hwndDlg, lParam);
1400 }
1401 else {
1402 if ( (theDlg = DLGetWindowLongPtr<StdMtlDlg *>(hwndDlg) ) == NULL )
1403 return FALSE;
1404 }
1405 BOOL res;
1406 theDlg->isActive = 1;
1407 res = theDlg->ExtraPanelProc(hwndDlg,msg,wParam,lParam);
1408 theDlg->isActive = 0;
1409 return res;
1410 }
1411
TexmapPanelDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)1412 static INT_PTR CALLBACK TexmapPanelDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
1413 StdMtlDlg *theDlg;
1414 if (msg==WM_INITDIALOG) {
1415 theDlg = (StdMtlDlg*)lParam;
1416 theDlg->hPanelTexmap = hwndDlg;
1417 DLSetWindowLongPtr(hwndDlg, lParam);
1418 }
1419 else {
1420 if ( (theDlg = DLGetWindowLongPtr<StdMtlDlg *>(hwndDlg) ) == NULL )
1421 return FALSE;
1422 }
1423 BOOL res;
1424 theDlg->isActive = 1;
1425 res = theDlg->TexmapPanelProc(hwndDlg,msg,wParam,lParam);
1426 theDlg->isActive = 0;
1427 return res;
1428 }
1429
1430
DynamPanelDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)1431 static INT_PTR CALLBACK DynamPanelDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
1432 StdMtlDlg *theDlg;
1433 if (msg==WM_INITDIALOG) {
1434 theDlg = (StdMtlDlg*)lParam;
1435 theDlg->hPanelDynam = hwndDlg;
1436 DLSetWindowLongPtr(hwndDlg, lParam);
1437 }
1438 else {
1439 if ( (theDlg = DLGetWindowLongPtr<StdMtlDlg *>(hwndDlg) ) == NULL )
1440 return FALSE;
1441 }
1442 BOOL res;
1443 theDlg->isActive = 1;
1444 res = theDlg->DynamPanelProc(hwndDlg,msg,wParam,lParam);
1445 theDlg->isActive = 0;
1446 return res;
1447 }
1448
UpdateTexmapDisplay(int i)1449 void StdMtlDlg::UpdateTexmapDisplay(int i) {
1450 texAmtSpin[i]->SetValue(FracToPc(theMtl->GetTexmapAmt(i)),FALSE);
1451 texAmtSpin[i]->SetKeyBrackets(theMtl->AmtKeyAtTime(i,curTime));
1452 SetCheckBox(hPanelTexmap, texOnID[i], theMtl->IsMapEnabled(i));
1453 Texmap *t = (*theMtl->maps)[i].map;
1454 TSTR nm;
1455 if (t)
1456 nm = t->GetFullName();
1457 else
1458 nm = GetString(IDS_DS_NONE);
1459 iBut[i]->SetText(nm.data());
1460 // SetDlgItemText(hPanelTexmap, texMapID[i], nm.data());
1461 UpdateMBut(i);
1462 }
1463
UpdateTexmaps()1464 void StdMtlDlg::UpdateTexmaps() {
1465 for (int i=0; i<NTEXMAPS; i++)
1466 UpdateTexmapDisplay(i);
1467 }
1468
LoadDialog(BOOL draw)1469 void StdMtlDlg::LoadDialog(BOOL draw) {
1470 if (theMtl&&hPanelBasic) {
1471 Interval v;
1472 // assert(hPanelBasic);
1473
1474 // BASIC PANEL
1475 HWND hwndShading = GetDlgItem(hPanelBasic, IDC_SHADING);
1476 SendMessage( hwndShading, CB_SETCURSEL, ListIDFromShade((WPARAM)theMtl->GetShaderId()), (LPARAM)0 );
1477 ULONG flg = theMtl->flags;
1478 SetCheckBox(hPanelBasic,IDC_WIRE, (flg&STDMTL_WIRE)?1:0);
1479 SetCheckBox(hPanelBasic,IDC_2SIDE, (flg&STDMTL_2SIDE)?1:0);
1480 SetCheckBox(hPanelBasic,IDC_SUPER_SAMP, (flg&STDMTL_SSAMP)?1:0);
1481
1482 // SetCheckBox(hPanelBasic,IDC_SOFTEN, (flg&STDMTL_SOFTEN)?1:0);
1483 // SetCheckBox(hPanelBasic,IDC_OLD_SPEC, (flg&STDMTL_OLDSPEC)?1:0);
1484 SetCheckBox(hPanelBasic,IDC_FACE_MAP, (flg&STDMTL_FACEMAP)?1:0);
1485 CheckRadioButton( hPanelBasic, IDC_AMB,IDC_FILT, IDC_AMB+editingColor);
1486 shSpin->SetValue(FracToPc(theMtl->GetShininess()),FALSE);
1487 shSpin->SetKeyBrackets(KeyAtCurTime(PB_SHININESS));
1488
1489 ssSpin->SetValue(FracToPc(theMtl->GetShinStr()),FALSE);
1490 ssSpin->SetKeyBrackets(KeyAtCurTime(PB_SHIN_STR));
1491
1492 // >>>>
1493 siSpin->SetValue(FracToPc(theMtl->GetSelfIll()),FALSE);
1494 siSpin->SetKeyBrackets(KeyAtCurTime(PB_SELFI));
1495
1496 trSpin->SetValue(FracToPc(theMtl->GetOpacity()),FALSE);
1497 trSpin->SetKeyBrackets(KeyAtCurTime(PB_OPAC));
1498
1499 tfSpin->SetValue(FracToPc(theMtl->GetOpacFalloff()),FALSE);
1500 tfSpin->SetKeyBrackets(KeyAtCurTime(PB_OPFALL));
1501
1502 softSpin->SetValue(theMtl->softThresh,FALSE);
1503 softSpin->SetKeyBrackets(KeyAtCurTime(PB_SOFTEN));
1504 softSpin->Enable(theMtl->shading!=SHADE_METAL);
1505
1506 CheckButton(hPanelBasic, IDC_LOCK_AD, theMtl->GetFlag(STDMTL_LOCK_AD));
1507 CheckButton(hPanelBasic, IDC_LOCK_DS, theMtl->GetFlag(STDMTL_LOCK_DS));
1508 UpdateLockADTex();
1509 FixFilterButtons();
1510 EnablePhongStuff();
1511
1512 curRGB = MtlColor(editingColor).toRGB();
1513 RGBtoHSV(curRGB, &H, &S, &V);
1514 UpdateColControls(SET_HSV|SET_RGB);
1515
1516 UpdateColSwatches();
1517 UpdateHilite();
1518
1519 // EXTRA PANEL
1520 int b,c;
1521 b = theMtl->GetFlag(STDMTL_ADD_TRANSP);
1522 c = theMtl->GetFlag(STDMTL_FILT_TRANSP);
1523 CheckRadioButton(hPanelExtra,IDC_TR_ADD,IDC_TR_SUB2,b?IDC_TR_ADD:c?IDC_TR_SUB2:IDC_TR_SUB);
1524
1525 b = theMtl->GetFlag(STDMTL_FALLOFF_OUT);
1526 CheckRadioButton(hPanelExtra,IDC_TF_IN,IDC_TF_OUT,b?IDC_TF_OUT:IDC_TF_IN);
1527
1528 b = theMtl->GetFlag(STDMTL_WIRE_UNITS);
1529 CheckRadioButton(hPanelExtra,IDC_PIXELS,IDC_UNITS,b?IDC_UNITS:IDC_PIXELS);
1530
1531 wireSizeSpin->SetValue( theMtl->WireSize(),FALSE);
1532 wireSizeSpin->SetKeyBrackets(KeyAtCurTime(PB_WIRESZ));
1533
1534 iorSpin->SetValue( theMtl->GetIOR(),FALSE);
1535 iorSpin->SetKeyBrackets(KeyAtCurTime(PB_IOR));
1536
1537 SetCheckBox(hPanelExtra,IDC_DIM_REFL,theMtl->dimReflect);
1538
1539 dimSpin->SetValue( theMtl->GetDimIntens(curTime),FALSE);
1540 dimSpin->SetKeyBrackets(KeyAtCurTime(PB_DIMLEV));
1541
1542 dimMultSpin->SetValue( theMtl->GetDimMult(curTime),FALSE);
1543 dimMultSpin->SetKeyBrackets(KeyAtCurTime(PB_DIMMULT));
1544
1545
1546 // TEXMAP PANEL & BASIC PANEL
1547 for (int i=0; i<NTEXMAPS; i++)
1548 UpdateTexmapDisplay(i);
1549
1550 #ifndef NO_MTL_DYNAMICS_PARAMETERS
1551 // DYNAMICS PANEL
1552 iBounce->SetValue(theMtl->GetDynamicsProperty(curTime,0,DYN_BOUNCE),FALSE);
1553 iBounce->SetKeyBrackets(KeyAtCurTime(PB_BOUNCE));
1554
1555 iStatFrict->SetValue(theMtl->GetDynamicsProperty(curTime,0,DYN_STATIC_FRICTION),FALSE);
1556 iStatFrict->SetKeyBrackets(KeyAtCurTime(PB_STATFRIC));
1557
1558 iSlidFrict->SetValue(theMtl->GetDynamicsProperty(curTime,0,DYN_SLIDING_FRICTION),FALSE);
1559 iSlidFrict->SetKeyBrackets(KeyAtCurTime(PB_SLIDFRIC));
1560 #endif
1561 }
1562 }
1563
SetRGB(DWORD rgb)1564 void StdMtlDlg::SetRGB(DWORD rgb) {
1565 curRGB = rgb;
1566 RGBtoHSV (curRGB, &H, &S, &V);
1567 }
1568
1569
UpdateColSwatches()1570 void StdMtlDlg::UpdateColSwatches() {
1571 for(int i=0; i<NCOLBOX; i++) {
1572 cs[i]->SetKeyBrackets(theMtl->KeyAtTime(PB_ID[i],curTime));
1573 cs[i]->SetColor(MtlColor(i));
1574 }
1575 }
1576
UpdateColControls(int which)1577 void StdMtlDlg::UpdateColControls( int which) {
1578 HDC hdc;
1579 hdc = GetDC (hPanelBasic);
1580 BOOL key = KeyAtCurTime(PB_ID[editingColor]);
1581 if (which & SET_HSV) {
1582 hSpin->SetValue((int)H,FALSE);
1583 sSpin->SetValue((int)S,FALSE);
1584 vSpin->SetValue((int)V,FALSE);
1585 hSpin->SetKeyBrackets(key);
1586 sSpin->SetKeyBrackets(key);
1587 vSpin->SetKeyBrackets(key);
1588 }
1589 if (which & SET_RGB) {
1590 rSpin->SetValue((int)GetRValue (curRGB),FALSE);
1591 gSpin->SetValue((int)GetGValue (curRGB),FALSE);
1592 bSpin->SetValue((int)GetBValue (curRGB),FALSE);
1593 rSpin->SetKeyBrackets(key);
1594 gSpin->SetKeyBrackets(key);
1595 bSpin->SetKeyBrackets(key);
1596 }
1597 ReleaseDC(hPanelBasic,hdc);
1598 }
1599
UpdateColFromSpin(HWND hwndDlg,int indx,ISpinnerControl * spin)1600 void StdMtlDlg::UpdateColFromSpin(HWND hwndDlg,int indx, ISpinnerControl *spin ) {
1601 int r, g, b;
1602 int *vals[6] = {&H, &S, &V, &r, &g, &b};
1603 int update = 0;
1604 r = GetRValue (curRGB);
1605 g = GetGValue (curRGB);
1606 b = GetBValue (curRGB);
1607 *vals[indx] = spin->GetIVal();
1608 switch (indx) {
1609 case Hc: case Sc: case Vc:
1610 // Changing the HSV settings. Compute new RGB.
1611 curRGB = HSVtoRGB (H, S, V);
1612 update |= SET_RGB; // Update only the RGB controls.
1613 break;
1614 case Rc: case Gc: case Bc:
1615 // Changing the RGB settings. Compute new HSV.
1616 SetRGB(RGB(r,g,b));
1617 update |= SET_HSV; // Update only the HSV controls.
1618 break;
1619 }
1620 SetMtlColor(editingColor,Color(curRGB));
1621 UpdateColControls(update);
1622 cs[editingColor]->SetColor(MtlColor(editingColor));
1623 }
1624
UpdateMtlDisplay()1625 void StdMtlDlg::UpdateMtlDisplay() {
1626 ip->MtlChanged(); // redraw viewports
1627 }
1628
1629
ActivateDlg(BOOL onOff)1630 void StdMtlDlg::ActivateDlg(BOOL onOff) {
1631 UpdateColControls(0);
1632 for(int i=0; i<NCOLBOX; i++)
1633 cs[i]->Activate(onOff);
1634 // UpdateColSwatches();
1635 }
1636
SetEditColor(int i)1637 void StdMtlDlg::SetEditColor(int i) {
1638 editingColor = i;
1639 cs[editingColor]->EditThis(FALSE);
1640 curRGB = MtlColor(i).toRGB();
1641 RGBtoHSV(curRGB, &H, &S, &V);
1642 UpdateColControls(SET_HSV|SET_RGB);
1643 if (hPanelBasic) {
1644 CheckRadioButton( hPanelBasic, IDC_AMB,IDC_FILT, IDC_AMB+i);
1645 //cs[i]->SetCheck(check);
1646 }
1647 }
1648
1649
SetLockAD(BOOL lock)1650 void StdMtlDlg::SetLockAD(BOOL lock) {
1651 if (lock) {
1652 if (IDYES!=MessageBox(hwmedit, GetString(IDS_DS_LOCKAD), GetString(IDS_DS_LOCKCOL), MB_YESNO)) {
1653 CheckButton(hPanelBasic, IDC_LOCK_AD, FALSE);
1654 return;
1655 }
1656 if (editingColor==0)
1657 SetMtlColor(1, MtlColor(0));
1658 else
1659 SetMtlColor(0, MtlColor(1));
1660 UpdateColControls(SET_HSV|SET_RGB);
1661 UpdateColSwatches();
1662 }
1663 theMtl->SetFlag(STDMTL_LOCK_AD,lock);
1664 }
1665
IndexForMapID(int id)1666 static int IndexForMapID(int id) {
1667 for (int i=0; i<NTEXMAPS; i++) if (id==texMapID[i]) return i;
1668 return 0;
1669 }
UpdateLockADTex()1670 void StdMtlDlg::UpdateLockADTex() {
1671 int lock = theMtl->GetFlag(STDMTL_LOCK_ADTEX);
1672 CheckButton(hPanelBasic, IDC_LOCK_ADTEX,lock);
1673 CheckButton(hPanelTexmap, IDC_LOCK_ADTEX,lock);
1674 ShowWindow(GetDlgItem(hPanelBasic,IDC_MAPON_AM), !lock);
1675 iBut[IndexForMapID(IDC_MAP_AM)]->Enable(!lock);
1676 }
1677
SetLockADTex(BOOL lock)1678 void StdMtlDlg::SetLockADTex(BOOL lock) {
1679 theMtl->SetFlag(STDMTL_LOCK_ADTEX,lock);
1680 UpdateLockADTex();
1681 theMtl->NotifyChanged();
1682 UpdateMtlDisplay();
1683 }
1684
SetLockDS(BOOL lock)1685 void StdMtlDlg::SetLockDS(BOOL lock) {
1686 if (lock) {
1687 if (IDYES!=MessageBox(hwmedit, GetString(IDS_DS_LOCK_DS),GetString(IDS_DS_LOCKCOL), MB_YESNO)) {
1688 CheckButton(hPanelBasic, IDC_LOCK_DS, FALSE);
1689 return;
1690 }
1691 if (editingColor==2)
1692 SetMtlColor(1, MtlColor(2));
1693 else
1694 SetMtlColor(2, MtlColor(1));
1695 UpdateColControls(SET_HSV|SET_RGB);
1696 UpdateColSwatches();
1697 }
1698 theMtl->SetFlag(STDMTL_LOCK_DS,lock);
1699 }
1700
SetThing(ReferenceTarget * m)1701 void StdMtlDlg::SetThing(ReferenceTarget *m) {
1702 assert (m->SuperClassID()==MATERIAL_CLASS_ID);
1703 assert (m->ClassID()==stdmtlClassID);
1704 if (theMtl)
1705 theMtl->paramDlg = NULL;
1706 theMtl = (StdMtl *)m;
1707 if (theMtl)
1708 theMtl->paramDlg = this;
1709 LoadDialog(TRUE);
1710 if (hPanelBasic)
1711 for (int i=0; i<4; i++) cs[i]->InitColor(MtlColor(i));
1712 }
1713
VertLine(HDC hdc,int x,int ystart,int yend)1714 static void VertLine(HDC hdc,int x, int ystart, int yend) {
1715 MoveToEx(hdc,x,ystart,NULL);
1716 if (ystart<=yend)
1717 LineTo(hdc, x, yend+1);
1718 else
1719 LineTo(hdc, x, yend-1);
1720 }
1721
1722
1723 //-------------------------------------------------------
1724
1725 //-------------------------------------------------------
GenDrawHilite(HDC hdc,Rect & rect,SShader & sh)1726 void StdMtlDlg::GenDrawHilite(HDC hdc, Rect& rect, SShader &sh) {
1727 int w,h,npts,xcen,ybot,ytop,ylast,i,iy;
1728 HPEN linePen = (HPEN)GetStockObject(WHITE_PEN);
1729 HPEN fgPen = CreatePen(PS_SOLID,0,GetCustSysColor(COLOR_BTNFACE));
1730 HPEN bgPen = CreatePen(PS_SOLID,0,GetCustSysColor(COLOR_BTNSHADOW));
1731 w = rect.w();
1732 h = rect.h()-3;
1733 npts = (w-2)/2;
1734 xcen = rect.left+npts;
1735 ybot = rect.top+h;
1736 ytop = rect.top+2;
1737 ylast = -1;
1738 for (i=0; i<npts; i++) {
1739 float v = sh.EvalHilite((float)i/((float)npts*2.0f));
1740 if (v>2.0f) v = 2.0f; // keep iy from wrapping
1741 iy = ybot-(int)(v*((float)h-2.0f));
1742
1743 if (iy<ytop) iy = ytop;
1744
1745 SelectPen(hdc, fgPen);
1746 VertLine(hdc,xcen+i,ybot,iy);
1747 VertLine(hdc,xcen-i,ybot,iy);
1748
1749 if (iy-1>ytop) {
1750 // Fill in above curve
1751 SelectPen(hdc,bgPen);
1752 VertLine(hdc,xcen+i, ytop, iy-1);
1753 VertLine(hdc,xcen-i, ytop, iy-1);
1754 }
1755 if (ylast>=0) {
1756 SelectPen(hdc,linePen);
1757 VertLine(hdc,xcen+i-1,iy-1,ylast);
1758 VertLine(hdc,xcen-i+1,iy-1,ylast);
1759 }
1760
1761 ylast = iy;
1762 }
1763 SelectObject( hdc, linePen );
1764 DeleteObject(fgPen);
1765 DeleteObject(bgPen);
1766 WhiteRect3D(hdc, rect, 1);
1767 }
1768
DrawHilite(HDC hdc,Rect & rect)1769 void StdMtlDlg::DrawHilite(HDC hdc, Rect& rect) {
1770 if (theMtl==NULL) return;
1771 theMtl->UpdateShader();
1772 GenDrawHilite(hdc,rect,*theMtl->curShader);
1773 }
1774
EnablePhongStuff()1775 void StdMtlDlg::EnablePhongStuff() {
1776 BOOL b = theMtl->shading==SHADE_METAL?0:1;
1777 EnableWindow(GetDlgItem(hPanelBasic,IDC_SOFTEN), b);
1778 EnableWindow(GetDlgItem(hPanelBasic,IDC_SPEC), b);
1779 EnableWindow(GetDlgItem(hPanelBasic,IDC_MAPON_SP), b);
1780 EnableWindow(GetDlgItem(hPanelTexmap,IDC_USEMAP_SP), b);
1781 EnableWindow(GetDlgItem(hPanelTexmap,IDC_AMT_SP), b);
1782 EnableWindow(GetDlgItem(hPanelTexmap,IDC_SPIN_SP), b);
1783 EnableWindow(GetDlgItem(hPanelTexmap,IDC_MAP_SP), b);
1784 EnableWindow(GetDlgItem(hPanelTexmap,IDC_MAP_SP), b);
1785 if (b) cs[2]->Enable(); else cs[2]->Disable();
1786 }
1787
UpdateHilite()1788 void StdMtlDlg::UpdateHilite() {
1789 HDC hdc = GetDC(hwHilite);
1790 Rect r;
1791 GetClientRect(hwHilite,&r);
1792 DrawHilite(hdc, r);
1793 ReleaseDC(hwHilite,hdc);
1794 }
1795
1796
BuildDialog()1797 void StdMtlDlg::BuildDialog() {
1798 if ((theMtl->flags&(STDMTL_ROLLUP_FLAGS))==0)
1799 theMtl->flags |= STDMTL_ROLLUP1_OPEN;
1800 hPanelBasic = ip->AddRollupPage(
1801 hInstance, //getResMgr().getHInst(RES_ID_DS),
1802 MAKEINTRESOURCE(IDD_DMTL_BASIC),
1803 BasicPanelDlgProc,
1804 GetString(IDS_DS_BASIC),
1805 (LPARAM)this,
1806 theMtl->flags&STDMTL_ROLLUP1_OPEN?0:APPENDROLL_CLOSED
1807 );
1808
1809 hPanelExtra = ip->AddRollupPage(
1810 hInstance, //getResMgr().getHInst(RES_ID_DS),
1811 MAKEINTRESOURCE(IDD_DMTL_EXTRA),
1812 ExtraPanelDlgProc,
1813 GetString(IDS_DS_EXTRA),
1814 (LPARAM)this,
1815 theMtl->flags&STDMTL_ROLLUP2_OPEN?0:APPENDROLL_CLOSED
1816 );
1817
1818 hPanelTexmap = ip->AddRollupPage(
1819 hInstance, //getResMgr().getHInst(RES_ID_DS),
1820 MAKEINTRESOURCE(IDD_DMTL_TEXMAP),
1821 TexmapPanelDlgProc,
1822 GetString(IDS_DS_TEXMAP),
1823 (LPARAM)this,
1824 theMtl->flags&STDMTL_ROLLUP3_OPEN?0:APPENDROLL_CLOSED
1825 );
1826
1827 #ifndef NO_MTL_DYNAMICS_PARAMETERS
1828 hPanelDynam = ip->AddRollupPage(
1829 hInstance, //getResMgr().getHInst(RES_ID_DS),
1830 MAKEINTRESOURCE(IDD_DMTL_DYNAM),
1831 DynamPanelDlgProc,
1832 GetString(IDS_DS_DYNAMICS),
1833 (LPARAM)this,
1834 theMtl->flags&STDMTL_ROLLUP4_OPEN?0:APPENDROLL_CLOSED
1835 );
1836 #endif
1837
1838 ip->SetRollupScrollPos(theMtl->rollScroll);
1839 }
1840
1841
1842 //-----------------------------------------------------------------------------
1843 // StdMtl
1844 //-----------------------------------------------------------------------------
1845
1846
1847 #define NPARAMS 17
1848 #define STDMTL_PBVERSION 9
1849
1850 //Current Param Block Descriptor
1851 static ParamBlockDescID stdmtlPB[NPARAMS] = {
1852 { TYPE_RGBA, NULL, TRUE,1 }, // ambient
1853 { TYPE_RGBA, NULL, TRUE,2 }, // diffuse
1854 { TYPE_RGBA, NULL, TRUE,3 }, // specular
1855 { TYPE_FLOAT, NULL, TRUE,4 }, // shininess
1856 { TYPE_FLOAT, NULL, TRUE,5 }, // shini_strength
1857 { TYPE_FLOAT, NULL, TRUE,6 }, // self-illum
1858 { TYPE_FLOAT, NULL, TRUE,7 }, // opacity
1859 { TYPE_FLOAT, NULL, TRUE,8 }, // opfalloff
1860 { TYPE_RGBA, NULL, TRUE,9 }, // filter
1861 { TYPE_FLOAT, NULL, TRUE,10 }, // wireSize
1862 { TYPE_FLOAT, NULL, TRUE,11 }, // index of refraction
1863 { TYPE_FLOAT, NULL, TRUE,12 }, // bounce
1864 { TYPE_FLOAT, NULL, TRUE,13 }, // static friction
1865 { TYPE_FLOAT, NULL, TRUE,14 }, // sliding friction
1866 { TYPE_FLOAT, NULL, TRUE,15 }, // reflect dim level
1867 { TYPE_FLOAT, NULL, TRUE,16 }, // reflect dim multiplier
1868 { TYPE_FLOAT, NULL, TRUE,17 } // soften
1869 };
1870
1871 #define NUMOLDVER 9
1872
1873 static ParamVersionDesc oldVersions[NUMOLDVER] = {
1874 ParamVersionDesc(stdmtlPB,8, 0),
1875 ParamVersionDesc(stdmtlPB,9, 1),
1876 ParamVersionDesc(stdmtlPB,9, 2),
1877 ParamVersionDesc(stdmtlPB,10,3),
1878 ParamVersionDesc(stdmtlPB,11,4),
1879 ParamVersionDesc(stdmtlPB,14,5),
1880 ParamVersionDesc(stdmtlPB,15,6),
1881 ParamVersionDesc(stdmtlPB,15,7),
1882 ParamVersionDesc(stdmtlPB,16,8)
1883 };
1884
1885 static ParamVersionDesc curVersion(stdmtlPB,NPARAMS,STDMTL_PBVERSION);
1886
Reset()1887 void StdMtl::Reset() {
1888 SuspendSetKeyMode();
1889 // shading = SHADE_PHONG;
1890 SetShadingNoNotify(SHADE_BLINN);
1891 flags = STDMTL_FILT_TRANSP|STDMTL_LOCK_ADTEX|STDMTL_SOFTEN;
1892 dimReflect = FALSE;
1893 ReplaceReference( 0, CreateParameterBlock( stdmtlPB, NPARAMS, STDMTL_PBVERSION ) );
1894 ReplaceReference( 1, new Texmaps((MtlBase*)this));
1895 ivalid.SetEmpty();
1896 SetDimIntens(0.0f,0);
1897 SetDimMult(3.0f,0);
1898 SetSoftenLevel(0.1f,0);
1899 SetAmbient(Color(0.1f,0.1f,0.1f),0);
1900 SetDiffuse(Color(0.5f,0.5f,0.5f),0);
1901 SetSpecular(Color(0.9f,0.9f,0.9f),0);
1902 SetOpacity(1.0f,0);
1903 SetFilter(Color(.5f,.5f,.5f),0);
1904 SetShininess(.25f,0); // change from .4, 5-21-97
1905 SetShinStr(.05f,0); // change from .3, 5-21-97
1906 // >>>>
1907 SetSelfIllum(.0f,0);
1908 SetOpacFalloff(0.0f,0);
1909 SetWireSize(1.0f,0);
1910 SetIOR(1.5f,0);
1911 SetTexmapAmt(ID_BU, BUMP_DEF_AMT, 0);
1912 SetDynamicsProperty(0,0,DYN_BOUNCE,1.0f);
1913 SetDynamicsProperty(0,0,DYN_STATIC_FRICTION,0.0f);
1914 SetDynamicsProperty(0,0,DYN_SLIDING_FRICTION,0.0f);
1915 ResumeSetKeyMode();
1916 }
1917
StdMtl(BOOL loading)1918 StdMtl::StdMtl(BOOL loading) {
1919 paramDlg = NULL;
1920 pblock = NULL;
1921 maps = NULL;
1922 ambient = diffuse = specular = filter = Color(0.0f,0.0f,0.0f);
1923 SetShadingNoNotify(SHADE_PHONG);
1924 flags = STDMTL_FILT_TRANSP|STDMTL_LOCK_ADTEX|STDMTL_SOFTEN;
1925 dimReflect = FALSE;
1926 dimIntens = 0.0f;
1927 dimMult = 2.0f;
1928 ivalid.SetEmpty();
1929 if (!loading)
1930 Reset();
1931 rollScroll = 0;
1932 flags |= STDMTL_ROLLUP1_OPEN;
1933 }
1934
Clone(RemapDir & remap)1935 RefTargetHandle StdMtl::Clone(RemapDir &remap) {
1936 //DebugPrint(" Cloning STDMTL %d \n",++numStdMtls);
1937 StdMtl *mnew = new StdMtl();
1938 *((MtlBase*)mnew) = *((MtlBase*)this); // copy superclass stuff
1939 mnew->ReplaceReference(0,remap.CloneRef(pblock));
1940 mnew->ReplaceReference(1,remap.CloneRef(maps));
1941 mnew->ivalid.SetEmpty();
1942 mnew->flags = flags;
1943 mnew->ambient = ambient;
1944 mnew->diffuse = diffuse;
1945 mnew->specular = specular;
1946 mnew->filter = filter;
1947 mnew->shininess = shininess;
1948 mnew->phongexp = phongexp;
1949 mnew->shine_str = shine_str;
1950 mnew->self_illum = self_illum;
1951 mnew->opacity = opacity;
1952 mnew->opfall = opfall;
1953 mnew->wireSize = wireSize;
1954 mnew->ioRefract = ioRefract;
1955 mnew->dimReflect = dimReflect;
1956 mnew->softThresh = softThresh;
1957 mnew->SetShadingNoNotify(shading);
1958 BaseClone(this, mnew, remap);
1959 return (RefTargetHandle)mnew;
1960 }
1961
CreateParamDlg(HWND hwMtlEdit,IMtlParams * imp)1962 ParamDlg* StdMtl::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp) {
1963 Interval v;
1964 Update(imp->GetTime(),v);
1965 StdMtlDlg *dm = new StdMtlDlg(hwMtlEdit, imp, this);
1966 LoadStdMtlResources();
1967 dm->BuildDialog();
1968 dm->LoadDialog(FALSE);
1969 SetParamDlg(dm);
1970 return dm;
1971 }
1972
1973 #define LIMIT0_1(x) if (x<0.0f) x = 0.0f; else if (x>1.0f) x = 1.0f;
1974 #define LIMITMINMAX(x,min,max) if (x<min) x = min; else if (x>max) x = max;
1975
LimitColor(Color c)1976 static Color LimitColor(Color c) {
1977 LIMIT0_1(c.r);
1978 LIMIT0_1(c.g);
1979 LIMIT0_1(c.b);
1980 return c;
1981 }
1982
Update(TimeValue t,Interval & valid)1983 void StdMtl::Update(TimeValue t, Interval &valid) {
1984 Point3 p;
1985 if (!ivalid.InInterval(t)) {
1986 ivalid.SetInfinite();
1987 pblock->GetValue( PB_AMBIENT, t, p, ivalid );
1988 ambient = LimitColor(Color(p.x,p.y,p.z));
1989 pblock->GetValue( PB_DIFFUSE, t, p, ivalid );
1990 diffuse= LimitColor(Color(p.x,p.y,p.z));
1991 pblock->GetValue( PB_SPECULAR, t, p, ivalid );
1992 specular = LimitColor(Color(p.x,p.y,p.z));
1993 pblock->GetValue( PB_FILTER, t, p, ivalid );
1994 filter = LimitColor(Color(p.x,p.y,p.z));
1995 pblock->GetValue( PB_SHININESS, t, shininess, ivalid );
1996 pblock->GetValue( PB_SHIN_STR, t, shine_str, ivalid );
1997 // >>>>>
1998 pblock->GetValue( PB_SELFI, t, self_illum, ivalid );
1999 pblock->GetValue( PB_OPAC, t, opacity, ivalid );
2000
2001 pblock->GetValue( PB_OPFALL, t, opfall, ivalid );
2002 pblock->GetValue( PB_WIRESZ, t, wireSize, ivalid );
2003 pblock->GetValue( PB_IOR, t, ioRefract, ivalid );
2004 pblock->GetValue( PB_DIMLEV, t, dimIntens, ivalid );
2005 pblock->GetValue( PB_DIMMULT, t, dimMult, ivalid );
2006 pblock->GetValue( PB_SOFTEN, t, softThresh, ivalid);
2007
2008 LIMIT0_1(opacity);
2009 LIMIT0_1(self_illum);
2010 LIMIT0_1(shininess);
2011 LIMITMINMAX(shine_str,0.0f,9.99f);
2012 LIMIT0_1(opfall);
2013 LIMIT0_1(dimIntens);
2014 LIMIT0_1(softThresh);
2015
2016 phongexp = (float)pow(2.0,shininess*10.0);
2017
2018 for (int i=0; i<NTEXMAPS; i++) {
2019 if (MAPACTIVE(i))
2020 maps->txmap[i].Update(t,ivalid);
2021 }
2022 }
2023 valid &= ivalid;
2024 }
2025
2026 //-----------------------------------------------------------------------
2027 // DS - 4/7/97: Changed Opacity, Self-illumination, SHininess, Shininess strengh
2028 // so that the map amount blends between the corresponding slider
2029 // setting and the map value. This code fixes up old files so they
2030 // will render the same way. This does not correctly handle animated values
2031 // for the amount or parameter sliders.
2032 //-----------------------------------------------------------------------
2033
OldVerFix(int loadVer)2034 void StdMtl::OldVerFix(int loadVer) {
2035 if (loadVer<8) {
2036 Interval v;
2037 Update(0,v);
2038 if (MAPACTIVE(ID_OP)) {
2039 if (maps->txmap[ID_OP].amount != 1.0f)
2040 SetOpacity(0.0f,0);
2041 }
2042 if (MAPACTIVE(ID_SI)) {
2043 if (maps->txmap[ID_SI].amount != 1.0f)
2044 // >>>>>
2045 SetSelfIllum(0.0f,0);
2046 }
2047 if (MAPACTIVE(ID_SS)) {
2048 float amt = maps->txmap[ID_SS].amount;
2049 SetTexmapAmt(ID_SS,amt*shine_str,0);
2050 SetShinStr(0.0f,0);
2051 }
2052 if (MAPACTIVE(ID_SH)) {
2053 float amt = maps->txmap[ID_SH].amount;
2054 SetTexmapAmt(ID_SH,amt*shininess,0);
2055 SetShininess(0.0f,0);
2056 }
2057 }
2058 if (loadVer<9) {
2059 if (flags&STDMTL_SOFTEN)
2060 SetSoftenLevel(.6f,0);
2061 else
2062 SetSoftenLevel(0.0f,0);
2063 }
2064 }
2065
2066
2067
Requirements(int subMtlNum)2068 ULONG StdMtl::Requirements(int subMtlNum) {
2069 ULONG req = 0;
2070
2071 switch (shading) {
2072 case SHADE_CONST:
2073 req |= MTLREQ_DONTMERGE_FRAGMENTS;
2074 break;
2075 case SHADE_PHONG:
2076 case SHADE_BLINN:
2077 case SHADE_METAL: req |= MTLREQ_PHONG; break;
2078 }
2079
2080 if (opacity!=1.0f||MAPACTIVE(ID_OP)||opfall>0.0f)
2081 req |= MTLREQ_TRANSP;
2082
2083 if (opacity!=1.0f)
2084 req |= MTLREQ_TRANSP_IN_VP;
2085
2086 for (int i=0; i<NTEXMAPS; i++) {
2087 if (MAPACTIVE(i))
2088 req |= (*maps)[i].map->Requirements(subMtlNum);
2089 }
2090 if (MAPACTIVE(ID_BU)) {
2091 ULONG bmpreq = (*maps)[ID_BU].map->Requirements(subMtlNum);
2092 if (bmpreq&MTLREQ_UV)
2093 req |= MTLREQ_BUMPUV;
2094 if (bmpreq&MTLREQ_UV2)
2095 req |= MTLREQ_BUMPUV2;
2096 }
2097 if (flags&STDMTL_WIRE) req|= MTLREQ_WIRE;
2098 if (flags&STDMTL_2SIDE) req|= MTLREQ_2SIDE;
2099 if (flags&STDMTL_SSAMP) req|= MTLREQ_SUPERSAMPLE;
2100 if (flags&STDMTL_WIRE_UNITS) req|= MTLREQ_WIRE_ABS;
2101 if (flags&STDMTL_FACEMAP) req |= MTLREQ_FACEMAP;
2102 if (flags&STDMTL_ADD_TRANSP) req |= MTLREQ_ADDITIVE_TRANSP;
2103 if (MAPACTIVE(ID_DP)) req |= MTLREQ_DISPLACEMAP;
2104 return req;
2105 }
2106
Validity(TimeValue t)2107 Interval StdMtl::Validity(TimeValue t) {
2108 Interval v;
2109 Update(t,v);
2110 return ivalid;
2111 }
2112
NotifyChanged()2113 void StdMtl::NotifyChanged() {
2114 NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
2115 }
2116
SetFlag(ULONG f,ULONG val)2117 void StdMtl::SetFlag(ULONG f, ULONG val) {
2118 if (val) flags|=f;
2119 else flags &= ~f;
2120 }
2121
SetTransparencyType(int type)2122 void StdMtl::SetTransparencyType(int type) {
2123 switch (type) {
2124 case TRANSP_SUBTRACTIVE:
2125 SetFlag(STDMTL_ADD_TRANSP,0);
2126 SetFlag(STDMTL_FILT_TRANSP,0);
2127 break;
2128 case TRANSP_ADDITIVE:
2129 SetFlag(STDMTL_ADD_TRANSP,1);
2130 SetFlag(STDMTL_FILT_TRANSP,0);
2131 break;
2132 case TRANSP_FILTER:
2133 SetFlag(STDMTL_ADD_TRANSP,0);
2134 SetFlag(STDMTL_FILT_TRANSP,1);
2135 break;
2136 }
2137 }
2138
DeleteThis()2139 void StdMtl::DeleteThis() {
2140 //DebugPrint(" Deleting STDMTL %d \n",numStdMtls--);
2141 delete this;
2142 }
2143
SubAnimName(int i)2144 TSTR StdMtl::SubAnimName(int i) {
2145 return TSTR(GetString(i==0?IDS_DS_PARAMETERS:IDS_DS_TEXMAPS));
2146 }
2147
SubAnim(int i)2148 Animatable* StdMtl::SubAnim(int i) {
2149 switch(i) {
2150 case 0: return pblock;
2151 case 1: return maps;
2152 default: assert(0); return NULL;
2153 }
2154 }
2155
GetReference(int i)2156 RefTargetHandle StdMtl::GetReference(int i) {
2157 switch(i) {
2158 case 0: return pblock;
2159 case 1: return maps;
2160 default: assert(0); return NULL;
2161 }
2162 }
2163
SetReference(int i,RefTargetHandle rtarg)2164 void StdMtl::SetReference(int i, RefTargetHandle rtarg) {
2165 switch(i) {
2166 case 0: pblock = (IParamBlock*)rtarg; return;
2167 case 1: {
2168 maps = (Texmaps*)rtarg;
2169 if (maps!=NULL)
2170 maps->client = this;
2171 return;
2172 }
2173 default: assert(0);
2174 }
2175 }
2176
SetSubTexmap(int i,Texmap * m)2177 void StdMtl::SetSubTexmap(int i, Texmap *m) {
2178 assert(i<NTEXMAPS);
2179 maps->ReplaceReference(2*i+1,m);
2180 if (m!=NULL) {
2181 EnableMap(i,TRUE);
2182 if (maps->txmap[i].amtCtrl==NULL) {
2183 maps->ReplaceReference(2*i, NewDefaultFloatController());
2184 maps->txmap[i].amtCtrl->SetValue(TimeValue(0),&maps->txmap[i].amount);
2185 }
2186 }
2187 else {
2188 if (maps->txmap[i].amtCtrl!=NULL)
2189 maps->DeleteReference(2*i);
2190 SetTexmapAmt(i, i==ID_BU?BUMP_DEF_AMT:1.0f,TimeValue(0));
2191 EnableMap(i,FALSE);
2192 }
2193 if (m&&(i==ID_RL||i==ID_RR)) {
2194 UVGen* uvg0 = m->GetTheUVGen();
2195 if (uvg0&&uvg0->IsStdUVGen()) {
2196 StdUVGen *uvg = (StdUVGen*)uvg0;
2197 uvg->InitSlotType(MAPSLOT_ENVIRON);
2198 uvg->SetCoordMapping(UVMAP_SPHERE_ENV);
2199 }
2200 }
2201 if (paramDlg)
2202 paramDlg->UpdateTexmapDisplay(i);
2203 }
2204
2205 static int nameID[NPARAMS] = {
2206 IDS_DS_AMBIENT, IDS_DS_DIFFUSE, IDS_DS_SPECULAR, IDS_DS_SHININESS,IDS_DS_SHIN_STR,
2207 IDS_DS_SELFI,IDS_DS_OPACITY,IDS_DS_XPFALL,IDS_DS_FILTER,IDS_DS_WIRESZ,
2208 IDS_DS_IOR,IDS_DS_BOUNCE,IDS_DS_STATFRIC,IDS_DS_SLIDFRIC,IDS_DS_DIMLEV,IDS_DS_DIMMULT,
2209 IDS_DS_SOFTEN};
2210
NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget,PartID & partID,RefMessage message)2211 RefResult StdMtl::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
2212 PartID& partID, RefMessage message ) {
2213 switch (message) {
2214 case REFMSG_WANT_SHOWPARAMLEVEL:
2215 {
2216 BOOL *pb = (BOOL *)(partID);
2217 *pb = TRUE;
2218 return REF_STOP;
2219 }
2220 case REFMSG_CHANGE:
2221 ivalid.SetEmpty();
2222 if (paramDlg) {
2223 if (hTarget==pblock) {
2224 int np =pblock->LastNotifyParamNum();
2225 paramDlg->UpdateControlFor(np);
2226 }
2227 else// if (!paramDlg->isActive)
2228 paramDlg->Invalidate();
2229 }
2230 break;
2231 case REFMSG_GET_PARAM_DIM: {
2232 GetParamDim *gpd = (GetParamDim*)partID;
2233 switch (gpd->index) {
2234 case PB_AMBIENT:
2235 case PB_DIFFUSE:
2236 case PB_SPECULAR:
2237 case PB_FILTER:
2238 gpd->dim = stdColor255Dim;
2239 break;
2240 case PB_BOUNCE:
2241 case PB_STATFRIC:
2242 case PB_SLIDFRIC:
2243 case PB_DIMLEV:
2244 case PB_DIMMULT:
2245 case PB_SOFTEN:
2246 case PB_WIRESZ:
2247 case PB_IOR:
2248 gpd->dim = defaultDim;
2249 break;
2250 case PB_SHININESS:
2251 case PB_SHIN_STR:
2252 case PB_SELFI:
2253 case PB_OPAC:
2254 case PB_OPFALL:
2255 default:
2256 gpd->dim = stdPercentDim;
2257 break;
2258 }
2259 return REF_STOP;
2260 }
2261
2262 case REFMSG_GET_PARAM_NAME: {
2263 GetParamName *gpn = (GetParamName*)partID;
2264 gpn->name = GetString(nameID[gpn->index]);
2265 return REF_STOP;
2266 }
2267 }
2268 return(REF_SUCCEED);
2269 }
2270
ClassID()2271 Class_ID StdMtl::ClassID() {
2272 return stdmtlClassID;
2273 }
2274
GetSubTexmapSlotName(int i)2275 TSTR StdMtl::GetSubTexmapSlotName(int i) {
2276 return GetString(texNameID[i]);
2277 }
2278
2279
EnableMap(int i,BOOL onoff)2280 void StdMtl::EnableMap(int i, BOOL onoff) {
2281 maps->txmap[i].mapOn = onoff;
2282 NotifyChanged();
2283 }
2284
2285 // forward
2286 SShader *GetShaderFromId(int s);
2287
SetShadingNoNotify(int s)2288 void StdMtl::SetShadingNoNotify( int s) {
2289 shading = s;
2290 curShader = GetShaderFromId(shading);
2291 }
2292
SetShaderId(long s)2293 void StdMtl::SetShaderId( long s) {
2294 long old = shading;
2295 SetShadingNoNotify(s);
2296 if (old!=shading) {
2297 NotifyChanged();
2298 if (paramDlg) {
2299 paramDlg->UpdateHilite();
2300 paramDlg->EnablePhongStuff();
2301 }
2302 }
2303 }
2304
SetAmbient(Color c,TimeValue t)2305 void StdMtl::SetAmbient(Color c, TimeValue t) {
2306 ambient =c;
2307 pblock->SetValue( PB_AMBIENT, t, Point3(c.r,c.g,c.b));
2308 NotifyChanged();
2309 }
2310
SetDiffuse(Color c,TimeValue t)2311 void StdMtl::SetDiffuse(Color c, TimeValue t) {
2312 Point3 p;
2313 Interval iv;
2314 pblock->SetValue( PB_DIFFUSE, t, Point3(c.r,c.g,c.b));
2315 pblock->GetValue( PB_DIFFUSE, t, p, ivalid );
2316 diffuse= LimitColor(Color(p.x,p.y,p.z));
2317 NotifyChanged();
2318 }
2319
SetSpecular(Color c,TimeValue t)2320 void StdMtl::SetSpecular(Color c, TimeValue t) {
2321 specular =c;
2322 pblock->SetValue( PB_SPECULAR, t, Point3(c.r,c.g,c.b));
2323 NotifyChanged();
2324 }
2325
SetFilter(Color c,TimeValue t)2326 void StdMtl::SetFilter(Color c, TimeValue t) {
2327 filter =c;
2328 pblock->SetValue( PB_FILTER, t, Point3(c.r,c.g,c.b));
2329 if (opacity!=1.0f||MAPACTIVE(ID_OP))
2330 NotifyChanged();
2331 }
2332
SetShininess(float v,TimeValue t)2333 void StdMtl::SetShininess(float v, TimeValue t) {
2334 shininess =v;
2335 phongexp = (float)pow(2.0,shininess*10.0);
2336 pblock->SetValue( PB_SHININESS, t, v);
2337 NotifyChanged();
2338 }
2339
SetShinStr(float v,TimeValue t)2340 void StdMtl::SetShinStr(float v, TimeValue t) {
2341 shine_str =v;
2342 pblock->SetValue( PB_SHIN_STR, t, v);
2343 NotifyChanged();
2344 }
2345
2346 // >>>>
SetSelfIllum(float v,TimeValue t)2347 void StdMtl::SetSelfIllum(float v, TimeValue t) {
2348 self_illum =v;
2349 pblock->SetValue( PB_SELFI, t, v);
2350 NotifyChanged();
2351 }
2352
SetOpacity(float v,TimeValue t)2353 void StdMtl::SetOpacity(float v, TimeValue t) {
2354 opacity = v;
2355 pblock->SetValue( PB_OPAC, t, v);
2356 NotifyChanged();
2357 }
2358
SetOpacFalloff(float v,TimeValue t)2359 void StdMtl::SetOpacFalloff(float v, TimeValue t) {
2360 opfall = v;
2361 pblock->SetValue( PB_OPFALL, t, v);
2362 if (opacity!=1.0f||MAPACTIVE(ID_OP))
2363 NotifyChanged();
2364 }
2365
SetWireSize(float v,TimeValue t)2366 void StdMtl::SetWireSize(float v, TimeValue t) {
2367 wireSize = v;
2368 pblock->SetValue( PB_WIRESZ, t, v);
2369 if (flags&STDMTL_WIRE)
2370 NotifyChanged();
2371 }
2372
SetIOR(float v,TimeValue t)2373 void StdMtl::SetIOR(float v, TimeValue t) {
2374 ioRefract = v;
2375 pblock->SetValue( PB_IOR, t, v);
2376 NotifyChanged();
2377 }
2378
SetDimIntens(float v,TimeValue t)2379 void StdMtl::SetDimIntens(float v, TimeValue t) {
2380 dimIntens = v;
2381 pblock->SetValue( PB_DIMLEV, t, v);
2382 NotifyChanged();
2383 }
2384
SetDimMult(float v,TimeValue t)2385 void StdMtl::SetDimMult(float v, TimeValue t) {
2386 dimMult = v;
2387 pblock->SetValue( PB_DIMMULT, t, v);
2388 NotifyChanged();
2389 }
2390
SetSoftenLevel(float v,TimeValue t)2391 void StdMtl::SetSoftenLevel(float v, TimeValue t) {
2392 softThresh = v;
2393 pblock->SetValue( PB_SOFTEN, t, v);
2394 NotifyChanged();
2395 }
2396
SetTexmapAmt(int imap,float amt,TimeValue t)2397 void StdMtl::SetTexmapAmt(int imap, float amt, TimeValue t) {
2398 if (maps->txmap[imap].amtCtrl)
2399 maps->txmap[imap].amtCtrl->SetValue(t,&amt);
2400 maps->txmap[imap].amount = amt;
2401 if (maps->txmap[imap].IsActive())
2402 NotifyChanged();
2403 }
2404
AmtKeyAtTime(int i,TimeValue t)2405 BOOL StdMtl::AmtKeyAtTime(int i, TimeValue t) {
2406 if (maps->txmap[i].amtCtrl)
2407 return maps->txmap[i].amtCtrl->IsKeyAtTime(t,0);
2408 else
2409 return FALSE;
2410 }
2411
GetShaderId()2412 long StdMtl::GetShaderId() {
2413 return shading;
2414 }
2415
UpdateShader()2416 void StdMtl::UpdateShader() {
2417 curShader->SetShininess(shininess,shine_str);
2418 }
2419
GetAmbient(int mtlNum,BOOL backFace)2420 Color StdMtl::GetAmbient(int mtlNum, BOOL backFace) { return ambient;}
GetDiffuse(int mtlNum,BOOL backFace)2421 Color StdMtl::GetDiffuse(int mtlNum, BOOL backFace) { return diffuse;}
GetSpecular(int mtlNum,BOOL backFace)2422 Color StdMtl::GetSpecular(int mtlNum, BOOL backFace) { return specular; }
GetFilter()2423 Color StdMtl::GetFilter() { return filter; }
2424
GetTexmapAmt(int imap)2425 float StdMtl::GetTexmapAmt(int imap) { return maps->txmap[imap].amount; }
2426
GetTexmapAmt(int imap,TimeValue t)2427 float StdMtl::GetTexmapAmt(int imap, TimeValue t) { return maps->txmap[imap].GetAmount(t); }
2428
2429
GetAmbient(TimeValue t)2430 Color StdMtl::GetAmbient(TimeValue t) { return pblock->GetColor(PB_AMBIENT,t);}
GetDiffuse(TimeValue t)2431 Color StdMtl::GetDiffuse(TimeValue t) { return pblock->GetColor(PB_DIFFUSE,t); }
GetSpecular(TimeValue t)2432 Color StdMtl::GetSpecular(TimeValue t) { return pblock->GetColor(PB_SPECULAR,t); }
GetFilter(TimeValue t)2433 Color StdMtl::GetFilter(TimeValue t) { return pblock->GetColor(PB_FILTER,t); }
GetShininess(TimeValue t)2434 float StdMtl::GetShininess( TimeValue t) {return pblock->GetFloat(PB_SHININESS,t); }
GetShinStr(TimeValue t)2435 float StdMtl::GetShinStr(TimeValue t) { return pblock->GetFloat(PB_SHIN_STR,t); }
2436 // >>>>
GetSelfIllum(TimeValue t)2437 float StdMtl::GetSelfIllum(TimeValue t){ return pblock->GetFloat(PB_SELFI,t); }
GetOpacity(TimeValue t)2438 float StdMtl::GetOpacity( TimeValue t) { return pblock->GetFloat(PB_OPAC,t); }
GetOpacFalloff(TimeValue t)2439 float StdMtl::GetOpacFalloff(TimeValue t){ return pblock->GetFloat(PB_OPFALL,t);}
GetWireSize(TimeValue t)2440 float StdMtl::GetWireSize(TimeValue t) { return pblock->GetFloat(PB_WIRESZ,t);}
GetIOR(TimeValue t)2441 float StdMtl::GetIOR( TimeValue t) { return pblock->GetFloat(PB_IOR,t);}
GetDimIntens(TimeValue t)2442 float StdMtl::GetDimIntens( TimeValue t) { return pblock->GetFloat(PB_DIMLEV,t); }
GetDimMult(TimeValue t)2443 float StdMtl::GetDimMult( TimeValue t) { return pblock->GetFloat(PB_DIMMULT,t); }
GetSoftenLevel(TimeValue t)2444 float StdMtl::GetSoftenLevel( TimeValue t) { return pblock->GetFloat(PB_SOFTEN,t); }
MapEnabled(int i)2445 BOOL StdMtl::MapEnabled(int i) { return maps->txmap[i].mapOn;}
2446
2447
GetDynamicsProperty(TimeValue t,int mtlNum,int propID)2448 float StdMtl::GetDynamicsProperty(TimeValue t, int mtlNum, int propID) {
2449 float val;
2450 Interval ivalid;
2451 switch(propID) {
2452 case DYN_BOUNCE:
2453 pblock->GetValue(PB_BOUNCE,t,val,ivalid);
2454 return val;
2455 case DYN_STATIC_FRICTION:
2456 pblock->GetValue(PB_STATFRIC,t,val,ivalid);
2457 return val;
2458 case DYN_SLIDING_FRICTION:
2459 pblock->GetValue(PB_SLIDFRIC,t,val,ivalid);
2460 return val;
2461 default:
2462 assert(0);
2463 return 0.0f;
2464 }
2465 }
2466
SetDynamicsProperty(TimeValue t,int mtlNum,int propID,float value)2467 void StdMtl::SetDynamicsProperty(TimeValue t, int mtlNum, int propID, float value){
2468 switch(propID) {
2469 case DYN_BOUNCE:
2470 pblock->SetValue( PB_BOUNCE, t, value);
2471 break;
2472 case DYN_STATIC_FRICTION:
2473 pblock->SetValue( PB_STATFRIC, t, value);
2474 break;
2475 case DYN_SLIDING_FRICTION:
2476 pblock->SetValue( PB_SLIDFRIC, t, value);
2477 break;
2478 default:
2479 assert(0);
2480 break;
2481 }
2482 }
2483
2484 #define MTL_HDR_CHUNK 0x4000
2485 #define STDMTL_FLAGS_CHUNK 0x5000
2486 #define STDMTL_SHADING_CHUNK 0x5004
2487 #define STDMTL_TEX_ONOFF_CHUNK 0x5002
2488 #define STDMTL_TEX_AMT0 0x5100
2489 #define STDMTL_TEX_AMT1 0x5101
2490 #define STDMTL_TEX_AMT2 0x5102
2491 #define STDMTL_TEX_AMT3 0x5103
2492 #define STDMTL_TEX_AMT4 0x5104
2493 #define STDMTL_TEX_AMT5 0x5105
2494 #define STDMTL_TEX_AMT6 0x5106
2495 #define STDMTL_TEX_AMT7 0x5107
2496 #define STDMTL_TEX_AMT8 0x5108
2497 #define STDMTL_TEX_AMT9 0x5109
2498 #define STDMTL_TEX_AMTA 0x510A
2499
2500 //#define STDMTL_BUMP1_CHUNK 0x5200
2501 #define STDMTL_VERS_CHUNK 0x5300
2502 #define STDMTL_DIM_REFLECT 0x5400
2503
2504 #define STDMTL_VERSION 9
2505
2506 // IO
Save(ISave * isave)2507 IOResult StdMtl::Save(ISave *isave) {
2508 ULONG nb;
2509 IOResult res;
2510 isave->BeginChunk(MTL_HDR_CHUNK);
2511 res = MtlBase::Save(isave);
2512 if (res!=IO_OK) return res;
2513 isave->EndChunk();
2514
2515 isave->BeginChunk(STDMTL_FLAGS_CHUNK);
2516 isave->Write(&flags,sizeof(flags),&nb);
2517 isave->EndChunk();
2518
2519 isave->BeginChunk(STDMTL_SHADING_CHUNK);
2520 isave->Write(&shading,sizeof(shading),&nb);
2521 isave->EndChunk();
2522
2523 isave->BeginChunk(STDMTL_VERS_CHUNK);
2524 int version = STDMTL_VERSION;
2525 isave->Write(&version,sizeof(version),&nb);
2526 isave->EndChunk();
2527
2528 if (dimReflect) {
2529 isave->BeginChunk(STDMTL_DIM_REFLECT);
2530 isave->EndChunk();
2531 }
2532 return IO_OK;
2533 }
2534
2535 class StdMtlCB: public PostLoadCallback {
2536 public:
2537 StdMtl *m;
2538 int loadVersion;
StdMtlCB(StdMtl * s,int loadVers)2539 StdMtlCB(StdMtl *s, int loadVers) { m = s; loadVersion = loadVers; }
proc(ILoad * iload)2540 void proc(ILoad *iload) {
2541 m->OldVerFix(loadVersion);
2542 delete this;
2543 }
2544 };
2545
2546
Load(ILoad * iload)2547 IOResult StdMtl::Load(ILoad *iload) {
2548 ULONG nb;
2549 int id;
2550 int version = 0;
2551 IOResult res;
2552 // .......... use this???
2553 iload->RegisterPostLoadCallback(new ParamBlockPLCB(oldVersions,NUMOLDVER, &curVersion, this,0));
2554 while (IO_OK==(res=iload->OpenChunk())) {
2555 switch(id = iload->CurChunkID()) {
2556 case MTL_HDR_CHUNK:
2557 res = MtlBase::Load(iload);
2558 ivalid.SetEmpty();
2559 break;
2560 case STDMTL_FLAGS_CHUNK:
2561 res = iload->Read(&flags,sizeof(flags), &nb);
2562 break;
2563 case STDMTL_SHADING_CHUNK:
2564 res = iload->Read(&shading,sizeof(shading), &nb);
2565 if (shading<0||shading>SHADE_BLINN) {
2566 shading = SHADE_PHONG;
2567 }
2568 SetShadingNoNotify(shading);
2569 break;
2570 case STDMTL_VERS_CHUNK:
2571 res = iload->Read(&version,sizeof(version), &nb);
2572 break;
2573 case STDMTL_TEX_ONOFF_CHUNK:
2574 {
2575 ULONG f;
2576 res = iload->Read(&f,sizeof(f), &nb);
2577 for (int i=0; i<NTEXMAPS; i++)
2578 maps->txmap[i].mapOn = (f&(1<<i))?1:0;
2579 }
2580 break;
2581 case STDMTL_DIM_REFLECT:
2582 dimReflect = TRUE;
2583 break;
2584 }
2585 iload->CloseChunk();
2586 if (res!=IO_OK)
2587 return res;
2588 }
2589 if (version<9) {
2590 iload->RegisterPostLoadCallback(new StdMtlCB(this,version));
2591 iload->SetObsolete();
2592 }
2593
2594 return IO_OK;
2595
2596 }
2597
2598 // Composite c_over on top of c. Assume c_over has pre-multiplied
2599 // alpha.
AlphaCompCol(Color & c,RGBA c_over)2600 inline void AlphaCompCol(Color& c, RGBA c_over) {
2601 float ia = 1.0f - c_over.a;
2602 c.r = c.r*ia + c_over.r;
2603 c.g = c.g*ia + c_over.g;
2604 c.b = c.b*ia + c_over.b;
2605 }
2606
Intens(RGBA & c)2607 static inline float Intens(RGBA& c) { return (c.r+c.g+c.b)/3.0f; }
2608
2609 static Color blackCol(0.0f,0.0f,0.0f);
2610 static Color whiteCol(1.0f,1.0f,1.0f);
2611
2612
2613 #define MAX3(a,b,c) ((a)>(b)?((a)>(c)?(a):(c)):((b)>(c)?(b):(c)))
2614
MaxRGB(Color c)2615 static inline float MaxRGB(Color c) { return MAX3(c.r,c.g,c.b); }
2616
TranspColor(ShadeContext & sc,float opac,Color & diff)2617 Color StdMtl::TranspColor(ShadeContext& sc, float opac, Color& diff) {
2618 // Compute the color of the transparent filter color
2619 if (flags&STDMTL_ADD_TRANSP) {
2620 float f = 1.0f - opac;
2621 return Color(f,f,f); //XXX
2622 }
2623 else
2624 {
2625 // Transparent Filter color mapping
2626 if (flags&STDMTL_FILT_TRANSP) {
2627 Color filt = filter;
2628 if (MAPACTIVE(ID_FI))
2629 AlphaCompCol(filt,(*maps)[ID_FI].Eval(sc));
2630 #ifdef OLDFILTER
2631 if (opac>0.5f) {
2632 // lerp (filt --> black) as opac goes ( 0.5--> 1.0)
2633 float s= 2.0f*(opac-.5f);
2634 return (1.0f-s)*filt;
2635 }
2636 else {
2637 // lerp (white --> filt) as opac goes (0.0 --> .5 )
2638 float s = 2.0f*opac;
2639 return (1.0f-s) + filt*s;
2640 }
2641 #else
2642 if (opac>0.5f) {
2643 // darken as opac goes ( 0.5--> 1.0)
2644 // so that max component reaches 0.0f when opac reaches 1.0
2645 // find max component of filt
2646 float m = (filt.r>filt.g)?filt.r:filt.g;
2647 if(filt.b>m) m = filt.b;
2648 Color fc;
2649 float d = 2.0f*(opac-.5f)*m;
2650 fc = filt-d;
2651 if (fc.r<0.0f) fc.r = 0.0f;
2652 if (fc.g<0.0f) fc.g = 0.0f;
2653 if (fc.b<0.0f) fc.b = 0.0f;
2654 return fc;
2655 }
2656 else {
2657 // lighten as opac goes ( 0.5--> 0.0)
2658 // so that min component reaches 1.0f when opac reaches 1.0
2659 // find min component of filt
2660 float m = (filt.r<filt.g)?filt.r:filt.g;
2661 if(filt.b<m) m = filt.b;
2662 Color fc;
2663 float d = (1.0f-2.0f*opac)*(1.0f-m);
2664 fc = filt+d;
2665 if (fc.r>1.0f) fc.r = 1.0f;
2666 if (fc.g>1.0f) fc.g = 1.0f;
2667 if (fc.b>1.0f) fc.b = 1.0f;
2668 return fc;
2669 }
2670 #endif
2671 }
2672 else {
2673 Color f = (1.0f-diff); // original 3DS transparency
2674 return (1.0f-opac)*f;
2675 }
2676 }
2677 }
2678
2679
2680
2681 //----------------------------------------------------------------------------------------
2682 //- Phong Shader ------------------------------------------------------------------------
2683 //----------------------------------------------------------------------------------------
2684
2685
2686 class Phong: public SShader {
2687 float fs;
2688 float shin_str;
2689 public:
2690 void Illum(ShadeContext &sc, SIllumParams &ip);
AffectReflMap(ShadeContext & sc,SIllumParams & ip,Color & rcol)2691 void AffectReflMap(ShadeContext &sc, SIllumParams &ip, Color &rcol) { rcol *= ip.spec; };
SetShininess(float shininess,float shineStr)2692 void SetShininess(float shininess, float shineStr) {
2693 fs = (float)pow(2.0,shininess*10.0);
2694 shin_str = shineStr;
2695 }
EvalHilite(float x)2696 float EvalHilite(float x) {
2697 return shin_str*(float)pow((double)cos(x*PI),(double)fs);
2698 }
2699 };
2700
whoa()2701 static void whoa(){}
2702
Illum(ShadeContext & sc,SIllumParams & ip)2703 void Phong::Illum(ShadeContext &sc, SIllumParams &ip) {
2704 LightDesc *l;
2705 Color lightCol;
2706 BOOL is_shiny;
2707 Point3 R;
2708 if (is_shiny=(ip.sh_str>0.0f))
2709 R = sc.ReflectVector();
2710
2711 // IPoint2 sp = sc.ScreenCoord();
2712 // if (sp.x==260&&sp.y==180)
2713 // whoa();
2714 for (int i=0; i<sc.nLights; i++) {
2715 l = sc.Light(i);
2716 register float NL, diffCoef;
2717 Point3 L;
2718 if (l->Illuminate(sc,ip.N,lightCol,L,NL,diffCoef)) {
2719 if (l->ambientOnly) {
2720 ip.ambIllum += lightCol;
2721 continue;
2722 }
2723 if (NL<=0.0f)
2724 continue;
2725 // diffuse
2726 if (l->affectDiffuse)
2727 ip.diffIllum += diffCoef*lightCol;
2728 if (is_shiny&&l->affectSpecular) {
2729 // specular (Phong)
2730 float c = DotProd(L,R);
2731 if (c>0.0f) {
2732 if (ip.softThresh!=0.0&&diffCoef<ip.softThresh) {
2733 float r = diffCoef/ip.softThresh;
2734 c *= Soften(r);
2735 }
2736 c = (float)pow((double)c, (double)ip.ph_exp); // could use table lookup for speed
2737 ip.specIllum += c*ip.sh_str*lightCol;
2738 }
2739 }
2740 }
2741 }
2742 ip.specIllum *= ip.spec;
2743 }
2744
2745
2746 //----------------------------------------------------------------------------------------
2747 //- Blinn Shader ------------------------------------------------------------------------
2748 //----------------------------------------------------------------------------------------
2749
2750 class Blinn: public SShader {
2751 float fs;
2752 float shin_str;
2753 public:
2754 void Illum(ShadeContext &sc, SIllumParams &ip);
AffectReflMap(ShadeContext & sc,SIllumParams & ip,Color & rcol)2755 void AffectReflMap(ShadeContext &sc, SIllumParams &ip, Color &rcol) { rcol *= ip.spec; };
SetShininess(float shininess,float shineStr)2756 void SetShininess(float shininess, float shineStr) {
2757 fs = (float)pow(2.0,shininess*10.0);
2758 shin_str = shineStr;
2759 }
EvalHilite(float x)2760 float EvalHilite(float x) {
2761 return shin_str*(float)pow((double)cos(x*PI),(double)fs);
2762 }
2763 };
2764
2765
Illum(ShadeContext & sc,SIllumParams & ip)2766 void Blinn::Illum(ShadeContext &sc, SIllumParams &ip) {
2767 LightDesc *l;
2768 Color lightCol;
2769
2770 // Blinn style phong
2771 BOOL is_shiny=(ip.sh_str>0.0f)?1:0;
2772 double ph_exp = double(ip.ph_exp)*4.0; // This is to make the hilite compatible with normal phong
2773 for (int i=0; i<sc.nLights; i++) {
2774 l = sc.Light(i);
2775 register float NL, diffCoef;
2776 Point3 L;
2777 if (l->Illuminate(sc,ip.N,lightCol,L,NL,diffCoef)) {
2778 if (l->ambientOnly) {
2779 ip.ambIllum += lightCol;
2780 continue;
2781 }
2782 if (NL<=0.0f)
2783 continue;
2784
2785 // diffuse
2786 if (l->affectDiffuse)
2787 ip.diffIllum += diffCoef*lightCol;
2788
2789 // specular (Phong)
2790 if (is_shiny&&l->affectSpecular) {
2791 Point3 H = FNormalize(L-ip.V);
2792 float c = DotProd(ip.N,H);
2793 if (c>0.0f) {
2794 if (ip.softThresh!=0.0&&diffCoef<ip.softThresh) {
2795 c *= Soften(diffCoef/ip.softThresh);
2796 }
2797 c = (float)pow((double)c, ph_exp); // could use table lookup for speed
2798 ip.specIllum += c*ip.sh_str*lightCol;
2799 }
2800 }
2801 }
2802 }
2803 ip.specIllum *= ip.spec;
2804 }
2805
2806 //----------------------------------------------------------------------------------------
2807 //- Metal Shader ------------------------------------------------------------------------
2808 //----------------------------------------------------------------------------------------
2809
2810 class Metal: public SShader {
2811 float fm2inv, fshin_str;
2812 public:
2813 void Illum(ShadeContext &sc, SIllumParams &ip);
AffectReflMap(ShadeContext & sc,SIllumParams & ip,Color & rcol)2814 void AffectReflMap(ShadeContext &sc, SIllumParams &ip, Color &rcol) { rcol *= ip.diff; };
2815 void SetShininess(float shininess, float shineStr);
2816 float EvalHilite(float x);
2817 };
2818
CompK(float f0)2819 float CompK(float f0) {
2820 return float(2.0*sqrt(f0)/sqrt(1.0-f0));
2821 }
2822
fres_metal(float c,float k)2823 float fres_metal(float c, float k) {
2824 float b,rpl,rpp,c2;
2825 b = k*k + 1.0f;
2826 c2 = c*c;
2827 rpl = (b*c2-2*c+1)/(b*c2+2*c+1);
2828 rpp = (b-2*c+c2)/(b+2*c+c2);
2829 return(.5f*(rpl+rpp));
2830 }
2831
Illum(ShadeContext & sc,SIllumParams & ip)2832 void Metal::Illum(ShadeContext &sc, SIllumParams &ip) {
2833 LightDesc *l;
2834 Color lightCol;
2835 BOOL gotKav = FALSE;
2836 float kav, fav0, m2inv,NV;
2837
2838 //IPoint2 sp = sc.ScreenCoord();
2839
2840 BOOL is_shiny;
2841 if (ip.sh_str>0.0f) {
2842 NV = -DotProd(ip.N,ip.V); // N dot V: view vector is TOWARDS us.
2843 is_shiny = 1;
2844 float r = 1.0f-ip.shine;
2845 if (r==0.0f) r = .00001f;
2846 m2inv = 1.0f/(r*r);
2847 }
2848 else
2849 is_shiny = 0;
2850
2851
2852 for (int i=0; i<sc.nLights; i++) {
2853 l = sc.Light(i);
2854 register float NL, diffCoef;
2855 Point3 L;
2856
2857 if (!l->Illuminate(sc,ip.N,lightCol,L,NL,diffCoef))
2858 continue;
2859
2860 if (l->ambientOnly) {
2861 ip.ambIllum += lightCol;
2862 continue;
2863 }
2864
2865 // diffuse
2866 if (NL>0.0f&&l->affectDiffuse) // TBD is the NL test necessary?
2867 ip.diffIllum += diffCoef*lightCol;
2868
2869 if (is_shiny&&l->affectSpecular) { // SPECULAR
2870 Color fcol;
2871 float LH,NH,VH;
2872 float sec2; // Was double?? TBD
2873 Point3 H;
2874
2875 if (NV<0.0f) continue;
2876
2877 H = FNormalize(L-ip.V);
2878
2879 LH = DotProd(L,H); // cos(phi)
2880 NH = DotProd(ip.N,H); // cos(alpha)
2881 if (NH==0.0f) continue;
2882 VH = -DotProd(ip.V,H);
2883
2884 // compute geometrical attenuation factor
2885 float G = (NV<NL)? (2.0f*NV*NH/VH): (2.0f*NL*NH/VH);
2886 if (G>0.0f) {
2887 // Compute (approximate) indices of refraction
2888 // this can be factored out for non-texture-mapped mtls
2889 if (!gotKav) {
2890 fav0 = Intens(ip.diff);
2891 if (fav0>=1.0f) fav0 = .9999f;
2892 kav = CompK(fav0);
2893 gotKav = TRUE;
2894 }
2895
2896 float fav = fres_metal(LH,kav);
2897 float t = (fav-fav0)/(1.0f-fav0);
2898 fcol = (1.0f-t)*ip.diff + Color(t,t,t);
2899
2900 // Beckman distribution (from Cook-Torrance paper)
2901 sec2 = 1.0f/(NH*NH); // 1/sqr(cos)
2902 float D = (.5f/PI)*sec2*sec2*m2inv*(float)exp((1.0f-sec2)*m2inv);
2903 if (G>1.0f) G = 1.0f;
2904 float Rs = ip.sh_str*D*G/(NV+.05f);
2905 ip.specIllum += fcol*Rs*lightCol;
2906 }
2907 }
2908 }
2909 ip.diffIllum *= 1.0f - ip.sh_str;
2910 }
2911
2912
SetShininess(float shininess,float shineStr)2913 void Metal::SetShininess(float shininess, float shineStr) {
2914 float r = 1.0f-shininess;
2915 if (r==0.0f) r = .00001f;
2916 fm2inv = 1.0f/(r*r);
2917 fshin_str = shineStr;
2918 }
2919
EvalHilite(float x)2920 float Metal::EvalHilite(float x) {
2921 float c = (float)cos(x*PI);
2922 float sec2 = 1.0f/(c*c); /* 1/sqr(cos) */
2923 return fshin_str*(.5f/PI)*sec2*sec2*fm2inv*(float)exp((1.0f-sec2)*fm2inv);
2924 }
2925
2926 //-------------------------------------------------------------------------
2927
2928
2929 static Phong phongShader;
2930 static Blinn blinnShader;
2931 static Metal metalShader;
2932
2933 static SShader *shaders[4] = {
2934 &phongShader, // CONST
2935 &phongShader,
2936 &metalShader,
2937 &blinnShader
2938 };
2939
GetShaderFromId(int s)2940 static SShader *GetShaderFromId(int s) { return shaders[s]; };
2941
2942 #define DOMAP(i) (sc.doMaps&&(*maps)[i].IsActive())
2943
Shade(ShadeContext & sc)2944 void StdMtl::Shade(ShadeContext& sc) {
2945 SIllumParams ip;
2946 Color lightCol,rescol, diffIllum0;
2947 float opac;
2948 RGBA mval;
2949 Point3 N0,P;
2950 BOOL bumped = FALSE;
2951 if (gbufID) sc.SetGBufferID(gbufID);
2952
2953 ip.flags = flags;
2954 ip.softThresh = softThresh;
2955 ip.diffIllum = blackCol;
2956 ip.specIllum = blackCol;
2957 ip.ambIllum = blackCol;
2958 ip.amb = ambient;
2959 ip.diff = diffuse;
2960 ip.spec = specular;
2961
2962 opac = opacity;
2963
2964 if (sc.mode==SCMODE_SHADOW) {
2965 // Opacity mapping;
2966 if (DOMAP(ID_OP))
2967 opac = (*maps)[ID_OP].LerpEvalMono(sc,opac);
2968
2969 // "Shadow mode": This just computes the transparency, which is all
2970 // you need for shadowing.
2971 if (opac!=1.0f||opfall!=0.0f) {
2972 if (opfall!=0.0f) {
2973 ip.N = (shading==SHADE_CONST)?sc.GNormal():sc.Normal();
2974 ip.V = sc.V(); // get unit view vector
2975 float d = (float)fabs(DotProd(ip.N,ip.V));
2976 if (flags&STDMTL_FALLOFF_OUT) d = 1.0f-d;
2977 opac *= (1.0f-opfall*d);
2978 }
2979
2980 // Transparency may use diffuse color mapping
2981 if ((flags&STDMTL_ADD_TRANSP|STDMTL_FILT_TRANSP)==0) {
2982 if (DOMAP(ID_DI)) {
2983 mval = (*maps)[ID_DI].Eval(sc);
2984 AlphaCompCol(ip.diff,mval);
2985 }
2986 }
2987 // Compute the transpareny color
2988 sc.out.t = TranspColor(sc, opac, ip.diff);
2989 }
2990 else
2991 sc.out.t = blackCol;
2992 return;
2993 }
2994
2995 N0 = ip.N = sc.Normal();
2996
2997 if (shading==SHADE_CONST) {
2998 ip.N = sc.GNormal();
2999 bumped = TRUE;
3000 sc.SetNormal(ip.N);
3001 }
3002
3003 P = sc.P();
3004 ip.V = sc.V(); // get unit view vector
3005
3006 // Do texture mapping
3007
3008 // Bump mapping: Do this FIRST so other maps can use the perturbed normal
3009 if (DOMAP(ID_BU)) {
3010 Point3 dn = (*maps)[ID_BU].EvalNormalPerturb(sc);
3011 bumped = TRUE;
3012 ip.N = FNormalize(ip.N + (sc.backFace?-dn:dn));
3013 sc.SetNormal(ip.N);
3014 }
3015
3016 // Diffuse color mapping
3017 if (DOMAP(ID_DI)) {
3018 mval = (*maps)[ID_DI].Eval(sc);
3019 AlphaCompCol(ip.diff,mval);
3020 if (flags&STDMTL_LOCK_ADTEX)
3021 AlphaCompCol(ip.amb,mval);
3022 }
3023
3024 // Ambient color mapping
3025 if (!(flags&STDMTL_LOCK_ADTEX)) {
3026 if (DOMAP(ID_AM)) {
3027 AlphaCompCol(ip.amb, (*maps)[ID_AM].Eval(sc));
3028 }
3029 }
3030
3031 // Specular color mapping
3032 if (DOMAP(ID_SP))
3033 AlphaCompCol(ip.spec,(*maps)[ID_SP].Eval(sc));
3034
3035 // Opacity mapping;
3036 if (DOMAP(ID_OP)) {
3037 opac = (*maps)[ID_OP].LerpEvalMono(sc,opac);
3038 }
3039
3040 // Shininess mapping
3041 if (DOMAP(ID_SH)) {
3042 //ip.shine = shininess*(*maps)[ID_SH].EvalMono(sc);
3043 ip.shine = (*maps)[ID_SH].LerpEvalMono(sc,shininess);
3044 ip.ph_exp = (float)pow(2.0,ip.shine*10.0); // expensive.!! TBD
3045 }
3046 else {
3047 ip.shine = shininess;
3048 ip.ph_exp = phongexp;
3049 }
3050
3051 // Shininess strength mapping
3052 ip.sh_str = (DOMAP(ID_SS))? (*maps)[ID_SS].LerpEvalMono(sc,shine_str): shine_str;
3053
3054 // Self illumination mapping
3055 float self_i = (DOMAP(ID_SI))? (*maps)[ID_SI].LerpEvalMono(sc,self_illum) : self_illum;
3056
3057 curShader->Illum(sc,ip);
3058
3059 diffIllum0 = ip.diffIllum; // save this for reflection dimming
3060
3061 // Apply self illumination
3062 if (self_i>0.0f) {
3063 ip.diffIllum = (self_i>=1.0f) ? whiteCol: ip.diffIllum*(1.0f-self_i) + self_i;
3064 }
3065
3066 ip.diffIllum = ip.amb*(sc.ambientLight+ip.ambIllum) + ip.diff*ip.diffIllum;
3067
3068 if (DOMAP(ID_RR)) {
3069 // Set up for opacity for Refraction map.
3070 opac *= 1.0f-(*maps)[ID_RR].amount;
3071
3072 // Make more opaque where specular hilite occurs:
3073 float a_s = MaxRGB(ip.specIllum);
3074 if (a_s>1.0f) a_s = 1.0f;
3075 sc.out.c = opac*ip.diffIllum + ip.specIllum;
3076 opac = opac + a_s - opac*a_s;
3077
3078 // Evaluate refraction map, filtered by filter color.
3079 Texmap *refrmap = (*maps)[ID_RR].map;
3080 AColor rcol;
3081 sc.SetIOR(ioRefract);
3082 if (refrmap->HandleOwnViewPerturb())
3083 rcol = refrmap->EvalColor(sc);
3084 else
3085 rcol = sc.EvalEnvironMap(refrmap, sc.RefractVector(ioRefract));
3086 sc.out.c += Color(rcol.r,rcol.g,rcol.b)*TranspColor(sc, opac, ip.diff);
3087 sc.out.t.Black(); // no transparency when doing refraction
3088 }
3089 else {
3090 if (opac!=1.0f||opfall!=0.0f) {
3091 if (opfall!=0.0f) {
3092 float d = (float)fabs(DotProd(ip.N,ip.V));
3093 if (flags&STDMTL_FALLOFF_OUT) d = 1.0f-d;
3094 opac *= (1.0f-opfall*d);
3095 }
3096
3097 // Make more opaque where specular hilite occurs, so you
3098 // can still see the hilite:
3099 float a_s = MaxRGB(ip.specIllum);
3100 if (a_s>1.0f) a_s = 1.0f;
3101 sc.out.c = opac*ip.diffIllum + ip.specIllum;
3102 opac = opac + a_s - opac*a_s;
3103
3104 // Compute the color of the transparent filter color
3105 sc.out.t = TranspColor(sc, opac, ip.diff);
3106 }
3107 else {
3108 sc.out.t = blackCol;
3109 sc.out.c = ip.diffIllum + ip.specIllum;
3110 }
3111 }
3112
3113 // Evaluate reflection map.
3114 if (DOMAP(ID_RL)) {
3115 AColor rcol;
3116 Texmap *reflmap = (*maps)[ID_RL].map;
3117 if (reflmap->HandleOwnViewPerturb()) {
3118 sc.TossCache(reflmap);
3119 rcol = reflmap->EvalColor(sc);
3120 }
3121 else
3122 rcol = sc.EvalEnvironMap(reflmap, sc.ReflectVector());
3123 Color rc(rcol.r,rcol.g,rcol.b);
3124 curShader->AffectReflMap(sc,ip,rc);
3125 float r = rcol.a*(*maps)[ID_RL].amount;
3126 if (dimReflect) {
3127 float dimfact = ((1.0f-dimIntens)*Intens(diffIllum0)*dimMult + dimIntens);
3128 r *= dimfact;
3129 }
3130 sc.out.c += (rc*r);
3131 }
3132 if (bumped) sc.SetNormal(N0);
3133 }
3134
EvalDisplacement(ShadeContext & sc)3135 float StdMtl::EvalDisplacement(ShadeContext& sc) {
3136 if (DOMAP(ID_DP))
3137 return (*maps)[ID_DP].EvalMono(sc);
3138 else return 0.0f;
3139 }
3140
DisplacementValidity(TimeValue t)3141 Interval StdMtl::DisplacementValidity(TimeValue t) {
3142 if (MAPACTIVE(ID_DP)) {
3143 Interval iv;
3144 iv.SetInfinite();
3145 maps->txmap[ID_DP].Update(t,iv);
3146 return iv;
3147 }
3148 else
3149 return FOREVER;
3150 }
3151
3152
3153
3154
3155