1 /**************************************************************************\
2 * Copyright (c) Kongsberg Oil & Gas Technologies AS
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * Neither the name of the copyright holder nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32
33 /*!
34 \class SbCylinderSheetProjector SbCylinderSheetProjector.h Inventor/projectors/SbCylinderSheetProjector.h
35 \brief The SbCylinderSheetProjector class projects 2D points to 3D points on a sheet covering a cylindrical shape.
36
37 \ingroup projectors
38 */
39
40 // FIXME: we do not use a hyperbolic sheet, as we're supposed to do,
41 // for this class. Instead we use a straight plane. This should hardly
42 // be noticable for the user, but for correctness, a hyperbolic sheet
43 // should of course be used. 20000308 mortene.
44
45 #include <Inventor/projectors/SbCylinderSheetProjector.h>
46 #include <cfloat> // FLT_EPSILON
47
48 #if COIN_DEBUG
49 #include <Inventor/errors/SoDebugError.h>
50 #endif // COIN_DEBUG
51
52 /*! \var SbCylinderSheetProjector::workingProjPoint
53 Last projected point, in the working space coordinate system.
54 */
55 /*! \var SbCylinderSheetProjector::planeDir
56 Normal vector of the plane defining the orientation of the sheet.
57 */
58 /*! \var SbCylinderSheetProjector::tolPlane
59 The tolerance value specifying how much of the cylinder is "above"
60 the sheet.
61 */
62
63
64 /*!
65 Constructor. Uses default cylinder defintion, see
66 SbCylinderProjector::SbCylinderProjector().
67
68 \a orienttoeye decides whether or not the cylinder and sheet should
69 always be oriented towards the viewer.
70 */
SbCylinderSheetProjector(const SbBool orienttoeye)71 SbCylinderSheetProjector::SbCylinderSheetProjector(const SbBool orienttoeye)
72 : inherited(orienttoeye)
73 {
74 }
75
76 /*!
77 Constructor with explicit definition of projection cylinder.
78 */
SbCylinderSheetProjector(const SbCylinder & cyl,const SbBool orienttoeye)79 SbCylinderSheetProjector::SbCylinderSheetProjector(const SbCylinder & cyl,
80 const SbBool orienttoeye)
81 : inherited(cyl, orienttoeye)
82 {
83 }
84
85 // Documented in superclass.
86 SbProjector *
copy(void) const87 SbCylinderSheetProjector::copy(void) const
88 {
89 return new SbCylinderSheetProjector(*this);
90 }
91
92 // Documented in superclass.
93 SbVec3f
project(const SbVec2f & point)94 SbCylinderSheetProjector::project(const SbVec2f & point)
95 {
96 if (this->needSetup) this->setupPlane();
97
98 SbLine projline = this->getWorkingLine(point);
99 SbVec3f projpt;
100
101 // FIXME: add code to intersect hyperbolic sheet (see code in
102 // SbSphereSheetProjector).
103 //
104 // Here's a complete, stand-alone example that can be used while
105 // testing projection. It projects a grid on top of the
106 // SbCylinderSheetProjector and spits out an iv-file with an
107 // SoPointSet that shows off how the sheet will look:
108 //
109 //
110 // -----8<--- [snip] -----8<--- [snip] -----8<--- [snip] ---
111 // #include <cstdio>
112 // #include <Inventor/SbLinear.h>
113 // #include <Inventor/projectors/SbCylinderSheetProjector.h>
114 // #include <Inventor/SoDB.h>
115 //
116 // int
117 // main(void)
118 // {
119 // SoDB::init();
120 //
121 // const float START = 0.0f;
122 // const float END = 1.0f;
123 // const float STEPS = 50.0f;
124 // const float STEPSIZE = ((END - START) / STEPS);
125 //
126 // SbCylinderSheetProjector ssp;
127 //
128 // SbViewVolume volume;
129 // volume.ortho(-1, 1, -1, 1, -1, 1);
130 // ssp.setViewVolume(volume);
131 //
132 // (void)fprintf(stdout, "#Inventor V2.1 ascii\n\n"
133 // "Separator {\n"
134 // " Coordinate3 {\n"
135 // " point [\n");
136 //
137 // for (float i=START; i <= END; i += STEPSIZE) {
138 // for (float j=START; j <= END; j += STEPSIZE) {
139 // SbVec3f v = ssp.project(SbVec2f(j, i));
140 // (void)fprintf(stdout, "\t%f %f %f,\n", v[0], v[1], v[2]);
141 // }
142 // }
143 //
144 // (void)fprintf(stdout, " ]\n"
145 // " }\n"
146 // " DrawStyle { pointSize 2 }\n"
147 // " PointSet { }\n"
148 // "}\n");
149 //
150 // return 0;
151 // }
152 // -----8<--- [snip] -----8<--- [snip] -----8<--- [snip] ---
153
154 SbBool tst = this->intersectCylinderFront(projline, projpt);
155 if (!tst) {
156 if (!this->tolPlane.intersect(projline, projpt)) {
157 #if COIN_DEBUG
158 SoDebugError::postWarning("SbCylinderSheetProjector::project",
159 "working line is parallel to cylinder axis.");
160 #endif // COIN_DEBUG
161 return SbVec3f(0.0f, 0.0f, 0.0f);
162 }
163 }
164 this->lastPoint = projpt;
165 this->workingProjPoint = projpt; // FIXME: investigate (pederb)
166 return projpt;
167 }
168
169 // Documented in superclass.
170 SbRotation
getRotation(const SbVec3f & point1,const SbVec3f & point2)171 SbCylinderSheetProjector::getRotation(const SbVec3f & point1,
172 const SbVec3f & point2)
173 {
174 const SbLine & axis = this->cylinder.getAxis();
175 SbVec3f v1 = point1 - axis.getClosestPoint(point1);
176 SbVec3f v2 = point2 - axis.getClosestPoint(point2);
177 SbRotation rot(v1, v2); // rotate vector v1 into vector v2
178
179 // FIXME: add rotation from sheet (pederb)
180
181 SbVec3f dummy;
182 float angle;
183 rot.getValue(dummy, angle);
184
185 if (dummy.dot(axis.getDirection()) > 0.0f)
186 return SbRotation(axis.getDirection(), angle);
187 return SbRotation(axis.getDirection(), -angle);
188 }
189
190 /*!
191 Recalculates projection surface settings after changes to the
192 parameters.
193 */
194 void
setupPlane(void)195 SbCylinderSheetProjector::setupPlane(void)
196 {
197 const SbLine & axis = this->cylinder.getAxis();
198 SbVec3f refDir;
199 if (this->orientToEye) {
200 refDir = -this->viewVol.getProjectionDirection();
201 this->worldToWorking.multDirMatrix(refDir, refDir);
202 }
203 else {
204 refDir = SbVec3f(0.0f, 0.0f, 1.0f);
205 }
206 SbVec3f somePt = axis.getPosition() + refDir;
207 SbVec3f ptOnAxis = axis.getClosestPoint(somePt);
208
209 this->planeDir = somePt - ptOnAxis;
210
211 if (this->planeDir.normalize() < FLT_EPSILON) {
212 // the cylinder axis is parallel to the view direction. This is a
213 // special case, and not really supported by the projector. Just
214 // create a tilted plane to make it possible to rotate the
215 // cylinder even for this case.
216 this->planeDir = this->viewVol.getViewUp() +
217 this->viewVol.getProjectionDirection();
218 this->worldToWorking.multDirMatrix(this->planeDir, this->planeDir);
219 (void) this->planeDir.normalize();
220 }
221
222 if (!this->intersectFront) this->planeDir = -this->planeDir;
223
224 this->tolPlane = SbPlane(this->planeDir, axis.getPosition());
225 this->needSetup = FALSE;
226 }
227