File: CollisionModel.h

package info (click to toggle)
sofa-framework 1.0~beta4-11
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 88,820 kB
  • ctags: 27,300
  • sloc: cpp: 151,126; ansic: 2,387; xml: 581; sh: 417; makefile: 68
file content (395 lines) | stat: -rw-r--r-- 16,266 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                              SOFA :: Framework                              *
*                                                                             *
* Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
* H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
* M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#ifndef SOFA_CORE_COLLISIONMODEL_H
#define SOFA_CORE_COLLISIONMODEL_H

#include <vector>
#include <sofa/core/objectmodel/BaseObject.h>
#include <sofa/core/CollisionElement.h>


namespace sofa
{

namespace core
{

/**
 *  \brief Abstract CollisionModel interface.
 *
 *  A CollisionModel contains a list of same-type elements. It can be part of a
 *  list of CollisionModels, each describing a level in a bounding-volume
 *  hierarchy.
 *
 *  Each CollisionModel stores a pointer to the next model in the hierarchy
 *  (i.e. finer / lower / child level) as well as the previous model (i.e.
 *  coarser / upper / parent level). The first CollisionModel in this list is
 *  the root of the hierarchy and contains only one element. The last
 *  CollisionModel contains the leaves of the hierarchy which are the real
 *  elements of the object.
 *
 *  Each element inside CollisionModels except for the last one can have a list
 *  of children. There are 2 types of child elements:
 *  \li internal children: child elements of the same type as their parent (often
 *    corresponding to non-final elements)
 *  \li external children: child elements of a different type (often corresponding
 *    to the final elements) 
 *
 */
class SOFA_CORE_API CollisionModel : public virtual objectmodel::BaseObject
{
public:

    typedef CollisionElementIterator Iterator;
    typedef componentmodel::topology::BaseMeshTopology Topology;

    /// Constructor
    CollisionModel()
    : bActive(initData(&bActive, true, "active", "flag indicating if this collision model is active and should be included in default collision detections"))
    , bMoving(initData(&bMoving, true, "moving", "flag indicating if this object is changing position between iterations"))
    , bSimulated(initData(&bSimulated, true, "simulated", "flag indicating if this object is controlled by a simulation"))
    , bSelfCollision(initData(&bSelfCollision, false, "selfCollision", "flag indication if the object can self collide"))
    , proximity(initData(&proximity, 0.0, "proximity", "Distance to the actual (visual) surface"))
    , contactStiffness(initData(&contactStiffness, 10.0, "contactStiffness", "Default contact stiffness"))
    , contactFriction(initData(&contactFriction, 0.01, "contactFriction", "Default contact friction (damping) coefficient"))
    , contactResponse(initData(&contactResponse, "contactResponse", "if set, indicate to the ContactManager that this model should use the given class of contacts.\nNote that this is only indicative, and in particular if both collision models specify a different class it is up to the manager to choose."))
    , group(initData(&group, 0, "group", "If not zero, ID of a group containing this model. No collision can occur between collision models of the same group (allowing the same object to have multiple collision models)"))
    , color(initData(&color, defaulttype::Vec4f(1,0,0,1), "color", "color used to display the collision model if requested"))
    , size(0), previous(NULL)  , next(NULL), numberOfContacts(0)
    {
    }

    virtual void bwdInit()
    {
      getColor4f(); //init the color to default value
    }
    /// Destructor
    virtual ~CollisionModel() { }    
    
    /// Return true if there are no elements
    bool empty() const
    {
        return size==0;
    }

    /// Get the number of elements.
    int getSize() const
    {
        return size;
    }

	/// Get the number of contacts attached to the collision model
	int getNumberOfContacts() const
	{
		return numberOfContacts;
	}

	/// Set the number of contacts attached to the collision model
	void setNumberOfContacts(int i)
	{
		numberOfContacts = i;
	}

    /// Set the number of elements.
    virtual void resize(int s)
    {
        size = s;
    }

    /// Return an iterator to the first element.
    Iterator begin()
    {
        return Iterator(this,0);
    }

    /// Return an iterator pointing after the last element.
    Iterator end()
    {
        return Iterator(this,size);
    }

    /// Return the next (finer / lower / child level) CollisionModel in the hierarchy.
    CollisionModel* getNext()
    {
        return next;
    }

    /// Return the previous (coarser / upper / parent level) CollisionModel in the hierarchy.
    CollisionModel* getPrevious()
    {
        return previous;
    }

