Tizen 2.1 base
[framework/osp/uifw.git] / src / ui / effects / runtime / FUiEffects_RuntimeGraphicalSurface.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Flora License, Version 1.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://floralicense.org/license/
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an AS IS BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 /**
18  * @file        FUiEffects_RuntimeGraphicalSurface.cpp
19  * @brief       This file contains an implementation of GraphicalSurface class methods
20  *
21  */
22
23 #include <list>
24 #include <FBaseSysLog.h>
25 #include <FBaseErrors.h>
26 #include "../FUiEffects_EffectErrorMessages.h"
27 #include "FUiEffects_RuntimeGraphicalSurface.h"
28
29 using namespace Tizen::Ui::Effects;
30 using namespace Tizen::Ui::Effects::_Utils;
31
32 namespace Tizen { namespace Ui { namespace Effects { namespace _Runtime
33 {
34
35 #define SIGN(x) (((x) >= 0) ? (1) : (-1))
36
37
38 GraphicalSurface::GraphicalSurface(long objId,
39                                                                    long bitmapID,
40                                                                    float transpar)
41                                                                                 : ElementSurface(objId)
42                                                                                 , _pRenderData(null)
43                                                                                 , __initTransparency(transpar)
44                                                                                 , __initBitmapID(bitmapID)
45                                                                                 , __initModelMtr(Mat4f::getIdentity())
46 {
47 }
48
49 GraphicalSurface::~GraphicalSurface(void)
50 {
51 }
52
53 long
54 GraphicalSurface::GetBitmapId(void) const
55 {
56         return _pRenderData->bitmapId;
57 }
58
59 void
60 GraphicalSurface::SetBitmapId(long bitmapId)
61 {
62         _pRenderData->bitmapId = bitmapId;
63         _pRenderData->bitmapIdChanged = true;
64         return;
65 }
66
67 void
68 GraphicalSurface::Construct(TypeElemSurfaceCollection* pElemSurfaceCollection, RenderDataSurfaceCollection* pRenderDataSurfaceCollection)
69 {
70         pRenderDataSurfaceCollection->push_back(_pRenderData.get());
71         return;
72 }
73
74 PropertyCast
75 GraphicalSurface::GetProperty(ElementProperty propName)const
76 {
77         PropertyCast propCast = {PropertyCast::NO_PROPERTY, {0} };
78         switch (propName)
79         {
80         case N_TRANSPARENCY:
81                 propCast.value.numberValue = _pRenderData->transparency;
82                 propCast.type = PropertyCast::NUMBER;
83                 break;
84         default:
85                 propCast.type = PropertyCast::NO_PROPERTY;
86                 break;
87         }
88         return propCast;
89 }
90
91 bool
92 GraphicalSurface::SetProperty(ElementProperty propName, bool propValue)
93 {
94         return false;
95 }
96
97 bool
98 GraphicalSurface::SetProperty(ElementProperty propName, LUA_NUMBER propValue)
99 {
100         switch (propName)
101         {
102         case N_TRANSPARENCY:
103                 _pRenderData->transparency = propValue;
104                 _pRenderData->transparencyChanged = true;
105                 return true;
106                 break;
107         default:
108                 return false;
109                 break;
110         }
111 }
112
113 bool
114 GraphicalSurface::SetProperty(ElementProperty propName, const Vec3f &propValue)
115 {
116         return false;
117 }
118
119 void
120 GraphicalSurface::Initialize(void)
121 {
122         _pRenderData->transparency = __initTransparency;
123         _pRenderData->transparencyChanged = true;
124         _pRenderData->bitmapId = __initBitmapID;
125         _pRenderData->bitmapIdChanged = true;
126         _pRenderData->modelMtr = __initModelMtr;
127         _pRenderData->modelMtrChanged = true;
128         return;
129 }
130
131 PropertyCast
132 GraphicalSurface::GetNearestPointsIds(Vec3f &position) const
133 {
134         IndicesCollection::iterator itIndex;
135         IndicesCollection::iterator itIndex1;
136         IndicesCollection::iterator itIndex2;
137         IndicesCollection::iterator itIndex3;
138         std::list<IndicesCollection::iterator> listIndeces;
139         //if there are no crossing with a triangle it returns nil (in scripts)
140         PropertyCast res = {PropertyCast::NO_PROPERTY, {0}};
141         //Finds triangles from RenderData structure which are crossed by
142         //a ray with position (position.x, position.y)
143         for (itIndex = _pRenderData->indices.begin(); itIndex != _pRenderData->indices.end(); )
144         {
145                 SysAssertf(itIndex != _pRenderData->indices.end(), _UiEffectError::INTERNAL_ERROR);
146                 itIndex1 = itIndex++;
147
148                 SysAssertf(itIndex != _pRenderData->indices.end(), _UiEffectError::INTERNAL_ERROR);
149                 itIndex2 = itIndex++;
150
151                 SysAssertf(itIndex != _pRenderData->indices.end(), _UiEffectError::INTERNAL_ERROR);
152                 itIndex3 = itIndex++;
153
154                 if (InTriangle(position, *itIndex1, *itIndex2, *itIndex3))
155                 {
156                         listIndeces.push_back(itIndex1);
157                 }
158         }
159
160         if (listIndeces.empty())
161         {
162                 res.type = PropertyCast::NO_PROPERTY;
163         }
164         else
165         {
166                 res.type = PropertyCast::VEC3;
167
168                 std::list<IndicesCollection::iterator>::iterator itList;
169                 IndicesCollection::iterator itList1;
170                 IndicesCollection::iterator itList2;
171                 IndicesCollection::iterator itList3;
172                 float maxZ = 0.f;
173                 IndicesCollection::iterator itVertexTriangle;
174                 //Finds z-coordinates of crossing planes of triangles from RenderData structure with
175                 //a ray (position.x, position.y)
176                 for (itList = listIndeces.begin(); itList != listIndeces.end(); ++itList)
177                 {
178                         itList1 = *itList;
179                         itList2 = *itList+1;
180                         itList3 = *itList+2;
181                         float curZ = ZInPlane(position, *itList1, *itList2, *itList3);
182                         //finding maximal z-coordinate and storing corresponding triangle
183                         if (maxZ < curZ || itList == listIndeces.begin())
184                         {
185                                 maxZ = curZ;
186                                 itVertexTriangle = *itList;
187                         }
188                 }
189
190                 position.z = maxZ;
191         }
192
193         return res;
194 }
195
196 bool
197 GraphicalSurface::InTriangle(const Vec3f &pos, short i1, short i2, short i3) const
198 {
199         //If point pos and any triangle vertex lie on opposite sides relatively an other side,
200         //then point pos lies outside of triangle
201
202         unsigned short i = 0;
203         unsigned short k = 0;
204         unsigned short p = 0;
205         float c = 0.f;
206         float c1 = 0.f;
207         for (short ic = 0; ic < 3; ic++)
208         {
209                 if (ic == 0)
210                 {
211                         i = i1;
212                         k = i2;
213                         p = i3;
214                 }
215                 else if (ic == 1)
216                 {
217                         i = i2;
218                         k = i1;
219                         p = i3;
220                 }
221                 else
222                 {
223                         i = i3;
224                         k = i1;
225                         p = i2;
226                 }
227
228                 const Vec3f &point1 = _pRenderData->vnt[k].pos;
229                 const Vec3f &point2 = _pRenderData->vnt[p].pos;
230                 const Vec3f &pointp = _pRenderData->vnt[i].pos;
231
232                 if (fabsf(point1.x - point2.x) > std::numeric_limits<float>::epsilon())
233                 {
234                         c = (pos.x - point2.x) * (point1.y - point2.y) / (point1.x - point2.x) + point2.y;
235                         c1 = (pointp.x - point2.x) * (point1.y-point2.y) / (point1.x - point2.x) + point2.y;
236                         if (SIGN(pos.y - c) != SIGN(pointp.y - c1))
237                         {
238                                 return false;
239                         }
240                 }
241                 else if (fabsf(point1.y - point2.y) > std::numeric_limits<float>::epsilon())
242                 {
243                         c = (pos.y - point2.y) * (point1.x - point2.x) / (point1.y - point2.y) + point2.x;
244                         c1 = (pointp.y - point2.y) * (point1.x-point2.x) / (point1.y - point2.y) + point2.x;
245                         if (SIGN(pos.x - c) != SIGN(pointp.x - c1))
246                         {
247                                 return false;
248                         }
249                 }
250                 else
251                 {
252                         return false;
253                 }
254         }
255         return true;
256 }
257
258 float
259 GraphicalSurface::ZInPlane(const Vec3f &pos, short i1, short i2, short i3) const
260 {
261         //restoring the plane passing through 3 triangle vertexes
262         //z=Ax+By+C
263         //Kramer's method for solving the linear equations system with 3 equations and 3 variables is used
264         const Vec3f &p1 = _pRenderData->vnt[i1].pos;
265         const Vec3f &p2 = _pRenderData->vnt[i2].pos;
266         const Vec3f &p3 = _pRenderData->vnt[i3].pos;
267
268         float delta = p1.x * p2.y + p3.x * p1.y + p2.x * p3.y - p3.x * p2.y - p1.x * p3.y - p2.x * p1.y;
269         float deltaA = p2.y * p1.z + p1.y * p3.z + p3.y * p2.z - p2.y * p3.z - p1.y * p2.z - p3.y * p1.z;
270         float deltaB = p1.x * p2.z + p3.x * p1.z + p2.x * p3.z - p3.x * p2.z - p2.x * p1.z - p1.x * p3.z;
271         float deltaC = p1.x * p2.y * p3.z + p3.x * p1.y * p2.z + p2.x * p3.y * p1.z - p3.x * p2.y * p1.z - p1.x * p3.y * p2.z - p2.x * p1.y * p3.z;
272
273         float res = 0.f;
274         //if 3 triangle vertexes lie on vertical plane, returns maximal z-coordinate of one of these points
275         if (fabsf(delta) <= std::numeric_limits<float>::epsilon())
276         {
277                 float t1 = p1.z;
278                 float t2 = p2.z;
279                 float t3 = p3.z;
280                 res = (t1 >= t2 ? (t1 >= t3 ? t1 : t3) : (t2 >= t3 ? t2 : t3));
281         }
282         else
283         {
284                 float koefA = deltaA / delta;
285                 float koefB = deltaB / delta;
286                 float koefC = deltaC / delta;
287
288                 res = koefA * pos.x + koefB * pos.y + koefC;
289         }
290         return res;
291 }
292
293 void
294 GraphicalSurface::ResetSurfaceTransformation(void)
295 {
296         LuaMat4<float> matrix4;
297         _pRenderData->modelMtr = matrix4;
298         _pRenderData->modelMtrChanged = true;
299         return;
300 }
301
302 void
303 GraphicalSurface::SetTransformationMatrix(const LuaMatrix4& luaMatrix4)
304 {
305         _pRenderData->modelMtr = luaMatrix4;
306         _pRenderData->modelMtrChanged = true;
307         return;
308 }
309
310 void
311 GraphicalSurface::MoveSurface(float x0, float y0, float z0)
312 {
313         LuaMat4<float> matrix4(_pRenderData->modelMtr);
314         matrix4.Translate(x0, y0, z0);
315
316         _pRenderData->modelMtr = matrix4;
317         _pRenderData->modelMtrChanged = true;
318
319         return;
320 }
321
322 bool
323 GraphicalSurface::ScaleSurface(float ax, float ay, float az, float x0, float y0, float z0)
324 {
325         LuaMat4<float> matrix4(_pRenderData->modelMtr);
326         bool result = matrix4.Scale(ax, ay, az, x0, y0, z0);
327
328         if (result)
329         {
330                 _pRenderData->modelMtr = matrix4;
331                 _pRenderData->modelMtrChanged = true;
332         }
333         return result;
334 }
335
336 bool
337 GraphicalSurface::RotateSurface(float angle, _Axis axis,
338                                                                 float ax, float ay, float az, float x0, float y0, float z0)
339 {
340         bool res = false;
341
342         LuaMat4<float> matrix4(_pRenderData->modelMtr);
343         switch (axis)
344         {
345         case AXIS_X:
346                 matrix4.RotateAroundAxisX(angle, x0, y0, z0);
347                 res = true;
348                 break;
349         case AXIS_Y:
350                 matrix4.RotateAroundAxisY(angle, x0, y0, z0);
351                 res = true;
352                 break;
353         case AXIS_Z:
354                 matrix4.RotateAroundAxisZ(angle, x0, y0, z0);
355                 res = true;
356                 break;
357         case AXIS_ARBITRARY:
358                 res = matrix4.RotateAroundAxisArbitrary(angle, ax, ay, az, x0, y0, z0);
359                 break;
360         default:
361                 res = false;
362                 break;
363         }
364
365         if (res)
366         {
367                 _pRenderData->modelMtr = matrix4;
368                 _pRenderData->modelMtrChanged = true;
369         }
370         return res;
371 }
372
373 } } } } // Tizen::Ui::Effects::_Runtime