[go: up one dir, main page]

File: Collision.cpp

package info (click to toggle)
coin3 3.1.3-1
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 48,344 kB
  • ctags: 70,042
  • sloc: cpp: 314,328; ansic: 15,927; sh: 13,635; makefile: 8,780; perl: 2,149; lex: 1,302; lisp: 1,247; yacc: 184; xml: 175; sed: 68
file content (257 lines) | stat: -rw-r--r-- 9,211 bytes parent folder | download | duplicates (2)
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
/**************************************************************************\
 *
 *  This file is part of the Coin 3D visualization library.
 *  Copyright (C) by Kongsberg Oil & Gas Technologies.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  ("GPL") version 2 as published by the Free Software Foundation.
 *  See the file LICENSE.GPL at the root directory of this source
 *  distribution for additional information about the GNU GPL.
 *
 *  For using Coin with software that can not be combined with the GNU
 *  GPL, and for taking advantage of the additional benefits of our
 *  support services, please contact Kongsberg Oil & Gas Technologies
 *  about acquiring a Coin Professional Edition License.
 *
 *  See http://www.coin3d.org/ for more information.
 *
 *  Kongsberg Oil & Gas Technologies, Bygdoy Alle 5, 0257 Oslo, NORWAY.
 *  http://www.sim.no/  sales@sim.no  coin-support@coin3d.org
 *
\**************************************************************************/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif // HAVE_CONFIG_H

#ifdef HAVE_VRML97

/*!
  \class SoVRMLCollision SoVRMLCollision.h Inventor/VRMLnodes/SoVRMLCollision.h
  \brief The SoVRMLCollision class is used for collision detection with the avatar.
  \ingroup VRMLnodes

  \WEB3DCOPYRIGHT

  \verbatim
  Collision {
    eventIn      MFNode   addChildren
    eventIn      MFNode   removeChildren
    exposedField MFNode   children        []
    exposedField SFBool   collide         TRUE
    field        SFVec3f  bboxCenter      0 0 0      # (-,)
    field        SFVec3f  bboxSize        -1 -1 -1   # (0,) or -1,-1,-1
    field        SFNode   proxy           NULL
    eventOut     SFTime   collideTime
  }
  \endverbatim

  The Collision node is a grouping node that specifies the collision
  detection properties for its children (and their descendants),
  specifies surrogate objects that replace its children during
  collision detection, and sends events signalling that a collision
  has occurred between the avatar and the Collision node's geometry or
  surrogate. By default, all geometric nodes in the scene are
  collidable with the viewer except IndexedLineSet, PointSet, and
  Text. Browsers shall detect geometric collisions between the avatar
  (see SoVRMLNavigationInfo) and the scene's geometry and prevent the
  avatar from 'entering' the geometry. See 4.13.4, Collision detection
  and terrain following
  (<http://www.web3d.org/x3d/specifications/vrml/ISO-IEC-14772-VRML97/part1/concepts.html#4.13.4>),
  for general information on collision detection.

  If there are no Collision nodes specified in a VRML file, browsers
  shall detect collisions between the avatar and all objects during
  navigation.

  Subclause 4.6.5, Grouping and children nodes
  (<http://www.web3d.org/x3d/specifications/vrml/ISO-IEC-14772-VRML97/part1/concepts.html#4.6.5>),
  contains a description of the children, addChildren, and
  removeChildren fields and eventIns.

  The Collision node's collide field enables and disables collision
  detection. If collide is set to FALSE, the children and all
  descendants of the Collision node shall not be checked for
  collision, even though they are drawn. This includes any descendent
  Collision nodes that have collide set to TRUE (i.e., setting collide
  to FALSE turns collision off for every node below it).

  Collision nodes with the collide field set to TRUE detect the
  nearest collision with their descendent geometry (or proxies). When
  the nearest collision is detected, the collided Collision node sends
  the time of the collision through its collideTime eventOut. If a
  Collision node contains a child, descendant, or proxy (see below)
  that is a Collision node, and both Collision nodes detect that a
  collision has occurred, both send a collideTime event at the same
  time. A collideTime event shall be generated if the avatar is
  colliding with collidable geometry when the Collision node is read
  from a VRML file or inserted into the transformation hierarchy.

  The bboxCenter and bboxSize fields specify a bounding box that
  encloses the Collision node's children. This is a hint that may be
  used for optimization purposes. The results are undefined if the
  specified bounding box is smaller than the actual bounding box of
  the children at any time. A default bboxSize value, (-1, -1, -1),
  implies that the bounding box is not specified and if needed shall
  be calculated by the browser. More details on the bboxCenter and
  bboxSize fields can be found in 4.6.4, Bounding boxes.
  (<http://www.web3d.org/x3d/specifications/vrml/ISO-IEC-14772-VRML97/part1/concepts.html#4.6.4>),

  The collision proxy, defined in the proxy field, is any legal
  children node as described in 4.6.5, Grouping and children nodes,
  (<http://www.web3d.org/x3d/specifications/vrml/ISO-IEC-14772-VRML97/part1/concepts.html#4.6.5>),
  that is used as a substitute for the Collision node's children
  during collision detection. The proxy is used strictly for collision
  detection; it is not drawn.  If the value of the collide field is
  TRUE and the proxy field is non-NULL, the proxy field defines the
  scene on which collision detection is performed. If the proxy value
  is NULL, collision detection is performed against the children of
  the Collision node.  If proxy is specified, any descendent children
  of the Collision node are ignored during collision detection. If
  children is empty, collide is TRUE, and proxy is specified,
  collision detection is performed against the proxy but nothing is
  displayed. In this manner, invisible collision objects may be
  supported.

  The collideTime eventOut generates an event specifying the time when
  the avatar (see SoVRMLNavigationInfo) makes contact with the
  collidable children or proxy of the Collision node.  An ideal
  implementation computes the exact time of collision. Implementations
  may approximate the ideal by sampling the positions of collidable
  objects and the user. The SoVRMLNavigationInfo node contains additional
  information for parameters that control the avatar size.
*/

