MaterialParameter.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. #include "Base.h"
  2. #include "MaterialParameter.h"
  3. namespace gameplay
  4. {
  5. MaterialParameter::MaterialParameter(const char* name) :
  6. _type(MaterialParameter::NONE), _count(1), _dynamic(false), _name(name), _uniform(NULL)
  7. {
  8. clearValue();
  9. }
  10. MaterialParameter::~MaterialParameter()
  11. {
  12. clearValue();
  13. }
  14. void MaterialParameter::clearValue()
  15. {
  16. if (_dynamic)
  17. {
  18. switch (_type)
  19. {
  20. case MaterialParameter::FLOAT:
  21. case MaterialParameter::VECTOR2:
  22. case MaterialParameter::VECTOR3:
  23. case MaterialParameter::VECTOR4:
  24. case MaterialParameter::MATRIX:
  25. SAFE_DELETE_ARRAY(_value.floatPtrValue);
  26. break;
  27. case MaterialParameter::INT:
  28. SAFE_DELETE_ARRAY(_value.intPtrValue);
  29. break;
  30. case MaterialParameter::METHOD:
  31. SAFE_RELEASE(_value.method);
  32. break;
  33. }
  34. _dynamic = false;
  35. _count = 1;
  36. }
  37. else
  38. {
  39. switch (_type)
  40. {
  41. case MaterialParameter::SAMPLER:
  42. if (_value.samplerValue)
  43. {
  44. const_cast<Texture::Sampler*>(_value.samplerValue)->release();
  45. }
  46. break;
  47. }
  48. }
  49. memset(&_value, 0, sizeof(_value));
  50. _type = MaterialParameter::NONE;
  51. }
  52. const char* MaterialParameter::getName() const
  53. {
  54. return _name.c_str();
  55. }
  56. void MaterialParameter::setValue(float value)
  57. {
  58. clearValue();
  59. _value.floatValue = value;
  60. _type = MaterialParameter::FLOAT;
  61. }
  62. void MaterialParameter::setValue(int value)
  63. {
  64. clearValue();
  65. _value.intValue = value;
  66. _type = MaterialParameter::INT;
  67. }
  68. void MaterialParameter::setValue(const float* values, unsigned int count)
  69. {
  70. clearValue();
  71. _value.floatPtrValue = const_cast<float*> (values);
  72. _count = count;
  73. _type = MaterialParameter::FLOAT;
  74. }
  75. void MaterialParameter::setValue(const int* values, unsigned int count)
  76. {
  77. clearValue();
  78. _value.intPtrValue = const_cast<int*> (values);
  79. _count = count;
  80. _type = MaterialParameter::INT;
  81. }
  82. void MaterialParameter::setValue(const Vector2& value)
  83. {
  84. clearValue();
  85. // Copy data by-value into a dynamic array.
  86. float* array = new float[2];
  87. memcpy(array, &value.x, sizeof(float) * 2);
  88. _value.floatPtrValue = array;
  89. _dynamic = true;
  90. _count = 1;
  91. _type = MaterialParameter::VECTOR2;
  92. }
  93. void MaterialParameter::setValue(const Vector2* values, unsigned int count)
  94. {
  95. clearValue();
  96. _value.floatPtrValue = const_cast<float*> (&values[0].x);
  97. _count = count;
  98. _type = MaterialParameter::VECTOR2;
  99. }
  100. void MaterialParameter::setValue(const Vector3& value)
  101. {
  102. clearValue();
  103. // Copy data by-value into a dynamic array.
  104. float* array = new float[3];
  105. memcpy(array, &value.x, sizeof(float) * 3);
  106. _value.floatPtrValue = array;
  107. _dynamic = true;
  108. _count = 1;
  109. _type = MaterialParameter::VECTOR3;
  110. }
  111. void MaterialParameter::setValue(const Vector3* values, unsigned int count)
  112. {
  113. clearValue();
  114. _value.floatPtrValue = const_cast<float*> (&values[0].x);
  115. _count = count;
  116. _type = MaterialParameter::VECTOR3;
  117. }
  118. void MaterialParameter::setValue(const Vector4& value)
  119. {
  120. clearValue();
  121. // Copy data by-value into a dynamic array.
  122. float* array = new float[4];
  123. memcpy(array, &value.x, sizeof(float) * 4);
  124. _value.floatPtrValue = array;
  125. _dynamic = true;
  126. _count = 1;
  127. _type = MaterialParameter::VECTOR4;
  128. }
  129. void MaterialParameter::setValue(const Vector4* values, unsigned int count)
  130. {
  131. clearValue();
  132. _value.floatPtrValue = const_cast<float*> (&values[0].x);
  133. _count = count;
  134. _type = MaterialParameter::VECTOR4;
  135. }
  136. void MaterialParameter::setValue(const Matrix& value)
  137. {
  138. // If this parameter is already storing a single dynamic matrix, no need to clear it.
  139. if (!(_dynamic && _count == 1 && _type == MaterialParameter::MATRIX && _value.floatPtrValue != NULL))
  140. {
  141. clearValue();
  142. // Allocate a new dynamic matrix.
  143. _value.floatPtrValue = new float[16];
  144. }
  145. memcpy(_value.floatPtrValue, value.m, sizeof(float) * 16);
  146. _dynamic = true;
  147. _count = 1;
  148. _type = MaterialParameter::MATRIX;
  149. }
  150. void MaterialParameter::setValue(const Matrix* values, unsigned int count)
  151. {
  152. clearValue();
  153. _value.floatPtrValue = const_cast<Matrix&> (values[0]).m;
  154. _count = count;
  155. _type = MaterialParameter::MATRIX;
  156. }
  157. void MaterialParameter::setValue(const Texture::Sampler* sampler)
  158. {
  159. clearValue();
  160. if (sampler)
  161. {
  162. const_cast<Texture::Sampler*>(sampler)->addRef();
  163. _value.samplerValue = sampler;
  164. _type = MaterialParameter::SAMPLER;
  165. }
  166. }
  167. Texture::Sampler* MaterialParameter::setValue(const char* texturePath, bool generateMipmaps)
  168. {
  169. if (texturePath)
  170. {
  171. clearValue();
  172. Texture::Sampler* sampler = Texture::Sampler::create(texturePath, generateMipmaps);
  173. if (sampler)
  174. {
  175. _value.samplerValue = sampler;
  176. _type = MaterialParameter::SAMPLER;
  177. }
  178. return sampler;
  179. }
  180. return NULL;
  181. }
  182. void MaterialParameter::bind(Effect* effect)
  183. {
  184. // If we had a Uniform cached that is not from the passed in effect,
  185. // we need to update our uniform to point to the new effect's uniform.
  186. if (!_uniform || _uniform->getEffect() != effect)
  187. {
  188. _uniform = effect->getUniform(_name.c_str());
  189. if (!_uniform)
  190. {
  191. // This parameter was not found in the specified effect, so do nothing.
  192. WARN_VARG("Warning: Material parameter '%s' not found in effect '%s'.", _name.c_str(), effect->getId());
  193. return;
  194. }
  195. }
  196. switch (_type)
  197. {
  198. case MaterialParameter::FLOAT:
  199. if (_count == 1)
  200. {
  201. effect->setValue(_uniform, _value.floatValue);
  202. }
  203. else
  204. {
  205. assert(_value.floatPtrValue);
  206. effect->setValue(_uniform, _value.floatPtrValue, _count);
  207. }
  208. break;
  209. case MaterialParameter::INT:
  210. if (_count == 1)
  211. {
  212. effect->setValue(_uniform, _value.intValue);
  213. }
  214. else
  215. {
  216. assert(_value.intPtrValue);
  217. effect->setValue(_uniform, _value.intPtrValue, _count);
  218. }
  219. break;
  220. case MaterialParameter::VECTOR2:
  221. assert(_value.floatPtrValue);
  222. effect->setValue(_uniform, reinterpret_cast<Vector2*>(_value.floatPtrValue), _count);
  223. break;
  224. case MaterialParameter::VECTOR3:
  225. assert(_value.floatPtrValue);
  226. effect->setValue(_uniform, reinterpret_cast<Vector3*>(_value.floatPtrValue), _count);
  227. break;
  228. case MaterialParameter::VECTOR4:
  229. assert(_value.floatPtrValue);
  230. effect->setValue(_uniform, reinterpret_cast<Vector4*>(_value.floatPtrValue), _count);
  231. break;
  232. case MaterialParameter::MATRIX:
  233. assert(_value.floatPtrValue);
  234. effect->setValue(_uniform, reinterpret_cast<Matrix*>(_value.floatPtrValue), _count);
  235. break;
  236. case MaterialParameter::SAMPLER:
  237. assert(_value.samplerValue);
  238. effect->setValue(_uniform, _value.samplerValue);
  239. break;
  240. case MaterialParameter::METHOD:
  241. assert(_value.method);
  242. _value.method->setValue(effect);
  243. break;
  244. }
  245. }
  246. unsigned int MaterialParameter::getAnimationPropertyComponentCount(int propertyId) const
  247. {
  248. switch (propertyId)
  249. {
  250. case ANIMATE_UNIFORM:
  251. {
  252. switch (_type)
  253. {
  254. // These types don't support animation.
  255. case NONE:
  256. case MATRIX:
  257. case SAMPLER:
  258. case METHOD:
  259. return 0;
  260. case FLOAT:
  261. case INT:
  262. return _count;
  263. case VECTOR2:
  264. return 2 * _count;
  265. case VECTOR3:
  266. return 3 * _count;
  267. case VECTOR4:
  268. return 4 * _count;
  269. default:
  270. return 0;
  271. }
  272. }
  273. }
  274. return 0;
  275. }
  276. void MaterialParameter::getAnimationPropertyValue(int propertyId, AnimationValue* value)
  277. {
  278. switch (propertyId)
  279. {
  280. case ANIMATE_UNIFORM:
  281. {
  282. switch (_type)
  283. {
  284. case FLOAT:
  285. if (_count == 1)
  286. {
  287. value->setFloat(0, _value.floatValue);
  288. }
  289. else
  290. {
  291. for (unsigned int i = 0; i < _count; i++)
  292. {
  293. value->setFloat(i, _value.floatPtrValue[i]);
  294. }
  295. }
  296. break;
  297. case INT:
  298. if (_count == 1)
  299. {
  300. value->setFloat(0, _value.intValue);
  301. }
  302. else
  303. {
  304. for (unsigned int i = 0; i < _count; i++)
  305. {
  306. value->setFloat(i, _value.intPtrValue[i]);
  307. }
  308. }
  309. break;
  310. case VECTOR2:
  311. for (unsigned int i = 0; i < _count; i++)
  312. {
  313. value->setFloat(_value.floatPtrValue, i * 2, 2);
  314. }
  315. break;
  316. case VECTOR3:
  317. for (unsigned int i = 0; i < _count; i++)
  318. {
  319. value->setFloat(_value.floatPtrValue, i * 3, 3);
  320. }
  321. break;
  322. case VECTOR4:
  323. for (unsigned int i = 0; i < _count; i++)
  324. {
  325. value->setFloat(_value.floatPtrValue, i * 4, 4);
  326. }
  327. break;
  328. // UNSUPPORTED: NONE, MATRIX, METHOD, SAMPLER
  329. }
  330. }
  331. }
  332. }
  333. void MaterialParameter::setAnimationPropertyValue(int propertyId, AnimationValue* value, float blendWeight)
  334. {
  335. assert(blendWeight >= 0.0f && blendWeight <= 1.0f);
  336. switch (propertyId)
  337. {
  338. case ANIMATE_UNIFORM:
  339. {
  340. switch (_type)
  341. {
  342. case FLOAT:
  343. {
  344. if (_count == 1)
  345. {
  346. if ((_animationPropertyBitFlag & ANIMATION_UNIFORM_BIT) != ANIMATION_UNIFORM_BIT)
  347. {
  348. _animationPropertyBitFlag |= ANIMATION_UNIFORM_BIT;
  349. _value.floatValue = value->getFloat(0);
  350. }
  351. else
  352. {
  353. _value.floatValue = Curve::lerp(blendWeight, _value.floatValue, value->getFloat(0));
  354. }
  355. }
  356. else
  357. {
  358. applyAnimationValue(value, blendWeight, 1);
  359. }
  360. break;
  361. }
  362. case INT:
  363. {
  364. if (_count == 1)
  365. {
  366. if ((_animationPropertyBitFlag & ANIMATION_UNIFORM_BIT) != ANIMATION_UNIFORM_BIT)
  367. {
  368. _animationPropertyBitFlag |= ANIMATION_UNIFORM_BIT;
  369. _value.intValue = value->getFloat(0);
  370. }
  371. else
  372. {
  373. _value.intValue = Curve::lerp(blendWeight, _value.intValue, value->getFloat(0));
  374. }
  375. }
  376. else
  377. {
  378. if ((_animationPropertyBitFlag & ANIMATION_UNIFORM_BIT) != ANIMATION_UNIFORM_BIT)
  379. {
  380. _animationPropertyBitFlag |= ANIMATION_UNIFORM_BIT;
  381. for (unsigned int i = 0; i < _count; i++)
  382. _value.intPtrValue[i] = value->getFloat(i);
  383. }
  384. else
  385. {
  386. for (unsigned int i = 0; i < _count; i++)
  387. _value.intPtrValue[i] = Curve::lerp(blendWeight, _value.intPtrValue[i], value->getFloat(i));
  388. }
  389. }
  390. break;
  391. }
  392. case VECTOR2:
  393. {
  394. applyAnimationValue(value, blendWeight, 2);
  395. break;
  396. }
  397. case VECTOR3:
  398. {
  399. applyAnimationValue(value, blendWeight, 3);
  400. break;
  401. }
  402. case VECTOR4:
  403. {
  404. applyAnimationValue(value, blendWeight, 4);
  405. break;
  406. }
  407. // UNSUPPORTED: NONE, MATRIX, METHOD, SAMPLER
  408. }
  409. }
  410. }
  411. }
  412. void MaterialParameter::applyAnimationValue(AnimationValue* value, float blendWeight, int components)
  413. {
  414. unsigned int count = _count * components;
  415. if ((_animationPropertyBitFlag & ANIMATION_UNIFORM_BIT) != ANIMATION_UNIFORM_BIT)
  416. {
  417. _animationPropertyBitFlag |= ANIMATION_UNIFORM_BIT;
  418. for (unsigned int i = 0; i < count; i++)
  419. _value.floatPtrValue[i] = value->getFloat(i);
  420. }
  421. else
  422. {
  423. for (unsigned int i = 0; i < count; i++)
  424. _value.floatPtrValue[i] = Curve::lerp(blendWeight, _value.floatPtrValue[i], value->getFloat(i));
  425. }
  426. }
  427. void MaterialParameter::cloneInto(MaterialParameter* materialParameter) const
  428. {
  429. materialParameter->_type = _type;
  430. materialParameter->_count = _count;
  431. materialParameter->_dynamic = _dynamic;
  432. materialParameter->_uniform = _uniform;
  433. switch (_type)
  434. {
  435. case NONE:
  436. break;
  437. case FLOAT:
  438. materialParameter->setValue(_value.floatValue);
  439. break;
  440. case INT:
  441. materialParameter->setValue(_value.intValue);
  442. break;
  443. case VECTOR2:
  444. {
  445. Vector2* value = reinterpret_cast<Vector2*>(_value.floatPtrValue);
  446. if (_count == 1)
  447. {
  448. materialParameter->setValue(*value);
  449. }
  450. else
  451. {
  452. materialParameter->setValue(value, _count);
  453. }
  454. break;
  455. }
  456. case VECTOR3:
  457. {
  458. Vector3* value = reinterpret_cast<Vector3*>(_value.floatPtrValue);
  459. if (_count == 1)
  460. {
  461. materialParameter->setValue(*value);
  462. }
  463. else
  464. {
  465. materialParameter->setValue(value, _count);
  466. }
  467. break;
  468. }
  469. case VECTOR4:
  470. {
  471. Vector4* value = reinterpret_cast<Vector4*>(_value.floatPtrValue);
  472. if (_count == 1)
  473. {
  474. materialParameter->setValue(*value);
  475. }
  476. else
  477. {
  478. materialParameter->setValue(value, _count);
  479. }
  480. break;
  481. }
  482. case MATRIX:
  483. {
  484. Matrix* value = reinterpret_cast<Matrix*>(_value.floatPtrValue);
  485. if (_count == 1)
  486. {
  487. materialParameter->setValue(*value);
  488. }
  489. else
  490. {
  491. materialParameter->setValue(value, _count);
  492. }
  493. break;
  494. }
  495. case SAMPLER:
  496. materialParameter->setValue(_value.samplerValue);
  497. break;
  498. case METHOD:
  499. materialParameter->_value.method = _value.method;
  500. materialParameter->_value.method->addRef();
  501. break;
  502. }
  503. }
  504. }