1 /**********************************************************************
2 *<
3 FILE: Wood.cpp
4
5 DESCRIPTION: Wood 3D Texture map.
6
7 CREATED BY: Suryan Stalin
8
9 HISTORY: Modified from Marble.cpp by adding IPAS wood stuff
10
11 *> Copyright (c) 1994, All Rights Reserved.
12 **********************************************************************/
13
14
15 //Includes
16 #include "mtlhdr.h"
17 #include "woodres.h"
18 #include "iparamm2.h"
19 #include "stdmat.h"
20 #include "wooddent.h"
21 #include "wood.h"
22 #include "macrorec.h"
23
24
25 // JBW: IDs for ParamBlock2 blocks and parameters
26 // Parameter and ParamBlock IDs
27 enum { wood_params, }; // pblock ID
28 // dents_params param IDs
29 enum
30 {
31 wood_map1,wood_map2,wood_color1,wood_color2,
32 wood_map1_on, wood_map2_on, // main grad params
33
34 wood_thickness,wood_rnoise, wood_anoise,
35 wood_coords,
36 // wood_seed
37
38 };
39
40 //externs
41 extern HINSTANCE hInstance;
42
43 ParamDlg *Wood::xyzGenDlg;
44
45 //Globals
46 static WoodClassDesc woodCD;
47 static int subTexId[NSUBTEX] = { IDC_WOOD_TEX1, IDC_WOOD_TEX2 };
48 static ParamBlockDescID pbdesc[] = {
49 { TYPE_FLOAT, NULL, TRUE,wood_thickness }, // size
50 { TYPE_FLOAT, NULL, TRUE,wood_rnoise }, // r1
51 { TYPE_FLOAT, NULL, TRUE,wood_anoise }, // r2
52 { TYPE_RGBA, NULL, TRUE,wood_color1 }, // col1
53 { TYPE_RGBA, NULL, TRUE,wood_color2 } // col2
54 };
55 static int nameID[] = { IDS_DS_WOODSIZE,
56 IDS_DS_WOODR1,
57 IDS_DS_WOODR2,
58 IDS_DS_COLOR1,
59 IDS_DS_COLOR2
60 };
61 static int colID[2] = { IDC_WOOD_COL1, IDC_WOOD_COL2 };
62 static Class_ID woodClassID(WOOD_CLASS_ID,0);
63 static float noiseTable[NOISE_DIM+1][NOISE_DIM+1][NOISE_DIM+1];
64 static int noiseInited = 0;
65 // Array of old versions
66 static ParamVersionDesc versions[1] = {
67 ParamVersionDesc(pbdesc,5,1)
68 };
69 // per instance gradient block
70 static ParamBlockDesc2 wood_param_blk ( wood_params, _T("parameters"), 0, &woodCD, P_AUTO_CONSTRUCT + P_AUTO_UI, 1,
71 //rollout
72 IDD_WOOD, IDS_DS_WOOD_PARAMS, 0, 0, NULL,
73 // params
74 wood_map1, _T("map1"), TYPE_TEXMAP, P_OWNERS_REF, IDS_PW_MAP1,
75 p_refno, 2,
76 p_subtexno, 0,
77 p_ui, TYPE_TEXMAPBUTTON, IDC_WOOD_TEX1,
78 end,
79 wood_map2, _T("map2"), TYPE_TEXMAP, P_OWNERS_REF, IDS_PW_MAP2,
80 p_refno, 3,
81 p_subtexno, 1,
82 p_ui, TYPE_TEXMAPBUTTON, IDC_WOOD_TEX2,
83 end,
84 wood_color1, _T("color1"), TYPE_RGBA, P_ANIMATABLE, IDS_DS_COLOR1,
85 p_default, Color(0,0,0),
86 p_ui, TYPE_COLORSWATCH, IDC_WOOD_COL1,
87 end,
88 wood_color2, _T("color2"), TYPE_RGBA, P_ANIMATABLE, IDS_DS_COLOR2,
89 p_default, Color(1,1,1),
90 p_ui, TYPE_COLORSWATCH, IDC_WOOD_COL2,
91 end,
92 wood_map1_on, _T("map1Enabled"), TYPE_BOOL, 0, IDS_PW_MAP1ENABLE,
93 p_default, TRUE,
94 p_ui, TYPE_SINGLECHEKBOX, IDC_MAPON1,
95 end,
96 wood_map2_on, _T("map2Enabled"), TYPE_BOOL, 0, IDS_PW_MAP2ENABLE,
97 p_default, TRUE,
98 p_ui, TYPE_SINGLECHEKBOX, IDC_MAPON2,
99 end,
100
101 wood_thickness, _T("thickness"), TYPE_FLOAT, P_ANIMATABLE, IDS_DS_WOODSIZE,
102 p_default, 7.0,
103 p_range, 0.0, 999999999.0,
104 p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_WOODSIZE_EDIT, IDC_WOODSIZE_SPIN, .1f,
105 end,
106 wood_rnoise, _T("radialNoise"), TYPE_FLOAT, P_ANIMATABLE, IDS_DS_WOODR1,
107 p_default, 1.0,
108 p_range, 0.0, 100.0,
109 p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_R1_EDIT, IDC_R1_SPIN, .1f,
110 end,
111 wood_anoise, _T("axialNoise"), TYPE_FLOAT, P_ANIMATABLE, IDS_DS_WOODR2,
112 p_default, 1.0f,
113 p_range, 0.0, 100.0f,
114 p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_R2_EDIT, IDC_R2_SPIN, .1f,
115 end,
116 wood_coords, _T("coords"), TYPE_REFTARG, P_OWNERS_REF, IDS_DS_COORDINATES,
117 p_refno, 0,
118 end,
119 // wood_seed, _T("seed"), TYPE_INT, 0, IDS_PW_SEED,
120 // p_default, 65432,
121 // p_range, 0, 99999999,
122 // p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_WOODSEED_EDIT, IDC_WOODSEED_SPIN, 1.0f,
123 // end,
124
125 end
126 );
127
128 //Class Implementations
129
130 //dialog stuff to get the Set Ref button
131 class WoodDlgProc : public ParamMap2UserDlgProc {
132 //public ParamMapUserDlgProc {
133 public:
134 Wood *wood;
WoodDlgProc(Wood * m)135 WoodDlgProc(Wood *m) {wood = m;}
136 INT_PTR DlgProc(TimeValue t,IParamMap2 *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
DeleteThis()137 void DeleteThis() {delete this;}
SetThing(ReferenceTarget * m)138 void SetThing(ReferenceTarget *m) {
139 wood = (Wood*)m;
140 }
141 };
142
143
144
DlgProc(TimeValue t,IParamMap2 * map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)145 INT_PTR WoodDlgProc::DlgProc(
146 TimeValue t,IParamMap2 *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
147 {
148 switch (msg) {
149 case WM_COMMAND:
150 switch (LOWORD(wParam))
151 {
152 case IDC_WOOD_SWAP:
153 {
154 wood->SwapInputs();
155 }
156 }
157 break;
158 }
159 return FALSE;
160 }
161
162
163 // Wood
Wood()164 Wood::Wood()
165 {
166 #ifdef SHOW_3DMAPS_WITH_2D
167 texHandle = NULL;
168 #endif
169 Param1 = FALSE;
170 subTex[0] = subTex[1] = NULL;
171 pblock = NULL;
172 xyzGen = NULL;
173 seed = 0;
174 InitNoise();
175 woodCD.MakeAutoParamBlocks(this); // make and intialize paramblock2
176 Init();
177 rollScroll=0;
178 vers = 0;
179 }
180
181 #define IN_TO_M(x) (x / 39.370079f)
182
Init()183 void Wood::Init()
184 {
185 if (xyzGen) xyzGen->Reset();
186 else ReplaceReference( 0, GetNewDefaultXYZGen());
187 ivalid.SetEmpty();
188 SetColor(0, Color(0.79f,0.69f,0.27f), TimeValue(0));
189 SetColor(1, Color(0.51f,0.32f,0.05f), TimeValue(0));
190 RegisterDistanceDefault(_T("Wood Params"), _T("Size"), 7.0f, IN_TO_M(7.0f));
191 float size = GetDistanceDefault(_T("Wood Params"), _T("Size"));
192 SetSize(size, TimeValue(0));
193 SetR1(1.0f, TimeValue(0));
194 SetR2(1.0f, TimeValue(0));
195 for (int i=0; i<NSUBTEX; i++) mapOn[i] = TRUE;
196 }
197
Reset()198 void Wood::Reset()
199 {
200 woodCD.Reset(this, TRUE); // reset pb2 params
201 DeleteReference(2);
202 DeleteReference(3);
203 Init();
204 }
205
206 #ifdef SHOW_3DMAPS_WITH_2D
GetActiveTexHandle(TimeValue t,TexHandleMaker & thmaker)207 DWORD_PTR Wood::GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker) {
208 if (texHandle) {
209 if (texHandleValid.InInterval(t))
210 return texHandle->GetHandle();
211 else DiscardTexHandle();
212 }
213 texHandle = thmaker.MakeHandle(GetVPDisplayDIB(t,thmaker,texHandleValid));
214 return texHandle->GetHandle();
215 }
216 #endif
217
218
NotifyChanged()219 void Wood::NotifyChanged()
220 {
221 NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
222 }
223
ClassID()224 Class_ID Wood::ClassID()
225 {
226 return woodClassID;
227 }
228
Clone(RemapDir & remap)229 RefTargetHandle Wood::Clone(RemapDir &remap)
230 {
231 Wood *mnew = new Wood();
232 *((MtlBase*)mnew) = *((MtlBase*)this); // copy superclass stuff
233 mnew->ReplaceReference(0,remap.CloneRef(xyzGen));
234 mnew->ReplaceReference(1,remap.CloneRef(pblock));
235 mnew->col[0] = col[0];
236 mnew->col[1] = col[1];
237 mnew->r1 = r1;
238 mnew->r2 = r2;
239 mnew->size = size;
240 // mnew->seed = seed;
241 // mnew->InitNoise();
242 mnew->ivalid.SetEmpty();
243 for (int i = 0; i<NSUBTEX; i++) {
244 mnew->subTex[i] = NULL;
245 if (subTex[i])
246 mnew->ReplaceReference(i+2,remap.CloneRef(subTex[i]));
247 mnew->mapOn[i] = mapOn[i];
248 }
249 BaseClone(this, mnew, remap);
250 return (RefTargetHandle)mnew;
251 }
252
CreateParamDlg(HWND hwMtlEdit,IMtlParams * imp)253 ParamDlg* Wood::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
254 {
255 // create the rollout dialogs
256 xyzGenDlg = xyzGen->CreateParamDlg(hwMtlEdit, imp);
257 IAutoMParamDlg* masterDlg = woodCD.CreateParamDlgs(hwMtlEdit, imp, this);
258 // add the secondary dialogs to the master
259 masterDlg->AddDlg(xyzGenDlg);
260 //attach a dlg proc to handle the swap button
261 wood_param_blk.SetUserDlgProc(new WoodDlgProc(this));
262
263 return masterDlg;
264
265 }
266
SetDlgThing(ParamDlg * dlg)267 BOOL Wood::SetDlgThing(ParamDlg* dlg)
268 {
269 // PW: set the appropriate 'thing' sub-object for each
270 // secondary dialog
271 if (dlg == xyzGenDlg)
272 xyzGenDlg->SetThing(xyzGen);
273 else
274 return FALSE;
275 return TRUE;
276 }
277
ReadSXPData(TCHAR * name,void * sxpdata)278 void Wood::ReadSXPData(TCHAR *name, void *sxpdata)
279 {
280 WoodState *state = (WoodState*)sxpdata;
281 if (state->version==WOOD_VERS) {
282 SetColor(0, ColrFromCol24(state->col1),0);
283 SetColor(1, ColrFromCol24(state->col2),0);
284 SetR1(state->r1,0);
285 SetR2(state->r2,0);
286 SetSize(state->size,0);
287 }
288 }
289
Update(TimeValue t,Interval & valid)290 void Wood::Update(TimeValue t, Interval& valid)
291 {
292
293 /* if (Param1)
294 {
295 pblock->SetValue(wood_map1_on,t,mapOn[0]);
296 pblock->SetValue(wood_map2_on,t,mapOn[1]);
297 pblock->SetValue(wood_seed,t,seed);
298 Param1 = FALSE;
299 }
300 */
301
302 if (!ivalid.InInterval(t)) {
303 ivalid.SetInfinite();
304 xyzGen->Update(t,ivalid);
305 pblock->GetValue( wood_color1, t, col[0], ivalid );
306 col[0].ClampMinMax();
307 pblock->GetValue( wood_color2, t, col[1], ivalid );
308 col[1].ClampMinMax();
309 pblock->GetValue( wood_rnoise, t, r1, ivalid );
310 pblock->GetValue( wood_anoise, t, r2, ivalid );
311 pblock->GetValue( wood_thickness, t, size, ivalid );
312 pblock->GetValue( wood_map1_on, t, mapOn[0], ivalid );
313 pblock->GetValue( wood_map2_on, t, mapOn[1], ivalid );
314
315 // int rseed =-9876545;
316 // pblock->GetValue( wood_seed, t, rseed, ivalid );
317 // if (rseed != seed)
318 // {
319 // seed = rseed;
320 // InitNoise();
321 // }
322 // else seed = rseed;
323 //
324 for (int i=0; i<NSUBTEX; i++) {
325 if (subTex[i])
326 subTex[i]->Update(t,ivalid);
327 }
328 }
329 valid &= ivalid;
330 }
331
332
SetColor(int i,Color c,TimeValue t)333 void Wood:: SetColor(int i, Color c, TimeValue t)
334 {
335 // col[i] = c;
336 col[i].r = c.r;
337 col[i].g = c.g;
338 col[i].b = c.b;
339 pblock->SetValue( i==0?wood_color1:wood_color2, t, c);
340 }
341
SwapInputs()342 void Wood::SwapInputs()
343 {
344 Color t = col[0]; col[0] = col[1]; col[1] = t;
345 Texmap *x = subTex[0]; subTex[0] = subTex[1]; subTex[1] = x;
346 pblock->SwapControllers(wood_color1,0,wood_color2,0);
347 wood_param_blk.InvalidateUI(wood_color1);
348 wood_param_blk.InvalidateUI(wood_color2);
349 wood_param_blk.InvalidateUI(wood_map1);
350 wood_param_blk.InvalidateUI(wood_map2);
351 macroRec->FunctionCall(_T("swap"), 2, 0, mr_prop, _T("color1"), mr_reftarg, this, mr_prop, _T("color2"), mr_reftarg, this);
352 macroRec->FunctionCall(_T("swap"), 2, 0, mr_prop, _T("map1"), mr_reftarg, this, mr_prop, _T("map2"), mr_reftarg, this);
353
354 }
355
SetR1(float f,TimeValue t)356 void Wood::SetR1(float f, TimeValue t)
357 {
358 r1 = f;
359 pblock->SetValue( wood_rnoise, t, f);
360 }
361
SetR2(float f,TimeValue t)362 void Wood::SetR2(float f, TimeValue t)
363 {
364 r2 = f;
365 pblock->SetValue( wood_anoise, t, f);
366 }
367
SetSize(float f,TimeValue t)368 void Wood::SetSize(float f, TimeValue t)
369 {
370 size = f;
371 pblock->SetValue( wood_thickness, t, f);
372 }
373
GetReference(int i)374 RefTargetHandle Wood::GetReference(int i)
375 {
376 switch(i) {
377 case 0: return xyzGen;
378 case 1: return pblock ;
379 default:return subTex[i-2];
380 }
381 }
382
SetReference(int i,RefTargetHandle rtarg)383 void Wood::SetReference(int i, RefTargetHandle rtarg)
384 {
385 switch(i) {
386 case 0: xyzGen = (XYZGen *)rtarg; break;
387 case 1: pblock = (IParamBlock2 *)rtarg; break;
388 default: subTex[i-2] = (Texmap *)rtarg; break;
389 }
390 }
391
SetSubTexmap(int i,Texmap * m)392 void Wood::SetSubTexmap(int i, Texmap *m)
393 {
394 ReplaceReference(i+2,m);
395 if (i==0)
396 {
397 wood_param_blk.InvalidateUI(wood_map1);
398 ivalid.SetEmpty();
399 }
400 else if (i==1)
401 {
402 wood_param_blk.InvalidateUI(wood_map2);
403 ivalid.SetEmpty();
404 }
405
406 }
407
GetSubTexmapSlotName(int i)408 TSTR Wood::GetSubTexmapSlotName(int i)
409 {
410 switch(i) {
411 case 0: return TSTR(GetString(IDS_DS_COLOR1));
412 case 1: return TSTR(GetString(IDS_DS_COLOR2));
413 default: return TSTR(_T(""));
414 }
415 }
416
SubAnim(int i)417 Animatable* Wood::SubAnim(int i)
418 {
419 switch (i) {
420 case 0: return xyzGen;
421 case 1: return pblock;
422 default: return subTex[i-2];
423 }
424 }
425
SubAnimName(int i)426 TSTR Wood::SubAnimName(int i)
427 {
428 switch (i) {
429 case 0: return TSTR(GetString(IDS_DS_COORDINATES));
430 case 1: return TSTR(GetString(IDS_DS_PARAMETERS));
431 default: return GetSubTexmapTVName(i-2);
432 }
433 }
434
435
NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget,PartID & partID,RefMessage message)436 RefResult Wood::NotifyRefChanged( Interval changeInt, RefTargetHandle hTarget,
437 PartID& partID, RefMessage message )
438 {
439 switch (message) {
440 case REFMSG_CHANGE:
441 ivalid.SetEmpty();
442 if (hTarget == pblock )
443 {
444 // see if this message came from a changing parameter in the pblock,
445 // if so, limit rollout update to the changing item and update any active viewport texture
446 ParamID changing_param = pblock->LastNotifyParamID();
447 // if (hTarget != xyzGen && hTarget != pblock )
448 wood_param_blk.InvalidateUI(changing_param);
449 // notify our dependents that we've changed
450 // NotifyChanged(); //DS this is redundant
451 #ifdef SHOW_3DMAPS_WITH_2D
452 if (changing_param != -1)
453 DiscardTexHandle();
454 #endif
455 }
456 if (hTarget == xyzGen )
457 {
458 #ifdef SHOW_3DMAPS_WITH_2D
459 DiscardTexHandle();
460 #endif
461 // NotifyChanged(); //DS this is redundant
462 }
463
464 break;
465 }
466 return(REF_SUCCEED);
467 }
468
469 #define MAPOFF_CHUNK 0x1000
470 #define PARAM2_CHUNK 0x1010
471
Save(ISave * isave)472 IOResult Wood::Save(ISave *isave)
473 {
474 // ULONG nb;
475 IOResult res;
476 // Save common stuff
477 isave->BeginChunk(MTL_HDR_CHUNK);
478 res = MtlBase::Save(isave);
479 if (res!=IO_OK) return res;
480 isave->EndChunk();
481
482 // isave->BeginChunk(WOOD_NOISE_CHUNK);
483 // isave->Write(&seed,sizeof(int),&nb);
484 // isave->EndChunk();
485
486 isave->BeginChunk(PARAM2_CHUNK);
487 isave->EndChunk();
488
489 return IO_OK;
490 }
491
492 class WoodPostLoad : public PostLoadCallback
493 {
494 public:
495 Wood *chk;
WoodPostLoad(Wood * b)496 WoodPostLoad(Wood *b) {chk=b;}
proc(ILoad * iload)497 void proc(ILoad *iload) {
498 if (chk->vers<1) {
499 if (chk->pblock)
500 chk->pblock->RescaleParam(wood_thickness, 0, 100.0f);
501 // ScaleFloatController(chk->pblock, PB_SIZE, 100.0f);
502 // iload->SetObsolete();
503 }
504 delete this;
505 }
506 };
507
508 //watje
509
510 class Wood2PostLoadCallback:public PostLoadCallback
511 {
512 public:
513 Wood *s;
514 int Param1;
Wood2PostLoadCallback(Wood * r,BOOL b)515 Wood2PostLoadCallback(Wood *r, BOOL b) {s=r;Param1 = b;}
516 void proc(ILoad *iload);
517 };
518
proc(ILoad * iload)519 void Wood2PostLoadCallback::proc(ILoad *iload)
520 {
521 if (Param1)
522 {
523 TimeValue t = 0;
524 s->pblock->SetValue(wood_map1_on,t,s->mapOn[0]);
525 s->pblock->SetValue(wood_map2_on,t,s->mapOn[1]);
526 // s->pblock->SetValue(wood_seed,t,s->seed);
527 Param1 = FALSE;
528 }
529
530 // Interval ivalid;
531 // s->pblock->GetValue( wood_seed, 0, s->seed, ivalid );
532 // s->InitNoise();
533
534 delete this;
535 }
536
537
Load(ILoad * iload)538 IOResult Wood::Load(ILoad *iload)
539 {
540 // ULONG nb;
541 IOResult res;
542 int id;
543 vers = 0;
544 Param1 = TRUE;
545
546 while (IO_OK==(res=iload->OpenChunk()))
547 {
548 switch(id = iload->CurChunkID())
549 {
550 case MTL_HDR_CHUNK:
551 res = MtlBase::Load(iload);
552 break;
553 case WOODVERS1_CHUNK:
554 vers = 1;
555
556 break;
557 case MAPOFF_CHUNK+0:
558 case MAPOFF_CHUNK+1:
559 mapOn[id-MAPOFF_CHUNK] = 0;
560 break;
561
562 #if 0
563 case WOOD_NOISE_CHUNK:
564 iload->Read(&seed,sizeof(int),&nb);
565 // InitNoise();
566 break;
567 #endif
568 case PARAM2_CHUNK:
569 Param1 = FALSE;
570 break;
571
572
573 }
574 iload->CloseChunk();
575 if (res!=IO_OK)
576 return res;
577 }
578 if (Param1)
579 {
580 ParamBlock2PLCB* plcb = new ParamBlock2PLCB(versions, 1, &wood_param_blk, this, 1);
581 iload->RegisterPostLoadCallback(plcb);
582 }
583 Wood2PostLoadCallback* wood2plcb = new Wood2PostLoadCallback(this,Param1);
584 iload->RegisterPostLoadCallback(wood2plcb);
585
586 return IO_OK;
587 }
588
InitNoise()589 void Wood::InitNoise()
590 {
591 // if(!seed)
592 // seed = rand()+1;
593 if (!noiseInited) {
594 noiseInited = 1;
595 srand(65432);
596 int i, j, k, ii, jj, kk;
597 for (i=0; i<=NOISE_DIM; i++)
598 for (j=0; j<=NOISE_DIM; j++)
599 for (k=0; k<=NOISE_DIM; k++)
600 {
601 noiseTable[i][j][k] = (float)(rand()&0x7FFF);
602 ii = (i==NOISE_DIM)?0:i;
603 jj = (j==NOISE_DIM)?0:j;
604 kk = (k==NOISE_DIM)?0:k;
605 noiseTable[i][j][k] = noiseTable[ii][jj][kk];
606 }
607 }
608 }
609
WoodNoise(float x)610 float Wood::WoodNoise(float x)
611 {
612 int ix;
613 double fx, mx;
614 double n0, n1;
615 mx = fmod((double)x, FNOISE_DIM);
616 if (mx<0) mx += FNOISE_DIM;
617 ix = (int)mx;
618 fx = fmod(mx, 1.0);
619 n0 = noiseTable[ix][0][0];
620 n1 = noiseTable[ix+1][0][0];
621
622 return (float)((n0+fx*(n1-n0))/32768.0);
623 }
624
625 /*
626 float noise(float x, float y, float z)
627 {
628 int ix, iy, iz;
629 float fx, fy, fz, mx, my, mz;
630 float n, n00, n01, n10, n11, n0, n1;
631 mx = fmod(x, FNOISE_DIM); if (mx<0) mx += FNOISE_DIM;
632 my = fmod(y, FNOISE_DIM); if (my<0) my += FNOISE_DIM;
633 mz = fmod(z, FNOISE_DIM); if (mz<0) mz += FNOISE_DIM;
634 ix = (int)mx;
635 iy = (int)my;
636 iz = (int)mz;
637 fx = fmod(mx, 1.0);
638 fy = fmod(my, 1.0);
639 fz = fmod(mz, 1.0);
640 n = noise_table[ix][iy][iz];
641 n00 = n + fx*(noise_table[ix+1][iy][iz]-n);
642 n = noise_table[ix][iy][iz+1];
643 n01 = n + fx*(noise_table[ix+1][iy][iz+1]-n);
644 n = noise_table[ix][iy+1][iz];
645 n10 = n + fx*(noise_table[ix+1][iy+1][iz]-n);
646 n = noise_table[ix][iy+1][iz+1];
647 n11 = n + fx*(noise_table[ix+1][iy+1][iz+1]-n);
648 n0 = n00 + fy*(n10-n00);
649 n1 = n01 + fy*(n11-n01);
650 return(((float)(n0+fz*(n1-n0)))/32768.0);
651 }
652
653 */
654
LerpColor(RGBA * c,RGBA * a,RGBA * b,float f)655 void Wood::LerpColor(RGBA *c, RGBA *a, RGBA *b, float f)
656 {
657 int alph, ialph;
658
659 if (f>1.0) f = 1.0f;
660 alph = (int)(4096*f);
661 ialph = 4096-alph;
662
663 c->r = (float)(((int)(ialph*a->r + alph*b->r)*255)>>12);
664 c->g = (float)(((int)(ialph*a->g + alph*b->g)*255)>>12);
665 c->b = (float)(((int)(ialph*a->b + alph*b->b)*255)>>12);
666
667 c->r /= 255.0f;
668 c->g /= 255.0f;
669 c->b /= 255.0f;
670
671 }
672
673 /* smooth step function with hermite interpolation*/
SmoothStep(float x0,float x1,float v)674 float Wood::SmoothStep(float x0, float x1, float v)
675 {
676 if (v<=x0) return(0.0f);
677 else if (v>=x1) return(1.0f);
678 else {
679 float u = (v-x0)/(x1-x0);
680 return(u*u*(3-2*u));
681 }
682 }
683
WoodFunc(Point3 p)684 float Wood::WoodFunc(Point3 p) {
685 float r;
686 float px = p.x/size;
687 float py = p.y/size;
688 float pz = p.z/size;
689 px += WoodNoise(px)*r1;
690 py += WoodNoise(py)*r1;
691 pz += WoodNoise(pz)*r1;
692 r = (float) sqrt(py*py+pz*pz);
693 r += WoodNoise(r)+r2*WoodNoise(px/4.0f);
694 r = (float)fmod((double)r, 1.0); /* be periodic */
695 r = SmoothStep(0.0f, 0.8f, r) - SmoothStep(0.83f, 1.0f, r);
696 return(r);
697 }
698
699 static AColor black(0.0f,0.0f,0.0f,0.0f);
700
EvalColor(ShadeContext & sc)701 RGBA Wood::EvalColor(ShadeContext& sc)
702 {
703 Point3 p,dp;
704 RGBA c;
705 if (!sc.doMaps) return black;
706 if (gbufID) sc.SetGBufferID(gbufID);
707
708 xyzGen->GetXYZ(sc,p,dp);
709 if (size==0.0f) size=.0001f;
710 // p *= FACT/size;
711
712 float d = WoodFunc(p);
713
714 if (d<=.0005f)
715 return (mapOn[0]&&subTex[0]) ? subTex[0]->EvalColor(sc): col[0];
716 else
717 if (d>=.9995)
718 return (mapOn[1]&&subTex[1]) ? subTex[1]->EvalColor(sc): col[1];
719 RGBA c0 = (mapOn[0]&&subTex[0]) ? subTex[0]->EvalColor(sc): col[0];
720 RGBA c1 = (mapOn[1]&&subTex[1]) ? subTex[1]->EvalColor(sc): col[1];
721 c = (1.0f-d)*c0 + d*c1;
722 return c;
723 }
724
EvalNormalPerturb(ShadeContext & sc)725 Point3 Wood::EvalNormalPerturb(ShadeContext& sc)
726 {
727 float del,d;
728 Point3 p,dp;
729
730 if (!sc.doMaps) return Point3(0,0,0);
731 if (gbufID) sc.SetGBufferID(gbufID);
732 xyzGen->GetXYZ(sc,p,dp);
733 if (size==0.0f) size=.0001f;
734 // p *= FACT/size;
735
736 d = WoodFunc(p);
737 // del = 20.0f;
738 del = 0.1f;
739 Point3 np;
740 Point3 M[3];
741 xyzGen->GetBumpDP(sc,M);
742 np.x = (WoodFunc(p+del*M[0]) - d)/del;
743 np.y = (WoodFunc(p+del*M[1]) - d)/del;
744 np.z = (WoodFunc(p+del*M[2]) - d)/del;
745 // return np*100.0f;
746 np = sc.VectorFromNoScale(np,REF_OBJECT);
747 Texmap *sub0 = mapOn[0]?subTex[0]:NULL;
748 Texmap *sub1 = mapOn[1]?subTex[1]:NULL;
749 if (sub0||sub1) {
750 // d((1-k)*a + k*b ) = dk*(b-a) + k*(db-da) + da
751 float a,b;
752 Point3 da,db;
753 if (sub0) { a = sub0->EvalMono(sc); da = sub0->EvalNormalPerturb(sc); }
754 else { a = Intens(col[0]); da = Point3(0.0f,0.0f,0.0f); }
755 if (sub1) { b = sub1->EvalMono(sc); db = sub1->EvalNormalPerturb(sc); }
756 else { b = Intens(col[1]); db= Point3(0.0f,0.0f,0.0f); }
757 np = (b-a)*np + d*(db-da) + da;
758 }
759 else
760 np *= Intens(col[1])-Intens(col[0]);
761 return np;
762 }
763
764 //WoodClassDesc
ClassID()765 Class_ID WoodClassDesc::ClassID()
766 {
767 return woodClassID;
768 }
GetWoodDesc()769 ClassDesc* GetWoodDesc() { return &woodCD; }
770
771