[dali_2.0.26] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / page-turn-view / page-turn-effect.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // EXTERNAL INCLUDES
19 #include <dali/public-api/actors/actor.h>
20 #include <dali/public-api/animation/constraint.h>
21 #include <dali/public-api/object/property-map.h>
22 #include <string.h>
23
24 // INTERNAL INCLUDES
25 #include <dali-toolkit/internal/controls/page-turn-view/page-turn-effect.h>
26 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
27 #include <dali-toolkit/public-api/visuals/visual-properties.h>
28
29 using namespace Dali;
30 using namespace Dali::Toolkit;
31
32 namespace
33 {
34 const char* const PROPERTY_COMMON_PARAMETERS("uCommonParameters");
35 const char* const PROPERTY_ORIGINAL_CENTER("originalCenter");
36 const char* const PROPERTY_CURRENT_CENTER("currentCenter");
37 } // namespace
38
39 /**
40  * This constraint updates the common parameter values used by every vertex.
41  * By using constraint, they are calculate once in CPU then pass into the vertex shader as uniforms
42  */
43 struct CommonParametersConstraint
44 {
45   CommonParametersConstraint(float pageHeight)
46   : mPageHeight(pageHeight)
47   {
48   }
49
50   void operator()(Dali::Matrix& current, const PropertyInputContainer& inputs)
51   {
52     const Vector2& originalCenter = inputs[0]->GetVector2();
53     Vector2        currentCenter  = inputs[1]->GetVector2();
54
55     // calculate the curve direction and the vanishing point
56     // here, the vanishing point is the intersection of spine with the line passing through original center and vertical to curve direction
57     Vector2 curveDirection(currentCenter - originalCenter);
58     curveDirection.Normalize();
59     if(fabs(curveDirection.y) < 0.01f) // eliminate the possibility of division by zero in the next step
60     {
61       curveDirection.y = 0.01f;
62     }
63     float vanishingPointY = originalCenter.y + curveDirection.x * originalCenter.x / curveDirection.y;
64
65     float curveEndY, cosTheta, sinTheta, translateX, translateY;
66     // when the vanishing point is very far away, make it infinitely, in this case, the page bent horizontally
67     const float THRESHOLD(20.0);
68     if(fabs(vanishingPointY - mPageHeight * 0.5f) >= mPageHeight * THRESHOLD)
69     {
70       curveDirection  = Vector2(-1.f, 0.f);
71       currentCenter.y = originalCenter.y;
72
73       curveEndY  = originalCenter.y;
74       cosTheta   = 1.f;
75       sinTheta   = 0.f;
76       translateX = currentCenter.x - originalCenter.x;
77       translateY = vanishingPointY;
78     }
79     else
80     {
81       curveEndY = currentCenter.y - curveDirection.y * (currentCenter.x / curveDirection.x);
82       Vector2 v1(currentCenter.x, currentCenter.y - vanishingPointY);
83       v1.Normalize();
84       Vector2 v2(originalCenter.x, originalCenter.y - vanishingPointY);
85       v2.Normalize();
86       cosTheta   = v1.x * v2.x + v1.y * v2.y;
87       sinTheta   = (vanishingPointY > mPageHeight * 0.5f) ? sqrt(1.0 - cosTheta * cosTheta) : -sqrt(1.0 - cosTheta * cosTheta);
88       translateX = currentCenter.x - cosTheta * originalCenter.x - sinTheta * (originalCenter.y - vanishingPointY);
89       translateY = currentCenter.y + sinTheta * originalCenter.x - cosTheta * (originalCenter.y - vanishingPointY);
90     }
91
92     float originalLength = fabs(originalCenter.x / curveDirection.x);
93     float currentLength  = fabs(currentCenter.x / curveDirection.x);
94     float curveHeight    = 0.45f * sqrt(originalLength * originalLength - currentLength * currentLength);
95
96     float* parameterArray = current.AsFloat();
97     parameterArray[0]     = cosTheta;
98     parameterArray[1]     = -sinTheta;
99     parameterArray[2]     = originalCenter.x;
100     parameterArray[3]     = originalCenter.y;
101     parameterArray[4]     = sinTheta;
102     parameterArray[5]     = cosTheta;
103     parameterArray[6]     = currentCenter.x;
104     parameterArray[7]     = currentCenter.y;
105     parameterArray[8]     = translateX;
106     parameterArray[9]     = translateY;
107     parameterArray[10]    = vanishingPointY;
108     parameterArray[11]    = curveEndY;
109     parameterArray[12]    = curveDirection.x;
110     parameterArray[13]    = curveDirection.y;
111     parameterArray[14]    = curveHeight;
112     parameterArray[15]    = currentLength;
113   }
114
115   float mPageHeight;
116 };
117
118 void Dali::Toolkit::Internal::PageTurnApplyInternalConstraint(Actor& actor, float pageHeight)
119 {
120   Constraint constraint = Constraint::New<Dali::Matrix>(actor, actor.GetPropertyIndex(PROPERTY_COMMON_PARAMETERS), CommonParametersConstraint(pageHeight));
121   constraint.AddSource(LocalSource(actor.GetPropertyIndex(PROPERTY_ORIGINAL_CENTER)));
122   constraint.AddSource(LocalSource(actor.GetPropertyIndex(PROPERTY_CURRENT_CENTER)));
123   constraint.Apply();
124 }
125
126 Property::Map Dali::Toolkit::Internal::CreatePageTurnEffect()
127 {
128   Property::Map map;
129
130   Property::Map customShader;
131
132   customShader[Toolkit::Visual::Shader::Property::VERTEX_SHADER]    = SHADER_PAGE_TURN_EFFECT_VERT.data();
133   customShader[Toolkit::Visual::Shader::Property::FRAGMENT_SHADER]  = SHADER_PAGE_TURN_EFFECT_FRAG.data();
134   customShader[Toolkit::Visual::Shader::Property::SUBDIVIDE_GRID_X] = 20;
135   customShader[Toolkit::Visual::Shader::Property::SUBDIVIDE_GRID_Y] = 20;
136
137   map[Toolkit::Visual::Property::SHADER] = customShader;
138   return map;
139 }