    /// Set the next (finer / lower / child level) CollisionModel in the hierarchy.
    void setNext(CollisionModel* val)
    {
        next = val;
    }

    /// Set the previous (coarser / upper / parent level) CollisionModel in the hierarchy.
    void setPrevious(CollisionModel* val)
    {
        previous = val;
    }

    /// \brief Return true if this CollisionModel should be used for collisions.
    ///
    /// Default to true.
    virtual bool isActive() const { return bActive.getValue() && getContext()->isActive(); }

    /// \brief Set true if this CollisionModel should be used for collisions.
    virtual void setActive(bool val=true) { bActive.setValue(val); }

    /// \brief Return true if this CollisionModel is changing position between
    /// iterations.
    ///
    /// Default to true.
    virtual bool isMoving() const { return bMoving.getValue(); }

    /// \brief Set true if this CollisionModel is changing position between
    /// iterations.
    virtual void setMoving(bool val=true) { bMoving.setValue(val); }

    /// \brief Return true if this CollisionModel is attached to a simulation.
    /// It is false for immobile or procedurally animated objects that don't
    /// use contact forces
    ///
    /// Default to true.
    virtual bool isSimulated() const { return bSimulated.getValue(); }

    /// \brief Set true if this CollisionModel is attached to a simulation.
    virtual void setSimulated(bool val=true) { bSimulated.setValue(val); }

    /// Create or update the bounding volume hierarchy.
    virtual void computeBoundingTree(int maxDepth=0) = 0;

    /// \brief Create or update the bounding volume hierarchy, accounting for motions
    /// within the given timestep.
    ///
    /// Default to computeBoundingTree().
    virtual void computeContinuousBoundingTree(double /*dt*/, int maxDepth=0) { computeBoundingTree(maxDepth); }

    /// \brief Return the list (as a pair of iterators) of <i>internal children</i> of
    /// an element.
    ///
    /// Internal children are child elements of the same type as their parent
    /// (often corresponding to non-final elements). This distinction is used
    /// to optimize the intersection tests inside the hierarchy, as internal
    /// children can be processed without dynamically retrieving a new
    /// intersection method.
    ///
    /// Default to empty (i.e. two identical iterators)
    virtual std::pair<CollisionElementIterator,CollisionElementIterator> getInternalChildren(int /*index*/) const
    {
        return std::make_pair(CollisionElementIterator(),CollisionElementIterator());
    }

    /// \brief Return the list (as a pair of iterators) of <i>external children</i> of
    /// an element.
    ///
    /// External children are child elements of a different type than their
    /// parent (often corresponding to the final elements).
    ///
    /// Default to empty (i.e. two identical iterators)
    virtual std::pair<CollisionElementIterator,CollisionElementIterator> getExternalChildren(int /*index*/) const
    {
        return std::make_pair(CollisionElementIterator(),CollisionElementIterator());
    }


    /// \brief Checks if the element(index) is a leaf and a primitive of the collision model.
    ///
    /// Default to true since triangle model, line model, etc. does not have this method implemented and they
    /// are themselves (normally) leaves and primitives
    virtual bool isLeaf( int /*index*/ ) const
    {
        return true;  //e.g. Triangle will return true 
    }


    /// \brief Test if this model can collide with another model.
    ///
    /// Note that this test is only related to <b>what</b> are the two models
    /// (i.e. which type, attached to which object) and not <b>where</b> they
    /// are in space. It is used to prune unnecessary or invalid collisions
    /// (i.e. vertices of an object should be tested with triangles of another
    /// but not the same object).
    ///
    /// Default to false if the collision models are attached to the same
    /// context (i.e. the same node in the scenegraph).
    virtual bool canCollideWith(CollisionModel* model)
    {
	if (model != this && this->group.getValue() != 0 && this->group.getValue() == model->group.getValue())
	    return false;
        else if (model->getContext() != this->getContext())
            return true;
        else return bSelfCollision.getValue();
    }
    //virtual bool canCollideWith(CollisionModel* model) { return model != this; }

    /// \brief Test if two elements can collide with each other.
    ///
    /// This method should be implemented by models supporting
    /// self-collisions to prune tests between adjacent elements.
    ///
    /// Default to true. Note that this method assumes that canCollideWith(model2)
    /// was already used to test if the collision models can collide.
    virtual bool canCollideWithElement(int /*index*/, CollisionModel* /*model2*/, int /*index2*/) { return true; }

    
    /// Render an collision element.
    virtual void draw(int /*index*/) {}
    
