Removed model loading and lighting
[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 namespace Dali
45 {
46
47 namespace Internal
48 {
49
50 namespace SceneGraph
51 {
52
53 class Material;
54
55 MeshAttachment* MeshAttachment::New()
56 {
57   return new MeshAttachment();
58 }
59
60 MeshAttachment::MeshAttachment()
61 : RenderableAttachment( true ), // scale enabled
62   mRenderer( NULL )
63 {
64 }
65
66 void MeshAttachment::PropertyOwnerDisconnected( BufferIndex bufferIndex, PropertyOwner& owner )
67 {
68   // Bone node has been disconnected.
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 );
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
122   typedef Message< MeshRenderer > DerivedType;
123
124   // Reserve some memory inside the render queue
125   unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
126
127   // Construct message in the mRenderer queue memory; note that delete should not be called on the return value
128   new (slot) DerivedType( mRenderer, &MeshRenderer::ResetCustomUniforms );
129 }
130
131 void MeshAttachment::SizeChanged( BufferIndex updateBufferIndex )
132 {
133   SetRecalculateScaleForSize();
134 }
135
136 void MeshAttachment::SetMesh( ResourceId meshId, const SceneGraph::Material* material, std::size_t boneCount )
137 {
138   mMesh.meshResourceId = meshId;
139   mMesh.material = material;
140   mMesh.boneCount = boneCount;
141
142   if( mMesh.boneCount > 0 )
143   {
144     mMesh.boneNodes.resize(mMesh.boneCount, NULL);
145   }
146 }
147
148 void MeshAttachment::SetMaterial( const SceneGraph::Material* material )
149 {
150   mMesh.material = material;
151 }
152
153 void MeshAttachment::SetBoneNode( Node* node, size_t boneIdx, size_t boneCount )
154 {
155   DALI_ASSERT_DEBUG(boneIdx < mMesh.boneNodes.size());
156
157   // Observe bone nodes (this ensures that their world matrix will be calculated)
158   if(mMesh.boneNodes[boneIdx] != NULL)
159   {
160     mMesh.boneNodes[boneIdx]->RemoveObserver( *this );
161   }
162
163   mMesh.boneNodes[boneIdx] = node;
164   if( node != NULL )
165   {
166     mMesh.boneNodes[boneIdx]->AddObserver( *this );
167   }
168 }
169
170 void MeshAttachment::CalculateBoneTransforms( BufferIndex               updateBufferIndex,
171                                               const Mesh*               mesh,
172                                               const BoneNodeContainer&  boneNodes,
173                                               BoneTransforms&           boneTransforms )
174 {
175   size_t boneCount = std::min( mesh->GetMeshData(Mesh::UPDATE_THREAD).GetBoneCount(), MAX_NUMBER_OF_BONES_PER_MESH );
176
177   const BoneContainer& bones = mesh->GetMeshData(Mesh::UPDATE_THREAD).GetBones();
178
179   for(size_t boneIdx=0; boneIdx < boneCount; ++boneIdx)
180   {
181     const Matrix&  boneMatrix = bones.at(boneIdx).GetOffsetMatrix();
182     const Node*    boneNode   = boneNodes[boneIdx];
183
184     if ( boneNode != NULL )
185     {
186       Matrix& transform = boneTransforms.transforms[boneIdx];
187       Matrix::Multiply(transform, boneMatrix, boneNode->GetWorldMatrix( updateBufferIndex ) );
188       // These transform matrices are modified once per update per renderer.
189       // The correct view matrix will be applied in the render thread to the viewTransforms
190       // list once per renderer per render task
191     }
192   }
193 }
194
195 /*
196  * Go through each mesh resource and material resource. If any of the resources aren't yet ready,
197  * stop and return false.
198  */
199 bool MeshAttachment::DoPrepareResources( BufferIndex updateBufferIndex, ResourceManager& resourceManager )
200 {
201   bool ready = false;
202   mFinishedResourceAcquisition = false;
203
204   if ( !mMesh.mesh )
205   {
206     SceneGraph::Mesh* mesh(resourceManager.GetMesh(mMesh.meshResourceId));
207     mMesh.mesh = mesh;
208   }
209
210   if ( mMesh.mesh && mMesh.mesh->HasGeometry( Mesh::UPDATE_THREAD ) )
211   {
212     const SceneGraph::Material* material = mMesh.material;
213     ready = material->AreResourcesReady();
214     mFinishedResourceAcquisition = ready;
215   }
216
217   return ready;
218 }
219
220 void MeshAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
221 {
222   DALI_ASSERT_DEBUG(mSceneController);
223
224   // Provide renderer with ModelIT matrix, mesh, material, and bone transforms for the next frame
225   MeshRenderer::MeshInfo& meshInfo = mRenderer->GetMeshInfo( updateBufferIndex );
226
227   Mesh*           meshPtr  = mMesh.mesh;
228   RenderMaterial* material = mMesh.material->GetRenderMaterial();
229
230   meshInfo.mesh     = meshPtr;
231   meshInfo.material = material;
232
233   if ( material )
234   {
235     std::size_t boneCount = mMesh.boneNodes.size();
236
237     if ( boneCount > 0 )
238     {
239       if( meshInfo.boneTransforms.transforms.size() != boneCount )
240       {
241         // Reallocate bone transforms if the number of bones has changed.
242         // ( Prefer allocation in Update thread rather than in render thread )
243         meshInfo.boneTransforms.transforms.resize( boneCount );
244         meshInfo.boneTransforms.viewTransforms.resize( boneCount );
245         meshInfo.boneTransforms.inverseTransforms.resize( boneCount );
246       }
247
248       CalculateBoneTransforms( updateBufferIndex, meshPtr, mMesh.boneNodes, meshInfo.boneTransforms );
249     }
250   }
251 }
252
253 bool MeshAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
254 {
255   bool fullyOpaque = true; // good default, since transparency is evil.
256
257   /**
258    * Fully opaque when:
259    *   1) The material is opaque
260    *   2) The inherited color is not transparent nor semi-transparent
261    *   3) The inherited shader does not blend
262    */
263
264   const SceneGraph::Material* material = mMesh.material;
265
266   if ( material && !material->IsOpaque() )
267   {
268     fullyOpaque = false;
269   }
270
271   if( mParent != NULL )
272   {
273     if( fullyOpaque )
274     {
275       fullyOpaque = ( mParent->GetWorldColor(updateBufferIndex).a >= FULLY_OPAQUE );
276     }
277
278     if ( fullyOpaque )
279     {
280       if( mShader != NULL )
281       {
282         fullyOpaque = (mShader->GetGeometryHints() != Dali::ShaderEffect::HINT_BLENDING );
283       }
284     }
285   }
286   return fullyOpaque;
287 }
288
289 void MeshAttachment::DoGetScaleForSize( const Vector3& nodeSize, Vector3& scaling )
290 {
291   scaling = Vector3::ONE;
292   // Check whether mesh data should be scaled to requiredSize
293   if( NULL != mMesh.mesh )
294   {
295     const MeshData& meshData = mMesh.mesh->GetMeshData( Mesh::UPDATE_THREAD );
296
297     if( meshData.IsScalingRequired() )
298     {
299       scaling = nodeSize;
300     }
301   }
302 }
303
304 } // namespace SceneGraph
305
306 } // namespace Internal
307
308 } // namespace Dali