]> git.mxchange.org Git - simgear.git/blob - simgear/bvh/BVHLineSegmentVisitor.cxx
bvh: Move the basic bounding volume tree functionality into core.
[simgear.git] / simgear / bvh / BVHLineSegmentVisitor.cxx
1 // Copyright (C) 2008 - 2009  Mathias Froehlich - Mathias.Froehlich@web.de
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Library General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16 //
17
18 #ifdef HAVE_CONFIG_H
19 #  include <simgear_config.h>
20 #endif
21
22 #include "BVHLineSegmentVisitor.hxx"
23
24 #include <simgear/math/SGGeometry.hxx>
25
26 #include "BVHVisitor.hxx"
27
28 #include "BVHNode.hxx"
29 #include "BVHGroup.hxx"
30 #include "BVHTransform.hxx"
31 #include "BVHMotionTransform.hxx"
32 #include "BVHLineGeometry.hxx"
33 #include "BVHStaticGeometry.hxx"
34
35 #include "BVHStaticData.hxx"
36
37 #include "BVHStaticNode.hxx"
38 #include "BVHStaticTriangle.hxx"
39 #include "BVHStaticBinary.hxx"
40
41 namespace simgear {
42
43 void
44 BVHLineSegmentVisitor::apply(BVHGroup& group)
45 {
46     if (!intersects(_lineSegment, group.getBoundingSphere()))
47         return;
48     group.traverse(*this);
49 }
50     
51 void
52 BVHLineSegmentVisitor::apply(BVHTransform& transform)
53 {
54     if (!intersects(_lineSegment, transform.getBoundingSphere()))
55         return;
56     
57     bool haveHit = _haveHit;
58     _haveHit = false;
59     
60     // Push the line segment
61     SGLineSegmentd lineSegment = getLineSegment();
62     _lineSegment = transform.lineSegmentToLocal(lineSegment);
63     
64     transform.traverse(*this);
65     
66     if (_haveHit) {
67         _linearVelocity = transform.vecToWorld(_linearVelocity);
68         _angularVelocity = transform.vecToWorld(_angularVelocity);
69         SGVec3d point(transform.ptToWorld(_lineSegment.getEnd()));
70         _lineSegment.set(lineSegment.getStart(), point);
71         _normal = transform.vecToWorld(_normal);
72     } else {
73         _lineSegment = lineSegment;
74         _haveHit = haveHit;
75     }
76 }
77
78 void
79 BVHLineSegmentVisitor::apply(BVHMotionTransform& transform)
80 {
81     if (!intersects(_lineSegment, transform.getBoundingSphere()))
82         return;
83     
84     bool haveHit = _haveHit;
85     _haveHit = false;
86
87     // Push the line segment
88     SGLineSegmentd lineSegment = getLineSegment();
89     SGMatrixd toLocal = transform.getToLocalTransform(_time);
90     _lineSegment = lineSegment.transform(toLocal);
91     
92     transform.traverse(*this);
93     
94     if (_haveHit) {
95         SGMatrixd toWorld = transform.getToWorldTransform(_time);
96         SGVec3d localStart = _lineSegment.getStart();
97         _linearVelocity += transform.getLinearVelocityAt(localStart);
98         _angularVelocity += transform.getAngularVelocity();
99         _linearVelocity = toWorld.xformVec(_linearVelocity);
100         _angularVelocity = toWorld.xformVec(_angularVelocity);
101         SGVec3d localEnd = _lineSegment.getEnd();
102         _lineSegment.set(lineSegment.getStart(), toWorld.xformPt(localEnd));
103         _normal = toWorld.xformVec(_normal);
104         if (!_id)
105             _id = transform.getId();
106     } else {
107         _lineSegment = lineSegment;
108         _haveHit = haveHit;
109     }
110 }
111
112 void
113 BVHLineSegmentVisitor::apply(BVHLineGeometry&)
114 {
115 }
116     
117 void
118 BVHLineSegmentVisitor::apply(BVHStaticGeometry& node)
119 {
120     if (!intersects(_lineSegment, node.getBoundingSphere()))
121         return;
122     node.traverse(*this);
123 }
124
125 void
126 BVHLineSegmentVisitor::apply(const BVHStaticBinary& node,
127                              const BVHStaticData& data)
128 {
129     if (!intersects(SGLineSegmentf(_lineSegment), node.getBoundingBox()))
130         return;
131     
132     // The first box to enter is the one the startpoint is in.
133     // this increases the probability, that on exit of that box we do not
134     // even need to walk the other one, since the line segment is
135     // then already short enough to not intersect the other one anymore.
136     node.traverse(*this, data, _lineSegment.getStart());
137 }
138
139 void
140 BVHLineSegmentVisitor::apply(const BVHStaticTriangle& triangle,
141                              const BVHStaticData& data)
142 {
143     SGTrianglef tri = triangle.getTriangle(data);
144     SGVec3f point;
145     if (!intersects(point, tri, SGLineSegmentf(_lineSegment), 1e-4f))
146         return;
147     setLineSegmentEnd(SGVec3d(point));
148     _normal = SGVec3d(tri.getNormal());
149     _linearVelocity = SGVec3d::zeros();
150     _angularVelocity = SGVec3d::zeros();
151     _material = data.getMaterial(triangle.getMaterialIndex());
152     _id = 0;
153     _haveHit = true;
154 }
155
156
157 }