Revert "License conversion from Flora to Apache 2.0"
[platform/core/uifw/dali-core.git] / dali / internal / update / node-attachments / scene-graph-mesh-attachment.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 // CLASS HEADER
18 #include <dali/internal/update/node-attachments/scene-graph-mesh-attachment.h>
19
20 // INTERNAL INCLUDES
21 #include <dali/public-api/common/dali-common.h>
22 #include <dali/integration-api/debug.h>
23
24 #include <dali/internal/common/internal-constants.h>
25
26 #include <dali/internal/event/images/image-impl.h>
27 #include <dali/internal/event/modeling/mesh-impl.h>
28 #include <dali/internal/event/modeling/material-impl.h>
29
30 #include <dali/internal/update/common/discard-queue.h>
31 #include <dali/internal/update/resources/resource-manager.h>
32 #include <dali/internal/update/controllers/render-message-dispatcher.h>
33 #include <dali/internal/update/controllers/scene-controller.h>
34 #include <dali/internal/update/modeling/scene-graph-mesh.h>
35 #include <dali/internal/update/modeling/scene-graph-material.h>
36 #include <dali/internal/update/nodes/node.h>
37
38 #include <dali/internal/render/queue/render-queue.h>
39 #include <dali/internal/render/renderers/scene-graph-mesh-renderer.h>
40 #include <dali/internal/render/shaders/program.h>
41 #include <dali/internal/render/shaders/shader.h>
42
43
44 using namespace std;
45
46 namespace Dali
47 {
48
49 namespace Internal
50 {
51
52 namespace SceneGraph
53 {
54
55 class Material;
56
57 MeshAttachment* MeshAttachment::New()
58 {
59   return new MeshAttachment();
60 }
61
62 MeshAttachment::MeshAttachment()
63 : RenderableAttachment( true ), // scale enabled
64   mRenderer( NULL ),
65   mAffectedByLighting(true),
66   mLastLightingState(true),
67   mLightInitialized(false)
68 {
69 }
70
71 void MeshAttachment::PropertyOwnerDestroyed( PropertyOwner& owner )
72 {
73   // Bone node has been destroyed.
74 }
75
76 void MeshAttachment::ConnectToSceneGraph2( BufferIndex updateBufferIndex )
77 {
78   DALI_ASSERT_DEBUG( NULL != mSceneController );
79
80   // Create main renderer, passing ownership to the render-thread
81   mRenderer = MeshRenderer::New( *mParent, mSceneController->GetLightController() );
82   mSceneController->GetRenderMessageDispatcher().AddRenderer( *mRenderer );
83 }
84
85 void MeshAttachment::OnDestroy2()
86 {
87   DALI_ASSERT_DEBUG( NULL != mSceneController );
88
89   // Request deletion in the next Render
90   mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
91   mRenderer = NULL;
92 }
93
94 MeshAttachment::~MeshAttachment()
95 {
96   BoneNodeContainer& boneNodes = mMesh.boneNodes;
97   for( BoneNodeContainer::iterator iter = boneNodes.begin(); iter != boneNodes.end(); ++iter )
98   {
99     Node* node = (*iter);
100     if( node != NULL )
101     {
102       node->RemoveObserver( *this );
103     }
104   }
105
106 }
107
108 Renderer& MeshAttachment::GetRenderer()
109 {
110   return *mRenderer;
111 }
112
113 const Renderer& MeshAttachment::GetRenderer() const
114 {
115   return *mRenderer;
116 }
117
118 void MeshAttachment::ShaderChanged( BufferIndex updateBufferIndex )
119 {
120   DALI_ASSERT_DEBUG(mSceneController);
121   Shader* shader = GetParent().GetInheritedShader();
122
123   {
124     typedef MessageValue1< Renderer, Shader* > DerivedType;
125
126     // Reserve some memory inside the render queue
127     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
128
129     // Construct message in the mRenderer queue memory; note that delete should not be called on the return value
130     new (slot) DerivedType( mRenderer, &Renderer::SetShader, shader );
131   }
132
133   {
134     typedef Message< MeshRenderer > DerivedType;
135
136     // Reserve some memory inside the render queue
137     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
138
139     // Construct message in the mRenderer queue memory; note that delete should not be called on the return value
140     new (slot) DerivedType( mRenderer, &MeshRenderer::ResetCustomUniforms );
141   }
142 }
143
144 void MeshAttachment::SizeChanged( BufferIndex updateBufferIndex )
145 {
146   SetRecalculateScaleForSize();
147 }
148
149 void MeshAttachment::SetMesh( ResourceId meshId, const SceneGraph::Material* material, std::size_t boneCount )
150 {
151   mMesh.meshResourceId = meshId;
152   mMesh.material = material;
153   mMesh.boneCount = boneCount;
154
155   if( mMesh.boneCount > 0 )
156   {
157     mMesh.boneNodes.resize(mMesh.boneCount, NULL);
158   }
159 }
160
161 void MeshAttachment::SetMaterial( const SceneGraph::Material* material )
162 {
163   mMesh.material = material;
164 }
165
166 void MeshAttachment::SetAffectedByLighting( bool affectedByLighting )
167 {
168   mAffectedByLighting = affectedByLighting;
169 }
170
171 void MeshAttachment::SetBoneNode( Node* node, size_t boneIdx, size_t boneCount )
172 {
173   DALI_ASSERT_DEBUG(boneIdx < mMesh.boneNodes.size());
174
175   // Observe bone nodes (this ensures that their world matrix will be calculated)
176   if(mMesh.boneNodes[boneIdx] != NULL)
177   {
178     mMesh.boneNodes[boneIdx]->RemoveObserver( *this );
179   }
180
181   mMesh.boneNodes[boneIdx] = node;
182   if( node != NULL )
183   {
184     mMesh.boneNodes[boneIdx]->AddObserver( *this );
185   }
186 }
187
188 void MeshAttachment::CalculateBoneTransforms( BufferIndex               updateBufferIndex,
189                                               const Mesh*               mesh,
190                                               const BoneNodeContainer&  boneNodes,
191                                               BoneTransforms&           boneTransforms )
192 {
193   size_t boneCount = std::min( mesh->GetMeshData(Mesh::UPDATE_THREAD).GetBoneCount(), MAX_NUMBER_OF_BONES_PER_MESH );
194
195   const BoneContainer& bones = mesh->GetMeshData(Mesh::UPDATE_THREAD).GetBones();
196
197   for(size_t boneIdx=0; boneIdx < boneCount; ++boneIdx)
198   {
199     const Matrix&  boneMatrix = bones.at(boneIdx).GetOffsetMatrix();
200     const Node*    boneNode   = boneNodes[boneIdx];
201
202     if ( boneNode != NULL )
203     {
204       Matrix& transform = boneTransforms.transforms[boneIdx];
205       Matrix::Multiply(transform, boneMatrix, boneNode->GetWorldMatrix( updateBufferIndex ) );
206       // These transform matrices are modified once per update per renderer.
207       // The correct view matrix will be applied in the render thread to the viewTransforms
208       // list once per renderer per render task
209     }
210   }
211 }
212
213 /*
214  * Go through each mesh resource and material resource. If any of the resources aren't yet ready,
215  * stop and return false.
216  */
217 bool MeshAttachment::DoPrepareResources( BufferIndex updateBufferIndex, ResourceManager& resourceManager )
218 {
219   bool ready = false;
220   mFinishedResourceAcquisition = false;
221
222   if ( !mMesh.mesh )
223   {
224     SceneGraph::Mesh* mesh(resourceManager.GetMesh(mMesh.meshResourceId));
225     mMesh.mesh = mesh;
226   }
227
228   if ( mMesh.mesh && mMesh.mesh->HasGeometry( Mesh::UPDATE_THREAD ) )
229   {
230     const SceneGraph::Material* material = mMesh.material;
231     ready = material->AreResourcesReady();
232     mFinishedResourceAcquisition = ready;
233   }
234
235   return ready;
236 }
237
238 void MeshAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
239 {
240   DALI_ASSERT_DEBUG(mSceneController);
241   RenderQueue& renderQueue = mSceneController->GetRenderQueue();
242
243   if( !mLightInitialized || ( mAffectedByLighting != mLastLightingState ) )
244   {
245     mLastLightingState = mAffectedByLighting;
246     mLightInitialized = true;
247
248     typedef MessageValue1< MeshRenderer, bool > DerivedType;
249
250     // Reserve some memory inside the render queue
251     unsigned int* slot = renderQueue.ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
252
253     // Construct message in the render queue memory; note that delete should not be called on the return value
254     new (slot) DerivedType( mRenderer, &MeshRenderer::SetAffectedByLighting, mAffectedByLighting );
255   }
256
257   // Provide renderer with ModelIT matrix, mesh, material, and bone transforms for the next frame
258   MeshRenderer::MeshInfo& meshInfo = mRenderer->GetMeshInfo( updateBufferIndex );
259
260   Mesh*           meshPtr  = mMesh.mesh;
261   RenderMaterial* material = mMesh.material->GetRenderMaterial();
262
263   meshInfo.mesh     = meshPtr;
264   meshInfo.material = material;
265
266   if ( material )
267   {
268     std::size_t boneCount = mMesh.boneNodes.size();
269
270     if ( boneCount > 0 )
271     {
272       if( meshInfo.boneTransforms.transforms.size() != boneCount )
273       {
274         // Reallocate bone transforms if the number of bones has changed.
275         // ( Prefer allocation in Update thread rather than in render thread )
276         meshInfo.boneTransforms.transforms.resize( boneCount );
277         meshInfo.boneTransforms.viewTransforms.resize( boneCount );
278         meshInfo.boneTransforms.inverseTransforms.resize( boneCount );
279       }
280
281       CalculateBoneTransforms( updateBufferIndex, meshPtr, mMesh.boneNodes, meshInfo.boneTransforms );
282     }
283   }
284 }
285
286 bool MeshAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
287 {
288   bool fullyOpaque = true; // good default, since transparency is evil.
289
290   /**
291    * Fully opaque when:
292    *   1) The material is opaque
293    *   2) The inherited color is not transparent nor semi-transparent
294    *   3) The inherited shader does not blend
295    */
296
297   const SceneGraph::Material* material = mMesh.material;
298
299   if ( material && !material->IsOpaque() )
300   {
301     fullyOpaque = false;
302   }
303
304   if( mParent != NULL )
305   {
306     if( fullyOpaque )
307     {
308       fullyOpaque = ( mParent->GetWorldColor(updateBufferIndex).a >= FULLY_OPAQUE );
309     }
310
311     if ( fullyOpaque )
312     {
313       Shader* shader = mParent->GetInheritedShader();
314       if( shader != NULL )
315       {
316         fullyOpaque = (shader->GetGeometryHints() != Dali::ShaderEffect::HINT_BLENDING );
317       }
318     }
319   }
320   return fullyOpaque;
321 }
322
323 void MeshAttachment::DoGetScaleForSize( const Vector3& nodeSize, Vector3& scaling )
324 {
325   scaling = Vector3::ONE;
326   // Check whether mesh data should be scaled to requiredSize
327   if( NULL != mMesh.mesh )
328   {
329     const MeshData& meshData = mMesh.mesh->GetMeshData( Mesh::UPDATE_THREAD );
330
331     if( meshData.IsScalingRequired() )
332     {
333       scaling = nodeSize;
334     }
335   }
336 }
337
338 } // namespace SceneGraph
339
340 } // namespace Internal
341
342 } // namespace Dali