PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/HelloOpenGL/HelloOpenGL/CC3Foundation.m

https://gitlab.com/praveenvelanati/ios-demo
Objective C | 570 lines | 429 code | 92 blank | 49 comment | 48 complexity | 95fbf83f314f9328412d46132a04c981 MD5 | raw file
  1. /*
  2. * CC3Foundation.mm
  3. *
  4. * $Version: cocos3d 0.5.4 (f5cd4df5048c) on 2011-04-14 $
  5. * Author: Bill Hollings
  6. * Copyright (c) 2010-2011 The Brenwill Workshop Ltd. All rights reserved.
  7. * http://www.brenwill.com
  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. * http://en.wikipedia.org/wiki/MIT_License
  28. *
  29. * See header file CC3Foundation.h for full API documentation.
  30. */
  31. #import "CC3Foundation.h"
  32. #pragma mark -
  33. #pragma mark 3D cartesian vector structure and functions
  34. NSString* NSStringFromCC3Vector(CC3Vector v) {
  35. return [NSString stringWithFormat: @"(%.3f, %.3f, %.3f)", v.x, v.y, v.z];
  36. }
  37. CC3Vector CC3VectorMake(GLfloat x, GLfloat y, GLfloat z) {
  38. CC3Vector v;
  39. v.x = x;
  40. v.y = y;
  41. v.z = z;
  42. return v;
  43. }
  44. BOOL CC3VectorsAreEqual(CC3Vector v1, CC3Vector v2) {
  45. return v1.x == v2.x && v1.y == v2.y && v1.z == v2.z;
  46. }
  47. CC3Vector CC3VectorMinimize(CC3Vector v1, CC3Vector v2) {
  48. CC3Vector vMin;
  49. vMin.x = MIN(v1.x, v2.x);
  50. vMin.y = MIN(v1.y, v2.y);
  51. vMin.z = MIN(v1.z, v2.z);
  52. return vMin;
  53. }
  54. CC3Vector CC3VectorMaximize(CC3Vector v1, CC3Vector v2) {
  55. CC3Vector vMax;
  56. vMax.x = MAX(v1.x, v2.x);
  57. vMax.y = MAX(v1.y, v2.y);
  58. vMax.z = MAX(v1.z, v2.z);
  59. return vMax;
  60. }
  61. GLfloat CC3VectorLength(CC3Vector v) {
  62. GLfloat x = v.x;
  63. GLfloat y = v.y;
  64. GLfloat z = v.z;
  65. return sqrtf((x * x) + (y * y) + (z * z));
  66. }
  67. CC3Vector CC3VectorNormalize(CC3Vector v) {
  68. GLfloat len = CC3VectorLength(v);
  69. if (len == 0.0) return v;
  70. CC3Vector normal;
  71. normal.x = v.x / len;
  72. normal.y = v.y / len;
  73. normal.z = v.z / len;
  74. return normal;
  75. }
  76. CC3Vector CC3VectorNegate(CC3Vector v) {
  77. CC3Vector result;
  78. result.x = -v.x;
  79. result.y = -v.y;
  80. result.z = -v.z;
  81. return result;
  82. }
  83. CC3Vector CC3VectorInvert(CC3Vector v) {
  84. CC3Vector result;
  85. result.x = 1.0 / v.x;
  86. result.y = 1.0 / v.y;
  87. result.z = 1.0 / v.z;
  88. return result;
  89. }
  90. CC3Vector CC3VectorDifference(CC3Vector minuend, CC3Vector subtrahend) {
  91. CC3Vector difference;
  92. difference.x = minuend.x - subtrahend.x;
  93. difference.y = minuend.y - subtrahend.y;
  94. difference.z = minuend.z - subtrahend.z;
  95. return difference;
  96. }
  97. CC3Vector CC3VectorRotationalDifference(CC3Vector minuend, CC3Vector subtrahend) {
  98. CC3Vector difference;
  99. difference.x = CyclicDifference(minuend.x, subtrahend.x, kCircleDegreesPeriod);
  100. difference.y = CyclicDifference(minuend.y, subtrahend.y, kCircleDegreesPeriod);
  101. difference.z = CyclicDifference(minuend.z, subtrahend.z, kCircleDegreesPeriod);
  102. return difference;
  103. }
  104. GLfloat CC3VectorDistance(CC3Vector start, CC3Vector end) {
  105. return CC3VectorLength(CC3VectorDifference(end, start));
  106. }
  107. CC3Vector CC3VectorScale(CC3Vector v, CC3Vector scale) {
  108. CC3Vector result;
  109. result.x = v.x * scale.x;
  110. result.y = v.y * scale.y;
  111. result.z = v.z * scale.z;
  112. return result;
  113. }
  114. CC3Vector CC3VectorScaleUniform(CC3Vector v, GLfloat scale) {
  115. CC3Vector result;
  116. result.x = v.x * scale;
  117. result.y = v.y * scale;
  118. result.z = v.z * scale;
  119. return result;
  120. }
  121. CC3Vector CC3VectorAdd(CC3Vector v, CC3Vector translation) {
  122. CC3Vector result;
  123. result.x = v.x + translation.x;
  124. result.y = v.y + translation.y;
  125. result.z = v.z + translation.z;
  126. return result;
  127. }
  128. GLfloat CC3VectorDot(CC3Vector v1, CC3Vector v2) {
  129. return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z);
  130. }
  131. CC3Vector CC3VectorCross(CC3Vector v1, CC3Vector v2) {
  132. CC3Vector result;
  133. result.x = v1.y * v2.z - v1.z * v2.y;
  134. result.y = v1.z * v2.x - v1.x * v2.z;
  135. result.z = v1.x * v2.y - v1.y * v2.x;
  136. return result;
  137. }
  138. CC3Vector CC3VectorLerp(CC3Vector v1, CC3Vector v2, GLfloat blendFactor) {
  139. // Short-circuit if we know it's one of the end-points.
  140. if (blendFactor == 0.0f) {
  141. return v1;
  142. } else if (blendFactor == 1.0f) {
  143. return v2;
  144. }
  145. // Return: v1 + (blendFactor * (v2 - v1))
  146. return CC3VectorAdd(v1, CC3VectorScaleUniform(CC3VectorDifference(v2, v1), blendFactor));
  147. }
  148. #pragma mark -
  149. #pragma mark 3D angular vector structure and functions
  150. NSString* NSStringFromCC3AngularVector(CC3AngularVector av) {
  151. return [NSString stringWithFormat: @"(%.3f, %.3f, %.3f)", av.heading, av.inclination, av.radius];
  152. }
  153. CC3AngularVector CC3AngularVectorMake(GLfloat heading, GLfloat inclination, GLfloat radius) {
  154. CC3AngularVector av;
  155. av.heading = heading;
  156. av.inclination = inclination;
  157. av.radius = radius;
  158. return av;
  159. }
  160. CC3AngularVector CC3AngularVectorFromVector(CC3Vector aCoord) {
  161. CC3AngularVector av;
  162. av.radius = CC3VectorLength(aCoord);
  163. av.inclination = av.radius ? RadiansToDegrees(asinf(aCoord.y / av.radius)) : 0.0;
  164. av.heading = RadiansToDegrees(atan2f(aCoord.x, -aCoord.z));
  165. return av;
  166. }
  167. CC3Vector CC3VectorFromAngularVector(CC3AngularVector av) {
  168. CC3Vector unitDir;
  169. // First, incline up the Y-axis from the negative Z-axis.
  170. GLfloat radInclination = DegreesToRadians(av.inclination);
  171. unitDir.y = sinf(radInclination);
  172. GLfloat xzLen = cosf(radInclination);
  173. // Now rotate around the Y-axis to the heading. The length of the projection of the direction
  174. // vector into the X-Z plane is the length of the projection onto the negative Z-axis after
  175. // the initial inclination. Use this length as the basis for calculating the X & Z CC3Vectors.
  176. // The result is a unit direction vector projected into all three axes.
  177. GLfloat radHeading = DegreesToRadians(av.heading);
  178. unitDir.x = xzLen * sinf(radHeading);
  179. unitDir.z = -xzLen * cosf(radHeading);
  180. return CC3VectorScaleUniform(unitDir, av.radius);
  181. }
  182. CC3AngularVector CC3AngularVectorDifference(CC3AngularVector minuend, CC3AngularVector subtrahend) {
  183. CC3AngularVector difference;
  184. difference.heading = CyclicDifference(minuend.heading, subtrahend.heading, kCircleDegreesPeriod);
  185. difference.inclination = minuend.inclination - subtrahend.inclination;
  186. difference.radius = minuend.radius - subtrahend.radius;
  187. return difference;
  188. }
  189. #pragma mark -
  190. #pragma mark Cartesian vector in 4D homogeneous coordinate space structure and functions
  191. NSString* NSStringFromCC3Vector4(CC3Vector4 v) {
  192. return [NSString stringWithFormat: @"(%.3f, %.3f, %.3f, %.3f)", v.x, v.y, v.z, v.w];
  193. }
  194. CC3Vector4 CC3Vector4Make(GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
  195. CC3Vector4 v;
  196. v.x = x;
  197. v.y = y;
  198. v.z = z;
  199. v.w = w;
  200. return v;
  201. }
  202. CC3Vector4 CC3Vector4FromCC3Vector(CC3Vector v, GLfloat w) {
  203. CC3Vector4 v4;
  204. v4.x = v.x;
  205. v4.y = v.y;
  206. v4.z = v.z;
  207. v4.w = w;
  208. return v4;
  209. }
  210. CC3Vector CC3VectorFromCC3Vector4(CC3Vector4 v) {
  211. CC3Vector4 hv = CC3Vector4Homogenize(v);
  212. CC3Vector v3;
  213. v3.x = hv.x;
  214. v3.y = hv.y;
  215. v3.z = hv.z;
  216. return v3;
  217. }
  218. BOOL CC3Vector4sAreEqual(CC3Vector4 v1, CC3Vector4 v2) {
  219. return v1.x == v2.x && v1.y == v2.y && v1.z == v2.z && v1.w == v2.w;
  220. }
  221. CC3Vector4 CC3Vector4Homogenize(CC3Vector4 v) {
  222. if (v.w == 0.0f) {
  223. return v;
  224. }
  225. CC3Vector4 hv;
  226. hv.x = v.x / v.w;
  227. hv.y = v.y / v.w;
  228. hv.z = v.z / v.w;
  229. hv.w = 1.0;
  230. return hv;
  231. }
  232. GLfloat CC3Vector4Length(CC3Vector4 v) {
  233. GLfloat x = v.x;
  234. GLfloat y = v.y;
  235. GLfloat z = v.z;
  236. GLfloat w = v.w;
  237. return sqrtf((x * x) + (y * y) + (z * z) + (w * w));
  238. }
  239. CC3Vector4 CC3Vector4Normalize(CC3Vector4 v) {
  240. GLfloat mag = CC3Vector4Length(v);
  241. CC3Vector4 normal;
  242. normal.x = v.x / mag;
  243. normal.y = v.y / mag;
  244. normal.z = v.z / mag;
  245. normal.w = v.w / mag;
  246. return normal;
  247. }
  248. CC3Vector4 CC3Vector4Negate(CC3Vector4 v) {
  249. CC3Vector4 result;
  250. result.x = -v.x;
  251. result.y = -v.y;
  252. result.z = -v.z;
  253. result.w = -v.w;
  254. return result;
  255. }
  256. CC3Vector4 CC3Vector4ScaleUniform(CC3Vector4 v, GLfloat scale) {
  257. CC3Vector4 result;
  258. result.x = v.x * scale;
  259. result.y = v.y * scale;
  260. result.z = v.z * scale;
  261. result.w = v.w * scale;
  262. return result;
  263. }
  264. CC3Vector4 CC3Vector4Translate(CC3Vector4 v, CC3Vector4 translation) {
  265. CC3Vector4 result;
  266. result.x = v.x + translation.x;
  267. result.y = v.y + translation.y;
  268. result.z = v.z + translation.z;
  269. result.w = v.w + translation.w;
  270. return result;
  271. }
  272. GLfloat CC3Vector4Dot(CC3Vector4 v1, CC3Vector4 v2) {
  273. return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z) + (v1.w * v2.w);
  274. }
  275. #define kSlerpCosAngleLinearEpsilon 0.01 // about 8 degrees
  276. CC3Vector4 CC3Vector4Slerp(CC3Vector4 v1, CC3Vector4 v2, GLfloat blendFactor) {
  277. // Short-circuit if we know it's one of the end-points.
  278. if (blendFactor == 0.0f) {
  279. return v1;
  280. } else if (blendFactor == 1.0f) {
  281. return v2;
  282. }
  283. GLfloat theta, cosTheta, oneOverSinTheta, v1Weight, v2Weight;
  284. cosTheta = CC3Vector4Dot(v1, v2) / (CC3Vector4Length(v1) * CC3Vector4Length(v2));
  285. // (Q and −Q map to the same rotation), the rotation path may turn either the "short way"
  286. // (less than 180°) or the "long way" (more than 180°). Long paths can be prevented by
  287. // negating one end if the dot product, cos(theta), is negative, thus ensuring that
  288. // −90° ≤ theta ≤ 90°. Taken from http://en.wikipedia.org/wiki/Slerp
  289. if (cosTheta < 0.0) {
  290. return CC3Vector4Slerp(v1, CC3Vector4Negate(v2), blendFactor);
  291. }
  292. // If angle close to zero (cos() close to one), save cycles by interpolating linearly
  293. if ((1.0 - cosTheta) < kSlerpCosAngleLinearEpsilon) {
  294. v1Weight = 1.0 - blendFactor;
  295. v2Weight = blendFactor;
  296. } else {
  297. theta = acosf(cosTheta);
  298. oneOverSinTheta = 1.0 / sinf(theta);
  299. v1Weight = (sinf(theta * (1.0 - blendFactor)) * oneOverSinTheta);
  300. v2Weight = (sinf(theta * blendFactor) * oneOverSinTheta);
  301. }
  302. CC3Vector4 result = CC3Vector4Normalize(CC3Vector4Translate(CC3Vector4ScaleUniform(v1, v1Weight),
  303. CC3Vector4ScaleUniform(v2, v2Weight)));
  304. LogTrace(@"SLERP with cos %.3f at %.3f between %@ and %@ is %@", cosTheta, blendFactor,
  305. NSStringFromCC3Vector4(v1), NSStringFromCC3Vector4(v2),
  306. NSStringFromCC3Vector4(result));
  307. return result;
  308. }
  309. #pragma mark -
  310. #pragma mark Plane and frustrum structures and functions
  311. NSString* NSStringFromCC3Plane(CC3Plane p) {
  312. return [NSString stringWithFormat: @"(%.3f, %.3f, %.3f, %.3f)", p.a, p.b, p.c, p.d];
  313. }
  314. CC3Plane CC3PlaneMake(GLfloat a, GLfloat b, GLfloat c, GLfloat d) {
  315. CC3Plane p;
  316. p.a = a;
  317. p.b = b;
  318. p.c = c;
  319. p.d = d;
  320. return p;
  321. }
  322. CC3Plane CC3PlaneFromPoints(CC3Vector p1, CC3Vector p2, CC3Vector p3) {
  323. CC3Vector v12 = CC3VectorDifference(p2, p1);
  324. CC3Vector v23 = CC3VectorDifference(p3, p2);
  325. CC3Vector n = CC3VectorNormalize(CC3VectorCross(v12, v23));
  326. GLfloat d = -CC3VectorDot(p1, n);
  327. return CC3PlaneMake(n.x, n.y, n.z, d);
  328. }
  329. CC3Vector CC3PlaneNormal(CC3Plane p) {
  330. return cc3v(p.a, p.b, p.c);
  331. }
  332. CC3Plane CC3PlaneNormalize(CC3Plane p) {
  333. GLfloat normLen = CC3VectorLength(CC3PlaneNormal(p));
  334. CC3Plane np;
  335. np.a = p.a / normLen;
  336. np.b = p.b / normLen;
  337. np.c = p.c / normLen;
  338. np.d = p.d / normLen;
  339. return np;
  340. }
  341. GLfloat CC3DistanceFromNormalizedPlane(CC3Plane p, CC3Vector v) {
  342. return (p.a * v.x) + (p.b * v.y) + (p.c * v.z) + p.d;
  343. }
  344. CC3Vector4 CC3RayIntersectionWithPlane(CC3Ray ray, CC3Plane plane) {
  345. // For a plane defined by v.pn + d = 0, where v is a point on the plane, pn is the normal
  346. // of the plane and d is a constant, and a ray defined by v(t) = rs + t*rd, where rs is
  347. // the ray start rd is the ray direction, and t is a multiple, the intersection occurs
  348. // where the two are equal: (rs + t*rd).pn + d = 0.
  349. // Solving for t gives t = -(rs.pn + d) / rd.pn
  350. // The denominator rd.n will be zero if the ray is parallel to the plane.
  351. CC3Vector pn = CC3PlaneNormal(plane);
  352. CC3Vector rs = ray.startLocation;
  353. CC3Vector rd = ray.direction;
  354. GLfloat dirDotNorm = CC3VectorDot(rd, pn);
  355. if (dirDotNorm != 0.0f) {
  356. GLfloat dirDist = -(CC3VectorDot(rs, pn) + plane.d) / CC3VectorDot(rd, pn);
  357. CC3Vector loc = CC3VectorAdd(rs, CC3VectorScaleUniform(rd, dirDist));
  358. return CC3Vector4FromCC3Vector(loc, dirDist);
  359. } else {
  360. return kCC3Vector4Zero;
  361. }
  362. }
  363. #pragma mark -
  364. #pragma mark Viewport structure and functions
  365. NSString* NSStringFromCC3Viewport(CC3Viewport vp) {
  366. return [NSString stringWithFormat: @"(%i, %i, %i, %i)", vp.x, vp.y, vp.w, vp.h];
  367. }
  368. CC3Viewport CC3ViewportMake(GLint x, GLint y, GLint w, GLint h) {
  369. CC3Viewport vp;
  370. vp.x = x;
  371. vp.y = y;
  372. vp.w = w;
  373. vp.h = h;
  374. return vp;
  375. }
  376. BOOL CC3ViewportsAreEqual(CC3Viewport vp1, CC3Viewport vp2) {
  377. return vp1.x == vp2.x && vp1.y == vp2.y && vp1.w == vp2.w && vp1.h == vp2.h;
  378. }
  379. BOOL CC3ViewportContainsPoint(CC3Viewport vp, CGPoint point) {
  380. return (point.x >= vp.x) && (point.x < vp.x + vp.w) &&
  381. (point.y >= vp.y) && (point.y < vp.y + vp.h);
  382. }
  383. CGRect CGRectFromCC3Viewport(CC3Viewport vp) {
  384. return CGRectMake(vp.x, vp.y, vp.w, vp.h);
  385. }
  386. #pragma mark -
  387. #pragma mark ccColor4F functions
  388. NSString* NSStringFromCCC4F(ccColor4F rgba) {
  389. return [NSString stringWithFormat: @"(%.2f, %.2f, %.2f, %.2f)", rgba.r, rgba.g, rgba.b, rgba.a];
  390. }
  391. ccColor4F CCC4FMake(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
  392. ccColor4F color;
  393. color.r = red;
  394. color.g = green;
  395. color.b = blue;
  396. color.a = alpha;
  397. return color;
  398. }
  399. BOOL CCC4FAreEqual(ccColor4F c1, ccColor4F c2) {
  400. return c1.r == c2.r && c1.g == c2.g && c1.b == c2.b && c1.a == c2.a;
  401. }
  402. ccColor4F CCC4FAdd(ccColor4F rgba, ccColor4F translation) {
  403. ccColor4F result;
  404. result.r = CLAMP(rgba.r + translation.r, 0.0, 1.0);
  405. result.g = CLAMP(rgba.g + translation.g, 0.0, 1.0);
  406. result.b = CLAMP(rgba.b + translation.b, 0.0, 1.0);
  407. result.a = CLAMP(rgba.a + translation.a, 0.0, 1.0);
  408. return result;
  409. }
  410. ccColor4F CCC4FDifference(ccColor4F minuend, ccColor4F subtrahend) {
  411. ccColor4F result;
  412. result.r = CLAMP(minuend.r - subtrahend.r, 0.0, 1.0);
  413. result.g = CLAMP(minuend.g - subtrahend.g, 0.0, 1.0);
  414. result.b = CLAMP(minuend.b - subtrahend.b, 0.0, 1.0);
  415. result.a = CLAMP(minuend.a - subtrahend.a, 0.0, 1.0);
  416. return result;
  417. }
  418. ccColor4F CCC4FUniformTranslate(ccColor4F rgba, GLfloat offset) {
  419. return CCC4FAdd(rgba, CCC4FMake(offset, offset, offset, offset));
  420. }
  421. ccColor4F CCC4FBlend(ccColor4F baseColor, ccColor4F blendColor, GLfloat blendWeight) {
  422. blendWeight = CLAMP(blendWeight, 0.0, 1.0);
  423. return CCC4FMake(WAVG(baseColor.r, blendColor.r, blendWeight),
  424. WAVG(baseColor.g, blendColor.g, blendWeight),
  425. WAVG(baseColor.b, blendColor.b, blendWeight),
  426. WAVG(baseColor.a, blendColor.a, blendWeight));
  427. }
  428. ccColor4F RandomCCC4FBetween(ccColor4F min, ccColor4F max) {
  429. ccColor4F result;
  430. result.r = RandomFloatBetween(min.r, max.r);
  431. result.g = RandomFloatBetween(min.g, max.g);
  432. result.b = RandomFloatBetween(min.b, max.b);
  433. result.a = RandomFloatBetween(min.a, max.a);
  434. return result;
  435. }
  436. GLfloat CCColorFloatFromByte(GLubyte colorValue) {
  437. return (GLfloat)(colorValue / 255.0f);
  438. }
  439. GLubyte CCColorByteFromFloat(GLfloat colorValue) {
  440. return (GLubyte)(colorValue * 255.0f);
  441. }
  442. #pragma mark -
  443. #pragma mark Miscellaneous extensions and functionality
  444. @implementation NSObject (CC3)
  445. -(id) copyAutoreleased {
  446. return [[self copy] autorelease];
  447. }
  448. @end
  449. @implementation UIColor (CC3)
  450. -(ccColor4F) asCCColor4F {
  451. ccColor4F rgba = kCCC4FWhite; // initialize to white
  452. CGColorRef cgColor= self.CGColor;
  453. size_t componentCount = CGColorGetNumberOfComponents(cgColor);
  454. const CGFloat* colorComponents = CGColorGetComponents(cgColor);
  455. switch(componentCount) {
  456. case 4: // RGB + alpha: set alpha then fall through to RGB
  457. rgba.a = colorComponents[3];
  458. case 3: // RGB: alpha already set
  459. rgba.r = colorComponents[0];
  460. rgba.g = colorComponents[1];
  461. rgba.b = colorComponents[2];
  462. break;
  463. case 2: // gray scale + alpha: set alpha then fall through to gray scale
  464. rgba.a = colorComponents[1];
  465. case 1: // gray scale: alpha already set
  466. rgba.r = colorComponents[0];
  467. rgba.g = colorComponents[0];
  468. rgba.b = colorComponents[0];
  469. break;
  470. default: // if all else fails, return white which is already set
  471. break;
  472. }
  473. return rgba;
  474. }
  475. +(UIColor*) colorWithCCColor4F: (ccColor4F) rgba {
  476. return [UIColor colorWithRed: rgba.r green: rgba.g blue: rgba.b alpha: rgba.a];
  477. }
  478. @end