├── src ├── logo.bmp ├── BerconNoise.rc ├── DLL │ ├── BerconMaps_2021_64.dlt │ ├── BerconMaps_2022_64.dlt │ ├── BerconMaps_2023_64.dlt │ ├── BerconMaps_2024_64.dlt │ ├── BerconMaps_2025_64.dlt │ └── BerconMaps_2026_64.dlt ├── BerconNoise.def ├── BerconNoise.vcxproj.DotSettings ├── BerconMap.h ├── worley.h ├── GradientMap.h ├── curvectrl.h ├── commonMath.cpp ├── BerconDlg.h ├── BerconRefMaker.h ├── IGradient.h ├── BerconMaps.sln ├── commonMath.h ├── NoiseAverages.h ├── perlin.h ├── noise.h ├── curvectrl.cpp ├── DllEntry.cpp ├── GradientRamp.h ├── fractal.h ├── BerconDistortion.h ├── tile.h ├── worley.cpp ├── BerconTile.h ├── IGradient.cpp ├── BerconNoise.vcxproj.filters ├── BerconWood.h ├── BerconNoise.h ├── BerconGradient.h ├── BerconSC.h ├── BerconDistortion.cpp ├── fractal.cpp ├── noise.cpp ├── BerconCommon.cpp ├── perlin.cpp ├── GradientRamp.cpp └── tile.cpp ├── README.md ├── change notes.txt ├── .gitignore └── LICENSE /src/logo.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bercon/BerconMaps/HEAD/src/logo.bmp -------------------------------------------------------------------------------- /src/BerconNoise.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bercon/BerconMaps/HEAD/src/BerconNoise.rc -------------------------------------------------------------------------------- /src/DLL/BerconMaps_2021_64.dlt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bercon/BerconMaps/HEAD/src/DLL/BerconMaps_2021_64.dlt -------------------------------------------------------------------------------- /src/DLL/BerconMaps_2022_64.dlt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bercon/BerconMaps/HEAD/src/DLL/BerconMaps_2022_64.dlt -------------------------------------------------------------------------------- /src/DLL/BerconMaps_2023_64.dlt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bercon/BerconMaps/HEAD/src/DLL/BerconMaps_2023_64.dlt -------------------------------------------------------------------------------- /src/DLL/BerconMaps_2024_64.dlt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bercon/BerconMaps/HEAD/src/DLL/BerconMaps_2024_64.dlt -------------------------------------------------------------------------------- /src/DLL/BerconMaps_2025_64.dlt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bercon/BerconMaps/HEAD/src/DLL/BerconMaps_2025_64.dlt -------------------------------------------------------------------------------- /src/DLL/BerconMaps_2026_64.dlt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bercon/BerconMaps/HEAD/src/DLL/BerconMaps_2026_64.dlt -------------------------------------------------------------------------------- /src/BerconNoise.def: -------------------------------------------------------------------------------- 1 | LIBRARY BerconNoise.dlt 2 | EXPORTS 3 | LibDescription @1 PRIVATE 4 | LibNumberClasses @2 PRIVATE 5 | LibClassDesc @3 PRIVATE 6 | LibVersion @4 PRIVATE 7 | LibInitialize @6 PRIVATE 8 | LibShutdown @7 PRIVATE 9 | SECTIONS 10 | .data READ WRITE 11 | -------------------------------------------------------------------------------- /src/BerconNoise.vcxproj.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | Cpp17 -------------------------------------------------------------------------------- /src/BerconMap.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2008 Jerry Ylilammi 2 | // All rights reserved. 3 | 4 | /* 5 | Extra map interface that should be filled by all my maps that support extra features. 6 | 7 | Features: 8 | mapID Similar to mtlNum but aimed for maps not materials 9 | 10 | */ 11 | 12 | #pragma once 13 | 14 | #include "BerconNoise.h" 15 | 16 | class BerconMap : public Texmap { 17 | public: 18 | virtual RGBA BerconEvalColor(ShadeContext& sc, int mapID) = 0; 19 | virtual float BerconEvalMono(ShadeContext& sc, int mapID) = 0; 20 | virtual Point3 BerconEvalNormalPerturb(ShadeContext& sc, int mapID) = 0; 21 | }; -------------------------------------------------------------------------------- /src/worley.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | // Based on Steven Worley's cellular noise 19 | 20 | class Worley { 21 | public: 22 | Worley() {} 23 | ~Worley() {} 24 | 25 | static void noise(double at[3], int order, double* F, int function); 26 | 27 | private: 28 | static void add(long xi, long yi, long zi, double at[3], int order, double *F, int function); 29 | }; -------------------------------------------------------------------------------- /src/GradientMap.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | /* 19 | Interface that has to be filled so gradient control can report users actions 20 | */ 21 | 22 | #pragma once 23 | 24 | class GradientMap { 25 | public: 26 | virtual void gradAddKey(float pos) = 0; 27 | virtual void gradMoveKey(int n, float pos) = 0; 28 | virtual void gradDelKey(int n) = 0; 29 | virtual void gradSelKey() = 0; 30 | virtual void gradReset() = 0; 31 | }; -------------------------------------------------------------------------------- /src/curvectrl.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | 19 | #include "Max.h" 20 | #include "resource.h" 21 | #include "istdplug.h" 22 | #include "icurvctl.h" 23 | 24 | // Handles basic operations on curve control 25 | 26 | class CurveCtrl { 27 | public: 28 | CurveCtrl() {} 29 | ~CurveCtrl() {} 30 | 31 | static void update(ICurveCtl *curve, HWND hParent, ReferenceMaker *resMaker); 32 | static void disable(ICurveCtl *curve); 33 | static void init(ICurveCtl *curve); 34 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | BerconMaps 2 | ========== 3 | 4 | BerconMaps is a 3rd party texture plugin for Autodesk 3ds Max. It adds five new prodecural texture maps: Noise, Wood, Tile, Distortion and Gradient. 5 | 6 | For more information, pictures and binaries go to http://www.ylilammi.com/2013/09/berconmaps/ 7 | 8 | Binaries 9 | ------------------------- 10 | Binaries can be found under `src/DLL/` folder: https://github.com/Bercon/BerconMaps/tree/master/src/DLL 11 | 12 | License 13 | ------------------------- 14 | 15 | Apache License, Version 2.0 16 | 17 | Read LICENSE file 18 | 19 | Contributing 20 | ------------------------- 21 | 22 | - Fork 23 | - Improve 24 | - Submit a pull request 25 | 26 | Credits 27 | ------------------------- 28 | 29 | - Jerry Ylilammi (author) 30 | - Vladimir Koylazov (bug fixes and support for 3ds Max 2015) 31 | - Ken Perlin (Perlin/Simplex noise) 32 | - Stefan Gustavson (C++ implementation of Perlin and Simplex noises) 33 | - Steven Worley (Worley noise and C implementation of it) 34 | - Blender team (Fractals) 35 | - John Burnett (Distortions max shadecontext implementation) 36 | - David Baker (Compiled Max 8 version of the plugin and edited source codes for Max 8) 37 | - Vladislav Gavrilov (Helped with integrating my custom gradient control into Max) 38 | -------------------------------------------------------------------------------- /src/commonMath.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #include "commonMath.h" 19 | 20 | float smooth(float d) { 21 | return (d*d*(3.f-2.f*d)); 22 | } 23 | 24 | float smooth(float d, float low, float high) { 25 | d = (d-low)/(high-low); 26 | if (d < 0) return 0.f; 27 | if (d > 1) return 1.f; 28 | return (d*d*(3.f-2.f*d)); 29 | } 30 | 31 | float linear(float d, float low, float high) { 32 | d = (d-low)/(high-low); 33 | if (d < 0) return 0.f; 34 | if (d > 1) return 1.f; 35 | return d; 36 | } 37 | 38 | float lerp(float a, float b, float blend) { 39 | return b + blend * (a-b); 40 | } -------------------------------------------------------------------------------- /src/BerconDlg.h: -------------------------------------------------------------------------------- 1 | #include "3dsmaxsdk_preinclude.h" 2 | #include "Max.h" 3 | #include "resource.h" 4 | #include "istdplug.h" 5 | #include "iparamb2.h" 6 | #include "iparamm2.h" 7 | #include "curvectrl.h" 8 | 9 | class BerconDlg: public ParamDlg { 10 | public: 11 | ParamDlg* pd; 12 | Class_ID id; 13 | int ref; 14 | 15 | BerconDlg(ParamDlg* pd, Class_ID id, int ref): pd (pd), id (id), ref (ref) {} 16 | 17 | Class_ID ClassID() { return pd->ClassID(); } 18 | void SetThing (ReferenceTarget *m) { 19 | ReferenceTarget* old = pd->GetThing(); 20 | if (old->ClassID() == id && m->ClassID() == id && old != m) { 21 | ((ICurveCtl*)old->GetReference(ref))->SetActive(FALSE); 22 | ((ICurveCtl*)old->GetReference(ref))->EnableDraw(FALSE); 23 | } 24 | pd->SetThing(m); 25 | } 26 | ReferenceTarget * GetThing () { return pd->GetThing(); } 27 | void SetTime (TimeValue t) { pd->SetTime(t); } 28 | void ReloadDialog () { pd->ReloadDialog(); } 29 | void DeleteThis () { pd->DeleteThis(); delete this; } 30 | void ActivateDlg (BOOL onOff) { pd->ActivateDlg(onOff); } 31 | int FindSubTexFromHWND (HWND hwnd) { return pd->FindSubTexFromHWND(hwnd); } 32 | int FindSubMtlFromHWND (HWND hwnd) { return pd->FindSubMtlFromHWND(hwnd); } 33 | INT_PTR Execute (int cmd, ULONG_PTR arg1=0, ULONG_PTR arg2=0, ULONG_PTR arg3=0) { return pd->Execute(cmd, arg1, arg2, arg3); } 34 | }; -------------------------------------------------------------------------------- /src/BerconRefMaker.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #include "Max.h" 19 | #include "resource.h" 20 | #include "istdplug.h" 21 | #include "icurvctl.h" 22 | 23 | #ifndef NOTIFY_REF_CHANGED_ARGS 24 | #if MAX_RELEASE < 16900 25 | #define NOTIFY_REF_CHANGED_ARGS Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message 26 | #else 27 | #define NOTIFY_REF_CHANGED_ARGS const Interval &changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message, BOOL propagate 28 | #endif // MAX_RELEASE 29 | #endif // #ifndef NOTIFY_REF_CHANGED_ARGS 30 | 31 | class BerconRefMaker : public ReferenceMaker { 32 | public: 33 | BerconRefMaker(ResourceMakerCallback *m) {thing = m;} 34 | ResourceMakerCallback *thing; 35 | void DeleteThis() {delete this;} 36 | virtual void* GetInterface(ULONG id) { 37 | if(id == I_RESMAKER_INTERFACE) 38 | return (void *) thing; 39 | else 40 | return ReferenceMaker::GetInterface(id); 41 | } 42 | RefResult NotifyRefChanged(NOTIFY_REF_CHANGED_ARGS){return REF_DONTCARE;} 43 | }; -------------------------------------------------------------------------------- /src/IGradient.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "Max.h" 21 | #include "resource.h" 22 | #include "plugapi.h" 23 | //#include "3dsmaxport.h" 24 | 25 | #include "GradientRamp.h" 26 | 27 | class IGradient : public ICustomControl { 28 | private: 29 | HWND hWndMain; 30 | public: 31 | GradientRamp *gradient; 32 | 33 | IGradient(HWND hwRamp, GradientRamp *r) { 34 | hWndMain = hwRamp; 35 | gradient = r; 36 | DLSetWindowLongPtr(hWndMain, this); 37 | Execute(I_EXEC_CB_NO_BORDER); 38 | } 39 | 40 | ~IGradient() { 41 | DLSetWindowLongPtr(hWndMain, NULL); 42 | DestroyWindow(hWndMain); 43 | hWndMain = NULL; 44 | gradient = NULL; 45 | } 46 | 47 | void setGradient(GradientRamp *r) { gradient = r; } 48 | 49 | static LRESULT CALLBACK GradientProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); // control window callback, 50 | 51 | //AColor getRampColor(float x) { return gradient->GetColor(x); } 52 | 53 | void Disable() {} 54 | 55 | void DeleteMe() {delete this;} 56 | 57 | int IsEnabled(){ return TRUE; } 58 | 59 | void Enable(int cmd) {} 60 | 61 | void Enable2(int cmd) {} 62 | 63 | HWND GetHwnd() { return hWndMain; } 64 | 65 | //void SetTooltip(bool bEnable, MCHAR* text) {} 66 | void SetTooltip(bool bEnable, const MCHAR* text) {} 67 | 68 | INT_PTR Execute(int cmd, ULONG_PTR arg1=0, ULONG_PTR arg2=0, ULONG_PTR arg3=0) { return 0; } 69 | }; 70 | -------------------------------------------------------------------------------- /src/BerconMaps.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.9.34723.18 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BerconMaps", "BerconNoise.vcxproj", "{E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Max2021|x64 = Max2021|x64 11 | Max2022|x64 = Max2022|x64 12 | Max2023|x64 = Max2023|x64 13 | Max2024_debug|x64 = Max2024_debug|x64 14 | Max2024|x64 = Max2024|x64 15 | Max2025|x64 = Max2025|x64 16 | Max2026|x64 = Max2026|x64 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Max2021|x64.ActiveCfg = Max2021|x64 20 | {E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Max2021|x64.Build.0 = Max2021|x64 21 | {E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Max2022|x64.ActiveCfg = Max2022|x64 22 | {E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Max2022|x64.Build.0 = Max2022|x64 23 | {E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Max2023|x64.ActiveCfg = Max2023|x64 24 | {E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Max2023|x64.Build.0 = Max2023|x64 25 | {E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Max2024_debug|x64.ActiveCfg = Max2024_debug|x64 26 | {E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Max2024_debug|x64.Build.0 = Max2024_debug|x64 27 | {E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Max2024|x64.ActiveCfg = Max2024|x64 28 | {E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Max2024|x64.Build.0 = Max2024|x64 29 | {E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Max2025|x64.ActiveCfg = Max2025|x64 30 | {E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Max2025|x64.Build.0 = Max2025|x64 31 | {E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Max2026|x64.ActiveCfg = Max2026|x64 32 | {E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Max2026|x64.Build.0 = Max2026|x64 33 | EndGlobalSection 34 | GlobalSection(SolutionProperties) = preSolution 35 | HideSolutionNode = FALSE 36 | EndGlobalSection 37 | GlobalSection(ExtensibilityGlobals) = postSolution 38 | SolutionGuid = {18F31B82-2705-494F-AAD9-4D1A23FB175F} 39 | EndGlobalSection 40 | EndGlobal 41 | -------------------------------------------------------------------------------- /src/commonMath.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #pragma once 19 | //TODO: Use for v3.1 20 | #include "math.h" 21 | 22 | typedef float real; 23 | typedef double ireal; 24 | 25 | // Functions 26 | 27 | float smooth(float d); 28 | 29 | float smooth(float d, float low, float high); 30 | 31 | float linear(float d, float low, float high); 32 | 33 | float lerp(float a, float b, float blend); 34 | 35 | inline float avg(float a, float b) { return (a + b) / 2.f; } 36 | inline float avg(float a, float b, float c) { return (a + b + c) / 3.f; } 37 | 38 | inline float length(float a, float b) { return sqrtf(a*a + b*b); } 39 | inline float length(float a, float b, float c) { return sqrtf(a*a + b*b + c*c); } 40 | 41 | // Macros 42 | 43 | #define SMOOTH(d) (d*d*(3.f-2.f*d)) 44 | 45 | #define MAX(a,b) (((a) > (b)) ? (a) : (b)) 46 | 47 | #define MIN(a,b) (((a) > (b)) ? (b) : (a)) 48 | 49 | #define FASTFLOOR(x) ((x) < 0 ? ((int)x-1) : ((int)x) ) 50 | 51 | #define FASTFLOORI(x) ((x) < 0 ? ((int)x-1) : ((int)x) ) 52 | 53 | #define FASTFLOORL(x) ((x) < 0 ? ((long)x-1) : ((long)x) ) 54 | 55 | #define FADE(t) ( t * t * t * ( t * ( t * 6 - 15 ) + 10 ) ) 56 | 57 | #define LERP(t, a, b) ((a) + (t)*((b)-(a))) 58 | 59 | #define ABS(x) ((x) < 0 ? (-x) : (x)) 60 | 61 | //#define LERP(a, b, blend) (b + blend * (a-b)) 62 | 63 | #define SFRAND() ((double)rand() / (double)RAND_MAX) // Random number (0..1) 64 | 65 | #define UFRAND() ((double)rand() / (double)RAND_MAX * 2. - 1.) // Random number (-1..1) 66 | 67 | #define SQRT2 1.41421356 // sqrt(2); 68 | 69 | #define DEG2RAD 0.0174532925f -------------------------------------------------------------------------------- /src/NoiseAverages.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #define sfrand() ((double)rand() / (double)RAND_MAX) 19 | #define ufrand() ((double)rand() / (double)RAND_MAX * 2. - 1.) 20 | 21 | /* 22 | Used to compute average values for noise functions, these can be used in filtering 23 | Generally the average value should be 0.0 24 | 25 | Results for the code below are: 26 | Noise #0 = 0.000004 27 | Noise #1 = -0.000373 28 | Noise #2 = 0.000208 29 | Noise #3 = 0.000020 30 | Noise #4 = -0.000007 31 | Noise #5 = 0.000211 32 | Noise #6 = -0.000336 33 | Noise #7 = -0.000121 34 | Which means they all average out pretty near 0.0 so we can use it 35 | */ 36 | class NoiseAverages { 37 | public: 38 | static void computeAverages() { 39 | CharStream *out = thread_local(current_stdout); 40 | srand(12345); 41 | 42 | int SAMPLES = 1000000; // Number of samples computed to get average 43 | float RANGE = 12345.0f; // The size of the area where samples are taken 44 | 45 | double noiseValue[8]; 46 | for (int i=0;i<8;i++) 47 | noiseValue[i] = 0.; 48 | 49 | for (int i=0;iprintf("Noise #%d = %f\n", i, noiseValue[i] / (double)SAMPLES); 67 | } 68 | } 69 | }; 70 | -------------------------------------------------------------------------------- /change notes.txt: -------------------------------------------------------------------------------- 1 | v3.05 (tested with Max 2024 only) 2 | FIX: Berconmap types display their type (e.g., "BerconWood") instead of just a generic 'Texture' in Slate editor. An override was required on the localized name. 3 | 4 | FIX: xyz_tile only referencing IDS_XYZ_TILE_X [though in practice I don't think it matters] 5 | 6 | FIX: prevent setting tiling scale to zero in XYZ pblock 7 | 8 | FIX: Random by Material checkbox/XYZ pblock. Wrong parameter label for random by material checkbox, and so this function did not work. 9 | 10 | FIX: Prevent user from using Slate spinner to set tiling option to invalid value. 11 | 12 | FIX: Macros defining versions can't be used in place of values like 25900 without setting up a separate definitions file for them. Max 2021 does not know the version number of Max 2024. :) 13 | 14 | ADD comments for future maintainers 15 | 16 | CHANGE "BerconMapping" to "BerconDistortion" 17 | 18 | REFACTOR: berconcommon uvwgen switch cases. The "Filtering:" setting was never reached except in case 0 or 1. It is now active for all map coordinate systems. 19 | 20 | KNOWN ISSUE: Gradient keys will not sort. I suspect they are sorted, but the new sort is never actually sent to the dialog window handler. (Issue present in previous commit) 21 | 22 | KNOWN ISSUE: Gradient map will display "NO MAP" in a key slot even if there's a map assigned. It will only display if the dialog window is destroyed and refreshed by switching to another map/material and back. Conversely, if the gradient is 'reset' via the right-click option, the label will persist even though the map is no longer connected. 23 | 24 | OTHER: Tweaked dialog boxes for alignment and readability (words slightly cut off, more space for options to be readable, etc.) 25 | 26 | NOTE: In Slate editor, map channel is always preset to 0 (but correctly set to 1 in dialog box). This is a cosmetic issue, albeit an annoying one. I deem it to be an Autodesk issue. 27 | 28 | NOTE: The custom control curve slows things down in "Realistic Maps" mode, or when rendering. It takes only a few maps to bring the session down to a crawl on a Skylake-X chip with 24 threads, an RTX 4070, and 128GB of RAM. 29 | 30 | NOTE FOR USERS: 31 | Note for users, nitrous viewport only matches render if viewport is in Shaded Maps mode (not Realistic mode), Explicit Map Channel is set and object has no UVW map. Assigning a UVW map will enable both modes. 32 | If "variance" is used note that the same map applied to different objects will result in an incorrect preview. This is because the map is only evaluated once for the nitrous viewport; two or more objects sharing the same material with random variance are effectively multiple maps as far as 3DSMax is concerned. This is why you will only get one preview image in the material editor for any map. 33 | -------------------------------------------------------------------------------- /src/perlin.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | // Based on Ken Perlin's perlin noise/simplex and Stefan Gustavson's 19 | // implementation of perlin/simplex noise, (Simplex)Noise1234 20 | 21 | #pragma once 22 | 23 | #include "commonMath.h" 24 | 25 | class Perlin { 26 | public: 27 | Perlin() {} 28 | ~Perlin() {} 29 | 30 | static float noise(float x); 31 | static float noise(float x, float y); 32 | static float noise(float x, float y, float z); 33 | static float noise(float x, float y, float z, float w); 34 | 35 | static float snoise(float x); 36 | static float snoise(float x, float y); 37 | static float snoise(float x, float y, float z); 38 | static float snoise(float x, float y, float z, float w); 39 | 40 | /* Filtered Noises, this means they'll fade to average value (0.0) when viewed from a distance 41 | to prevent noise caused by details smaller than pixel. Its worth pointing out that the 4D 42 | noise doesn't do filtering the fourth dimension, there is no point since you'll never render 43 | it as four dimensionsional pattern but choose some constant for the w paramater, basicly 44 | slicing the four dimensional noise into 3D space with using a plane. */ 45 | 46 | static float fnoise2D(float x, float y, float d); 47 | static float fnoise3D(float x, float y, float z, float d); 48 | static float fnoise4D(float x, float y, float z, float w, float d); 49 | 50 | static float fsnoise2D(float x, float y, float d); 51 | static float fsnoise3D(float x, float y, float z, float d); 52 | static float fsnoise4D(float x, float y, float z, float w, float d); 53 | 54 | private: 55 | static float grad( int hash, float x); 56 | static float grad( int hash, float x, float y ); 57 | static float grad( int hash, float x, float y , float z ); 58 | static float grad( int hash, float x, float y, float z, float t ); 59 | 60 | inline static float point(float x, int i); 61 | inline static float point(float x, float y, int i, int j); 62 | inline static float point(float x, float y, float z, int i, int j, int k); 63 | inline static float point(float x, float y, float z, float w, int i, int j, int k, int l); 64 | }; 65 | -------------------------------------------------------------------------------- /src/noise.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "Max.h" 21 | 22 | #include "texutil.h" 23 | 24 | #include "worley.h" 25 | #include "perlin.h" 26 | 27 | #include "commonMath.h" 28 | 29 | class NoiseParams { 30 | public: 31 | int noiseFunction; 32 | int fractalFunction; 33 | int worleyFunction; 34 | 35 | float phase; 36 | float spread; 37 | float F1, F2, F3, F4; 38 | 39 | float levels; 40 | float H; 41 | float lacunarity; 42 | float offset; 43 | float gain; 44 | 45 | float smoothWidth; 46 | 47 | float low, high; 48 | }; 49 | 50 | class WoodParam { // Wood parameters 51 | public: 52 | int woodType; 53 | float randSeed; 54 | int samples; 55 | 56 | float lowTresh; 57 | float highTresh; 58 | float skew; 59 | float widthVar; 60 | float gainVar; 61 | 62 | float trunkStr; 63 | float trunkFreq; 64 | 65 | float radialStr; 66 | float radialFreq; 67 | float radialZ; 68 | 69 | float angleStr; 70 | float angleFreq; 71 | float angleRad; 72 | }; 73 | 74 | class Noise { 75 | public: 76 | Noise() {} 77 | ~Noise() {} 78 | 79 | // The main noise function 80 | static float noise(Point3 p, NoiseParams& np); 81 | static float noise(Point3 p, float d, NoiseParams& np); 82 | 83 | // Wrapper for worley 84 | static float worleyWrapper(Point3 p, NoiseParams& np); 85 | 86 | // Wood function 87 | static float wood(Point3 p, Point3 &g, WoodParam& wp); 88 | static float wood(Point3 p, Point3 dPdx, Point3 dPdy, Point3 &g, WoodParam wp); // Filtered version 89 | 90 | // UVW 91 | static void alterUVW(Point3& p, int type); 92 | 93 | // Cell noise 94 | static float cellNoise(float x, float y, float z) { 95 | int xi = FASTFLOOR(x); 96 | int yi = FASTFLOOR(y); 97 | int zi = FASTFLOOR(z); 98 | unsigned int n = xi + yi*1301 + zi*314159; 99 | n ^= (n<<13); 100 | return ((float)(n*(n*n*15731 + 789221) + 1376312589) / 4294967296.0f); 101 | } 102 | 103 | static float limitedNoise(Point3 p, NoiseParams &np); 104 | static float limitedNoise(Point3 p, Point3 dpdx, Point3 dpdy, NoiseParams &np); 105 | }; 106 | 107 | -------------------------------------------------------------------------------- /src/curvectrl.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #include "curvectrl.h" 19 | 20 | 21 | void CurveCtrl::update(ICurveCtl *curve, HWND hParent, ReferenceMaker *resMaker) { 22 | curve->SetCustomParentWnd(hParent); 23 | // DebugPrint(_T("CCtrl UPDATED")); 24 | #if MAX_RELEASE >= 18900 25 | curve->RegisterResourceMaker(static_cast(resMaker)); 26 | #else 27 | curve->RegisterResourceMaker(static_cast(resMaker)); 28 | #endif 29 | BitArray ba = BitArray(1); 30 | ba.SetAll(); 31 | curve->SetDisplayMode(ba); 32 | curve->EnableDraw(TRUE); 33 | curve->SetActive(TRUE); 34 | curve->SetZoomValues(256.f, 128.f); 35 | curve->SetScrollValues(-16, -45); 36 | curve->Redraw(); 37 | } 38 | void CurveCtrl::disable(ICurveCtl *curve) { 39 | curve->SetActive(FALSE); 40 | curve->EnableDraw(FALSE); 41 | // DebugPrint(_T("CCtrl DISABLED")); 42 | } 43 | 44 | void CurveCtrl::init(ICurveCtl *curve) { 45 | curve->SetTitle(L"Function value curve"); 46 | // DebugPrint(_T("Curve initialized!")); 47 | 48 | // UI 49 | DWORD flags = CC_NONE; 50 | flags |= CC_DRAWBG; 51 | flags |= CC_DRAWGRID; 52 | flags |= CC_DRAWUTOOLBAR; 53 | flags |= 0; //CC_DRAWLTOOLBAR; 54 | flags |= CC_SHOWRESET; 55 | // flags |= 0; //CC_DRAWSCROLLBARS; 56 | // flags |= 0; //CC_AUTOSCROLL; 57 | flags |= CC_DRAWRULER; 58 | // flags |= 0; //CC_ASPOPUP; 59 | flags |= CC_CONSTRAIN_Y; 60 | flags |= CC_HIDE_DISABLED_CURVES; 61 | 62 | // RC Menu 63 | flags |= CC_RCMENU_MOVE_XY; 64 | flags |= CC_RCMENU_MOVE_X; 65 | flags |= CC_RCMENU_MOVE_Y; 66 | flags |= CC_RCMENU_SCALE; 67 | flags |= CC_RCMENU_INSERT_CORNER; 68 | flags |= CC_RCMENU_INSERT_BEZIER; 69 | flags |= CC_RCMENU_DELETE; 70 | 71 | curve->SetCCFlags(flags); 72 | 73 | // Range 74 | curve->SetXRange(0.0f,1.0f); 75 | curve->SetYRange(0.0f,1.0f); 76 | 77 | // Setup curve 78 | curve->SetNumCurves(1, TRUE); 79 | // DebugPrint(_T("Curve SetNumCurves")); 80 | ICurve *pCurve = curve->GetControlCurve(0); 81 | pCurve->SetNumPts(2); 82 | pCurve->SetPenProperty( RGB(0,0,0)); 83 | pCurve->SetDisabledPenProperty( RGB(128,128,128)); 84 | //TODO: Implement user option for LUT for 3.1 85 | //pCurve->SetLookupTableSize(4096); // curve is x+y: a 2D xform. RGBA @ 16-bits per channel. Allow 64^2 bits = 4096 for max precision. (seems to work) 86 | TimeValue t = 0; 87 | 88 | // Point 0 89 | CurvePoint pt = pCurve->GetPoint(t,0); 90 | pt.p.y = 0.f; 91 | pCurve->SetPoint(t,0,&pt); 92 | 93 | // Point 1 94 | pt = pCurve->GetPoint(t,1); 95 | pt.p.y = 1.f; 96 | pCurve->SetPoint(t,1,&pt); 97 | } -------------------------------------------------------------------------------- /src/DllEntry.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | //#define COMPILE_MULTIMAP 1 19 | 20 | #ifndef COMPILE_MULTIMAP 21 | 22 | #include "BerconWood.h" 23 | 24 | extern ClassDesc2* GetBerconNoiseDesc(); 25 | extern ClassDesc2* GetBerconWoodDesc(); 26 | extern ClassDesc2* GetBerconTileDesc(); 27 | extern ClassDesc2* GetBerconDistortionDesc(); 28 | extern ClassDesc2* GetBerconGradientDesc(); 29 | extern void InitGradientControls(); 30 | 31 | HINSTANCE hInstance; 32 | int controlsInit = FALSE; 33 | 34 | BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID /*lpvReserved*/) { 35 | if( fdwReason == DLL_PROCESS_ATTACH ) { 36 | hInstance = hinstDLL; 37 | DisableThreadLibraryCalls(hInstance); 38 | } 39 | 40 | if (!controlsInit) { 41 | controlsInit = TRUE; 42 | //InitCustomControls(hInstance); // Initialize MAX's custom controls 43 | InitCommonControls(); // Initialize Win95 controls [deprecated] 44 | InitGradientControls(); // Initialize my GradientRamp control 45 | } 46 | // DebugPrint(_T("Berconmaps is loaded!")); } 47 | return(TRUE); 48 | } 49 | 50 | __declspec( dllexport ) int LibNumberClasses() { 51 | return 5; 52 | } 53 | 54 | __declspec( dllexport ) ClassDesc* LibClassDesc(int i) { 55 | switch(i) { 56 | case 0: return GetBerconNoiseDesc(); 57 | case 1: return GetBerconWoodDesc(); 58 | case 2: return GetBerconTileDesc(); 59 | case 3: return GetBerconDistortionDesc(); 60 | case 4: return GetBerconGradientDesc(); 61 | default: return 0; 62 | } 63 | } 64 | 65 | #else 66 | 67 | #include "MultiMap.h" 68 | 69 | extern ClassDesc2* GetMultiMapDesc(); 70 | HINSTANCE hInstance; 71 | int controlsInit = FALSE; 72 | BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID /*lpvReserved*/) { 73 | if( fdwReason == DLL_PROCESS_ATTACH ) { 74 | hInstance = hinstDLL; 75 | DisableThreadLibraryCalls(hInstance); 76 | } 77 | return(TRUE); 78 | } 79 | 80 | __declspec( dllexport ) int LibNumberClasses() { 81 | return 1; 82 | } 83 | 84 | __declspec( dllexport ) ClassDesc* LibClassDesc(int i) { 85 | switch(i) { 86 | case 0: return GetMultiMapDesc(); 87 | default: return 0; 88 | } 89 | } 90 | 91 | #endif 92 | 93 | 94 | 95 | __declspec( dllexport ) const TCHAR* LibDescription() 96 | { 97 | return GetString(IDS_LIBDESCRIPTION); 98 | } 99 | 100 | __declspec( dllexport ) ULONG LibVersion() 101 | { 102 | return VERSION_3DSMAX; 103 | } 104 | 105 | __declspec( dllexport ) int LibInitialize(void) { 106 | return TRUE; 107 | } 108 | 109 | __declspec( dllexport ) int LibShutdown(void) { 110 | return TRUE; 111 | } 112 | 113 | -------------------------------------------------------------------------------- /src/GradientRamp.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | /* 19 | Gradient class 20 | 21 | Note that IGradient does NOT directly edit this class 22 | It reports UI actions to BerconGradient which then updates 23 | this to represent the changes done. 24 | */ 25 | 26 | #pragma once 27 | 28 | #include "GradientMap.h" 29 | #include "BerconNoise.h" 30 | 31 | class GradientRamp { 32 | private: 33 | static const int PADDING = 6; 34 | static const int ARROWS = 6; 35 | static const COLORREF ARROWDESEL = RGB(0,0,0); 36 | static const COLORREF ARROWSEL = RGB(255,255,255); 37 | 38 | HWND m_hWnd; 39 | GradientMap* parent; 40 | 41 | int width; 42 | int height; 43 | 44 | // Key information, always sorted by postion. From left to right (0..1) 45 | Texmap** subtex; 46 | float* position; 47 | AColor* color; 48 | int* number; 49 | 50 | int keys; 51 | 52 | bool keyMoved; 53 | 54 | public: 55 | int selected; // Key number, not index 56 | int interpolation; // 0 linear 1 smooth 2 solid near 3 solid left 4 solid right 57 | 58 | GradientRamp(GradientMap* p) { 59 | m_hWnd = NULL; 60 | parent = p; 61 | selected = 0; 62 | interpolation = 0; 63 | keys = 0; 64 | subtex = NULL; 65 | position = NULL; 66 | color = NULL; 67 | number = NULL; 68 | reset(); 69 | sort(); 70 | } 71 | 72 | ~GradientRamp() { 73 | delete[] subtex; 74 | delete[] position; 75 | delete[] color; 76 | delete[] number; 77 | } 78 | 79 | void setHWND(HWND hWnd); 80 | 81 | // Paint 82 | void paint(HDC hDC); 83 | void paintArrow(int px, int py, bool up, HDC hDC, COLORREF colR); 84 | void invalidate(); 85 | 86 | // Mouse methods 87 | int hit(int x, int y, bool broad = false); 88 | float toPos(int x); 89 | 90 | void leftDown(int x, int y, bool ctrl, bool shift, bool alt); 91 | void leftUp(int x, int y, bool ctrl, bool shift, bool alt); 92 | void dragging(int x, int y, bool ctrl, bool shift, bool alt); 93 | 94 | void popup(int x, int y, int sel); 95 | 96 | // Key methods 97 | int toIndex(int n); 98 | void selectKey(int n); 99 | //void moveKey(int n, float pos); 100 | void addKey(int n, float pos, AColor col, Texmap* sub = NULL); 101 | void reset(); 102 | //sort before we swap 103 | void sort(); //TODO: Figure out why it refuses to sort 104 | void swap(int a, int b); 105 | Texmap* getSubtex(int n = -1); 106 | void setSubtex(int n, Texmap* sub); 107 | void setSubtex(Texmap* sub); 108 | int numKeys() { return keys; } 109 | 110 | // Shading methods 111 | int findHighKey(float x); 112 | float interpolate(float x, float low, float high); 113 | AColor getColor(float x); // Required for preview 114 | AColor getColor(float x, ShadeContext& sc); // ShadeContext required for maps 115 | Point3 getBump(float x, Point3 normal, ShadeContext& sc); // ShadeContext required for maps 116 | }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | [Dd]ebug/ 11 | [Dd]ebugPublic/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | bld/ 16 | [Bb]in/ 17 | [Oo]bj/ 18 | 19 | # MSTest test Results 20 | [Tt]est[Rr]esult*/ 21 | [Bb]uild[Ll]og.* 22 | 23 | #NUNIT 24 | *.VisualState.xml 25 | TestResult.xml 26 | 27 | # Build Results of an ATL Project 28 | [Dd]ebugPS/ 29 | [Rr]eleasePS/ 30 | dlldata.c 31 | 32 | *_i.c 33 | *_p.c 34 | *_i.h 35 | *.ilk 36 | *.meta 37 | *.obj 38 | *.pch 39 | *.pdb 40 | *.pgc 41 | *.pgd 42 | *.rsp 43 | *.sbr 44 | *.tlb 45 | *.tli 46 | *.tlh 47 | *.tmp 48 | *.tmp_proj 49 | *.log 50 | *.vspscc 51 | *.vssscc 52 | .builds 53 | *.pidb 54 | *.svclog 55 | *.scc 56 | 57 | # Chutzpah Test files 58 | _Chutzpah* 59 | 60 | # Visual C++ cache files 61 | ipch/ 62 | *.aps 63 | *.ncb 64 | *.opensdf 65 | *.sdf 66 | *.cachefile 67 | 68 | # Visual Studio profiler 69 | *.psess 70 | *.vsp 71 | *.vspx 72 | 73 | # TFS 2012 Local Workspace 74 | $tf/ 75 | 76 | # Guidance Automation Toolkit 77 | *.gpState 78 | 79 | # ReSharper is a .NET coding add-in 80 | _ReSharper*/ 81 | *.[Rr]e[Ss]harper 82 | *.DotSettings.user 83 | 84 | # JustCode is a .NET coding addin-in 85 | .JustCode 86 | 87 | # TeamCity is a build add-in 88 | _TeamCity* 89 | 90 | # DotCover is a Code Coverage Tool 91 | *.dotCover 92 | 93 | # NCrunch 94 | *.ncrunch* 95 | _NCrunch_* 96 | .*crunch*.local.xml 97 | 98 | # MightyMoose 99 | *.mm.* 100 | AutoTest.Net/ 101 | 102 | # Web workbench (sass) 103 | .sass-cache/ 104 | 105 | # Installshield output folder 106 | [Ee]xpress/ 107 | 108 | # DocProject is a documentation generator add-in 109 | DocProject/buildhelp/ 110 | DocProject/Help/*.HxT 111 | DocProject/Help/*.HxC 112 | DocProject/Help/*.hhc 113 | DocProject/Help/*.hhk 114 | DocProject/Help/*.hhp 115 | DocProject/Help/Html2 116 | DocProject/Help/html 117 | 118 | # Click-Once directory 119 | publish/ 120 | 121 | # Publish Web Output 122 | *.[Pp]ublish.xml 123 | *.azurePubxml 124 | 125 | # NuGet Packages Directory 126 | packages/ 127 | ## TODO: If the tool you use requires repositories.config uncomment the next line 128 | #!packages/repositories.config 129 | 130 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 131 | # This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) 132 | !packages/build/ 133 | 134 | # Windows Azure Build Output 135 | csx/ 136 | *.build.csdef 137 | 138 | # Windows Store app package directory 139 | AppPackages/ 140 | 141 | # Others 142 | sql/ 143 | *.Cache 144 | ClientBin/ 145 | [Ss]tyle[Cc]op.* 146 | ~$* 147 | *~ 148 | *.dbmdl 149 | *.dbproj.schemaview 150 | *.pfx 151 | *.publishsettings 152 | node_modules/ 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | *.mdf 166 | *.ldf 167 | 168 | # Business Intelligence projects 169 | *.rdl.data 170 | *.bim.layout 171 | *.bim_*.settings 172 | 173 | # Microsoft Fakes 174 | FakesAssemblies/ 175 | src/.vs/ 176 | src/.vscode/ 177 | .vscode/ 178 | .vs/ 179 | tempforcompare/ 180 | *.asm 181 | *.cod 182 | *.sarif 183 | *.idb 184 | *.xml 185 | *.enc 186 | *.diagsession 187 | *.map 188 | src/Release_2024 189 | /src/ssecheck.cpp 190 | src/BerconDlg.h 191 | src/Release_2021/ 192 | src/Release_2022/ 193 | src/Release_2023/ 194 | src/DLL/BerconMaps_2024_64_debug.dlt 195 | 196 | -------------------------------------------------------------------------------- /src/fractal.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #include "noise.h" 19 | 20 | class Fractal { 21 | public: 22 | Fractal() {} 23 | ~Fractal() {} 24 | 25 | static float fractal(Point3 p, NoiseParams& np); 26 | static float turbulence(Point3 p, NoiseParams& np); 27 | static float fBm(Point3 p, NoiseParams& np); 28 | static float fBmTurb(Point3 p, NoiseParams& np); 29 | static float heteroTerrain(Point3 p, NoiseParams& np); 30 | static float hybridMultiFractal(Point3 p, NoiseParams& np); 31 | static float ridgedMultiFractal(Point3 p, NoiseParams& np); 32 | 33 | static float fractal(Point3 p, float d, NoiseParams& np); 34 | static float turbulence(Point3 p, float d, NoiseParams& np); 35 | static float fBm(Point3 p, float d, NoiseParams& np); 36 | static float fBmTurb(Point3 p, float d, NoiseParams& np); 37 | static float heteroTerrain(Point3 p, float d, NoiseParams& np); 38 | static float hybridMultiFractal(Point3 p, float d, NoiseParams& np); 39 | static float ridgedMultiFractal(Point3 p, float d, NoiseParams& np); 40 | 41 | static float marble(Point3 p, float d, NoiseParams& np); 42 | 43 | // Generic 44 | static float fBm(Point3 p, float levels, float lacunarity, float H); 45 | // Grain 46 | static float grain(Point3 p, float amount, float freq); 47 | 48 | static float f(Point3 p, NoiseParams &np) { 49 | switch (np.fractalFunction) { 50 | case 0: return (1.0f + Noise::noise(p, np)) * .5f; 51 | case 1: return fractal(p, np); 52 | case 2: return turbulence(p, np); 53 | case 3: return fBm(p, np); 54 | case 4: return fBmTurb(p, np); 55 | case 5: return heteroTerrain(p, np); 56 | case 6: return hybridMultiFractal(p, np); 57 | case 7: return ridgedMultiFractal(p, np); 58 | } 59 | return 0.f; 60 | } 61 | 62 | static float f(Point3 p, float d, NoiseParams &np) { 63 | switch (np.fractalFunction) { 64 | case 0: return (1.0f + Noise::noise(p, d, np)) * .5f; 65 | case 1: return fractal(p, d, np); 66 | case 2: return turbulence(p, d, np); 67 | case 3: return fBm(p, d, np); 68 | case 4: return fBmTurb(p, d, np); 69 | case 5: return heteroTerrain(p, np); 70 | case 6: return hybridMultiFractal(p, d, np); 71 | case 7: return ridgedMultiFractal(p, d, np); 72 | } 73 | return 0.f; 74 | } 75 | }; 76 | /* 77 | float BerconNoise::noise(Point3 p, Point3 dp, NoiseParams &np) { 78 | float res; 79 | switch (noiseF.type) { 80 | case 0: 81 | res = (1.0f + noiseF.noise(p, dp, np)) * .5f; 82 | break; 83 | case 1: 84 | res = Fractal::fractal(noiseF, p, dp, np); 85 | break; 86 | case 2: 87 | res = Fractal::turbulence(noiseF, p, dp, np); 88 | break; 89 | case 3: 90 | res = Fractal::fBm(noiseF, p, dp, np); 91 | break; 92 | case 4: 93 | res = Fractal::heteroTerrain(noiseF, p, dp, np); 94 | break; 95 | case 5: 96 | res = Fractal::hybridMultiFractal(noiseF, p, dp, np); 97 | break; 98 | case 6: 99 | res = Fractal::ridgedMultiFractal(noiseF, p, dp, np); 100 | break; 101 | case 7: 102 | res = Fractal::fBmTurb(noiseF, p, dp, np); 103 | break; 104 | default: res = 1.0f; 105 | } 106 | return res; 107 | } 108 | };*/ -------------------------------------------------------------------------------- /src/BerconDistortion.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "BerconCommon.h" 21 | 22 | extern TCHAR *GetString(int id); 23 | 24 | extern HINSTANCE hInstance; 25 | 26 | #define DIST_NSUBTEX 3 // Number of subtextures 27 | 28 | class BerconDistortion; 29 | 30 | class BerconDistortion : public Texmap { 31 | public: 32 | // Distortion 33 | BOOL useDistortion; 34 | float distortionStr; 35 | 36 | Point3 getDistVector(ShadeContext& sc); 37 | 38 | // Parameter block 39 | IParamBlock2 *pblock; //ref 0 40 | Texmap *subtex[DIST_NSUBTEX]; //array of sub-materials 41 | Interval ivalid; 42 | 43 | IParamBlock2 *pbXYZ; 44 | BerconXYZ berconXYZ; 45 | 46 | // Interactive Display 47 | TexHandle *texHandle; 48 | Interval texHandleValid; 49 | void DiscardTexHandle() { if (texHandle) { texHandle->DeleteThis(); texHandle = NULL; } } 50 | BOOL SupportTexDisplay() { return TRUE; } 51 | void ActivateTexDisplay(BOOL onoff) { if (!onoff) DiscardTexHandle(); } 52 | DWORD_PTR GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker); 53 | 54 | //From MtlBase 55 | ParamDlg* CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp); 56 | BOOL SetDlgThing(ParamDlg* dlg); 57 | void Update(TimeValue t, Interval& valid); 58 | void Reset(); 59 | Interval Validity(TimeValue t); 60 | ULONG LocalRequirements(int subMtlNum) { return berconXYZ.req(); } 61 | void MappingsRequired(int subMtlNum, BitArray& mapreq, BitArray& bumpreq) { berconXYZ.map(subMtlNum, mapreq, bumpreq); } 62 | 63 | //TODO: Return the number of sub-textures 64 | int NumSubTexmaps() { return DIST_NSUBTEX; } 65 | //TODO: Return the pointer to the 'i-th' sub-texmap 66 | Texmap* GetSubTexmap(int i) { return subtex[i]; } 67 | void SetSubTexmap(int i, Texmap *m); 68 | TSTR GetSubTexmapSlotName(ARG_LOCALIZED(int i)); 69 | 70 | //From Texmap 71 | RGBA EvalColor(ShadeContext& sc); 72 | float EvalMono(ShadeContext& sc); 73 | Point3 EvalNormalPerturb(ShadeContext& sc); 74 | 75 | //XYZGen *GetTheXYZGen() { return NULL; } 76 | 77 | //TODO: Return anim index to reference index 78 | int SubNumToRefNum(int subNum) { return subNum; } 79 | 80 | void ReadSXPData(TCHAR *name, void *sxpdata) { } 81 | 82 | //From Animatable 83 | Class_ID ClassID() {return BerconDistortion_CLASS_ID;} 84 | SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; } 85 | #if MAX_RELEASE < 23900 86 | void GetClassName(ARG_LOCALIZED(TSTR& s)) { s = GetString(IDS_BERCON_DIST); } 87 | #else 88 | void GetClassName(ARG_LOCALIZED(TSTR& s)) const override { s = GetString(IDS_BERCON_DIST); } //override for Slate editor 89 | #endif 90 | 91 | RefTargetHandle Clone( RemapDir &remap ); 92 | RefResult NotifyRefChanged(NOTIFY_REF_CHANGED_ARGS); 93 | 94 | int NumSubs() { return 2+DIST_NSUBTEX; } 95 | Animatable* SubAnim(int i); 96 | TSTR SubAnimName(ARG_LOCALIZED(int i)); 97 | 98 | // TODO: Maintain the number or references here 99 | int NumRefs() { return 5; } 100 | RefTargetHandle GetReference(int i); 101 | void SetReference(int i, RefTargetHandle rtarg); 102 | 103 | int NumParamBlocks() { return 2; } // return number of ParamBlocks in this instance 104 | IParamBlock2* GetParamBlock(int i) { return i ? pbXYZ : pblock; } // return i'th ParamBlock 105 | IParamBlock2* GetParamBlockByID(BlockID id) { return (pblock->ID() == id) ? pblock : pbXYZ; } // return id'd ParamBlock 106 | 107 | void DeleteThis() { delete this; } 108 | 109 | //Constructor/Destructor 110 | BerconDistortion(); 111 | ~BerconDistortion(); 112 | }; 113 | 114 | class BerconDistortionClassDesc : public ClassDesc2 { 115 | public: 116 | BerconDistortionClassDesc() {} 117 | virtual ~BerconDistortionClassDesc() {} 118 | virtual int IsPublic() { return TRUE; } 119 | virtual void* Create(BOOL /*loading = FALSE*/) { return new BerconDistortion(); } 120 | virtual SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; } 121 | virtual Class_ID ClassID() { return BerconDistortion_CLASS_ID; } 122 | virtual const TCHAR* Category() { return TEXMAP_CAT_3D; } 123 | 124 | virtual const TCHAR* InternalName() { return _T("BerconDistortion"); } // returns fixed parsable name (scripter-visible name) 125 | virtual HINSTANCE HInstance() { return hInstance; } // returns owning module handle 126 | LOCALIZED_CLASS_NAME(IDS_BERCON_DIST) 127 | }; 128 | -------------------------------------------------------------------------------- /src/tile.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #include "noise.h" 19 | #include 20 | #include 21 | #include 22 | 23 | #pragma once 24 | 25 | /* 26 | x_offset, height, a, b, c, d... / 27 | x_offset, height, a, b, c, d... / 28 | x_offset, height, a, b, c, d... / 29 | x_offset, height, a, b, c, d... / 30 | ... 31 | 32 | Strecher Bond: 33 | 0, 1, 1 / 34 | 0.5, 1, 1 35 | 36 | Auto scaling 37 | scale to fit 38 | scale to fit no stretch 39 | scale to tile size 40 | no scale 41 | 42 | random offset xy 43 | random scale xy (lock) 44 | rotation (random amount -+) (0..180) 45 | random flip x axis, random flip y axis 46 | 47 | randomize z coordinate (for MultiTexture etc.) 48 | 49 | map tile center to channel X 50 | 51 | 52 | 53 | */ 54 | 55 | class TileRow { 56 | public: 57 | TileRow(float offset) {this->offset = offset;} 58 | 59 | float offset; 60 | float totalWidth; 61 | std::vector tiles; 62 | 63 | void update() { 64 | totalWidth = 0.f; 65 | for (int i=0; i heights; 77 | std::vector rows; 78 | 79 | void setPattern(std::wstring s); 80 | 81 | void update() { 82 | totalHeight = 0.f; 83 | for (int i=0; i .5f) tileHeightVar = .5f; 136 | if (tileWidthVar > .5f) tileWidthVar = .5f; 137 | if (edgeHeightVar > 1.f) edgeHeightVar = 1.f; 138 | if (edgeWidthVar > 1.f) edgeWidthVar = 1.f; 139 | 140 | if (tilingType == 1) { // Herringbond can't have variation in these 141 | tileMaxHeight = tileWidth * .5f; 142 | tileMaxWidth = tileWidth; 143 | } else { 144 | tileMaxHeight = tileHeight * (1.f + tileHeightVar * 2.f); 145 | tileMaxWidth = tileWidth * (1.f + tileWidthVar * 2.f); 146 | } 147 | 148 | eW_var = edgeWidthVar > 0.0001f; 149 | eH_var = edgeHeightVar > 0.0001f; 150 | 151 | randScale = randSX > 0.0001f || randSY > 0.0001f; 152 | randOffset = randX > 0.0001f || randY > 0.0001f; 153 | } 154 | }; 155 | 156 | class TilePoint { // TilePoint class is used to define point in tiling texture 157 | public: 158 | 159 | Point3 center; // Tile center 160 | Point3 uvw; // UVW 161 | float d; // Shade, -1 == edge, 0..1 = tile 162 | int id; // ID for MultiTexture 163 | 164 | TilePoint() {d = -1.f;} 165 | TilePoint(float y) {d = y;} 166 | TilePoint(Point3 x) {uvw = x;} 167 | TilePoint(Point3 x, float y) {uvw = x; d = y;} 168 | //TilePoint(Point3 x, float y, Color z) {p = x; d = y; c = z;} 169 | //TilePoint(Color z) {c = z; d = -3.f; } 170 | }; 171 | 172 | class Tile { 173 | private: 174 | // Helpers 175 | static float edgeBlur(float d, float r, int type); 176 | static TilePoint corner(float rX, float rY, float w, float h, TileParam& t); 177 | static void rotatePoint2(Point3& d, float angle); 178 | static void rotateUV(int rotUV, float var, Point3& d); 179 | 180 | static void uvMapping(TilePoint& tp, Point3 p, float edges[4], TileParam& t, int dir=0); 181 | static TilePoint drawTile(Point3 p, float edges[4], TileParam& t, int id=0, int dir=0); 182 | 183 | // Patterns 184 | static TilePoint pat_xBond(Point3 p, TileParam& t); 185 | static TilePoint pat_herring(Point3 p, TileParam& t); 186 | 187 | public: 188 | 189 | static TilePoint draw(Point3 p, TileParam& t); 190 | 191 | }; 192 | 193 | -------------------------------------------------------------------------------- /src/worley.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | // Implementation of Steven Worley's cellular noise 19 | 20 | #include 21 | #include "worley.h" 22 | 23 | static char Poisson_count[256]= { 24 | 4,3,1,1,1,2,4,2,2,2,5,1,0,2,1,2,2,0,4,3,2,1,2,1,3,2,2,4,2,2,5,1,2,3,2,2,2,2,2,3, 25 | 2,4,2,5,3,2,2,2,5,3,3,5,2,1,3,3,4,4,2,3,0,4,2,2,2,1,3,2,2,2,3,3,3,1,2,0,2,1,1,2, 26 | 2,2,2,5,3,2,3,2,3,2,2,1,0,2,1,1,2,1,2,2,1,3,4,2,2,2,5,4,2,4,2,2,5,4,3,2,2,5,4,3, 27 | 3,3,5,2,2,2,2,2,3,1,1,4,2,1,3,3,4,3,2,4,3,3,3,4,5,1,4,2,4,3,1,2,3,5,3,2,1,3,1,3, 28 | 3,3,2,3,1,5,5,4,2,2,4,1,3,4,1,5,3,3,5,3,4,3,2,2,1,1,1,1,1,2,4,5,4,5,4,2,1,5,1,1, 29 | 2,3,3,3,2,5,2,3,3,2,0,2,1,1,4,2,1,3,2,1,2,2,3,2,5,5,3,4,5,5,2,4,4,5,3,2,2,2,1,4, 30 | 2,3,3,4,2,5,4,2,4,2,2,2,4,5,3,2}; 31 | 32 | #define DENSITY_ADJUSTMENT 0.398150 33 | #define FASTFLOORL(x) ((x)<0 ? ((long)x-1) : ((long)x) ) 34 | #define ADD(a,b,c) ( add(int_at[0]+a, int_at[1]+b, int_at[2]+c, new_at, order, F, function) ) 35 | 36 | void Worley::noise(double at[3], int order, double *F, int function) { 37 | double x2, y2, z2, mx2, my2, mz2; 38 | double new_at[3]; 39 | long int_at[3]; 40 | 41 | for (int i=0; i>24]; 105 | ROLL(seed); 106 | 107 | for (int j=0; jy)?x:y; 136 | d = ((z>t)?z:t); 137 | break; } 138 | case 4: // Minkovsky 0.5 139 | d = sqrt(fabs(d3[0])) + sqrt(fabs(d3[1])) + sqrt(fabs(d3[2])); 140 | d *= d; 141 | break; 142 | case 5: {// Minkovsky 4 143 | double x = d3[0]*d3[0]; 144 | double y = d3[1]*d3[1]; 145 | double z = d3[2]*d3[2]; 146 | d = sqrt(sqrt(x*x + y*y + z*z)); 147 | break; } 148 | } 149 | 150 | if (d < F[order-1]) { 151 | int index = order; 152 | while (index > 0 && d < F[index-1]) index--; 153 | for (int i=order-2; i>=index; i--) 154 | F[i+1] = F[i]; 155 | F[index] = d; 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/BerconTile.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "BerconCommon.h" 21 | #include "tile.h" 22 | 23 | extern TCHAR *GetString(int id); 24 | 25 | extern HINSTANCE hInstance; 26 | 27 | #define TILE_NSUBTEX 7 // Number of subtextures 28 | 29 | class BerconTile; 30 | 31 | class BerconTile : public Texmap, public ResourceMakerCallback { 32 | public: 33 | // Tiling parameters 34 | float tileSize; 35 | 36 | TileParam tileParam; 37 | int lockEdge, uvChan, uvChan2; 38 | 39 | TilePattern pattern; 40 | 41 | // Tiling 42 | bool mappedParameters; 43 | TileParam EvalParameters(ShadeContext& sc); 44 | 45 | // Distortion 46 | BOOL useDistortion; 47 | float distortionStr; 48 | Point3 getDistVector(ShadeContext& sc); 49 | 50 | // User Interface 51 | void EnableStuff(TimeValue t); 52 | 53 | // Parameter block 54 | IParamBlock2 *pblock; //ref 1 55 | IParamBlock2 *pbMap; //ref PBMAP_REF 56 | IParamBlock2 *pbXYZ; //ref COORDS 57 | 58 | BerconXYZ berconXYZ; 59 | 60 | Color col[3]; 61 | Texmap *subtex[TILE_NSUBTEX]; //array of sub-materials 62 | BOOL mapOn[TILE_NSUBTEX]; 63 | static ParamDlg* texoutDlg; 64 | TextureOutput *texout; 65 | Interval ivalid; 66 | //bool viewportPreview; 67 | // fixed compiler error 4596 68 | inline AColor getColor(ShadeContext &sc, int i) { return mapOn[i]&&subtex[i] ? subtex[i]->EvalColor(sc): col[i]; } 69 | inline float getFloat(ShadeContext &sc, int i) { return mapOn[i]&&subtex[i] ? subtex[i]->EvalMono(sc): Intens(col[i]); } 70 | inline Point3 getNormal(ShadeContext &sc, int i) { return mapOn[i]&&subtex[i] ? subtex[i]->EvalNormalPerturb(sc): Point3(0,0,0); } 71 | 72 | // Methods for interactive display 73 | TexHandle *texHandle; 74 | Interval texHandleValid; 75 | void DiscardTexHandle() { if (texHandle) { texHandle->DeleteThis(); texHandle = NULL; } } 76 | BOOL SupportTexDisplay() { return TRUE; } 77 | void ActivateTexDisplay(BOOL onoff) { if (!onoff) DiscardTexHandle(); } 78 | DWORD_PTR GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker); 79 | 80 | //From MtlBase 81 | ParamDlg* CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp); 82 | BOOL SetDlgThing(ParamDlg* dlg); 83 | void Update(TimeValue t, Interval& valid); 84 | void Reset(); 85 | Interval Validity(TimeValue t); 86 | ULONG LocalRequirements(int subMtlNum) { return berconXYZ.req(); } 87 | void MappingsRequired(int subMtlNum, BitArray& mapreq, BitArray& bumpreq) { berconXYZ.map(subMtlNum, mapreq, bumpreq); } 88 | 89 | int NumSubTexmaps() { return TILE_NSUBTEX; } 90 | Texmap* GetSubTexmap(int i) { return subtex[i]; } 91 | void SetSubTexmap(int i, Texmap *m); 92 | TSTR GetSubTexmapSlotName(ARG_LOCALIZED(int i)); 93 | 94 | //From Texmap 95 | RGBA EvalColor(ShadeContext& sc); 96 | float EvalMono(ShadeContext& sc); 97 | Point3 EvalNormalPerturb(ShadeContext& sc); 98 | 99 | int SubNumToRefNum(int subNum) { return subNum; } 100 | 101 | void ReadSXPData(TCHAR *name, void *sxpdata) { } 102 | 103 | //From Animatable 104 | Class_ID ClassID() {return BerconTile_CLASS_ID;} 105 | SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; } 106 | #if MAX_RELEASE < 23900 107 | void GetClassName(ARG_LOCALIZED(TSTR& s)) {s = GetString(IDS_BERCON_TILE);} //override for Slate editor 108 | #else 109 | void GetClassName(ARG_LOCALIZED(TSTR& s)) const override { s = GetString(IDS_BERCON_TILE); } //override for Slate editor 110 | #endif 111 | 112 | RefTargetHandle Clone( RemapDir &remap ); 113 | RefResult NotifyRefChanged(NOTIFY_REF_CHANGED_ARGS); 114 | 115 | int NumSubs() { return 11; } 116 | Animatable* SubAnim(int i); 117 | TSTR SubAnimName(ARG_LOCALIZED(int i)); 118 | 119 | int NumRefs() { return 11; } 120 | RefTargetHandle GetReference(int i); 121 | void SetReference(int i, RefTargetHandle rtarg); 122 | 123 | int NumParamBlocks() { return 3; } // return number of ParamBlocks in this instance 124 | IParamBlock2* GetParamBlock(int i) { switch (i) { case 0: return pblock; case 1: return pbMap; case 2: return pbXYZ; } return NULL; } 125 | IParamBlock2* GetParamBlockByID(BlockID id) { 126 | if (pblock->ID() == id) return pblock; 127 | if (pbMap->ID() == id) return pbMap; 128 | if (pbXYZ->ID() == id) return pbXYZ; 129 | return NULL; 130 | } 131 | void DeleteThis() { delete this; } 132 | 133 | //Constructor/Destructor 134 | BerconTile(); 135 | ~BerconTile(); 136 | 137 | void* GetInterface(ULONG id) { 138 | if(id == I_RESMAKER_INTERFACE) 139 | return (void *) (ResourceMakerCallback*) this; 140 | else 141 | return Texmap::GetInterface(id); 142 | } 143 | }; 144 | 145 | class BerconTileClassDesc : public ClassDesc2 { 146 | public: 147 | BerconTileClassDesc() {} 148 | virtual ~BerconTileClassDesc() {} 149 | virtual int IsPublic() { return TRUE; } 150 | virtual void* Create(BOOL /*loading = FALSE*/) { return new BerconTile(); } 151 | virtual SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; } 152 | virtual Class_ID ClassID() { return BerconTile_CLASS_ID; } 153 | virtual const TCHAR* Category() { return TEXMAP_CAT_3D; } 154 | virtual const TCHAR* InternalName() { return _T("BerconTile"); } // returns fixed parsable name (scripter-visible name) 155 | virtual HINSTANCE HInstance() { return hInstance; } 156 | LOCALIZED_CLASS_NAME(IDS_BERCON_TILE) 157 | }; 158 | -------------------------------------------------------------------------------- /src/IGradient.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #include "IGradient.h" 19 | 20 | /* 21 | mouse input 22 | 23 | * MK_LBUTTON - left 24 | * MK_MBUTTON - middle 25 | * MK_RBUTTON - right 26 | * MK_CONTROL - Ctrl pressed 27 | * MK_SHIFT - shift pressed 28 | 29 | To detect that the ALT key was pressed, check whether GetKeyState(VK_MENU) < 0. Note, this must not be GetAsyncKeyState. 30 | 31 | int mouse_x = (int)LOWORD(lparam); 32 | int mouse_y = (int)HIWORD(lparam); 33 | // get the button state 34 | int buttons = (int)wparam; 35 | sprintf(buffer,"Right Button = %d ",((buttons & MK_RBUTTON) ? 1 : 0)); 36 | 37 | */ 38 | 39 | LRESULT CALLBACK IGradient::GradientProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { 40 | IGradient *grad = DLGetWindowLongPtr(hWnd); 41 | if(grad == NULL && msg != WM_CREATE) 42 | return DefWindowProc(hWnd, msg, wParam, lParam); 43 | 44 | switch(msg) { 45 | case WM_CREATE: { 46 | LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam; 47 | grad = (IGradient*)lpcs->lpCreateParams; 48 | DLSetWindowLongPtr(hWnd, grad); 49 | break; 50 | } 51 | /* 52 | case WM_KILLFOCUS: 53 | if (ctrl->m_bMouseOver) { 54 | ctrl->m_bMouseOver = false; 55 | ctrl->run_event_handler(n_mouseout, (short)LOWORD(lParam), (short)HIWORD(lParam), wParam, false); 56 | } 57 | break; 58 | */ 59 | case WM_MOUSEMOVE: { 60 | int buttons = (int)wParam; 61 | if (buttons & MK_LBUTTON) { 62 | int mouse_x = (int)LOWORD(lParam); 63 | int mouse_y = (int)HIWORD(lParam); 64 | grad->gradient->dragging(mouse_x, mouse_y, buttons&MK_CONTROL, buttons&MK_SHIFT, GetKeyState(VK_MENU) < 0); 65 | //CharStream *out = thread_local(current_stdout); 66 | //out->printf("Dragging %d %d\n", mouse_x, mouse_y); 67 | } 68 | break; 69 | } 70 | 71 | case WM_LBUTTONDOWN: { 72 | CharStream *out = thread_local(current_stdout); 73 | 74 | int buttons = (int)wParam; 75 | int mouse_x = (int)LOWORD(lParam); 76 | int mouse_y = (int)HIWORD(lParam); 77 | 78 | grad->gradient->leftDown(mouse_x, mouse_y, buttons&MK_CONTROL, buttons&MK_SHIFT, GetKeyState(VK_MENU) < 0); 79 | 80 | /* 81 | if (buttons & MK_CONTROL) { 82 | out->printf("Left mouse DOWN + control\n"); 83 | } else if (buttons & MK_SHIFT) { 84 | out->printf("Left mouse DOWN + shift\n"); 85 | } else { 86 | out->printf("Left mouse DOWN %d %d\n", mouse_x, mouse_y); 87 | }*/ 88 | 89 | break; 90 | } 91 | 92 | case WM_LBUTTONUP: { 93 | CharStream *out = thread_local(current_stdout); 94 | 95 | int buttons = (int)wParam; 96 | int mouse_x = (int)LOWORD(lParam); 97 | int mouse_y = (int)HIWORD(lParam); 98 | grad->gradient->leftUp(mouse_x, mouse_y, buttons&MK_CONTROL, buttons&MK_SHIFT, GetKeyState(VK_MENU) < 0); 99 | 100 | /* 101 | if (buttons & MK_CONTROL) { 102 | out->printf("Left mouse + control\n"); 103 | } else if (buttons & MK_SHIFT) { 104 | out->printf("Left mouse + shift\n"); 105 | } else { 106 | out->printf("Left mouse\n"); 107 | } */ 108 | break; 109 | } 110 | 111 | case WM_RBUTTONUP: { 112 | HMENU Popup; 113 | POINT pt; 114 | Popup = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_GRADIENTMENU)); 115 | Popup = GetSubMenu(Popup, 0); 116 | GetCursorPos(&pt); 117 | int sel = TrackPopupMenuEx(Popup, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, hWnd, NULL); 118 | if (sel > 0) { 119 | int mouse_x = (int)LOWORD(lParam); 120 | int mouse_y = (int)HIWORD(lParam); 121 | grad->gradient->popup(mouse_x, mouse_y, sel); 122 | } 123 | break; 124 | } 125 | 126 | case WM_MBUTTONUP: { 127 | /* 128 | CharStream *out = thread_local(current_stdout); 129 | 130 | int buttons = (int)wParam; 131 | if (buttons & MK_CONTROL) { 132 | out->printf("Middle mouse + control\n"); 133 | } else if (buttons & MK_SHIFT) { 134 | out->printf("Middle mouse + shift\n"); 135 | } else { 136 | out->printf("Middle mouse\n"); 137 | } */ 138 | break; 139 | } 140 | 141 | /* 142 | case WM_LBUTTONUP: 143 | return ctrl->ButtonUp((short)LOWORD(lParam), (short)HIWORD(lParam), wParam, left); 144 | 145 | case WM_LBUTTONDBLCLK: 146 | return ctrl->ButtonDblClk((short)LOWORD(lParam), (short)HIWORD(lParam), wParam, left); 147 | 148 | case WM_RBUTTONDOWN: 149 | return ctrl->ButtonDown((short)LOWORD(lParam), (short)HIWORD(lParam), wParam, right); 150 | 151 | case WM_RBUTTONUP: 152 | return ctrl->ButtonUp((short)LOWORD(lParam), (short)HIWORD(lParam), wParam, right); 153 | 154 | case WM_RBUTTONDBLCLK: 155 | return ctrl->ButtonDblClk((short)LOWORD(lParam), (short)HIWORD(lParam), wParam, right); 156 | 157 | case WM_MBUTTONDOWN: 158 | return ctrl->ButtonDown((short)LOWORD(lParam), (short)HIWORD(lParam), wParam, middle); 159 | 160 | case WM_MBUTTONUP: 161 | return ctrl->ButtonUp((short)LOWORD(lParam), (short)HIWORD(lParam), wParam, middle); 162 | 163 | case WM_MBUTTONDBLCLK: 164 | return ctrl->ButtonDblClk((short)LOWORD(lParam), (short)HIWORD(lParam), wParam, middle); 165 | 166 | case WM_ERASEBKGND: 167 | return ctrl->EraseBkgnd((HDC)wParam); 168 | 169 | */ 170 | case WM_PAINT: { 171 | //CharStream *out = thread_local(current_stdout); 172 | //out->printf("!!Paint!!\n"); 173 | PAINTSTRUCT ps; 174 | BeginPaint(hWnd,&ps); 175 | grad->gradient->paint(ps.hdc); 176 | EndPaint(hWnd,&ps); 177 | return FALSE; 178 | } 179 | default: 180 | return DefWindowProc(hWnd, msg, wParam, lParam); 181 | } 182 | return FALSE; 183 | } 184 | 185 | void InitGradientControls() { 186 | WNDCLASSEX wc; 187 | wc.cbClsExtra = 0; 188 | wc.cbWndExtra = 0; 189 | wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); 190 | wc.hCursor = LoadCursor(NULL, /*IDC_CROSS*/IDC_ARROW); 191 | wc.hIcon = NULL; 192 | wc.hIconSm = NULL; 193 | wc.hInstance = hInstance; 194 | wc.lpfnWndProc = IGradient::GradientProc; //DlgProc control 195 | wc.lpszClassName = L"CustGradient"; 196 | wc.lpszMenuName = NULL; 197 | wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; 198 | wc.cbSize = sizeof(wc); 199 | RegisterClassEx(&wc); 200 | } 201 | -------------------------------------------------------------------------------- /src/BerconNoise.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {43067d0a-0e6f-4679-83b2-7a5b5fb21603} 6 | cpp;c;cxx;rc;def;r;odl;idl;hpj;bat 7 | 8 | 9 | {4971b58f-2900-4764-865b-561d35c7409a} 10 | 11 | 12 | {db93fbce-443f-45a7-8184-65c8eed4182a} 13 | 14 | 15 | {dc7a81ea-e5ca-446c-94da-34fe8824490b} 16 | 17 | 18 | {82fc4a5a-c3d4-45ac-803b-d459667eb4e6} 19 | 20 | 21 | {3a83a3f3-71e8-4f57-890e-0f46e6724ede} 22 | 23 | 24 | {d3a384ab-d0d5-4b7a-a8cc-7241b062b9dc} 25 | h;hpp;hxx;hm;inl 26 | 27 | 28 | {ee43c05d-259d-4f09-9ff5-1d262fcb0779} 29 | 30 | 31 | {f3d73eff-61be-4c8f-9e6c-c84e1660efcd} 32 | 33 | 34 | {bfe95d02-e91e-40a3-a0f3-4f4864626228} 35 | 36 | 37 | {1d9a5287-0d3c-4b7d-beca-15e9f20eb325} 38 | 39 | 40 | {53c9e9ad-0ae7-4739-bdf6-25a1e5401e51} 41 | 42 | 43 | {680604e9-378e-42b9-896f-596580a2bca7} 44 | ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe 45 | 46 | 47 | 48 | 49 | Source Files 50 | 51 | 52 | Resource Files 53 | 54 | 55 | 56 | 57 | Source Files\Main 58 | 59 | 60 | Source Files\Main 61 | 62 | 63 | Source Files\Main 64 | 65 | 66 | Source Files\Main 67 | 68 | 69 | Source Files\Main 70 | 71 | 72 | Source Files\Main 73 | 74 | 75 | Source Files\Gradient 76 | 77 | 78 | Source Files\Gradient 79 | 80 | 81 | Source Files\Curve 82 | 83 | 84 | Source Files\Patterns 85 | 86 | 87 | Source Files\Patterns 88 | 89 | 90 | Source Files\Patterns 91 | 92 | 93 | Source Files\Patterns 94 | 95 | 96 | Source Files\Patterns 97 | 98 | 99 | Source Files\Misc 100 | 101 | 102 | Source Files\Misc 103 | 104 | 105 | 106 | 107 | Header Files\Main 108 | 109 | 110 | Header Files\Main 111 | 112 | 113 | Header Files\Main 114 | 115 | 116 | Header Files\Main 117 | 118 | 119 | Header Files\Main 120 | 121 | 122 | Header Files\Main 123 | 124 | 125 | Header Files\Patterns 126 | 127 | 128 | Header Files\Patterns 129 | 130 | 131 | Header Files\Patterns 132 | 133 | 134 | Header Files\Patterns 135 | 136 | 137 | Header Files\Patterns 138 | 139 | 140 | Header Files\Gradient 141 | 142 | 143 | Header Files\Gradient 144 | 145 | 146 | Header Files\Gradient 147 | 148 | 149 | Header Files\Curve 150 | 151 | 152 | Header Files\Misc 153 | 154 | 155 | Header Files\Misc 156 | 157 | 158 | Header Files\Misc 159 | 160 | 161 | Header Files 162 | 163 | 164 | 165 | 166 | Resource Files 167 | 168 | 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /src/BerconWood.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "BerconCommon.h" 21 | 22 | extern TCHAR *GetString(int id); 23 | 24 | extern HINSTANCE hInstance; 25 | 26 | #define WOOD_NSUBTEX = 21 27 | 28 | class BerconWood : public Texmap, public ResourceMakerCallback { 29 | private: 30 | static const int NSUBTEX = 21; 31 | static const int NCOLS = 3; 32 | static const int NUMREF = 27; 33 | 34 | public: 35 | BOOL useCurve, useDistortion, lockGrain; 36 | float woodSize; 37 | float grainAmount, grainFreq; 38 | 39 | int woodType; 40 | float randSeed; 41 | int samples; 42 | 43 | float lowTresh; 44 | float highTresh; 45 | float skew; 46 | float widthVar; 47 | float gainVar; 48 | 49 | float trunkStr; 50 | float trunkFreq; 51 | 52 | float radialStr; 53 | float radialFreq; 54 | float radialZ; 55 | 56 | float angleStr; 57 | float angleFreq; 58 | float angleRad; 59 | 60 | // Distortion 61 | float distortionStr; 62 | void applyDistortion(ShadeContext& sc, Point3& p); 63 | 64 | // User Interface 65 | void EnableStuff(); 66 | 67 | BerconXYZ berconXYZ; 68 | 69 | // Parameter block 70 | IParamBlock2 *pbXYZ; //ref 0 71 | IParamBlock2 *pblock; //ref 1 72 | IParamBlock2 *pbCurve; //ref CURVEPB_REF 73 | IParamBlock2 *pbMap; //ref PBMAP_REF 74 | 75 | Color col[NCOLS]; 76 | Texmap *subtex[NSUBTEX]; //array of sub-materials 77 | BOOL mapOn[NSUBTEX]; 78 | 79 | static ParamDlg* texoutDlg; 80 | TextureOutput *texout; 81 | Interval ivalid; 82 | 83 | bool mappedParameters; 84 | WoodParam EvalParameters(ShadeContext& sc); 85 | 86 | // Curve 87 | ICurveCtl* curve; 88 | // From ResourceMakerCallback 89 | BOOL SetCustomImageList(HIMAGELIST &hCTools,ICurveCtl *pCCtl) { return TRUE; }; 90 | BOOL GetToolTip(int iButton, TSTR &ToolTip,ICurveCtl *pCCtl) { return TRUE; }; 91 | void ResetCallback(int curvenum, ICurveCtl *pCCtl) { ICurve *pCurve = NULL; pCurve = pCCtl->GetControlCurve(curvenum); if(pCurve) { pCurve->SetNumPts(2); NewCurveCreatedCallback(curvenum, pCCtl); }} 92 | void NewCurveCreatedCallback(int curvenum, ICurveCtl *pCCtl) { 93 | ICurve *pCurve = NULL; pCurve = pCCtl->GetControlCurve(curvenum); TimeValue t = GetCOREInterface()->GetTime(); 94 | CurvePoint pt = pCurve->GetPoint(t,0); pt.p.y = 0.f; pCurve->SetPoint(t,0,&pt); 95 | pCurve->SetPenProperty( RGB(0,0,0)); pCurve->SetDisabledPenProperty( RGB(128,128,128)); 96 | pt = pCurve->GetPoint(t,1); pt.p.y = 1.f; pCurve->SetPoint(t,1,&pt); 97 | } 98 | 99 | // Interactive Display 100 | TexHandle *texHandle; 101 | Interval texHandleValid; 102 | void DiscardTexHandle() { if (texHandle) { texHandle->DeleteThis(); texHandle = NULL; } } 103 | BOOL SupportTexDisplay() { return TRUE; } 104 | void ActivateTexDisplay(BOOL onoff) { if (!onoff) DiscardTexHandle(); } 105 | DWORD_PTR GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker); 106 | 107 | //From MtlBase 108 | ParamDlg* CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp); 109 | BOOL SetDlgThing(ParamDlg* dlg); 110 | void Update(TimeValue t, Interval& valid); 111 | void Reset(); 112 | Interval Validity(TimeValue t); 113 | ULONG LocalRequirements(int subMtlNum) { return berconXYZ.req(); } 114 | void MappingsRequired(int subMtlNum, BitArray& mapreq, BitArray& bumpreq) { berconXYZ.map(subMtlNum, mapreq, bumpreq); } 115 | 116 | int NumSubTexmaps() { return NSUBTEX; } 117 | Texmap* GetSubTexmap(int i) { return subtex[i]; } 118 | void SetSubTexmap(int i, Texmap *m); 119 | TSTR GetSubTexmapSlotName(ARG_LOCALIZED(int i)); 120 | 121 | //From Texmap 122 | RGBA EvalColor(ShadeContext& sc); 123 | float EvalMono(ShadeContext& sc); 124 | Point3 EvalNormalPerturb(ShadeContext& sc); 125 | 126 | int SubNumToRefNum(int subNum) { return subNum; } 127 | 128 | void ReadSXPData(TCHAR *name, void *sxpdata) { } 129 | 130 | //From Animatable 131 | Class_ID ClassID() {return BerconWood_CLASS_ID;} 132 | SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; } 133 | #if MAX_RELEASE < 23900 134 | void GetClassName(ARG_LOCALIZED(TSTR& s)) { s = GetString(IDS_BERCON_WOOD); } 135 | #else 136 | void GetClassName(ARG_LOCALIZED(TSTR& s)) const override { s = GetString(IDS_BERCON_WOOD); } //override for Slate editor 137 | #endif 138 | 139 | RefTargetHandle Clone( RemapDir &remap ); 140 | RefResult NotifyRefChanged(NOTIFY_REF_CHANGED_ARGS); 141 | 142 | int NumSubs() { return NUMREF; } 143 | Animatable* SubAnim(int i); 144 | TSTR SubAnimName(ARG_LOCALIZED(int i)); 145 | 146 | int NumRefs() { return NUMREF; } 147 | RefTargetHandle GetReference(int i); 148 | void SetReference(int i, RefTargetHandle rtarg); 149 | 150 | int NumParamBlocks() { return 4; } 151 | IParamBlock2* GetParamBlock(int i) { switch (i) { case 0: return pblock; case 1: return pbCurve; case 2: return pbMap; case 3: return pbXYZ; } return NULL; } 152 | IParamBlock2* GetParamBlockByID(BlockID id) { 153 | if (pblock->ID() == id) return pblock; 154 | if (pbCurve->ID() == id) return pbCurve; 155 | if (pbMap->ID() == id) return pbMap; 156 | if (pbXYZ->ID() == id) return pbXYZ; 157 | return NULL; 158 | } 159 | 160 | void DeleteThis() { delete this; } 161 | 162 | //Constructor/Destructor 163 | BerconWood(); 164 | ~BerconWood(); 165 | 166 | void* GetInterface(ULONG id) { 167 | if(id == I_RESMAKER_INTERFACE) 168 | return (void *) (ResourceMakerCallback*) this; 169 | else 170 | return Texmap::GetInterface(id); 171 | } 172 | }; 173 | 174 | class BerconWoodClassDesc : public ClassDesc2 { 175 | public: 176 | virtual int IsPublic() { return TRUE; } 177 | virtual void* Create(BOOL /*loading = FALSE*/) { return new BerconWood(); } 178 | virtual SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; } 179 | virtual Class_ID ClassID() { return BerconWood_CLASS_ID; } 180 | virtual const TCHAR* Category() { return TEXMAP_CAT_3D; } 181 | virtual const TCHAR* InternalName() { return _T("BerconWood"); } // returns fixed parsable name (scripter-visible name) 182 | virtual HINSTANCE HInstance() { return hInstance; } 183 | LOCALIZED_CLASS_NAME(IDS_BERCON_WOOD) 184 | }; 185 | -------------------------------------------------------------------------------- /src/BerconNoise.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | /* 19 | This is the general include file, used by all maps. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include "BerconCommon.h" 25 | 26 | extern TCHAR *GetString(int id); 27 | 28 | extern HINSTANCE hInstance; 29 | 30 | 31 | #define NOISE_NSUBTEX 18 // Number of subtextures 32 | 33 | class BerconNoise; 34 | 35 | class BerconNoise : public Texmap, public ResourceMakerCallback/*, public imrShaderTranslation*/ { 36 | public: 37 | bool mappedParameters; 38 | NoiseParams EvalParameters(ShadeContext* sc); 39 | 40 | //void limitLevel(Point3 dp, NoiseParams &np, float nSize); 41 | 42 | //void calcAverage(); 43 | //float average; 44 | 45 | // Noise variables 46 | float size; 47 | float phase; 48 | float spread; 49 | float F1, F2, F3, F4; 50 | 51 | int noiseFunction; 52 | int worleyFunction; 53 | int fractalFunction; 54 | 55 | // Fractal variables 56 | float levels; 57 | float low, high; 58 | float fractalH, fractalOffset, fractalGain, fractalLacunarity; 59 | 60 | // Distortion 61 | BOOL useDistortion; 62 | float distortionStr; 63 | void applyDistortion(ShadeContext& sc, Point3& p); 64 | int uvwDist; 65 | 66 | // User Interface 67 | void EnableStuff(); 68 | 69 | // Parameter block 70 | IParamBlock2 *pbXYZ; 71 | IParamBlock2 *pblock; //ref 0 72 | IParamBlock2 *pbCurve; //ref CURVEPB_REF 73 | IParamBlock2 *pbMap; //ref PBMAP_REF 74 | 75 | BerconXYZ berconXYZ; 76 | 77 | Color col[2]; 78 | Texmap *subtex[NOISE_NSUBTEX]; //array of sub-materials 79 | BOOL mapOn[NOISE_NSUBTEX]; 80 | static ParamDlg* texoutDlg; 81 | TextureOutput *texout; 82 | Interval ivalid; 83 | 84 | // Curve 85 | ICurveCtl* curve; 86 | BOOL useCurve; 87 | // From ResourceMakerCallback 88 | BOOL SetCustomImageList(HIMAGELIST &hCTools,ICurveCtl *pCCtl) { return TRUE; }; 89 | BOOL GetToolTip(int iButton, TSTR &ToolTip,ICurveCtl *pCCtl) { return TRUE; }; 90 | void ResetCallback(int curvenum, ICurveCtl *pCCtl) { ICurve *pCurve = NULL; pCurve = pCCtl->GetControlCurve(curvenum); if(pCurve) { pCurve->SetNumPts(2); NewCurveCreatedCallback(curvenum, pCCtl); }} 91 | void NewCurveCreatedCallback(int curvenum, ICurveCtl *pCCtl) { 92 | ICurve *pCurve = NULL; pCurve = pCCtl->GetControlCurve(curvenum); TimeValue t = GetCOREInterface()->GetTime(); 93 | CurvePoint pt = pCurve->GetPoint(t,0); pt.p.y = 0.f; pCurve->SetPoint(t,0,&pt); 94 | pCurve->SetPenProperty( RGB(0,0,0)); pCurve->SetDisabledPenProperty( RGB(128,128,128)); 95 | pt = pCurve->GetPoint(t,1); pt.p.y = 1.f; pCurve->SetPoint(t,1,&pt); 96 | } 97 | 98 | // Interactive Display 99 | TexHandle *texHandle; 100 | Interval texHandleValid; 101 | void DiscardTexHandle() { if (texHandle) { texHandle->DeleteThis(); texHandle = NULL; } } 102 | BOOL SupportTexDisplay() { return TRUE; } 103 | void ActivateTexDisplay(BOOL onoff) { if (!onoff) DiscardTexHandle(); } 104 | DWORD_PTR GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker); 105 | 106 | //From MtlBase 107 | ParamDlg* CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp); 108 | BOOL SetDlgThing(ParamDlg* dlg); 109 | void Update(TimeValue t, Interval& valid); 110 | void Reset(); 111 | Interval Validity(TimeValue t); 112 | ULONG LocalRequirements(int subMtlNum) { return berconXYZ.req(); } 113 | void MappingsRequired(int subMtlNum, BitArray& mapreq, BitArray& bumpreq) { berconXYZ.map(subMtlNum, mapreq, bumpreq); } 114 | 115 | 116 | int NumSubTexmaps() { return NOISE_NSUBTEX; } 117 | Texmap* GetSubTexmap(int i) { return subtex[i]; } 118 | void SetSubTexmap(int i, Texmap *m); 119 | TSTR GetSubTexmapSlotName(ARG_LOCALIZED(int i)); 120 | 121 | //From Texmap 122 | RGBA EvalColor(ShadeContext& sc); 123 | float EvalMono(ShadeContext& sc); 124 | Point3 EvalNormalPerturb(ShadeContext& sc); 125 | 126 | XYZGen *GetTheXYZGen() { return NULL; } 127 | 128 | int SubNumToRefNum(int subNum) { return subNum; } 129 | 130 | void ReadSXPData(TCHAR *name, void *sxpdata) { } 131 | 132 | //From Animatable 133 | Class_ID ClassID() {return BerconNoise_CLASS_ID;} 134 | SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; } 135 | #if MAX_RELEASE < 23900 136 | void GetClassName(ARG_LOCALIZED(TSTR& s)) { s = GetString(IDS_CLASS_NAME); } //override for Slate editor 137 | #else 138 | void GetClassName(ARG_LOCALIZED(TSTR& s)) const override { s = GetString(IDS_CLASS_NAME); } //override for Slate editor 139 | #endif 140 | 141 | RefTargetHandle Clone( RemapDir &remap ); 142 | RefResult NotifyRefChanged(NOTIFY_REF_CHANGED_ARGS); 143 | 144 | int NumSubs() { return 24; } 145 | Animatable* SubAnim(int i); 146 | TSTR SubAnimName(ARG_LOCALIZED(int i)); 147 | 148 | // TODO: Maintain the number or references here 149 | int NumRefs() { return 24; } 150 | RefTargetHandle GetReference(int i); 151 | void SetReference(int i, RefTargetHandle rtarg); 152 | 153 | int NumParamBlocks() { return 4; } 154 | IParamBlock2* GetParamBlock(int i) { switch (i) { case 0: return pblock; case 1: return pbCurve; case 2: return pbMap; case 3: return pbXYZ; } return NULL; } 155 | IParamBlock2* GetParamBlockByID(BlockID id) { 156 | if (pblock->ID() == id) return pblock; 157 | if (pbCurve->ID() == id) return pbCurve; 158 | if (pbMap->ID() == id) return pbMap; 159 | if (pbXYZ->ID() == id) return pbXYZ; 160 | return NULL; 161 | } 162 | 163 | void DeleteThis() { delete this; } 164 | 165 | //Constructor/Destructor 166 | BerconNoise(); 167 | ~BerconNoise(); 168 | 169 | void* GetInterface(ULONG id) { 170 | if(id == I_RESMAKER_INTERFACE) 171 | return (void *) (ResourceMakerCallback*) this; 172 | else 173 | return Texmap::GetInterface(id); 174 | } 175 | }; 176 | 177 | class BerconNoiseClassDesc : public ClassDesc2 { 178 | public: 179 | virtual int IsPublic() { return TRUE; } 180 | virtual void* Create(BOOL) { return new BerconNoise(); } 181 | virtual SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; } 182 | virtual Class_ID ClassID() { return BerconNoise_CLASS_ID; } 183 | virtual const TCHAR* Category() { return TEXMAP_CAT_3D; } 184 | virtual const TCHAR* InternalName() { return _T("BerconNoise"); } // returns fixed parsable name (scripter-visible name) 185 | virtual HINSTANCE HInstance() { return hInstance; } 186 | LOCALIZED_CLASS_NAME(IDS_CLASS_NAME) 187 | }; 188 | -------------------------------------------------------------------------------- /src/BerconGradient.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "BerconCommon.h" 21 | #include "windows.h" 22 | #include "IGradient.h" 23 | #include "chkmtlapi.h" 24 | 25 | extern TCHAR *GetString(int id); 26 | 27 | extern HINSTANCE hInstance; 28 | 29 | //#define GRADIENT3D 30 | 31 | class BerconGradient : public Texmap, public GradientMap, public ResourceMakerCallback { 32 | public: 33 | // Parameter block 34 | IParamBlock2 *pblock; 35 | IParamBlock2 *pbCurve; //ref CURVEPB_REF 36 | IParamBlock2 *pbXYZ; //ref COORDS 37 | 38 | BerconXYZ berconXYZ; 39 | static ParamDlg* texoutDlg; 40 | TextureOutput *texout; 41 | 42 | Interval ivalid; 43 | 44 | // Values 45 | GradientRamp* gradient; 46 | IGradient* gradientUI; 47 | int dirty; 48 | 49 | int p_seed; 50 | int p_type; 51 | int p_randObj; int p_randMat; int p_randPar; int p_randTile; 52 | float p_rangeMin; float p_rangeMax; 53 | int p_rangeLoop; 54 | int p_uvwType; 55 | int p_reverse; 56 | int p_normalType; 57 | int p_normalFunction; 58 | float p_ior; 59 | int p_disOn; 60 | float p_disStr; 61 | 62 | // Helpers 63 | void seedRandomGen(ShadeContext& sc); 64 | int limitRange(float& d); 65 | void EnableStuff(); 66 | 67 | // Shading 68 | float getGradientValueUVW(Point3 p); 69 | float getGradientValueDist(ShadeContext& sc); 70 | float getGradientValueNormal(ShadeContext& sc); 71 | float getGradientValue(ShadeContext& sc); 72 | 73 | // UI 74 | int previewMatIDMode; 75 | 76 | // Submaps 77 | Texmap* p_maptex; 78 | Texmap* p_distex; 79 | INode* p_node; 80 | 81 | void setKeyTex(Texmap* m); 82 | Texmap* getKeyTex(); 83 | 84 | // Editing keys 85 | void keyColorChanged(AColor col); 86 | void keyNumChanged(int num); 87 | void keyPosChanged(float pos); 88 | 89 | // GradientRampInterface 90 | int countKeys(); 91 | void resetKeys(); 92 | 93 | // From GradientMap 94 | void gradAddKey(float pos); 95 | void gradMoveKey(int n, float pos); 96 | void gradDelKey(int n); 97 | void gradSelKey(); 98 | void gradReset() { resetKeys(); } 99 | 100 | // Curve 101 | ICurveCtl* curve; 102 | BOOL p_curveOn; 103 | // From ResourceMakerCallback 104 | BOOL SetCustomImageList(HIMAGELIST &hCTools,ICurveCtl *pCCtl) { return TRUE; }; 105 | BOOL GetToolTip(int iButton, TSTR &ToolTip,ICurveCtl *pCCtl) { return TRUE; }; 106 | void ResetCallback(int curvenum, ICurveCtl *pCCtl) { ICurve *pCurve = NULL; pCurve = pCCtl->GetControlCurve(curvenum); if(pCurve) { pCurve->SetNumPts(2); NewCurveCreatedCallback(curvenum, pCCtl); }} 107 | void NewCurveCreatedCallback(int curvenum, ICurveCtl *pCCtl) { 108 | ICurve *pCurve = NULL; pCurve = pCCtl->GetControlCurve(curvenum); TimeValue t = GetCOREInterface()->GetTime(); 109 | CurvePoint pt = pCurve->GetPoint(t,0); pt.p.y = 0.f; pCurve->SetPoint(t,0,&pt); 110 | pCurve->SetPenProperty( RGB(0,0,0)); pCurve->SetDisabledPenProperty( RGB(128,128,128)); 111 | pt = pCurve->GetPoint(t,1); pt.p.y = 1.f; pCurve->SetPoint(t,1,&pt); 112 | } 113 | 114 | //From MtlBase 115 | ParamDlg* CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp); 116 | BOOL SetDlgThing(ParamDlg* dlg); 117 | void Update(TimeValue t, Interval& valid); 118 | void Reset(); 119 | Interval Validity(TimeValue t); 120 | 121 | ULONG LocalRequirements(int subMtlNum) { return berconXYZ.req(); } 122 | void MappingsRequired(int subMtlNum, BitArray& mapreq, BitArray& bumpreq) { berconXYZ.map(subMtlNum, mapreq, bumpreq); } 123 | 124 | int NumSubTexmaps() { return 3 + gradient->numKeys(); } // !! Update submap count !! 125 | Texmap* GetSubTexmap(int i); 126 | void SetSubTexmap(int i, Texmap *m); 127 | TSTR GetSubTexmapSlotName(ARG_LOCALIZED(int i)); 128 | 129 | //From Texmap 130 | RGBA EvalColor(ShadeContext& sc); 131 | float EvalMono(ShadeContext& sc); 132 | Point3 EvalNormalPerturb(ShadeContext& sc); 133 | int SubNumToRefNum(int subNum) { return subNum; } 134 | 135 | void ReadSXPData(TCHAR *name, void *sxpdata) {} 136 | 137 | // Interactive Display 138 | TexHandle *texHandle; 139 | Interval texHandleValid; 140 | void DiscardTexHandle() { if (texHandle) { texHandle->DeleteThis(); texHandle = NULL; } } 141 | BOOL SupportTexDisplay() { return TRUE; } 142 | void ActivateTexDisplay(BOOL onoff) { if (!onoff) DiscardTexHandle(); } 143 | DWORD_PTR GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker); 144 | 145 | //From Animatable 146 | Class_ID ClassID() {return BerconGradient_CLASS_ID;} 147 | SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; } 148 | #if MAX_RELEASE < 23900 149 | void GetClassName(ARG_LOCALIZED(TSTR& s)) { s = GetString(IDS_BERCON_COLOR); } 150 | #else 151 | void GetClassName(ARG_LOCALIZED(TSTR& s)) const override { s = GetString(IDS_BERCON_COLOR); } //override for Slate editor 152 | #endif 153 | 154 | RefTargetHandle Clone( RemapDir &remap ); 155 | RefResult NotifyRefChanged(NOTIFY_REF_CHANGED_ARGS); 156 | 157 | int NumSubs() { return 8+gradient->numKeys(); } // !! Update submap count !! 158 | Animatable* SubAnim(int i); 159 | TSTR SubAnimName(ARG_LOCALIZED(int i)); 160 | 161 | int NumRefs() { return 8+gradient->numKeys(); } // !! Update submap count !! 162 | RefTargetHandle GetReference(int i); 163 | void SetReference(int i, RefTargetHandle rtarg); 164 | 165 | int NumParamBlocks() { return 3; } 166 | IParamBlock2* GetParamBlock(int i) { switch (i) { case 0: return pblock; case 1: return pbCurve; case 2: return pbXYZ; } return NULL; } 167 | IParamBlock2* GetParamBlockByID(BlockID id) { 168 | if (pblock->ID() == id) return pblock; 169 | if (pbCurve->ID() == id) return pbCurve; 170 | if (pbXYZ->ID() == id) return pbXYZ; 171 | return NULL; 172 | } 173 | 174 | int RenderBegin(TimeValue t, ULONG flags = 0) { if (!flags) previewMatIDMode = FALSE; return 1; } 175 | int RenderEnd(TimeValue t) { previewMatIDMode = TRUE; return 1; } 176 | 177 | void DeleteThis() { delete this; } 178 | 179 | BerconGradient(); 180 | ~BerconGradient(); 181 | 182 | void* GetInterface(ULONG id) { 183 | if(id == I_RESMAKER_INTERFACE) 184 | return (void *) (ResourceMakerCallback*) this; 185 | else 186 | return Texmap::GetInterface(id); 187 | } 188 | }; 189 | 190 | class BerconGradientClassDesc : public ClassDesc2 { 191 | public: 192 | virtual int IsPublic() { return TRUE; } 193 | virtual void* Create(BOOL /*loading = FALSE*/) { return new BerconGradient(); } 194 | virtual SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; } 195 | virtual Class_ID ClassID() { return BerconGradient_CLASS_ID; } 196 | virtual const TCHAR* Category() { return TEXMAP_CAT_3D; } 197 | virtual const TCHAR* InternalName() { return _T("BerconGradient"); } // scripter-visible name 198 | virtual HINSTANCE HInstance() { return hInstance; } 199 | LOCALIZED_CLASS_NAME(IDS_BERCON_COLOR) 200 | }; 201 | -------------------------------------------------------------------------------- /src/BerconSC.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #include "max.h" 19 | 20 | #define BERCON_SHADE_CONTEXT_CLASS_ID Class_ID(0x7c0a38f1, 0x2f1a67f2) 21 | 22 | class BerconSC: public ShadeContext { 23 | private: 24 | ShadeContext* const sc; 25 | 26 | int type; 27 | Point3 uvPoint; 28 | Point3 uvPoint2; 29 | int uvChannel; 30 | int uvChannel2; 31 | bool useMultiTexture; 32 | float val; 33 | 34 | public: 35 | BerconSC(ShadeContext* const sc) : sc (sc) { 36 | mode = sc->mode; 37 | doMaps = sc->doMaps; 38 | filterMaps = sc->filterMaps; 39 | shadow = sc->shadow; 40 | backFace = sc->backFace; 41 | mtlNum = sc->mtlNum; 42 | ambientLight = sc->ambientLight; 43 | nLights = sc->nLights; 44 | rayLevel = sc->rayLevel; 45 | xshadeID = sc->xshadeID; 46 | atmosSkipLight = sc->atmosSkipLight; 47 | globContext = sc->globContext; 48 | out = sc->out; 49 | 50 | uvChannel = -1; uvChannel2 = -1; useMultiTexture = false; type = -1; 51 | } 52 | 53 | void setParams(Point3 p, int type, int chan=0) { 54 | uvPoint = p; 55 | this->type = type; 56 | uvChannel = chan; 57 | } 58 | 59 | void setUV1(Point3 uvw, int chan) { 60 | uvPoint = uvw; 61 | uvChannel = chan; 62 | } 63 | 64 | void setUV2(Point3 uvw, int chan) { 65 | uvPoint2 = uvw; 66 | uvChannel2 = chan; 67 | } 68 | 69 | void setMultiTexture(float val) { 70 | this->val = val; 71 | useMultiTexture = true; 72 | } 73 | 74 | void ResetOutput (int n) { sc->ResetOutput(n); } 75 | Class_ID ClassID () { return BERCON_SHADE_CONTEXT_CLASS_ID; } 76 | BOOL InMtlEditor () { return sc->InMtlEditor(); } 77 | int Antialias () { return sc->Antialias(); } 78 | int ProjType () { return sc->ProjType(); } 79 | LightDesc* Light (int n) { return sc->Light(n); } 80 | TimeValue CurTime () { return sc->CurTime(); } 81 | int NodeID () { return sc->NodeID(); } 82 | INode* Node () { return sc->Node(); } 83 | Object* GetEvalObject () { return sc->GetEvalObject(); } 84 | Point3 BarycentricCoords () { return sc->BarycentricCoords(); } 85 | int FaceNumber () { return sc->FaceNumber(); } 86 | Point3 Normal () { return sc->Normal(); } 87 | void SetNormal (Point3 p) { sc->SetNormal(p); } 88 | Point3 OrigNormal () { return sc->OrigNormal(); } 89 | Point3 GNormal () { return sc->GNormal(); } 90 | float Curve () { return sc->Curve(); } 91 | Point3 V () { return sc->V(); } 92 | void SetView (Point3 p) { sc->SetView(p); } 93 | Point3 OrigView () { return sc->OrigView(); } 94 | Point3 ReflectVector () { return sc->ReflectVector(); } 95 | Point3 RefractVector (float ior) { return sc->RefractVector(ior); } 96 | void SetIOR (float ior) { sc->SetIOR(ior); } 97 | float GetIOR () { return sc->GetIOR(); } 98 | Point3 CamPos () { return sc->CamPos(); } 99 | inline Point3 P (); // Overridden 100 | Point3 DP () { return sc->DP(); } 101 | void DP (Point3& dpdx, Point3& dpdy) { sc->DP(dpdx, dpdx); } 102 | inline Point3 PObj (); // Overridden 103 | Point3 DPObj () { return sc->DPObj(); } 104 | Box3 ObjectBox () { return sc->ObjectBox(); } 105 | inline Point3 PObjRelBox (); // Overridden 106 | Point3 DPObjRelBox () { return sc->DPObjRelBox(); } 107 | inline void ScreenUV (Point2& uv, Point2 &duv); // Overridden 108 | IPoint2 ScreenCoord () { return sc->ScreenCoord(); } 109 | Point2 SurfacePtScreen (){ return sc->SurfacePtScreen(); } 110 | inline Point3 UVW (int channel); // Overridden 111 | Point3 DUVW (int channel) { return sc->DUVW(channel); } 112 | void DPdUVW (Point3 dP[3], int channel){ sc->DPdUVW(dP, channel); } 113 | int BumpBasisVectors (Point3 dP[2], int axis, int channel){ return sc->BumpBasisVectors(dP, axis, channel); } 114 | BOOL IsSuperSampleOn () { return sc->IsSuperSampleOn(); } 115 | BOOL IsTextureSuperSampleOn () { return sc->IsTextureSuperSampleOn(); } 116 | int GetNSuperSample () { return sc->GetNSuperSample(); } 117 | float GetSampleSizeScale (){ return sc->GetSampleSizeScale(); } 118 | Point3 UVWNormal (int channel){ return sc->UVWNormal(channel); } 119 | float RayDiam (){ return sc->RayDiam(); } 120 | float RayConeAngle (){ return sc->RayConeAngle(); } 121 | AColor EvalEnvironMap (Texmap* map, Point3 view) { return sc->EvalEnvironMap(map, view); } 122 | void GetBGColor (Color& bgcol, Color& transp, BOOL fogBG){ sc->GetBGColor(bgcol, transp, fogBG); } 123 | float CamNearRange () { return sc->CamNearRange(); } 124 | float CamFarRange (){ return sc->CamFarRange(); } 125 | Point3 PointTo (const Point3& p, RefFrame ito) { return sc->PointTo(p, ito); } 126 | Point3 PointFrom (const Point3& p, RefFrame ifrom) { return sc->PointFrom(p, ifrom); } 127 | Point3 VectorTo (const Point3& p, RefFrame ito) { return sc->VectorTo(p, ito); } 128 | Point3 VectorFrom (const Point3& p, RefFrame ifrom) { return sc->VectorFrom(p, ifrom); } 129 | Point3 VectorToNoScale (const Point3& p, RefFrame ito) { return sc->VectorToNoScale(p, ito); } 130 | Point3 VectorFromNoScale (const Point3& p, RefFrame ifrom){ return sc->VectorFromNoScale(p, ifrom); } 131 | void SetGBufferID (int gbid){ sc->SetGBufferID(gbid); } 132 | FILE* DebugFile (){ return sc->DebugFile(); } 133 | AColor EvalGlobalEnvironMap (Point3 dir){ return sc->EvalGlobalEnvironMap(dir); } 134 | BOOL GetCache (Texmap* map, AColor &c) { return sc->GetCache(map, c); } 135 | BOOL GetCache (Texmap* map, float &f) { return sc->GetCache(map, f); } 136 | BOOL GetCache (Texmap* map, Point3 &p) { return sc->GetCache(map, p); } 137 | void PutCache (Texmap* map, const AColor &c) { sc->PutCache(map, c); } 138 | void PutCache (Texmap* map, const float f) { sc->PutCache(map, f); } 139 | void PutCache (Texmap* map, const Point3 &p) { sc->PutCache(map, p); } 140 | void TossCache (Texmap* map){ sc->TossCache(map); } 141 | INT_PTR Execute (int cmd, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3){ return sc->Execute(cmd, arg1, arg2, arg3); } 142 | LightDesc* GetAtmosSkipLight () { return sc->GetAtmosSkipLight(); } 143 | void SetAtmosSkipLight (LightDesc* lt){ sc->SetAtmosSkipLight(lt); } 144 | int NRenderElements () { return sc->NRenderElements(); } 145 | IRenderElement* GetRenderElement (int n){ return sc->GetRenderElement(n); } 146 | Color DiffuseIllum (){ return sc->DiffuseIllum(); } 147 | 148 | #if MAX_RELEASE < 23900 149 | //#if MAX_RELEASE < MAX_RELEASE_R24_PREVIEW (2021 and earlier) 150 | bool IsPhysicalSpace () const{ return sc->IsPhysicalSpace(); } 151 | template void ScaledToRGB (T& energy) const { sc->ScaledToRGB(energy); } 152 | float ScaledToRGB (float energy) const{ return sc->ScaledToRGB(energy); } 153 | void ScaledToRGB (){ sc->ScaledToRGB(); } 154 | template void ScalePhysical (T& energy) const { sc->ScaledPhysical(energy); } 155 | float ScalePhysical (float energy) const{ return sc->ScalePhysical(energy); } 156 | template void ScaleRGB (T& energy) const { sc->ScaleRGB(energy); } 157 | float ScaleRGB (float energy) const{ return sc->ScaleRGB(energy); } 158 | #endif 159 | 160 | #if MAX_RELEASE >= 25900 // The 2023 Max SDK does not know the value of MAX_RELEASE_R26_PREVIEW 161 | //#if MAX_RELEASE >= MAX_RELEASE_R26_PREVIEW 162 | Matrix3 MatrixTo(RefFrame ito) override { return sc->MatrixTo(ito); } 163 | 164 | Matrix3 MatrixFrom(RefFrame ifrom) override { return sc->MatrixFrom(ifrom); } 165 | #endif 166 | }; 167 | 168 | inline Point3 BerconSC::PObjRelBox() { 169 | return sc->PObjRelBox(); 170 | } 171 | 172 | inline void BerconSC::ScreenUV(Point2& uv, Point2 &duv) { 173 | sc->ScreenUV(uv, duv); 174 | if (type == 4) { 175 | uv.x = uvPoint.x; 176 | uv.y = uvPoint.y; 177 | } 178 | } 179 | 180 | inline Point3 BerconSC::P() { 181 | return type == 3 ? uvPoint : sc->P(); 182 | } 183 | 184 | inline Point3 BerconSC::PObj() { 185 | return type == 2 ? uvPoint : sc->PObj(); 186 | } 187 | 188 | inline Point3 BerconSC::UVW(int channel) { 189 | if (useMultiTexture && 99 == channel) 190 | return Point3(val, val, val); 191 | 192 | if ((type == 0 || type == 1) && uvChannel == channel) 193 | return uvPoint; 194 | 195 | if (uvChannel > 0 && uvChannel == channel) 196 | return uvPoint; 197 | 198 | if (uvChannel2 > 0 && uvChannel2 == channel) 199 | return uvPoint2; 200 | 201 | return sc->UVW(channel); 202 | } -------------------------------------------------------------------------------- /src/BerconDistortion.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #include "BerconDistortion.h" 19 | 20 | #define PBLOCK_REF 0 21 | #define MAP1_REF 1 22 | #define MAP2_REF 2 23 | #define MAP3_REF 3 24 | #define COORD_REF 4 25 | 26 | #define NAMELENGTH 64 27 | typedef TCHAR TChBuffer[NAMELENGTH]; 28 | 29 | static BerconDistortionClassDesc BerconDistortionDesc; 30 | ClassDesc2* GetBerconDistortionDesc() { return &BerconDistortionDesc; } 31 | 32 | enum { BerconDistortion_params, xyz_params }; 33 | 34 | XYZ_Desc xyz_blk(&BerconDistortionDesc, COORD_REF, xyz_params, 0, 1, 1, 1, 0); 35 | 36 | enum { map1, distortion_map, distortion_map2, use_distortion, distortion_str, }; 37 | 38 | static ParamBlockDesc2 BerconDistortion_param_blk ( BerconDistortion_params, _T("params"), 0, &BerconDistortionDesc, 39 | P_AUTO_CONSTRUCT + P_AUTO_UI, PBLOCK_REF, 40 | IDD_PANEL_DISTORTION, IDS_PARAMS, 0, 0, NULL, 41 | // params 42 | // Distortion controls 43 | 44 | distortion_map, _T("map1"), TYPE_TEXMAP, P_OWNERS_REF, IDS_DISTORTION_MAP, 45 | p_refno, MAP1_REF, 46 | p_subtexno, 0, 47 | p_ui, TYPE_TEXMAPBUTTON, IDC_DISTORTION_TEX, 48 | p_end, 49 | distortion_map2, _T("map2"), TYPE_TEXMAP, P_OWNERS_REF, IDS_DISTORTION_MAP2, 50 | p_refno, MAP2_REF, 51 | p_subtexno, 1, 52 | p_ui, TYPE_TEXMAPBUTTON, IDC_DISTORTION_TEX2, 53 | p_end, 54 | map1, _T("map3"), TYPE_TEXMAP, P_OWNERS_REF, IDS_MAP1, 55 | p_refno, MAP3_REF, 56 | p_subtexno, 2, 57 | p_ui, TYPE_TEXMAPBUTTON, IDC_MAP1, 58 | p_end, 59 | distortion_str, _T("distortionStr"), TYPE_FLOAT, P_ANIMATABLE, IDS_DISTORTION_STRENGTH, 60 | p_default, 0.1f, 61 | p_range, 0.0f, 1000.0f, 62 | p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_DISTORTION_EDIT, IDC_DISTORTION_SPIN, 0.001f, 63 | p_end, 64 | use_distortion, _T("useDistortion"), TYPE_BOOL, 0, IDS_USE_DISTORTION, 65 | p_default, FALSE, 66 | p_ui, TYPE_SINGLECHEKBOX, IDC_USE_DISTORTION, 67 | p_end, 68 | p_end 69 | ); 70 | 71 | //--- BerconDistortion ------------------------------------------------------- 72 | BerconDistortion::BerconDistortion() { 73 | for (int i=0; iGetHandle(); 94 | else DiscardTexHandle(); 95 | } 96 | texHandle = thmaker.MakeHandle(GetVPDisplayDIB(t,thmaker,texHandleValid)); 97 | return texHandle->GetHandle(); 98 | } 99 | 100 | void BerconDistortion::Update(TimeValue t, Interval& valid) { 101 | if (pblock == NULL) return; 102 | 103 | if (!ivalid.InInterval(t)) { 104 | ivalid.SetInfinite(); 105 | for (int i=0; iUpdate(t,ivalid); 108 | pblock->GetValue( distortion_str, t, distortionStr, ivalid); 109 | pblock->GetValue( use_distortion, t, useDistortion, ivalid); 110 | 111 | berconXYZ.update(pbXYZ, t, ivalid); 112 | } 113 | valid &= ivalid; 114 | } 115 | 116 | Interval BerconDistortion::Validity(TimeValue t) { 117 | Interval v; 118 | Update(t,v); 119 | return ivalid; 120 | } 121 | 122 | ParamDlg* BerconDistortion::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp) { 123 | IAutoMParamDlg* masterDlg = BerconDistortionDesc.CreateParamDlgs(hwMtlEdit, imp, this); 124 | xyz_blk.SetUserDlgProc(new BerconXYZDlgProc(this)); 125 | return masterDlg; 126 | } 127 | 128 | BOOL BerconDistortion::SetDlgThing(ParamDlg* dlg) { 129 | return FALSE; 130 | } 131 | 132 | void BerconDistortion::SetSubTexmap(int i, Texmap *m) { 133 | ReplaceReference(i+1,m); 134 | if (i==0) { 135 | BerconDistortion_param_blk.InvalidateUI(distortion_map); 136 | ivalid.SetEmpty(); 137 | } else if (i==1) { 138 | BerconDistortion_param_blk.InvalidateUI(distortion_map2); 139 | ivalid.SetEmpty(); 140 | } else if (i==2) { 141 | BerconDistortion_param_blk.InvalidateUI(map1); 142 | ivalid.SetEmpty(); 143 | } 144 | } 145 | 146 | TSTR BerconDistortion::GetSubTexmapSlotName(ARG_LOCALIZED(int i)) { 147 | switch(i) { 148 | case 0: return TSTR(GetString(IDS_DISTORTION_MAP)); 149 | case 1: return TSTR(GetString(IDS_DISTORTION_MAP2)); 150 | case 2: return TSTR(GetString(IDS_MAP1)); 151 | default: return TSTR(_T("")); 152 | } 153 | } 154 | 155 | RefTargetHandle BerconDistortion::GetReference(int i) { 156 | switch (i) { 157 | case PBLOCK_REF: return pblock; 158 | case COORD_REF: return pbXYZ; 159 | default: return subtex[i-1]; 160 | } 161 | } 162 | 163 | void BerconDistortion::SetReference(int i, RefTargetHandle rtarg) { 164 | switch(i) { 165 | case PBLOCK_REF: pblock = (IParamBlock2 *)rtarg; break; 166 | case COORD_REF: pbXYZ = (IParamBlock2 *)rtarg; break; 167 | default: subtex[i-1] = (Texmap *)rtarg; break; 168 | } 169 | } 170 | 171 | RefTargetHandle BerconDistortion::Clone(RemapDir &remap) { 172 | BerconDistortion *mnew = new BerconDistortion(); 173 | *((MtlBase*)mnew) = *((MtlBase*)this); // copy superclass stuff 174 | mnew->ReplaceReference(PBLOCK_REF,remap.CloneRef(pblock)); 175 | mnew->ReplaceReference(COORD_REF,remap.CloneRef(pbXYZ)); 176 | mnew->ivalid.SetEmpty(); 177 | for (int i = 0; isubtex[i] = NULL; 179 | if (subtex[i]) 180 | mnew->ReplaceReference(i+1,remap.CloneRef(subtex[i])); 181 | } 182 | BaseClone(this, mnew, remap); 183 | return (RefTargetHandle)mnew; 184 | } 185 | 186 | Animatable* BerconDistortion::SubAnim(int i) { 187 | switch (i) { 188 | case PBLOCK_REF: return pblock; 189 | case COORD_REF: return pbXYZ; 190 | default: return subtex[i-1]; 191 | } 192 | } 193 | 194 | TSTR BerconDistortion::SubAnimName(ARG_LOCALIZED(int i)) { 195 | switch (i) { 196 | case PBLOCK_REF: return GetString(IDS_PARAMS); 197 | case COORD_REF: return GetString(IDS_XYZ); 198 | default: return GetSubTexmapTVName(FORWARD_ARG_LOCALIZED(i-1)); 199 | } 200 | } 201 | 202 | RefResult BerconDistortion::NotifyRefChanged(NOTIFY_REF_CHANGED_ARGS) { 203 | switch (message) { 204 | case REFMSG_CHANGE: 205 | ivalid.SetEmpty(); 206 | if (hTarget == pblock) { 207 | ParamID changing_param = pblock->LastNotifyParamID(); 208 | BerconDistortion_param_blk.InvalidateUI(changing_param); 209 | if (changing_param != -1) DiscardTexHandle(); 210 | } 211 | break; 212 | } 213 | return(REF_SUCCEED); 214 | } 215 | 216 | // Define some basic values 217 | static AColor black(0.0f,0.0f,0.0f,1.0f); 218 | 219 | Point3 BerconDistortion::getDistVector(ShadeContext& sc) { 220 | if (subtex[1]) 221 | return subtex[0]->EvalNormalPerturb(sc)*distortionStr*subtex[1]->EvalMono(sc); 222 | else 223 | return subtex[0]->EvalNormalPerturb(sc)*distortionStr; 224 | } 225 | 226 | AColor BerconDistortion::EvalColor(ShadeContext& sc) { 227 | if (!subtex[2]) return black; 228 | Point3 p; 229 | berconXYZ.get(sc, p); 230 | BerconSC& bsc = BerconSC(&sc); 231 | if (useDistortion && subtex[0]) p += getDistVector(sc); 232 | bsc.setParams(p, berconXYZ.type(), berconXYZ.chan()); 233 | return subtex[2]->EvalColor(bsc); 234 | } 235 | 236 | float BerconDistortion::EvalMono(ShadeContext& sc) { 237 | if (!subtex[2]) return 0.f; 238 | Point3 p; 239 | berconXYZ.get(sc, p); 240 | BerconSC& bsc = BerconSC(&sc); 241 | if (useDistortion && subtex[0]) p += getDistVector(sc); 242 | bsc.setParams(p, berconXYZ.type(), berconXYZ.chan()); 243 | return subtex[2]->EvalMono(bsc); 244 | } 245 | 246 | Point3 BerconDistortion::EvalNormalPerturb(ShadeContext& sc) { 247 | if (!subtex[2]) return Point3(0.f, 0.f, 0.f); 248 | Point3 p; 249 | berconXYZ.get(sc, p); 250 | BerconSC& bsc = BerconSC(&sc); 251 | if (useDistortion && subtex[0]) p += getDistVector(sc); 252 | bsc.setParams(p, berconXYZ.type(), berconXYZ.chan()); 253 | return subtex[2]->EvalNormalPerturb(bsc); 254 | } -------------------------------------------------------------------------------- /src/fractal.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #include "fractal.h" 19 | 20 | float Fractal::fractal(Point3 p, NoiseParams& np) { 21 | float sum = 0.0f; 22 | float l, f = 1.0f; 23 | for (l = np.levels; l >= 1.0f; l-=1.0f) { 24 | sum += Noise::noise(p*f, np)/f; 25 | f *= 2.0f; 26 | } 27 | if (l>0.0f) 28 | sum += l*Noise::noise(p*f, np)/f; 29 | return 0.5f*(sum+1.0f); 30 | } 31 | 32 | float Fractal::turbulence(Point3 p, NoiseParams& np) { 33 | float sum = 0.0f; 34 | float l,f = 1.0f; 35 | for (l = np.levels; l >= 1.0f; l-=1.0f) { 36 | sum += fabs(Noise::noise(p*f, np))/f; 37 | f *= 2.0f; 38 | } 39 | if (l>0.0f) 40 | sum += l*fabs(Noise::noise(p*f, np))/f; 41 | return sum; 42 | } 43 | 44 | float Fractal::fBm(Point3 p, NoiseParams& np) { 45 | float sum = 0.0f; 46 | float pwr = 1.0f; 47 | float pwHL = pow(np.lacunarity, -np.H); 48 | 49 | for (int i=0; i<(int)np.levels; i++) { 50 | sum += Noise::noise(p, np) * pwr; 51 | pwr *= pwHL; 52 | p *= np.lacunarity; 53 | } 54 | 55 | float rmd = np.levels - FASTFLOOR(np.levels); 56 | if (rmd!=0.f) sum += rmd * Noise::noise(p, np) * pwr; 57 | 58 | return (sum+1.f)*.5f; 59 | } 60 | 61 | float Fractal::fBmTurb(Point3 p, NoiseParams& np) { 62 | float sum = 0.0f; 63 | float pwr = 1.0f; 64 | float pwHL = pow(np.lacunarity, -np.H); 65 | 66 | for (int i=0; i<(int)np.levels; i++) { 67 | sum += fabs(Noise::noise(p, np)) * pwr; 68 | pwr *= pwHL; 69 | p *= np.lacunarity; 70 | } 71 | 72 | float rmd = np.levels - FASTFLOOR(np.levels); 73 | if (rmd!=0.f) sum += rmd * fabs(Noise::noise(p, np)) * pwr; 74 | 75 | return sum; 76 | } 77 | 78 | float Fractal::heteroTerrain(Point3 p, NoiseParams& np) { 79 | float sum = 0.0f; 80 | float pwHL = pow(np.lacunarity, -np.H); 81 | float pwr = pwHL; 82 | 83 | sum = Noise::noise(p, np) + np.offset; 84 | p *= np.lacunarity; 85 | 86 | for (int i=0; i<(int)np.levels; i++) { 87 | sum += (Noise::noise(p, np) + np.offset) * pwr * sum; 88 | pwr *= pwHL; 89 | p *= np.lacunarity; 90 | } 91 | 92 | float rmd = np.levels - FASTFLOOR(np.levels); 93 | if (rmd!=0.f) sum += rmd * (Noise::noise(p, np) + np.offset) * pwr * sum; 94 | 95 | return (sum+1.f)*.5f; 96 | } 97 | 98 | float Fractal::hybridMultiFractal(Point3 p, NoiseParams& np) { 99 | float sum = 0.0f; 100 | float pwHL = pow(np.lacunarity, -np.H); 101 | float pwr = pwHL; 102 | 103 | float signal, weight, rmd; 104 | 105 | sum = Noise::noise(p, np) + np.offset; 106 | weight = np.gain * sum; 107 | p *= np.lacunarity; 108 | 109 | for (int i=1; (weight>0.001) && (i<(int)np.levels); i++) { 110 | if (weight>1.0) weight=1.0; 111 | signal = (Noise::noise(p, np) + np.offset) * pwr; 112 | pwr *= pwHL; 113 | sum += weight * signal; 114 | weight *= np.gain * signal; 115 | p *= np.lacunarity; 116 | } 117 | 118 | rmd = np.levels - FASTFLOOR(np.levels); 119 | if (rmd!=0.f) sum += rmd * (Noise::noise(p, np) + np.offset) * pwr; 120 | 121 | return (sum+1.f)*.5f; 122 | } 123 | 124 | float Fractal::ridgedMultiFractal(Point3 p, NoiseParams& np) { 125 | float sum = 0.0f; 126 | float pwHL = pow(np.lacunarity, -np.H); 127 | float pwr = pwHL; 128 | 129 | float signal, weight; 130 | 131 | signal = np.offset - fabs(Noise::noise(p, np)); 132 | signal *= signal; 133 | sum = signal; 134 | weight = 1.f; 135 | 136 | for(int i=1; i<(int)np.levels; i++ ) { 137 | p *= np.lacunarity; 138 | weight = signal * np.gain; 139 | if (weight>1.0) weight=1.0; else if (weight<0.0) weight=0.0; 140 | signal = np.offset - fabs(Noise::noise(p, np)); 141 | signal *= signal; 142 | signal *= weight; 143 | sum += signal * pwr; 144 | pwr *= pwHL; 145 | } 146 | 147 | return sum; 148 | } 149 | 150 | // Filtered 151 | 152 | float Fractal::fractal(Point3 p, float d, NoiseParams& np) { 153 | float sum = 0.0f; 154 | float l, f = 1.0f; 155 | for (l = np.levels; l >= 1.0f; l-=1.0f) { 156 | sum += Noise::noise(p*f, d*f, np)/f; 157 | f *= 2.0f; 158 | } 159 | if (l>0.0f) 160 | sum += l*Noise::noise(p*f, d*f, np)/f; 161 | return 0.5f*(sum+1.0f); 162 | } 163 | 164 | float Fractal::turbulence(Point3 p, float d, NoiseParams& np) { 165 | float sum = 0.0f; 166 | float l,f = 1.0f; 167 | for (l = np.levels; l >= 1.0f; l-=1.0f) { 168 | sum += fabs(Noise::noise(p*f, d*f, np))/f; 169 | f *= 2.0f; 170 | } 171 | if (l>0.0f) 172 | sum += l*fabs(Noise::noise(p*f, d*f, np))/f; 173 | return sum; 174 | } 175 | 176 | float Fractal::fBm(Point3 p, float d, NoiseParams& np) { 177 | float sum = 0.0f; 178 | float pwr = 1.0f; 179 | float pwHL = pow(np.lacunarity, -np.H); 180 | 181 | for (int i=0; i<(int)np.levels; i++) { 182 | sum += Noise::noise(p, d, np) * pwr; 183 | pwr *= pwHL; 184 | p *= np.lacunarity; 185 | d *= np.lacunarity; 186 | } 187 | 188 | float rmd = np.levels - FASTFLOOR(np.levels); 189 | if (rmd!=0.f) sum += rmd * Noise::noise(p, d, np) * pwr; 190 | 191 | return (sum+1.f)*.5f; 192 | } 193 | 194 | float Fractal::fBmTurb(Point3 p, float d, NoiseParams& np) { 195 | float sum = 0.0f; 196 | float pwr = 1.0f; 197 | float pwHL = pow(np.lacunarity, -np.H); 198 | 199 | for (int i=0; i<(int)np.levels; i++) { 200 | sum += fabs(Noise::noise(p, d, np)) * pwr; 201 | pwr *= pwHL; 202 | p *= np.lacunarity; 203 | d *= np.lacunarity; 204 | } 205 | 206 | float rmd = np.levels - FASTFLOOR(np.levels); 207 | if (rmd!=0.f) sum += rmd * fabs(Noise::noise(p, d, np)) * pwr; 208 | 209 | return sum; 210 | } 211 | 212 | float Fractal::heteroTerrain(Point3 p, float d, NoiseParams& np) { 213 | float sum = 0.0f; 214 | float pwHL = pow(np.lacunarity, -np.H); 215 | float pwr = pwHL; 216 | 217 | sum = Noise::noise(p, np) + np.offset; 218 | p *= np.lacunarity; 219 | d *= np.lacunarity; 220 | 221 | for (int i=0; i<(int)np.levels; i++) { 222 | sum += (Noise::noise(p, d, np) + np.offset) * pwr * sum; 223 | pwr *= pwHL; 224 | p *= np.lacunarity; 225 | d *= np.lacunarity; 226 | } 227 | 228 | float rmd = np.levels - FASTFLOOR(np.levels); 229 | if (rmd!=0.f) sum += rmd * (Noise::noise(p, d, np) + np.offset) * pwr * sum; 230 | 231 | return (sum+1.f)*.5f; 232 | } 233 | 234 | float Fractal::hybridMultiFractal(Point3 p, float d, NoiseParams& np) { 235 | float sum = 0.0f; 236 | float pwHL = pow(np.lacunarity, -np.H); 237 | float pwr = pwHL; 238 | 239 | float signal, weight, rmd; 240 | 241 | sum = Noise::noise(p, d, np) + np.offset; 242 | weight = np.gain * sum; 243 | p *= np.lacunarity; 244 | d *= np.lacunarity; 245 | 246 | for (int i=1; (weight>0.001) && (i<(int)np.levels); i++) { 247 | if (weight>1.0) weight=1.0; 248 | signal = (Noise::noise(p, d, np) + np.offset) * pwr; 249 | pwr *= pwHL; 250 | sum += weight * signal; 251 | weight *= np.gain * signal; 252 | p *= np.lacunarity; 253 | d *= np.lacunarity; 254 | } 255 | 256 | rmd = np.levels - FASTFLOOR(np.levels); 257 | if (rmd!=0.f) sum += rmd * (Noise::noise(p, d, np) + np.offset) * pwr; 258 | 259 | return (sum+1.f)*.5f; 260 | } 261 | 262 | float Fractal::ridgedMultiFractal(Point3 p, float d, NoiseParams& np) { 263 | float sum = 0.0f; 264 | float pwHL = pow(np.lacunarity, -np.H); 265 | float pwr = pwHL; 266 | 267 | float signal, weight; 268 | 269 | signal = np.offset - fabs(Noise::noise(p, d, np)); 270 | signal *= signal; 271 | sum = signal; 272 | weight = 1.f; 273 | 274 | for(int i=1; i<(int)np.levels; i++ ) { 275 | p *= np.lacunarity; 276 | d *= np.lacunarity; 277 | weight = signal * np.gain; 278 | if (weight>1.0) weight=1.0; else if (weight<0.0) weight=0.0; 279 | signal = np.offset - fabs(Noise::noise(p, d, np)); 280 | signal *= signal; 281 | signal *= weight; 282 | sum += signal * pwr; 283 | pwr *= pwHL; 284 | } 285 | 286 | return sum; 287 | } 288 | 289 | // Generic 290 | float Fractal::fBm(Point3 p, float levels, float lacunarity, float H) { 291 | float sum = 0.0f; 292 | float pwr = 1.0f; 293 | float pwHL = pow(lacunarity, -H); 294 | 295 | for (int i=0; i<(int)levels; i++) { 296 | sum += Perlin::noise(p.x, p.y, p.z) * pwr; 297 | pwr *= pwHL; 298 | p *= lacunarity; 299 | } 300 | 301 | float rmd = levels - FASTFLOOR(levels); 302 | if (rmd!=0.f) sum += rmd * Perlin::noise(p.x, p.y, p.z) * pwr; 303 | 304 | return (sum+1.f)*.5f; 305 | } 306 | 307 | // Wood specific 308 | float Fractal::grain(Point3 p, float amount, float freq) { 309 | p *= freq; 310 | p.z *= .05f; 311 | float g = (fBm(p, 4.f, 2.f, .5f)+1.f)*.5f; 312 | return smooth(g, (1.f-amount), 1.f);; 313 | } 314 | -------------------------------------------------------------------------------- /src/noise.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #include "noise.h" 19 | #include "fractal.h" 20 | 21 | void Noise::alterUVW(Point3& p, int type) { 22 | switch (type) { 23 | case 1: 24 | p.x = sqrt(p.x * p.x + p.y * p.y); 25 | p.y = 0.f; 26 | break; 27 | case 2: 28 | p.x = sqrt(p.x * p.x + p.y * p.y + p.z * p.z); 29 | p.y = 0.f; 30 | p.z = 0.f; 31 | break; 32 | } 33 | } 34 | 35 | float Noise::noise(Point3 p, NoiseParams& np) { 36 | switch (np.noiseFunction) { 37 | case 0: return Perlin::noise(p.x, p.y); 38 | case 1: return Perlin::noise(p.x, p.y, p.z); 39 | case 2: return Perlin::noise(p.x, p.y, p.z, np.phase); 40 | case 3: return Perlin::snoise(p.x, p.y); 41 | case 4: return Perlin::snoise(p.x, p.y, p.z); 42 | case 5: return Perlin::snoise(p.x, p.y, p.z, np.phase); 43 | case 6: return worleyWrapper(p, np); 44 | default: return 0.0f; 45 | } 46 | } 47 | 48 | float Noise::noise(Point3 p, float d, NoiseParams& np) { 49 | switch (np.noiseFunction) { 50 | case 0: return Perlin::fnoise2D(p.x, p.y, d); 51 | case 1: return Perlin::fnoise3D(p.x, p.y, p.z, d); 52 | case 2: return Perlin::fnoise4D(p.x, p.y, p.z, np.phase, d); 53 | case 3: return Perlin::fsnoise2D(p.x, p.y, d); 54 | case 4: return Perlin::fsnoise3D(p.x, p.y, p.z, d); 55 | case 5: return Perlin::fsnoise4D(p.x, p.y, p.z, np.phase, d); 56 | case 6: return worleyWrapper(p, np); 57 | default: return 0.0f; 58 | } 59 | } 60 | 61 | float Noise::worleyWrapper(Point3 p, NoiseParams& np) { 62 | float val; 63 | double p3[3] = {(double)p.x, (double)p.y, (double)p.z}; 64 | double f[4]; 65 | int order = 1; 66 | // Calc order 67 | if (np.F4 > 0.0001f || np.F4 < -0.0001f) 68 | order = 4; 69 | else if (np.F3 > 0.0001f || np.F3 < -0.0001f) 70 | order = 3; 71 | else if (np.F2 > 0.0001f || np.F2 < -0.0001f) 72 | order = 2; 73 | // Worley 74 | Worley::noise(p3, order, f, np.worleyFunction); 75 | // Return value 76 | switch (order) { 77 | case 1: val = (float)f[0]*np.F1; break; 78 | case 2: val = (float)f[0]*np.F1 + (float)f[1]*np.F2; break; 79 | case 3: val = (float)f[0]*np.F1 + (float)f[1]*np.F2 + (float)f[2]*np.F3; break; 80 | case 4: val = (float)f[0]*np.F1 + (float)f[1]*np.F2 + (float)f[2]*np.F3 + (float)f[3]*np.F4; break; 81 | default: val = 0.0f; 82 | } 83 | val = val/np.spread*2.f-1.f; 84 | return val; 85 | } 86 | 87 | float Noise::wood(Point3 p, Point3 &g, WoodParam &wp) { 88 | // Radial noise 89 | p.x += Perlin::snoise(p.x*wp.radialFreq, p.y*wp.radialFreq, p.z*wp.radialZ, wp.randSeed-1.125f) * wp.radialStr; 90 | p.y += Perlin::snoise(p.x*wp.radialFreq, p.y*wp.radialFreq, p.z*wp.radialZ, wp.randSeed+1.125f) * wp.radialStr; 91 | g = p; // Store radial component for gain 92 | // Trunk wobble 93 | float angle = Perlin::snoise(p.z*wp.trunkFreq, wp.randSeed+3.f) * (float)pi; // Offset so we dont get the same value as below 94 | p += Point3(cos(angle), sin(angle), 0.f) * Perlin::snoise(p.z*wp.trunkFreq, wp.randSeed-5.5f) * wp.trunkStr; 95 | g = .5f*g + .5f*p; // We don't want trunk wobble to affect too much to grain 96 | // Distance 97 | float dist = 0.f; 98 | switch (wp.woodType) { 99 | case 0: dist = sqrt(p.x*p.x+p.y*p.y); break; 100 | case 1: p*=.05f; dist = (Perlin::noise(p.x, p.y, p.z, wp.randSeed-7.1f)+1.f) / .5f * 15.f; break; 101 | case 2: p*=.05f; dist = (Perlin::snoise(p.x, p.y, p.z, wp.randSeed+3.15f)+1.f) / .5f * 15.f; break; 102 | case 3: dist = p.x<0.f?-p.x:p.x; break; 103 | } 104 | // Width variation 105 | dist += Perlin::snoise(dist+wp.randSeed*2.f) * wp.widthVar; 106 | // Angular noise 107 | float d = dist; 108 | if (d > wp.angleRad) d = wp.angleRad; 109 | dist += smooth(d/wp.angleRad) * Perlin::noise(p.x*wp.angleFreq, p.y*wp.angleFreq, p.z*wp.angleFreq*.5f, wp.randSeed+10.6f) * wp.angleStr; 110 | // Mod 111 | float ipart = (float)(int)dist; 112 | dist -= ipart; 113 | // Skew 114 | if (dist < wp.skew) 115 | dist *= .5f / wp.skew; 116 | else 117 | dist = dist * .5f / (1.f-wp.skew) - wp.skew * (.5f/(1.f-wp.skew)) + .5f; 118 | // Reverse 119 | dist *= 2.f; 120 | if (dist > 1.f) 121 | dist = 2.f-dist; 122 | // Smooth and scale 123 | dist = smooth(dist, wp.lowTresh, wp.highTresh); 124 | // Gain variation 125 | float gain = (Perlin::snoise((ipart + wp.randSeed) * 314.134f) + 1.f) * .5f; 126 | dist *= (1.f-wp.gainVar) + gain * wp.gainVar; 127 | // Return 128 | return dist; 129 | } 130 | 131 | /* 132 | This version super samples the mod function to avoid aliasing 133 | Filtered versions of Noises are used, meaning they fade out once their frequency is too high compared to sampled area 134 | Noises are also asumed constant in the sampled area, meaning they are not super sampled, just calculated once and filtered 135 | With the optimizations above this filtered version shouldn't result in any significan performance loss 136 | 137 | 2 x Filtered 4D Simplex 138 | 2 x Filtered 2D Simplex 139 | 1 x Filtered 4D Perlin 140 | samples x samples x 2 x 1D Simplex 141 | */ 142 | 143 | float Noise::wood(Point3 p, Point3 dPdx, Point3 dPdy, Point3 &g, WoodParam wp) { 144 | // Filtered noises are only intrested in maximum change in X, Y and Z axis. 145 | float lx = dPdx.Length(); 146 | float ly = dPdy.Length(); 147 | float filter = MAX(lx, ly); 148 | // Radial noise 149 | p.x += Perlin::fsnoise4D(p.x*wp.radialFreq, p.y*wp.radialFreq, p.z*wp.radialZ, wp.randSeed-1.125f, filter*wp.radialFreq) * wp.radialStr; 150 | p.y += Perlin::fsnoise4D(p.x*wp.radialFreq, p.y*wp.radialFreq, p.z*wp.radialZ, wp.randSeed+1.125f, filter*wp.radialFreq) * wp.radialStr; 151 | g = p; // Store radial component for gain 152 | // Trunk wobble 153 | float angle = Perlin::fsnoise2D(p.z*wp.trunkFreq, wp.randSeed+3.f, filter*wp.trunkFreq) * (float)pi; 154 | p += Point3(cos(angle), sin(angle), 0.f) * Perlin::fsnoise2D(p.z*wp.trunkFreq, wp.randSeed-5.5f, filter*wp.trunkFreq) * wp.trunkStr; 155 | g = .5f*g + .5f*p; // We don't want trunk wobble to affect too much to grain 156 | // Angular noise (applied inside super sampled code, but not dependant on it) 157 | float angNoise = Perlin::fnoise4D(p.x*wp.angleFreq, p.y*wp.angleFreq, p.z*wp.angleFreq*.5f, wp.randSeed+10.6f, filter*wp.angleFreq); 158 | // Super sampling the mod function and functions dependant on it starts here 159 | float samplesf = (float)wp.samples; 160 | float total = 0.f; 161 | Point3 fp = p - dPdx * .5f - dPdy * .5f; 162 | for (int i=0; i wp.angleRad) d = wp.angleRad; 178 | dist += SMOOTH(d/wp.angleRad) * angNoise * wp.angleStr; 179 | // Mod 180 | float ipart = (float)(int)dist; 181 | dist -= ipart; 182 | // Skew 183 | if (dist < wp.skew) 184 | dist *= .5f / wp.skew; 185 | else 186 | dist = dist * .5f / (1.f-wp.skew) - wp.skew * (.5f/(1.f-wp.skew)) + .5f; 187 | // Reverse 188 | dist *= 2.f; 189 | if (dist > 1.f) 190 | dist = 2.f - dist; 191 | // Smooth and scale 192 | dist = smooth(dist, wp.lowTresh, wp.highTresh); 193 | // Gain variation 194 | float gain = (Perlin::snoise((ipart + wp.randSeed) * 314.134f) + 1.f) * .5f; // Again we need FAST random function, in this case it doesn't have to be continous 195 | dist *= (1.f-wp.gainVar) + gain * wp.gainVar; 196 | // Add to total value 197 | total += dist; 198 | } 199 | // Return final value, just need to divide sum with number of samples taken 200 | return total / (float)(wp.samples * wp.samples); 201 | } 202 | 203 | float Noise::limitedNoise(Point3 p, NoiseParams &np) { 204 | float res = Fractal::f(p, np); 205 | if (np.low 1) return 1.0f; 208 | return res; 209 | } 210 | 211 | float Noise::limitedNoise(Point3 p, Point3 dpdx, Point3 dpdy, NoiseParams &np) { 212 | float lx = dpdx.Length(); 213 | float ly = dpdy.Length(); 214 | lx = MAX(lx, ly); 215 | float res = Fractal::f(p, lx, np); 216 | if (np.low 1) return 1.0f; 219 | return res; 220 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. -------------------------------------------------------------------------------- /src/BerconCommon.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #include "BerconCommon.h" 19 | #include "chkmtlapi.h" 20 | 21 | //BerconCommon is referenced by all the maps. This lets the DLL handler know which map we're in. 22 | //We match the map description to the ID specified in the header file and the DLLEntry.cpp file 23 | TCHAR *GetString(int id) { 24 | static TCHAR buf[256]; 25 | 26 | if (hInstance) 27 | return LoadString(hInstance, id, buf, sizeof(buf)) ? buf : NULL; 28 | return NULL; 29 | } 30 | 31 | void BerconXYZ::reset(IParamBlock2* pblock, Interval& ivalid, int type, int x, int y, int z) { 32 | if (!pblock) return; 33 | //if (!pblock->GetMap()) return; 34 | 35 | TimeValue t = GetCOREInterface()->GetTime(); 36 | 37 | pblockSetValue(xyz_offset_x, 0.f); 38 | pblockSetValue(xyz_offset_y, 0.f); 39 | pblockSetValue(xyz_offset_z, 0.f); 40 | pblockSetValue(xyz_size_x, 1.f); 41 | pblockSetValue(xyz_size_y, 1.f); 42 | pblockSetValue(xyz_size_z, 1.f); 43 | pblockSetValue(xyz_angle_x, 0.f); 44 | pblockSetValue(xyz_angle_y, 0.f); 45 | pblockSetValue(xyz_angle_z, 0.f); 46 | 47 | pblockSetValue(xyz_offset_x2, 0.f); 48 | pblockSetValue(xyz_offset_y2, 0.f); 49 | pblockSetValue(xyz_offset_z2, 0.f); 50 | pblockSetValue(xyz_size_x2, 0.f); 51 | pblockSetValue(xyz_size_y2, 0.f); 52 | pblockSetValue(xyz_size_z2, 0.f); 53 | pblockSetValue(xyz_angle_x2, 0.f); 54 | pblockSetValue(xyz_angle_y2, 0.f); 55 | pblockSetValue(xyz_angle_z2, 0.f); 56 | 57 | pblockSetValue(xyz_tile_x, x); 58 | pblockSetValue(xyz_tile_y, y); 59 | pblockSetValue(xyz_tile_z, z); 60 | 61 | pblockSetValue(xyz_seed, 12345); 62 | pblockSetValue(xyz_rand_obj, TRUE); 63 | pblockSetValue(xyz_rand_mat, FALSE); 64 | pblockSetValue(xyz_rand_par, FALSE); 65 | 66 | pblockSetValue(xyz_map, type); 67 | pblockSetValue(xyz_chan, 1); 68 | 69 | pblockSetValue(xyz_lock, TRUE); 70 | 71 | pblockSetValue(xyz_filtering, 1.f); 72 | 73 | ivalid.SetEmpty(); 74 | } 75 | 76 | void BerconXYZ::update(IParamBlock2* pblock, TimeValue t, Interval& ivalid) { 77 | if (!pblock) return; 78 | //if (!pblock->GetMap()) return; 79 | 80 | pblockGetValue(xyz_offset_x, offX); 81 | pblockGetValue(xyz_offset_y, offY); 82 | pblockGetValue(xyz_offset_z, offZ); 83 | pblockGetValue(xyz_size_x, sizeX); 84 | pblockGetValue(xyz_size_y, sizeY); 85 | pblockGetValue(xyz_size_z, sizeZ); 86 | pblockGetValue(xyz_angle_x, angX); 87 | pblockGetValue(xyz_angle_y, angY); 88 | pblockGetValue(xyz_angle_z, angZ); 89 | 90 | pblockGetValue(xyz_offset_x2, offX2); 91 | pblockGetValue(xyz_offset_y2, offY2); 92 | pblockGetValue(xyz_offset_z2, offZ2); 93 | pblockGetValue(xyz_size_x2, sizeX2); 94 | pblockGetValue(xyz_size_y2, sizeY2); 95 | pblockGetValue(xyz_size_z2, sizeZ2); 96 | pblockGetValue(xyz_angle_x2, angX2); 97 | pblockGetValue(xyz_angle_y2, angY2); 98 | pblockGetValue(xyz_angle_z2, angZ2); 99 | 100 | pblockGetValue(xyz_tile_x, tileX); 101 | pblockGetValue(xyz_tile_y, tileY); 102 | pblockGetValue(xyz_tile_z, tileZ); 103 | 104 | pblockGetValue(xyz_seed, p_seed); 105 | pblockGetValue(xyz_rand_obj, p_randObj); 106 | pblockGetValue(xyz_rand_mat, p_randMat); 107 | pblockGetValue(xyz_rand_par, p_randPar); 108 | 109 | pblockGetValue(xyz_map, mappingType); 110 | pblockGetValue(xyz_chan, mappingChannel); 111 | 112 | pblockGetValue(xyz_lock, lock); 113 | 114 | pblockGetValue(xyz_filtering, filtering); 115 | 116 | //Override the spinner control's minval because we don't want tiling scale to be zero 117 | if (sizeX == 0.f) { 118 | pblockSetValue(xyz_size_x, 0.001f); 119 | } 120 | if (sizeY == 0.f) { 121 | pblockSetValue(xyz_size_y, 0.001f); 122 | } 123 | if (sizeZ == 0.f) { 124 | pblockSetValue(xyz_size_z, 0.001f); 125 | } 126 | 127 | angX *= DEG_TO_RAD; angY *= DEG_TO_RAD; angZ *= DEG_TO_RAD; 128 | angX2 *= DEG_TO_RAD; angY2 *= DEG_TO_RAD; angZ2 *= DEG_TO_RAD; 129 | 130 | EnableStuff(pblock, t); 131 | update(); 132 | } 133 | 134 | void BerconXYZ::EnableStuff(IParamBlock2* pblock, TimeValue t) { 135 | if (pblock) { 136 | IParamMap2 *map = pblock->GetMap(); 137 | if (map) { 138 | map->Enable(xyz_size_y2, !lock); 139 | map->Enable(xyz_size_z2, !lock); 140 | 141 | bool s = mappingType==0; // || mappingType==1; 142 | map->Enable(xyz_tile_x, s); 143 | map->Enable(xyz_tile_y, s); 144 | map->Enable(xyz_tile_z, s); 145 | 146 | int type = isRealworld(); 147 | 148 | setSpinnerType(map, t, xyz_offset_x, IDC_OFF_X, IDC_OFF_X_SPIN, type, true); 149 | setSpinnerType(map, t, xyz_offset_y, IDC_OFF_Y, IDC_OFF_Y_SPIN, type, true); 150 | setSpinnerType(map, t, xyz_offset_z, IDC_OFF_Z, IDC_OFF_Z_SPIN, type, true); 151 | setSpinnerType(map, t, xyz_size_x, IDC_SIZ_X, IDC_SIZ_X_SPIN, type); 152 | setSpinnerType(map, t, xyz_size_y, IDC_SIZ_Y, IDC_SIZ_Y_SPIN, type); 153 | setSpinnerType(map, t, xyz_size_z, IDC_SIZ_Z, IDC_SIZ_Z_SPIN, type); 154 | setSpinnerType(map, t, xyz_offset_x2, IDC_OFF_X2, IDC_OFF_X_SPIN2, type); 155 | setSpinnerType(map, t, xyz_offset_y2, IDC_OFF_Y2, IDC_OFF_Y_SPIN2, type); 156 | setSpinnerType(map, t, xyz_offset_z2, IDC_OFF_Z2, IDC_OFF_Z_SPIN2, type); 157 | setSpinnerType(map, t, xyz_size_x2, IDC_SIZ_X2, IDC_SIZ_X_SPIN2, type); 158 | setSpinnerType(map, t, xyz_size_y2, IDC_SIZ_Y2, IDC_SIZ_Y_SPIN2, type); 159 | setSpinnerType(map, t, xyz_size_z2, IDC_SIZ_Z2, IDC_SIZ_Z_SPIN2, type); 160 | } 161 | } 162 | } 163 | 164 | void BerconXYZ::getBasis(Matrix3 transform, Point3* b) { 165 | if (mappingType==4&&mode2D) { 166 | Matrix3 temp = transform; 167 | temp.Invert(); 168 | b[0] = Normalize(temp.GetRow(0)); 169 | b[1] = Normalize(temp.GetRow(1)); 170 | b[2] = Normalize(temp.GetRow(2)); 171 | } else { 172 | b[0] = Normalize(transform.GetRow(0)); 173 | b[1] = Normalize(transform.GetRow(1)); 174 | b[2] = Normalize(transform.GetRow(2)); 175 | } 176 | } 177 | 178 | #define NZERO(x) (x > 0.0001f) 179 | void BerconXYZ::update() { 180 | tm.IdentityMatrix(); 181 | tm.Translate(Point3(offX, offY, offZ)); 182 | tm.RotateX(angX); 183 | tm.RotateY(angY); 184 | tm.RotateZ(angZ); 185 | 186 | invNoScaleTm = tm; 187 | invNoScaleTm.Invert(); 188 | 189 | tm.Scale(Point3(1.f/sizeX, 1.f/sizeY, 1.f/sizeZ)); 190 | 191 | getBasis(tm, b); 192 | 193 | variance = NZERO(offX2) || NZERO(offY2) || NZERO(offZ2) || NZERO(sizeX2) || NZERO(sizeY2) || NZERO(sizeZ2) || NZERO(angX2) || NZERO(angY2) || NZERO(angZ2); 194 | } 195 | 196 | Matrix3 BerconXYZ::random(ShadeContext& sc, Matrix3* inv) { 197 | seedRandomGen(sc); 198 | 199 | Matrix3 transform; 200 | transform.IdentityMatrix(); 201 | transform.Translate(Point3(offX+offX2*URANDF(), offY+offY2*URANDF(), offZ+offZ2*URANDF())); 202 | transform.RotateX(angX+angX2*URANDF()); 203 | transform.RotateY(angY+angY2*URANDF()); 204 | transform.RotateZ(angZ+angZ2*URANDF()); 205 | 206 | if (inv) { 207 | *inv = transform; 208 | inv->Invert(); 209 | } 210 | 211 | Point3 scale; 212 | if (lock) { 213 | float add = sizeX2*URANDF(); 214 | scale = Point3(sizeX+add, sizeY+add, sizeZ+add); 215 | } else { 216 | scale = Point3(sizeX+sizeX2*URANDF(), sizeY+sizeY2*URANDF(), sizeZ+sizeZ2*URANDF()); 217 | } 218 | if (scale.x < 0.0001f) scale.x = 0.0001f; 219 | if (scale.y < 0.0001f) scale.y = 0.0001f; 220 | if (scale.z < 0.0001f) scale.z = 0.0001f; 221 | scale.x = 1.f/scale.x; scale.y = 1.f/scale.y; scale.z = 1.f/scale.z; 222 | transform.Scale(scale); 223 | 224 | return transform; 225 | } 226 | 227 | // Random by Material, Object or Particle 228 | void BerconXYZ::seedRandomGen(ShadeContext& sc) { 229 | int seed = 1; 230 | 231 | if (p_randMat) { 232 | seed += sc.mtlNum; 233 | } 234 | if (p_randObj) { 235 | INode *node=sc.Node(); 236 | if (node) { 237 | int hand = (int) node->GetHandle(); 238 | seed += hand*(hand*hand*15731 + 789221); 239 | } 240 | } 241 | if (p_randPar) { 242 | Object *ob = sc.GetEvalObject(); 243 | if (ob && ob->IsParticleSystem()) { 244 | ParticleObject *obj = (ParticleObject*)ob; 245 | IChkMtlAPI* chkMtlAPI = static_cast(obj->GetInterface(I_NEWMTLINTERFACE)); 246 | if ((chkMtlAPI && chkMtlAPI->SupportsParticleIDbyFace())) { 247 | int id = chkMtlAPI->GetParticleFromFace(sc.FaceNumber()); 248 | seed += id*(id*id*571 + 789221); 249 | } 250 | } 251 | } 252 | 253 | seed *= p_seed; 254 | srand(seed*(seed*seed*15731 + 789221)); 255 | } 256 | 257 | //Continue, Stretch, Tile, Mirror, None 258 | inline static int tiling(int type, float& x) { 259 | switch (type) { 260 | //case 0 is "Continue" 261 | case 1: {D_STRE(x) return TRUE;} 262 | case 2: {D_LOOP(x) return TRUE;} 263 | case 3: {D_MIRR(x) return TRUE;} 264 | case 4: {if (x<0||x>1) return FALSE;} 265 | } 266 | return TRUE; 267 | } 268 | 269 | inline static int tiling(int type, float& x, int& flips) { 270 | switch (type) { 271 | case 1: {D_STRE(x) return TRUE;} 272 | case 2: {D_LOOP(x) return TRUE;} 273 | case 3: { 274 | if (x<0) x = -x; 275 | int ix = (int)x; 276 | if (ix%2==0) x = x - ix; 277 | else { x = 1.f - x + ix; flips = 1; } 278 | return TRUE; 279 | } 280 | case 4: {if (x<0||x>1) return FALSE;} 281 | } 282 | return TRUE; 283 | } 284 | 285 | #define OFFSET_5 Point3(0.5f, 0.5f, 0.f) 286 | 287 | // COORD_REF menu and UVWgen for render or Realistic Maps mode 288 | int BerconXYZ::get(ShadeContext& sc, Point3& p, Point3& dpdx, Point3& dpdy, Matrix3 transform, int* flips) { 289 | 290 | switch (mappingType) { 291 | case 0: // Explicit Map 2D 292 | p = transform * (sc.UVW(mappingChannel) - OFFSET_5) + OFFSET_5; 293 | { 294 | Point3 duvw = VectorTransform(transform, sc.DUVW(mappingChannel)); 295 | dpdx = Point3(duvw.x, 0.f, 0.f); 296 | dpdy = Point3(0.f, duvw.y, 0.f); 297 | } 298 | if (flips) { if (!tiling(tileX, p.x, flips[0])) return FALSE; } 299 | else { if (!tiling(tileX, p.x)) return FALSE; } 300 | if (flips) { if (!tiling(tileY, p.y, flips[1])) return FALSE; } 301 | else { if (!tiling(tileY, p.y)) return FALSE; } 302 | if (flips) { if (!tiling(tileZ, p.z, flips[2])) return FALSE; } 303 | else { if (!tiling(tileZ, p.z)) return FALSE; } 304 | dpdx = dpdx * filtering; dpdy = dpdy * filtering; 305 | break; 306 | case 1: // Explicit Map 2D Real World 307 | p = transform * sc.UVW(mappingChannel); 308 | { 309 | Point3 duvw = VectorTransform(transform, sc.DUVW(mappingChannel)); 310 | dpdx = Point3(duvw.x, 0.f, 0.f); 311 | dpdy = Point3(0.f, duvw.y, 0.f); 312 | } 313 | dpdx = dpdx * filtering; dpdy = dpdy * filtering; 314 | break; 315 | case 2: // Object XYZ 316 | p = transform * sc.PointTo(sc.P(), REF_OBJECT); 317 | sc.DP(dpdx, dpdy); 318 | dpdx = VectorTransform(transform, sc.VectorTo(dpdx, REF_OBJECT)); 319 | dpdy = VectorTransform(transform, sc.VectorTo(dpdy, REF_OBJECT)); 320 | dpdx = dpdx * filtering; dpdy = dpdy * filtering; 321 | break; 322 | case 3: // World XYZ 323 | p = transform * sc.PointTo(sc.P(),REF_WORLD); 324 | sc.DP(dpdx, dpdy); 325 | dpdx = VectorTransform(transform, sc.VectorTo(dpdx, REF_WORLD)); 326 | dpdy = VectorTransform(transform, sc.VectorTo(dpdy, REF_WORLD)); 327 | dpdx = dpdx * filtering; dpdy = dpdy * filtering; 328 | break; 329 | case 4: // Screen (2d mode) 330 | Point2 uv, duv; 331 | sc.ScreenUV(uv, duv); 332 | p = transform * Point3(uv.x, uv.y, 0.f); 333 | dpdx = VectorTransform(transform, Point3(duv.x, 0.f, 0.f)); 334 | dpdy = VectorTransform(transform, Point3(0.f, duv.y, 0.f)); 335 | dpdx = dpdx * filtering; dpdy = dpdy * filtering; 336 | break; 337 | } 338 | return TRUE; 339 | } 340 | 341 | // COORD_REF menu and UVWgen for Shaded Maps mode 342 | int BerconXYZ::get(ShadeContext& sc, Point3& p, Matrix3 transform, int* flips) { 343 | switch (mappingType) { 344 | case 0: 345 | p = transform * (sc.UVW(mappingChannel) - OFFSET_5) + OFFSET_5; 346 | if (flips) { if (!tiling(tileX, p.x, flips[0])) return FALSE; } 347 | else { if (!tiling(tileX, p.x)) return FALSE; } 348 | if (flips) { if (!tiling(tileY, p.y, flips[1])) return FALSE; } 349 | else { if (!tiling(tileY, p.y)) return FALSE; } 350 | if (flips) { if (!tiling(tileZ, p.z, flips[2])) return FALSE; } 351 | else { if (!tiling(tileZ, p.z)) return FALSE; } 352 | break; 353 | case 1: 354 | p = transform * sc.UVW(mappingChannel); 355 | break; 356 | case 2: 357 | p = transform * sc.PointTo(sc.P(),REF_OBJECT); 358 | break; 359 | case 3: 360 | p = transform * sc.PointTo(sc.P(),REF_WORLD); 361 | break; 362 | case 4: 363 | Point2 uv, duv; 364 | sc.ScreenUV(uv, duv); 365 | p = transform * Point3(uv.x, uv.y, 0.f); 366 | break; 367 | } 368 | return TRUE; 369 | } 370 | 371 | // A random variation is set and we're rendering or in Realistic Maps mode 372 | int BerconXYZ::get(ShadeContext& sc, Point3& p, Point3& dpdx, Point3& dpdy) { 373 | return get(sc, p, dpdx, dpdy, variance?random(sc):tm); 374 | } 375 | 376 | // A random variation is set and we're in Shaded Materials mode 377 | int BerconXYZ::get(ShadeContext& sc, Point3& p) { 378 | return get(sc, p, variance?random(sc):tm); 379 | } 380 | 381 | // Map is in a bump map slot and we're rendering or in a Realistic Maps mode 382 | int BerconXYZ::get(ShadeContext& sc, Point3& p, Point3& dpdx, Point3& dpdy, Point3* basis) { 383 | 384 | if ((mappingType == 0 || mappingType == 1) && mode2D) { 385 | Matrix3 inv; 386 | Matrix3 transform = variance?random(sc, &inv):tm; 387 | if (!variance) inv = invNoScaleTm; 388 | 389 | if (!get(sc, p, dpdx, dpdy, transform)) {return FALSE;} 390 | Point3 dp[3]; 391 | 392 | if (sc.BumpBasisVectors(dp, AXIS_UV, mappingChannel)) { 393 | basis[0] = VectorTransform(inv, dp[0]); 394 | basis[1] = VectorTransform(inv, dp[1]); 395 | basis[2] = VectorTransform(inv, dp[0]^dp[1]); 396 | } else { 397 | sc.DPdUVW(dp, mappingChannel); 398 | transform.Invert(); 399 | basis[0] = VectorTransform(inv, dp[0]); 400 | basis[1] = VectorTransform(inv, dp[1]); 401 | basis[2] = VectorTransform(inv, dp[2]); 402 | } 403 | } else { 404 | Matrix3 transform = variance?random(sc):tm; 405 | if (!get(sc, p, dpdx, dpdy, transform)) {return FALSE;} 406 | if (variance) 407 | getBasis(transform, basis); 408 | else 409 | for (int i=0; i<3; i++) 410 | basis[i] = b[i]; 411 | } 412 | return TRUE; 413 | } 414 | 415 | // Map is in a bump map slot and we're in Shaded Materials mode 416 | int BerconXYZ::get(ShadeContext& sc, Point3& p, Point3* basis) { 417 | /*int* flips = NULL; 418 | if (mappingType == 0) { 419 | flips = new int[3]; 420 | flips[0]=0;flips[1]=0;flips[2]=0; 421 | }*/ 422 | 423 | // BerconGradient + BerconTile are 2D maps, mode2D = TRUE 424 | if ((mappingType == 0 || mappingType == 1) && mode2D) { 425 | Matrix3 inv; 426 | Matrix3 transform = variance?random(sc, &inv):tm; 427 | if (!variance) inv = invNoScaleTm; 428 | 429 | if (!get(sc, p, transform)) {return FALSE;} 430 | Point3 dp[3]; 431 | 432 | if (sc.BumpBasisVectors(dp, AXIS_UV, mappingChannel)) { 433 | basis[0] = VectorTransform(inv, dp[0]); 434 | basis[1] = VectorTransform(inv, dp[1]); 435 | basis[2] = VectorTransform(inv, dp[0]^dp[1]); 436 | } else { 437 | sc.DPdUVW(dp, mappingChannel); 438 | transform.Invert(); 439 | basis[0] = VectorTransform(inv, dp[0]); 440 | basis[1] = VectorTransform(inv, dp[1]); 441 | basis[2] = VectorTransform(inv, dp[2]); 442 | } 443 | 444 | } else { 445 | Matrix3 transform = variance?random(sc):tm; 446 | if (!get(sc, p, transform)) {return FALSE;} 447 | if (variance) 448 | getBasis(transform, basis); 449 | else 450 | for (int i=0; i<3; i++) 451 | basis[i] = b[i]; 452 | } 453 | 454 | return TRUE; 455 | } 456 | 457 | //CharStream *out = thread_local(current_stdout); 458 | //out->printf("Val: %d\n", mappingChannel); -------------------------------------------------------------------------------- /src/perlin.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | // Based on Ken Perlin's perlin noise/simplex and Stefan Gustavson's 19 | // implementation of perlin/simplex noise, (Simplex)Noise1234 20 | 21 | #include "perlin.h" 22 | 23 | // Chart given by Ken Perlin, using the same to get identical results 24 | static unsigned char perm[] = { 25 | 151,160,137,91,90,15, 26 | 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 27 | 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 28 | 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 29 | 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 30 | 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 31 | 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 32 | 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 33 | 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 34 | 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 35 | 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 36 | 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 37 | 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, 38 | 151,160,137,91,90,15, 39 | 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 40 | 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 41 | 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 42 | 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 43 | 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 44 | 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 45 | 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 46 | 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 47 | 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 48 | 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 49 | 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 50 | 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 51 | }; 52 | 53 | static unsigned char simplex[64][4] = { 54 | {0,1,2,3},{0,1,3,2},{0,0,0,0},{0,2,3,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,2,3,0}, 55 | {0,2,1,3},{0,0,0,0},{0,3,1,2},{0,3,2,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,3,2,0}, 56 | {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, 57 | {1,2,0,3},{0,0,0,0},{1,3,0,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,3,0,1},{2,3,1,0}, 58 | {1,0,2,3},{1,0,3,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,0,3,1},{0,0,0,0},{2,1,3,0}, 59 | {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, 60 | {2,0,1,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,0,1,2},{3,0,2,1},{0,0,0,0},{3,1,2,0}, 61 | {2,1,0,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,1,0,2},{0,0,0,0},{3,2,0,1},{3,2,1,0}}; 62 | 63 | float lerp2(float t, float a,float b) {return a+t*(b-a);} 64 | 65 | // #################### // Gradients \\ #################### 66 | 67 | float Perlin::grad( int hash, float x ) { 68 | int h = hash & 15; 69 | float grad = 1.0f + (h & 7); 70 | if (h&8) grad = -grad; 71 | return ( grad * x ); 72 | } 73 | 74 | float Perlin::grad(int hash, float x, float y) { 75 | int h = hash & 7; 76 | float i = h<4 ? x : y; 77 | float j = h<4 ? y : x; 78 | return ((h&1)? -i : i) + ((h&2)? -2.f*j : 2.f*j); 79 | } 80 | 81 | float Perlin::grad(int hash, float x, float y, float z) { 82 | int h = hash & 15; 83 | float i = h<8 ? x : y; 84 | float j = h<4 ? y : h==12||h==14 ? x : z; 85 | return ((h&1) ? -i : i) + ((h&2) ? -j : j); 86 | } 87 | 88 | float Perlin::grad(int hash, float x, float y, float z, float w) { 89 | int h = hash & 31; 90 | float i = h<24 ? x : y; 91 | float j = h<16 ? y : z; 92 | float k = h<8 ? z : w; 93 | return ((h&1)? -i : i) + ((h&2)? -j : j) + ((h&4)? -k : k); 94 | } 95 | 96 | // #################### // Perlin \\ #################### 97 | 98 | float Perlin::noise(float x) { 99 | int ix0 = FASTFLOOR(x); 100 | int ix1 = (ix0+1) & 255; 101 | float xf0 = x - ix0; 102 | float xf1 = xf0 - 1.0f; 103 | ix0 = ix0 & 0xff; // Wrap to 0..255 104 | float s = FADE(xf0); 105 | return lerp2(s, grad(perm[ix0], xf0), 106 | grad(perm[ix1], xf1)) * 0.188f; 107 | } 108 | 109 | float Perlin::noise(float x, float y) { 110 | int xi = FASTFLOOR(x); 111 | int yi = FASTFLOOR(y); 112 | float xf0 = x - xi; 113 | float yf0 = y - yi; 114 | float xf1 = xf0 - 1.0f; 115 | float yf1 = yf0 - 1.0f; 116 | xi = xi & 255; 117 | yi = yi & 255; 118 | float i = FADE(xf0); 119 | float j = FADE(yf0); 120 | int A = perm[xi ] + yi; 121 | int B = perm[xi+1] + yi; 122 | 123 | return lerp2(j, lerp2(i, grad(perm[A ], xf0, yf0), 124 | grad(perm[B ], xf1, yf0)), 125 | lerp2(i, grad(perm[A+1], xf0, yf1), 126 | grad(perm[B+1], xf1, yf1))) * 0.507f; 127 | } 128 | 129 | float Perlin::noise(float x, float y, float z) { 130 | int xi = FASTFLOOR(x); 131 | int yi = FASTFLOOR(y); 132 | int zi = FASTFLOOR(z); 133 | float xf = x - (float)xi; 134 | float yf = y - (float)yi; 135 | float zf = z - (float)zi; 136 | xi = xi & 255; 137 | yi = yi & 255; 138 | zi = zi & 255; 139 | float i = FADE(xf); 140 | float j = FADE(yf); 141 | float k = FADE(zf); 142 | int A = perm[xi ]+yi, AA = perm[A]+zi, AB = perm[A+1]+zi; 143 | int B = perm[xi+1]+yi, BA = perm[B]+zi, BB = perm[B+1]+zi; 144 | 145 | return lerp2(k, lerp2(j, lerp2(i, grad(perm[AA ], xf , yf , zf ), 146 | grad(perm[BA ], xf-1, yf , zf )), 147 | lerp2(i, grad(perm[AB ], xf , yf-1, zf ), 148 | grad(perm[BB ], xf-1, yf-1, zf ))), 149 | lerp2(j, lerp2(i, grad(perm[AA+1], xf , yf , zf-1 ), 150 | grad(perm[BA+1], xf-1, yf , zf-1 )), 151 | lerp2(i, grad(perm[AB+1], xf , yf-1, zf-1 ), 152 | grad(perm[BB+1], xf-1, yf-1, zf-1 )))) * 0.936f; 153 | } 154 | 155 | float Perlin::noise(float x, float y, float z, float w) { 156 | int xi = FASTFLOOR(x); 157 | int yi = FASTFLOOR(y); 158 | int zi = FASTFLOOR(z); 159 | int wi = FASTFLOOR(w); 160 | float xf0 = x - xi; 161 | float yf0 = y - yi; 162 | float zf0 = z - zi; 163 | float wf0 = w - wi; 164 | float xf1 = xf0 - 1.0f; 165 | float yf1 = yf0 - 1.0f; 166 | float zf1 = zf0 - 1.0f; 167 | float wf1 = wf0 - 1.0f; 168 | xi = xi & 255; 169 | yi = yi & 255; 170 | zi = zi & 255; 171 | wi = wi & 255; 172 | float i = FADE(xf0); 173 | float j = FADE(yf0); 174 | float k = FADE(zf0); 175 | float l = FADE(wf0); 176 | 177 | int A = perm[xi] +yi, AA = perm[A] +zi, AAA = perm[AA] +wi, 178 | AAB = perm[AA+1]+wi, 179 | AB = perm[A+1]+zi, ABA = perm[AB] +wi, 180 | ABB = perm[AB+1]+wi; 181 | int B = perm[xi+1]+yi, BA = perm[B] +zi, BAA = perm[BA] +wi, 182 | BAB = perm[BA+1]+wi, 183 | BB = perm[B+1]+zi, BBA = perm[BB] +wi, 184 | BBB = perm[BB+1]+wi; 185 | 186 | 187 | float l1 = lerp2(i, grad(perm[AAA ], xf0, yf0, zf0, wf0), grad(perm[BAA ], xf1, yf0, zf0, wf0)); 188 | float l2 = lerp2(i, grad(perm[ABA ], xf0, yf1, zf0, wf0), grad(perm[BBA ], xf1, yf1, zf0, wf0)); 189 | float l3 = lerp2(i, grad(perm[AAB ], xf0, yf0, zf1, wf0), grad(perm[BAB ], xf1, yf0, zf1, wf0)); 190 | float l4 = lerp2(i, grad(perm[ABB ], xf0, yf1, zf1, wf0), grad(perm[BBB ], xf1, yf1, zf1, wf0)); 191 | float l5 = lerp2(i, grad(perm[AAA+1], xf0, yf0, zf0, wf1), grad(perm[BAA+1], xf1, yf0, zf0, wf1)); 192 | float l6 = lerp2(i, grad(perm[ABA+1], xf0, yf1, zf0, wf1), grad(perm[BBA+1], xf1, yf1, zf0, wf1)); 193 | float l7 = lerp2(i, grad(perm[AAB+1], xf0, yf0, zf1, wf1), grad(perm[BAB+1], xf1, yf0, zf1, wf1)); 194 | float l8 = lerp2(i, grad(perm[ABB+1], xf0, yf1, zf1, wf1), grad(perm[BBB+1], xf1, yf1, zf1, wf1)); 195 | 196 | l1 = lerp2(j, l1, l2); 197 | l2 = lerp2(j, l3, l4); 198 | l3 = lerp2(j, l5, l6); 199 | l4 = lerp2(j, l7, l8); 200 | 201 | l1 = lerp2(k, l1, l2); 202 | l2 = lerp2(k, l3, l4); 203 | 204 | return lerp2(l, l1, l2) * 0.87f; 205 | } 206 | 207 | // #################### // Simplex points \\ #################### 208 | 209 | inline float Perlin::point(float x, int i) { 210 | float t = 1.0f - x*x; 211 | t *= t; 212 | return t * t * grad(perm[i & 255], x); 213 | } 214 | 215 | inline float Perlin::point(float x, float y, int i, int j) { 216 | float t = 0.5f - x*x - y*y; 217 | if(t < 0.0f) 218 | return 0.0f; 219 | t *= t; 220 | return t * t * grad(perm[i+perm[j]], x, y); 221 | } 222 | 223 | inline float Perlin::point(float x, float y, float z, int i, int j, int k) { 224 | float t = 0.6f - x*x - y*y - z*z; 225 | if(t < 0.0f) 226 | return 0.0f; 227 | t *= t; 228 | return t * t * grad(perm[i+perm[j+perm[k]]], x, y, z); 229 | } 230 | 231 | inline float Perlin::point(float x, float y, float z, float w, int i, int j, int k, int l) { 232 | float t = 0.6f - x*x - y*y - z*z - w*w; 233 | if(t < 0.0f) 234 | return 0.0f; 235 | t *= t; 236 | return t * t * grad(perm[i+perm[j+perm[k+perm[l]]]], x, y, z, w); 237 | } 238 | 239 | // #################### // Simplex \\ #################### 240 | 241 | float Perlin::snoise(float x) { 242 | int i0 = FASTFLOOR(x); 243 | int i1 = i0 + 1; 244 | float x0 = x - i0; 245 | float x1 = x0 - 1.0f; 246 | return (1.f/2.53125f) * (point(x0, i0) + point(x1, i1)); 247 | } 248 | 249 | float Perlin::snoise(float x, float y) { 250 | 251 | #define F2 0.366025403f // F2 = 0.5*(sqrt(3.0)-1.0) 252 | #define G2 0.211324865f // G2 = (3.0-Math.sqrt(3.0))/6.0 253 | 254 | float s = (x+y)*F2; 255 | float xs = x + s; 256 | float ys = y + s; 257 | int i = FASTFLOOR(xs); 258 | int j = FASTFLOOR(ys); 259 | 260 | float t = (float)(i+j)*G2; 261 | float X0 = i-t; 262 | float Y0 = j-t; 263 | float x0 = x-X0; 264 | float y0 = y-Y0; 265 | 266 | int i1, j1; 267 | if(x0>y0) {i1=1; j1=0;} 268 | else {i1=0; j1=1;} 269 | 270 | float x1 = x0 - i1 + G2, x2 = x0 - 1.0f + 2.0f * G2; 271 | float y1 = y0 - j1 + G2, y2 = y0 - 1.0f + 2.0f * G2; 272 | 273 | int ii = i & 0xff; 274 | int jj = j & 0xff; 275 | 276 | return 40.0f * (point(x0, y0, ii, jj) + 277 | point(x1, y1, ii+i1, jj+j1) + 278 | point(x2, y2, ii+1, jj+1)); 279 | } 280 | 281 | float Perlin::snoise(float x, float y, float z) { 282 | 283 | #define F3 0.333333333f 284 | #define G3 0.166666667f 285 | #define G3a (2.0f * G3) 286 | #define G3b (3.0f * G3 - 1.0f) 287 | 288 | float s = (x+y+z)*F3; 289 | float xs = x+s; 290 | float ys = y+s; 291 | float zs = z+s; 292 | int i = FASTFLOOR(xs); 293 | int j = FASTFLOOR(ys); 294 | int k = FASTFLOOR(zs); 295 | 296 | float t = (float)(i+j+k)*G3; 297 | float X0 = i-t; 298 | float Y0 = j-t; 299 | float Z0 = k-t; 300 | float x0 = x-X0; 301 | float y0 = y-Y0; 302 | float z0 = z-Z0; 303 | 304 | int i1, j1, k1; 305 | int i2, j2, k2; 306 | 307 | if(x0>=y0) { 308 | if(y0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } 309 | else if(x0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } 310 | else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } 311 | } else { 312 | if(y0 y0) ? 32 : 0; 361 | int c2 = (x0 > z0) ? 16 : 0; 362 | int c3 = (y0 > z0) ? 8 : 0; 363 | int c4 = (x0 > w0) ? 4 : 0; 364 | int c5 = (y0 > w0) ? 2 : 0; 365 | int c6 = (z0 > w0) ? 1 : 0; 366 | int c = c1 + c2 + c3 + c4 + c5 + c6; 367 | 368 | int i1, j1, k1, l1; 369 | int i2, j2, k2, l2; 370 | int i3, j3, k3, l3; 371 | 372 | i1 = simplex[c][0]>=3 ? 1 : 0; i2 = simplex[c][0]>=2 ? 1 : 0; i3 = simplex[c][0]>=1 ? 1 : 0; 373 | j1 = simplex[c][1]>=3 ? 1 : 0; j2 = simplex[c][1]>=2 ? 1 : 0; j3 = simplex[c][1]>=1 ? 1 : 0; 374 | k1 = simplex[c][2]>=3 ? 1 : 0; k2 = simplex[c][2]>=2 ? 1 : 0; k3 = simplex[c][2]>=1 ? 1 : 0; 375 | l1 = simplex[c][3]>=3 ? 1 : 0; l2 = simplex[c][3]>=2 ? 1 : 0; l3 = simplex[c][3]>=1 ? 1 : 0; 376 | 377 | float x1 = x0 - i1 + G4, x2 = x0 - i2 + G4a, x3 = x0 - i3 + G4b, x4 = x0 + G4c; 378 | float y1 = y0 - j1 + G4, y2 = y0 - j2 + G4a, y3 = y0 - j3 + G4b, y4 = y0 + G4c; 379 | float z1 = z0 - k1 + G4, z2 = z0 - k2 + G4a, z3 = z0 - k3 + G4b, z4 = z0 + G4c; 380 | float w1 = w0 - l1 + G4, w2 = w0 - l2 + G4a, w3 = w0 - l3 + G4b, w4 = w0 + G4c; 381 | 382 | int ii = i & 0xff; 383 | int jj = j & 0xff; 384 | int kk = k & 0xff; 385 | int ll = l & 0xff; 386 | 387 | return 27.0f * (point(x0, y0, z0, w0, ii, jj, kk, ll) + 388 | point(x1, y1, z1, w1, ii+i1, jj+j1, kk+k1, ll+l1) + 389 | point(x2, y2, z2, w2, ii+i2, jj+j2, kk+k2, ll+l2) + 390 | point(x3, y3, z3, w3, ii+i3, jj+j3, kk+k3, ll+l3) + 391 | point(x4, y4, z4, w4, ii+1, jj+1, kk+1, ll+1)); 392 | } 393 | 394 | /* 395 | Filtered functions, simply add the fading functinality once the size of the sampled 396 | area becomes larger than the details. 397 | */ 398 | 399 | #define FILTDIV 1.2f 400 | #define FILTSTART 1.2f 401 | #define FILTEND 2.2f 402 | 403 | #define FILTER(d) d = smooth(d / FILTDIV, FILTSTART, FILTEND); \ 404 | if (d >= .9999f) return 0.f; 405 | 406 | float Perlin::fnoise2D(float x, float y, float d) { 407 | FILTER(d) 408 | return lerp2(d, noise(x,y), 0.f); 409 | } 410 | 411 | float Perlin::fnoise3D(float x, float y, float z, float d) { 412 | FILTER(d) 413 | return lerp2(d, noise(x,y,z), 0.f); 414 | } 415 | 416 | float Perlin::fnoise4D(float x, float y, float z, float w, float d) { 417 | FILTER(d) 418 | return lerp2(d, noise(x,y,z,w), 0.f); 419 | } 420 | 421 | float Perlin::fsnoise2D(float x, float y, float d) { 422 | FILTER(d) 423 | return lerp2(d, snoise(x,y), 0.f); 424 | } 425 | 426 | float Perlin::fsnoise3D(float x, float y, float z, float d) { 427 | FILTER(d) 428 | return lerp2(d, snoise(x,y,z), 0.f); 429 | } 430 | 431 | float Perlin::fsnoise4D(float x, float y, float z, float w, float d) { 432 | FILTER(d) 433 | return lerp2(d, snoise(x,y,z,w), 0.f); 434 | } -------------------------------------------------------------------------------- /src/GradientRamp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | /* 19 | 20 | #include "Max.h" 21 | #include "resource.h" 22 | #include "plugapi.h" 23 | #include "3dsmaxport.h" 24 | 25 | #include "maxscrpt/MAXScrpt.h"*/ 26 | 27 | #include "GradientRamp.h" 28 | 29 | 30 | void GradientRamp::setHWND(HWND hWnd) { 31 | m_hWnd = hWnd; 32 | RECT rect; 33 | GetWindowRect(m_hWnd, &rect); 34 | width = rect.right - rect.left; 35 | height = rect.bottom - rect.top; 36 | } 37 | 38 | // ############################################################################################# 39 | // #################################/ Paint \################################ 40 | // ############################################################################################# 41 | 42 | void GradientRamp::paint(HDC hDC) { 43 | if (m_hWnd == NULL) return; 44 | //SetBkMode(hDC, TRANSPARENT); 45 | 46 | //RECT rect; 47 | //GetClientRect(m_hWnd, &rect); 48 | 49 | /*SelectObject(hdc,red_pen); 50 | MoveToEx(hdc,10,20,NULL); 51 | LineTo(hdc,10,40,NULL); 52 | LineTo(hdc,50,150,NULL);*/ 53 | /* 54 | int width = rect.right - rect.left; 55 | int height = rect.top - rect.bottom; 56 | 57 | RECT rect2; 58 | GetWindowRect(m_hWnd, &rect2); 59 | 60 | CharStream *out = thread_local(current_stdout); 61 | out->printf("Rectangle: %d %d %d %d\n", rect.left, rect.right, rect.top, rect.bottom); 62 | out->printf("Rectangle2: %d %d %d %d\n", (int)(rect2.left, (int)(rect2.right), (int)(rect2.top), (int)(rect2.bottom)); 63 | */ 64 | 65 | HDC tempHDC = CreateCompatibleDC(hDC); 66 | HBITMAP hbm_Buffer = CreateCompatibleBitmap(hDC, width, height); 67 | HBITMAP hbm_oldBuffer = (HBITMAP)SelectObject(tempHDC, hbm_Buffer); 68 | 69 | // Borders 70 | RECT rect; 71 | HBRUSH gray = CreateSolidBrush(RGB(175,175,175)); 72 | rect.left = 0; rect.top = 0; rect.right = width; rect.bottom = PADDING; 73 | FillRect(tempHDC,&rect,gray); 74 | rect.right = PADDING; rect.bottom = height; 75 | FillRect(tempHDC,&rect,gray); 76 | rect.left = width-PADDING; rect.right = width; 77 | FillRect(tempHDC,&rect,gray); 78 | rect.left = 0; rect.top = height-PADDING; 79 | FillRect(tempHDC,&rect,gray); 80 | 81 | int g_Width = width - PADDING * 2; 82 | int g_Height = height - PADDING *2; 83 | float f_Width = (float)g_Width; 84 | 85 | // Gradient 86 | for (int x=PADDING; xprintf("Key pos: %f\n", position[i]); 101 | if (number[i] != selected) { 102 | int x = (int)(f_Width * position[i]) + PADDING; 103 | paintArrow(x, yTop, false, tempHDC, ARROWDESEL); 104 | paintArrow(x, yBottom, true, tempHDC, ARROWDESEL); 105 | } else { 106 | sel = i; 107 | } 108 | } 109 | if (sel != -1) { 110 | paintArrow((int)(f_Width * position[sel]) + PADDING, yTop, false, tempHDC, ARROWSEL); 111 | paintArrow((int)(f_Width * position[sel]) + PADDING, yBottom, true, tempHDC, ARROWSEL); 112 | } 113 | 114 | //GetClientRect(m_hWnd, &rect); 115 | BitBlt(hDC, 0, 0, width, height, tempHDC, 0, 0, SRCCOPY); 116 | //BitBlt(hDC, rect.left, rect.top, rect.right, rect.bottom, tempHDC, 0, 0, SRCCOPY); 117 | 118 | SelectObject(tempHDC, hbm_oldBuffer); 119 | DeleteDC(tempHDC); 120 | DeleteObject(hbm_Buffer); 121 | } 122 | 123 | void GradientRamp::paintArrow(int px, int py, bool up, HDC hDC, COLORREF colR) { 124 | int offset = 0; 125 | for (int y=0;y width - PADDING) 152 | pos = 1.f; 153 | else if (x > PADDING) 154 | pos = (float)(x - PADDING) / (float)(width - PADDING * 2); 155 | return pos; 156 | } 157 | 158 | int GradientRamp::toIndex(int n) { 159 | for (int i=0;i PADDING && y < (height - PADDING) && !broad) 170 | return -1; 171 | 172 | // Distance from gradient 173 | int dist = 0; 174 | if (broad) 175 | dist = ARROWS; 176 | else if (y < PADDING) 177 | dist = PADDING - y; 178 | else 179 | dist = y - height + PADDING; 180 | 181 | //CharStream *out = thread_local(current_stdout); 182 | // Intersect all keys 183 | float f_Width = (float)(width - PADDING * 2); 184 | for (int i=0;iprintf("Hit key: %d %d %d\n", x-dist, x+dist, x); 187 | if (kx-dist <= x && kx+dist >= x) 188 | return i; 189 | } 190 | 191 | // No keys found 192 | return -1; 193 | } 194 | 195 | void GradientRamp::leftDown(int x, int y, bool ctrl, bool shift, bool alt) { 196 | int key = hit(x,y,true); 197 | 198 | //CharStream *out = thread_local(current_stdout); 199 | //out->printf("Hit key: %d %d\n", key, selected); 200 | //out->printf("Left down\n"); 201 | 202 | if (!alt && key >= 0) { 203 | selectKey(number[key]); 204 | } else if (key == -1) { 205 | selectKey(-1); 206 | } 207 | 208 | //out->printf("Selected key: %d\n", selected); 209 | //out->printf("## Seletion DONE! ##\n", selected); 210 | } 211 | 212 | void GradientRamp::leftUp(int x, int y, bool ctrl, bool shift, bool alt) { 213 | int key = hit(x,y); 214 | if (alt && key == -1) { 215 | parent->gradAddKey(toPos(x)); 216 | selected = keys - 1; // New key gets the last id 217 | parent->gradSelKey(); 218 | 219 | //CharStream *out = thread_local(current_stdout); 220 | //out->printf("Key added!\n"); 221 | 222 | } else if (alt && key >= 0) { 223 | if (selected == number[key]) selected = -1; 224 | parent->gradDelKey(number[key]); 225 | } 226 | } 227 | 228 | void GradientRamp::dragging(int x, int y, bool ctrl, bool shift, bool alt) { 229 | if (selected <= 1) // Refuse to move ends and empty 230 | return; 231 | if (selected < keys) 232 | parent->gradMoveKey(selected, toPos(x)); 233 | //CharStream *out = thread_local(current_stdout); 234 | //out->printf("Move key: %d %f\n", number[selected], pos); 235 | } 236 | 237 | void GradientRamp::popup(int x, int y, int sel) { 238 | int key = hit(x,y,true); 239 | switch (sel) { 240 | case ID_MENU_ADDKEY: 241 | if (key == -1) { 242 | parent->gradAddKey(toPos(x)); 243 | selected = keys - 1; // New key gets the last id 244 | parent->gradSelKey(); 245 | } 246 | break; 247 | case ID_MENU_REMOVEKEY: 248 | if (key >= 0) { 249 | if (selected == number[key]) selected = -1; 250 | parent->gradDelKey(number[key]); 251 | } else if (selected >= 0) { 252 | int k = selected; 253 | selected = -1; 254 | parent->gradDelKey(k); 255 | } 256 | break; 257 | case ID_RESET_RESET: 258 | selected = -1; 259 | parent->gradReset(); 260 | break; 261 | } 262 | } 263 | 264 | 265 | // ############################################################################################# 266 | // #################################/ Keys \################################ 267 | // ############################################################################################# 268 | 269 | void GradientRamp::selectKey(int n) { 270 | selected = n; 271 | //CharStream *out = thread_local(current_stdout); 272 | //out->printf("Selection sent (%d)\n", selected); 273 | parent->gradSelKey(); 274 | //out->printf("Invalidate\n"); 275 | //invalidate(); 276 | } 277 | 278 | /* 279 | // n is the number of the key 280 | void GradientRamp::moveKey(int n, float pos) { 281 | if (n == 0 || n == 1) // Refuse to move ends 282 | return; 283 | 284 | for (int i=0;imoveKey(n, pos); 293 | } 294 | */ 295 | 296 | void GradientRamp::addKey(int n, float pos, AColor col, Texmap* sub) { 297 | if (pos < 0.f) pos = 0.f; 298 | else if (pos > 1.f) pos = 1.f; 299 | 300 | int key = -1; 301 | for (int i=0;i= 0) { // update only, no keys added 306 | subtex[key] = sub; 307 | position[key] = pos; 308 | color[key] = col; 309 | return; 310 | } 311 | 312 | keys++; 313 | Texmap** t_subtex = new Texmap*[keys]; 314 | float* t_position = new float[keys]; 315 | AColor* t_color = new AColor[keys]; 316 | int* t_number = new int[keys]; 317 | keys--; 318 | 319 | for (int i=0;i position[i]) { 399 | swap(i - 1, i); 400 | swapped = true; 401 | } 402 | } 403 | } while (swapped); 404 | } */ 405 | 406 | // ############################################################################################# 407 | // #################################/ Subtex \################################ 408 | // ############################################################################################# 409 | 410 | Texmap* GradientRamp::getSubtex(int n) { 411 | if (n == -1) 412 | if (selected >= 0 && selected < keys) 413 | return subtex[toIndex(selected)]; 414 | else 415 | return NULL; 416 | else 417 | return subtex[toIndex(n)]; 418 | } 419 | 420 | 421 | void GradientRamp::setSubtex(int n, Texmap* sub) { 422 | subtex[toIndex(n)] = sub; 423 | } 424 | 425 | void GradientRamp::setSubtex(Texmap* sub) { 426 | if (selected >= 0 && selected < keys) 427 | setSubtex(selected, sub); 428 | } 429 | 430 | // ############################################################################################# 431 | // #################################/ Color \################################ 432 | // ############################################################################################# 433 | 434 | // Linear Search 435 | // O(N) 436 | /* 437 | int GradientRamp::findHighKey(float x) { 438 | int high = 1; // Always 2 keys so we start from key number two since they are ordered by position 439 | while (x > position[high]) { 440 | high++; 441 | if (high >= keys) 442 | return (keys - 1); 443 | } 444 | return high; 445 | } 446 | */ 447 | 448 | // More intelligent search 449 | // O(log N) 450 | int GradientRamp::findHighKey(float x) { 451 | int low = 0; 452 | int high = keys-1; 453 | int mid; 454 | if (x < position[low]) 455 | return low; 456 | while (low < (high-1)) { 457 | mid = (low + high) / 2; 458 | if (x < position[mid]) 459 | high = mid; 460 | else 461 | low = mid; 462 | } 463 | return high; 464 | } 465 | 466 | float GradientRamp::interpolate(float x, float low, float high) { 467 | //int interpolation; // 0 linear 1 smooth 2 solid near 3 solid left 4 solid right 468 | switch (interpolation) { 469 | case 0: 470 | return (x - low) / (high - low); 471 | case 1: 472 | x = (x-low)/(high-low); 473 | if (x < 0.f) x = 0.f; 474 | else if (x > 1.f) x = 1.f; 475 | return (x*x*(3.f-2.f*x)); 476 | } 477 | return 0.f; 478 | } 479 | 480 | AColor GradientRamp::getColor(float x) { 481 | if (x<=0) return color[0]; 482 | if (x>=1) return color[keys-1]; 483 | int high = findHighKey(x); 484 | if (interpolation == 4) return color[high]; 485 | int low = (high > 0 ? high - 1 : 0); // should never happen but just in case 486 | if (interpolation == 3) return color[low]; 487 | if (interpolation == 2) return color[x-position[low]EvalColor(sc):color[0]; 494 | if (x>=1) return subtex[keys-1]?subtex[keys-1]->EvalColor(sc):color[keys-1]; 495 | int high = findHighKey(x); 496 | if (interpolation == 4) return subtex[high]?subtex[high]->EvalColor(sc):color[high]; 497 | int low = (high > 0 ? high - 1 : 0); // should never happen but just in case 498 | if (interpolation == 3) return subtex[low]?subtex[low]->EvalColor(sc):color[low]; 499 | if (interpolation == 2) { 500 | int key = x-position[low]EvalColor(sc):color[key]; 502 | } 503 | float mult = interpolate(x, position[low], position[high]); 504 | return (subtex[low]?subtex[low]->EvalColor(sc):color[low]) 505 | * (1.f - mult) + (subtex[high]?subtex[high]->EvalColor(sc):color[high]) * mult; 506 | } 507 | 508 | #define NOBUMP Point3(0.f,0.f,0.f) 509 | Point3 GradientRamp::getBump(float x, Point3 normal, ShadeContext& sc) { 510 | if (x<=0) return subtex[0]?subtex[0]->EvalNormalPerturb(sc):NOBUMP; 511 | if (x>=1) return subtex[keys-1]?subtex[keys-1]->EvalNormalPerturb(sc):NOBUMP; 512 | int high = findHighKey(x); 513 | if (interpolation == 4) return subtex[high]?subtex[high]->EvalNormalPerturb(sc):NOBUMP; 514 | int low = high - 1; 515 | if (interpolation == 3) return subtex[low]?subtex[low]->EvalNormalPerturb(sc):NOBUMP; 516 | if (interpolation == 2) { 517 | int key = x-position[low]EvalNormalPerturb(sc):NOBUMP; 519 | } 520 | 521 | //float f1, f2; 522 | Point3 v1, v2; 523 | bool maps = false; 524 | if (subtex[0]) { 525 | //f1 = subtex[low]->EvalMono(sc); 526 | v1 = subtex[low]->EvalNormalPerturb(sc); 527 | maps = true; 528 | } else { 529 | //f1 = Intens(color[low]); 530 | v1 = Point3(0.f, 0.f, 0.f); 531 | } 532 | if (subtex[1]) { 533 | //f2 = subtex[high]->EvalMono(sc); 534 | v2 = subtex[high]->EvalNormalPerturb(sc); 535 | maps = true; 536 | } else { 537 | //f2 = Intens(color[high]); 538 | v2 = Point3(0.f, 0.f, 0.f); 539 | } 540 | 541 | // Calculate vector 542 | if (maps) { 543 | float mult = interpolate(x, position[low], position[high]); 544 | v1 = /*(f2-f1)**/ normal + mult*v2 + (1.f-mult)*v1; 545 | } else { 546 | v1 = normal; // * (f2 - f1); 547 | } 548 | 549 | return v1; 550 | } 551 | -------------------------------------------------------------------------------- /src/tile.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. The ASF licenses this 4 | file to you under the Apache License, Version 2.0 (the 5 | "License"); you may not use this file except in compliance 6 | with the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #include "tile.h" 19 | #include "perlin.h" 20 | 21 | inline static int generateID(int x, int y) { return (y-101) * 1000 + x; } 22 | 23 | inline static float noise(float x, float rand) { return Perlin::snoise(x * 31.4 + rand); } 24 | 25 | inline static int STEPUP(int n, int m) { 26 | return (n + 1) % m; 27 | } 28 | 29 | inline static void rotate90(float& x, float& y) { float temp = y; y = x; x = -temp; } 30 | inline static void rotate270(float& x, float& y) { float temp = x; x = y; y = -temp; } 31 | 32 | inline static int STEPDOWN(int n, int m) { 33 | if (n-1 < 0) return m-1; 34 | return n-1; 35 | } 36 | 37 | 38 | float Tile::edgeBlur(float d, float r, int type) { 39 | switch (type) { 40 | case 1: return d/r; // Linear 41 | case 2: // Cubic 42 | d = 1.f - (d/r); 43 | return sqrt(1-d*d); 44 | case 3: return smooth(d, 0.f, r); // Smooth 45 | default: return 1.f; 46 | } 47 | } 48 | 49 | TilePoint Tile::corner(float rX, float rY, float w, float h, TileParam& t) { 50 | // Evaluate maps 51 | if (t.tileRound) { 52 | bool inCorner = false; 53 | float cX=0.0f, cY=0.0f; 54 | // Detect corner 55 | if (rX < t.tileCrnrRad) { 56 | if (rY < t.tileCrnrRad) { // Bottom left 57 | cX = t.tileCrnrRad - rX; 58 | cY = t.tileCrnrRad - rY; 59 | inCorner = true; 60 | } else if (rY > h - t.tileCrnrRad) { // Top left 61 | cX = t.tileCrnrRad - rX; 62 | cY = h - rY - t.tileCrnrRad; 63 | inCorner = true; 64 | } 65 | } else if (rX > w - t.tileCrnrRad) { 66 | if (rY < t.tileCrnrRad) { // Bottom right 67 | cX = w - rX - t.tileCrnrRad; 68 | cY = t.tileCrnrRad - rY; 69 | inCorner = true; 70 | } else if (rY > h - t.tileCrnrRad) { // Top right 71 | cX = w - rX - t.tileCrnrRad; 72 | cY = h - rY - t.tileCrnrRad; 73 | inCorner = true; 74 | } 75 | } 76 | float d = cY*cY + cX*cX; 77 | if (inCorner) { 78 | if (d > t.tileCrnrRad*t.tileCrnrRad) 79 | return TilePoint(); 80 | // Calculate corner blur 81 | d = t.tileCrnrRad - sqrt(d); 82 | if (t.tileBlur > 0 && d w - t.tileBlurRad) { 94 | dX = w - rX; 95 | inCorner = true; 96 | } 97 | // Distance to horizontal walls 98 | if (rY < t.tileBlurRad) { 99 | inCorner = true; 100 | } else if (rY > h - t.tileBlurRad) { 101 | dY = h - rY; 102 | inCorner = true; 103 | } 104 | if (inCorner) 105 | return dX 0 ? -angle : angle, HALFPI) + QUATPI); 209 | scaleX *= scale; 210 | scaleY *= scale; 211 | } 212 | 213 | // Apply auto scale 214 | if (t.autoScale) { 215 | uvw.x /= scaleX; 216 | uvw.y /= scaleY; 217 | } 218 | 219 | // Flip 220 | if (t.flipX) if (rand() % 2) uvw.x = -uvw.x; 221 | if (t.flipY) if (rand() % 2) uvw.y = -uvw.y; 222 | 223 | // Random scale 224 | if (t.randScale) { 225 | if (t.lock) { 226 | float s = 1.f + SFRAND() * t.randSX; 227 | scaleX = s; 228 | scaleY = s; 229 | } else { 230 | scaleX = 1.f + SFRAND() * t.randSX; 231 | scaleY = 1.f + SFRAND() * t.randSY; 232 | } 233 | 234 | if (scaleX < 0) scaleX = 0.f; 235 | if (scaleY < 0) scaleY = 0.f; 236 | 237 | uvw.x /= scaleX; 238 | uvw.y /= scaleY; 239 | } 240 | 241 | // Offset 242 | if (t.randOffset) { 243 | uvw.x += UFRAND() * t.randX; 244 | uvw.y += UFRAND() * t.randY; 245 | } 246 | 247 | // Rotate 248 | if (t.rotUV) 249 | rotatePoint2(uvw, angle); 250 | 251 | // Offset to 0..1 252 | if (t.autoScale) { 253 | uvw.x += .5f; 254 | uvw.y += .5f; 255 | } 256 | 257 | // Return 258 | tp.uvw = uvw; 259 | } 260 | 261 | // All parameters are in world space (p,edges,width,height) 262 | // edges = left top right down 263 | 264 | static void offsetEdges(float edges[4], float x, float y) { 265 | edges[0] += x; 266 | edges[2] += x; 267 | edges[3] += y; 268 | edges[1] += y; 269 | } 270 | 271 | TilePoint Tile::drawTile(Point3 p, float edges[4], TileParam& t, int id, int dir) { 272 | float hEdgeW = t.edgeWidth * .5f; 273 | float hEdgeH = t.edgeHeight * .5f; 274 | 275 | float randomSeed = (float)id * 1.23f + 0.1234f; 276 | if (dir) { 277 | edges[0] += t.eH_var ? hEdgeH * (1.f + noise(edges[0], randomSeed) * t.edgeHeightVar) : hEdgeH; 278 | edges[2] -= t.eH_var ? hEdgeH * (1.f + noise(edges[2], randomSeed) * t.edgeHeightVar) : hEdgeH; 279 | edges[3] += t.eW_var ? hEdgeW * (1.f + noise(edges[3], randomSeed) * t.edgeWidthVar) : hEdgeW; 280 | edges[1] -= t.eW_var ? hEdgeW * (1.f + noise(edges[1], randomSeed) * t.edgeWidthVar) : hEdgeW; 281 | } else { 282 | edges[0] += t.eW_var ? hEdgeW * (1.f + noise(edges[0], randomSeed) * t.edgeWidthVar) : hEdgeW; 283 | edges[2] -= t.eW_var ? hEdgeW * (1.f + noise(edges[2], randomSeed) * t.edgeWidthVar) : hEdgeW; 284 | edges[3] += t.eH_var ? hEdgeH * (1.f + noise(edges[3], randomSeed) * t.edgeHeightVar) : hEdgeH; 285 | edges[1] -= t.eH_var ? hEdgeH * (1.f + noise(edges[1], randomSeed) * t.edgeHeightVar) : hEdgeH; 286 | } 287 | 288 | if (p.x < edges[0]) return TilePoint(); 289 | if (p.x > edges[2]) return TilePoint(); 290 | if (p.y < edges[3]) return TilePoint(); 291 | if (p.y > edges[1]) return TilePoint(); 292 | 293 | float width = edges[2] - edges[0]; 294 | float height = edges[1] - edges[3]; 295 | if (width < 0 || height < 0) return TilePoint(); 296 | 297 | TilePoint tp = corner(p.x - edges[0], p.y - edges[3], width, height, t); 298 | if (tp.d < 0) return tp; // On edge 299 | 300 | //if (t.tileID || t.mapUV) 301 | tp.id = id; 302 | 303 | if (t.center || (t.mapUV && dir)) 304 | tp.center = Point3(edges[0] + (edges[2] - edges[0]) * .5f, 305 | edges[3] + (edges[1] - edges[3]) * .5f, p.z); 306 | 307 | if (dir) { 308 | offsetEdges(edges, -tp.center.x, -tp.center.y); 309 | rotate90(edges[0], edges[3]); 310 | rotate90(edges[2], edges[1]); 311 | offsetEdges(edges, tp.center.x, tp.center.y); 312 | p -= tp.center; rotate90(p.x, p.y); p += tp.center; 313 | } 314 | 315 | if (t.mapUV) 316 | uvMapping(tp, p, edges, t, dir); 317 | 318 | if (dir) { 319 | offsetEdges(edges, -tp.center.x, -tp.center.y); 320 | rotate270(edges[0], edges[3]); 321 | rotate270(edges[2], edges[1]); 322 | offsetEdges(edges, tp.center.x, tp.center.y); 323 | p -= tp.center; rotate270(p.x, p.y); p += tp.center; 324 | } 325 | 326 | return tp; 327 | } 328 | 329 | static int rowcol(float& low, float& high, int& id, float pos, float total, std::vector& arr, float size, float var, float rand) { 330 | int num = int(arr.size()); 331 | float h = total * size; 332 | float y = pos / h; 333 | float yi = (float)FASTFLOOR(y); // group ID 334 | y = pos - yi * h; // pos within group 335 | 336 | float sumY = 0.f; 337 | float tileHeight = 0.f; 338 | int cur = 0; 339 | while (cur < num) { 340 | tileHeight = arr[cur] * size; 341 | if (y < sumY + tileHeight) 342 | break; 343 | sumY += tileHeight; 344 | cur++; 345 | } 346 | if (cur < 0 || cur >= num) // Necessary due floating point error 347 | return -1; 348 | 349 | id = yi * num + cur; 350 | 351 | // Variance 352 | // ----------- To determine max var 353 | // ----------- If we rose 354 | // ----------- eTop -> neTop 355 | // x 356 | // ----------- eBot -> neBot 357 | // ----------- If we droped 358 | // ----------- To determine max var 359 | 360 | float eBot = yi * h + sumY; 361 | float eTop = eBot + tileHeight; 362 | 363 | if (var > 0.0001f) { 364 | float n; 365 | 366 | float bTileHeight = arr[STEPDOWN(cur, num)]*size; 367 | float tTileHeight = arr[STEPUP(cur, num)]*size; 368 | 369 | n = noise(eBot, rand); 370 | float neBot = eBot + (n>0 ? tileHeight : bTileHeight) * n * var; 371 | n = noise(eTop, rand); 372 | float neTop = eTop + (n<0 ? tileHeight : tTileHeight) * n * var; 373 | 374 | if (pos < neBot) { // We droped one cur down 375 | id--; 376 | cur = STEPDOWN(cur, num); 377 | low = eBot-bTileHeight; 378 | n = noise(low, rand); 379 | low += (n>0 ? bTileHeight : arr[STEPDOWN(cur, num)]*size) * n * var; 380 | high = neBot; 381 | 382 | } else if (pos > neTop) { // We rose one cur up 383 | id++; 384 | cur = STEPUP(cur, num); 385 | high = eTop+tTileHeight; 386 | n = noise(high, rand); 387 | high += (n<0 ? tTileHeight : arr[STEPUP(cur, num)]*size) * n * var; 388 | low = neTop; 389 | 390 | } else { // Still in the same cur 391 | low = neBot; 392 | high = neTop; 393 | } 394 | } else { 395 | low = eBot; 396 | high = eTop; 397 | } 398 | 399 | return cur; 400 | } 401 | 402 | TilePoint Tile::pat_xBond(Point3 p, TileParam& t) { 403 | TilePattern* pat = t.pattern; 404 | 405 | if (!pat) return TilePoint(); 406 | 407 | float edges[4]; 408 | int id = 0; 409 | int id2 = 0; 410 | 411 | // Tile top and bottom 412 | float rand = 3.14f; 413 | int row = rowcol(edges[3], edges[1], id, p.y, pat->totalHeight, pat->heights, t.tileHeight, t.tileHeightVar, rand); 414 | if (row == -1) return TilePoint(); 415 | 416 | // Tile sides 417 | rand = edges[3] * 1.325f + 31.41213f; 418 | float offset = pat->rows[row].offset * t.tileWidth; 419 | if (offset < 0) offset *= -id; 420 | 421 | row = rowcol(edges[0], edges[2], id2, p.x + offset, pat->rows[row].totalWidth, pat->rows[row].tiles, t.tileWidth, t.tileWidthVar, rand); 422 | if (row == -1) return TilePoint(); 423 | 424 | edges[0] -= offset; 425 | edges[2] -= offset; 426 | 427 | id = generateID(id2, id); 428 | 429 | // Draw it 430 | return drawTile(p, edges, t, id); 431 | } 432 | 433 | static unsigned char pat_herring_dir[] = { 434 | 0, 0, 1, 1, 435 | 0, 1, 1, 0, 436 | 1, 1, 0, 0, 437 | 1, 0, 0, 1 438 | }; 439 | 440 | static float pat_herring_x[] = { 441 | 1.0f, 1.0f, 2.5f, 3.5f, 442 | 0.0f, 1.5f, 2.5f, 4.0f, 443 | 0.5f, 1.5f, 3.0f, 3.0f, 444 | 0.5f, 2.0f, 2.0f, 3.5f 445 | }; 446 | 447 | static float pat_herring_y[] = { 448 | 0.5f, 0.5f, 1.0f, 0.0f, 449 | 1.5f, 2.0f, 1.0f, 1.5f, 450 | 3.0f, 2.0f, 2.5f, 2.5f, 451 | 3.0f, 3.5f, 3.5f, 4.0f 452 | }; 453 | 454 | static unsigned char pat_herring_id[] = { 455 | 1, 1, 1, 0, 456 | 0, 2, 1, 4, 457 | 3, 2, 3, 3, 458 | 3, 2, 2, 4 459 | }; 460 | 461 | TilePoint Tile::pat_herring(Point3 p, TileParam& t) { 462 | float s = t.tileWidth * 2.f; 463 | float h = t.tileWidth * .5f; 464 | float x = p.x / s; 465 | float y = p.y / s; 466 | int xi = FASTFLOOR(x); 467 | int yi = FASTFLOOR(y); 468 | x = xi * s; 469 | y = yi * s; 470 | int x_id = (int)((p.x - x) / h) % 4; 471 | int y_id = (int)((p.y - y) / h) % 4; 472 | int id = x_id + 4 * y_id; 473 | 474 | //Point3 center = Point3(pat_herring_x[id]*h+x, pat_herring_y[id]*h+y, p.z); 475 | 476 | float edges[4]; 477 | 478 | if (!pat_herring_dir[id]) { 479 | edges[0] = (pat_herring_x[id]-1.f) * h + x; 480 | edges[2] = edges[0] + t.tileWidth; 481 | edges[3] = (pat_herring_y[id]-.5f) * h + y; 482 | edges[1] = edges[3] + h; 483 | } else { 484 | edges[0] = (pat_herring_x[id]-.5f) * h + x; 485 | edges[2] = edges[0] + h; 486 | edges[3] = (pat_herring_y[id]-1.f) * h + y; 487 | edges[1] = edges[3] + t.tileWidth; 488 | } 489 | 490 | int tid = generateID(xi*4 + (pat_herring_dir[id] ? 0 : pat_herring_id[id]), 491 | yi*4 + (pat_herring_dir[id] ? pat_herring_id[id] : 0)); 492 | 493 | return drawTile(p, edges, t, tid, pat_herring_dir[id]); 494 | } 495 | 496 | void TilePattern::setPreset(int preset) { 497 | switch (preset) { 498 | case 0: setPattern(L"0, 1, 1"); break; // Stack 499 | case 1: setPattern(L"0, 1, 1 / 0.5, 1, 1"); break; // Stretcher 500 | case 2: setPattern(L".25, 1, 1, .5 / -.5, 1, 1 / -.5, 1, 1 / -.5, 1, 1 / -.5, 1, 1"); break; // Flemish Strecher 501 | case 3: setPattern(L".25, 1, .5 / -.5, 1, 1 / -.5, 1, 1 / -.5, 1, 1 / -.5, 1, 1"); break; // Common 502 | case 4: setPattern(L"0, 1, 1, .5 / .75, 1, 1, .5"); break; // Flemish 503 | case 5: setPattern(L"0, 1, 1, 1, .5 / 1.25, 1, 1, 1, .5"); break; // Monk Bond 504 | case 6: setPattern(L"0, 1, 1, 1, 1, .5 / 1.75, 1, 1, 1, 1, .5"); break; // Flemish Garden Wall 505 | case 7: setPattern(L".25, 1, .5 / 0, 1, 1"); break; // English 506 | case 8: setPattern(L"0,1,1 / -.25,1,.5 / -.25,1,1 / -.25,1,.5"); break; // English Cross 507 | case 9: setPattern(L"0,1,.5 / -.25,1,.5 / -.25,1,1 / -.25,1,1"); break; // Double English Cross 508 | } 509 | } 510 | 511 | TilePoint Tile::draw(Point3 p, TileParam& t) { 512 | if (t.tilingType == 1) 513 | return pat_herring(p, t); 514 | return pat_xBond(p, t); 515 | } 516 | 517 | static void tokenize(const std::wstring& str, std::vector& tokens, const std::wstring& delimiters) { 518 | std::wstring::size_type lastPos = str.find_first_not_of(delimiters, 0); 519 | std::wstring::size_type pos = str.find_first_of(delimiters, lastPos); 520 | 521 | while (std::wstring::npos != pos || std::wstring::npos != lastPos) { 522 | tokens.push_back(str.substr(lastPos, pos - lastPos)); 523 | lastPos = str.find_first_not_of(delimiters, pos); 524 | pos = str.find_first_of(delimiters, lastPos); 525 | } 526 | } 527 | 528 | static int parsePattern(std::wstring str, TilePattern* pat) { 529 | pat->rows.clear(); 530 | pat->heights.clear(); 531 | 532 | std::vector rowStrings = std::vector(); 533 | tokenize(str, rowStrings, L"/"); 534 | 535 | for (int i=0; i row = std::vector(); 537 | tokenize(rowStrings[i], row, L","); 538 | 539 | if (row.size() < 3) 540 | return FALSE; 541 | 542 | double offset, height, width; 543 | std::wstringstream s0(row[0]); 544 | s0 >> offset; 545 | std::wstringstream s1(row[1]); 546 | s1 >> height; 547 | 548 | TileRow r = TileRow(offset); 549 | 550 | for (int j=2; j> width; 553 | 554 | r.tiles.push_back(width); 555 | } 556 | 557 | pat->rows.push_back(r); 558 | pat->heights.push_back((float)height); 559 | } 560 | 561 | return TRUE; 562 | } 563 | 564 | void TilePattern::setPattern(std::wstring s) { 565 | parsePattern(s, this); 566 | update(); 567 | } 568 | --------------------------------------------------------------------------------