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 "Debug/BsDebugDraw.h"
4#include "Mesh/BsMesh.h"
5#include "RenderAPI/BsVertexDataDesc.h"
6#include "Utility/BsShapeMeshes3D.h"
7#include "Image/BsSpriteTexture.h"
8#include "CoreThread/BsCoreThread.h"
9#include "Material/BsMaterial.h"
10#include "RenderAPI/BsGpuParams.h"
11#include "Material/BsGpuParamsSet.h"
12#include "RenderAPI/BsRenderAPI.h"
13#include "Renderer/BsRenderer.h"
14#include "Renderer/BsRendererUtility.h"
15#include "Utility/BsDrawHelper.h"
16#include "Renderer/BsRendererExtension.h"
17#include "Resources/BsBuiltinResources.h"
18#include "Renderer/BsCamera.h"
19#include "Profiling/BsProfilerGPU.h"
20
21using namespace std::placeholders;
22
23namespace bs
24{
25 DebugDraw::DebugDraw()
26 {
27 mDrawHelper = bs_new<DrawHelper>();
28 mRenderer = RendererExtension::create<ct::DebugDrawRenderer>(nullptr);
29 }
30
31 DebugDraw::~DebugDraw()
32 {
33 bs_delete(mDrawHelper);
34 }
35
36 void DebugDraw::setColor(const Color& color)
37 {
38 mDrawHelper->setColor(color);
39 }
40
41 void DebugDraw::setTransform(const Matrix4& transform)
42 {
43 mDrawHelper->setTransform(transform);
44 }
45
46 void DebugDraw::drawCube(const Vector3& position, const Vector3& extents)
47 {
48 mDrawHelper->cube(position, extents);
49 }
50
51 void DebugDraw::drawSphere(const Vector3& position, float radius)
52 {
53 mDrawHelper->sphere(position, radius);
54 }
55
56 void DebugDraw::drawCone(const Vector3& base, const Vector3& normal, float height, float radius, const Vector2& scale)
57 {
58 mDrawHelper->cone(base, normal, height, radius, scale);
59 }
60
61 void DebugDraw::drawDisc(const Vector3& position, const Vector3& normal, float radius)
62 {
63 mDrawHelper->disc(position, normal, radius);
64 }
65
66 void DebugDraw::drawWireCube(const Vector3& position, const Vector3& extents)
67 {
68 mDrawHelper->wireCube(position, extents);
69 }
70
71 void DebugDraw::drawWireSphere(const Vector3& position, float radius)
72 {
73 mDrawHelper->wireSphere(position, radius);
74 }
75
76 void DebugDraw::drawWireCone(const Vector3& base, const Vector3& normal, float height, float radius, const Vector2& scale)
77 {
78 mDrawHelper->wireCone(base, normal, height, radius, scale);
79 }
80
81 void DebugDraw::drawLine(const Vector3& start, const Vector3& end)
82 {
83 mDrawHelper->line(start, end);
84 }
85
86 void DebugDraw::drawLineList(const Vector<Vector3>& linePoints)
87 {
88 mDrawHelper->lineList(linePoints);
89 }
90
91 void DebugDraw::drawWireDisc(const Vector3& position, const Vector3& normal, float radius)
92 {
93 mDrawHelper->wireDisc(position, normal, radius);
94 }
95
96 void DebugDraw::drawWireArc(const Vector3& position, const Vector3& normal, float radius,
97 Degree startAngle, Degree amountAngle)
98 {
99 mDrawHelper->wireArc(position, normal, radius, startAngle, amountAngle);
100 }
101
102 void DebugDraw::drawWireMesh(const SPtr<MeshData>& meshData)
103 {
104 mDrawHelper->wireMesh(meshData);
105 }
106
107 void DebugDraw::drawFrustum(const Vector3& position, float aspect, Degree FOV, float near, float far)
108 {
109 mDrawHelper->frustum(position, aspect, FOV, near, far);
110 }
111
112 Vector<DebugDraw::MeshRenderData> DebugDraw::createMeshProxyData(const Vector<DrawHelper::ShapeMeshData>& meshData)
113 {
114 Vector<MeshRenderData> proxyData;
115 for (auto& entry : meshData)
116 {
117 if (entry.type == DrawHelper::MeshType::Solid)
118 proxyData.push_back(MeshRenderData(entry.mesh->getCore(), entry.subMesh, DebugDrawMaterial::Solid));
119 else if (entry.type == DrawHelper::MeshType::Wire)
120 proxyData.push_back(MeshRenderData(entry.mesh->getCore(), entry.subMesh, DebugDrawMaterial::Wire));
121 else if (entry.type == DrawHelper::MeshType::Line)
122 proxyData.push_back(MeshRenderData(entry.mesh->getCore(), entry.subMesh, DebugDrawMaterial::Line));
123 }
124
125 return proxyData;
126 }
127
128 void DebugDraw::clear()
129 {
130 mDrawHelper->clear();
131 }
132
133 void DebugDraw::_update()
134 {
135 mActiveMeshes.clear();
136 mActiveMeshes = mDrawHelper->buildMeshes(DrawHelper::SortType::None);
137
138 Vector<MeshRenderData> proxyData = createMeshProxyData(mActiveMeshes);
139
140 ct::DebugDrawRenderer* renderer = mRenderer.get();
141 gCoreThread().queueCommand(std::bind(&ct::DebugDrawRenderer::updateData, renderer, proxyData));
142 }
143
144 namespace ct
145 {
146
147 DebugDrawParamsDef gDebugDrawParamsDef;
148
149 DebugDrawMat::DebugDrawMat()
150 {
151 // Do nothing
152 }
153
154 void DebugDrawMat::execute(const SPtr<GpuParamBlockBuffer>& params, const SPtr<Mesh>& mesh, const SubMesh& subMesh)
155 {
156 BS_RENMAT_PROFILE_BLOCK
157
158 mParams->setParamBlockBuffer("Params", params);
159
160 bind();
161 gRendererUtility().draw(mesh, subMesh);
162 }
163
164 DebugDrawMat* DebugDrawMat::getVariation(DebugDrawMaterial mat)
165 {
166 if (mat == DebugDrawMaterial::Solid)
167 return get(getVariation<true, false, false>());
168
169 if (mat == DebugDrawMaterial::Wire)
170 return get(getVariation<false, false, true>());
171
172 return get(getVariation<false, true, false>());
173 }
174
175 DebugDrawRenderer::DebugDrawRenderer()
176 :RendererExtension(RenderLocation::PostLightPass, 0)
177 {
178 }
179
180 void DebugDrawRenderer::initialize(const Any& data)
181 {
182 THROW_IF_NOT_CORE_THREAD;
183
184 mParamBuffer = gDebugDrawParamsDef.createBuffer();
185 }
186
187 void DebugDrawRenderer::updateData(const Vector<DebugDraw::MeshRenderData>& meshes)
188 {
189 mMeshes = meshes;
190 }
191
192 bool DebugDrawRenderer::check(const Camera& camera)
193 {
194 return true;
195 }
196
197 void DebugDrawRenderer::render(const Camera& camera)
198 {
199 SPtr<RenderTarget> renderTarget = camera.getViewport()->getTarget();
200 if (renderTarget == nullptr)
201 return;
202
203 Matrix4 viewMatrix = camera.getViewMatrix();
204 Matrix4 projMatrix = camera.getProjectionMatrixRS();
205 Matrix4 viewProjMat = projMatrix * viewMatrix;
206
207 gDebugDrawParamsDef.gMatViewProj.set(mParamBuffer, viewProjMat);
208 gDebugDrawParamsDef.gViewDir.set(mParamBuffer, (Vector4)camera.getTransform().getForward());
209
210 for (auto& entry : mMeshes)
211 {
212 DebugDrawMat* mat = DebugDrawMat::getVariation(entry.type);
213 mat->execute(mParamBuffer, entry.mesh, entry.subMesh);
214 }
215 }
216 }
217}
218