#include <Inventor/actions/SoRayPickAction.h>
SoRayPickAction - выполняет поиск пересечений луча с граф-сценой.
При поиске пересечений с лучом, полученным из координат мыши, следует обратить внимание на используемые системы координат. В OpenGL начало экраных координат находится в левом нижнем углу и ось Y направлена вверх. Если координаты мыши возвращаются в иной системе координат, то их необходимо скорректировать соответствующим образом.
Использование класса поиска пересечений я продемонстрирую на примере функции, выполняющей поиск. После небольших доработок её можно использовать в реальных проектах.
testpoint.cpp 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
// Тип объекта, пересечение с которым хотим найти. Например preferredType = SoIndexedFaceSet::getClassTypeId()
SoType preferredType;
// отбрасываем при поиске грани, повёрнутые лицевой стороной от эрана
bool testNormal = true;
// Вы можете сгруппировать несколько отдельных граней (узлом SoSeparator), чтобы они выглядели как одно цельное тело.
// Чтобы обнаружить пересечение с этим телом придётся пойти на небольшой трюк...
bool testSolid = false;
// используемая в граф-сцене камера
SoCamera * camera = 0;
// Проекция точки в экранных координатах в линию с учётом текущего положения камеры.
bool GetLine( SoNode * root, SbVec2s pos, SbLine & line )
{
// http://coin3d-ru.livejournal.com/28328.html
SoPath * path = SearchPath(root, SoCamera::getClassTypeId() );
if( !path )
return false;
// последний узел в пути это и есть искомый узел
camera = path->getTail();
// удаляем путь. Узлы, хранящиеся в пути, удалены не будут, т.к. они находятся в граф сцене и иих счётчики не обнулятся
path->unref();
if( !camera )
return false;
// получаем проекцию точки в линию
camera->getViewVolume().projectPointToLine(SbVec2f(pos[0], pos[1]), line);
return true;
}
/* SoRayPickAction
root - Узел в граф-сцене, от которого будет выполнен поиск
pos - Координаты мыши или любая другая точка в экранных координатах
vp - Размеры окна. Получается из текущего вьювера методом getViewportRegion()
line - линия, направленная от "глаз" в глубину экрана. Используется для проверки ориентации проверяемых граней, если это нужно
*/
SoPath * TestPoint( SoNode * root, SbVec2s pos, SbViewportRegion const & vp, const SbVec3f * line )
{
// Если фильтр хочется отключить, его можно отключить
if( filter
|