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