Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ogreode/src/OgreOdeDebugContact.cpp @ 21

Last change on this file since 21 was 21, checked in by nicolasc, 16 years ago

added ogreode and Colladaplugin

File size: 22.2 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    const Quaternion& DebugContactText::getWorldOrientation(void) const
559    {
560        assert(mpCam);
561        return const_cast<Quaternion&>(mpCam->getDerivedOrientation());
562    }
563    //------------------------------------------------------------------------------------------------
564    const Vector3& DebugContactText::getWorldPosition(void) const
565    {
566        assert(mParentNode);
567        return mParentNode->_getDerivedPosition();
568    }
569    //------------------------------------------------------------------------------------------------
570    void DebugContactText::getWorldTransforms(Matrix4 *xform) const 
571    {
572        if (this->isVisible() && mpCam)
573        {
574            Matrix3 rot3x3, scale3x3 = Matrix3::IDENTITY;
575
576            // store rotation in a matrix
577            mpCam->getDerivedOrientation().ToRotationMatrix(rot3x3);
578
579            // parent node position
580            Vector3 ppos = mParentNode->_getDerivedPosition() + Vector3::UNIT_Y*mAdditionalHeight;
581
582            // apply scale
583            scale3x3[0][0] = mParentNode->_getDerivedScale().x / 2;
584            scale3x3[1][1] = mParentNode->_getDerivedScale().y / 2;
585            scale3x3[2][2] = mParentNode->_getDerivedScale().z / 2;
586
587            // apply all transforms to xform       
588            *xform = (rot3x3 * scale3x3);
589            xform->setTrans(ppos);
590        }
591    }
592    //------------------------------------------------------------------------------------------------
593    void DebugContactText::getRenderOperation(RenderOperation &op)
594    {
595        if (this->isVisible())
596        {
597            if (mNeedUpdate)
598                this->_setupGeometry();
599            if (mUpdateColors)
600                this->_updateColors();
601            op = mRenderOp;
602        }
603    }
604    //------------------------------------------------------------------------------------------------
605    void DebugContactText::_notifyCurrentCamera(Camera *cam)
606    {
607        mpCam = cam;
608    }
609    //------------------------------------------------------------------------------------------------
610    void DebugContactText::_updateRenderQueue(RenderQueue* queue)
611    {
612        if (this->isVisible())
613        {
614            if (mNeedUpdate)
615                this->_setupGeometry();
616            if (mUpdateColors)
617                this->_updateColors();
618
619            queue->addRenderable(this, mRenderQueueID, OGRE_RENDERABLE_DEFAULT_PRIORITY);
620            //      queue->addRenderable(this, mRenderQueueID, RENDER_QUEUE_SKIES_LATE);
621        }
622    }
623}
Note: See TracBrowser for help on using the repository browser.