1 //////////////////////////////////////////////////////////////////////
2 //
3 // Shader UI Utilities
4 //
5 #include "shadersPch.h"
6 #include "shadersRc.h"
7 #include "shaders.h"
8 #include "shaderUtil.h"
9 #include "iColorMan.h"
10 #include "toneop.h"
11 
12 #include "3dsmaxport.h"
13 
14 static const float Pi = 3.1415926f;
15 static const float Pi2 = Pi * Pi;
16 static const float Pi2Ivr = 1.0f / Pi2;
17 static const float PiIvr = 1.0f / Pi;
18 
19 
OrenNayarIllum(Point3 & N,Point3 & L,Point3 & V,float rough,Color & rho,float * pDiffIntensOut,float NL)20 Color OrenNayarIllum( Point3& N, Point3& L, Point3& V, float rough, Color& rho, float* pDiffIntensOut, float NL )
21 {
22 // float a = NL >= -1.0f ? float( acos( NL / Len(L) )) : AngleBetween( N, L );
23    // use the non-uniform scale corrected NL
24    if ( NL < -1.0f )
25       NL = Dot( N, L );
26 // float a = float( acos( NL / Len(L) )) ;
27    float a = 0.0f;
28    if( NL < 0.9999f )
29       a = acosf( NL );
30    a = Bound( a, -Pi*0.49f, Pi*0.49f );
31    float NV = Dot( N, V );
32    // need this to accomodate double sided materials
33    if( NV < 0.0f ){
34       NV = -NV;
35       V = -V;
36    }
37    float b = 0.0f;
38    if( NV < 0.9999f )
39       b = acosf( NV );
40    MinMax( b, a ); // b gets min, a gets max
41 
42 
43    //N.V is the length of the projection of v onto n; times N is a vector along N of that length
44    // V - that pt gives a tangent vector in the plane of N, for measuring phi
45    Point3 tanV = V - N * NV;
46    Point3 tanL = L - N * NL;
47    float w = Len( tanV ) * Len( tanL );
48    float cosDPhi = (Abs(w) < 1e-4) ? 1.0f : Dot( tanV, tanL ) / w;
49    cosDPhi = Bound( cosDPhi, -1.0f, 1.0f );
50 
51 
52 // float bCube = (cosDPhi >= 0.0f) ? 0.0f : Cube( 2.0f * b * PiIvr );
53    float bCube = (cosDPhi >= 0.0f) ? Cube( 2.0f * -b * PiIvr ) : Cube( 2.0f * b * PiIvr );
54 
55    // these three can be pre-calc'd for speed
56    float sigma2 = Sqr( rough );
57    float sigma3 = sigma2 / (sigma2 + 0.09f);
58    float c1 = 1.0f - 0.5f * (sigma2 / (sigma2 + 0.33f));
59 
60    float c2 = 0.45f * sigma3 * (float(sin(a)) - bCube);
61    float c3 = 0.125f * sigma3 * Sqr( 4.0f * a * b * Pi2Ivr );
62    float tanB = float( tan(b) );
63    float tanAB = float( tan( (a+b) * 0.5f ));
64    tanB = Bound( tanB, -100.0f, 100.0f );
65    tanAB = Bound( tanAB, -100.0f, 100.0f );
66 
67    Color o;
68    float l1 = ( c1 + c2 * cosDPhi * tanB  + c3 * (1.0f - Abs( cosDPhi )) * tanAB );
69    float l2 = 0.17f * (sigma2 / (sigma2 + 0.13f)) * ( 1.0f - cosDPhi * Sqr( 2.0f * b * PiIvr ));
70    if( pDiffIntensOut )
71       *pDiffIntensOut = l1+l2;
72    o.r =  l1 * rho.r + l2 * Sqr( rho.r );
73    o.g =  l1 * rho.g + l2 * Sqr( rho.g );
74    o.b =  l1 * rho.b + l2 * Sqr( rho.b );
75    return UBound( o );
76 
77 }
78 
79 // perpendicular to N, in the U (reference) direction
GetTangent(ShadeContext & sc,int uvChan)80 Point3 GetTangent( ShadeContext &sc, int uvChan )
81 {
82 // Point3 basisVecs[ 3 ];
83 // sc.DPdUVW( basisVecs, uvChan ); // 0 is vtxclr, 1..n is uv channels, max_meshmaps in mesh.h
84 // Point3 U = Normalize( basisVecs[0] );
85 
86    Point3 U = sc.VectorFrom( Point3( 0.01f, 0.0f, 1.0f ), REF_OBJECT );
87 //Retry:
88    U = Normalize( U );
89 
90    Point3 N = sc.Normal();       //assumed normalized
91 
92    // the line between the tip of vec[0] and its projection on N is tangent
93    float UN = Dot( U, N );
94 // if ( Abs(UN) > 0.9999999f ){
95 //    U = sc.VectorFrom( Point3( 0.01f, 1.0f, 0.0f ), REF_OBJECT );
96 //    goto Retry;
97 // }
98    Point3 T = U - N * UN;
99    T = Normalize( T );
100    return T;
101 }
102 
103 
104 // specular reflectivity, no colors yet, all vectors assumed normalized
GaussHighlight(float gloss,float aniso,float orient,Point3 & N,Point3 & V,Point3 & L,Point3 & T,float * pNL)105 float GaussHighlight( float gloss, float aniso, float orient,
106                  Point3& N, Point3& V, Point3& L, Point3& T, float* pNL )
107 {
108    float out = 0.0f;
109 
110    float asz = (1.0f - gloss) * ALPHA_SZ;
111    float ax = ALPHA_MIN + asz;
112    float ay = ALPHA_MIN + asz * (1.0f-aniso);
113 // DbgAssert( ax >= 0.0f && ay >= 0.0f );
114    LBound( ax ); LBound( ay );
115 
116    Point3 H = Normalize(L - V); // (L + -V)/2
117    float NH = DotProd(N, H);
118    if (NH > 0.0f) {
119       float axy = /* normalizeOn ? ax * ay : */ DEFAULT_GLOSS2;
120       float norm = 1.0f / (4.0f * PI * axy );
121       float NV = -DotProd(N, V );
122       if ( NV <= 0.001f)
123          NV = 0.001f;
124 
125       float NL = pNL ? *pNL : DotProd( N, L );
126       float g = 1.0f / (float)sqrt( NL * NV );
127       if ( g > 3.0f ) g = 3.0f;
128 
129       // Apply Orientation rotation here
130       float or = orient * 180.0f;
131       Point3 T1 = T;
132       if ( or != 0.0f )
133          T1 = RotateVec( T, N, DegToRdn(or));
134 
135       // get binormal
136       Point3 B = CrossProd( T1, N );
137 
138       float x = Dot( H, T1 ) / ax;
139       float y = Dot( H, B ) / ay;
140       float e = (float)exp( -2.0 * (x*x + y*y) / (1.0+NH) );
141 
142       out = norm * g * e;
143    }
144    return SPEC_MAX * out;  // does not have speclev or light color or kL
145 }
146 
GaussHiliteCurve2(float x,float y,float sLevel,float gloss,float aniso)147 float GaussHiliteCurve2( float x, float y, float sLevel, float gloss, float aniso )
148 {
149    double axy = DEFAULT_GLOSS2;
150    double asz = (1.0f - gloss) * ALPHA_SZ;
151    double ax = ALPHA_MIN + asz;
152    double ay = ALPHA_MIN + asz * (1.0f - aniso) ;
153    double ax2 = ax * ax;
154    double ay2 = ay * ay;
155 
156    double t, a;
157    double l = sqrt( x*x + y*y );
158    if ( l == 0.0 ) {
159       a = t = 0.0;
160    } else {
161       x /= float(l); y /= float(l);
162       t = tan( l*PI*0.5 );
163       a = x*x/ax2 + y*y/ay2;
164    }
165    return SPEC_MAX * sLevel*(float)(exp( -(t * t) * a ) / (4.0 * PI * axy));
166 }
167 
168 //////////////////////////////////////////////////////////////////////////////
169 //
170 // Combine Components....Adding & compositing
171 //
172 #define COMBINE_ADD(ip) \
173    ((ip).finalAttenuation * ((ip).ambIllumOut + (ip).diffIllumOut  + (ip).selfIllumOut) \
174       + (ip).specIllumOut + (ip).reflIllumOut + (ip).transIllumOut)
175 
CombineComponentsAdd(IllumParams & ip)176 void CombineComponentsAdd( IllumParams& ip )
177 {
178    ip.finalC = COMBINE_ADD(ip);
179 }
180 
ChooseSpecularMethod(TimeValue t,RenderGlobalContext * rgc)181 void CombineComponentsCompShader::ChooseSpecularMethod(TimeValue t, RenderGlobalContext* rgc)
182 {
183    useComposite = true;
184    if (rgc == NULL) {
185       ToneOperatorInterface* tint = static_cast<ToneOperatorInterface*>(
186          GetCOREInterface(TONE_OPERATOR_INTERFACE));
187       if (tint != NULL) {
188          ToneOperator* top = tint->GetToneOperator();
189          if (top != NULL && top->Active(t))
190             useComposite = false;
191       }
192    } else {
193       ToneOperator* top = rgc->pToneOp;
194       if (top != NULL && top->Active(t))
195          useComposite = false;
196    }
197 }
198 
CombineComponents(ShadeContext & sc,IllumParams & ip)199 void CombineComponentsCompShader::CombineComponents( ShadeContext &sc, IllumParams& ip )
200 {
201    if (useComposite) {
202       Color spec, diff, rem;
203       spec = ip.specIllumOut + ip.reflIllumOut;
204       rem = 1.0f - spec;
205       rem = Bound( rem );
206       diff = ip.ambIllumOut + ip.diffIllumOut  + ip.selfIllumOut;
207       ip.finalC = spec + ip.finalAttenuation * rem * diff +  rem * ip.transIllumOut;
208    } else {
209       ip.finalC = COMBINE_ADD(ip);
210    }
211 }
212 
GetInterface(Interface_ID id)213 BaseInterface* CombineComponentsCompShader::GetInterface(Interface_ID id)
214 {
215    if (id == ISPECULAR_COMPOSITE_SHADER_ID)
216       return static_cast<ISpecularCompositeShader*>(this);
217    return NULL;
218 }
219 
220 
221 //////////////////////////////////////////////////////////////////////////////
222 //
223 // transpColor utility
224 //
transpColor(ULONG type,float opac,Color & filt,Color & diff)225 Color transpColor( ULONG type, float opac, Color& filt, Color& diff )
226 {
227    // Compute the color of the transparent filter color
228    if ( type == TRANSP_ADD ) { // flags & STDMTL_ADD_TRANSP) {
229       float f = 1.0f - opac;
230       return Color(f, f, f);
231 
232    } else if ( type == TRANSP_FILTER ) { //flags & STDMTL_FILT_TRANSP ){
233       // Transparent Filter color mapping
234       if (opac>0.5f) {
235          // darken as opac goes ( 0.5--> 1.0)
236          // so that max component reaches 0.0f when opac reaches 1.0
237          // find max component of filt
238          float m = Max(filt);
239          float d = 2.0f*(opac-.5f)*m;
240          Color fc = filt-d;
241          fc = LBound( fc );
242          return fc;
243       } else {
244          // lighten as opac goes ( 0.5--> 0.0)
245          // so that min component reaches 1.0f when opac reaches 1.0
246          // find min component of filt
247          float m = Min(filt);
248          float d = (1.0f-2.0f*opac)*(1.0f-m);
249          Color fc = filt+d;
250          fc = UBound( fc );
251          return fc;
252       }
253 
254    } else {
255       // original 3DS transparency
256       Color f = (1.0f-diff);
257       return  (1.0f-opac)*f;
258    }
259 
260 }
261 
262 //////////////////////////////////////////////////////////////////////////////
263 //
264 // UI utilities
265 //
266 static HIMAGELIST hLockButtons = NULL;
267 extern HINSTANCE hInstance;
268 
269 // mjm - begin - 5.10.99
270 class ResourceDelete
271 {
272 public:
ResourceDelete()273    ResourceDelete() {}
~ResourceDelete()274    ~ResourceDelete() { if (hLockButtons) ImageList_Destroy(hLockButtons); }
275 };
276 
277 static ResourceDelete theResourceDelete;
278 // mjm - end
279 
IsButtonChecked(HWND hWnd,int id)280 BOOL IsButtonChecked(HWND hWnd,int id)
281    {
282    ICustButton *iBut;
283    BOOL res;
284    iBut = GetICustButton(GetDlgItem(hWnd,id));
285    res = iBut->IsChecked();
286    ReleaseICustButton(iBut);
287    return res;
288    }
289 
CheckButton(HWND hWnd,int id,BOOL check)290 void CheckButton(HWND hWnd,int id, BOOL check) {
291    ICustButton *iBut;
292    iBut = GetICustButton(GetDlgItem(hWnd,id));
293    if( iBut )
294       iBut->SetCheck(check);
295    ReleaseICustButton(iBut);
296    }
297 
SetupLockButton(HWND hWnd,int id,BOOL check)298 void SetupLockButton(HWND hWnd,int id, BOOL check)
299    {
300    ICustButton *iBut;
301    iBut = GetICustButton(GetDlgItem(hWnd,id));
302    iBut->SetImage(hLockButtons,0,1,0,1,16,15);
303    iBut->SetType(CBT_CHECK);
304    ReleaseICustButton(iBut);
305    }
306 
SetupPadLockButton(HWND hWnd,int id,BOOL check)307 void SetupPadLockButton(HWND hWnd,int id, BOOL check) {
308    ICustButton *iBut;
309    iBut = GetICustButton(GetDlgItem(hWnd,id));
310    iBut->SetImage(hLockButtons,2,2,2,2,16,15);
311    iBut->SetType(CBT_CHECK);
312    ReleaseICustButton(iBut);
313    }
314 
LoadStdShaderResources()315 void LoadStdShaderResources()
316    {
317    static BOOL loaded=FALSE;
318    if (loaded) return;
319    loaded = TRUE;
320    HBITMAP hBitmap, hMask;
321 
322    hLockButtons = ImageList_Create(16, 15, TRUE, 2, 0);
323    hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_DMTL_BUTTONS));
324    hMask   = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_DMTL_MASKBUTTONS));
325    ImageList_Add(hLockButtons,hBitmap,hMask);
326    DeleteObject(hBitmap);
327    DeleteObject(hMask);
328    }
329 
330 
331 //-HiLite Curve Control------------------------------------------------------
332 
VertLine(HDC hdc,int x,int ystart,int yend)333 static void VertLine(HDC hdc,int x, int ystart, int yend)
334 {
335    MoveToEx(hdc, x, ystart, NULL);
336    if (ystart <= yend)
337       LineTo(hdc, x, yend+1);
338    else
339       LineTo(hdc, x, yend-1);
340 }
341 
DrawHilite(HDC hdc,Rect & rect,Shader * pShader)342 void DrawHilite(HDC hdc, Rect& rect, Shader* pShader )
343 {
344 int w,h,npts,xcen,ybot,ytop,ylast,i,iy;
345 
346    HPEN linePen = (HPEN)GetStockObject(WHITE_PEN);
347    HPEN fgPen = CreatePen(PS_SOLID,0,GetCustSysColor(COLOR_BTNFACE));
348    HPEN bgPen = CreatePen(PS_SOLID,0,GetCustSysColor(COLOR_BTNSHADOW));
349 
350    w = rect.w();
351    h = rect.h()-3;
352    npts = (w-2)/2;
353    xcen = rect.left+npts;
354    ybot = rect.top+h;
355    ytop = rect.top+2;
356    ylast = -1;
357    for (i=0; i<npts; i++) {
358       float v = pShader->EvalHiliteCurve( (float)i/((float)npts*2.0f) );
359       if (v>2.0f) v = 2.0f; // keep iy from wrapping
360       iy = ybot-(int)(v*((float)h-2.0f));
361 
362       if (iy<ytop) iy = ytop;
363 
364       SelectPen(hdc, fgPen);
365       VertLine(hdc,xcen+i,ybot,iy);
366       VertLine(hdc,xcen-i,ybot,iy);
367 
368       if (iy-1>ytop) {
369          // Fill in above curve
370          SelectPen(hdc,bgPen);
371          VertLine(hdc,xcen+i, ytop, iy-1);
372          VertLine(hdc,xcen-i, ytop, iy-1);
373          }
374       if (ylast>=0) {
375          SelectPen(hdc,linePen);
376          VertLine(hdc,xcen+i-1,iy-1,ylast);
377          VertLine(hdc,xcen-i+1,iy-1,ylast);
378          }
379 
380       ylast = iy;
381    }
382 
383    SelectObject( hdc, linePen );
384    DeleteObject(fgPen);
385    DeleteObject(bgPen);
386    WhiteRect3D(hdc, rect, 1);
387 }
388 
HiliteWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)389 LRESULT CALLBACK HiliteWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
390 {
391    LONG_PTR id = GetWindowLongPtr(hwnd,GWLP_ID);
392    HWND hwParent = GetParent(hwnd);
393    ShaderParamDlg *theDlg = DLGetWindowLongPtr<ShaderParamDlg *>(hwParent);
394    if (theDlg==NULL) return FALSE;
395 
396     switch (msg) {
397       case WM_COMMAND:
398       case WM_MOUSEMOVE:
399       case WM_LBUTTONUP:
400       case WM_CREATE:
401       case WM_DESTROY:
402       break;
403 
404       case WM_PAINT:
405       {
406          PAINTSTRUCT ps;
407          Rect rect;
408          HDC hdc = BeginPaint( hwnd, &ps );
409          if (!IsRectEmpty(&ps.rcPaint)) {
410             GetClientRect( hwnd, &rect );
411             Shader* pShader = theDlg->GetShader();
412             DrawHilite(hdc, rect, pShader );
413          }
414          EndPaint( hwnd, &ps );
415       }
416       break;
417    }
418    return DefWindowProc(hwnd,msg,wParam,lParam);
419 }
420 
421 // iso projection of 2 orthogonal highlight curves
DrawHilite2(HDC hdc,Rect & rect,Shader * pShader,int layer)422 void DrawHilite2(HDC hdc, Rect& rect, Shader* pShader, int layer )
423 {
424 int w,h,npts,xcen,ybot,ytop,ylast,i,iy, off, vals[200];
425 float ybr, ybl;
426 
427    HPEN linePen = (HPEN)GetStockObject(WHITE_PEN);
428    HPEN fgPen = CreatePen(PS_SOLID,0,GetCustSysColor(COLOR_BTNFACE));
429    HPEN fg2Pen = CreatePen(PS_SOLID,0,GetCustSysColor(COLOR_BTNHILIGHT));
430    HPEN bgPen = CreatePen(PS_SOLID,0,GetCustSysColor(COLOR_BTNSHADOW));
431 
432    w = rect.w();
433    assert( w/2 < 200 ); // 200 vals saved for visibility
434    h = rect.h()-3;
435    npts = (w-2)/2;
436    off = h / 6;
437    float slope = float(h-off-off)/w;
438    ybot = rect.top+h;
439    ytop = rect.top+2;
440 
441    // first the X curve
442    ybr = ybl = float(rect.top+h - 2.5* off);
443    xcen = rect.left+npts;
444    ylast = -1;
445    for (i=0; i<npts; i++) {
446       float v = pShader->EvalHiliteCurve2( (float)i/((float)npts*2.0f), 0.0f, layer );
447       if (v>2.0f) v = 2.0f; // keep iy from wrapping
448       iy = (int)(v* 0.6f * ((float)h-2.0f));
449 
450       int r = int( ybr + 0.5f );
451       if ( r > ybot ) r = ybot;
452       int l = int( ybl + 0.5f  );
453       if ( l > ybot ) l = ybot;
454 
455       int ry = r - iy;
456       if (ry<ytop) ry = ytop;
457       if (ry>ybot) ry = ybot;
458       vals[i] = ry;  // save for visibility
459 
460       int ly = l - iy;
461       if (ly<ytop) ly = ytop;
462       if (ly>ybot) ly = ybot;
463 
464       SelectPen(hdc, fgPen);
465       VertLine(hdc,xcen+i, r, ry); // start at center & spread out on both sides
466       VertLine(hdc,xcen-i, l, ly);
467 
468       SelectPen(hdc,bgPen);            // Fill in below baseline
469       VertLine(hdc,xcen+i, ybot, r+1);
470       VertLine(hdc,xcen-i, ybot, l+1);
471 
472       VertLine(hdc,xcen+i, ytop, ry-1);
473       VertLine(hdc,xcen-i, ytop, ly-1);   // fill in above curve
474 
475 //    if (ylast>=0) {
476 //       SelectPen(hdc,linePen);
477 //       VertLine(hdc, xcen+i-1, iy-1, ylast); // white dot marks curve
478 //       VertLine(hdc, xcen-i+1, iy-1, ylast);
479 //    }
480 
481       ylast = iy;
482       ybr += slope;
483       ybl += -slope;
484    }
485 
486    // now do the Y curve
487    ybr = ybl = float(rect.top+h - 2.5* off);
488    xcen = rect.left+npts - 1;
489    ylast = -1;
490    for (i=0; i < npts; i++) {
491       float v = pShader->EvalHiliteCurve2( 0.0f, (float)i/((float)npts*2.0f), layer );
492       if (v>2.0f) v = 2.0f; // keep iy from wrapping
493       iy = (int)(v* 0.6f * ((float)h-2.0f));
494 
495       int r = int( ybr + 0.5f );
496       if ( r > ybot ) r = ybot;
497       int l = int( ybl + 0.5f  );
498       if ( l > ybot ) l = ybot;
499 
500       int ry = r - iy;
501       if (ry<ytop) ry = ytop;
502       if (ry>ybot) ry = ybot;
503 
504       int ly = l - iy;
505       if (ly<ytop) ly = ytop;
506       if (ly>ybot) ly = ybot;
507 
508       SelectPen(hdc, fg2Pen);
509       VertLine(hdc,xcen-i, l, ly);  // left side always visible..in front
510 
511       if ( r <= vals[i] )
512          VertLine(hdc,xcen+i, r, ry); // start at center & spread out on both sides
513       else if ( ry <= vals[i] )
514          VertLine(hdc,xcen+i, vals[i]-1, ry); // start at center & spread out on both sides
515 
516 //    if (ylast>=0) {
517 //       SelectPen(hdc,linePen);
518 //       VertLine(hdc, xcen+i-1, iy-1, ylast); // white dot marks curve
519 //       VertLine(hdc, xcen-i+1, iy-1, ylast);
520 //    }
521 
522       ylast = iy;
523       ybr += -slope;
524       ybl += slope;
525    }
526 
527    SelectObject( hdc, linePen );
528    DeleteObject(fgPen);
529    DeleteObject(fg2Pen);
530    DeleteObject(bgPen);
531    WhiteRect3D(hdc, rect, 1);
532 }
533 
Hilite2WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)534 LRESULT CALLBACK Hilite2WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
535 {
536    LONG_PTR id = GetWindowLongPtr(hwnd,GWLP_ID);
537    HWND hwParent = GetParent(hwnd);
538    ShaderParamDlg *theDlg = DLGetWindowLongPtr<ShaderParamDlg *>(hwParent);
539    if (theDlg==NULL) return FALSE;
540 
541     switch (msg) {
542       case WM_COMMAND:
543       case WM_MOUSEMOVE:
544       case WM_LBUTTONUP:
545       case WM_CREATE:
546       case WM_DESTROY:
547       break;
548 
549       case WM_PAINT:
550       {
551          PAINTSTRUCT ps;
552          Rect rect;
553          HDC hdc = BeginPaint( hwnd, &ps );
554          if (!IsRectEmpty(&ps.rcPaint)) {
555             GetClientRect( hwnd, &rect );
556             Shader* pShader = theDlg->GetShader();
557             DrawHilite2(hdc, rect, pShader );
558          }
559          EndPaint( hwnd, &ps );
560       }
561       break;
562    }
563    return DefWindowProc(hwnd,msg,wParam,lParam);
564 }
565 
Hilite2Layer1WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)566 LRESULT CALLBACK Hilite2Layer1WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
567 {
568    LONG_PTR id = GetWindowLongPtr(hwnd,GWLP_ID);
569    HWND hwParent = GetParent(hwnd);
570    ShaderParamDlg *theDlg = DLGetWindowLongPtr<ShaderParamDlg *>(hwParent);
571    if (theDlg==NULL) return FALSE;
572 
573     switch (msg) {
574       case WM_PAINT:
575       {
576          PAINTSTRUCT ps;
577          Rect rect;
578          HDC hdc = BeginPaint( hwnd, &ps );
579          if (!IsRectEmpty(&ps.rcPaint)) {
580             GetClientRect( hwnd, &rect );
581             Shader* pShader = theDlg->GetShader();
582             DrawHilite2(hdc, rect, pShader, 1 );
583          }
584          EndPaint( hwnd, &ps );
585       }
586       break;
587    }
588    return DefWindowProc(hwnd,msg,wParam,lParam);
589 }
590 
Hilite2Layer2WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)591 LRESULT CALLBACK Hilite2Layer2WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
592 {
593    LONG_PTR id = GetWindowLongPtr(hwnd,GWLP_ID);
594    HWND hwParent = GetParent(hwnd);
595    ShaderParamDlg *theDlg = DLGetWindowLongPtr<ShaderParamDlg *>(hwParent);
596    if (theDlg==NULL) return FALSE;
597 
598     switch (msg) {
599       case WM_PAINT:
600       {
601          PAINTSTRUCT ps;
602          Rect rect;
603          HDC hdc = BeginPaint( hwnd, &ps );
604          if (!IsRectEmpty(&ps.rcPaint)) {
605             GetClientRect( hwnd, &rect );
606             Shader* pShader = theDlg->GetShader();
607             DrawHilite2(hdc, rect, pShader, 2 );
608          }
609          EndPaint( hwnd, &ps );
610       }
611       break;
612    }
613    return DefWindowProc(hwnd,msg,wParam,lParam);
614 }
615 
UpdateHilite(HWND hwHilite,Shader * pShader,int layer)616 void UpdateHilite( HWND hwHilite, Shader* pShader, int layer  )
617 {
618 Rect r;
619 
620       HDC hdc = GetDC( hwHilite );
621       GetClientRect( hwHilite, &r );
622       DrawHilite( hdc, r, pShader );
623       ReleaseDC( hwHilite, hdc );
624 }
625 
626 
UpdateHilite2(HWND hwHilite,Shader * pShader,int layer)627 void UpdateHilite2( HWND hwHilite, Shader* pShader, int layer )
628 {
629 Rect r;
630 
631       HDC hdc = GetDC( hwHilite );
632       GetClientRect( hwHilite, &r );
633       DrawHilite2( hdc, r, pShader, layer );
634       ReleaseDC( hwHilite, hdc );
635 }
636 
637 
638 ////////////////////////////////////////////////////////////////////////
639 
GetMtlColor(int i,Shader * pShader)640 Color GetMtlColor( int i, Shader* pShader )
641 {
642    switch(i) {
643       case 0:  return pShader->GetAmbientClr(0,0);
644       case 1:  return pShader->GetDiffuseClr(0,0);
645       case 2:  return pShader->GetSpecularClr(0,0);
646       case 3:  return pShader->GetSelfIllumClr(0,0);
647       default: return Color(0,0,0);
648    }
649 }
650 
GetColorName(int i)651 TCHAR *GetColorName( int i )
652 {
653    switch(i) {
654       case 0:  return GetString(IDS_DS_AMBIENT);
655       case 1:  return GetString(IDS_DS_DIFFUSE);
656       case 2:  return GetString(IDS_DS_SPECULAR);
657       case 3:  return GetString(IDS_KE_SELFILLUM_CLR);
658       default: return GetString(IDS_KE_NOSUCH_CLR);
659    }
660 }
661 
SetMtlColor(int i,Color c,Shader * pShader,IColorSwatch ** cs,TimeValue t)662 void SetMtlColor(int i, Color c, Shader* pShader, IColorSwatch** cs, TimeValue t)
663 {
664    switch(i) {
665       case 0: //ambient
666          pShader->SetAmbientClr(c,t);
667          if ( pShader->GetLockAD() ){
668             pShader->SetDiffuseClr(c, t);
669             cs[1]->SetColor( c );
670             if (pShader->GetLockDS() ){
671                pShader->SetSpecularClr(c,t);
672                cs[2]->SetColor(c);
673             }
674          }
675          break;
676       case 1: //diffuse
677          pShader->SetDiffuseClr(c,t);
678          if (pShader->GetLockAD() ){
679             pShader->SetAmbientClr(c,t);
680             cs[0]->SetColor(c);
681          }
682          if ( pShader->GetLockDS() ){
683             pShader->SetSpecularClr(c,t);
684             cs[2]->SetColor(c);
685             }
686          break;
687       case 2: // specular
688          pShader->SetSpecularClr(c,t);
689          if (pShader->GetLockDS() ){
690             pShader->SetDiffuseClr(c,t);
691             cs[1]->SetColor(c);
692             if (pShader->GetLockAD() ){
693                pShader->SetAmbientClr(c,t);
694                cs[0]->SetColor(c);
695                }
696             }
697          break;
698       case 3:
699          pShader->SetSelfIllumClr(c,t);
700          break;
701    }
702 }
703 
704 ///////////////////////////////////////////////////////////////////////////
705 // utility math routines
706 //
RotateVec(Point3 & p,Point3 & a,float rdn)707 Point3 RotateVec( Point3& p, Point3& a, float rdn )
708 {
709    float c = float( cos( rdn ));
710    float t = 1 - c;
711    float s = float( sin( rdn ));
712    float txy = t * a.x * a.y;
713    float tyz = t * a.y * a.z;
714    float txz = t * a.x * a.z;
715    float sx = s * a.x;
716    float sy = s * a.y;
717    float sz = s * a.z;
718 
719    Point3 out;
720    out.x = p.x *(t* a.x * a.x + c) + p.y * (txy - sz) + p.z * (txz + sy);
721    out.y = p.x *(txy + sz) + p.y * (t* a.y * a.y + c) + p.z * (tyz - sx);
722    out.z = p.x *(txz - sy) + p.y * (tyz + sx) + p.z * (t* a.z * a.z + c);
723 
724    return out;
725 }
726