Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/tools/DebugDrawer.cc @ 12250

Last change on this file since 12250 was 11814, checked in by landauf, 7 years ago

fixed material of debug drawer (to visualize collision shapes)

  • Property svn:eol-style set to native
File size: 20.3 KB
Line 
1/**
2 * @file DebugDrawer.cc
3 * Copy-pasted from
4 *  - https://bitbucket.org/hasyimi/ogre-debug-drawing-utility/src
5 *  - http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Debug+Drawing+Utility+Class
6 *
7 * This source code is released into the Public Domain.
8 *
9 * Modified by Fabian 'x3n' Landau
10 */
11
12#include "DebugDrawer.h"
13
14#include <OgreSceneManager.h>
15#include <OgreRenderQueue.h>
16#include <OgreManualObject.h>
17#include <OgreAxisAlignedBox.h>
18
19#define DEFAULT_ICOSPHERE_RECURSION_LEVEL 1
20
21namespace orxonox
22{
23    DebugDrawer::DebugDrawer(Ogre::SceneManager *_sceneManager, float _fillAlpha) :
24            sceneManager(_sceneManager), fillAlpha(_fillAlpha), manualObject(nullptr), isEnabled(true), linesIndex(0), trianglesIndex(0)
25    {
26        initialise();
27    }
28
29    DebugDrawer::~DebugDrawer()
30    {
31        shutdown();
32    }
33
34    void DebugDrawer::initialise()
35    {
36        Ogre::ResourcePtr resourcePtr = Ogre::MaterialManager::getSingleton().createOrRetrieve("debug_draw", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true).first;
37        Ogre::Material* material = dynamic_cast<Ogre::Material*>(resourcePtr.get());
38        material->getTechnique(0)->getPass(0)->setVertexColourTracking(Ogre::TrackVertexColourEnum::TVC_AMBIENT);
39        material->getTechnique(0)->getPass(0)->setLightingEnabled(false);
40        material->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
41        material->getTechnique(0)->getPass(0)->setSceneBlending(Ogre::SceneBlendType::SBT_TRANSPARENT_ALPHA);
42
43        manualObject = sceneManager->createManualObject("debug_object");
44        sceneManager->getRootSceneNode()->createChildSceneNode("debug_object")->attachObject(manualObject);
45        manualObject->setDynamic(true);
46
47        icoSphere0.create(0);
48        icoSphere1.create(1);
49        icoSphere2.create(2);
50        icoSphere3.create(3);
51        icoSphere4.create(4);
52
53        manualObject->begin("debug_draw", Ogre::RenderOperation::OT_LINE_LIST);
54        manualObject->position(Ogre::Vector3::ZERO);
55        manualObject->colour(Ogre::ColourValue::ZERO);
56        manualObject->index(0);
57        manualObject->end();
58        manualObject->begin("debug_draw", Ogre::RenderOperation::OT_TRIANGLE_LIST);
59        manualObject->position(Ogre::Vector3::ZERO);
60        manualObject->colour(Ogre::ColourValue::ZERO);
61        manualObject->index(0);
62        manualObject->end();
63
64        linesIndex = trianglesIndex = 0;
65    }
66
67    void DebugDrawer::shutdown()
68    {
69        sceneManager->destroySceneNode("debug_object");
70        sceneManager->destroyManualObject(manualObject);
71    }
72
73    void DebugDrawer::buildLine(const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::ColourValue& colour, float alpha)
74    {
75        int i = addLineVertex(start, Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
76        addLineVertex(end, Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
77
78        addLineIndices(i, i + 1);
79    }
80
81    void DebugDrawer::buildQuad(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, float alpha)
82    {
83        int index = addLineVertex(vertices[0], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
84        addLineVertex(vertices[1], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
85        addLineVertex(vertices[2], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
86        addLineVertex(vertices[3], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
87
88        for (int i = 0; i < 4; ++i)
89            addLineIndices(index + i, index + ((i + 1) % 4));
90    }
91
92    void DebugDrawer::buildCircle(const Ogre::Matrix4& transform, float radius, int segmentsCount, const Ogre::ColourValue& colour, float alpha)
93    {
94        int index = linesIndex;
95        float increment = 2 * Ogre::Math::PI / segmentsCount;
96        float angle = 0.0f;
97
98        for (int i = 0; i < segmentsCount; i++)
99        {
100            addLineVertex(transform * Ogre::Vector3(radius * Ogre::Math::Cos(angle), 0, radius * Ogre::Math::Sin(angle)),
101                    Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
102            angle += increment;
103        }
104
105        for (int i = 0; i < segmentsCount; i++)
106            addLineIndices(index + i, i + 1 < segmentsCount ? index + i + 1 : index);
107    }
108
109    void DebugDrawer::buildFilledCircle(const Ogre::Matrix4& transform, float radius, int segmentsCount, const Ogre::ColourValue& colour, bool up, float alpha)
110    {
111        int index = trianglesIndex;
112        float increment = 2 * Ogre::Math::PI / segmentsCount;
113        float angle = 0.0f;
114
115        for (int i = 0; i < segmentsCount; i++)
116        {
117            addTriangleVertex(transform * Ogre::Vector3(radius * Ogre::Math::Cos(angle), 0, radius * Ogre::Math::Sin(angle)),
118                    Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
119            angle += increment;
120        }
121
122        addTriangleVertex(transform.getTrans(), Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
123
124        for (int i = 0; i < segmentsCount; i++)
125        {
126            if (up)
127                addTriangleIndices(i + 1 < segmentsCount ? index + i + 1 : index, index + i, index + segmentsCount);
128            else
129                addTriangleIndices(index + i, i + 1 < segmentsCount ? index + i + 1 : index, index + segmentsCount);
130        }
131    }
132
133    void DebugDrawer::buildCylinder(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, int segmentsCount, float height, const Ogre::ColourValue& colour, float alpha)
134    {
135        int index = linesIndex;
136
137        Ogre::Matrix4 transform(rotation);
138        transform.setTrans(centre + rotation * Ogre::Vector3(0, height / 2, 0));
139        this->buildCircle(transform, radius, segmentsCount, colour, alpha);
140        transform.setTrans(centre + rotation * Ogre::Vector3(0, -height / 2, 0));
141        this->buildCircle(transform, radius, segmentsCount, colour, alpha);
142
143        for (int i = 0; i < segmentsCount; i++)
144            addLineIndices(index + i, segmentsCount + index + i);
145    }
146
147    void DebugDrawer::buildFilledCylinder(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, int segmentsCount, float height, const Ogre::ColourValue& colour,
148            float alpha)
149    {
150        int index = trianglesIndex;
151
152        Ogre::Matrix4 transform(rotation);
153        transform.setTrans(centre + rotation * Ogre::Vector3(0, height / 2, 0));
154        this->buildCircle(transform, radius, segmentsCount, colour);
155        this->buildFilledCircle(transform, radius, segmentsCount, colour, true, alpha);
156
157        transform.setTrans(centre + rotation * Ogre::Vector3(0, -height / 2, 0));
158        this->buildCircle(transform, radius, segmentsCount, colour);
159        this->buildFilledCircle(transform, radius, segmentsCount, colour, false, alpha);
160
161        for (int i = 0; i < segmentsCount; i++)
162        {
163            addQuadIndices(index + i, i + 1 < segmentsCount ? index + i + 1 : index,
164                    i + 1 < segmentsCount ? (segmentsCount + 1) + index + i + 1 : (segmentsCount + 1) + index, (segmentsCount + 1) + index + i);
165        }
166    }
167
168    void DebugDrawer::buildCone(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, int segmentsCount, float height, const Ogre::ColourValue& colour, float alpha)
169    {
170        int index = linesIndex;
171
172        Ogre::Matrix4 transform(rotation);
173        transform.setTrans(centre + rotation * Ogre::Vector3(0, -height / 2, 0));
174        this->buildCircle(transform, radius, segmentsCount, colour, alpha);
175
176        addLineVertex(centre + rotation * Ogre::Vector3(0, height / 2, 0), Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
177
178        for (int i = 0; i < segmentsCount; i++)
179            addLineIndices(index + i, index + segmentsCount);
180    }
181
182    void DebugDrawer::buildFilledCone(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, int segmentsCount, float height, const Ogre::ColourValue& colour,
183            float alpha)
184    {
185        int index = trianglesIndex;
186
187        Ogre::Matrix4 transform(rotation);
188        transform.setTrans(centre + rotation * Ogre::Vector3(0, -height / 2, 0));
189        this->buildCircle(transform, radius, segmentsCount, colour);
190        this->buildFilledCircle(transform, radius, segmentsCount, colour, false, alpha);
191
192        addTriangleVertex(centre + rotation * Ogre::Vector3(0, height / 2, 0), Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
193
194        for (int i = 0; i < segmentsCount; i++)
195            addTriangleIndices(index + i, index + segmentsCount + 1, i + 1 < segmentsCount ? index + i + 1 : index);
196    }
197
198    void DebugDrawer::buildCuboid(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, float alpha)
199    {
200        int index = addLineVertex(vertices[0], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
201        for (int i = 1; i < 8; ++i)
202            addLineVertex(vertices[i], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
203
204        for (int i = 0; i < 4; ++i)
205            addLineIndices(index + i, index + ((i + 1) % 4));
206        for (int i = 4; i < 8; ++i)
207            addLineIndices(index + i, i == 7 ? index + 4 : index + i + 1);
208        addLineIndices(index + 1, index + 5);
209        addLineIndices(index + 2, index + 4);
210        addLineIndices(index, index + 6);
211        addLineIndices(index + 3, index + 7);
212    }
213
214    void DebugDrawer::buildFilledCuboid(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, float alpha)
215    {
216        int index = addTriangleVertex(vertices[0], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
217        for (int i = 1; i < 8; ++i)
218            addTriangleVertex(vertices[i], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
219
220        addQuadIndices(index, index + 1, index + 2, index + 3);
221        addQuadIndices(index + 4, index + 5, index + 6, index + 7);
222
223        addQuadIndices(index + 1, index + 5, index + 4, index + 2);
224        addQuadIndices(index, index + 3, index + 7, index + 6);
225
226        addQuadIndices(index + 1, index, index + 6, index + 5);
227        addQuadIndices(index + 4, index + 7, index + 3, index + 2);
228    }
229
230    void DebugDrawer::buildFilledQuad(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, float alpha)
231    {
232        int index = addTriangleVertex(vertices[0], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
233        addTriangleVertex(vertices[1], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
234        addTriangleVertex(vertices[2], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
235        addTriangleVertex(vertices[3], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
236
237        addQuadIndices(index, index + 1, index + 2, index + 3);
238    }
239
240    void DebugDrawer::buildFilledTriangle(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, float alpha)
241    {
242        int index = addTriangleVertex(vertices[0], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
243        addTriangleVertex(vertices[1], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
244        addTriangleVertex(vertices[2], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
245
246        addTriangleIndices(index, index + 1, index + 2);
247    }
248
249    void DebugDrawer::buildTetrahedron(const Ogre::Vector3& centre, float scale, const Ogre::ColourValue& colour, float alpha)
250    {
251        int index = linesIndex;
252
253        // Distance from the centre
254        float bottomDistance = scale * 0.2f;
255        float topDistance = scale * 0.62f;
256        float frontDistance = scale * 0.289f;
257        float backDistance = scale * 0.577f;
258        float leftRightDistance = scale * 0.5f;
259
260        addLineVertex(Ogre::Vector3(centre.x, centre.y + topDistance, centre.z), Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
261        addLineVertex(Ogre::Vector3(centre.x, centre.y - bottomDistance, centre.z + frontDistance), Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
262        addLineVertex(Ogre::Vector3(centre.x + leftRightDistance, centre.y - bottomDistance, centre.z - backDistance),
263                Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
264        addLineVertex(Ogre::Vector3(centre.x - leftRightDistance, centre.y - bottomDistance, centre.z - backDistance),
265                Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
266
267        addLineIndices(index, index + 1);
268        addLineIndices(index, index + 2);
269        addLineIndices(index, index + 3);
270
271        addLineIndices(index + 1, index + 2);
272        addLineIndices(index + 2, index + 3);
273        addLineIndices(index + 3, index + 1);
274    }
275
276    void DebugDrawer::buildFilledTetrahedron(const Ogre::Vector3& centre, float scale, const Ogre::ColourValue& colour, float alpha)
277    {
278        int index = trianglesIndex;
279
280        // Distance from the centre
281        float bottomDistance = scale * 0.2f;
282        float topDistance = scale * 0.62f;
283        float frontDistance = scale * 0.289f;
284        float backDistance = scale * 0.577f;
285        float leftRightDistance = scale * 0.5f;
286
287        addTriangleVertex(Ogre::Vector3(centre.x, centre.y + topDistance, centre.z), Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
288        addTriangleVertex(Ogre::Vector3(centre.x, centre.y - bottomDistance, centre.z + frontDistance), Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
289        addTriangleVertex(Ogre::Vector3(centre.x + leftRightDistance, centre.y - bottomDistance, centre.z - backDistance),
290                Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
291        addTriangleVertex(Ogre::Vector3(centre.x - leftRightDistance, centre.y - bottomDistance, centre.z - backDistance),
292                Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
293
294        addTriangleIndices(index, index + 1, index + 2);
295        addTriangleIndices(index, index + 2, index + 3);
296        addTriangleIndices(index, index + 3, index + 1);
297
298        addTriangleIndices(index + 1, index + 3, index + 2);
299    }
300
301    void DebugDrawer::drawLine(const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::ColourValue& colour)
302    {
303        buildLine(start, end, colour);
304    }
305
306    void DebugDrawer::drawCircle(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, const Ogre::ColourValue& colour, bool isFilled)
307    {
308        int segmentsCount = std::min<int>(100, (int) (radius / 2.5));
309
310        Ogre::Matrix4 transform(rotation);
311        transform.setTrans(centre);
312
313        buildCircle(transform, radius, segmentsCount, colour);
314        if (isFilled)
315            buildFilledCircle(transform, radius, segmentsCount, colour, fillAlpha);
316    }
317
318    void DebugDrawer::drawCylinder(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, float height, const Ogre::ColourValue& colour, bool isFilled)
319    {
320        int segmentsCount = std::min<int>(100, (int) (radius / 2.5));
321
322        if (isFilled)
323            buildFilledCylinder(centre, rotation, radius, segmentsCount, height, colour, fillAlpha);
324        else
325            buildCylinder(centre, rotation, radius, segmentsCount, height, colour);
326    }
327
328    void DebugDrawer::drawCone(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, float height, const Ogre::ColourValue& colour, bool isFilled)
329    {
330        int segmentsCount = std::min<int>(100, (int) (radius / 2.5));
331
332        if (isFilled)
333            buildFilledCone(centre, rotation, radius, segmentsCount, height, colour, fillAlpha);
334        else
335            buildCone(centre, rotation, radius, segmentsCount, height, colour);
336    }
337
338    void DebugDrawer::drawQuad(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, bool isFilled)
339    {
340        buildQuad(vertices, colour);
341        if (isFilled)
342            buildFilledQuad(vertices, colour, fillAlpha);
343    }
344
345    void DebugDrawer::drawCuboid(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, bool isFilled)
346    {
347        buildCuboid(vertices, colour);
348        if (isFilled)
349            buildFilledCuboid(vertices, colour, fillAlpha);
350    }
351
352    void DebugDrawer::drawSphere(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, const Ogre::ColourValue& colour, bool isFilled)
353    {
354        const IcoSphere& sphere = this->getIcoSphere(radius);
355
356        if (isFilled)
357        {
358            this->drawCircle(centre, rotation * Ogre::Quaternion(Ogre::Degree(90), Ogre::Vector3(1, 0, 0)), radius, colour, false);
359            this->drawCircle(centre, rotation * Ogre::Quaternion(Ogre::Degree(90), Ogre::Vector3(0, 1, 0)), radius, colour, false);
360            this->drawCircle(centre, rotation * Ogre::Quaternion(Ogre::Degree(90), Ogre::Vector3(0, 0, 1)), radius, colour, false);
361
362            int baseIndex = trianglesIndex;
363            trianglesIndex += sphere.addToVertices(&triangleVertices, centre, Ogre::ColourValue(colour.r, colour.g, colour.b, fillAlpha), radius);
364            sphere.addToTriangleIndices(baseIndex, &triangleIndices);
365        }
366        else
367        {
368            int baseIndex = linesIndex;
369            linesIndex += sphere.addToVertices(&lineVertices, centre, colour, radius);
370            sphere.addToLineIndices(baseIndex, &lineIndices);
371        }
372    }
373
374    const IcoSphere& DebugDrawer::getIcoSphere(float radius) const
375    {
376        if (radius < 50)
377            return this->icoSphere0;
378        else if (radius < 500)
379            return this->icoSphere1;
380        else if (radius < 5000)
381            return this->icoSphere2;
382        else if (radius < 50000)
383            return this->icoSphere3;
384        else
385            return this->icoSphere4;
386    }
387
388    void DebugDrawer::drawTetrahedron(const Ogre::Vector3& centre, float scale, const Ogre::ColourValue& colour, bool isFilled)
389    {
390        buildTetrahedron(centre, scale, colour);
391        if (isFilled)
392            buildFilledTetrahedron(centre, scale, colour, fillAlpha);
393    }
394
395    void DebugDrawer::build()
396    {
397        manualObject->beginUpdate(0);
398        if (lineVertices.size() > 0 && isEnabled)
399        {
400            manualObject->estimateVertexCount(lineVertices.size());
401            manualObject->estimateIndexCount(lineIndices.size());
402            for (const VertexPair& pair : lineVertices)
403            {
404                manualObject->position(pair.first);
405                manualObject->colour(pair.second);
406            }
407            for (int lineIndex : lineIndices)
408                manualObject->index(lineIndex);
409        }
410        else
411            manualObject->index(0); // this is necessary to avoid crashes with ogre 1.7 if there's a light source in the level
412        manualObject->end();
413
414        manualObject->beginUpdate(1);
415        if (triangleVertices.size() > 0 && isEnabled)
416        {
417            manualObject->estimateVertexCount(triangleVertices.size());
418            manualObject->estimateIndexCount(triangleIndices.size());
419            for (const VertexPair& pair : triangleVertices)
420            {
421                manualObject->position(pair.first);
422                manualObject->colour(pair.second.r, pair.second.g, pair.second.b, fillAlpha);
423            }
424            for (int triangleIndex : triangleIndices)
425                manualObject->index(triangleIndex);
426        }
427        else
428            manualObject->index(0); // this is necessary to avoid crashes with ogre 1.7 if there's a light source in the level
429        manualObject->end();
430    }
431
432    void DebugDrawer::clear()
433    {
434        lineVertices.clear();
435        triangleVertices.clear();
436        lineIndices.clear();
437        triangleIndices.clear();
438        linesIndex = trianglesIndex = 0;
439    }
440
441    int DebugDrawer::addLineVertex(const Ogre::Vector3& vertex, const Ogre::ColourValue& colour)
442    {
443        lineVertices.emplace_back(vertex, colour);
444        return linesIndex++;
445    }
446
447    void DebugDrawer::addLineIndices(int index1, int index2)
448    {
449        lineIndices.push_back(index1);
450        lineIndices.push_back(index2);
451    }
452
453    int DebugDrawer::addTriangleVertex(const Ogre::Vector3& vertex, const Ogre::ColourValue& colour)
454    {
455        triangleVertices.emplace_back(vertex, colour);
456        return trianglesIndex++;
457    }
458
459    void DebugDrawer::addTriangleIndices(int index1, int index2, int index3)
460    {
461        triangleIndices.push_back(index1);
462        triangleIndices.push_back(index2);
463        triangleIndices.push_back(index3);
464    }
465
466    void DebugDrawer::addQuadIndices(int index1, int index2, int index3, int index4)
467    {
468        triangleIndices.push_back(index1);
469        triangleIndices.push_back(index2);
470        triangleIndices.push_back(index3);
471
472        triangleIndices.push_back(index1);
473        triangleIndices.push_back(index3);
474        triangleIndices.push_back(index4);
475    }
476}
Note: See TracBrowser for help on using the repository browser.