1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "BsCorePrerequisites.h"
6#include "Reflection/BsRTTIType.h"
7#include "Renderer/BsLightProbeVolume.h"
8#include "Renderer/BsRenderer.h"
9#include "CoreThread/BsCoreThread.h"
10#include "Private/RTTI/BsTextureRTTI.h"
11
12namespace bs
13{
14 /** @cond RTTI */
15 /** @addtogroup RTTI-Impl-Engine
16 * @{
17 */
18
19 BS_ALLOW_MEMCPY_SERIALIZATION(LightProbeSHCoefficients)
20
21 /** Serializable information about a single light probe. */
22 struct SavedLightProbeInfo
23 {
24 Vector<Vector3> positions;
25 Vector<LightProbeSHCoefficients> coefficients;
26 };
27
28 template<> struct RTTIPlainType<SavedLightProbeInfo>
29 {
30 enum { id = TID_SavedLightProbeInfo }; enum { hasDynamicSize = 1 };
31
32 static void toMemory(const SavedLightProbeInfo& data, char* memory)
33 {
34 UINT32 size = getDynamicSize(data);
35
36 UINT32 curSize = sizeof(UINT32);
37 memcpy(memory, &size, curSize);
38 memory += curSize;
39
40 UINT32 version = 0;
41
42 memory = rttiWriteElem(version, memory);
43 memory = rttiWriteElem(data.positions, memory);
44 rttiWriteElem(data.coefficients, memory);
45 }
46
47 static UINT32 fromMemory(SavedLightProbeInfo& data, char* memory)
48 {
49 UINT32 size;
50 memcpy(&size, memory, sizeof(UINT32));
51 memory += sizeof(UINT32);
52
53 UINT32 version;
54 memory = rttiReadElem(version, memory);
55
56 switch(version)
57 {
58 case 0:
59 memory = rttiReadElem(data.positions, memory);
60 memory = rttiReadElem(data.coefficients, memory);
61 break;
62 default:
63 LOGERR("Unknown version of SavedLightProbeInfo data. Unable to deserialize.");
64 break;
65 }
66
67 return size;
68 }
69
70 static UINT32 getDynamicSize(const SavedLightProbeInfo& data)
71 {
72 UINT64 dataSize = rttiGetElemSize(data.positions) + rttiGetElemSize(data.coefficients) + sizeof(UINT32) * 2;
73
74#if BS_DEBUG_MODE
75 if(dataSize > std::numeric_limits<UINT32>::max())
76 {
77 BS_EXCEPT(InternalErrorException, "Data overflow! Size doesn't fit into 32 bits.");
78 }
79#endif
80
81 return (UINT32)dataSize;
82 }
83 };
84
85 class BS_CORE_EXPORT LightProbeVolumeRTTI : public RTTIType <LightProbeVolume, IReflectable, LightProbeVolumeRTTI>
86 {
87 private:
88 BS_BEGIN_RTTI_MEMBERS
89 BS_RTTI_MEMBER_REFL(mTransform, 0)
90 BS_RTTI_MEMBER_PLAIN(mActive, 1)
91 BS_RTTI_MEMBER_PLAIN(mMobility, 2)
92 BS_RTTI_MEMBER_PLAIN(mVolume, 3)
93 BS_RTTI_MEMBER_PLAIN(mCellCount, 4)
94 BS_END_RTTI_MEMBERS
95
96 SavedLightProbeInfo& getProbeInfo(LightProbeVolume* obj)
97 {
98 obj->updateCoefficients();
99
100 UINT32 numProbes = (UINT32)obj->mProbes.size();
101 mSavedLightProbeInfo.coefficients.resize(numProbes);
102 mSavedLightProbeInfo.positions.resize(numProbes);
103
104 UINT32 idx = 0;
105 for(auto& entry : obj->mProbes)
106 {
107 mSavedLightProbeInfo.positions[idx] = entry.second.position;
108 mSavedLightProbeInfo.coefficients[idx] = entry.second.coefficients;
109
110 idx++;
111 }
112
113 return mSavedLightProbeInfo;
114 }
115
116 void setProbeInfo(LightProbeVolume* obj, SavedLightProbeInfo& data)
117 {
118 obj->mProbes.clear();
119
120 UINT32 numProbes = (UINT32)data.positions.size();
121 for(UINT32 i = 0; i < numProbes; ++i)
122 {
123 UINT32 handle = obj->mNextProbeId++;
124
125 LightProbeVolume::ProbeInfo probeInfo;
126 probeInfo.flags = LightProbeFlags::Clean;
127 probeInfo.position = data.positions[i];
128 probeInfo.coefficients = data.coefficients[i];
129
130 obj->mProbes[handle] = probeInfo;
131 }
132 }
133 public:
134 LightProbeVolumeRTTI()
135 {
136 addPlainField("mProbeInfo", 5, &LightProbeVolumeRTTI::getProbeInfo, &LightProbeVolumeRTTI::setProbeInfo,
137 RTTIFieldInfo(RTTIFieldFlag::SkipInReferenceSearch));
138 }
139
140 void onDeserializationEnded(IReflectable* obj, SerializationContext* context) override
141 {
142 // Note: Since this is a CoreObject I should call initialize() right after deserialization,
143 // but since this specific type is used in Components we delay initialization until Component
144 // itself does it. Keep this is mind in case this ever needs to be deserialized for non-Component
145 // purposes (you'll need to call initialize manually).
146 }
147
148 const String& getRTTIName() override
149 {
150 static String name = "LightProbeVolume";
151 return name;
152 }
153
154 UINT32 getRTTIId() override
155 {
156 return TID_LightProbeVolume;
157 }
158
159 SPtr<IReflectable> newRTTIObject() override
160 {
161 return LightProbeVolume::createEmpty();
162 }
163
164 private:
165 SavedLightProbeInfo mSavedLightProbeInfo;
166 };
167
168 /** @} */
169 /** @endcond */
170}
171