/*!
  \var SoSFBool SoVRMLCollision::collide
  Enable/disable collision.
*/

/*!
  \var SoSFNode SoVRMLCollision::proxy
  Proxy node(s) used for collision testing.
*/

/*!
  \var SoSFTime SoVRMLCollision::collideTime

  An eventOut sent for each collision that occurs.
*/

#include <Inventor/VRMLnodes/SoVRMLCollision.h>

#include <Inventor/VRMLnodes/SoVRMLMacros.h>
#include <Inventor/actions/SoGLRenderAction.h>
#include <Inventor/misc/SoState.h>
#include <Inventor/misc/SoChildList.h>
#include <Inventor/elements/SoCacheElement.h>

#include "nodes/SoSubNodeP.h"
#include "profiler/SoNodeProfiling.h"

SO_NODE_SOURCE(SoVRMLCollision);

// Doc in parent
void
SoVRMLCollision::initClass(void) // static
{
  SO_NODE_INTERNAL_INIT_CLASS(SoVRMLCollision, SO_VRML97_NODE_TYPE);
}

/*!
  Constructor.
*/
SoVRMLCollision::SoVRMLCollision(void)
{
  this->commonConstructor();
}

/*!
  Constructor. \a numchildren is the expected number of children.
*/
SoVRMLCollision::SoVRMLCollision(int numchildren)
  : inherited(numchildren)
{
  this->commonConstructor();
}

void
SoVRMLCollision::commonConstructor(void)
{
  SO_VRMLNODE_INTERNAL_CONSTRUCTOR(SoVRMLCollision);

  SO_VRMLNODE_ADD_EXPOSED_FIELD(collide, (TRUE));
  SO_VRMLNODE_ADD_FIELD(proxy, (NULL));

  SO_VRMLNODE_ADD_EVENT_OUT(collideTime);
}

/*!
  Destructor.
*/
SoVRMLCollision::~SoVRMLCollision() // virtual, protected
{
}

// Doc in parent
void
SoVRMLCollision::GLRender(SoGLRenderAction * action)
{
  SoState * state = action->getState();
  state->push();

  int numindices;
  const int * indices;
  SoAction::PathCode pathcode = action->getPathCode(numindices, indices);

  SoNode ** childarray = (SoNode**) this->getChildren()->getArrayPtr();

  if (pathcode == SoAction::IN_PATH) {
    int lastchild = indices[numindices - 1];
    for (int i = 0; i <= lastchild && !action->hasTerminated(); i++) {
      SoNode * child = childarray[i];
      action->pushCurPath(i, child);
      if (action->getCurPathCode() != SoAction::OFF_PATH ||
          child->affectsState()) {
        if (!action->abortNow()) {
          SoNodeProfiling profiling;
          profiling.preTraversal(action);
          child->GLRender(action);
          profiling.postTraversal(action);
        }
        else {
          SoCacheElement::invalidate(state);
        }
      }
      action->popCurPath(pathcode);
    }
  }
  else {
    action->pushCurPath();
    int n = this->getChildren()->getLength();
    for (int i = 0; i < n && !action->hasTerminated(); i++) {
      action->popPushCurPath(i, childarray[i]);
      if (action->abortNow()) {
        // only cache if we do a full traversal
        SoCacheElement::invalidate(state);
        break;
      }
      SoNodeProfiling profiling;
      profiling.preTraversal(action);
      childarray[i]->GLRender(action);
      profiling.postTraversal(action);
    }
    action->popCurPath();
  }
  state->pop();
}

// Doc in parent
void
SoVRMLCollision::notify(SoNotList * list)
{
  inherited::notify(list);
}

#endif // HAVE_VRML97