Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Cleaned up the heavy mess with header file includes in OgreOde. It should now compile a lot faster.

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