Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/ogreode/OgreOdeDebugContact.cpp @ 1919

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

Added OgreODE to our source repository because already we really need the newest version. And there is no hope to find any packages under linux.
The files included should compile and link with Ogre 1.4/1.6 and ODE 0.9/0.10. I was only able to test Ogre 1.4 and ODE 0.9/.10 under msvc until now.

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