Merge branch 'devel/master' into devel/new_mesh
[platform/core/uifw/dali-core.git] / dali / internal / update / rendering / scene-graph-geometry.cpp
1 /*
2  * Copyright (c) 2015 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 #include "scene-graph-geometry.h"
18
19 namespace Dali
20 {
21 namespace Internal
22 {
23 namespace SceneGraph
24 {
25
26 Geometry::Geometry()
27 : mIndexBuffer( NULL ),
28   mCenter(),
29   mHalfExtents(),
30   mRadius( 0.0f ),
31   mGeometryType(Dali::Geometry::TRIANGLES),
32   mRequiresDepthTest(false)
33 {
34
35   // Observe our own PropertyOwner's uniform map
36   AddUniformMapObserver( *this );
37 }
38
39 Geometry::~Geometry()
40 {
41   // @todo Inform renderers of deletion of buffers?
42
43   // could remove self from own uniform map observer, but it's about to be destroyed.
44 }
45
46 void Geometry::AddVertexBuffer( PropertyBuffer* vertexBuffer )
47 {
48   mVertexBuffers.PushBack( vertexBuffer );
49   CalculateExtents( vertexBuffer );
50   vertexBuffer->AddUniformMapObserver(*this);
51   mConnectionObservers.ConnectionsChanged(*this);
52 }
53
54 void Geometry::RemoveVertexBuffer( PropertyBuffer* vertexBuffer )
55 {
56   DALI_ASSERT_DEBUG( NULL != vertexBuffer );
57
58   // Find the object and destroy it
59   Vector<PropertyBuffer*>::Iterator match = std::find(
60     mVertexBuffers.Begin(),
61     mVertexBuffers.End(),
62     vertexBuffer );
63
64   DALI_ASSERT_DEBUG( mVertexBuffers.End() != match );
65   if( mVertexBuffers.End() != match )
66   {
67     vertexBuffer->RemoveUniformMapObserver(*this);
68     mVertexBuffers.Erase( match );
69     mConnectionObservers.ConnectionsChanged(*this);
70   }
71 }
72
73 void Geometry::SetIndexBuffer( PropertyBuffer* indexBuffer )
74 {
75   if( mIndexBuffer != indexBuffer )
76   {
77     mIndexBuffer = indexBuffer;
78     indexBuffer->AddUniformMapObserver(*this);
79     mConnectionObservers.ConnectionsChanged(*this);
80   }
81 }
82
83 void Geometry::ClearIndexBuffer()
84 {
85   // @todo Actually delete, or put on Discard Queue and tell Renderer in render thread?
86   if( mIndexBuffer )
87   {
88     mIndexBuffer->RemoveUniformMapObserver(*this);
89   }
90   mIndexBuffer = 0;
91   mConnectionObservers.ConnectionsChanged(*this);
92 }
93
94 void Geometry::SetGeometryType( BufferIndex bufferIndex, Geometry::GeometryType geometryType )
95 {
96   mGeometryType.Set( bufferIndex, geometryType);
97 }
98
99 Vector<PropertyBuffer*>& Geometry::GetVertexBuffers()
100 {
101   return mVertexBuffers;
102 }
103
104 PropertyBuffer* Geometry::GetIndexBuffer()
105 {
106   return mIndexBuffer;
107 }
108
109 Geometry::GeometryType Geometry::GetGeometryType( BufferIndex bufferIndex) const
110 {
111   int geometryType = mGeometryType[ bufferIndex ];
112   return static_cast< GeometryDataProvider::GeometryType > ( geometryType );
113 }
114
115 bool Geometry::GetRequiresDepthTesting( BufferIndex bufferIndex ) const
116 {
117   return mRequiresDepthTest.GetBoolean( bufferIndex );
118 }
119
120 void Geometry::ResetDefaultProperties( BufferIndex updateBufferIndex )
121 {
122   // Reset the animated properties
123   mCenter.ResetToBaseValue( updateBufferIndex );
124   mHalfExtents.ResetToBaseValue( updateBufferIndex );
125   mRadius.ResetToBaseValue( updateBufferIndex );
126
127   // Age the double buffered properties
128   mGeometryType.CopyPrevious(updateBufferIndex);
129   mRequiresDepthTest.CopyPrevious(updateBufferIndex);
130 }
131
132 void Geometry::CalculateExtents( PropertyBuffer* vertexBuffer )
133 {
134   // TODO calculate extents for all vertex buffers attached to geometry
135   unsigned int elementIndex = 0;
136   unsigned int elementCount = vertexBuffer->GetElementCount( 0 );
137   unsigned int elementCount1 = vertexBuffer->GetElementCount( 1 );
138
139   // Select the double buffered element list that is the largest...
140   if ( elementCount < elementCount1 )
141   {
142     elementCount = elementCount1;
143     elementIndex = 1;
144   }
145
146   unsigned int attributeCount = vertexBuffer->GetAttributeCount( elementIndex );
147   unsigned int elementSize = vertexBuffer->GetElementSize( elementIndex );
148
149   std::string posName( "aPos" );
150   std::size_t found;
151
152   float left = 0.0f;
153   float right = 0.0f;
154   float top = 0.0f;
155   float bottom = 0.0f;
156
157   // Find the position attribute index
158   for ( unsigned int i = 0; i < attributeCount; ++i )
159   {
160     found = vertexBuffer->GetAttributeName( 0, i ).find( posName );
161     if ( found != std::string::npos )
162     {
163       unsigned int offset = vertexBuffer->GetAttributeOffset( elementIndex, i );
164       const PropertyBufferDataProvider::BufferType& data = vertexBuffer->GetData( elementIndex );
165
166       // Check attribute type to determine correct position type
167       Property::Type positionType = vertexBuffer->GetAttributeType( elementIndex, i );
168       Vector3 halfExtents;
169       Vector3 center;
170       switch ( positionType )
171       {
172         case Property::VECTOR2:
173         {
174           for ( unsigned int j = 0; j < elementCount; ++j )
175           {
176             const Vector2* position = reinterpret_cast< const Vector2* >( &data[ offset ] );
177             offset += elementSize;
178
179             if ( position->x < left )
180             {
181               left = position->x;
182             }
183             if ( position->x > right )
184             {
185               right = position->x;
186             }
187             if ( position->y < top )
188             {
189               top = position->y;
190             }
191             if ( position->y > bottom )
192             {
193               bottom = position->y;
194             }
195           }
196
197           halfExtents = Vector3( ( right - left ) * 0.5f, ( bottom - top ) * 0.5f, 0.0f );
198           center = Vector3( halfExtents.x + left , halfExtents.y + top, 0.0f );
199           break;
200         }
201         case Property::VECTOR3:
202         {
203           float near = 0.0f;
204           float far = 0.0f;
205           for ( unsigned int j = 0; j < elementCount; ++j )
206           {
207             const Vector3* position = reinterpret_cast< const Vector3* >( &data[ offset ] );
208             offset += elementSize;
209
210             if ( position->x < left )
211             {
212               left = position->x;
213             }
214             if ( position->x > right )
215             {
216               right = position->x;
217             }
218             if ( position->y < top )
219             {
220               top = position->y;
221             }
222             if ( position->y > bottom )
223             {
224               bottom = position->y;
225             }
226             if ( position->z > far )
227             {
228               far = position->z;
229             }
230             if ( position->z < near )
231             {
232               near = position->z;
233             }
234           }
235           halfExtents = Vector3( ( right - left ) * 0.5f, ( bottom - top ) * 0.5f, ( far - near ) * 0.5f );
236           center = Vector3( halfExtents.x + left , halfExtents.y + top, halfExtents.z + near );
237           break;
238         }
239         default:
240         {
241           break;
242         }
243       }
244       mCenter.Bake( 0, center );
245       mCenter.Bake( 1, center );
246       mHalfExtents.Bake( 0, halfExtents );
247       mHalfExtents.Bake( 1, halfExtents );
248
249       float radius = halfExtents.x;
250       if ( radius < halfExtents.y )
251       {
252         radius = halfExtents.y;
253       }
254       mRadius.SetInitial( radius );
255     }
256   }
257 }
258
259 void Geometry::ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
260 {
261 }
262
263 void Geometry::DisconnectFromSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
264 {
265 }
266
267 void Geometry::AddConnectionObserver( ConnectionChangePropagator::Observer& observer )
268 {
269   mConnectionObservers.Add(observer);
270 }
271
272 void Geometry::RemoveConnectionObserver( ConnectionChangePropagator::Observer& observer )
273 {
274   mConnectionObservers.Remove(observer);
275 }
276
277 void Geometry::UniformMappingsChanged( const UniformMap& mappings )
278 {
279   // Our uniform map, or that of one of the watched children has changed.
280   // Inform connected observers.
281   mConnectionObservers.ConnectedUniformMapChanged();
282 }
283
284 } // namespace SceneGraph
285 } // namespace Internal
286 } // namespace Dali