2 * Copyright (c) 2024 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-toolkit/internal/controls/scene3d-view/gltf-loader.h>
22 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
23 #include <dali/devel-api/actors/camera-actor-devel.h>
24 #include <dali/devel-api/adaptor-framework/file-stream.h>
25 #include <dali/devel-api/adaptor-framework/image-loading.h>
26 #include <dali/integration-api/debug.h>
29 #include <dali-toolkit/internal/controls/scene3d-view/scene3d-view-impl.h>
41 constexpr float MIN_DURATION_SECONDS = 1e-2f;
44 const TreeNode* Tidx(const TreeNode* node, uint32_t index)
47 for(auto it = node->CBegin(), end = node->CEnd(); it != end; ++it, ++i)
51 return &((*it).second);
57 bool ReadBool(const TreeNode* node, bool& num)
63 bool returnValue = false;
65 if(node->GetType() == TreeNode::BOOLEAN)
67 num = node->GetBoolean();
74 bool ReadInt(const TreeNode* node, int32_t& num)
80 bool returnValue = false;
81 if(node->GetType() == TreeNode::INTEGER)
83 num = node->GetInteger();
86 else if(node->GetType() == TreeNode::FLOAT)
88 num = node->GetFloat();
95 bool ReadFloat(const TreeNode* node, float& num)
101 bool returnValue = false;
103 if(node->GetType() == TreeNode::FLOAT)
105 num = node->GetFloat();
108 else if(node->GetType() == TreeNode::INTEGER)
111 ReadInt(node, tempNum);
112 num = static_cast<float>(tempNum);
119 bool ReadVector(const TreeNode* node, float* num, uint32_t size)
125 bool returnValue = false;
127 if((node->Size() >= size) && (node->GetType() == TreeNode::ARRAY))
129 uint32_t offset = 0u;
130 for(auto it = node->CBegin(); offset < size; ++it, ++offset)
132 const TreeNode& coord = (*it).second;
133 if(!ReadFloat(&coord, *(num + offset)))
144 bool ReadString(const TreeNode* node, std::string& strValue)
150 bool returnValue = false;
151 if(node->GetType() == TreeNode::STRING)
153 strValue = node->GetString();
160 float IntToFloat(T element, bool normalize)
164 return static_cast<float>(element);
167 if(std::is_same<T, int8_t>::value)
169 return std::max(static_cast<float>(element) / 127.0, -1.0);
171 if(std::is_same<T, uint8_t>::value)
173 return static_cast<float>(element) / 255.0;
175 if(std::is_same<T, int16_t>::value)
177 return std::max(static_cast<float>(element) / 32767.0, -1.0);
179 if(std::is_same<T, uint16_t>::value)
181 return static_cast<float>(element) / 65535.0;
186 template<typename Td, typename Ts>
187 void FitBuffer(Dali::Vector<Td>& bufferDestination, Dali::Vector<Ts>& bufferSource, int32_t bufferSize, int32_t elementNumOfByteStride, bool normalize)
189 bufferDestination.Resize(bufferSize);
190 int32_t count = bufferSource.Size() / elementNumOfByteStride;
191 for(int32_t i = 0; i < count; ++i)
193 bufferDestination[i] = static_cast<Td>(bufferSource[i * elementNumOfByteStride]);
198 void FitBuffer(Dali::Vector<Vector2>& bufferDestination, Dali::Vector<T>& bufferSource, int32_t bufferSize, int32_t elementNumOfByteStride, bool normalize)
200 bufferDestination.Resize(bufferSize);
201 int32_t count = bufferSource.Size() / elementNumOfByteStride;
202 for(int32_t i = 0; i < count; ++i)
204 bufferDestination[i].x = IntToFloat(bufferSource[i * elementNumOfByteStride], normalize);
205 bufferDestination[i].y = IntToFloat(bufferSource[i * elementNumOfByteStride + 1], normalize);
210 void FitBuffer(Dali::Vector<Vector3>& bufferDestination, Dali::Vector<T>& bufferSource, int32_t bufferSize, int32_t elementNumOfByteStride, bool normalize)
212 bufferDestination.Resize(bufferSize);
213 int32_t count = bufferSource.Size() / elementNumOfByteStride;
214 for(int32_t i = 0; i < count; ++i)
216 bufferDestination[i].x = IntToFloat(bufferSource[i * elementNumOfByteStride], normalize);
217 bufferDestination[i].y = IntToFloat(bufferSource[i * elementNumOfByteStride + 1], normalize);
218 bufferDestination[i].z = IntToFloat(bufferSource[i * elementNumOfByteStride + 2], normalize);
223 void FitBuffer(Dali::Vector<Vector4>& bufferDestination, Dali::Vector<T>& bufferSource, int32_t bufferSize, int32_t elementNumOfByteStride, bool normalize)
225 bufferDestination.Resize(bufferSize);
226 int32_t count = bufferSource.Size() / elementNumOfByteStride;
227 for(int32_t i = 0; i < count; ++i)
229 bufferDestination[i].x = IntToFloat(bufferSource[i * elementNumOfByteStride], normalize);
230 bufferDestination[i].y = IntToFloat(bufferSource[i * elementNumOfByteStride + 1], normalize);
231 bufferDestination[i].z = IntToFloat(bufferSource[i * elementNumOfByteStride + 2], normalize);
232 bufferDestination[i].w = IntToFloat(bufferSource[i * elementNumOfByteStride + 3], normalize);
236 // Template functions
238 bool ReadBinFile(Vector<T>& dataBuffer, std::string url, int32_t offset, int32_t count)
240 size_t readCount = 0;
241 Dali::FileStream fileStream(url, FileStream::READ | FileStream::BINARY);
242 FILE* fp = fileStream.GetFile();
245 dataBuffer.Resize(count);
246 if(!fseek(fp, offset, SEEK_SET))
248 readCount = fread(&dataBuffer[0], sizeof(T), count, fp);
249 dataBuffer.Resize(readCount);
253 return (readCount > 0);
257 void LoadDataFromAccessor(int32_t accessorIdx, Dali::Vector<T>& bufferData, std::string path, std::vector<AccessorInfo>& accessorArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<BufferInfo>& bufferArray)
259 AccessorInfo accessor = accessorArray[accessorIdx];
260 BufferViewInfo bufferView = bufferViewArray[accessor.bufferView];
261 std::string load_uri = bufferArray[bufferView.buffer].uri;
263 // In the glTF 2.0 Specification, 5121 is UNSIGNED BYTE, 5123 is UNSIGNED SHORT
264 int32_t elementByteSize = (accessor.componentType <= 5121) ? 1 : ((accessor.componentType <= 5123) ? 2 : 4);
265 int32_t elementNum = 1;
266 if(accessor.type == "VEC2")
270 else if(accessor.type == "VEC3")
274 else if(accessor.type == "VEC4" || accessor.type == "MAT2")
278 else if(accessor.type == "MAT3")
282 else if(accessor.type == "MAT4")
290 int32_t elementNumOfByteStride = elementNum;
291 if(bufferView.byteStride > 0)
293 elementNumOfByteStride = bufferView.byteStride / elementByteSize;
297 * glTF 2.0 Specification
300 * 5121 : UNSIGNED_BYTE
302 * 5123 : UNSIGNED_SHORT
303 * 5125 : UNSIGNED_INT
306 if(accessor.componentType == 5120)
308 Dali::Vector<int8_t> inputBufferData;
309 if(ReadBinFile<int8_t>(inputBufferData, path + load_uri, bufferView.byteOffset + accessor.byteOffset, elementNumOfByteStride * accessor.count))
311 FitBuffer(bufferData, inputBufferData, accessor.count, elementNumOfByteStride, accessor.normalized);
314 else if(accessor.componentType == 5121)
316 Dali::Vector<uint8_t> inputBufferData;
317 if(ReadBinFile<uint8_t>(inputBufferData, path + load_uri, bufferView.byteOffset + accessor.byteOffset, elementNumOfByteStride * accessor.count))
319 FitBuffer(bufferData, inputBufferData, accessor.count, elementNumOfByteStride, accessor.normalized);
322 else if(accessor.componentType == 5122)
324 Dali::Vector<int16_t> inputBufferData;
325 if(ReadBinFile<int16_t>(inputBufferData, path + load_uri, bufferView.byteOffset + accessor.byteOffset, elementNumOfByteStride * accessor.count))
327 FitBuffer(bufferData, inputBufferData, accessor.count, elementNumOfByteStride, accessor.normalized);
330 else if(accessor.componentType == 5123)
332 Dali::Vector<uint16_t> inputBufferData;
333 if(ReadBinFile<uint16_t>(inputBufferData, path + load_uri, bufferView.byteOffset + accessor.byteOffset, elementNumOfByteStride * accessor.count))
335 FitBuffer(bufferData, inputBufferData, accessor.count, elementNumOfByteStride, accessor.normalized);
338 else if(accessor.componentType == 5125)
340 Dali::Vector<uint32_t> inputBufferData;
341 if(ReadBinFile<uint32_t>(inputBufferData, path + load_uri, bufferView.byteOffset + accessor.byteOffset, elementNumOfByteStride * accessor.count))
343 FitBuffer(bufferData, inputBufferData, accessor.count, elementNumOfByteStride, accessor.normalized);
346 else if(accessor.componentType == 5126)
348 Dali::Vector<float> inputBufferData;
349 if(ReadBinFile<float>(inputBufferData, path + load_uri, bufferView.byteOffset + accessor.byteOffset, elementNumOfByteStride * accessor.count))
351 FitBuffer(bufferData, inputBufferData, accessor.count, elementNumOfByteStride, accessor.normalized);
356 void SetMeshInfoAndCanonize(MeshInfo& meshInfo, Dali::Vector<Dali::Vector3>& vertexBufferData)
358 Vector3 pointMin(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
359 Vector3 pointMax(std::numeric_limits<float>::min(), std::numeric_limits<float>::min(), std::numeric_limits<float>::min());
360 for(auto&& data : vertexBufferData)
362 pointMin.x = std::min(data.x, pointMin.x);
363 pointMin.y = std::min(data.y, pointMin.y);
364 pointMin.z = std::min(data.z, pointMin.z);
366 pointMax.x = std::max(data.x, pointMax.x);
367 pointMax.y = std::max(data.y, pointMax.y);
368 pointMax.z = std::max(data.z, pointMax.z);
370 meshInfo.size = pointMax - pointMin;
371 meshInfo.pivot.x = (-pointMin.x) / (pointMax.x - pointMin.x);
372 meshInfo.pivot.y = (-pointMin.y) / (pointMax.y - pointMin.y);
373 meshInfo.pivot.z = (-pointMin.z) / (pointMax.z - pointMin.z);
375 Vector3 center = meshInfo.size * 0.5 + pointMin;
376 for(auto&& data : vertexBufferData)
378 data = data - center;
379 data.x = data.x / meshInfo.size.x;
380 data.y = data.y / meshInfo.size.y;
381 data.z = data.z / meshInfo.size.z;
386 VertexBuffer CreateVertexBuffer(Vector<T> bufferData, std::string map, int32_t type)
388 Property::Map positionMap;
389 positionMap[map] = type;
391 VertexBuffer vertexBuffer = VertexBuffer::New(positionMap);
392 vertexBuffer.SetData(bufferData.Begin(), bufferData.Count());
396 void SetVertexBufferData(MeshInfo& meshInfo, std::string path, std::vector<AccessorInfo>& accessorArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<BufferInfo>& bufferArray, int32_t accessorIdx, std::string map, int32_t type)
400 Dali::Vector<Vector3> bufferData;
401 LoadDataFromAccessor(accessorIdx, bufferData, std::move(path), accessorArray, bufferViewArray, bufferArray);
402 SetMeshInfoAndCanonize(meshInfo, bufferData);
404 VertexBuffer vertexBuffer = CreateVertexBuffer<Vector3>(bufferData, std::move(map), type);
405 meshInfo.geometry.AddVertexBuffer(vertexBuffer);
410 void SetAttributeBufferData(MeshInfo& meshInfo, std::string path, std::vector<AccessorInfo>& accessorArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<BufferInfo>& bufferArray, int32_t accessorIdx, std::string map, int32_t type)
414 Dali::Vector<T> bufferData;
415 LoadDataFromAccessor(accessorIdx, bufferData, std::move(path), accessorArray, bufferViewArray, bufferArray);
417 VertexBuffer vertexBuffer = CreateVertexBuffer<T>(bufferData, std::move(map), type);
418 meshInfo.geometry.AddVertexBuffer(vertexBuffer);
422 void SetIndexBuffersData(MeshInfo& meshInfo, std::string path, std::vector<AccessorInfo>& accessorArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<BufferInfo>& bufferArray, int32_t indexIdx)
424 Dali::Vector<uint16_t> indexBufferData;
425 LoadDataFromAccessor(indexIdx, indexBufferData, std::move(path), accessorArray, bufferViewArray, bufferArray);
426 meshInfo.geometry.SetIndexBuffer(&indexBufferData[0], indexBufferData.Size());
430 float LoadKeyFrames(const AnimationSamplerInfo& currentSampler, const Property::Index propIndex, KeyFrames& keyframes, std::string path, std::vector<AccessorInfo>& accessorArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<BufferInfo>& bufferArray)
432 Dali::Vector<float> inputBufferData;
433 Dali::Vector<T> outputBufferData;
435 LoadDataFromAccessor<float>(currentSampler.input, inputBufferData, path, accessorArray, bufferViewArray, bufferArray);
436 LoadDataFromAccessor<T>(currentSampler.output, outputBufferData, path, accessorArray, bufferViewArray, bufferArray);
438 uint32_t keyframeNum = inputBufferData.Size();
439 float lengthAnimation = std::max((inputBufferData.Size() > 0u ? inputBufferData[inputBufferData.Size() - 1] : MIN_DURATION_SECONDS), MIN_DURATION_SECONDS);
440 for(uint32_t i = 0; i < keyframeNum; i++)
442 if(propIndex == Dali::Actor::Property::ORIENTATION)
444 Vector4 vectorOrientation(outputBufferData[i]);
445 float vW = vectorOrientation.w;
446 vW = (vW < 0.0f) ? std::max(vW, -1.0f) : std::min(vW, 1.0f);
447 vectorOrientation.w = vW;
448 keyframes.Add(inputBufferData[i] / lengthAnimation, Quaternion(Vector4(vectorOrientation)));
450 else if(propIndex == Dali::Actor::Property::POSITION)
452 keyframes.Add(inputBufferData[i] / lengthAnimation, Vector3(outputBufferData[i]));
454 else if(propIndex == Dali::Actor::Property::SCALE)
456 keyframes.Add(inputBufferData[i] / lengthAnimation, Vector3(outputBufferData[i]));
459 return lengthAnimation;
462 bool LoadBuffer(const TreeNode& buffer, std::vector<BufferInfo>& bufferArray)
464 BufferInfo bufferInfo;
466 const TreeNode* uriNode = buffer.GetChild("uri");
469 ReadString(uriNode, bufferInfo.uri);
472 const TreeNode* byteLengthNode = buffer.GetChild("byteLength");
475 ReadInt(byteLengthNode, bufferInfo.byteLength);
476 if(bufferInfo.byteLength < 0)
482 const TreeNode* nameNode = buffer.GetChild("name");
485 ReadString(nameNode, bufferInfo.name);
488 bufferArray.push_back(bufferInfo);
493 bool LoadBufferView(const TreeNode& buffer, std::vector<BufferViewInfo>& bufferViewArray)
495 BufferViewInfo bufferViewInfo;
497 const TreeNode* bufferNode = buffer.GetChild("buffer");
500 ReadInt(bufferNode, bufferViewInfo.buffer);
501 if(bufferViewInfo.buffer < 0)
507 const TreeNode* byteOffsetNode = buffer.GetChild("byteOffset");
510 ReadInt(byteOffsetNode, bufferViewInfo.byteOffset);
513 const TreeNode* byteLengthNode = buffer.GetChild("byteLength");
516 ReadInt(byteLengthNode, bufferViewInfo.byteLength);
517 if(bufferViewInfo.byteLength < 0)
523 const TreeNode* byteStrideNode = buffer.GetChild("byteStride");
526 ReadInt(byteStrideNode, bufferViewInfo.byteStride);
529 const TreeNode* targetNode = buffer.GetChild("target");
532 ReadInt(targetNode, bufferViewInfo.target);
535 const TreeNode* nameNode = buffer.GetChild("name");
538 ReadString(nameNode, bufferViewInfo.name);
541 bufferViewArray.push_back(bufferViewInfo);
546 bool LoadAccessor(const TreeNode& buffer, std::vector<AccessorInfo>& accessorArray)
548 AccessorInfo accessorInfo;
550 const TreeNode* bufferViewNode = buffer.GetChild("bufferView");
553 ReadInt(bufferViewNode, accessorInfo.bufferView);
556 const TreeNode* byteOffsetNode = buffer.GetChild("byteOffset");
559 ReadInt(byteOffsetNode, accessorInfo.byteOffset);
562 const TreeNode* componentTypeNode = buffer.GetChild("componentType");
563 if(componentTypeNode)
565 ReadInt(componentTypeNode, accessorInfo.componentType);
566 if(accessorInfo.componentType < 0)
572 const TreeNode* normalizedNode = buffer.GetChild("normalized");
575 ReadBool(normalizedNode, accessorInfo.normalized);
578 const TreeNode* countNode = buffer.GetChild("count");
581 ReadInt(countNode, accessorInfo.count);
582 if(accessorInfo.count < 0)
588 const TreeNode* typeNode = buffer.GetChild("type");
591 ReadString(typeNode, accessorInfo.type);
592 if(accessorInfo.type == "")
598 const TreeNode* maxNode = buffer.GetChild("max");
601 ReadInt(maxNode, accessorInfo.max);
604 const TreeNode* minNode = buffer.GetChild("min");
607 ReadInt(minNode, accessorInfo.min);
610 const TreeNode* nameNode = buffer.GetChild("name");
613 ReadString(nameNode, accessorInfo.name);
616 accessorArray.push_back(accessorInfo);
621 bool LoadBinaryData(const TreeNode& root, std::vector<BufferInfo>& bufferArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<AccessorInfo>& accessorArray)
623 const TreeNode* buffersNode = root.GetChild("buffers");
628 for(auto bufferIter = buffersNode->CBegin(), end = buffersNode->CEnd(); bufferIter != end; ++bufferIter)
630 LoadBuffer((*bufferIter).second, bufferArray);
633 const TreeNode* bufferViewsNode = root.GetChild("bufferViews");
638 for(auto bufferViewIter = bufferViewsNode->CBegin(), end = bufferViewsNode->CEnd(); bufferViewIter != end; ++bufferViewIter)
640 LoadBufferView((*bufferViewIter).second, bufferViewArray);
643 const TreeNode* accessorsNode = root.GetChild("accessors");
648 for(auto accesorIter = accessorsNode->CBegin(), end = accessorsNode->CEnd(); accesorIter != end; ++accesorIter)
650 LoadAccessor((*accesorIter).second, accessorArray);
656 FilterMode::Type GetFilterMode(uint32_t mode)
658 FilterMode::Type retValue = FilterMode::DEFAULT;
660 * glTF 2.0 Specification
664 * 9984 : NEAREST_MIPMAP_NEAREST
665 * 9985 : LINEAR_MIPMAP_NEAREST
666 * 9986 : NEAREST_MIPMAP_LINEAR
667 * 9987 : LINEAR_MIPMAP_LINEAR
673 retValue = FilterMode::NEAREST;
678 retValue = FilterMode::LINEAR;
683 retValue = FilterMode::NEAREST_MIPMAP_NEAREST;
688 retValue = FilterMode::LINEAR_MIPMAP_NEAREST;
693 retValue = FilterMode::NEAREST_MIPMAP_LINEAR;
698 retValue = FilterMode::LINEAR_MIPMAP_LINEAR;
706 WrapMode::Type GetWrapMode(uint32_t mode)
708 WrapMode::Type retValue = WrapMode::REPEAT;
710 * glTF 2.0 Specification
712 * 33071 : CLAMP_TO_EDGE
713 * 33648 : MIRRORED_REPEAT
720 retValue = WrapMode::CLAMP_TO_EDGE;
725 retValue = WrapMode::MIRRORED_REPEAT;
730 retValue = WrapMode::REPEAT;
738 Texture LoadTexture(const char* imageUrl, bool generateMipmaps)
741 Devel::PixelBuffer pixelBuffer = LoadImageFromFile(imageUrl);
744 texture = Texture::New(TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), pixelBuffer.GetWidth(), pixelBuffer.GetHeight());
745 PixelData pixelData = Devel::PixelBuffer::Convert(pixelBuffer);
746 texture.Upload(pixelData);
750 texture.GenerateMipmaps();
757 Sampler LoadSampler(const TreeNode& samplerNode)
759 Sampler sampler = Sampler::New();
761 FilterMode::Type minFilter = FilterMode::DEFAULT;
762 FilterMode::Type magFilter = FilterMode::DEFAULT;
763 const TreeNode* magFilterNode = samplerNode.GetChild("magFilter");
766 int32_t magFilter_integer = 0;
767 ReadInt(magFilterNode, magFilter_integer);
768 magFilter = GetFilterMode(magFilter_integer);
771 const TreeNode* minFilterNode = samplerNode.GetChild("minFilter");
774 int32_t minFilter_integer = 0;
775 ReadInt(minFilterNode, minFilter_integer);
776 minFilter = GetFilterMode(minFilter_integer);
779 WrapMode::Type wrapR = WrapMode::REPEAT;
780 WrapMode::Type wrapS = WrapMode::REPEAT;
781 WrapMode::Type wrapT = WrapMode::REPEAT;
782 const TreeNode* wrapNode = samplerNode.GetChild("wrapS");
785 wrapS = GetWrapMode(wrapNode->GetInteger());
788 wrapNode = samplerNode.GetChild("wrapT");
791 wrapT = GetWrapMode(wrapNode->GetInteger());
794 sampler.SetFilterMode(minFilter, magFilter);
795 sampler.SetWrapMode(wrapR, wrapS, wrapT);
800 bool LoadTextureArray(const TreeNode& root, std::string path, std::vector<Texture>& sourceArray, std::vector<Sampler>& samplerArray, std::vector<TextureInfo>& textureArray)
802 const TreeNode* imagesNode = root.GetChild("images");
805 for(auto imageIter = imagesNode->CBegin(), end = imagesNode->CEnd(); imageIter != end; ++imageIter)
807 std::string imageUrl;
808 const TreeNode* uriNode = (&((*imageIter).second))->GetChild("uri");
812 ReadString(uriNode, uri);
813 imageUrl = path + uri;
816 sourceArray.push_back(LoadTexture(imageUrl.c_str(), true));
820 const TreeNode* samplersNode = root.GetChild("samplers");
823 for(auto samplerIter = samplersNode->CBegin(), end = samplersNode->CEnd(); samplerIter != end; ++samplerIter)
825 samplerArray.push_back(LoadSampler(((*samplerIter).second)));
829 const TreeNode* texturesNode = root.GetChild("textures");
832 for(auto textureIter = texturesNode->CBegin(), end = texturesNode->CEnd(); textureIter != end; ++textureIter)
834 const TreeNode* TextureNode = &((*textureIter).second);
837 const TreeNode* sourceNode = TextureNode->GetChild("source");
840 ReadInt(sourceNode, texture.sourceIdx);
843 const TreeNode* samplerNode = TextureNode->GetChild("sampler");
846 ReadInt(samplerNode, texture.samplerIdx);
849 textureArray.push_back(texture);
855 bool LoadPbrMetallicRoughness(const TreeNode& material, MaterialInfo& materialInfo)
858 const TreeNode* pbrMetallicRoughnessNode = material.GetChild("pbrMetallicRoughness");
859 if(!pbrMetallicRoughnessNode)
864 const TreeNode* tempNode;
865 tempNode = pbrMetallicRoughnessNode->GetChild("metallicFactor");
868 ReadFloat(tempNode, materialInfo.metallicFactor);
871 tempNode = pbrMetallicRoughnessNode->GetChild("roughnessFactor");
874 ReadFloat(tempNode, materialInfo.roughnessFactor);
877 tempNode = pbrMetallicRoughnessNode->GetChild("baseColorFactor");
878 if(tempNode && ReadVector(tempNode, floatVec, 4))
880 materialInfo.baseColorFactor = Vector4(floatVec[0], floatVec[1], floatVec[2], floatVec[3]);
883 const TreeNode* baseColorTextureNode = pbrMetallicRoughnessNode->GetChild("baseColorTexture");
884 if(baseColorTextureNode)
886 tempNode = baseColorTextureNode->GetChild("index");
889 materialInfo.baseColorTexture.index = tempNode->GetInteger();
892 tempNode = baseColorTextureNode->GetChild("texCoord");
895 materialInfo.baseColorTexture.texCoord = tempNode->GetInteger();
899 const TreeNode* metallicRoughnessTextureNode = pbrMetallicRoughnessNode->GetChild("metallicRoughnessTexture");
900 if(metallicRoughnessTextureNode)
902 tempNode = metallicRoughnessTextureNode->GetChild("index");
905 materialInfo.metallicRoughnessTexture.index = tempNode->GetInteger();
908 tempNode = metallicRoughnessTextureNode->GetChild("texCoord");
911 materialInfo.metallicRoughnessTexture.texCoord = tempNode->GetInteger();
918 bool LoadMaterialSetArray(const TreeNode& root, std::vector<MaterialInfo>& materialArray)
920 const TreeNode* materialsNode = root.GetChild("materials");
926 for(auto materialIter = materialsNode->CBegin(), end = materialsNode->CEnd(); materialIter != end; ++materialIter)
928 MaterialInfo materialInfo;
929 LoadPbrMetallicRoughness(((*materialIter).second), materialInfo);
931 const TreeNode* materialNode = &((*materialIter).second);
932 const TreeNode* tempNode = materialNode->GetChild("name");
935 ReadString(tempNode, materialInfo.name);
938 materialInfo.alphaMode = "OPAQUE";
939 tempNode = materialNode->GetChild("alphaMode");
942 ReadString(tempNode, materialInfo.alphaMode);
945 materialInfo.alphaCutoff = 1.0;
946 tempNode = materialNode->GetChild("alphaCutoff");
949 ReadFloat(tempNode, materialInfo.alphaCutoff);
952 materialInfo.doubleSided = false;
953 tempNode = materialNode->GetChild("doubleSided");
956 ReadBool(tempNode, materialInfo.doubleSided);
960 tempNode = materialNode->GetChild("emissiveFactor");
961 if(tempNode && ReadVector(tempNode, floatVec, 3))
963 materialInfo.emissiveFactor = Vector3(floatVec[0], floatVec[1], floatVec[2]);
966 const TreeNode* texture = materialNode->GetChild("normalTexture");
969 tempNode = texture->GetChild("index");
972 materialInfo.normalTexture.index = tempNode->GetInteger();
975 tempNode = texture->GetChild("texCoord");
978 materialInfo.normalTexture.texCoord = tempNode->GetInteger();
981 materialInfo.normalTexture.value = 1.0;
982 tempNode = texture->GetChild("scale");
985 ReadFloat(tempNode, materialInfo.normalTexture.value);
989 texture = materialNode->GetChild("occlusionTexture");
992 tempNode = texture->GetChild("index");
995 materialInfo.occlusionTexture.index = tempNode->GetInteger();
998 tempNode = texture->GetChild("texCoord");
1001 materialInfo.occlusionTexture.texCoord = tempNode->GetInteger();
1004 tempNode = texture->GetChild("strength");
1007 ReadFloat(tempNode, materialInfo.occlusionTexture.value);
1011 texture = materialNode->GetChild("emissiveTexture");
1014 tempNode = texture->GetChild("index");
1017 materialInfo.emissiveTexture.index = tempNode->GetInteger();
1020 tempNode = texture->GetChild("texCoord");
1023 materialInfo.emissiveTexture.texCoord = tempNode->GetInteger();
1026 materialArray.push_back(materialInfo);
1031 bool LoadAttribute(const TreeNode* primitive, MeshInfo& meshInfo)
1033 const TreeNode* attrbuteNode = primitive->GetChild("attributes");
1039 const TreeNode* tempNode;
1040 tempNode = attrbuteNode->GetChild("POSITION");
1043 meshInfo.attribute.POSITION = tempNode->GetInteger();
1046 tempNode = attrbuteNode->GetChild("NORMAL");
1049 meshInfo.attribute.NORMAL = tempNode->GetInteger();
1052 tempNode = attrbuteNode->GetChild("TANGENT");
1055 meshInfo.attribute.TANGENT = tempNode->GetInteger();
1059 meshInfo.attribute.TEXCOORD.clear();
1060 tempNode = attrbuteNode->GetChild("TEXCOORD_" + std::to_string(index));
1063 uint32_t value = tempNode->GetInteger();
1064 meshInfo.attribute.TEXCOORD.push_back(value);
1065 tempNode = attrbuteNode->GetChild("TEXCOORD_" + std::to_string(++index));
1069 meshInfo.attribute.COLOR.clear();
1070 tempNode = attrbuteNode->GetChild("COLOR_" + std::to_string(index));
1073 uint32_t value = tempNode->GetInteger();
1074 meshInfo.attribute.COLOR.push_back(value);
1075 tempNode = attrbuteNode->GetChild("COLOR" + std::to_string(++index));
1081 bool LoadPrimitive(const TreeNode& mesh, MeshInfo& meshInfo)
1083 const TreeNode* primitivesNode = mesh.GetChild("primitives");
1089 for(auto primitiveIter = primitivesNode->CBegin(), end = primitivesNode->CEnd(); primitiveIter != end; ++primitiveIter)
1091 const TreeNode* primitiveNode = (&(*primitiveIter).second);
1092 const TreeNode* tempNode;
1094 tempNode = primitiveNode->GetChild("indices");
1097 meshInfo.indicesIdx = tempNode->GetInteger();
1100 tempNode = primitiveNode->GetChild("material");
1103 meshInfo.materialsIdx = tempNode->GetInteger();
1106 tempNode = primitiveNode->GetChild("mode");
1109 meshInfo.mode = tempNode->GetInteger();
1112 LoadAttribute(primitiveNode, meshInfo);
1118 bool SetGeometry(MeshInfo& meshInfo, std::string path, std::vector<BufferInfo>& bufferArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<AccessorInfo>& accessorArray)
1120 int32_t indicesIdx = meshInfo.indicesIdx;
1122 if(meshInfo.mode != 0)
1124 meshInfo.geometry.SetType((Dali::Geometry::Type)meshInfo.mode);
1129 SetIndexBuffersData(meshInfo, path, accessorArray, bufferViewArray, bufferArray, indicesIdx);
1132 SetVertexBufferData(meshInfo, path, accessorArray, bufferViewArray, bufferArray, meshInfo.attribute.POSITION, "aPosition", Property::VECTOR3);
1133 SetAttributeBufferData<Vector3>(meshInfo, path, accessorArray, bufferViewArray, bufferArray, meshInfo.attribute.NORMAL, "aNormal", Property::VECTOR3);
1134 SetAttributeBufferData<Vector4>(meshInfo, path, accessorArray, bufferViewArray, bufferArray, meshInfo.attribute.TANGENT, "aTangent", Property::VECTOR4);
1136 for(uint32_t i = 0; i < meshInfo.attribute.TEXCOORD.size(); ++i)
1138 int32_t accessorIdx = meshInfo.attribute.TEXCOORD[i];
1139 std::ostringstream texCoordString;
1140 texCoordString << "aTexCoord" << i;
1141 SetAttributeBufferData<Vector2>(meshInfo, path, accessorArray, bufferViewArray, bufferArray, accessorIdx, texCoordString.str(), Property::VECTOR2);
1144 for(auto&& accessorIdx : meshInfo.attribute.COLOR)
1151 if(accessorArray[accessorIdx].type == "VEC3")
1153 Dali::Vector<Vector3> inputBufferData;
1154 LoadDataFromAccessor(accessorIdx, inputBufferData, path, accessorArray, bufferViewArray, bufferArray);
1156 Dali::Vector<Vector4> bufferData;
1157 bufferData.Resize(inputBufferData.Size());
1158 for(uint32_t i = 0; i < inputBufferData.Size(); ++i)
1160 bufferData[i].x = inputBufferData[i].x;
1161 bufferData[i].y = inputBufferData[i].y;
1162 bufferData[i].z = inputBufferData[i].z;
1163 bufferData[i].w = 1.0;
1165 VertexBuffer vertexBuffer = CreateVertexBuffer<Vector4>(bufferData, "aVertexColor", Property::VECTOR4);
1166 meshInfo.geometry.AddVertexBuffer(vertexBuffer);
1168 else if(accessorArray[accessorIdx].type == "VEC4")
1170 SetAttributeBufferData<Vector4>(meshInfo, path, accessorArray, bufferViewArray, bufferArray, accessorIdx, "aVertexColor", Property::VECTOR4);
1176 bool LoadMeshArray(const TreeNode& root, std::string path, std::vector<MeshInfo>& meshArray, std::vector<BufferInfo>& bufferArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<AccessorInfo>& accessorArray)
1178 const TreeNode* meshesNode = root.GetChild("meshes");
1184 for(auto meshIter = meshesNode->CBegin(), end = meshesNode->CEnd(); meshIter != end; ++meshIter)
1187 const TreeNode* nameNode = (&(*meshIter).second)->GetChild("name");
1190 ReadString(nameNode, meshInfo.name);
1192 meshInfo.geometry = Geometry::New();
1194 //Need to add weights for Morph targets.
1195 LoadPrimitive((*meshIter).second, meshInfo);
1196 SetGeometry(meshInfo, path, bufferArray, bufferViewArray, accessorArray);
1197 meshArray.push_back(meshInfo);
1215 bool Loader::LoadScene(const std::string& filePath, Internal::Scene3dView& scene3dView)
1217 // Extracting directory path from full path to load resources.
1218 if(std::string::npos != filePath.rfind('/'))
1220 mPath = filePath.substr(0, filePath.rfind('/')) + "/";
1223 if(!ParseGltf(filePath))
1225 DALI_LOG_ERROR("Fail to parse json file\n");
1229 mRoot = mParser.GetRoot();
1232 CreateScene(scene3dView))
1239 bool Loader::ParseGltf(const std::string& filePath)
1241 std::streampos bufferSize = 0;
1242 Dali::Vector<char> buffer;
1243 std::string fileBuffer;
1244 if(!Dali::FileLoader::ReadFile(filePath, bufferSize, buffer, FileLoader::FileType::BINARY))
1249 fileBuffer.assign(&buffer[0], bufferSize);
1250 mParser = Dali::Toolkit::JsonParser::New();
1251 return mParser.Parse(fileBuffer);
1254 bool Loader::LoadAssets()
1256 if(LoadBinaryData(*mRoot, mBufferArray, mBufferViewArray, mAccessorArray) &&
1257 LoadTextureArray(*mRoot, mPath, mSourceArray, mSamplerArray, mTextureArray) &&
1258 LoadMaterialSetArray(*mRoot, mMaterialArray) &&
1259 LoadMeshArray(*mRoot, mPath, mMeshArray, mBufferArray, mBufferViewArray, mAccessorArray))
1266 bool Loader::CreateScene(Internal::Scene3dView& scene3dView)
1268 scene3dView.SetDefaultCamera(Dali::Camera::LOOK_AT_TARGET, 0.01, Vector3::ZERO);
1269 LoadCamera(scene3dView);
1271 if(LoadSceneNodes(scene3dView) &&
1272 LoadAnimation(scene3dView))
1279 void Loader::LoadCamera(Scene3dView& scene3dView)
1281 const TreeNode* camerasNode = mRoot->GetChild("cameras");
1287 for(auto cameraIter = camerasNode->CBegin(), end = camerasNode->CEnd(); cameraIter != end; ++cameraIter)
1289 const TreeNode* tempNode = (&(*cameraIter).second)->GetChild("name");
1290 CameraInfo cameraInfo;
1293 ReadString(tempNode, cameraInfo.name);
1296 tempNode = (&(*cameraIter).second)->GetChild("type");
1299 ReadString(tempNode, cameraInfo.type);
1302 CameraActor cameraActor = CameraActor::New();
1303 cameraActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
1304 cameraActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
1306 if(cameraInfo.type == "orthographic")
1308 LoadOrthoGraphic((*cameraIter).second, cameraInfo);
1309 float xMag_2 = cameraInfo.orthographic.xmag / 2.0;
1310 float yMag_2 = cameraInfo.orthographic.ymag / 2.0;
1311 const float aspect = xMag_2 / yMag_2;
1313 cameraActor.SetProjectionMode(Dali::Camera::ORTHOGRAPHIC_PROJECTION);
1314 cameraActor.SetProperty(Dali::DevelCameraActor::Property::ORTHOGRAPHIC_SIZE, yMag_2);
1316 cameraActor.SetNearClippingPlane(cameraInfo.orthographic.znear);
1317 if(cameraInfo.orthographic.zfar > 0.0)
1319 cameraActor.SetFarClippingPlane(cameraInfo.orthographic.zfar);
1321 if(aspect > 0.0f) // Avoid divide-by-zero logic
1323 cameraActor.SetAspectRatio(aspect);
1326 else if(cameraInfo.type == "perspective")
1328 if(!LoadPerspective((*cameraIter).second, cameraInfo))
1332 cameraActor.SetProjectionMode(Dali::Camera::PERSPECTIVE_PROJECTION);
1333 cameraActor.SetFieldOfView(cameraInfo.perspective.yfov);
1334 cameraActor.SetNearClippingPlane(cameraInfo.perspective.znear);
1336 if(cameraInfo.perspective.zfar > 0.0)
1338 cameraActor.SetFarClippingPlane(cameraInfo.perspective.zfar);
1340 if(cameraInfo.perspective.aspectRatio > 0.0)
1342 cameraActor.SetAspectRatio(cameraInfo.perspective.aspectRatio);
1346 scene3dView.AddCamera(cameraActor);
1350 bool Loader::LoadOrthoGraphic(const TreeNode& camera, CameraInfo& cameraInfo)
1352 const TreeNode* orthographicNode = camera.GetChild("orthographic");
1353 if(!orthographicNode)
1358 const TreeNode* tempNode;
1359 tempNode = orthographicNode->GetChild("xmag");
1362 ReadFloat(tempNode, cameraInfo.orthographic.xmag);
1365 tempNode = orthographicNode->GetChild("ymag");
1368 ReadFloat(tempNode, cameraInfo.orthographic.ymag);
1371 tempNode = orthographicNode->GetChild("zfar");
1374 ReadFloat(tempNode, cameraInfo.orthographic.zfar);
1377 tempNode = orthographicNode->GetChild("znear");
1380 ReadFloat(tempNode, cameraInfo.orthographic.znear);
1386 bool Loader::LoadPerspective(const TreeNode& camera, CameraInfo& cameraInfo)
1388 const TreeNode* perspectiveNode = camera.GetChild("perspective");
1389 if(!perspectiveNode)
1394 const TreeNode* tempNode;
1395 tempNode = perspectiveNode->GetChild("aspectRatio");
1398 ReadFloat(tempNode, cameraInfo.perspective.aspectRatio);
1401 tempNode = perspectiveNode->GetChild("yfov");
1404 ReadFloat(tempNode, cameraInfo.perspective.yfov);
1407 tempNode = perspectiveNode->GetChild("zfar");
1410 ReadFloat(tempNode, cameraInfo.perspective.zfar);
1413 tempNode = perspectiveNode->GetChild("znear");
1416 ReadFloat(tempNode, cameraInfo.perspective.znear);
1422 bool Loader::LoadSceneNodes(Scene3dView& scene3dView)
1424 const TreeNode* sceneNode = mRoot->GetChild("scene");
1425 uint32_t sceneNum = 0;
1428 sceneNum = sceneNode->GetInteger();
1431 const TreeNode* scenesNode = mRoot->GetChild("scenes");
1432 if(!(scenesNode && (mNodes = mRoot->GetChild("nodes"))))
1437 const TreeNode* tempNode = Tidx(scenesNode, sceneNum);
1443 tempNode = tempNode->GetChild("nodes");
1449 for(auto nodeIter = tempNode->CBegin(), end = tempNode->CEnd(); nodeIter != end; ++nodeIter)
1451 Actor actor = AddNode(scene3dView, ((*nodeIter).second).GetInteger());
1452 actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
1453 scene3dView.GetRoot().Add(actor);
1459 Actor Loader::AddNode(Scene3dView& scene3dView, uint32_t index)
1461 const TreeNode* node = Tidx(mNodes, index);
1462 Actor actor = Actor::New();
1463 Vector3 actorSize(Vector3::ONE);
1465 Vector3 translation = Vector3(0.0, 0.0, 0.0);
1466 Vector3 scale = Vector3(1.0, 1.0, 1.0);
1467 Quaternion orientation(Vector4(0.0, 0.0, 0.0, 1.0));
1469 Vector3 anchorPoint = AnchorPoint::CENTER;
1471 const TreeNode* tempNode = NULL;
1472 if((tempNode = node->GetChild("translation")))
1474 float floatVec[3] = {0.0, 0.0, 0.0};
1475 if(tempNode && ReadVector(tempNode, floatVec, 3))
1477 translation = Vector3(floatVec[0], floatVec[1], floatVec[2]);
1481 if((tempNode = node->GetChild("scale")))
1483 float floatVec[3] = {1.0, 1.0, 1.0};
1484 if(tempNode && ReadVector(tempNode, floatVec, 3))
1486 scale = Vector3(floatVec[0], floatVec[1], floatVec[2]);
1490 if((tempNode = node->GetChild("rotation")))
1492 float floatVec[4] = {0.0, 0.0, 0.0, 1.0};
1493 if(tempNode && ReadVector(tempNode, floatVec, 4))
1495 orientation = Quaternion(Vector4(floatVec[0], floatVec[1], floatVec[2], floatVec[3]));
1499 if((tempNode = node->GetChild("matrix")))
1501 float floatVec[16] = {1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0};
1502 if(tempNode && ReadVector(tempNode, floatVec, 16))
1504 Matrix nodeMatrix = Matrix(floatVec);
1505 nodeMatrix.GetTransformComponents(translation, orientation, scale);
1509 if((tempNode = node->GetChild("mesh")))
1511 MeshInfo meshInfo = mMeshArray[tempNode->GetInteger()];
1512 bool isMaterial = (meshInfo.materialsIdx >= 0);
1514 TextureSet textureSet;
1515 textureSet = TextureSet::New();
1518 int32_t shaderTypeIndex = 0;
1519 int32_t maxMipmapLevel = 0;
1520 bool isBaseColorTexture = false;
1521 bool isMetallicRoughnessTexture = false;
1522 bool isNormalTexture = false;
1523 bool isOcclusionTexture = false;
1524 bool isEmissiveTexture = false;
1526 std::string VERTEX_SHADER, FRAGMENT_SHADER;
1527 VERTEX_SHADER = SHADER_GLTF_GLES_VERSION_300_DEF.data();
1528 VERTEX_SHADER += SHADER_GLTF_PHYSICALLY_BASED_SHADER_VERT.data();
1529 FRAGMENT_SHADER = SHADER_GLTF_GLES_VERSION_300_DEF.data();
1531 bool useIBL = scene3dView.HasImageBasedLighting();
1534 MaterialInfo materialInfo = mMaterialArray[meshInfo.materialsIdx];
1535 if(SetTextureAndSampler(textureSet, materialInfo.baseColorTexture.index, FRAGMENT_SHADER, SHADER_GLTF_BASECOLOR_TEXTURE_DEF.data(), addIdx))
1537 shaderTypeIndex += static_cast<int32_t>(ShaderType::BASECOLOR_SHADER);
1538 isBaseColorTexture = true;
1540 if(SetTextureAndSampler(textureSet, materialInfo.metallicRoughnessTexture.index, FRAGMENT_SHADER, SHADER_GLTF_METALLICROUGHNESS_TEXTURE_DEF.data(), addIdx))
1542 shaderTypeIndex += static_cast<int32_t>(ShaderType::METALLICROUGHNESS_SHADER);
1543 isMetallicRoughnessTexture = true;
1545 if(SetTextureAndSampler(textureSet, materialInfo.normalTexture.index, FRAGMENT_SHADER, SHADER_GLTF_NORMAL_TEXTURE_DEF.data(), addIdx))
1547 shaderTypeIndex += static_cast<int32_t>(ShaderType::NORMAL_SHADER);
1548 isNormalTexture = true;
1550 if(SetTextureAndSampler(textureSet, materialInfo.occlusionTexture.index, FRAGMENT_SHADER, SHADER_GLTF_OCCULUSION_TEXTURE_DEF.data(), addIdx))
1552 shaderTypeIndex += static_cast<int32_t>(ShaderType::OCCLUSION_SHADER);
1553 isOcclusionTexture = true;
1555 if(SetTextureAndSampler(textureSet, materialInfo.emissiveTexture.index, FRAGMENT_SHADER, SHADER_GLTF_EMIT_TEXTURE_DEF.data(), addIdx))
1557 shaderTypeIndex += static_cast<int32_t>(ShaderType::EMIT_SHADER);
1558 isEmissiveTexture = true;
1563 shaderTypeIndex += static_cast<int32_t>(ShaderType::IBL_SHADER);
1564 FRAGMENT_SHADER += SHADER_GLTF_IBL_TEXTURE_DEF.data();
1566 Sampler sampler = Sampler::New();
1567 sampler.SetFilterMode(FilterMode::DEFAULT, FilterMode::DEFAULT);
1568 sampler.SetWrapMode(WrapMode::REPEAT, WrapMode::REPEAT, WrapMode::REPEAT);
1570 textureSet.SetTexture(addIdx, scene3dView.GetBRDFTexture());
1571 textureSet.SetSampler(addIdx++, sampler);
1572 Sampler samplerIBL = Sampler::New();
1573 samplerIBL.SetFilterMode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR);
1574 samplerIBL.SetWrapMode(WrapMode::CLAMP_TO_EDGE, WrapMode::CLAMP_TO_EDGE, WrapMode::CLAMP_TO_EDGE);
1575 textureSet.SetTexture(addIdx, scene3dView.GetDiffuseTexture());
1576 textureSet.SetSampler(addIdx++, samplerIBL);
1577 Texture specularTexture = scene3dView.GetSpecularTexture();
1578 textureSet.SetTexture(addIdx, specularTexture);
1579 textureSet.SetSampler(addIdx++, samplerIBL);
1581 int32_t textureSize = std::min(specularTexture.GetWidth(), specularTexture.GetHeight());
1583 while(textureSize >= 1)
1591 FRAGMENT_SHADER += SHADER_GLTF_PHYSICALLY_BASED_SHADER_FRAG.data();
1592 if(!mShaderCache[shaderTypeIndex])
1594 std::ostringstream oss;
1595 oss << "GLTF_VIEW_" << shaderTypeIndex;
1596 mShaderCache[shaderTypeIndex] = Shader::New(VERTEX_SHADER, FRAGMENT_SHADER, Shader::Hint::NONE, oss.str());
1597 scene3dView.AddShader(mShaderCache[shaderTypeIndex]);
1599 Shader shader = mShaderCache[shaderTypeIndex];
1601 Renderer renderer = Renderer::New(meshInfo.geometry, shader);
1602 renderer.SetProperty(Renderer::Property::DEPTH_WRITE_MODE, DepthWriteMode::ON);
1603 renderer.SetProperty(Renderer::Property::DEPTH_TEST_MODE, DepthTestMode::ON);
1604 renderer.SetTextures(textureSet);
1606 anchorPoint = meshInfo.pivot;
1607 actor.SetProperty(Actor::Property::ANCHOR_POINT, anchorPoint);
1609 actor.SetProperty(Actor::Property::SIZE, Vector3(meshInfo.size.x, meshInfo.size.y, meshInfo.size.z));
1610 actor.AddRenderer(renderer);
1612 actor.SetProperty(Actor::Property::SCALE, scale);
1613 actor.RotateBy(orientation);
1614 actor.SetProperty(Actor::Property::POSITION, translation);
1616 float hasLightSource = static_cast<float>(!!(scene3dView.GetLightType() & (Toolkit::Scene3dView::LightType::POINT_LIGHT | Toolkit::Scene3dView::LightType::DIRECTIONAL_LIGHT)));
1617 float isPointLight = static_cast<float>(!!(scene3dView.GetLightType() & Toolkit::Scene3dView::LightType::POINT_LIGHT));
1618 shader.RegisterProperty("uHasLightSource", hasLightSource);
1619 shader.RegisterProperty("uIsPointLight", isPointLight);
1620 shader.RegisterProperty("uLightVector", scene3dView.GetLightVector());
1621 shader.RegisterProperty("uLightColor", scene3dView.GetLightColor());
1623 actor.RegisterProperty("uHasVertexColor", meshInfo.attribute.COLOR.size() > 0 ? 1.0f : 0.0f);
1626 MaterialInfo materialInfo = mMaterialArray[meshInfo.materialsIdx];
1627 actor.RegisterProperty("uBaseColorFactor", materialInfo.baseColorFactor);
1628 actor.RegisterProperty("uMetallicRoughnessFactors", Vector2(materialInfo.metallicFactor, materialInfo.roughnessFactor));
1630 if(materialInfo.alphaMode == "OPAQUE")
1632 actor.RegisterProperty("uAlphaMode", 0.0f);
1634 else if(materialInfo.alphaMode == "MASK")
1636 actor.RegisterProperty("uAlphaMode", 1.0f);
1640 actor.RegisterProperty("uAlphaMode", 2.0f);
1642 actor.RegisterProperty("alphaCutoff", materialInfo.alphaCutoff);
1644 if(isBaseColorTexture)
1646 actor.RegisterProperty("uBaseColorTexCoordIndex", materialInfo.baseColorTexture.texCoord);
1648 if(isMetallicRoughnessTexture)
1650 actor.RegisterProperty("uMetallicRoughnessTexCoordIndex", materialInfo.metallicRoughnessTexture.texCoord);
1654 actor.RegisterProperty("uNormalScale", materialInfo.normalTexture.value);
1655 actor.RegisterProperty("uNormalTexCoordIndex", materialInfo.normalTexture.texCoord);
1657 if(isOcclusionTexture)
1659 actor.RegisterProperty("uOcclusionTexCoordIndex", materialInfo.occlusionTexture.texCoord);
1660 actor.RegisterProperty("uOcclusionStrength", materialInfo.occlusionTexture.value);
1662 if(isEmissiveTexture)
1664 actor.RegisterProperty("uEmissiveTexCoordIndex", materialInfo.emissiveTexture.texCoord);
1665 actor.RegisterProperty("uEmissiveFactor", materialInfo.emissiveFactor);
1669 if(isMaterial && useIBL)
1671 actor.RegisterProperty("uScaleIBLAmbient", scene3dView.GetIBLScaleFactor());
1672 actor.RegisterProperty("uMipmapLevel", static_cast<float>(maxMipmapLevel));
1677 actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
1678 actor.SetProperty(Actor::Property::POSITION, translation);
1679 actor.RotateBy(orientation);
1680 actor.SetProperty(Actor::Property::SIZE, actorSize);
1683 tempNode = node->GetChild("camera");
1686 int32_t cameraNum = tempNode->GetInteger();
1687 CameraActor cameraActor = scene3dView.GetCamera(cameraNum);
1690 actor.Add(cameraActor);
1694 tempNode = node->GetChild("name");
1697 std::string nameString;
1698 ReadString(tempNode, nameString);
1699 actor.SetProperty(Dali::Actor::Property::NAME, nameString);
1702 SetActorCache(actor, index);
1703 if((tempNode = node->GetChild("children")))
1705 for(auto childIter = tempNode->CBegin(), end = tempNode->CEnd(); childIter != end; ++childIter)
1707 Actor childActor = AddNode(scene3dView, ((*childIter).second).GetInteger());
1708 childActor.SetProperty(Actor::Property::PARENT_ORIGIN, anchorPoint);
1709 actor.Add(childActor);
1716 void Loader::SetActorCache(Actor& actor, uint32_t index)
1718 if(mActorCache.size() < index + 1)
1720 mActorCache.resize(index + 1);
1722 mActorCache[index] = actor;
1725 bool Loader::SetTextureAndSampler(TextureSet& textureSet, int32_t textureIdx, std::string& toShader, std::string shader, int32_t& addIdx)
1730 TextureInfo textureInfo = mTextureArray[textureIdx];
1731 if(textureInfo.sourceIdx >= 0)
1733 textureSet.SetTexture(addIdx, mSourceArray[textureInfo.sourceIdx]);
1735 if(textureInfo.samplerIdx >= 0)
1737 textureSet.SetSampler(addIdx, mSamplerArray[textureInfo.samplerIdx]);
1741 Sampler sampler = Sampler::New();
1742 sampler.SetFilterMode(FilterMode::DEFAULT, FilterMode::DEFAULT);
1743 sampler.SetWrapMode(WrapMode::REPEAT, WrapMode::REPEAT, WrapMode::REPEAT);
1744 textureSet.SetSampler(addIdx, sampler);
1752 bool Loader::LoadAnimation(Scene3dView& scene3dView)
1754 const TreeNode* animationsNode = mRoot->GetChild("animations");
1760 for(auto animationIter = animationsNode->CBegin(), end = animationsNode->CEnd(); animationIter != end; ++animationIter)
1762 const TreeNode* nameNode = (&(*animationIter).second)->GetChild("name");
1763 AnimationInfo animationInfo;
1766 ReadString(nameNode, animationInfo.name);
1769 Property::Index propIndex = Property::INVALID_INDEX;
1770 LoadAnimationChannels((*animationIter).second, animationInfo);
1771 if(animationInfo.channelArray.size() == 0)
1776 LoadAnimationSamplers((*animationIter).second, animationInfo);
1778 for(auto&& currentChannel : animationInfo.channelArray)
1780 if(currentChannel.path == "rotation")
1782 propIndex = Dali::Actor::Property::ORIENTATION;
1784 else if(currentChannel.path == "translation")
1786 propIndex = Dali::Actor::Property::POSITION;
1788 else if(currentChannel.path == "scale")
1790 propIndex = Dali::Actor::Property::SCALE;
1793 float duration = 0.0f;
1794 KeyFrames keyframes = KeyFrames::New();
1795 if(propIndex == Dali::Actor::Property::ORIENTATION)
1797 duration = LoadKeyFrames<Vector4>(animationInfo.samplerArray[currentChannel.sampler], propIndex, keyframes, mPath, mAccessorArray, mBufferViewArray, mBufferArray);
1801 duration = LoadKeyFrames<Vector3>(animationInfo.samplerArray[currentChannel.sampler], propIndex, keyframes, mPath, mAccessorArray, mBufferViewArray, mBufferArray);
1804 Animation animation = Animation::New(duration);
1805 Animation::Interpolation interpolation = Animation::Interpolation::LINEAR;
1806 if(animationInfo.samplerArray[currentChannel.sampler].interpolation == "CUBICSPLINE")
1808 interpolation = Animation::Interpolation::CUBIC;
1810 if(animationInfo.samplerArray[currentChannel.sampler].interpolation == "STEP")
1814 animation.AnimateBetween(Property(mActorCache[currentChannel.targetNode], propIndex), keyframes, interpolation);
1816 animation.SetLooping(false);
1817 scene3dView.AddAnimation(animation);
1824 bool Loader::LoadAnimationChannels(const TreeNode& animation, AnimationInfo& animationInfo)
1826 const TreeNode* channelsNode = animation.GetChild("channels");
1832 for(auto channelIter = channelsNode->CBegin(), end = channelsNode->CEnd(); channelIter != end; ++channelIter)
1834 AnimationChannelInfo animationChannelInfo;
1835 const TreeNode* channelNode = (&(*channelIter).second);
1836 const TreeNode* samplerNode = channelNode->GetChild("sampler");
1839 animationChannelInfo.sampler = samplerNode->GetInteger();
1842 const TreeNode* targetNode = channelNode->GetChild("target");
1845 const TreeNode* tempNode = targetNode->GetChild("node");
1848 animationChannelInfo.targetNode = tempNode->GetInteger();
1855 tempNode = targetNode->GetChild("path");
1858 ReadString(tempNode, animationChannelInfo.path);
1862 animationInfo.channelArray.push_back(animationChannelInfo);
1867 bool Loader::LoadAnimationSamplers(const TreeNode& animation, AnimationInfo& animationInfo)
1869 const TreeNode* samplersNode = animation.GetChild("samplers");
1875 for(auto sampler = samplersNode->CBegin(), end = samplersNode->CEnd(); sampler != end; ++sampler)
1877 AnimationSamplerInfo animationSamplerInfo;
1878 const TreeNode* samplerNode = (&(*sampler).second);
1879 const TreeNode* tempNode = samplerNode->GetChild("input");
1882 animationSamplerInfo.input = tempNode->GetInteger();
1885 tempNode = samplerNode->GetChild("output");
1888 animationSamplerInfo.output = tempNode->GetInteger();
1891 tempNode = samplerNode->GetChild("interpolation");
1894 ReadString(tempNode, animationSamplerInfo.interpolation);
1897 animationInfo.samplerArray.push_back(animationSamplerInfo);
1905 } //namespace Internal
1907 } //namespace Toolkit