1 /*===========================================================================*\
2 | File: Splat.cpp
3 |
4 | Purpose: A 3D Map for creating splatd surface textures.
5 | This is a port of the 3D Studio/DOS SXP by Dan Silva.
6 |
7 | History: Mark Meier, Began 02/03/97.
8 | MM, Last Change 02/03/97.
9 | Updated to Param Block2 by Peter Watje 12/1/1998
10 | MM, 02/99, Bug fix.
11 \*===========================================================================*/
12 /*===========================================================================*\
13 | Include Files
14 \*===========================================================================*/
15 #include "procmaps.h"
16 #include "iparamm2.h"
17 #include "resource.h"
18 #include "resourceOverride.h"
19 #include "macrorec.h"
20
21 /*===========================================================================*\
22 | Miscellaneous Defines
23 \*===========================================================================*/
24
25 #define SHOW_3DMAPS_WITH_2D
26
27 // The unique ClassID
28 static Class_ID splatClassID(SPLAT_CLASS_ID, 0);
29
30 // This is the number of colors used
31 #define NUM_COLORS 2
32
33 // This is the number of sub-texmaps used
34 #define NUM_SUB_TEXMAPS 2
35
36 // This is the version number of the IPAS SXP files that can be read
37 #define SPLAT_SXP_VERSION 0xE041
38
39 #define EPSILON 0.02f
40
41 struct Col24 {
42 ULONG r, g, b;
43 };
44
ColorFromCol24(Col24 a)45 static Color ColorFromCol24(Col24 a) {
46 Color c;
47 c.r = (float)a.r/255.0f;
48 c.g = (float)a.g/255.0f;
49 c.b = (float)a.b/255.0f;
50 return c;
51 }
52
53 #pragma pack(1)
54 struct SplatState {
55 ulong version;
56 float size, thresh;
57 int init;
58 Col24 col1, col2;
59 float strength;
60 };
61 #pragma pack()
62
63 // These are various resource IDs
64 static int colID[2] = { IDC_COL1, IDC_COL2 };
65 static int subTexId[NUM_SUB_TEXMAPS] = { IDC_TEX1, IDC_TEX2 };
66 static int mapOnId[NUM_SUB_TEXMAPS] = { IDC_MAPON1, IDC_MAPON2 };
67
68 // Forward references
69 //class Splat;
70 //class SplatDlgProc;
71
72 /*===========================================================================*\
73 | Splat 3D Texture Map Plug-In Class
74 \*===========================================================================*/
75 class Splat : public Tex3D {
76 // This allows the class that manages the UI to access the private
77 // data members of this class.
78 // friend class SplatDlg;
79
80 // This is the function that actually computes the speckling.
81 float splatter(Point3 p);
82
83 // These are the current colors from the color swatch controls.
84 Color col[NUM_COLORS];
85
86 // These are the parameters managed by the parameter map
87 float size;
88 float thresh;
89 int iter;
90 Point3 col1, col2;
91
92 // This points to the XYZGen instance used to handle the
93 // 'Coordinates' rollup in the materials editor.
94 // This is reference #0 of this class.
95 XYZGen *xyzGen;
96 // These are the sub-texmaps. If these are set by the user
97 // then the color of our texture is affected by the sub-texmaps
98 // and not the color swatches.
99 // These are reference #2 and #3 of this class.
100 Texmap *subTex[NUM_SUB_TEXMAPS];
101 // Indicates if a sub-texmap is to be used or not
102 // This holds the validity interval of the texmap.
103 Interval texValidity;
104 // This is the version of the texture loaded from disk.
105 int fileVersion;
106 // This points to the ParamDlg instance used to manage the UI
107 // SplatDlg *paramDlg;
108
109 #ifdef SHOW_3DMAPS_WITH_2D
110 TexHandle *texHandle;
111 Interval texHandleValid;
112 #endif
113
114 public:
115 static ParamDlg* xyzGenDlg;
116 // This is the parameter block which manages the data for the
117 // spinner and color swatch controls.
118 // This is reference #1 of this class.
119 IParamBlock2 *pblock;
120 BOOL mapOn[NUM_SUB_TEXMAPS];
121 // --- Methods inherited from Animatable ---
ClassID()122 Class_ID ClassID() { return splatClassID; }
SuperClassID()123 SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; }
GetClassName(TSTR & s)124 void GetClassName(TSTR& s) { s= GetString(IDS_DS_SPLAT); }
DeleteThis()125 void DeleteThis() { delete this; }
126
127 // We have 4 sub-animatables. These are the xyzGen,
128 // the pblock, and the two sub-texmaps
NumSubs()129 int NumSubs() { return 2+NUM_SUB_TEXMAPS; }
130 Animatable* SubAnim(int i);
131 TSTR SubAnimName(int i);
SubNumToRefNum(int subNum)132 int SubNumToRefNum(int subNum) { return subNum; }
133
134 // --- Methods inherited from ReferenceMaker ---
135 // We have 4 references. These are the xyzGen,
136 // the pblock, and the two sub-texmaps
NumRefs()137 int NumRefs() { return 2+NUM_SUB_TEXMAPS; }
138 RefTargetHandle GetReference(int i);
139 void SetReference(int i, RefTargetHandle rtarg);
140 RefResult NotifyRefChanged(Interval changeInt,
141 RefTargetHandle hTarget, PartID& partID, RefMessage message);
142 IOResult Save(ISave *isave);
143 IOResult Load(ILoad *iload);
144
145 // --- Methods inherited from ReferenceTarget ---
146 RefTargetHandle Clone(RemapDir &remap = DefaultRemapDir());
147
148 // --- Methods inherited from MtlBase ---
LocalRequirements(int subMtlNum)149 ULONG LocalRequirements(int subMtlNum) {
150 return xyzGen->Requirements(subMtlNum);
151 }
LocalMappingsRequired(int subMtlNum,BitArray & mapreq,BitArray & bumpreq)152 void LocalMappingsRequired(int subMtlNum, BitArray & mapreq, BitArray &bumpreq) {
153 xyzGen->MappingsRequired(subMtlNum,mapreq,bumpreq);
154 }
155 void Update(TimeValue t, Interval& ivalid);
156 void Init();
157 void Reset();
158 Interval Validity(TimeValue t);
159 ParamDlg* CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
NumSubTexmaps()160 int NumSubTexmaps() { return NUM_SUB_TEXMAPS; }
161 Texmap* GetSubTexmap(int i);
162 void SetSubTexmap(int i, Texmap *m);
163 TSTR GetSubTexmapSlotName(int i);
164
165 // --- Methods inherited from Texmap ---
GetTheXYZGen()166 XYZGen *GetTheXYZGen() { return xyzGen; }
167 RGBA EvalColor(ShadeContext& sc);
168 Point3 EvalNormalPerturb(ShadeContext& sc);
169
170 // --- Methods inherited from Tex3D ---
171 void ReadSXPData(TCHAR *name, void *sxpdata);
172
173 // --- Methods of Splat ---
174 Splat();
~Splat()175 ~Splat() {
176 #ifdef SHOW_3DMAPS_WITH_2D
177 DiscardTexHandle();
178 #endif
179 }
180 void SwapInputs();
181 void NotifyChanged();
182 void SetSize(float f, TimeValue t);
183 void SetThresh(float f, TimeValue t);
184 void SetIter(int i, TimeValue t);
185 void SetColor(int i, Color c, TimeValue t);
186 void ClampFloat(float &f, float min, float max);
187 void ClampInt(int &i, int min, int max);
188
189 #ifdef SHOW_3DMAPS_WITH_2D
DiscardTexHandle()190 void DiscardTexHandle() {
191 if (texHandle) {
192 texHandle->DeleteThis();
193 texHandle = NULL;
194 }
195 }
SupportTexDisplay()196 BOOL SupportTexDisplay() { return TRUE; }
ActivateTexDisplay(BOOL onoff)197 void ActivateTexDisplay(BOOL onoff) {
198 if (!onoff) DiscardTexHandle();
199 }
200 DWORD_PTR GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker);
201 #endif SHOW_3DMAPS_WITH_2D
202
203
204 // JBW: direct ParamBlock access is added
NumParamBlocks()205 int NumParamBlocks() { return 1; } // return number of ParamBlocks in this instance
GetParamBlock(int i)206 IParamBlock2* GetParamBlock(int i) { return pblock; } // return i'th ParamBlock
GetParamBlockByID(BlockID id)207 IParamBlock2* GetParamBlockByID(BlockID id) { return (pblock->ID() == id) ? pblock : NULL; } // return id'd ParamBlock
208 BOOL SetDlgThing(ParamDlg* dlg);
209
IsLocalOutputMeaningful(ShadeContext & sc)210 bool IsLocalOutputMeaningful( ShadeContext& sc ) { return true; }
211 };
212
213 // This is the Class Descriptor for the Splat 3D Texture plug-in
214 class SplatClassDesc : public ClassDesc2 {
215 public:
IsPublic()216 int IsPublic() { return GetAppID() != kAPP_VIZR; }
Create(BOOL loading)217 void * Create(BOOL loading) { return new Splat; }
ClassName()218 const TCHAR * ClassName() { return GetString(IDS_DS_SPLAT_CDESC); } // mjm - 2.3.99
SuperClassID()219 SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; }
ClassID()220 Class_ID ClassID() { return splatClassID; }
Category()221 const TCHAR* Category() { return TEXMAP_CAT_3D; }
222 // JBW: new descriptor data accessors added. Note that the
223 // internal name is hardwired since it must not be localized.
InternalName()224 const TCHAR* InternalName() { return _T("splat"); } // returns fixed parsable name (scripter-visible name)
HInstance()225 HINSTANCE HInstance() { return hInstance; } // returns owning module handle
226 };
227 static SplatClassDesc splatCD;
GetSplatDesc()228 ClassDesc *GetSplatDesc() { return &splatCD; }
229 ParamDlg* Splat::xyzGenDlg;
230
231 /*===========================================================================*\
232 | Class to Manage the User Interface in the Materials Editor
233 \*===========================================================================*/
234 /*
235 class SplatDlg: public ParamDlg {
236 public:
237 // This is our UI rollup page window handle in the materials editor
238 HWND hParamDlg;
239 // Window handle of the materials editor dialog itself
240 HWND hMedit;
241 // Interface for calling methods provided by MAX
242 IMtlParams *ip;
243 // The current Splat being edited.
244 Splat *theTex;
245 // Parameter Map for handling UI controls
246 IParamMap *pmap;
247 // Custom buttons for texture maps
248 ICustButton *iCustButton[NUM_SUB_TEXMAPS];
249 // Custom conrols for the colors
250 IColorSwatch *cs[NUM_COLORS];
251 // This is used inside the SetTime method to only update the UI
252 // controls when the time slider has changed
253 TimeValue curTime;
254 // Point to the XYZGenDlg we use
255 ParamDlg *xyzGenDlg;
256 BOOL valid;
257 BOOL isActive;
258 TexDADMgr dadMgr;
259
260 // --- Methods inherited from ParamDlg ---
261 Class_ID ClassID();
262 void SetThing(ReferenceTarget *m);
263 ReferenceTarget* GetThing();
264 void SetTime(TimeValue t);
265 int FindSubTexFromHWND(HWND hw);
266 void ReloadDialog();
267 void ActivateDlg(BOOL onOff);
268 void DeleteThis() { delete this; }
269
270 // --- SplatDlg Methods ---
271 SplatDlg(HWND hwMtlEdit, IMtlParams *imp, Splat *m);
272 ~SplatDlg();
273 INT_PTR PanelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
274 void UpdateSubTexNames();
275 void LoadDialog();
276 void UpdateMtlDisplay() { ip->MtlChanged(); }
277 void Invalidate();
278 };
279 */
280 /*===========================================================================*\
281 | Parameter Map Related Data and Methods
282 \*===========================================================================*/
283 // Parameter block indices
284 /*
285 #define PB_SIZE 0
286 #define PB_THRESH 1
287 #define PB_ITER 2
288 #define PB_COL1 3
289 #define PB_COL2 4
290 */
291 // Spinner limits
292 #define MIN_SIZE 0.001f
293 #define MAX_SIZE 999999999.0f
294
295 #define MIN_THRESH 0.0f
296 #define MAX_THRESH 1.0f
297
298 #define MIN_ITER 1
299 #define MAX_ITER 10
300
301 // Paramter block version number
302 #define SPLAT_PB_VERSION 2
303
304
305 enum { splat_params }; // pblock ID
306 // grad_params param IDs
307 enum
308 {
309 splat_size,splat_iteration,splat_threshold,
310 splat_color1, splat_color2,
311 splat_map1, splat_map2,
312 splat_mapon1,splat_mapon2,
313 splat_coords, // access for UVW mapping
314 };
315
316
317 static ParamBlockDesc2 splat_param_blk ( splat_params, _T("parameters"), 0, &splatCD, P_AUTO_CONSTRUCT + P_AUTO_UI, 1,
318 //rollout
319 IDD_SPLAT, IDS_DS_SPLAT_PARAMS, 0, 0, NULL,
320 // params
321
322
323 splat_size, _T("size"), TYPE_FLOAT, P_ANIMATABLE, IDS_DS_SIZE,
324 p_default, 40.f,
325 p_range, MIN_SIZE, MAX_SIZE,
326 p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_SIZE_EDIT,IDC_SIZE_SPIN, 0.1f,
327 end,
328 splat_iteration, _T("iterations"), TYPE_INT, P_ANIMATABLE, IDS_DS_ITER,
329 p_default, 4,
330 p_range, MIN_ITER, MAX_ITER,
331 p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_ITER_EDIT,IDC_ITER_SPIN, 1.f,
332 end,
333 splat_threshold, _T("threshold"), TYPE_FLOAT, P_ANIMATABLE, IDS_DS_THRESH,
334 p_default, 0.2f,
335 p_range, MIN_THRESH, MAX_THRESH,
336 p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_THRESH_EDIT,IDC_THRESH_SPIN, 0.1f,
337 end,
338 splat_color1, _T("color1"), TYPE_RGBA, P_ANIMATABLE, IDS_DS_COL1,
339 p_default, Color(0.7f, 0.8f, 0.8f),
340 p_ui, TYPE_COLORSWATCH, IDC_COL1,
341 end,
342 splat_color2, _T("color2"), TYPE_RGBA, P_ANIMATABLE, IDS_DS_COL2,
343 p_default, Color(0.2f, 0.5f, 1.0f),
344 p_ui, TYPE_COLORSWATCH, IDC_COL2,
345 end,
346 splat_map1, _T("map1"), TYPE_TEXMAP, P_OWNERS_REF, IDS_PW_MAP1,
347 p_refno, 2,
348 p_subtexno, 0,
349 p_ui, TYPE_TEXMAPBUTTON, IDC_TEX1,
350 end,
351 splat_map2, _T("map2"), TYPE_TEXMAP, P_OWNERS_REF, IDS_PW_MAP2,
352 p_refno, 3,
353 p_subtexno, 1,
354 p_ui, TYPE_TEXMAPBUTTON, IDC_TEX2,
355 end,
356 splat_mapon1, _T("map1On"), TYPE_BOOL, 0, IDS_PW_MAPON1,
357 p_default, TRUE,
358 p_ui, TYPE_SINGLECHEKBOX, IDC_MAPON1,
359 end,
360 splat_mapon2, _T("map2On"), TYPE_BOOL, 0, IDS_PW_MAPON2,
361 p_default, TRUE,
362 p_ui, TYPE_SINGLECHEKBOX, IDC_MAPON2,
363 end,
364 splat_coords, _T("coords"), TYPE_REFTARG, P_OWNERS_REF, IDS_PW_COORDINATES,
365 p_refno, 0,
366 end,
367
368 end
369 );
370
371 /*
372 // Array of parameter descriptors
373 static ParamUIDesc paramDesc[] = {
374 ParamUIDesc(
375 PB_SIZE,
376 EDITTYPE_FLOAT,
377 IDC_SIZE_EDIT,IDC_SIZE_SPIN,
378 MIN_SIZE, MAX_SIZE,
379 SPIN_AUTOSCALE),
380
381 ParamUIDesc(
382 PB_THRESH,
383 EDITTYPE_FLOAT,
384 IDC_THRESH_EDIT,IDC_THRESH_SPIN,
385 MIN_THRESH, MAX_THRESH,
386 SPIN_AUTOSCALE),
387
388 ParamUIDesc(
389 PB_ITER,
390 EDITTYPE_INT,
391 IDC_ITER_EDIT,IDC_ITER_SPIN,
392 MIN_ITER, MAX_ITER,
393 SPIN_AUTOSCALE),
394
395 ParamUIDesc(PB_COL1, TYPE_COLORSWATCH, IDC_COL1),
396 ParamUIDesc(PB_COL2, TYPE_COLORSWATCH, IDC_COL2)
397 };
398 */
399 // The number of descriptors in the paramDesc array
400 #define PARAMDESC_LENGTH 5
401
402 // Parameter block parameters
403 static ParamBlockDescID pbdesc[] = {
404 { TYPE_FLOAT, NULL, TRUE, splat_size }, // size
405 { TYPE_FLOAT, NULL, TRUE, splat_threshold }, // thresh
406 { TYPE_INT, NULL, TRUE, splat_iteration }, // iter
407 { TYPE_RGBA, NULL, TRUE, splat_color1 }, // color 1
408 { TYPE_RGBA, NULL, TRUE, splat_color2 } // color 2
409 };
410 // The number of parameters in the parameter block
411 #define PB_LENGTH 5
412
413 static ParamVersionDesc versions[] = {
414 ParamVersionDesc(pbdesc,5,1) // Version 1 params
415 };
416
417 // The names of the parameters in the parameter block
418 static int nameIDs[] = { IDS_DS_SIZE, IDS_DS_THRESH, IDS_DS_ITER, IDS_DS_COL1, IDS_DS_COL2 };
419 /*
420 // This is the class that allows the sub-map buttons to be processed.
421 class SplatDlgProc : public ParamMapUserDlgProc {
422 public:
423 SplatDlg *theDlg;
424 SplatDlgProc(SplatDlg *s) { theDlg = s; }
425 INT_PTR DlgProc(TimeValue t, IParamMap *map,
426 HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
427 void DeleteThis() { delete this; }
428 };
429
430 // This is the dialog proc to process the texmap buttons
431 INT_PTR SplatDlgProc::DlgProc(TimeValue t, IParamMap *map,
432 HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
433 theDlg->isActive = TRUE;
434 BOOL res = theDlg->PanelProc(hWnd, msg, wParam, lParam);
435 theDlg->isActive = FALSE;
436 return res;
437 }
438
439 INT_PTR SplatDlg::PanelProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
440 int id = LOWORD(wParam);
441 int code = HIWORD(wParam);
442 switch (msg) {
443 case WM_INITDIALOG: {
444 for (int i = 0; i < NUM_COLORS; i++)
445 cs[i] = GetIColorSwatch(GetDlgItem(hParamDlg, colID[i]),
446 theTex->col[i], theTex->GetSubTexmapSlotName(i).data());
447 for (i = 0; i < NUM_SUB_TEXMAPS; i++) {
448 iCustButton[i] = GetICustButton(GetDlgItem(hWnd, subTexId[i]));
449 iCustButton[i]->SetDADMgr(&dadMgr);
450 SetCheckBox(hWnd, mapOnId[i], theTex->mapOn[i]);
451 }
452 return TRUE;
453 }
454 break;
455
456 case WM_COMMAND:
457 switch (id) {
458 case IDC_TEX1:
459 PostMessage(hMedit, WM_TEXMAP_BUTTON, 0, (LPARAM)theTex);
460 break;
461
462 case IDC_TEX2:
463 PostMessage(hMedit, WM_TEXMAP_BUTTON, 1, (LPARAM)theTex);
464 break;
465
466 case IDC_SWAP: {
467 theTex->SwapInputs();
468 IParamBlock *pb = (IParamBlock *)pmap->GetParamBlock();
469 pb->SetValue(PB_COL1, curTime, theTex->col[0]);
470 pb->SetValue(PB_COL2, curTime, theTex->col[1]);
471 pmap->Invalidate();
472 UpdateSubTexNames();
473 UpdateMtlDisplay();
474 theTex->NotifyChanged();
475 }
476 break;
477
478 case IDC_MAPON1:
479 theTex->mapOn[0] = GetCheckBox(hWnd, id);
480 theTex->NotifyChanged();
481 UpdateMtlDisplay();
482 break;
483
484 case IDC_MAPON2:
485 theTex->mapOn[1] = GetCheckBox(hWnd, id);
486 theTex->NotifyChanged();
487 UpdateMtlDisplay();
488 break;
489 }
490 break;
491
492 case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_MOUSEMOVE:
493 ip->RollupMouseMessage(hWnd, msg, wParam, lParam);
494 return FALSE;
495
496 case WM_PAINT:
497 if (!valid) {
498 valid = TRUE;
499 ReloadDialog();
500 }
501 break;
502
503 case WM_CLOSE:
504 break;
505
506 case WM_DESTROY:
507 break;
508 }
509 return FALSE;
510 }
511 */
512 /*===========================================================================*\
513 | SplatDlg Methods
514 \*===========================================================================*/
515 // --- SplatDlg Methods ---
516 // Constructor.
517 // This is called from within the Splat::CreateParamDlg method. That
518 // method is passed the handle to the materials editor dialog, and an
519 // interface for calling methods of MAX. These are passed in here and stored.
520 /*
521 SplatDlg::SplatDlg(HWND hwMtlEdit, IMtlParams *imp, Splat *m) {
522 dadMgr.Init(this);
523 hMedit = hwMtlEdit;
524 ip = imp;
525 theTex = m;
526 valid = FALSE;
527 isActive = FALSE;
528 curTime = ip->GetTime();
529
530 // This call allocates a new instance of the XYZGen class
531 xyzGenDlg = theTex->xyzGen->CreateParamDlg(hMedit, imp);
532
533 // Creates a parameter map to handle the display of texture map
534 // parameters in the material editor
535 pmap = CreateMParamMap(paramDesc, PARAMDESC_LENGTH,
536 theTex->pblock, ip, hInstance, MAKEINTRESOURCE(IDD_SPLAT),
537 GetString(IDS_DS_SPLAT_PARAMS), 0);
538
539 // Save the window handle of the rollup page
540 hParamDlg = pmap->GetHWnd();
541
542 // Establish the dialog proc to handle the custom button controls
543 pmap->SetUserDlgProc(new SplatDlgProc(this));
544 }
545
546 // Destructor.
547 // This is called after the user changes to another sample slot in
548 // the materials editor that does not contain a Splat texture.
549 // Note that it is not called if they do go to another Splat -- in
550 // that case, the parameters in the rollup page are updated, but
551 // the entire page is not deleted. This is accomplished by simply
552 // changing the parameter block pointer (done inside SplatDlg::SetThing()).
553 SplatDlg::~SplatDlg() {
554 theTex->paramDlg = NULL;
555 for (int i = 0; i < NUM_SUB_TEXMAPS; i++) {
556 ReleaseICustButton(iCustButton[i]);
557 iCustButton[i] = NULL;
558 }
559 // Delete the XYZGen class we created
560 xyzGenDlg->DeleteThis();
561 // Delete the parameter map
562 DestroyMParamMap(pmap);
563 pmap = NULL;
564 }
565
566 // This is called by the DADMgr
567 int SplatDlg::FindSubTexFromHWND(HWND hw) {
568 for (int i=0; i<NUM_SUB_TEXMAPS; i++) {
569 if (hw == iCustButton[i]->GetHwnd()) return i;
570 }
571 return -1;
572 }
573
574
575 // This is called when the dialog is loaded to set the names of the
576 // textures displayed
577 void SplatDlg::UpdateSubTexNames() {
578 for (int i = 0; i < NUM_SUB_TEXMAPS; i++) {
579 TSTR nm;
580 Texmap *m = theTex->subTex[i];
581 if (m)
582 nm = m->GetFullName();
583 else
584 nm = GetString(IDS_DS_NONE);
585 iCustButton[i]->SetText(nm.data());
586 }
587 }
588
589 // Update the dialog display with the values of the texture we are
590 // currently editing.
591 void SplatDlg::LoadDialog() {
592 if (theTex) {
593 Interval ivalid;
594 theTex->Update(curTime, ivalid);
595
596 ISpinnerControl *spin = (ISpinnerControl *)
597 GetISpinner(GetDlgItem(hParamDlg, IDC_SIZE_SPIN));
598 spin->SetValue(theTex->size, FALSE);
599 ReleaseISpinner(spin);
600 spin = (ISpinnerControl *)
601 GetISpinner(GetDlgItem(hParamDlg, IDC_THRESH_SPIN));
602 spin->SetValue(theTex->thresh, FALSE);
603 ReleaseISpinner(spin);
604 spin = (ISpinnerControl *)
605 GetISpinner(GetDlgItem(hParamDlg, IDC_ITER_SPIN));
606 spin->SetValue(theTex->iter, FALSE);
607 ReleaseISpinner(spin);
608
609 cs[0]->SetColor(theTex->col[0]);
610 cs[1]->SetColor(theTex->col[1]);
611
612 UpdateSubTexNames();
613 }
614 }
615
616 // This method invalidates the rollup page so it will get redrawn
617 void SplatDlg::Invalidate() {
618 InvalidateRect(hParamDlg, NULL, FALSE);
619 valid = FALSE;
620 }
621
622 // --- Methods inherited from ParamDlg ---
623 // Returns the Class_ID of the plug-in this dialog manages
624 Class_ID SplatDlg::ClassID() {
625 return splatClassID;
626 }
627
628 // This sets the current texture being edited to the texture passed
629 void SplatDlg::SetThing(ReferenceTarget *m) {
630 assert(m->ClassID() == splatClassID);
631 assert(m->SuperClassID() == TEXMAP_CLASS_ID);
632 if (theTex)
633 theTex->paramDlg = NULL;
634
635 // Set the pointer to the texmap being edited to the one passed.
636 theTex = (Splat *)m;
637
638 // Point the parameter map parameter block pointer at the
639 // one that is now being edited.
640 pmap->SetParamBlock(theTex->pblock);
641 if (theTex)
642 theTex->paramDlg = this;
643
644 // Let the XYZGen set the new one being edited
645 xyzGenDlg->SetThing(theTex->xyzGen);
646
647 // Update the dialog display with the values of the new texmap.
648 LoadDialog();
649 }
650
651 // This returns the current texture being edited
652 ReferenceTarget *SplatDlg::GetThing() {
653 return (ReferenceTarget *)theTex;
654 }
655
656 // This method is called when the current time has changed.
657 // This gives the developer an opportunity to update any user
658 // interface data that may need adjusting due to the change in time.
659 void SplatDlg::SetTime(TimeValue t) {
660 Interval ivalid;
661 if (t != curTime) {
662 xyzGenDlg->SetTime(t);
663 curTime = t;
664 theTex->Update(curTime, ivalid);
665 LoadDialog();
666 InvalidateRect(hParamDlg, NULL, 0);
667 }
668 }
669
670 // This method should place values into all the parameter dialog's controls,
671 // edit fields etc.
672 void SplatDlg::ReloadDialog() {
673 Interval ivalid;
674 theTex->Update(curTime, ivalid);
675 LoadDialog();
676 }
677
678 // This method is called when the dialog box becomes active or inactive.
679 void SplatDlg::ActivateDlg(BOOL onOff) {
680 for (int i = 0; i < NUM_COLORS; i++) {
681 cs[i]->Activate(onOff);
682 }
683 }
684 */
685 //dialog stuff to get the Set Ref button
686 class SplatDlgProc : public ParamMap2UserDlgProc {
687 //public ParamMapUserDlgProc {
688 public:
689 Splat *splat;
SplatDlgProc(Splat * m)690 SplatDlgProc(Splat *m) {splat = m;}
691 INT_PTR DlgProc(TimeValue t,IParamMap2 *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
DeleteThis()692 void DeleteThis() {delete this;}
693 };
694
695
696
DlgProc(TimeValue t,IParamMap2 * map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)697 INT_PTR SplatDlgProc::DlgProc(
698 TimeValue t,IParamMap2 *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
699 {
700 switch (msg) {
701 case WM_COMMAND:
702 switch (LOWORD(wParam))
703 {
704 case IDC_SWAP:
705 {
706 splat = (Splat*)map->GetParamBlock()->GetOwner();
707
708 splat->SwapInputs();
709 }
710 break;
711 }
712 break;
713 }
714 return FALSE;
715 }
716
717 /*===========================================================================*\
718 | Splat Methods
719 \*===========================================================================*/
720 // --- Methods inherited from Animatable ---
721 // This method returns a pointer to the 'i-th' sub-anim.
SubAnim(int i)722 Animatable* Splat::SubAnim(int i) {
723 switch (i) {
724 case 0: return xyzGen;
725 case 1: return pblock;
726 default: return subTex[i-2];
727 }
728 }
729
730 // This method returns the name of the 'i-th' sub-anim to appear in track view.
SubAnimName(int i)731 TSTR Splat::SubAnimName(int i) {
732 switch (i) {
733 case 0: return GetString(IDS_DS_COORDS);
734 case 1: return GetString(IDS_DS_PARAMETERS);
735 default: return GetSubTexmapTVName(i-2);
736 }
737 }
738
739 // --- Methods inherited from ReferenceMaker ---
740 // Return the 'i-th' reference
GetReference(int i)741 RefTargetHandle Splat::GetReference(int i) {
742 switch(i) {
743 case 0: return xyzGen;
744 case 1: return pblock ;
745 default:return subTex[i-2];
746 }
747 }
748
749 // Save the 'i-th' reference
SetReference(int i,RefTargetHandle rtarg)750 void Splat::SetReference(int i, RefTargetHandle rtarg) {
751 switch(i) {
752 case 0: xyzGen = (XYZGen *)rtarg; break;
753 case 1: pblock = (IParamBlock2 *)rtarg; break;
754 default: subTex[i-2] = (Texmap *)rtarg; break;
755 }
756 }
757
758 // This method is responsible for responding to the change notification
759 // messages sent by the texmap dependants.
NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget,PartID & partID,RefMessage message)760 RefResult Splat::NotifyRefChanged(Interval changeInt,
761 RefTargetHandle hTarget, PartID& partID, RefMessage message ) {
762 switch (message) {
763 case REFMSG_CHANGE:
764 // One of the texmap dependants have changed. We set our
765 // validity interval to empty and invalidate the dialog
766 // so it gets redrawn.
767 // texValidity.SetEmpty();
768 // if (hTarget != xyzGen) {
769 // if (paramDlg)
770 // paramDlg->pmap->Invalidate();
771 // }
772 texValidity.SetEmpty();
773 if (hTarget == pblock)
774 {
775
776 ParamID changing_param = pblock->LastNotifyParamID();
777 splat_param_blk.InvalidateUI(changing_param);
778 #ifdef SHOW_3DMAPS_WITH_2D
779 if (changing_param != -1)
780 DiscardTexHandle();
781 #endif
782 }
783 #ifdef SHOW_3DMAPS_WITH_2D
784 else if (hTarget == xyzGen)
785 {
786 DiscardTexHandle();
787 }
788 #endif
789
790 break;
791 /*
792 case REFMSG_GET_PARAM_DIM: {
793 // This returns the 'dimension' of the parameter. This is
794 // the type and order of magnitude of the parameter.
795 GetParamDim *gpd = (GetParamDim *)partID;
796 switch (gpd->index) {
797 case PB_SIZE: gpd->dim = stdWorldDim; break;
798 case PB_THRESH:
799 case PB_ITER:
800 gpd->dim = defaultDim; break;
801 case PB_COL1:
802 case PB_COL2: gpd->dim = stdColor255Dim; break;
803 }
804 return REF_STOP;
805 }
806
807 case REFMSG_GET_PARAM_NAME: {
808 // This returns the name that will appear in track view
809 // of the parameter.
810 GetParamName *gpn = (GetParamName *)partID;
811 gpn->name = GetString(nameIDs[gpn->index]);
812 return REF_STOP;
813 }
814 */
815 }
816 return(REF_SUCCEED);
817 }
818
819 // Load/Save Chunk IDs
820 #define MTL_HDR_CHUNK 0x4000
821 #define SPLAT_VERS1_CHUNK 0x4001
822 #define MAPOFF_CHUNK 0x1000
823 #define PARAM2_CHUNK 0x1010
824
825 // This is called by the system to allow the plug-in to save its data
Save(ISave * isave)826 IOResult Splat::Save(ISave *isave) {
827 IOResult res;
828
829 // Save the common stuff from the base class
830 isave->BeginChunk(MTL_HDR_CHUNK);
831 res = MtlBase::Save(isave);
832 if (res != IO_OK)
833 return res;
834 isave->EndChunk();
835 isave->BeginChunk(PARAM2_CHUNK);
836 isave->EndChunk();
837 /*
838 // Save a version number chunk
839 isave->BeginChunk(SPLAT_VERS1_CHUNK);
840 isave->EndChunk();
841 // Save the on/off status of the sub-texmaps
842 for (int i = 0; i < NUM_SUB_TEXMAPS; i++) {
843 if (mapOn[i] == 0) {
844 isave->BeginChunk(MAPOFF_CHUNK+i);
845 isave->EndChunk();
846 }
847 }
848 */
849 return IO_OK;
850 }
851
852 class SplatPostLoad : public PostLoadCallback {
853 public:
854 Splat *n;
855 BOOL Param1;
SplatPostLoad(Splat * ns,BOOL b)856 SplatPostLoad(Splat *ns, BOOL b) {n = ns; Param1 = b;}
proc(ILoad * iload)857 void proc(ILoad *iload) {
858 if (Param1)
859 {
860 n->pblock->SetValue( splat_mapon1, 0, n->mapOn[0]);
861 n->pblock->SetValue( splat_mapon2, 0, n->mapOn[1]);
862 }
863 delete this;
864
865
866 }
867 };
868
869
870
871 // This is called by the system to allow the plug-in to load its data
Load(ILoad * iload)872 IOResult Splat::Load(ILoad *iload) {
873 IOResult res;
874 int id;
875 fileVersion = 0;
876 BOOL Param1 = TRUE;
877 while (IO_OK == (res = iload->OpenChunk())) {
878 switch(id = iload->CurChunkID()) {
879 case MTL_HDR_CHUNK:
880 // Load the common stuff from the base class
881 res = MtlBase::Load(iload);
882 break;
883 case SPLAT_VERS1_CHUNK:
884 // Set the version number
885 fileVersion = 1;
886 break;
887 case PARAM2_CHUNK:
888 // Set the version number
889 Param1 = FALSE;;
890 break;
891 case MAPOFF_CHUNK+0:
892 case MAPOFF_CHUNK+1:
893 // Set the sub-texmap on/off settings
894 mapOn[id-MAPOFF_CHUNK] = 0;
895 break;
896 }
897 iload->CloseChunk();
898 if (res != IO_OK)
899 return res;
900 }
901 // JBW: register old version ParamBlock to ParamBlock2 converter
902 ParamBlock2PLCB* plcb = new ParamBlock2PLCB(versions, 1, &splat_param_blk, this, 1);
903 iload->RegisterPostLoadCallback(plcb);
904
905 iload->RegisterPostLoadCallback(new SplatPostLoad(this,Param1));
906 return IO_OK;
907 }
908
909 // --- Methods inherited from ReferenceTarget ---
910 // This method is called to have the plug-in clone itself.
Clone(RemapDir & remap)911 RefTargetHandle Splat::Clone(RemapDir &remap) {
912 // Create a new instance of the plug-in class
913 Splat *newSplat = new Splat();
914
915 // Copy superclass stuff
916 *((MtlBase *)newSplat) = *((MtlBase *)this);
917
918 // Clone the items we reference
919 newSplat->ReplaceReference(0, remap.CloneRef(xyzGen));
920 newSplat->ReplaceReference(1, remap.CloneRef(pblock));
921 newSplat->col[0] = col[0];
922 newSplat->col[1] = col[1];
923 newSplat->size = size;
924 newSplat->thresh = thresh;
925 newSplat->iter = iter;
926 newSplat->texValidity.SetEmpty();
927 for (int i = 0; i < NUM_SUB_TEXMAPS; i++) {
928 newSplat->subTex[i] = NULL;
929 newSplat->mapOn[i] = mapOn[i];
930 if (subTex[i])
931 newSplat->ReplaceReference(i+2, remap.CloneRef(subTex[i]));
932 }
933 BaseClone(this, newSplat, remap);
934 // Return the new cloned texture
935 return (RefTargetHandle)newSplat;
936 }
937
938 // --- Methods inherited from MtlBase ---
939 // This method is called to return the validity interval of the texmap.
Validity(TimeValue t)940 Interval Splat::Validity(TimeValue t) {
941 Interval v;
942 // Calling Update() sets texValidity.
943 Update(t, v);
944 return texValidity;
945 }
946
947 #define IN_TO_M(x) (x / 39.370079f)
948
949 // This method is called to reset the texmap back to its default values.
Init()950 void Splat::Init() {
951 // Reset the XYZGen or allocate a new one
952 if (xyzGen)
953 xyzGen->Reset();
954 else
955 ReplaceReference(0, GetNewDefaultXYZGen());
956
957 // Set the inital parameters
958 SetColor(0, Color(0.7f, 0.8f, 0.8f), TimeValue(0));
959 SetColor(1, Color(0.2f, 0.5f, 1.0f), TimeValue(0));
960
961 RegisterDistanceDefault(_T("Splat Params"), _T("Size"), 40.0f, IN_TO_M(40.0f));
962 float size = GetDistanceDefault(_T("Splat Params"), _T("Size"));
963 SetSize(size, TimeValue(0));
964
965 SetThresh(0.2f, TimeValue(0));
966 SetIter(4, TimeValue(0));
967
968 // Set the validity interval of the texture to empty
969 texValidity.SetEmpty();
970 }
971
Reset()972 void Splat::Reset() {
973 splatCD.Reset(this, TRUE); // reset all pb2's
974 DeleteReference(2);
975 DeleteReference(3);
976 Init();
977 }
978
Splat()979 Splat::Splat() {
980 #ifdef SHOW_3DMAPS_WITH_2D
981 texHandle = NULL;
982 #endif
983 subTex[0] = subTex[1] = NULL;
984 pblock = NULL;
985 xyzGen = NULL;
986 // paramDlg = NULL;
987 mapOn[0] = mapOn[1] = 1;
988 splatCD.MakeAutoParamBlocks(this); // make and intialize paramblock2
989 Init();
990 fileVersion = 0;
991 }
992
993 // This method gets called when the material or texture is to be displayed
994 // in the material editor parameters area.
CreateParamDlg(HWND hwMtlEdit,IMtlParams * imp)995 ParamDlg* Splat::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp) {
996 // Allocate a new instance of ParamDlg to manage the UI. This will
997 // create the rollup page in the materials editor.
998 // SplatDlg *splatDlg = new SplatDlg(hwMtlEdit, imp, this);
999 // Update the dialog display with the proper values of the texture.
1000 // splatDlg->LoadDialog();
1001 // paramDlg = splatDlg;
1002 // return splatDlg;
1003
1004 xyzGenDlg = xyzGen->CreateParamDlg(hwMtlEdit, imp);
1005 IAutoMParamDlg* masterDlg = splatCD.CreateParamDlgs(hwMtlEdit, imp, this);
1006 // add the secondary dialogs to the master
1007 masterDlg->AddDlg(xyzGenDlg);
1008 splat_param_blk.SetUserDlgProc(new SplatDlgProc(this));
1009
1010 return masterDlg;
1011
1012 }
1013
1014 #ifdef SHOW_3DMAPS_WITH_2D
GetActiveTexHandle(TimeValue t,TexHandleMaker & thmaker)1015 DWORD_PTR Splat::GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker) {
1016 if (texHandle) {
1017 if (texHandleValid.InInterval(t))
1018 return texHandle->GetHandle();
1019 else DiscardTexHandle();
1020 }
1021 texHandle = thmaker.MakeHandle(GetVPDisplayDIB(t,thmaker,texHandleValid));
1022 return texHandle->GetHandle();
1023 }
1024 #endif
1025
SetDlgThing(ParamDlg * dlg)1026 BOOL Splat::SetDlgThing(ParamDlg* dlg)
1027 {
1028 // JBW: set the appropriate 'thing' sub-object for each
1029 // secondary dialog
1030 if ((xyzGenDlg!= NULL) && (dlg == xyzGenDlg))
1031 xyzGenDlg->SetThing(xyzGen);
1032 else
1033 return FALSE;
1034 return TRUE;
1035 }
1036 // This method is called before rendering begins to allow the plug-in
1037 // to evaluate anything prior to the render so it can store this information.
Update(TimeValue t,Interval & ivalid)1038 void Splat::Update(TimeValue t, Interval& ivalid) {
1039 if (!texValidity.InInterval(t)) {
1040 texValidity.SetInfinite();
1041 xyzGen->Update(t, texValidity);
1042 // pblock->GetValue(PB_COL1, t, col[0], texValidity);
1043 pblock->GetValue(splat_color1, t, col[0], texValidity);
1044 col[0].ClampMinMax();
1045 // pblock->GetValue(PB_COL2, t, col[1], texValidity);
1046 pblock->GetValue(splat_color2, t, col[1], texValidity);
1047 col[1].ClampMinMax();
1048 // pblock->GetValue(PB_SIZE, t, size, texValidity);
1049 pblock->GetValue(splat_size, t, size, texValidity);
1050 ClampFloat(size, MIN_SIZE, MAX_SIZE);
1051 // pblock->GetValue(PB_THRESH, t, thresh, texValidity);
1052 pblock->GetValue(splat_threshold, t, thresh, texValidity);
1053 ClampFloat(thresh, MIN_THRESH, MAX_THRESH);
1054 // pblock->GetValue(PB_ITER, t, iter, texValidity);
1055 pblock->GetValue(splat_iteration, t, iter, texValidity);
1056 pblock->GetValue(splat_mapon1, t, mapOn[0], texValidity);
1057 pblock->GetValue(splat_mapon2, t, mapOn[1], texValidity);
1058 ClampInt(iter, (int) MIN_ITER, (int) MAX_ITER);
1059 for (int i = 0; i < NUM_SUB_TEXMAPS; i++) {
1060 if (subTex[i])
1061 subTex[i]->Update(t, texValidity);
1062 }
1063 }
1064 ivalid &= texValidity;
1065 }
1066
ClampFloat(float & f,float min,float max)1067 void Splat::ClampFloat(float &f, float min, float max) {
1068 if (f < min) f = min;
1069 else if (f > max) f = max;
1070 }
1071
ClampInt(int & i,int min,int max)1072 void Splat::ClampInt(int &i, int min, int max) {
1073 if (i < min) i = min;
1074 else if (i > max) i = max;
1075 }
1076
1077 // Returns a pointer to the 'i-th' sub-texmap managed by this texture.
GetSubTexmap(int i)1078 Texmap *Splat::GetSubTexmap(int i) {
1079 return subTex[i];
1080 }
1081
1082 // Stores the 'i-th' sub-texmap managed by the material or texture.
SetSubTexmap(int i,Texmap * m)1083 void Splat::SetSubTexmap(int i, Texmap *m) {
1084 ReplaceReference(i+2, m);
1085
1086 if (i==0)
1087 {
1088 splat_param_blk.InvalidateUI(splat_map1);
1089 texValidity.SetEmpty();
1090 }
1091 else if (i==1)
1092 {
1093 splat_param_blk.InvalidateUI(splat_map2);
1094 texValidity.SetEmpty();
1095 }
1096
1097 // if (paramDlg)
1098 // paramDlg->UpdateSubTexNames();
1099 }
1100
1101 // This name appears in the materials editor dialog when editing the
1102 // 'i-th' sub-map.
GetSubTexmapSlotName(int i)1103 TSTR Splat::GetSubTexmapSlotName(int i) {
1104 switch(i) {
1105 case 0: return GetString(IDS_DS_COL1);
1106 case 1: return GetString(IDS_DS_COL2);
1107 default: return TSTR(_T(""));
1108 }
1109 }
1110
1111 // --- Methods inherited from Texmap ---
EvalColor(ShadeContext & sc)1112 RGBA Splat::EvalColor(ShadeContext& sc) {
1113 // After being evaluated, if a map or material has a non-zero gbufID,
1114 // it should call ShadeContext::SetGBuffer() to store it into
1115 // the shade context.
1116 if (gbufID)
1117 sc.SetGBufferID(gbufID);
1118
1119 // Use the XYZGen instance to get a transformed point from the
1120 // ShadeContext.
1121 Point3 p, dp;
1122 xyzGen->GetXYZ(sc, p, dp);
1123 if (size == 0.0f)
1124 size = 0.0001f;
1125
1126 float d = splatter(p);
1127
1128 // If we have sub-texmaps and they are enabled, get the colors from
1129 // the sub-texmaps, otherwise get them from the color swatch
1130 RGBA c0 = (mapOn[0]&&subTex[0]) ? subTex[0]->EvalColor(sc): col[0];
1131 RGBA c1 = (mapOn[1]&&subTex[1]) ? subTex[1]->EvalColor(sc): col[1];
1132
1133 // Composite the colors together and return the result.
1134 return (1.0f-d)*c0 + d*c1;
1135 }
1136
EvalNormalPerturb(ShadeContext & sc)1137 Point3 Splat::EvalNormalPerturb(ShadeContext& sc) {
1138 float del, d, f;
1139 Point3 p, dp, np;
1140
1141 if (gbufID)
1142 sc.SetGBufferID(gbufID);
1143
1144 xyzGen->GetXYZ(sc, p, dp);
1145
1146 d = splatter(p);
1147 del = 0.1f;
1148 // float strength = (abs((int)col[1].r-(int)col[0].r)+
1149 // abs((int)col[1].g-(int)col[0].g)+
1150 // abs((int)col[1].b-(int)col[0].b)); ///100.0f; // 756.0f
1151
1152 // f = strength/del;
1153 f = 1.0f/del;
1154 Point3 M[3];
1155 xyzGen->GetBumpDP(sc,M);
1156 np.x = f*(splatter(p+del*M[0]) - d);
1157 np.y = f*(splatter(p+del*M[1]) - d);
1158 np.z = f*(splatter(p+del*M[2]) - d);
1159
1160 np = sc.VectorFromNoScale(np,REF_OBJECT);
1161 Texmap *sub0 = mapOn[0]?subTex[0]:NULL;
1162 Texmap *sub1 = mapOn[1]?subTex[1]:NULL;
1163 if (sub0||sub1) {
1164 // d((1-k)*a + k*b ) = dk*(b-a) + k*(db-da) + da
1165 float a,b;
1166 Point3 da,db;
1167 if (sub0) {
1168 a = sub0->EvalMono(sc);
1169 da = sub0->EvalNormalPerturb(sc);
1170 }
1171 else {
1172 a = Intens(col[0]);
1173 da = Point3(0.0f,0.0f,0.0f);
1174 }
1175 if (sub1) {
1176 b = sub1->EvalMono(sc);
1177 db = sub1->EvalNormalPerturb(sc);
1178 }
1179 else {
1180 b = Intens(col[1]);
1181 db= Point3(0.0f,0.0f,0.0f);
1182 }
1183 np = (b-a)*np + d*(db-da) + da;
1184 }
1185 else
1186 np *= Intens(col[1])-Intens(col[0]);
1187 return np;
1188 }
1189
1190 // --- Methods inherited from Tex3D ---
ReadSXPData(TCHAR * name,void * sxpdata)1191 void Splat::ReadSXPData(TCHAR *name, void *sxpdata) {
1192 SplatState *state = (SplatState*)sxpdata;
1193 if (state != NULL && (state->version == SPLAT_SXP_VERSION)) {
1194 SetColor(0, ColorFromCol24(state->col1), TimeValue(0));
1195 SetColor(1, ColorFromCol24(state->col2), TimeValue(0));
1196 SetSize(state->size, TimeValue(0));
1197 SetThresh(state->thresh, TimeValue(0));
1198 }
1199 }
1200
1201 // --- Methods of Splat ---
1202
splatter(Point3 p)1203 float Splat::splatter(Point3 p) {
1204 float fact, ss, q[3], t;
1205
1206 q[0] = p[0]/size;
1207 q[1] = p[1]/size;
1208 q[2] = p[2]/size;
1209 fact = 1.0f;
1210 for (int i = 0; i < iter; i++) {
1211 t = NOISE(q);
1212 if (t > 1.0)
1213 t = 1.0f;
1214 ss = smoothstep(thresh-EPSILON, thresh+EPSILON, t);
1215 fact *= ss;
1216 q[0] *= 2.0f; q[1] *= 2.0f; q[2] *= 2.0f;
1217 }
1218 return(1.0f-fact);
1219 }
1220
NotifyChanged()1221 void Splat::NotifyChanged() {
1222 NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
1223 }
1224
SwapInputs()1225 void Splat::SwapInputs() {
1226 Color t = col[0]; col[0] = col[1]; col[1] = t;
1227 Texmap *x = subTex[0]; subTex[0] = subTex[1]; subTex[1] = x;
1228 // pblock->SwapControllers(PB_COL1, PB_COL2);
1229 pblock->SwapControllers(splat_color1,0, splat_color2,0);
1230 splat_param_blk.InvalidateUI(splat_color1);
1231 splat_param_blk.InvalidateUI(splat_color2);
1232 splat_param_blk.InvalidateUI(splat_map1);
1233 splat_param_blk.InvalidateUI(splat_map2);
1234 macroRec->FunctionCall(_T("swap"), 2, 0, mr_prop, _T("color1"), mr_reftarg, this, mr_prop, _T("color2"), mr_reftarg, this);
1235 macroRec->FunctionCall(_T("swap"), 2, 0, mr_prop, _T("map1"), mr_reftarg, this, mr_prop, _T("map2"), mr_reftarg, this);
1236 }
1237
SetColor(int i,Color c,TimeValue t)1238 void Splat::SetColor(int i, Color c, TimeValue t) {
1239 col[i] = c;
1240 // pblock->SetValue((i == 0) ? PB_COL1 : PB_COL2, t, c);
1241 pblock->SetValue((i == 0) ? splat_color1 : splat_color2, t, c);
1242 }
1243
SetSize(float f,TimeValue t)1244 void Splat::SetSize(float f, TimeValue t) {
1245 size = f;
1246 // pblock->SetValue(PB_SIZE, t, f);
1247 pblock->SetValue(splat_size, t, f);
1248 }
1249
SetThresh(float f,TimeValue t)1250 void Splat::SetThresh(float f, TimeValue t) {
1251 thresh = f;
1252 if (thresh < EPSILON)
1253 thresh = EPSILON;
1254 if (thresh > 1.0f-EPSILON)
1255 thresh = 1.0f-EPSILON;
1256 // pblock->SetValue(PB_THRESH, t, thresh);
1257 pblock->SetValue(splat_threshold, t, thresh);
1258 }
1259
SetIter(int i,TimeValue t)1260 void Splat::SetIter(int i, TimeValue t) {
1261 iter = i;
1262 // pblock->SetValue(PB_ITER, t, i);
1263 pblock->SetValue(splat_iteration, t, i);
1264 }
1265
1266