    /// Render the whole collision model.
    virtual void draw() {}

    /// Return the first (i.e. root) CollisionModel in the hierarchy.
    CollisionModel* getFirst()
    {
        CollisionModel *cm = this;
        CollisionModel *cm2;
        while ((cm2 = cm->getPrevious())!=NULL)
            cm = cm2;
        return cm;
    }

    /// Return the last (i.e. leaf) CollisionModel in the hierarchy.
    CollisionModel* getLast()
    {
        CollisionModel *cm = this;
        CollisionModel *cm2;
        while ((cm2 = cm->getNext())!=NULL)
                cm = cm2;
        return cm;
    }


    /// Helper method to get or create the previous model in the hierarchy.
    template<class DerivedModel>
	DerivedModel* createPrevious()
    {
      DerivedModel* pmodel = dynamic_cast<DerivedModel*>(previous);
      if (pmodel == NULL)
      {
	if (previous != NULL)
	  delete previous;
	pmodel = new DerivedModel();
	pmodel->setContext(getContext());
	pmodel->setMoving(isMoving());
	pmodel->setSimulated(isSimulated());
	pmodel->proximity.setValue(proximity.getValue());
	pmodel->group.setValue(group.getValue());
	previous = pmodel;
	pmodel->setNext(this);
      }
      return pmodel;
    }
    
    /// @name Experimental methods
    /// @{

    /// Get distance to the actual (visual) surface
    double getProximity() { return proximity.getValue(); }

    /// Get contact stiffness
    double getContactStiffness(int /*index*/) { return contactStiffness.getValue(); }
    /// Set contact stiffness
	void setContactStiffness(double stiffness) { contactStiffness.setValue(stiffness); }

    /// Get contact friction (damping) coefficient
    double getContactFriction(int /*index*/) { return contactFriction.getValue(); }
    /// Set contact friction (damping) coefficient
	void setContactFriction(double friction) { contactFriction.setValue(friction); }
    
    /// Contact response algorithm
    std::string getContactResponse() { return contactResponse.getValue(); }
    
    /// If not zero, ID of a group containing this model. No collision can occur between collision
    /// models of the same group (allowing the same object to have multiple collision models)
    int getGroup() const { return group.getValue(); }

	/// Set ID of group of this model. No collision can occur between collision
    /// models of the same group (allowing the same object to have multiple collision models)
	void setGroup(const int groupId) { group.setValue(groupId); }
    
    /// @}
    
    /// Topology associated to the collision model
    virtual Topology* getTopology() { return getContext()->getMeshTopology(); }

	/// BaseMeshTopology associated to the collision model
	virtual sofa::core::componentmodel::topology::BaseMeshTopology* getMeshTopology() { return getContext()->getMeshTopology(); }

    /// Get a color that can be used to display this CollisionModel
    const float* getColor4f();
    /// Set a color that can be used to display this CollisionModel
    void setColor4f(const float *c){color.setValue(defaulttype::Vec4f(c[0],c[1],c[2],c[3]));};
protected:
    /// flag indicating if this collision model is active and should be included in default
    /// collision detections
    Data<bool> bActive;
    ///flag indicating if this object is changing position between iterations
    Data<bool> bMoving;
    /// flag indicating if this object is controlled by a simulation
    Data<bool> bSimulated;
    /// flag indication if the object can self collide
    Data<bool> bSelfCollision;
    /// Distance to the actual (visual) surface
    Data<double> proximity;
    /// Default contact stiffness
    Data<double> contactStiffness;
    /// Default contact friction (damping) coefficient
    Data<double> contactFriction;
    /// contactResponse", "if set, indicate to the ContactManager that this model should use the
    /// given class of contacts.\nNote that this is only indicative, and in particular if both
    /// collision models specify a different class it is up to the manager to choose.
    Data<std::string> contactResponse;
    /// If not zero, ID of a group containing this model. No collision can occur between collision
    /// models of the same group (allowing the same object to have multiple collision models)
    Data<int> group;
    /// color used to display the collision model if requested
    Data<defaulttype::Vec4f> color;

    /// Number of collision elements
    int size;

    /// Pointer to the previous (coarser / upper / parent level) CollisionModel in the hierarchy.
    CollisionModel* previous;

    /// Pointer to the next (finer / lower / child level) CollisionModel in the hierarchy.
    CollisionModel* next;

	/// number of contacts attached to the collision model
	int numberOfContacts;

};

} // namespace core

} // namespace sofa

#endif