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 | #include "Renderer/BsDecal.h" |
4 | #include "Private/RTTI/BsDecalRTTI.h" |
5 | #include "Scene/BsSceneObject.h" |
6 | #include "Renderer/BsRenderer.h" |
7 | #include "Material/BsMaterial.h" |
8 | #include "CoreThread/BsCoreObjectSync.h" |
9 | |
10 | namespace bs |
11 | { |
12 | DecalBase::DecalBase() |
13 | { |
14 | updateBounds(); |
15 | } |
16 | |
17 | DecalBase::DecalBase(const Vector2& size, float maxDistance) |
18 | : mSize(size), mMaxDistance(maxDistance) |
19 | { |
20 | updateBounds(); |
21 | } |
22 | |
23 | void DecalBase::setLayer(UINT64 layer) |
24 | { |
25 | const bool isPow2 = layer && !((layer - 1) & layer); |
26 | |
27 | if (!isPow2) |
28 | { |
29 | LOGWRN("Invalid layer provided. Only one layer bit may be set. Ignoring." ); |
30 | return; |
31 | } |
32 | |
33 | mLayer = layer; |
34 | _markCoreDirty(); |
35 | } |
36 | |
37 | void DecalBase::setTransform(const Transform& transform) |
38 | { |
39 | if (mMobility != ObjectMobility::Movable) |
40 | return; |
41 | |
42 | mTransform = transform; |
43 | mTfrmMatrix = transform.getMatrix(); |
44 | mTfrmMatrixNoScale = Matrix4::TRS(transform.getPosition(), transform.getRotation(), Vector3::ONE); |
45 | |
46 | _markCoreDirty(ActorDirtyFlag::Transform); |
47 | } |
48 | |
49 | void DecalBase::updateBounds() |
50 | { |
51 | const Vector2& extents = mSize * 0.5f; |
52 | |
53 | AABox localAABB( |
54 | Vector3(-extents.x, -extents.y, -mMaxDistance), |
55 | Vector3(extents.x, extents.y, 0.0f) |
56 | ); |
57 | |
58 | localAABB.transformAffine(mTfrmMatrix); |
59 | |
60 | mBounds = Bounds(localAABB, Sphere(localAABB.getCenter(), localAABB.getRadius())); |
61 | } |
62 | |
63 | template <bool Core> |
64 | template <class P> |
65 | void TDecal<Core>::rttiEnumFields(P p) |
66 | { |
67 | p(mSize); |
68 | p(mMaxDistance); |
69 | p(mMaterial); |
70 | p(mBounds); |
71 | p(mLayer); |
72 | p(mLayerMask); |
73 | } |
74 | |
75 | Decal::Decal(const HMaterial& material, const Vector2& size, float maxDistance) |
76 | :TDecal(material, size, maxDistance) |
77 | { |
78 | // Calling virtual method is okay here because this is the most derived type |
79 | updateBounds(); |
80 | } |
81 | |
82 | SPtr<ct::Decal> Decal::getCore() const |
83 | { |
84 | return std::static_pointer_cast<ct::Decal>(mCoreSpecific); |
85 | } |
86 | |
87 | SPtr<Decal> Decal::create(const HMaterial& material, const Vector2& size, float maxDistance) |
88 | { |
89 | Decal* decal = new (bs_alloc<Decal>()) Decal(material, size, maxDistance); |
90 | SPtr<Decal> decalPtr = bs_core_ptr<Decal>(decal); |
91 | decalPtr->_setThisPtr(decalPtr); |
92 | decalPtr->initialize(); |
93 | |
94 | return decalPtr; |
95 | } |
96 | |
97 | SPtr<Decal> Decal::createEmpty() |
98 | { |
99 | Decal* decal = new (bs_alloc<Decal>()) Decal(); |
100 | SPtr<Decal> decalPtr = bs_core_ptr<Decal>(decal); |
101 | decalPtr->_setThisPtr(decalPtr); |
102 | |
103 | return decalPtr; |
104 | } |
105 | |
106 | SPtr<ct::CoreObject> Decal::createCore() const |
107 | { |
108 | SPtr<ct::Material> material; |
109 | if(mMaterial.isLoaded(false)) |
110 | material = mMaterial->getCore(); |
111 | |
112 | ct::Decal* decal = new (bs_alloc<ct::Decal>()) ct::Decal(material, mSize, mMaxDistance); |
113 | SPtr<ct::Decal> decalPtr = bs_shared_ptr<ct::Decal>(decal); |
114 | decalPtr->_setThisPtr(decalPtr); |
115 | |
116 | return decalPtr; |
117 | } |
118 | |
119 | void Decal::getCoreDependencies(Vector<CoreObject*>& dependencies) |
120 | { |
121 | if (mMaterial.isLoaded()) |
122 | dependencies.push_back(mMaterial.get()); |
123 | } |
124 | |
125 | CoreSyncData Decal::syncToCore(FrameAlloc* allocator) |
126 | { |
127 | UINT32 size = 0; |
128 | size += rttiGetElemSize(getCoreDirtyFlags()); |
129 | size += coreSyncGetElemSize((SceneActor&)*this); |
130 | size += coreSyncGetElemSize(*this); |
131 | |
132 | UINT8* buffer = allocator->alloc(size); |
133 | |
134 | char* dataPtr = (char*)buffer; |
135 | dataPtr = rttiWriteElem(getCoreDirtyFlags(), dataPtr); |
136 | dataPtr = coreSyncWriteElem((SceneActor&)*this, dataPtr); |
137 | dataPtr = coreSyncWriteElem(*this, dataPtr); |
138 | |
139 | return CoreSyncData(buffer, size); |
140 | } |
141 | |
142 | void Decal::_markCoreDirty(ActorDirtyFlag flags) |
143 | { |
144 | markCoreDirty((UINT32)flags); |
145 | } |
146 | |
147 | RTTITypeBase* Decal::getRTTIStatic() |
148 | { |
149 | return DecalRTTI::instance(); |
150 | } |
151 | |
152 | RTTITypeBase* Decal::getRTTI() const |
153 | { |
154 | return Decal::getRTTIStatic(); |
155 | } |
156 | |
157 | template class TDecal<true>; |
158 | template class TDecal<false>; |
159 | |
160 | namespace ct |
161 | { |
162 | Decal::Decal(const SPtr<Material>& material, const Vector2& size, float maxDistance) |
163 | : TDecal(material, size, maxDistance) |
164 | { } |
165 | |
166 | Decal::~Decal() |
167 | { |
168 | gRenderer()->notifyDecalRemoved(this); |
169 | } |
170 | |
171 | void Decal::initialize() |
172 | { |
173 | updateBounds(); |
174 | gRenderer()->notifyDecalAdded(this); |
175 | |
176 | CoreObject::initialize(); |
177 | } |
178 | |
179 | void Decal::syncToCore(const CoreSyncData& data) |
180 | { |
181 | char* dataPtr = (char*)data.getBuffer(); |
182 | |
183 | UINT32 dirtyFlags = 0; |
184 | bool oldIsActive = mActive; |
185 | |
186 | dataPtr = rttiReadElem(dirtyFlags, dataPtr); |
187 | dataPtr = coreSyncReadElem((SceneActor&)*this, dataPtr); |
188 | dataPtr = coreSyncReadElem(*this, dataPtr); |
189 | |
190 | mTfrmMatrix = mTransform.getMatrix(); |
191 | mTfrmMatrixNoScale = Matrix4::TRS(mTransform.getPosition(), mTransform.getRotation(), Vector3::ONE); |
192 | |
193 | updateBounds(); |
194 | |
195 | if (dirtyFlags == (UINT32)ActorDirtyFlag::Transform) |
196 | { |
197 | if (mActive) |
198 | gRenderer()->notifyDecalUpdated(this); |
199 | } |
200 | else |
201 | { |
202 | if (oldIsActive != mActive) |
203 | { |
204 | if (mActive) |
205 | gRenderer()->notifyDecalAdded(this); |
206 | else |
207 | gRenderer()->notifyDecalRemoved(this); |
208 | } |
209 | else |
210 | { |
211 | gRenderer()->notifyDecalRemoved(this); |
212 | gRenderer()->notifyDecalAdded(this); |
213 | } |
214 | } |
215 | } |
216 | }} |
217 | |