2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/update/node-attachments/scene-graph-mesh-attachment.h>
22 #include <dali/public-api/common/dali-common.h>
23 #include <dali/integration-api/debug.h>
25 #include <dali/internal/common/internal-constants.h>
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>
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>
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>
58 MeshAttachment* MeshAttachment::New()
60 return new MeshAttachment();
63 MeshAttachment::MeshAttachment()
64 : RenderableAttachment( true ), // scale enabled
66 mAffectedByLighting(true),
67 mLastLightingState(true),
68 mLightInitialized(false)
72 void MeshAttachment::PropertyOwnerDestroyed( PropertyOwner& owner )
74 // Bone node has been destroyed.
77 void MeshAttachment::ConnectToSceneGraph2( BufferIndex updateBufferIndex )
79 DALI_ASSERT_DEBUG( NULL != mSceneController );
81 // Create main renderer, passing ownership to the render-thread
82 mRenderer = MeshRenderer::New( *mParent, mSceneController->GetLightController() );
83 mSceneController->GetRenderMessageDispatcher().AddRenderer( *mRenderer );
86 void MeshAttachment::OnDestroy2()
88 DALI_ASSERT_DEBUG( NULL != mSceneController );
90 // Request deletion in the next Render
91 mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
95 MeshAttachment::~MeshAttachment()
97 BoneNodeContainer& boneNodes = mMesh.boneNodes;
98 for( BoneNodeContainer::iterator iter = boneNodes.begin(); iter != boneNodes.end(); ++iter )
100 Node* node = (*iter);
103 node->RemoveObserver( *this );
109 Renderer& MeshAttachment::GetRenderer()
114 const Renderer& MeshAttachment::GetRenderer() const
119 void MeshAttachment::ShaderChanged( BufferIndex updateBufferIndex )
121 DALI_ASSERT_DEBUG(mSceneController);
123 typedef Message< MeshRenderer > DerivedType;
125 // Reserve some memory inside the render queue
126 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
132 void MeshAttachment::SizeChanged( BufferIndex updateBufferIndex )
134 SetRecalculateScaleForSize();
137 void MeshAttachment::SetMesh( ResourceId meshId, const SceneGraph::Material* material, std::size_t boneCount )
139 mMesh.meshResourceId = meshId;
140 mMesh.material = material;
141 mMesh.boneCount = boneCount;
143 if( mMesh.boneCount > 0 )
145 mMesh.boneNodes.resize(mMesh.boneCount, NULL);
149 void MeshAttachment::SetMaterial( const SceneGraph::Material* material )
151 mMesh.material = material;
154 void MeshAttachment::SetAffectedByLighting( bool affectedByLighting )
156 mAffectedByLighting = affectedByLighting;
159 void MeshAttachment::SetBoneNode( Node* node, size_t boneIdx, size_t boneCount )
161 DALI_ASSERT_DEBUG(boneIdx < mMesh.boneNodes.size());
163 // Observe bone nodes (this ensures that their world matrix will be calculated)
164 if(mMesh.boneNodes[boneIdx] != NULL)
166 mMesh.boneNodes[boneIdx]->RemoveObserver( *this );
169 mMesh.boneNodes[boneIdx] = node;
172 mMesh.boneNodes[boneIdx]->AddObserver( *this );
176 void MeshAttachment::CalculateBoneTransforms( BufferIndex updateBufferIndex,
178 const BoneNodeContainer& boneNodes,
179 BoneTransforms& boneTransforms )
181 size_t boneCount = std::min( mesh->GetMeshData(Mesh::UPDATE_THREAD).GetBoneCount(), MAX_NUMBER_OF_BONES_PER_MESH );
183 const BoneContainer& bones = mesh->GetMeshData(Mesh::UPDATE_THREAD).GetBones();
185 for(size_t boneIdx=0; boneIdx < boneCount; ++boneIdx)
187 const Matrix& boneMatrix = bones.at(boneIdx).GetOffsetMatrix();
188 const Node* boneNode = boneNodes[boneIdx];
190 if ( boneNode != NULL )
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
202 * Go through each mesh resource and material resource. If any of the resources aren't yet ready,
203 * stop and return false.
205 bool MeshAttachment::DoPrepareResources( BufferIndex updateBufferIndex, ResourceManager& resourceManager )
208 mFinishedResourceAcquisition = false;
212 SceneGraph::Mesh* mesh(resourceManager.GetMesh(mMesh.meshResourceId));
216 if ( mMesh.mesh && mMesh.mesh->HasGeometry( Mesh::UPDATE_THREAD ) )
218 const SceneGraph::Material* material = mMesh.material;
219 ready = material->AreResourcesReady();
220 mFinishedResourceAcquisition = ready;
226 void MeshAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
228 DALI_ASSERT_DEBUG(mSceneController);
229 RenderQueue& renderQueue = mSceneController->GetRenderQueue();
231 if( !mLightInitialized || ( mAffectedByLighting != mLastLightingState ) )
233 mLastLightingState = mAffectedByLighting;
234 mLightInitialized = true;
236 typedef MessageValue1< MeshRenderer, bool > DerivedType;
238 // Reserve some memory inside the render queue
239 unsigned int* slot = renderQueue.ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
245 // Provide renderer with ModelIT matrix, mesh, material, and bone transforms for the next frame
246 MeshRenderer::MeshInfo& meshInfo = mRenderer->GetMeshInfo( updateBufferIndex );
248 Mesh* meshPtr = mMesh.mesh;
249 RenderMaterial* material = mMesh.material->GetRenderMaterial();
251 meshInfo.mesh = meshPtr;
252 meshInfo.material = material;
256 std::size_t boneCount = mMesh.boneNodes.size();
260 if( meshInfo.boneTransforms.transforms.size() != boneCount )
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 );
269 CalculateBoneTransforms( updateBufferIndex, meshPtr, mMesh.boneNodes, meshInfo.boneTransforms );
274 bool MeshAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
276 bool fullyOpaque = true; // good default, since transparency is evil.
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
285 const SceneGraph::Material* material = mMesh.material;
287 if ( material && !material->IsOpaque() )
292 if( mParent != NULL )
296 fullyOpaque = ( mParent->GetWorldColor(updateBufferIndex).a >= FULLY_OPAQUE );
301 if( mShader != NULL )
303 fullyOpaque = (mShader->GetGeometryHints() != Dali::ShaderEffect::HINT_BLENDING );
310 void MeshAttachment::DoGetScaleForSize( const Vector3& nodeSize, Vector3& scaling )
312 scaling = Vector3::ONE;
313 // Check whether mesh data should be scaled to requiredSize
314 if( NULL != mMesh.mesh )
316 const MeshData& meshData = mMesh.mesh->GetMeshData( Mesh::UPDATE_THREAD );
318 if( meshData.IsScalingRequired() )
325 } // namespace SceneGraph
327 } // namespace Internal