/src/ogre/OgreMain/src/OgreMaterial.cpp
Line | Count | Source |
1 | | /* |
2 | | ----------------------------------------------------------------------------- |
3 | | This source file is part of OGRE |
4 | | (Object-oriented Graphics Rendering Engine) |
5 | | For the latest info, see http://www.ogre3d.org/ |
6 | | |
7 | | Copyright (c) 2000-2014 Torus Knot Software Ltd |
8 | | |
9 | | Permission is hereby granted, free of charge, to any person obtaining a copy |
10 | | of this software and associated documentation files (the "Software"), to deal |
11 | | in the Software without restriction, including without limitation the rights |
12 | | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
13 | | copies of the Software, and to permit persons to whom the Software is |
14 | | furnished to do so, subject to the following conditions: |
15 | | |
16 | | The above copyright notice and this permission notice shall be included in |
17 | | all copies or substantial portions of the Software. |
18 | | |
19 | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
20 | | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
21 | | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
22 | | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
23 | | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
24 | | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
25 | | THE SOFTWARE. |
26 | | ----------------------------------------------------------------------------- |
27 | | */ |
28 | | #include "OgreStableHeaders.h" |
29 | | |
30 | | #include "OgreMaterial.h" |
31 | | #include "OgreLodStrategyManager.h" |
32 | | #include "OgreLodStrategy.h" |
33 | | |
34 | | namespace Ogre { |
35 | | |
36 | | //----------------------------------------------------------------------- |
37 | | Material::Material(ResourceManager* creator, const String& name, ResourceHandle handle, |
38 | | const String& group, bool isManual, ManualResourceLoader* loader) |
39 | 0 | :Resource(creator, name, handle, group, false, NULL), |
40 | 0 | mReceiveShadows(true), |
41 | 0 | mTransparencyCastsShadows(false), |
42 | 0 | mCompilationRequired(true) |
43 | 0 | { |
44 | | // Override isManual, not applicable for Material (we always want to call loadImpl) |
45 | 0 | if(isManual) |
46 | 0 | { |
47 | 0 | LogManager::getSingleton().logWarning("Material " + name + |
48 | 0 | " was requested with isManual=true, but this is not applicable " |
49 | 0 | "for materials; the flag has been reset to false"); |
50 | 0 | } |
51 | | |
52 | | // Initialise to default strategy |
53 | 0 | mLodStrategy = LodStrategyManager::getSingleton().getDefaultStrategy(); |
54 | |
|
55 | 0 | mLodValues.push_back(0.0f); |
56 | |
|
57 | 0 | applyDefaults(); |
58 | | |
59 | | /* For consistency with StringInterface, but we don't add any parameters here |
60 | | That's because the Resource implementation of StringInterface is to |
61 | | list all the options that need to be set before loading, of which |
62 | | we have none as such. Full details can be set through scripts. |
63 | | */ |
64 | 0 | createParamDictionary("Material"); |
65 | 0 | } |
66 | | //----------------------------------------------------------------------- |
67 | | Material::~Material() |
68 | 0 | { |
69 | 0 | removeAllTechniques(); |
70 | | // have to call this here reather than in Resource destructor |
71 | | // since calling virtual methods in base destructors causes crash |
72 | 0 | unload(); |
73 | 0 | } |
74 | | //----------------------------------------------------------------------- |
75 | | Material& Material::operator=(const Material& rhs) |
76 | 0 | { |
77 | 0 | if (this == &rhs) |
78 | 0 | return *this; |
79 | | |
80 | 0 | Resource::operator=(rhs); |
81 | 0 | mReceiveShadows = rhs.mReceiveShadows; |
82 | 0 | mTransparencyCastsShadows = rhs.mTransparencyCastsShadows; |
83 | | |
84 | | // Copy Techniques |
85 | 0 | this->removeAllTechniques(); |
86 | 0 | for(auto *t : rhs.mTechniques) |
87 | 0 | { |
88 | 0 | Technique* tech = this->createTechnique(); |
89 | 0 | *tech = *t; |
90 | 0 | if (t->isSupported()) |
91 | 0 | { |
92 | 0 | insertSupportedTechnique(tech); |
93 | 0 | } |
94 | 0 | } |
95 | | |
96 | | // Also copy LOD information |
97 | 0 | mUserLodValues = rhs.mUserLodValues; |
98 | 0 | mLodValues = rhs.mLodValues; |
99 | 0 | mLodStrategy = rhs.mLodStrategy; |
100 | 0 | mCompilationRequired = rhs.mCompilationRequired; |
101 | | // illumination passes are not compiled right away so |
102 | | // mIsLoaded state should still be the same as the original material |
103 | 0 | assert(isLoaded() == rhs.isLoaded()); |
104 | |
|
105 | 0 | return *this; |
106 | 0 | } |
107 | | |
108 | | |
109 | | //----------------------------------------------------------------------- |
110 | | void Material::prepareImpl(void) |
111 | 0 | { |
112 | | // compile if required |
113 | 0 | if (mCompilationRequired) |
114 | 0 | compile(); |
115 | | |
116 | | // Load all supported techniques |
117 | 0 | for (auto *t : mSupportedTechniques) |
118 | 0 | { |
119 | 0 | t->_prepare(); |
120 | 0 | } |
121 | 0 | } |
122 | | //----------------------------------------------------------------------- |
123 | | void Material::unprepareImpl(void) |
124 | 0 | { |
125 | | // Load all supported techniques |
126 | 0 | for (auto *t : mSupportedTechniques) |
127 | 0 | { |
128 | 0 | t->_unprepare(); |
129 | 0 | } |
130 | 0 | } |
131 | | //----------------------------------------------------------------------- |
132 | | void Material::loadImpl(void) |
133 | 0 | { |
134 | | // Load all supported techniques |
135 | 0 | for (auto *t : mSupportedTechniques) |
136 | 0 | { |
137 | 0 | t->_load(); |
138 | 0 | } |
139 | 0 | } |
140 | | //----------------------------------------------------------------------- |
141 | | void Material::unloadImpl(void) |
142 | 0 | { |
143 | | // Unload all supported techniques |
144 | 0 | for (auto *t : mSupportedTechniques) |
145 | 0 | { |
146 | 0 | t->_unload(); |
147 | 0 | } |
148 | |
|
149 | 0 | mCompilationRequired = true; |
150 | 0 | } |
151 | | //----------------------------------------------------------------------- |
152 | | size_t Material::calculateSize(void) const |
153 | 0 | { |
154 | 0 | size_t memSize = sizeof(*this) + Resource::calculateSize(); |
155 | | |
156 | | // Tally up techniques |
157 | 0 | for (auto t : mTechniques) |
158 | 0 | { |
159 | 0 | memSize += t->calculateSize(); |
160 | 0 | } |
161 | |
|
162 | 0 | memSize += mUnsupportedReasons.size() * sizeof(char); |
163 | |
|
164 | 0 | return memSize; |
165 | 0 | } |
166 | | //----------------------------------------------------------------------- |
167 | | MaterialPtr Material::clone(const String& newName, const String& newGroup) const |
168 | 0 | { |
169 | 0 | MaterialPtr newMat = |
170 | 0 | MaterialManager::getSingleton().create(newName, newGroup.empty() ? mGroup : newGroup); |
171 | |
|
172 | 0 | if(!newMat) // interception by collision handler |
173 | 0 | return newMat; |
174 | | |
175 | | // Keep handle (see below, copy overrides everything) |
176 | 0 | ResourceHandle newHandle = newMat->getHandle(); |
177 | | // Assign values from this |
178 | 0 | *newMat = *this; |
179 | | // Restore new group if required, will have been overridden by operator |
180 | 0 | if (!newGroup.empty()) |
181 | 0 | { |
182 | 0 | newMat->mGroup = newGroup; |
183 | 0 | } |
184 | | |
185 | | // Correct the name & handle, they get copied too |
186 | 0 | newMat->mName = newName; |
187 | 0 | newMat->mHandle = newHandle; |
188 | | |
189 | | //if we're cloning from a loaded material, notify the creator or otherwise size won't be right |
190 | 0 | if (newMat->getLoadingState() == LOADSTATE_LOADED) |
191 | 0 | { |
192 | | // Notify manager |
193 | 0 | if (mCreator) |
194 | 0 | mCreator->_notifyResourceLoaded(newMat.get()); |
195 | 0 | } |
196 | |
|
197 | 0 | return newMat; |
198 | 0 | } |
199 | | //----------------------------------------------------------------------- |
200 | | void Material::copyDetailsTo(MaterialPtr& mat) const |
201 | 0 | { |
202 | | // Keep handle (see below, copy overrides everything) |
203 | 0 | ResourceHandle savedHandle = mat->mHandle; |
204 | 0 | String savedName = mat->mName; |
205 | 0 | String savedGroup = mat->mGroup; |
206 | | // Assign values from this |
207 | 0 | *mat = *this; |
208 | | // Correct the name & handle, they get copied too |
209 | 0 | mat->mName = savedName; |
210 | 0 | mat->mHandle = savedHandle; |
211 | 0 | mat->mGroup = savedGroup; |
212 | 0 | } |
213 | | //----------------------------------------------------------------------- |
214 | | void Material::applyDefaults(void) |
215 | 0 | { |
216 | 0 | MaterialPtr defaults = MaterialManager::getSingleton().getDefaultSettings(); |
217 | |
|
218 | 0 | if (defaults) |
219 | 0 | { |
220 | | // save name & handle |
221 | 0 | String savedName = mName; |
222 | 0 | String savedGroup = mGroup; |
223 | 0 | ResourceHandle savedHandle = mHandle; |
224 | 0 | *this = *defaults; |
225 | | // restore name & handle |
226 | 0 | mName = savedName; |
227 | 0 | mHandle = savedHandle; |
228 | 0 | mGroup = savedGroup; |
229 | 0 | } |
230 | 0 | mCompilationRequired = true; |
231 | |
|
232 | 0 | } |
233 | | //----------------------------------------------------------------------- |
234 | | Technique* Material::createTechnique(void) |
235 | 0 | { |
236 | 0 | Technique *t = OGRE_NEW Technique(this); |
237 | 0 | mTechniques.push_back(t); |
238 | 0 | mCompilationRequired = true; |
239 | 0 | return t; |
240 | 0 | } |
241 | | //----------------------------------------------------------------------- |
242 | | Technique* Material::getTechnique(const String& name) const |
243 | 0 | { |
244 | 0 | Technique* foundTechnique = 0; |
245 | | // iterate through techniques to find a match |
246 | 0 | for (auto *t : mTechniques) |
247 | 0 | { |
248 | 0 | if (t->getName() == name) |
249 | 0 | { |
250 | 0 | foundTechnique = t; |
251 | 0 | break; |
252 | 0 | } |
253 | 0 | } |
254 | |
|
255 | 0 | return foundTechnique; |
256 | 0 | } |
257 | | //----------------------------------------------------------------------- |
258 | | unsigned short Material::getNumLodLevels(unsigned short schemeIndex) const |
259 | 0 | { |
260 | | // Safety check - empty list? |
261 | 0 | if (mBestTechniquesBySchemeList.empty()) |
262 | 0 | return 0; |
263 | | |
264 | 0 | BestTechniquesBySchemeList::const_iterator i = |
265 | 0 | mBestTechniquesBySchemeList.find(schemeIndex); |
266 | 0 | if (i == mBestTechniquesBySchemeList.end()) |
267 | 0 | { |
268 | | // get the first item, will be 0 (the default) if default |
269 | | // scheme techniques exist, otherwise the earliest defined |
270 | 0 | i = mBestTechniquesBySchemeList.begin(); |
271 | 0 | } |
272 | |
|
273 | 0 | return static_cast<unsigned short>(i->second.size()); |
274 | 0 | } |
275 | | //----------------------------------------------------------------------- |
276 | | unsigned short Material::getNumLodLevels(const String& schemeName) const |
277 | 0 | { |
278 | 0 | return getNumLodLevels( |
279 | 0 | MaterialManager::getSingleton()._getSchemeIndex(schemeName)); |
280 | 0 | } |
281 | | //----------------------------------------------------------------------- |
282 | | void Material::insertSupportedTechnique(Technique* t) |
283 | 0 | { |
284 | 0 | mSupportedTechniques.push_back(t); |
285 | | // get scheme |
286 | 0 | unsigned short schemeIndex = t->_getSchemeIndex(); |
287 | | |
288 | | // Insert won't replace if supported technique for this scheme/lod is |
289 | | // already there, which is what we want |
290 | 0 | mBestTechniquesBySchemeList[schemeIndex].emplace(t->getLodIndex(), t); |
291 | |
|
292 | 0 | } |
293 | | //----------------------------------------------------------------------------- |
294 | | Technique* Material::getBestTechnique(unsigned short lodIndex, const Renderable* rend) |
295 | 0 | { |
296 | 0 | if (mSupportedTechniques.empty()) |
297 | 0 | { |
298 | 0 | return NULL; |
299 | 0 | } |
300 | 0 | else |
301 | 0 | { |
302 | 0 | Technique* ret = 0; |
303 | 0 | MaterialManager& matMgr = MaterialManager::getSingleton(); |
304 | | // get scheme |
305 | 0 | auto si = mBestTechniquesBySchemeList.find(matMgr._getActiveSchemeIndex()); |
306 | | // scheme not found? |
307 | 0 | if (si == mBestTechniquesBySchemeList.end()) |
308 | 0 | { |
309 | | // listener specified alternative technique available? |
310 | 0 | ret = matMgr._arbitrateMissingTechniqueForActiveScheme(this, lodIndex, rend); |
311 | 0 | if (ret) |
312 | 0 | return ret; |
313 | | |
314 | 0 | OgreAssert(!mBestTechniquesBySchemeList.empty(), "handleSchemeNotFound() must not remove techniques"); |
315 | | // Nope, use default |
316 | | // get the first item, will be 0 (the default) if default |
317 | | // scheme techniques exist, otherwise the earliest defined |
318 | 0 | si = mBestTechniquesBySchemeList.begin(); |
319 | 0 | } |
320 | | |
321 | | // get LOD |
322 | 0 | auto li = si->second.find(lodIndex); |
323 | | // LOD not found? |
324 | 0 | if (li == si->second.end()) |
325 | 0 | { |
326 | | // Use the next LOD level up |
327 | 0 | for (auto rli = si->second.rbegin(); rli != si->second.rend(); ++rli) |
328 | 0 | { |
329 | 0 | if (rli->second->getLodIndex() < lodIndex) |
330 | 0 | { |
331 | 0 | ret = rli->second; |
332 | 0 | break; |
333 | 0 | } |
334 | |
|
335 | 0 | } |
336 | 0 | if (!ret) |
337 | 0 | { |
338 | | // shouldn't ever hit this really, unless user defines no LOD 0 |
339 | | // pick the first LOD we have (must be at least one to have a scheme entry) |
340 | 0 | ret = si->second.begin()->second; |
341 | 0 | } |
342 | |
|
343 | 0 | } |
344 | 0 | else |
345 | 0 | { |
346 | | // LOD found |
347 | 0 | ret = li->second; |
348 | 0 | } |
349 | |
|
350 | 0 | return ret; |
351 | |
|
352 | 0 | } |
353 | 0 | } |
354 | | //----------------------------------------------------------------------- |
355 | | void Material::removeTechnique(unsigned short index) |
356 | 0 | { |
357 | 0 | assert (index < mTechniques.size() && "Index out of bounds."); |
358 | 0 | Techniques::iterator i = mTechniques.begin() + index; |
359 | 0 | OGRE_DELETE(*i); |
360 | 0 | mTechniques.erase(i); |
361 | 0 | clearBestTechniqueList(); |
362 | 0 | } |
363 | | //----------------------------------------------------------------------- |
364 | | void Material::removeAllTechniques(void) |
365 | 0 | { |
366 | 0 | for (auto *t : mTechniques) |
367 | 0 | { |
368 | 0 | OGRE_DELETE t; |
369 | 0 | } |
370 | 0 | mTechniques.clear(); |
371 | 0 | clearBestTechniqueList(); |
372 | 0 | } |
373 | | //----------------------------------------------------------------------- |
374 | | Material::TechniqueIterator Material::getTechniqueIterator(void) |
375 | 0 | { |
376 | 0 | return TechniqueIterator(mTechniques.begin(), mTechniques.end()); |
377 | 0 | } |
378 | | //----------------------------------------------------------------------- |
379 | | Material::TechniqueIterator Material::getSupportedTechniqueIterator(void) |
380 | 0 | { |
381 | 0 | return TechniqueIterator(mSupportedTechniques.begin(), mSupportedTechniques.end()); |
382 | 0 | } |
383 | | //----------------------------------------------------------------------- |
384 | | bool Material::isTransparent(void) const |
385 | 0 | { |
386 | | // Check each technique |
387 | 0 | for (auto *t : mTechniques) |
388 | 0 | { |
389 | 0 | if (t->isTransparent()) |
390 | 0 | return true; |
391 | 0 | } |
392 | 0 | return false; |
393 | 0 | } |
394 | | //----------------------------------------------------------------------- |
395 | | void Material::compile(bool autoManageTextureUnits) |
396 | 0 | { |
397 | | // Compile each technique, then add it to the list of supported techniques |
398 | 0 | clearBestTechniqueList(); |
399 | 0 | mUnsupportedReasons.clear(); |
400 | |
|
401 | 0 | size_t techNo = 0; |
402 | 0 | for (auto *t : mTechniques) |
403 | 0 | { |
404 | 0 | String compileMessages = t->_compile(autoManageTextureUnits); |
405 | 0 | if (t->isSupported()) |
406 | 0 | { |
407 | 0 | insertSupportedTechnique(t); |
408 | 0 | } |
409 | 0 | else |
410 | 0 | { |
411 | | // Log informational |
412 | 0 | StringStream str; |
413 | 0 | str << "Material " << mName << " Technique " << techNo; |
414 | 0 | if (!t->getName().empty()) |
415 | 0 | str << "(" << t->getName() << ")"; |
416 | 0 | str << " is not supported. " << compileMessages; |
417 | 0 | LogManager::getSingleton().logMessage(str.str(), LML_TRIVIAL); |
418 | 0 | mUnsupportedReasons += compileMessages; |
419 | 0 | } |
420 | 0 | ++techNo; |
421 | 0 | } |
422 | |
|
423 | 0 | mCompilationRequired = false; |
424 | | |
425 | | // Did we find any? |
426 | 0 | if (mSupportedTechniques.empty()) |
427 | 0 | { |
428 | 0 | LogManager::getSingleton().stream(LML_WARNING) |
429 | 0 | << "Warning: material " << mName << " has no supportable " |
430 | 0 | << "Techniques and will be blank. Explanation: \n" << mUnsupportedReasons; |
431 | 0 | } |
432 | 0 | } |
433 | | //----------------------------------------------------------------------- |
434 | | void Material::clearBestTechniqueList(void) |
435 | 0 | { |
436 | 0 | mSupportedTechniques.clear(); |
437 | 0 | mBestTechniquesBySchemeList.clear(); |
438 | 0 | mCompilationRequired = true; |
439 | 0 | } |
440 | | //----------------------------------------------------------------------- |
441 | 0 | #define ALL_TECHNIQUES(fncall) for(auto t : mTechniques) t->fncall |
442 | 0 | void Material::setPointSize(Real ps) { ALL_TECHNIQUES(setPointSize(ps)); } |
443 | | //----------------------------------------------------------------------- |
444 | 0 | void Material::setAmbient(float red, float green, float blue) { setAmbient(ColourValue(red, green, blue)); } |
445 | | //----------------------------------------------------------------------- |
446 | 0 | void Material::setAmbient(const ColourValue& ambient) { ALL_TECHNIQUES(setAmbient(ambient)); } |
447 | | //----------------------------------------------------------------------- |
448 | | void Material::setDiffuse(float red, float green, float blue, float alpha) |
449 | 0 | { |
450 | 0 | ALL_TECHNIQUES(setDiffuse(red, green, blue, alpha)); |
451 | 0 | } |
452 | | //----------------------------------------------------------------------- |
453 | 0 | void Material::setDiffuse(const ColourValue& diffuse) { setDiffuse(diffuse.r, diffuse.g, diffuse.b, diffuse.a); } |
454 | | //----------------------------------------------------------------------- |
455 | | void Material::setSpecular(float red, float green, float blue, float alpha) |
456 | 0 | { |
457 | 0 | ALL_TECHNIQUES(setSpecular(red, green, blue, alpha)); |
458 | 0 | } |
459 | | //----------------------------------------------------------------------- |
460 | | void Material::setSpecular(const ColourValue& specular) |
461 | 0 | { |
462 | 0 | setSpecular(specular.r, specular.g, specular.b, specular.a); |
463 | 0 | } |
464 | | //----------------------------------------------------------------------- |
465 | 0 | void Material::setShininess(Real val) { ALL_TECHNIQUES(setShininess(val)); } |
466 | | //----------------------------------------------------------------------- |
467 | | void Material::setSelfIllumination(float red, float green, float blue) |
468 | 0 | { |
469 | 0 | setSelfIllumination(ColourValue(red, green, blue)); |
470 | 0 | } |
471 | | //----------------------------------------------------------------------- |
472 | 0 | void Material::setSelfIllumination(const ColourValue& selfIllum) { ALL_TECHNIQUES(setSelfIllumination(selfIllum)); } |
473 | | //----------------------------------------------------------------------- |
474 | 0 | void Material::setDepthCheckEnabled(bool enabled) { ALL_TECHNIQUES(setDepthCheckEnabled(enabled)); } |
475 | | //----------------------------------------------------------------------- |
476 | 0 | void Material::setDepthWriteEnabled(bool enabled) { ALL_TECHNIQUES(setDepthWriteEnabled(enabled)); } |
477 | | //----------------------------------------------------------------------- |
478 | 0 | void Material::setDepthFunction(CompareFunction func) { ALL_TECHNIQUES(setDepthFunction(func)); } |
479 | | //----------------------------------------------------------------------- |
480 | 0 | void Material::setColourWriteEnabled(bool enabled) { ALL_TECHNIQUES(setColourWriteEnabled(enabled)); } |
481 | | //----------------------------------------------------------------------- |
482 | | void Material::setColourWriteEnabled(bool red, bool green, bool blue, bool alpha) |
483 | 0 | { |
484 | 0 | ALL_TECHNIQUES(setColourWriteEnabled(red, green, blue, alpha)); |
485 | 0 | } |
486 | | //----------------------------------------------------------------------- |
487 | 0 | void Material::setCullingMode(CullingMode mode) { ALL_TECHNIQUES(setCullingMode(mode)); } |
488 | | //----------------------------------------------------------------------- |
489 | 0 | void Material::setManualCullingMode(ManualCullingMode mode) { ALL_TECHNIQUES(setManualCullingMode(mode)); } |
490 | | //----------------------------------------------------------------------- |
491 | 0 | void Material::setLightingEnabled(bool enabled) { ALL_TECHNIQUES(setLightingEnabled(enabled)); } |
492 | | //----------------------------------------------------------------------- |
493 | 0 | void Material::setShadingMode(ShadeOptions mode) { ALL_TECHNIQUES(setShadingMode(mode)); } |
494 | | //----------------------------------------------------------------------- |
495 | | void Material::setFog(bool overrideScene, FogMode mode, const ColourValue& colour, Real expDensity, |
496 | | Real linearStart, Real linearEnd) |
497 | 0 | { |
498 | 0 | ALL_TECHNIQUES(setFog(overrideScene, mode, colour, expDensity, linearStart, linearEnd)); |
499 | 0 | } |
500 | | //----------------------------------------------------------------------- |
501 | | void Material::setDepthBias(float constantBias, float slopeScaleBias) |
502 | 0 | { |
503 | 0 | ALL_TECHNIQUES(setDepthBias(constantBias, slopeScaleBias)); |
504 | 0 | } |
505 | | //----------------------------------------------------------------------- |
506 | | void Material::setTextureFiltering(TextureFilterOptions filterType) |
507 | 0 | { |
508 | 0 | ALL_TECHNIQUES(setTextureFiltering(filterType)); |
509 | 0 | } |
510 | | // -------------------------------------------------------------------- |
511 | 0 | void Material::setTextureAnisotropy(int maxAniso) { ALL_TECHNIQUES(setTextureAnisotropy(maxAniso)); } |
512 | | // -------------------------------------------------------------------- |
513 | 0 | void Material::setSceneBlending(const SceneBlendType sbt) { ALL_TECHNIQUES(setSceneBlending(sbt)); } |
514 | | // -------------------------------------------------------------------- |
515 | | void Material::setSeparateSceneBlending(const SceneBlendType sbt, const SceneBlendType sbta) |
516 | 0 | { |
517 | 0 | ALL_TECHNIQUES(setSeparateSceneBlending(sbt, sbta)); |
518 | 0 | } |
519 | | // -------------------------------------------------------------------- |
520 | | void Material::setSceneBlending(const SceneBlendFactor sourceFactor, const SceneBlendFactor destFactor) |
521 | 0 | { |
522 | 0 | ALL_TECHNIQUES(setSceneBlending(sourceFactor, destFactor)); |
523 | 0 | } |
524 | | // -------------------------------------------------------------------- |
525 | | void Material::setSeparateSceneBlending( const SceneBlendFactor sourceFactor, const SceneBlendFactor destFactor, const SceneBlendFactor sourceFactorAlpha, const SceneBlendFactor destFactorAlpha) |
526 | 0 | { |
527 | 0 | ALL_TECHNIQUES(setSeparateSceneBlending(sourceFactor, destFactor, sourceFactorAlpha, destFactorAlpha)); |
528 | 0 | } |
529 | | #undef ALL_TECHNIQUES |
530 | | // -------------------------------------------------------------------- |
531 | | void Material::_notifyNeedsRecompile(void) |
532 | 0 | { |
533 | 0 | mCompilationRequired = true; |
534 | | // Also need to unload to ensure we loaded any new items |
535 | 0 | if (isLoaded()) // needed to stop this being called in 'loading' state |
536 | 0 | unload(); |
537 | 0 | } |
538 | | // -------------------------------------------------------------------- |
539 | | void Material::setLodLevels(const LodValueList& lodValues) |
540 | 0 | { |
541 | | // Square the distances for the internal list |
542 | | // First, clear and add single zero entry |
543 | 0 | mLodValues.clear(); |
544 | 0 | mUserLodValues.clear(); |
545 | 0 | mUserLodValues.push_back(0); |
546 | 0 | if (mLodStrategy) |
547 | 0 | mLodValues.push_back(mLodStrategy->getBaseValue()); |
548 | 0 | for (auto& v : lodValues) |
549 | 0 | { |
550 | 0 | mUserLodValues.push_back(v); |
551 | 0 | if (mLodStrategy) |
552 | 0 | mLodValues.push_back(mLodStrategy->transformUserValue(v)); |
553 | 0 | } |
554 | 0 | } |
555 | | // -------------------------------------------------------------------- |
556 | | ushort Material::getLodIndex(Real value) const |
557 | 0 | { |
558 | 0 | return mLodStrategy->getIndex(value, mLodValues); |
559 | 0 | } |
560 | | // -------------------------------------------------------------------- |
561 | | Material::LodValueIterator Material::getLodValueIterator(void) const |
562 | 0 | { |
563 | 0 | return LodValueIterator(mLodValues.begin(), mLodValues.end()); |
564 | 0 | } |
565 | | // -------------------------------------------------------------------- |
566 | | Material::LodValueIterator Material::getUserLodValueIterator(void) const |
567 | 0 | { |
568 | 0 | return LodValueIterator(mUserLodValues.begin(), mUserLodValues.end()); |
569 | 0 | } |
570 | | //--------------------------------------------------------------------- |
571 | | const LodStrategy *Material::getLodStrategy() const |
572 | 0 | { |
573 | 0 | return mLodStrategy; |
574 | 0 | } |
575 | | //--------------------------------------------------------------------- |
576 | | void Material::setLodStrategy(LodStrategy *lodStrategy) |
577 | 0 | { |
578 | 0 | mLodStrategy = lodStrategy; |
579 | |
|
580 | 0 | assert(mLodValues.size()); |
581 | 0 | mLodValues[0] = mLodStrategy->getBaseValue(); |
582 | | |
583 | | // Re-transform all user LOD values (starting at index 1, no need to transform base value) |
584 | 0 | for (size_t i = 1; i < mUserLodValues.size(); ++i) |
585 | 0 | mLodValues[i] = mLodStrategy->transformUserValue(mUserLodValues[i]); |
586 | 0 | } |
587 | | //--------------------------------------------------------------------- |
588 | | } |