Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/ogrebullet/Collisions/Debug/OgreBulletCollisionsDebugContact.cpp @ 1985

Last change on this file since 1985 was 1985, checked in by rgrieder, 16 years ago

Split up OgreBullet into Collisions and Dynamics as it was intended by the developers.

  • Property svn:eol-style set to native
File size: 23.7 KB
Line 
1/***************************************************************************
2
3This source file is part of OGREBULLET
4(Object-oriented Graphics Rendering Engine Bullet Wrapper)
5For the latest info, see http://www.ogre3d.org/phpBB2addons/viewforum.php?f=10
6
7Copyright (c) 2007 tuan.kuranes@gmail.com (Use it Freely, even Statically, but have to contribute any changes)
8
9
10
11This program is free software; you can redistribute it and/or modify it under
12the terms of the GPL General Public License with runtime exception as published by the Free Software
13Foundation; either version 2 of the License, or (at your option) any later
14version.
15
16This program is distributed in the hope that it will be useful, but WITHOUT
17ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18FOR A PARTICULAR PURPOSE. See the GPL General Public License with runtime exception for more details.
19
20You should have received a copy of the GPL General Public License with runtime exception along with
21this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22Place - Suite 330, Boston, MA 02111-1307, USA, or go to
23http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
24-----------------------------------------------------------------------------
25*/
26
27
28#include "OgreBulletCollisions.h"
29
30#include "Ogre.h"
31#include "OgreFontManager.h"
32
33#include "Debug/OgreBulletCollisionsDebugContact.h"
34#include "OgreBulletCollisionsShape.h"
35#include "OgreBulletCollisionsObject.h"
36#include "OgreBulletCollisionsWorld.h"
37
38using namespace Ogre;
39
40#define POS_TEX_BINDING    0
41#define COLOUR_BINDING     1
42
43namespace OgreBulletCollisions
44{
45    //------------------------------------------------------------------------------------------------
46    DebugContact::DebugContact(const String &name, CollisionsWorld *world) : 
47        _name(name), 
48        _world(world),
49        _enabled(false)
50    {
51        // scene node
52        _node = _world->getSceneManager()->getRootSceneNode ()->createChildSceneNode ();
53
54        // sphere attach to contact point
55        _point = _world->getSceneManager()->createEntity(name + String("_debug_point"), "sphere.mesh");
56        _point_node = _node->createChildSceneNode ();
57        _point_node->attachObject (_point);
58        _point_node->setScale(0.001, 0.001, 0.001);
59
60        // normal direction debug
61         _normal = new DebugNormal();
62         _node->attachObject (_normal);
63
64         // text info on contact
65        _text = new DebugContactText(name + String("_debug_text"), _node->createChildSceneNode ());
66        _text->setPosition (Vector3(0,5,0));
67        _text->setCaption ("-");
68        _text->setVisible (false);
69
70        _node->setVisible (false);
71    }
72     //------------------------------------------------------------------------------------------------
73    DebugContact::~DebugContact()
74    {
75        delete _text;
76
77        _point_node->detachObject (_point->getName ());
78        _node->detachObject (_normal->getName ());
79
80        _world->getSceneManager()->destroyEntity (_point->getName ());
81
82        _node->detachAllObjects ();
83        _node->removeAndDestroyAllChildren ();
84
85        delete _normal;
86    }
87    //------------------------------------------------------------------------------------------------
88    void DebugContact::update(const Ogre::Vector3 &normal, const Ogre::Vector3 &pt, const Ogre::Real depth)
89    {
90        _node->setPosition (pt);
91
92        _point_node->setPosition (depth * normal);
93
94        //String contactLabel("p: ");
95        //contactLabel = contactLabel + StringConverter::toString(contact->getPosition());
96        //contactLabel = contactLabel + ", n: ";
97        //contactLabel = contactLabel + StringConverter::toString(contact->getNormal());
98        //_text->setCaption (contactLabel);
99        //_text->setVisible (false);
100
101        //_text->setPosition (contact->getPosition () + Vector3(0,5,0));
102       
103        _normal->update (normal, pt, depth);
104    }
105    //------------------------------------------------------------------------------------------------
106    bool DebugContact::isEnabled () const 
107    {
108        return _enabled;
109    }
110    //------------------------------------------------------------------------------------------------
111    void DebugContact::setEnabled (bool enable)
112    {
113        _enabled = enable;
114        _node->setVisible (_enabled);
115    };
116    //------------------------------------------------------------------------------------------------
117    void DebugNormal::update(const Ogre::Vector3 &normal, const Ogre::Vector3 &pt, const Ogre::Real depth)
118    {
119       DebugLines::clear ();
120       // set normal following contact normal
121       //contact->_normal
122       //contact->_position
123       DebugLines::addLine (Vector3::ZERO, 
124                            5*normal);
125        DebugLines::draw ();
126    }
127    //------------------------------------------------------------------------------------------------
128    DebugContactText::DebugContactText(const String &name, 
129                                SceneNode *node,
130                                const String &caption, 
131                                const String &fontName, 
132                                int charHeight, 
133                                const ColourValue &color)
134        : mpCam(NULL)
135        , mpWin(NULL)
136        , mpFont(NULL)
137        , mName(name)
138        , mCaption(caption)
139        , mFontName(fontName)
140        , mCharHeight(charHeight)
141        , mColor(color)
142        , mType("DebugContact")
143        , mTimeUntilNextToggle(0)
144        , mSpaceWidth(0)
145        , mUpdateColors(true)
146        , mOnTop(false)
147        , mHorizontalAlignment(H_LEFT)
148        , mVerticalAlignment(V_BELOW)
149        , mAdditionalHeight(0.0)
150        , mNode(node)
151
152    {
153        if (name.empty())
154            Exception(Exception::ERR_INVALIDPARAMS, "Trying to create DebugContact without name", "DebugContact::DebugContact");
155//
156//         if (caption.empty())
157//            Exception(Exception::ERR_INVALIDPARAMS, "Trying to create DebugContact without caption", "DebugContact::DebugContact");
158
159        mRenderOp.vertexData = NULL;
160        this->setFontName(mFontName);
161        //this->_setupGeometry();
162        mNode->attachObject(this);
163    }
164    //------------------------------------------------------------------------------------------------
165    DebugContactText::~DebugContactText()
166    {
167        mNode->detachObject(this->getName());
168        if (mRenderOp.vertexData)
169            delete mRenderOp.vertexData;
170    }
171#if (OGRE_VERSION >=  ((1 << 16) | (5 << 8) | 0)) // must have at least shoggoth (1.5.0)
172        void DebugContactText::visitRenderables(Renderable::Visitor* visitor, 
173                bool debugRenderables)
174        {
175                visitor->visit(this, 0, false);
176        }
177#endif
178    //------------------------------------------------------------------------------------------------
179    void DebugContactText::setPosition(const Vector3 &pos)
180    {
181        mNode->setPosition (pos);
182    }
183    //------------------------------------------------------------------------------------------------
184    void DebugContactText::setFontName(const String &fontName)
185    {
186        if((Ogre::MaterialManager::getSingletonPtr()->resourceExists(mName + "Material"))) 
187        { 
188            Ogre::MaterialManager::getSingleton().remove(mName + "Material"); 
189        }
190
191        if (mFontName != fontName || mpMaterial.isNull() || !mpFont)
192        {
193            mFontName = fontName;
194            mpFont = (Font *)FontManager::getSingleton().getByName(mFontName).getPointer();
195            if (!mpFont)
196                Exception(Exception::ERR_ITEM_NOT_FOUND, "Could not find font " + fontName, "DebugContact::setFontName");
197
198            mpFont->load();
199            if (!mpMaterial.isNull())
200            {
201                MaterialManager::getSingletonPtr()->remove(mpMaterial->getName());
202                mpMaterial.setNull();
203            }
204
205            mpMaterial = mpFont->getMaterial()->clone(mName + "Material");
206            if (!mpMaterial->isLoaded())
207                mpMaterial->load();
208
209            mpMaterial->setDepthCheckEnabled(!mOnTop);
210            //mpMaterial->setDepthBias(!mOnTop);
211            mpMaterial->setDepthBias(0,!mOnTop);
212            mpMaterial->setDepthWriteEnabled(mOnTop);
213            mpMaterial->setLightingEnabled(false);
214            mNeedUpdate = true;
215        }
216    }
217    //------------------------------------------------------------------------------------------------
218    void DebugContactText::setCaption(const String &caption)
219    {
220        if (caption != mCaption)
221        {
222            mCaption = caption;
223            mNeedUpdate = true;
224        }
225    }
226    //------------------------------------------------------------------------------------------------
227    void DebugContactText::setColor(const ColourValue &color)
228    {
229        if (color != mColor)
230        {
231            mColor = color;
232            mUpdateColors = true;
233        }
234    }
235    //------------------------------------------------------------------------------------------------
236    void DebugContactText::setCharacterHeight(unsigned int height)
237    {
238        if (height != mCharHeight)
239        {
240            mCharHeight = height;
241            mNeedUpdate = true;
242        }
243    }
244    //------------------------------------------------------------------------------------------------
245    void DebugContactText::setSpaceWidth(unsigned int width)
246    {
247        if (width != mSpaceWidth)
248        {
249            mSpaceWidth = width;
250            mNeedUpdate = true;
251        }
252    }
253    //------------------------------------------------------------------------------------------------
254    void DebugContactText::setTextAlignment(const HorizontalAlignment& horizontalAlignment, const VerticalAlignment& verticalAlignment)
255    {
256        if(mHorizontalAlignment != horizontalAlignment)
257        {
258            mHorizontalAlignment = horizontalAlignment;
259            mNeedUpdate = true;
260        }
261        if(mVerticalAlignment != verticalAlignment)
262        {
263            mVerticalAlignment = verticalAlignment;
264            mNeedUpdate = true;
265        }
266    }
267    //------------------------------------------------------------------------------------------------
268    void DebugContactText::setAdditionalHeight( Real height )
269    {
270        if( mAdditionalHeight != height )
271        {
272            mAdditionalHeight = height;
273            mNeedUpdate = true;
274        }
275    }
276    //------------------------------------------------------------------------------------------------
277    void DebugContactText::showOnTop(bool show)
278    {
279        if( mOnTop != show && !mpMaterial.isNull() )
280        {
281            mOnTop = show;
282            mpMaterial->setDepthBias(0,!mOnTop);
283            mpMaterial->setDepthCheckEnabled(!mOnTop);
284            mpMaterial->setDepthWriteEnabled(mOnTop);
285        }
286    }
287    //------------------------------------------------------------------------------------------------
288    void DebugContactText::_setupGeometry()
289    {
290        assert(mpFont);
291        assert(!mpMaterial.isNull());
292
293        unsigned int vertexCount = static_cast<unsigned int>(mCaption.size() * 6);
294
295        if (mRenderOp.vertexData)
296        {
297            // Removed this test as it causes problems when replacing a caption
298            // of the same size: replacing "Hello" with "hello"
299            // as well as when changing the text alignment
300            //if (mRenderOp.vertexData->vertexCount != vertexCount)
301            {
302                delete mRenderOp.vertexData;
303                mRenderOp.vertexData = NULL;
304                mUpdateColors = true;
305            }
306        }
307
308        if (!mRenderOp.vertexData)
309            mRenderOp.vertexData = new VertexData();
310
311        mRenderOp.indexData = 0;
312        mRenderOp.vertexData->vertexStart = 0;
313        mRenderOp.vertexData->vertexCount = vertexCount;
314        mRenderOp.operationType = RenderOperation::OT_TRIANGLE_LIST; 
315        mRenderOp.useIndexes = false; 
316
317        VertexDeclaration  *decl = mRenderOp.vertexData->vertexDeclaration;
318        VertexBufferBinding   *bind = mRenderOp.vertexData->vertexBufferBinding;
319        size_t offset = 0;
320
321        // create/bind positions/tex.ccord. buffer
322        if (!decl->findElementBySemantic(VES_POSITION))
323            decl->addElement(POS_TEX_BINDING, offset, VET_FLOAT3, VES_POSITION);
324
325        offset += VertexElement::getTypeSize(VET_FLOAT3);
326
327        if (!decl->findElementBySemantic(VES_TEXTURE_COORDINATES))
328            decl->addElement(POS_TEX_BINDING, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0);
329
330        HardwareVertexBufferSharedPtr ptbuf = HardwareBufferManager::getSingleton().createVertexBuffer(decl->getVertexSize(POS_TEX_BINDING),
331            mRenderOp.vertexData->vertexCount,
332            HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY);
333        bind->setBinding(POS_TEX_BINDING, ptbuf);
334
335        // Colours - store these in a separate buffer because they change less often
336        if (!decl->findElementBySemantic(VES_DIFFUSE))
337            decl->addElement(COLOUR_BINDING, 0, VET_COLOUR, VES_DIFFUSE);
338
339        HardwareVertexBufferSharedPtr cbuf = HardwareBufferManager::getSingleton().createVertexBuffer(decl->getVertexSize(COLOUR_BINDING),
340            mRenderOp.vertexData->vertexCount,
341            HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY);
342        bind->setBinding(COLOUR_BINDING, cbuf);
343
344        size_t charlen = mCaption.size();
345        Real *pPCBuff = static_cast<Real*>(ptbuf->lock(HardwareBuffer::HBL_DISCARD));
346
347        float largestWidth = 0;
348        float left = 0 * 2.0 - 1.0;
349        float top = -((0 * 2.0) - 1.0);
350
351        // Derive space width from a capital A
352        if (mSpaceWidth == 0)
353            mSpaceWidth = mpFont->getGlyphAspectRatio('A') * mCharHeight * 2.0;
354
355        // for calculation of AABB
356        Ogre::Vector3 min, max, currPos;
357        Ogre::Real maxSquaredRadius;
358        bool first = true;
359
360        // Use iterator
361        String::iterator i, iend;
362        iend = mCaption.end();
363        bool newLine = true;
364        Real len = 0.0f;
365
366        if(mVerticalAlignment == DebugContactText::V_ABOVE)
367        {
368            // Raise the first line of the caption
369            top += mCharHeight;
370            for (i = mCaption.begin(); i != iend; ++i)
371            {
372                if (*i == '\n')
373                    top += mCharHeight * 2.0;
374            }
375        }
376
377        for (i = mCaption.begin(); i != iend; ++i)
378        {
379            if (newLine)
380            {
381                len = 0.0f;
382                for (String::iterator j = i; j != iend && *j != '\n'; j++)
383                {
384                    if (*j == ' ')
385                        len += mSpaceWidth;
386                    else 
387                        len += mpFont->getGlyphAspectRatio(*j) * mCharHeight * 2.0;
388                }
389                newLine = false;
390            }
391
392            if (*i == '\n')
393            {
394                left = 0 * 2.0 - 1.0;
395                top -= mCharHeight * 2.0;
396                newLine = true;
397                continue;
398            }
399
400            if (*i == ' ')
401            {
402                // Just leave a gap, no tris
403                left += mSpaceWidth;
404                // Also reduce tri count
405                mRenderOp.vertexData->vertexCount -= 6;
406                continue;
407            }
408
409            Real horiz_height = mpFont->getGlyphAspectRatio(*i);
410           
411            //mpFont->getGlyphTexCoords(*i, u1, v1, u2, v2);
412            const Font::UVRect &uvRect = mpFont->getGlyphTexCoords(*i);
413            const Real u1 = uvRect.left; 
414            const Real u2 = uvRect.right; 
415            const Real v1 = uvRect.top; 
416            const Real v2 = uvRect.bottom; 
417
418            // each vert is (x, y, z, u, v)
419            //-------------------------------------------------------------------------------------
420            // First tri
421            //
422            // Upper left
423            if(mHorizontalAlignment == DebugContactText::H_LEFT)
424                *pPCBuff++ = left;
425            else
426                *pPCBuff++ = left - (len / 2);
427            *pPCBuff++ = top;
428            *pPCBuff++ = -1.0;
429            *pPCBuff++ = u1;
430            *pPCBuff++ = v1;
431
432            // Deal with bounds
433            if(mHorizontalAlignment == DebugContactText::H_LEFT)
434                currPos = Ogre::Vector3(left, top, -1.0);
435            else
436                currPos = Ogre::Vector3(left - (len / 2), top, -1.0);
437            if (first)
438            {
439                min = max = currPos;
440                maxSquaredRadius = currPos.squaredLength();
441                first = false;
442            }
443            else
444            {
445                min.makeFloor(currPos);
446                max.makeCeil(currPos);
447                maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength());
448            }
449
450            top -= mCharHeight * 2.0;
451
452            // Bottom left
453            if(mHorizontalAlignment == DebugContactText::H_LEFT)
454                *pPCBuff++ = left;
455            else
456                *pPCBuff++ = left - (len / 2);
457            *pPCBuff++ = top;
458            *pPCBuff++ = -1.0;
459            *pPCBuff++ = u1;
460            *pPCBuff++ = v2;
461
462            // Deal with bounds
463            if(mHorizontalAlignment == DebugContactText::H_LEFT)
464                currPos = Ogre::Vector3(left, top, -1.0);
465            else
466                currPos = Ogre::Vector3(left - (len / 2), top, -1.0);
467            min.makeFloor(currPos);
468            max.makeCeil(currPos);
469            maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength());
470
471            top += mCharHeight * 2.0;
472            left += horiz_height * mCharHeight * 2.0;
473
474            // Top right
475            if(mHorizontalAlignment == DebugContactText::H_LEFT)
476                *pPCBuff++ = left;
477            else
478                *pPCBuff++ = left - (len / 2);
479            *pPCBuff++ = top;
480            *pPCBuff++ = -1.0;
481            *pPCBuff++ = u2;
482            *pPCBuff++ = v1;
483            //-------------------------------------------------------------------------------------
484
485            // Deal with bounds
486            if(mHorizontalAlignment == DebugContactText::H_LEFT)
487                currPos = Ogre::Vector3(left, top, -1.0);
488            else
489                currPos = Ogre::Vector3(left - (len / 2), top, -1.0);
490            min.makeFloor(currPos);
491            max.makeCeil(currPos);
492            maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength());
493
494            //-------------------------------------------------------------------------------------
495            // Second tri
496            //
497            // Top right (again)
498            if(mHorizontalAlignment == DebugContactText::H_LEFT)
499                *pPCBuff++ = left;
500            else
501                *pPCBuff++ = left - (len / 2);
502            *pPCBuff++ = top;
503            *pPCBuff++ = -1.0;
504            *pPCBuff++ = u2;
505            *pPCBuff++ = v1;
506
507            currPos = Ogre::Vector3(left, top, -1.0);
508            min.makeFloor(currPos);
509            max.makeCeil(currPos);
510            maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength());
511
512            top -= mCharHeight * 2.0;
513            left -= horiz_height  * mCharHeight * 2.0;
514
515            // Bottom left (again)
516            if(mHorizontalAlignment == DebugContactText::H_LEFT)
517                *pPCBuff++ = left;
518            else
519                *pPCBuff++ = left - (len / 2);
520            *pPCBuff++ = top;
521            *pPCBuff++ = -1.0;
522            *pPCBuff++ = u1;
523            *pPCBuff++ = v2;
524
525            currPos = Ogre::Vector3(left, top, -1.0);
526            min.makeFloor(currPos);
527            max.makeCeil(currPos);
528            maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength());
529
530            left += horiz_height  * mCharHeight * 2.0;
531
532            // Bottom right
533            if(mHorizontalAlignment == DebugContactText::H_LEFT)
534                *pPCBuff++ = left;
535            else
536                *pPCBuff++ = left - (len / 2);
537            *pPCBuff++ = top;
538            *pPCBuff++ = -1.0;
539            *pPCBuff++ = u2;
540            *pPCBuff++ = v2;
541            //-------------------------------------------------------------------------------------
542
543            currPos = Ogre::Vector3(left, top, -1.0);
544            min.makeFloor(currPos);
545            max.makeCeil(currPos);
546            maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength());
547
548            // Go back up with top
549            top += mCharHeight * 2.0;
550
551            float currentWidth = (left + 1)/2 - 0;
552            if (currentWidth > largestWidth)
553                largestWidth = currentWidth;
554        }
555
556        // Unlock vertex buffer
557        ptbuf->unlock();
558
559        // update AABB/Sphere radius
560        mAABB = Ogre::AxisAlignedBox(min, max);
561        mRadius = Ogre::Math::Sqrt(maxSquaredRadius);
562
563        if (mUpdateColors)
564            this->_updateColors();
565
566        mNeedUpdate = false;
567    }
568    //------------------------------------------------------------------------------------------------
569    void DebugContactText::_updateColors(void)
570    {
571        assert(mpFont);
572        assert(!mpMaterial.isNull());
573
574        // Convert to system-specific
575        RGBA color;
576        Root::getSingleton().convertColourValue(mColor, &color);
577        HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(COLOUR_BINDING);
578        RGBA *pDest = static_cast<RGBA*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));
579        for (unsigned int i = 0; i < mRenderOp.vertexData->vertexCount; ++i)
580            *pDest++ = color;
581        vbuf->unlock();
582        mUpdateColors = false;
583    }
584    //------------------------------------------------------------------------------------------------
585    const Quaternion& DebugContactText::getWorldOrientation(void) const
586    {
587        assert(mpCam);
588        return const_cast<Quaternion&>(mpCam->getDerivedOrientation());
589    }
590    //------------------------------------------------------------------------------------------------
591    const Vector3& DebugContactText::getWorldPosition(void) const
592    {
593        assert(mParentNode);
594        return mParentNode->_getDerivedPosition();
595    }
596    //------------------------------------------------------------------------------------------------
597    void DebugContactText::getWorldTransforms(Matrix4 *xform) const 
598    {
599        if (this->isVisible() && mpCam)
600        {
601            Matrix3 rot3x3, scale3x3 = Matrix3::IDENTITY;
602
603            // store rotation in a matrix
604            mpCam->getDerivedOrientation().ToRotationMatrix(rot3x3);
605
606            // parent node position
607            Vector3 ppos = mParentNode->_getDerivedPosition() + Vector3::UNIT_Y*mAdditionalHeight;
608
609            // apply scale
610            scale3x3[0][0] = mParentNode->_getDerivedScale().x / 2;
611            scale3x3[1][1] = mParentNode->_getDerivedScale().y / 2;
612            scale3x3[2][2] = mParentNode->_getDerivedScale().z / 2;
613
614            // apply all transforms to xform       
615            *xform = (rot3x3 * scale3x3);
616            xform->setTrans(ppos);
617        }
618    }
619    //------------------------------------------------------------------------------------------------
620    void DebugContactText::getRenderOperation(RenderOperation &op)
621    {
622        if (this->isVisible())
623        {
624            if (mNeedUpdate)
625                this->_setupGeometry();
626            if (mUpdateColors)
627                this->_updateColors();
628            op = mRenderOp;
629        }
630    }
631    //------------------------------------------------------------------------------------------------
632    void DebugContactText::_notifyCurrentCamera(Camera *cam)
633    {
634        mpCam = cam;
635    }
636    //------------------------------------------------------------------------------------------------
637    void DebugContactText::_updateRenderQueue(RenderQueue* queue)
638    {
639        if (this->isVisible())
640        {
641            if (mNeedUpdate)
642                this->_setupGeometry();
643            if (mUpdateColors)
644                this->_updateColors();
645
646            queue->addRenderable(this, mRenderQueueID, OGRE_RENDERABLE_DEFAULT_PRIORITY);
647            //      queue->addRenderable(this, mRenderQueueID, RENDER_QUEUE_SKIES_LATE);
648        }
649    }
650}
Note: See TracBrowser for help on using the repository browser.