2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
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
9 // http://floralicense.org/license/
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.
18 * @file FUiEffects_RuntimeGraphicalSurfaceNurbs.cpp
19 * @brief This file contains an implementation of GraphicalSurfaceNurbs class methods
26 #include <FBaseSysLog.h>
27 #include <FBaseErrors.h>
28 #include "../FUiEffects_EffectErrorMessages.h"
29 #include <FUiEffects_PePointSurfaceNURBS.h>
30 #include "FUiEffects_RuntimeGraphicalSurfaceNurbs.h"
32 using namespace Tizen::Ui::Effects;
33 using namespace Tizen::Ui::Effects::_PhysicsEngine;
34 using namespace Tizen::Ui::Effects::_Utils;
37 namespace Tizen { namespace Ui { namespace Effects { namespace _Runtime
40 GraphicalSurfaceNurbs::GraphicalSurfaceNurbs(long objID,
48 std::unique_ptr<TypeKnots> pKnotsX_,
49 std::unique_ptr<TypeKnots> pKnotsY_,
51 : GraphicalSurface(objID, bitmapID_, transparency_)
52 , __dimGraphX(dimGraphX_), __dimGraphY (dimGraphY_)
53 , __dimCtrlX(dimCtrlX_), __dimCtrlY(dimCtrlY_)
54 , __orderX(orderX_), __orderY(orderY_)
56 __pKnotsX = std::move(pKnotsX_);
57 __pKnotsY = std::move(pKnotsY_);
68 unique_ptr<TypePSurfaceNURBSCollection> pPSurfaceNURBSCollection(new (std::nothrow) TypePSurfaceNURBSCollection);
69 SysTryReturnVoidResult(NID_UI_EFFECT, pPSurfaceNURBSCollection.get() != null, E_OUT_OF_MEMORY, _UiEffectError::OUT_OF_MEMORY);
71 unique_ptr<TypeNURBSCoeffsCollection> pNURBSCoeffsCollection(new (std::nothrow) TypeNURBSCoeffsCollection);
72 SysTryReturnVoidResult(NID_UI_EFFECT, pNURBSCoeffsCollection.get() != null, E_OUT_OF_MEMORY, _UiEffectError::OUT_OF_MEMORY);
74 unique_ptr<RenderDataSurface> pRenderData(new (std::nothrow) RenderDataSurface(__dimGraphX * __dimGraphY, (__dimGraphX - 1) * (__dimGraphY - 1) * 6));
75 SysTryReturnVoidResult(NID_UI_EFFECT, pRenderData.get() != null, E_OUT_OF_MEMORY, _UiEffectError::OUT_OF_MEMORY);
77 unique_ptr<TypeCornerGrapSurPointsCollection> pCornerPointsGraphSurface(new (std::nothrow) TypeCornerGrapSurPointsCollection);
78 SysTryReturnVoidResult(NID_UI_EFFECT, pCornerPointsGraphSurface.get() != null, E_OUT_OF_MEMORY, _UiEffectError::OUT_OF_MEMORY);
79 unique_ptr<TypeCornerPhysSurPointsCollection> pCornerPointsPhysicalSurface(new (std::nothrow) TypeCornerPhysSurPointsCollection);
80 SysTryReturnVoidResult(NID_UI_EFFECT, pCornerPointsPhysicalSurface.get() != null, E_OUT_OF_MEMORY, _UiEffectError::OUT_OF_MEMORY);
82 unique_ptr<TypeNearestPointsCollection> pNearestPointsCollection(new (std::nothrow) TypeNearestPointsCollection);
83 SysTryReturnVoidResult(NID_UI_EFFECT, pNearestPointsCollection.get() != null, E_OUT_OF_MEMORY, _UiEffectError::OUT_OF_MEMORY);
85 __pPSurfaceNURBSCollection = std::move(pPSurfaceNURBSCollection);
86 __pPSurfaceNURBSCollection->resize(__dimCtrlX * __dimCtrlY);
87 __pNURBSCoeffsCollection = std::move(pNURBSCoeffsCollection);
88 _pRenderData = std::move(pRenderData);
89 __pCornerPointsGraphSurface = std::move(pCornerPointsGraphSurface);
90 __pCornerPointsPhysicalSurface = std::move(pCornerPointsPhysicalSurface);
91 __pNearestPointsCollection = std::move(pNearestPointsCollection);
93 _pRenderData->bitmapId = bitmapID_;
94 _pRenderData->transparency = transparency_;
96 TypeNURBSCoeffsCollection::size_type size = __dimCtrlX * __dimCtrlY * __dimGraphX * __dimGraphY;
97 __pNURBSCoeffsCollection->resize(size);
99 __pNearestPointsCollection->resize(__dimCtrlX + __dimCtrlY - 1);
100 (*__pNearestPointsCollection)[0].reserve(1);
101 TypeNearestPointsCollection::size_type sizeNearest = __pNearestPointsCollection->size();
102 for (TypeNearestPointsCollection::size_type i = 1, n = 0; i < sizeNearest; ++i)
104 if (i <= sizeNearest / 2)
110 n > 4 ? n -= 4 : n = 1;
112 (*__pNearestPointsCollection)[i].reserve(n);
116 GraphicalSurfaceNurbs::~GraphicalSurfaceNurbs()
122 GraphicalSurfaceNurbs::Construct(TypeElemSurfaceCollection* pElemSurfaceCollection, RenderDataSurfaceCollection* pRenderDataSurfaceCollection)
124 //constructing the collection of pointers to physical (PointSurfaceNURBS) points
125 TypeElemSurfaceCollection::iterator it;
126 TypeElemSurfaceCollection::size_type counter = 0;
127 for (it = pElemSurfaceCollection->begin(); it != pElemSurfaceCollection->end(); ++it)
129 if ((*it)->GetType() == ESURFACE_POINT_SURFACE_NURBS)
131 PointSurfaceNurbs* p = dynamic_cast<PointSurfaceNurbs*>(*it);
132 SysAssertf(p != null, _UiEffectError::INTERNAL_ERROR);
133 SysAssertf(counter < static_cast<TypeElemSurfaceCollection::size_type>(__dimCtrlX * __dimCtrlY), _UiEffectError::INTERNAL_ERROR);
134 (*__pPSurfaceNURBSCollection)[counter] = p;
138 SysAssertf(!__pPSurfaceNURBSCollection->empty(), _UiEffectError::INTERNAL_ERROR);
140 //constructing the corners of graphical surface as rectangular area
141 __pCornerPointsGraphSurface->push_back(&_pRenderData->vnt[0].pos);
142 __pCornerPointsGraphSurface->push_back(&_pRenderData->vnt[__dimGraphX - 1].pos);
143 __pCornerPointsGraphSurface->push_back(&_pRenderData->vnt[_pRenderData->vnt.size() - __dimGraphX].pos);
144 __pCornerPointsGraphSurface->push_back(&_pRenderData->vnt[_pRenderData->vnt.size() - 1].pos);
146 //constructing the corners of physical surface as rectangular area
147 __pCornerPointsPhysicalSurface->push_back(&(*__pPSurfaceNURBSCollection)[0]->GetPosition());
148 __pCornerPointsPhysicalSurface->push_back(&(*__pPSurfaceNURBSCollection)[__dimCtrlX - 1]->GetPosition());
149 __pCornerPointsPhysicalSurface->push_back(&(*__pPSurfaceNURBSCollection)[__pPSurfaceNURBSCollection->size() - __dimCtrlX]->GetPosition());
150 __pCornerPointsPhysicalSurface->push_back(&(*__pPSurfaceNURBSCollection)[__pPSurfaceNURBSCollection->size() - 1]->GetPosition());
152 //--------the order of these two functions is not important-------------
153 //indices calculation for triangles
155 //B-spline coefficients calculation + neglecting the coefficients which less then some threshold
156 CalculationNurbsCoefficients();
157 //---------------------------------------------------------------------
158 //Synchronizes the collections of graphical and physical points + recalculates of normals
159 //must be called after CalcIndices(); and CalculationNurbsCoefficients();
160 Initialize(); //GraphicalSurface::Initialize() + Update()
161 //---------------------------------------------------------------------
162 //calculates the texture coordinates
163 //must be called after Update();
165 //---------------------------------------------------------------------
167 //pRenderDataSurfaceCollection construction
168 GraphicalSurface::Construct(null, pRenderDataSurfaceCollection);
174 GraphicalSurfaceNurbs::Initialize(void)
176 GraphicalSurface::Initialize();
182 GraphicalSurfaceNurbs::GetNearestPointsIds(Vec3f &position) const
184 PropertyCast result = GraphicalSurface::GetNearestPointsIds(position);
185 if (result.type == PropertyCast::NO_PROPERTY)
192 TypePSurfaceNURBSCollection::iterator it;
193 TypePSurfaceNURBSCollection::iterator minIt;
194 for (it = __pPSurfaceNURBSCollection->begin(); it != __pPSurfaceNURBSCollection->end(); ++it)
196 const Vec3f &point = (*it)->GetPosition();
197 float r2 = point.distanceSqr(position);
198 if (it == __pPSurfaceNURBSCollection->begin() || r2 < minR2)
205 for (TypeNearestPointsCollection::size_type i = 0; i < __pNearestPointsCollection->size(); ++i)
207 (*__pNearestPointsCollection)[i].clear();
210 int minRow = (*minIt)->GetRow();
211 int minCol = (*minIt)->GetCol();
212 for (it = __pPSurfaceNURBSCollection->begin(); it != __pPSurfaceNURBSCollection->end(); ++it)
214 int row = (*it)->GetRow();
215 int col = (*it)->GetCol();
216 int radious = abs(row - minRow) + abs(col - minCol);
217 (*__pNearestPointsCollection)[radious].push_back((*it)->GetId());
220 result.type = PropertyCast::VECTOR_VECTOR;
221 result.value.vecVecValue = __pNearestPointsCollection.get();
227 GraphicalSurfaceNurbs::Calculate(float timeStep)
233 GraphicalSurfaceNurbs::GetType(void) const
235 return ESURFACE_GRAPHICAL_SURFACE_NURBS;
239 GraphicalSurfaceNurbs::GetProperty(ElementProperty propName)const
241 return GraphicalSurface::GetProperty(propName);
245 GraphicalSurfaceNurbs::SetProperty(ElementProperty propName, bool propValue)
247 return GraphicalSurface::SetProperty(propName, propValue);
251 GraphicalSurfaceNurbs::SetProperty(ElementProperty propName, LUA_NUMBER propValue)
253 return GraphicalSurface::SetProperty(propName, propValue);
257 GraphicalSurfaceNurbs::SetProperty(ElementProperty propName, const Tizen::Ui::Effects::_Utils::Vec3f &propValue)
259 return GraphicalSurface::SetProperty(propName, propValue);
263 GraphicalSurfaceNurbs::Update(void)
265 VertexDataCollection::iterator itGraph;
266 unsigned long pointIndex = 0;
267 unsigned long dataPointsCount = __dimCtrlX * __dimCtrlY;
269 for (itGraph = _pRenderData->vnt.begin(); itGraph != _pRenderData->vnt.end(); ++pointIndex, ++itGraph)
271 Vec3f &pos = itGraph->pos;
273 //case of corner graphical points
274 //(the coordinates of corner points of graphical surface and physical surface should be same (see NURBS theory))
275 //(there is some inaccuracy in NURBS weights calculation by reason of floating point values precision (whatever float or double))
276 bool isCorner = false;
277 TypeCornerGrapSurPointsCollection::iterator itG = __pCornerPointsGraphSurface->begin();
278 TypeCornerPhysSurPointsCollection::iterator itP = __pCornerPointsPhysicalSurface->begin();
279 for (; itG != __pCornerPointsGraphSurface->end(); ++itG, ++itP)
293 _DataPointWeight* pointWeight = &(*__pNURBSCoeffsCollection)[pointIndex * dataPointsCount];
299 for (unsigned long ii = 0; ii < dataPointsCount && pointWeight->pPoint != null; ++ii, ++pointWeight)
301 float &weight = pointWeight->weight;
302 const Vec3f &dataPoint = *pointWeight->pPoint;
304 pos.x += dataPoint.x * weight;
305 pos.y += dataPoint.y * weight;
306 pos.z += dataPoint.z * weight;
310 //normals recalculation
313 _pRenderData->vertexDataChanged = true;
319 GraphicalSurfaceNurbs::NurbsSingleBasisFunction(long i, long order, float u, const TypeKnots &knots) const
323 if (u >= knots[i] && u < knots[i + 1])
335 static float epsilon = std::numeric_limits<float>::epsilon();
337 if (fabs(knots[i + order - 1] - knots[i]) > epsilon)
339 result = (u - knots[i])/(knots[i + order - 1] - knots[i]) * NurbsSingleBasisFunction(i, order - 1, u, knots);
342 if (fabs((knots[i + order] - knots[i + 1])) > epsilon)
344 result += (knots[i + order] - u)/(knots[i + order] - knots[i + 1]) * NurbsSingleBasisFunction(i + 1, order - 1, u, knots);
352 GraphicalSurfaceNurbs::SummaryForNurbs(float u, float w) const
355 TypePSurfaceNURBSCollection::iterator it = __pPSurfaceNURBSCollection->begin();
356 for (int i1 = 0; i1 < __dimCtrlX; ++i1)
358 for (int j1 = 0; j1 < __dimCtrlY; ++j1)
360 SysAssertf(it != __pPSurfaceNURBSCollection->end(), _UiEffectError::INTERNAL_ERROR);
361 sum += (*it++)->GetWeight() * NurbsSingleBasisFunction(i1, __orderX, u, *__pKnotsX) *
362 NurbsSingleBasisFunction(j1, __orderY, w, *__pKnotsY);
369 GraphicalSurfaceNurbs::CalculationNurbsCoefficients(void)
371 float du = 1.0f / (__dimGraphX - 1);
372 float dv = 1.0f / (__dimGraphY - 1);
374 TypeNURBSCoeffsCollection::iterator itCoeff = __pNURBSCoeffsCollection->begin();
377 for (int kv = 0; kv < __dimGraphY; ++kv)
380 for (int ku = 0; ku < __dimGraphX; ++ku)
382 float sum = SummaryForNurbs(u, v);
384 TypePSurfaceNURBSCollection::iterator itData = __pPSurfaceNURBSCollection->begin();
386 for (int j = 0; j < __dimCtrlY; ++j)
388 for (int i = 0; i < __dimCtrlX; ++i)
390 SysAssertf(itData != __pPSurfaceNURBSCollection->end(), _UiEffectError::INTERNAL_ERROR);
391 SysAssertf(itCoeff != __pNURBSCoeffsCollection->end(), _UiEffectError::INTERNAL_ERROR);
393 (*itCoeff).weight = (*itData)->GetWeight() * NurbsSingleBasisFunction(i, __orderX, u, *__pKnotsX);
394 (*itCoeff).weight *= NurbsSingleBasisFunction(j, __orderY, v, *__pKnotsY) / sum;
395 (*itCoeff).pPoint = &(*itData)->GetPosition();
405 WeightsApplyThreshold(0.0001f);
411 GraphicalSurfaceNurbs::WeightsApplyThreshold(float threshold)
413 TypeNURBSCoeffsCollection::size_type graphicalPointsCount = __dimGraphX * __dimGraphY;
414 TypeNURBSCoeffsCollection::size_type dataPointsCount = __dimCtrlX * __dimCtrlY;
415 for (unsigned long pointIndex = 0; pointIndex < graphicalPointsCount; ++pointIndex)
417 long startW = pointIndex * dataPointsCount;
418 long endW = startW + dataPointsCount - 1;
420 for (; startW <= endW; ++startW)
422 if (fabs((*__pNURBSCoeffsCollection)[startW].weight) <= threshold)
424 (*__pNURBSCoeffsCollection)[startW] = (*__pNURBSCoeffsCollection)[endW];
425 (*__pNURBSCoeffsCollection)[endW].pPoint = null;
435 GraphicalSurfaceNurbs::CalcIndices(void)
437 unsigned long dimGraphXm1 = __dimGraphX - 1;
438 unsigned long dimGraphYm1 = __dimGraphY - 1;
440 IndicesCollection::iterator it = _pRenderData->indices.begin();
442 for (unsigned short i = 0; i < dimGraphYm1; ++i)
444 for (unsigned short j = 0, poffset = __dimGraphX * i; j < dimGraphXm1; ++j, ++poffset)
446 SysAssertf(it != _pRenderData->indices.end(), _UiEffectError::INTERNAL_ERROR);
447 (*it++) = poffset + __dimGraphX;
449 SysAssertf(it != _pRenderData->indices.end(), _UiEffectError::INTERNAL_ERROR);
450 (*it++) = poffset + 1;
452 SysAssertf(it != _pRenderData->indices.end(), _UiEffectError::INTERNAL_ERROR);
455 SysAssertf(it != _pRenderData->indices.end(), _UiEffectError::INTERNAL_ERROR);
456 (*it++) = poffset + __dimGraphX;
458 SysAssertf(it != _pRenderData->indices.end(), _UiEffectError::INTERNAL_ERROR);
459 (*it++) = poffset + __dimGraphX + 1;
461 SysAssertf(it != _pRenderData->indices.end(), _UiEffectError::INTERNAL_ERROR);
462 (*it++) = poffset + 1;
469 GraphicalSurfaceNurbs::CalcNormals(void)
471 IndicesCollection::iterator itIndex = _pRenderData->indices.begin();
473 unsigned long triCount = (__dimGraphX - 1) * (__dimGraphY - 1) * 2;
474 std::vector<Vec3f> triNormals;
475 triNormals.resize(triCount);
477 //calc normals for each triangle
478 for (unsigned long i = 0; i < triCount; ++i)
480 SysAssertf(itIndex != _pRenderData->indices.end(), _UiEffectError::INTERNAL_ERROR);
481 const Vec3f &tempVec0 = _pRenderData->vnt[*itIndex++].pos;
483 SysAssertf(itIndex != _pRenderData->indices.end(), _UiEffectError::INTERNAL_ERROR);
484 const Vec3f &tempVec1 = _pRenderData->vnt[*itIndex++].pos;
486 SysAssertf(itIndex != _pRenderData->indices.end(), _UiEffectError::INTERNAL_ERROR);
487 const Vec3f &tempVec2 = _pRenderData->vnt[*itIndex++].pos;
489 triNormals[i] = Vec3f::createCrossed(tempVec2 - tempVec0, tempVec1 - tempVec0);
490 triNormals[i].normalize();
493 itIndex = _pRenderData->indices.begin();
495 //not smoothed normals
496 for (unsigned long i = 0; i < triCount; ++i)
498 const Vec3f &norm = triNormals[i];
499 _pRenderData->vnt[*itIndex++].norm = norm;
500 _pRenderData->vnt[*itIndex++].norm = norm;
501 _pRenderData->vnt[*itIndex++].norm = norm;
508 GraphicalSurfaceNurbs::CalcTexCoords(void)
510 //------------------------the size of model------------------------
511 const Vec3f &posBegin = _pRenderData->vnt[0].pos;
512 unsigned int modelSizeX = _pRenderData->vnt[__dimGraphX - 1].pos.x - posBegin.x;
513 unsigned int modelSizeY = _pRenderData->vnt[_pRenderData->vnt.size() - 1].pos.y - posBegin.y;
514 //-----------------------------------------------------------------
516 VertexDataCollection::iterator itVnt = _pRenderData->vnt.begin();
517 for (; itVnt!=_pRenderData->vnt.end(); ++itVnt)
519 const Vec3f &posCur = itVnt->pos - posBegin;
520 itVnt->texcoords.x = posCur.x / modelSizeX;
521 itVnt->texcoords.y = posCur.y / modelSizeY;
527 GraphicalSurfaceNurbs::DefinePointOnModel(_Point point, Vec3f &pointOnModel,
528 float x0, float y0, float z0) const
533 pointOnModel = *(*__pCornerPointsGraphSurface)[2];
535 case POINT_CENTER_TOP:
536 pointOnModel = (*(*__pCornerPointsGraphSurface)[2] + *(*__pCornerPointsGraphSurface)[3]) / 2.f;
538 case POINT_RIGHT_TOP:
539 pointOnModel = *(*__pCornerPointsGraphSurface)[3];
541 case POINT_LEFT_CENTER:
542 pointOnModel = (*(*__pCornerPointsGraphSurface)[0] + *(*__pCornerPointsGraphSurface)[2]) / 2.f;
544 case POINT_CENTER_CENTER:
545 pointOnModel = (*(*__pCornerPointsGraphSurface)[1] + *(*__pCornerPointsGraphSurface)[2]) / 2.f;
547 case POINT_RIGHT_CENTER:
548 pointOnModel = (*(*__pCornerPointsGraphSurface)[1] + *(*__pCornerPointsGraphSurface)[3]) / 2.f;
550 case POINT_LEFT_BOTTOM:
551 pointOnModel = *(*__pCornerPointsGraphSurface)[0];
553 case POINT_CENTER_BOTTOM:
554 pointOnModel = (*(*__pCornerPointsGraphSurface)[0] + *(*__pCornerPointsGraphSurface)[1]) / 2.f;
556 case POINT_RIGHT_BOTTOM:
557 pointOnModel = *(*__pCornerPointsGraphSurface)[1];
559 case POINT_ARBITRARY:
573 GraphicalSurfaceNurbs::RotateSurface(float angle, _Axis axis, _Point point,
574 float ax, float ay, float az, float x0, float y0, float z0)
577 if (!DefinePointOnModel(point, tempPoint, x0, y0, z0))
581 return GraphicalSurface::RotateSurface(angle, axis, ax, ay, az, tempPoint.x, tempPoint.y, tempPoint.z);
585 GraphicalSurfaceNurbs::ScaleSurface(float ax, float ay, float az, _Point point,
586 float x0, float y0, float z0)
589 if (!DefinePointOnModel(point, tempPoint, x0, y0, z0))
593 return GraphicalSurface::ScaleSurface(ax, ay, az, tempPoint.x, tempPoint.y, tempPoint.z);
596 } } } } // Tizen::Ui::Effects::_Runtime