Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Added OgreBullet to the repository. The revision was 2493 (ogreaddons), trunk.

  • 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.