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>
55 MeshAttachment* MeshAttachment::New()
57 return new MeshAttachment();
60 MeshAttachment::MeshAttachment()
61 : RenderableAttachment( true ), // scale enabled
66 void MeshAttachment::PropertyOwnerDisconnected( BufferIndex bufferIndex, PropertyOwner& owner )
68 // Bone node has been disconnected.
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 );
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);
122 typedef Message< MeshRenderer > DerivedType;
124 // Reserve some memory inside the render queue
125 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
131 void MeshAttachment::SizeChanged( BufferIndex updateBufferIndex )
133 SetRecalculateScaleForSize();
136 void MeshAttachment::SetMesh( ResourceId meshId, const SceneGraph::Material* material, std::size_t boneCount )
138 mMesh.meshResourceId = meshId;
139 mMesh.material = material;
140 mMesh.boneCount = boneCount;
142 if( mMesh.boneCount > 0 )
144 mMesh.boneNodes.resize(mMesh.boneCount, NULL);
148 void MeshAttachment::SetMaterial( const SceneGraph::Material* material )
150 mMesh.material = material;
153 void MeshAttachment::SetBoneNode( Node* node, size_t boneIdx, size_t boneCount )
155 DALI_ASSERT_DEBUG(boneIdx < mMesh.boneNodes.size());
157 // Observe bone nodes (this ensures that their world matrix will be calculated)
158 if(mMesh.boneNodes[boneIdx] != NULL)
160 mMesh.boneNodes[boneIdx]->RemoveObserver( *this );
163 mMesh.boneNodes[boneIdx] = node;
166 mMesh.boneNodes[boneIdx]->AddObserver( *this );
170 void MeshAttachment::CalculateBoneTransforms( BufferIndex updateBufferIndex,
172 const BoneNodeContainer& boneNodes,
173 BoneTransforms& boneTransforms )
175 size_t boneCount = std::min( mesh->GetMeshData(Mesh::UPDATE_THREAD).GetBoneCount(), MAX_NUMBER_OF_BONES_PER_MESH );
177 const BoneContainer& bones = mesh->GetMeshData(Mesh::UPDATE_THREAD).GetBones();
179 for(size_t boneIdx=0; boneIdx < boneCount; ++boneIdx)
181 const Matrix& boneMatrix = bones.at(boneIdx).GetOffsetMatrix();
182 const Node* boneNode = boneNodes[boneIdx];
184 if ( boneNode != NULL )
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
196 * Go through each mesh resource and material resource. If any of the resources aren't yet ready,
197 * stop and return false.
199 bool MeshAttachment::DoPrepareResources( BufferIndex updateBufferIndex, ResourceManager& resourceManager )
202 mFinishedResourceAcquisition = false;
206 SceneGraph::Mesh* mesh(resourceManager.GetMesh(mMesh.meshResourceId));
210 if ( mMesh.mesh && mMesh.mesh->HasGeometry( Mesh::UPDATE_THREAD ) )
212 const SceneGraph::Material* material = mMesh.material;
213 ready = material->AreResourcesReady();
214 mFinishedResourceAcquisition = ready;
220 void MeshAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
222 DALI_ASSERT_DEBUG(mSceneController);
224 // Provide renderer with ModelIT matrix, mesh, material, and bone transforms for the next frame
225 MeshRenderer::MeshInfo& meshInfo = mRenderer->GetMeshInfo( updateBufferIndex );
227 Mesh* meshPtr = mMesh.mesh;
228 RenderMaterial* material = mMesh.material->GetRenderMaterial();
230 meshInfo.mesh = meshPtr;
231 meshInfo.material = material;
235 std::size_t boneCount = mMesh.boneNodes.size();
239 if( meshInfo.boneTransforms.transforms.size() != boneCount )
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 );
248 CalculateBoneTransforms( updateBufferIndex, meshPtr, mMesh.boneNodes, meshInfo.boneTransforms );
253 bool MeshAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
255 bool fullyOpaque = true; // good default, since transparency is evil.
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
264 const SceneGraph::Material* material = mMesh.material;
266 if ( material && !material->IsOpaque() )
271 if( mParent != NULL )
275 fullyOpaque = ( mParent->GetWorldColor(updateBufferIndex).a >= FULLY_OPAQUE );
280 if( mShader != NULL )
282 fullyOpaque = (mShader->GetGeometryHints() != Dali::ShaderEffect::HINT_BLENDING );
289 void MeshAttachment::DoGetScaleForSize( const Vector3& nodeSize, Vector3& scaling )
291 scaling = Vector3::ONE;
292 // Check whether mesh data should be scaled to requiredSize
293 if( NULL != mMesh.mesh )
295 const MeshData& meshData = mMesh.mesh->GetMeshData( Mesh::UPDATE_THREAD );
297 if( meshData.IsScalingRequired() )
304 } // namespace SceneGraph
306 } // namespace Internal