Supports cube map images in scene-loader
[platform/core/uifw/dali-toolkit.git] / dali-scene-loader / public-api / cube-loader.cpp
1 /*
2  * Copyright (c) 2022 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 // FILE HEADER
19 #include <dali-scene-loader/public-api/cube-loader.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/devel-api/adaptor-framework/image-loading.h>
23 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
24 #include <dali/public-api/common/vector-wrapper.h>
25 #include <dali/public-api/rendering/texture.h>
26 #include <dali/integration-api/debug.h>
27 #include <string.h>
28
29 namespace Dali
30 {
31 namespace
32 {
33 /**
34  * @brief cube map face index
35  * Cube map layer order is as fallows:
36  * POSITIVE_X, NEGATIVE_X, POSITIVE_Y, NEGATIVE_Y, POSITIVE_Z, NEGATIVE_Z. @see CubeMapLayer
37  * The indices are for 4 kind of environment cube map. Cross_horizontal, Array_horizontal, Cross_vertical, and Array_vertical.
38  */
39 const uint32_t CUBEMAP_INDEX_X[4][6] = {{2, 0, 1, 1, 1, 3}, {0, 1, 2, 3, 4, 5}, {1, 1, 1, 1, 0, 2}, {0, 0, 0, 0, 0, 0}};
40 const uint32_t CUBEMAP_INDEX_Y[4][6] = {{1, 1, 0, 2, 1, 1}, {0, 0, 0, 0, 0, 0}, {1, 3, 0, 2, 1, 1}, {0, 1, 2, 3, 4, 5}};
41
42 enum CubeType
43 {
44   CROSS_HORIZONTAL = 0, // Cross horizontal style cube map
45   ARRAY_HORIZONTAL,     // array horizontal style cube map
46   CROSS_VERTICAL,       // Cross vertical style cube map
47   ARRAY_VERTICAL,       // array vertical style cube map
48   NONE
49 };
50
51 uint8_t* GetCroppedBuffer(uint8_t* sourceBuffer, uint32_t bytesPerPixel, uint32_t width, uint32_t height, uint32_t xOffset, uint32_t yOffset, uint32_t xFaceSize, uint32_t yFaceSize)
52 {
53   uint32_t byteSize   = bytesPerPixel * xFaceSize * yFaceSize;
54   uint8_t* destBuffer = reinterpret_cast<uint8_t*>(malloc(byteSize + 4u));
55
56   int32_t srcStride  = width * bytesPerPixel;
57   int32_t destStride = xFaceSize * bytesPerPixel;
58   int32_t srcOffset  = xOffset * bytesPerPixel + yOffset * srcStride;
59   int32_t destOffset = 0;
60   for(uint16_t row = yOffset; row < yOffset + yFaceSize; ++row)
61   {
62     memcpy(destBuffer + destOffset, sourceBuffer + srcOffset, destStride);
63     srcOffset += srcStride;
64     destOffset += destStride;
65   }
66
67   return destBuffer;
68 }
69
70 PixelData GetCubeFace(Devel::PixelBuffer pixelBuffer, uint32_t faceIndex, CubeType cubeType, uint32_t faceSize)
71 {
72   PixelData pixelData;
73   if(cubeType != NONE)
74   {
75     uint8_t* imageBuffer   = pixelBuffer.GetBuffer();
76     uint32_t bytesPerPixel = Pixel::GetBytesPerPixel(pixelBuffer.GetPixelFormat());
77     uint32_t imageWidth    = pixelBuffer.GetWidth();
78     uint32_t imageHeight   = pixelBuffer.GetHeight();
79
80     uint32_t xOffset = CUBEMAP_INDEX_X[cubeType][faceIndex] * faceSize;
81     uint32_t yOffset = CUBEMAP_INDEX_Y[cubeType][faceIndex] * faceSize;
82
83     uint8_t* tempImageBuffer = GetCroppedBuffer(imageBuffer, bytesPerPixel, imageWidth, imageHeight, xOffset, yOffset, faceSize, faceSize);
84     pixelData                = PixelData::New(tempImageBuffer, faceSize * faceSize * bytesPerPixel, faceSize, faceSize, pixelBuffer.GetPixelFormat(), PixelData::FREE);
85   }
86   return pixelData;
87 }
88 } // namespace
89
90 namespace SceneLoader
91 {
92 bool LoadCubeData(const std::string& path, CubeData& cubedata)
93 {
94   Texture cubeTexture;
95   // Diffuse Cube Map
96   if(path.empty())
97   {
98     return false;
99   }
100
101   Devel::PixelBuffer pixelBuffer = LoadImageFromFile(path);
102   if(pixelBuffer)
103   {
104     uint32_t imageWidth  = pixelBuffer.GetWidth();
105     uint32_t imageHeight = pixelBuffer.GetHeight();
106
107     uint32_t faceSize = 0;
108     CubeType cubeType = NONE;
109     if(imageWidth / 4 == imageHeight / 3)
110     {
111       cubeType = CROSS_HORIZONTAL;
112       faceSize = imageWidth / 4;
113     }
114     else if(imageWidth / 6 == imageHeight)
115     {
116       cubeType = ARRAY_HORIZONTAL;
117       faceSize = imageHeight;
118     }
119     else if(imageWidth / 3 == imageHeight / 4)
120     {
121       cubeType = CROSS_VERTICAL;
122       faceSize = imageHeight / 4;
123     }
124     else if(imageWidth == imageHeight / 6)
125     {
126       cubeType = ARRAY_VERTICAL;
127       faceSize = imageWidth;
128     }
129     else
130     {
131       DALI_LOG_ERROR("The image is not a cube map\n");
132       return false;
133     }
134
135     cubedata.data.resize(6);
136     for(uint32_t i = 0; i < 6; ++i)
137     {
138       cubedata.data[i].resize(1);
139     }
140     for(uint32_t i = 0; i < 6; ++i)
141     {
142       cubedata.data[i][0] = GetCubeFace(pixelBuffer, i, cubeType, faceSize);
143     }
144
145     return true;
146   }
147   return false;
148 }
149
150 } // namespace SceneLoader
151 } // namespace Dali