2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 // http://floralicense.org/license/
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.
18 #include <dali/internal/update/node-attachments/scene-graph-mesh-attachment.h>
21 #include <dali/public-api/common/dali-common.h>
22 #include <dali/integration-api/debug.h>
24 #include <dali/internal/common/internal-constants.h>
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>
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>
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>
57 MeshAttachment* MeshAttachment::New()
59 return new MeshAttachment();
62 MeshAttachment::MeshAttachment()
63 : RenderableAttachment( true ), // scale enabled
65 mAffectedByLighting(true),
66 mLastLightingState(true),
67 mLightInitialized(false)
71 void MeshAttachment::PropertyOwnerDestroyed( PropertyOwner& owner )
73 // Bone node has been destroyed.
76 void MeshAttachment::ConnectToSceneGraph2( BufferIndex updateBufferIndex )
78 DALI_ASSERT_DEBUG( NULL != mSceneController );
80 // Create main renderer, passing ownership to the render-thread
81 mRenderer = MeshRenderer::New( *mParent, mSceneController->GetLightController() );
82 mSceneController->GetRenderMessageDispatcher().AddRenderer( *mRenderer );
85 void MeshAttachment::OnDestroy2()
87 DALI_ASSERT_DEBUG( NULL != mSceneController );
89 // Request deletion in the next Render
90 mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
94 MeshAttachment::~MeshAttachment()
96 BoneNodeContainer& boneNodes = mMesh.boneNodes;
97 for( BoneNodeContainer::iterator iter = boneNodes.begin(); iter != boneNodes.end(); ++iter )
102 node->RemoveObserver( *this );
108 Renderer& MeshAttachment::GetRenderer()
113 const Renderer& MeshAttachment::GetRenderer() const
118 void MeshAttachment::ShaderChanged( BufferIndex updateBufferIndex )
120 DALI_ASSERT_DEBUG(mSceneController);
121 Shader* shader = GetParent().GetInheritedShader();
124 typedef MessageValue1< Renderer, Shader* > DerivedType;
126 // Reserve some memory inside the render queue
127 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
134 typedef Message< MeshRenderer > DerivedType;
136 // Reserve some memory inside the render queue
137 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
144 void MeshAttachment::SizeChanged( BufferIndex updateBufferIndex )
146 SetRecalculateScaleForSize();
149 void MeshAttachment::SetMesh( ResourceId meshId, const SceneGraph::Material* material, std::size_t boneCount )
151 mMesh.meshResourceId = meshId;
152 mMesh.material = material;
153 mMesh.boneCount = boneCount;
155 if( mMesh.boneCount > 0 )
157 mMesh.boneNodes.resize(mMesh.boneCount, NULL);
161 void MeshAttachment::SetMaterial( const SceneGraph::Material* material )
163 mMesh.material = material;
166 void MeshAttachment::SetAffectedByLighting( bool affectedByLighting )
168 mAffectedByLighting = affectedByLighting;
171 void MeshAttachment::SetBoneNode( Node* node, size_t boneIdx, size_t boneCount )
173 DALI_ASSERT_DEBUG(boneIdx < mMesh.boneNodes.size());
175 // Observe bone nodes (this ensures that their world matrix will be calculated)
176 if(mMesh.boneNodes[boneIdx] != NULL)
178 mMesh.boneNodes[boneIdx]->RemoveObserver( *this );
181 mMesh.boneNodes[boneIdx] = node;
184 mMesh.boneNodes[boneIdx]->AddObserver( *this );
188 void MeshAttachment::CalculateBoneTransforms( BufferIndex updateBufferIndex,
190 const BoneNodeContainer& boneNodes,
191 BoneTransforms& boneTransforms )
193 size_t boneCount = std::min( mesh->GetMeshData(Mesh::UPDATE_THREAD).GetBoneCount(), MAX_NUMBER_OF_BONES_PER_MESH );
195 const BoneContainer& bones = mesh->GetMeshData(Mesh::UPDATE_THREAD).GetBones();
197 for(size_t boneIdx=0; boneIdx < boneCount; ++boneIdx)
199 const Matrix& boneMatrix = bones.at(boneIdx).GetOffsetMatrix();
200 const Node* boneNode = boneNodes[boneIdx];
202 if ( boneNode != NULL )
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
214 * Go through each mesh resource and material resource. If any of the resources aren't yet ready,
215 * stop and return false.
217 bool MeshAttachment::DoPrepareResources( BufferIndex updateBufferIndex, ResourceManager& resourceManager )
220 mFinishedResourceAcquisition = false;
224 SceneGraph::Mesh* mesh(resourceManager.GetMesh(mMesh.meshResourceId));
228 if ( mMesh.mesh && mMesh.mesh->HasGeometry( Mesh::UPDATE_THREAD ) )
230 const SceneGraph::Material* material = mMesh.material;
231 ready = material->AreResourcesReady();
232 mFinishedResourceAcquisition = ready;
238 void MeshAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
240 DALI_ASSERT_DEBUG(mSceneController);
241 RenderQueue& renderQueue = mSceneController->GetRenderQueue();
243 if( !mLightInitialized || ( mAffectedByLighting != mLastLightingState ) )
245 mLastLightingState = mAffectedByLighting;
246 mLightInitialized = true;
248 typedef MessageValue1< MeshRenderer, bool > DerivedType;
250 // Reserve some memory inside the render queue
251 unsigned int* slot = renderQueue.ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
257 // Provide renderer with ModelIT matrix, mesh, material, and bone transforms for the next frame
258 MeshRenderer::MeshInfo& meshInfo = mRenderer->GetMeshInfo( updateBufferIndex );
260 Mesh* meshPtr = mMesh.mesh;
261 RenderMaterial* material = mMesh.material->GetRenderMaterial();
263 meshInfo.mesh = meshPtr;
264 meshInfo.material = material;
268 std::size_t boneCount = mMesh.boneNodes.size();
272 if( meshInfo.boneTransforms.transforms.size() != boneCount )
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 );
281 CalculateBoneTransforms( updateBufferIndex, meshPtr, mMesh.boneNodes, meshInfo.boneTransforms );
286 bool MeshAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
288 bool fullyOpaque = true; // good default, since transparency is evil.
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
297 const SceneGraph::Material* material = mMesh.material;
299 if ( material && !material->IsOpaque() )
304 if( mParent != NULL )
308 fullyOpaque = ( mParent->GetWorldColor(updateBufferIndex).a >= FULLY_OPAQUE );
313 Shader* shader = mParent->GetInheritedShader();
316 fullyOpaque = (shader->GetGeometryHints() != Dali::ShaderEffect::HINT_BLENDING );
323 void MeshAttachment::DoGetScaleForSize( const Vector3& nodeSize, Vector3& scaling )
325 scaling = Vector3::ONE;
326 // Check whether mesh data should be scaled to requiredSize
327 if( NULL != mMesh.mesh )
329 const MeshData& meshData = mMesh.mesh->GetMeshData( Mesh::UPDATE_THREAD );
331 if( meshData.IsScalingRequired() )
338 } // namespace SceneGraph
340 } // namespace Internal