1 /**
2  * Mandelbulber v2, a 3D fractal generator       ,=#MKNmMMKmmßMNWy,
3  *                                             ,B" ]L,,p%%%,,,§;, "K
4  * Copyright (C) 2016-20 Mandelbulber Team     §R-==%w["'~5]m%=L.=~5N
5  *                                        ,=mm=§M ]=4 yJKA"/-Nsaj  "Bw,==,,
6  * This file is part of Mandelbulber.    §R.r= jw",M  Km .mM  FW ",§=ß., ,TN
7  *                                     ,4R =%["w[N=7]J '"5=],""]]M,w,-; T=]M
8  * Mandelbulber is free software:     §R.ß~-Q/M=,=5"v"]=Qf,'§"M= =,M.§ Rz]M"Kw
9  * you can redistribute it and/or     §w "xDY.J ' -"m=====WeC=\ ""%""y=%"]"" §
10  * modify it under the terms of the    "§M=M =D=4"N #"%==A%p M§ M6  R' #"=~.4M
11  * GNU General Public License as        §W =, ][T"]C  §  § '§ e===~ U  !§[Z ]N
12  * published by the                    4M",,Jm=,"=e~  §  §  j]]""N  BmM"py=ßM
13  * Free Software Foundation,          ]§ T,M=& 'YmMMpM9MMM%=w=,,=MT]M m§;'§,
14  * either version 3 of the License,    TWw [.j"5=~N[=§%=%W,T ]R,"=="Y[LFT ]N
15  * or (at your option)                   TW=,-#"%=;[  =Q:["V""  ],,M.m == ]N
16  * any later version.                      J§"mr"] ,=,," =="""J]= M"M"]==ß"
17  *                                          §= "=C=4 §"eM "=B:m|4"]#F,§~
18  * Mandelbulber is distributed in            "9w=,,]w em%wJ '"~" ,=,,ß"
19  * the hope that it will be useful,                 . "K=  ,=RMMMßM"""
20  * but WITHOUT ANY WARRANTY;                            .'''
21  * without even the implied warranty
22  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23  *
24  * See the GNU General Public License for more details.
25  * You should have received a copy of the GNU General Public License
26  * along with Mandelbulber. If not, see <http://www.gnu.org/licenses/>.
27  *
28  * ###########################################################################
29  *
30  * Authors: Krzysztof Marczak (buddhi1980@gmail.com)
31  *
32  * global method TextureMapping() - coordinate transformer for textures
33  *
34  * For the given parameters TextureMapping(...) determines the point x-y
35  * on the texture to use for processing
36  */
37 
38 #include "texture_mapping.hpp"
39 
40 #include "material.h"
41 #include "object_data.hpp"
42 #include "texture_enums.hpp"
43 
TextureMapping(CVector3 inPoint,CVector3 normalVector,const cObjectData & objectData,const cMaterial * material,CVector3 * textureVectorX,CVector3 * textureVectorY)44 CVector2<float> TextureMapping(CVector3 inPoint, CVector3 normalVector,
45 	const cObjectData &objectData, const cMaterial *material, CVector3 *textureVectorX,
46 	CVector3 *textureVectorY)
47 {
48 	CVector2<float> textureCoordinates;
49 	CVector3 point = inPoint;
50 	if (!material->textureFractalize)
51 	{
52 		point = point - objectData.position;
53 		point = objectData.rotationMatrix.RotateVector(point);
54 		point = point.mod(objectData.repeat);
55 		point /= objectData.size;
56 	}
57 	point = material->rotMatrix.RotateVector(point);
58 
59 	normalVector = objectData.rotationMatrix.RotateVector(normalVector);
60 
61 	switch (material->textureMappingType)
62 	{
63 		case texture::mappingPlanar:
64 		{
65 			textureCoordinates = CVector2<float>(point.x, point.y);
66 			textureCoordinates.x /= -material->textureScale.x;
67 			textureCoordinates.y /= material->textureScale.y;
68 			textureCoordinates.x -= material->textureCenter.x;
69 			textureCoordinates.y -= material->textureCenter.y;
70 
71 			if (textureVectorX && textureVectorY)
72 			{
73 				CVector3 texX(1.0, 0.0, 0.0);
74 				texX = objectData.rotationMatrix.Transpose().RotateVector(texX);
75 				texX = material->rotMatrix.Transpose().RotateVector(texX);
76 				*textureVectorX = texX;
77 
78 				CVector3 texY(0.0, -1.0, 0.0);
79 				texY = objectData.rotationMatrix.Transpose().RotateVector(texY);
80 				texY = material->rotMatrix.Transpose().RotateVector(texY);
81 				*textureVectorY = texY;
82 			}
83 			break;
84 		}
85 		case texture::mappingCylindrical:
86 		{
87 			double alphaTexture = fmod(point.GetAlpha() + 2.0 * M_PI, 2.0 * M_PI);
88 			textureCoordinates.x = alphaTexture / (2.0 * M_PI);
89 			textureCoordinates.y = -point.z;
90 			textureCoordinates.x /= material->textureScale.x;
91 			textureCoordinates.y /= material->textureScale.y;
92 			textureCoordinates.x -= material->textureCenter.x;
93 			textureCoordinates.y -= material->textureCenter.y;
94 
95 			if (textureVectorX && textureVectorY)
96 			{
97 				CVector3 texY(0.0, 0.0, 1.0);
98 				CVector3 texX = point.Cross(texY);
99 				texX = objectData.rotationMatrix.Transpose().RotateVector(texX);
100 				texX = material->rotMatrix.Transpose().RotateVector(texX);
101 				*textureVectorX = texX;
102 				texY = objectData.rotationMatrix.Transpose().RotateVector(texY);
103 				texY = material->rotMatrix.Transpose().RotateVector(texY);
104 				*textureVectorY = texY;
105 			}
106 
107 			break;
108 		}
109 		case texture::mappingSpherical:
110 		{
111 			double alphaTexture = fmod(point.GetAlpha() + 2.0 * M_PI, 2.0 * M_PI);
112 			double betaTexture = -point.GetBeta();
113 			textureCoordinates.x = alphaTexture / (2.0 * M_PI);
114 			textureCoordinates.y = betaTexture / M_PI;
115 			textureCoordinates.x /= material->textureScale.x;
116 			textureCoordinates.y /= material->textureScale.y;
117 			textureCoordinates.x -= material->textureCenter.x;
118 			textureCoordinates.y -= material->textureCenter.y;
119 
120 			if (textureVectorX && textureVectorY)
121 			{
122 				CVector3 texY(0.0, 0.0, -1.0);
123 				CVector3 texX = texY.Cross(point);
124 				texX.Normalize();
125 				texY = texX.Cross(point);
126 
127 				texX = objectData.rotationMatrix.Transpose().RotateVector(texX);
128 				texX = material->rotMatrix.Transpose().RotateVector(texX);
129 				*textureVectorX = texX;
130 				texY = objectData.rotationMatrix.Transpose().RotateVector(texY);
131 				texY = material->rotMatrix.Transpose().RotateVector(texY);
132 				*textureVectorY = texY;
133 			}
134 
135 			break;
136 		}
137 		case texture::mappingCubic:
138 		{
139 			point /= material->textureScale;
140 			point -= material->textureCenter;
141 
142 			CVector3 texX;
143 			CVector3 texY;
144 
145 			if (fabs(normalVector.x) > fabs(normalVector.y))
146 			{
147 				if (fabs(normalVector.x) > fabs(normalVector.z))
148 				{
149 					// x
150 					if (normalVector.x > 0)
151 						textureCoordinates = CVector2<float>(point.y, -point.z);
152 					else
153 						textureCoordinates = CVector2<float>(-point.y, -point.z);
154 
155 					if (textureVectorX && textureVectorY)
156 					{
157 						if (normalVector.x > 0)
158 						{
159 							texX = CVector3(0.0, -1.0, 0.0);
160 							texY = CVector3(0.0, 0.0, 1.0);
161 						}
162 						else
163 						{
164 							texX = CVector3(0.0, 1.0, 0.0);
165 							texY = CVector3(0.0, 0.0, 1.0);
166 						}
167 					}
168 				}
169 				else
170 				{
171 					// z
172 					if (normalVector.z > 0)
173 						textureCoordinates = CVector2<float>(-point.x, point.y);
174 					else
175 						textureCoordinates = CVector2<float>(point.x, point.y);
176 
177 					if (textureVectorX && textureVectorY)
178 					{
179 						if (normalVector.z > 0)
180 						{
181 							texX = CVector3(1.0, 0.0, 0.0);
182 							texY = CVector3(0.0, -1.0, 0.0);
183 						}
184 						else
185 						{
186 							texX = CVector3(-1.0, 0.0, 0.0);
187 							texY = CVector3(0.0, -1.0, 0.0);
188 						}
189 					}
190 				}
191 			}
192 			else
193 			{
194 				if (fabs(normalVector.y) > fabs(normalVector.z))
195 				{
196 					// y
197 					if (normalVector.y > 0)
198 						textureCoordinates = CVector2<float>(-point.x, -point.z);
199 					else
200 						textureCoordinates = CVector2<float>(point.x, -point.z);
201 
202 					if (textureVectorX && textureVectorY)
203 					{
204 						if (normalVector.y > 0)
205 						{
206 							texX = CVector3(1.0, 0.0, 0.0);
207 							texY = CVector3(0.0, 0.0, 1.0);
208 						}
209 						else
210 						{
211 							texX = CVector3(-1.0, 0.0, 0.0);
212 							texY = CVector3(0.0, 0.0, 1.0);
213 						}
214 					}
215 				}
216 				else
217 				{
218 					// z
219 					if (normalVector.z > 0)
220 						textureCoordinates = CVector2<float>(-point.x, point.y);
221 					else
222 						textureCoordinates = CVector2<float>(point.x, point.y);
223 
224 					if (textureVectorX && textureVectorY)
225 					{
226 						if (normalVector.z > 0)
227 						{
228 							texX = CVector3(1.0, 0.0, 0.0);
229 							texY = CVector3(0.0, -1.0, 0.0);
230 						}
231 						else
232 						{
233 							texX = CVector3(-1.0, 0.0, 0.0);
234 							texY = CVector3(0.0, -1.0, 0.0);
235 						}
236 					}
237 				}
238 			}
239 
240 			if (textureVectorX && textureVectorY)
241 			{
242 				texX = objectData.rotationMatrix.Transpose().RotateVector(texX);
243 				texX = material->rotMatrix.Transpose().RotateVector(texX);
244 				*textureVectorX = texX;
245 				texY = objectData.rotationMatrix.Transpose().RotateVector(texY);
246 				texY = material->rotMatrix.Transpose().RotateVector(texY);
247 				*textureVectorY = texY;
248 			}
249 
250 			break;
251 		}
252 	}
253 	return textureCoordinates;
254 }
255