Panda3D

portalClipper.cxx
Go to the documentation of this file.
1 /**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file portalClipper.cxx
10 * @author masad
11 * @date 2004-05-04
12 */
13
14 #include "portalClipper.h"
15 #include "cullTraverser.h"
16 #include "cullTraverserData.h"
17 #include "transformState.h"
18 #include "renderState.h"
19 #include "fogAttrib.h"
20 #include "cullHandler.h"
21 #include "dcast.h"
22 #include "geomNode.h"
23 #include "config_pgraph.h"
24 #include "boundingSphere.h"
25 #include "colorAttrib.h"
26 #include "renderModeAttrib.h"
27 #include "cullFaceAttrib.h"
28 #include "depthOffsetAttrib.h"
29 #include "geomVertexWriter.h"
30 #include "geomLinestrips.h"
31 #include "geomPoints.h"
32
33 using std::endl;
34 using std::max;
35 using std::min;
36
37 TypeHandle PortalClipper::_type_handle;
38
39 /**
40 *
41 */
42 PortalClipper::
43 PortalClipper(GeometricBoundingVolume *frustum, SceneSetup *scene_setup):
44 _reduced_viewport_min(-1,-1),
45 _reduced_viewport_max(1,1),
46 _clip_state(nullptr)
47 {
48 _previous = new GeomNode("my_frustum");
49
50 _view_frustum = _reduced_frustum = DCAST(BoundingHexahedron, frustum);
51
52
53 _scene_setup = scene_setup;
54 }
55
56 /**
57 *
58 */
59 PortalClipper::
60 ~PortalClipper() {
61 }
62
63 /**
64 * Moves the pen to the given point without drawing a line. When followed by
65 * draw_to(), this marks the first point of a line segment; when followed by
66 * move_to() or create(), this creates a single point.
67 */
68 void PortalClipper::
69 move_to(const LVecBase3 &v) {
70 // We create a new SegmentList with the initial point in it.
71 SegmentList segs;
72 segs.push_back(Point(v, _color));
73
74 // And add this list to the list of segments.
75 _list.push_back(segs);
76 }
77
78 /**
79 * Draws a line segment from the pen's last position (the last call to move_to
80 * or draw_to) to the indicated point. move_to() and draw_to() only update
81 * tables; the actual drawing is performed when create() is called.
82 */
83 void PortalClipper::
84 draw_to(const LVecBase3 &v) {
85 if (_list.empty()) {
86 // Let our first call to draw_to() be an implicit move_to().
87 move_to(v);
88
89 } else {
90 // Get the current SegmentList, which was the last one we added to the
91 // LineList.
92 SegmentList &segs = _list.back();
93
94 // Add the new point.
95 segs.push_back(Point(v, _color));
96 }
97 }
98
99 /**
100 * Given the BoundingHexahedron draw it using lines
101 *
102 */
103 void PortalClipper::
104 draw_hexahedron(BoundingHexahedron *frustum) {
105 // walk the view frustum as it should be drawn
106 move_to(frustum->get_point(0));
107 draw_to(frustum->get_point(1));
108 draw_to(frustum->get_point(2));
109 draw_to(frustum->get_point(3));
110
111 move_to(frustum->get_point(4));
112 draw_to(frustum->get_point(0));
113 draw_to(frustum->get_point(3));
114 draw_to(frustum->get_point(7));
115
116 move_to(frustum->get_point(5));
117 draw_to(frustum->get_point(4));
118 draw_to(frustum->get_point(7));
119 draw_to(frustum->get_point(6));
120
121 move_to(frustum->get_point(1));
122 draw_to(frustum->get_point(5));
123 draw_to(frustum->get_point(6));
124 draw_to(frustum->get_point(2));
125 }
126 /**
127 * _portal_node is the current portal, draw it.
128 *
129 */
130 void PortalClipper::
131 draw_current_portal()
132 {
133 move_to(_portal_node->get_vertex(0));
134 draw_to(_portal_node->get_vertex(1));
135 draw_to(_portal_node->get_vertex(2));
136 draw_to(_portal_node->get_vertex(3));
137 }
138
139 /**
140 * Draw all the lines in the buffer Cyan portal is the original geometry of
141 * the portal Yellow portal is the AA minmax & clipped portal Blue frustum is
142 * the frustum through portal White frustum is the camera frustum
143 */
144 void PortalClipper::
145 draw_lines() {
146 if (!_list.empty()) {
147 _created_data = nullptr;
148
149 PT(GeomVertexData) vdata = new GeomVertexData
150 ("portal", GeomVertexFormat::get_v3cp(), Geom::UH_static);
151 GeomVertexWriter vertex(vdata, InternalName::get_vertex());
152 GeomVertexWriter color(vdata, InternalName::get_color());
153
154 PT(GeomLinestrips) lines = new GeomLinestrips(Geom::UH_static);
155 PT(GeomPoints) points = new GeomPoints(Geom::UH_static);
156
157 int v = 0;
158 LineList::const_iterator ll;
159 SegmentList::const_iterator sl;
160
161 for (ll = _list.begin(); ll != _list.end(); ll++) {
162 const SegmentList &segs = (*ll);
163
164 if (segs.size() < 2) {
165 // A segment of length 1 is just a point.
166 for (sl = segs.begin(); sl != segs.end(); sl++) {
167 points->add_vertex(v);
168 vertex.add_data3((*sl)._point);
169 color.add_data4((*sl)._color);
170 v++;
171 }
172 points->close_primitive();
173
174 } else {
175 // A segment of length 2 or more is a line segment or segments.
176 for (sl = segs.begin(); sl != segs.end(); sl++) {
177 lines->add_vertex(v);
178 vertex.add_data3((*sl)._point);
179 color.add_data4((*sl)._color);
180 v++;
181 }
182 lines->close_primitive();
183 }
184 }
185
186 if (lines->get_num_vertices() != 0) {
187 PT(Geom) geom = new Geom(vdata);
188 geom->add_primitive(lines);
189 _previous->add_geom(geom);
190 }
191 if (points->get_num_vertices() != 0) {
192 PT(Geom) geom = new Geom(vdata);
193 geom->add_primitive(points);
194 _previous->add_geom(geom);
195 }
196 }
197 }
198 /**
199 * Given the portal draw the frustum with line segs for now. More
200 * functionalities coming up
201 */
202 bool PortalClipper::
203 prepare_portal(const NodePath &node_path)
204 {
205 // Get the Portal Node from this node_path
206 PandaNode *node = node_path.node();
207 _portal_node = nullptr;
208 if (node->is_of_type(PortalNode::get_class_type())) {
209 _portal_node = DCAST(PortalNode, node);
210 }
211
212 // Get the geometry from the portal
213 portal_cat.spam() << *_portal_node << endl;
214
215 // Get the camera transformation matrix
216 CPT(TransformState) ctransform = node_path.get_transform(_scene_setup->get_cull_center());
217 // CPT(TransformState) ctransform =
218 // node_path.get_transform(_scene_setup->get_camera_path());
219 LMatrix4 cmat = ctransform->get_mat();
220 portal_cat.spam() << cmat << endl;
221
222 LVertex temp[4];
223 temp[0] = _portal_node->get_vertex(0);
224 temp[1] = _portal_node->get_vertex(1);
225 temp[2] = _portal_node->get_vertex(2);
226 temp[3] = _portal_node->get_vertex(3);
227
228 portal_cat.spam() << "before transformation to camera space" << endl;
229 portal_cat.spam() << temp[0] << endl;
230 portal_cat.spam() << temp[1] << endl;
231 portal_cat.spam() << temp[2] << endl;
232 portal_cat.spam() << temp[3] << endl;
233
234 temp[0] = temp[0]*cmat;
235 temp[1] = temp[1]*cmat;
236 temp[2] = temp[2]*cmat;
237 temp[3] = temp[3]*cmat;
238
239 LPlane portal_plane(temp[0], temp[1], temp[2]);
240 if (!is_facing_view(portal_plane)) {
241 portal_cat.debug() << "portal failed 1st level test (isn't facing the camera)\n";
242 return false;
243 }
244
245 portal_cat.spam() << "after transformation to camera space" << endl;
246 portal_cat.spam() << temp[0] << endl;
247 portal_cat.spam() << temp[1] << endl;
248 portal_cat.spam() << temp[2] << endl;
249 portal_cat.spam() << temp[3] << endl;
250
251 // check if the portal intersects with the cameras 0 point (center of
252 // projection). In that case the portal will invert itself. portals
253 // intersecting the near plane or the 0 point are a weird case anyhow,
254 // therefore we don't reduce the frustum any further and just return true.
255 // In effect the portal doesn't reduce visibility but will draw everything
256 // in its out cell
257 const Lens *lens = _scene_setup->get_lens();
258 LVector3 forward = LVector3::forward(lens->get_coordinate_system());
259 int forward_axis;
260 if (forward[1]) {
261 forward_axis = 1;
262 }
263 else if (forward[2]) {
264 forward_axis = 2;
265 }
266 else {
267 forward_axis = 0;
268 }
269 if ((temp[0][forward_axis] * forward[forward_axis] <= 0) ||
270 (temp[1][forward_axis] * forward[forward_axis] <= 0) ||
271 (temp[2][forward_axis] * forward[forward_axis] <= 0) ||
272 (temp[3][forward_axis] * forward[forward_axis] <= 0)) {
273 portal_cat.debug() << "portal intersects with center of projection.." << endl;
274 return true;
275 }
276
277 // project portal points, so they are in the -1..1 range
278 LPoint3 projected_coords[4];
279 lens->project(temp[0], projected_coords[0]);
280 lens->project(temp[1], projected_coords[1]);
281 lens->project(temp[2], projected_coords[2]);
282 lens->project(temp[3], projected_coords[3]);
283
284 portal_cat.spam() << "after projection to 2d" << endl;
285 portal_cat.spam() << projected_coords[0] << endl;
286 portal_cat.spam() << projected_coords[1] << endl;
287 portal_cat.spam() << projected_coords[2] << endl;
288 portal_cat.spam() << projected_coords[3] << endl;
289
290 // calculate axis aligned bounding box of the portal
291 PN_stdfloat min_x, max_x, min_y, max_y;
292 min_x = min(min(min(projected_coords[0][0], projected_coords[1][0]), projected_coords[2][0]), projected_coords[3][0]);
293 max_x = max(max(max(projected_coords[0][0], projected_coords[1][0]), projected_coords[2][0]), projected_coords[3][0]);
294 min_y = min(min(min(projected_coords[0][1], projected_coords[1][1]), projected_coords[2][1]), projected_coords[3][1]);
295 max_y = max(max(max(projected_coords[0][1], projected_coords[1][1]), projected_coords[2][1]), projected_coords[3][1]);
296
297 portal_cat.spam() << "min_x " << min_x << ";max_x " << max_x << ";min_y " << min_y << ";max_y " << max_y << endl;
298
299 // clip the minima and maxima against the viewport
300 min_x = max(min_x, _reduced_viewport_min[0]);
301 min_y = max(min_y, _reduced_viewport_min[1]);
302 max_x = min(max_x, _reduced_viewport_max[0]);
303 max_y = min(max_y, _reduced_viewport_max[1]);
304
305 portal_cat.spam() << "after clipping: min_x " << min_x << ";max_x " << max_x << ";min_y " << min_y << ";max_y " << max_y << endl;
306
307 if ((min_x >= max_x) || (min_y >= max_y)) {
308 portal_cat.debug() << "portal got clipped away \n";
309 return false;
310 }
311
312 // here we know the portal is in view and we have its clipped extents
313 _reduced_viewport_min.set(min_x, min_y);
314 _reduced_viewport_max.set(max_x, max_y);
315
316 // calculate the near and far points so we can construct a frustum
317 LPoint3 near_point[4];
318 LPoint3 far_point[4];
319 lens->extrude(LPoint2(min_x, min_y), near_point[0], far_point[0]);
320 lens->extrude(LPoint2(max_x, min_y), near_point[1], far_point[1]);
321 lens->extrude(LPoint2(max_x, max_y), near_point[2], far_point[2]);
322 lens->extrude(LPoint2(min_x, max_y), near_point[3], far_point[3]);
323
324 // With these points, construct the new reduced frustum
325 _reduced_frustum = new BoundingHexahedron(far_point[0], far_point[1], far_point[2], far_point[3],
326 near_point[0], near_point[1], near_point[2], near_point[3]);
327
328 portal_cat.debug() << *_reduced_frustum << endl;
329
330 // do debug rendering, if requested
331 if (debug_portal_cull) {
332 // draw the reduced frustum
333 _color = LColor(0,0,1,1);
334 draw_hexahedron(DCAST(BoundingHexahedron, _reduced_frustum));
335
336 // lets first add the clipped portal (in yellow)
337 _color = LColor(1,1,0,1);
338 move_to((near_point[0]*0.99+far_point[0]*0.01)); // I choose a point in the middle between near and far.. could also be some other z value..
339 draw_to((near_point[1]*0.99+far_point[1]*0.01));
340 draw_to((near_point[2]*0.99+far_point[2]*0.01));
341 draw_to((near_point[3]*0.99+far_point[3]*0.01));
342 draw_to((near_point[0]*0.99+far_point[0]*0.01));
343
344 // ok, now lets add the original portal (in cyan)
345 _color = LColor(0,1,1,1);
346 move_to(temp[0]);
347 draw_to(temp[1]);
348 draw_to(temp[2]);
349 draw_to(temp[3]);
350 draw_to(temp[0]);
351 }
352
353 return true;
354 }
boundingSphere.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BoundingHexahedron
This defines a bounding convex hexahedron.
Definition: boundingHexahedron.h:32
BoundingHexahedron::get_point
get_point
Returns the nth vertex of the hexahedron.
Definition: boundingHexahedron.h:60
GeomLinestrips
Defines a series of line strips.
Definition: geomLinestrips.h:23
GeomNode
A node that holds Geom objects, renderable pieces of geometry.
Definition: geomNode.h:34
GeomPoints
Defines a series of disconnected points.
Definition: geomPoints.h:23
GeomVertexData
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
Definition: geomVertexData.h:68
GeomVertexFormat::get_v3cp
static const GeomVertexFormat * get_v3cp()
Returns a standard vertex format with a packed color and a 3-component vertex position.
Definition: geomVertexFormat.I:287
GeomVertexWriter
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
Definition: geomVertexWriter.h:55
GeomVertexWriter::add_data4
void add_data4(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat w)
Sets the write row to a particular 4-component value, and advances the write row.
Definition: geomVertexWriter.I:1164
GeomVertexWriter::add_data3
void add_data3(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the write row to a particular 3-component value, and advances the write row.
Definition: geomVertexWriter.I:1132
Geom
A container for geometry primitives.
Definition: geom.h:54
GeometricBoundingVolume
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
Definition: geometricBoundingVolume.h:29
Lens
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:41
Lens::project
bool project(const LPoint3 &point3d, LPoint3 &point2d) const
Given a 3-d point in space, determine the 2-d point this maps to, in the range (-1,...
Definition: lens.I:131
Lens::extrude
bool extrude(const LPoint2 &point2d, LPoint3 &near_point, LPoint3 &far_point) const
Given a 2-d point in the range (-1,1) in both dimensions, where (0,0) is the center of the lens and (...
Definition: lens.I:24
Lens::get_coordinate_system
get_coordinate_system
Returns the coordinate system that all 3-d computations are performed within for this Lens.
Definition: lens.h:74
NodePath
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:159
NodePath::node
PandaNode * node() const
Returns the referenced node of the path.
Definition: nodePath.I:227
NodePath::get_transform
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
Definition: nodePath.cxx:791
PandaNode
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
PortalClipper::move_to
void move_to(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Moves the pen to the given point without drawing a line.
Definition: portalClipper.I:56
PortalClipper::draw_current_portal
void draw_current_portal()
_portal_node is the current portal, draw it.
Definition: portalClipper.cxx:131
PortalClipper::is_facing_view
bool is_facing_view(const LPlane &portal_plane)
checks if the portal plane (in camera space) is facing the camera's near plane
Definition: portalClipper.I:142
PortalClipper::draw_hexahedron
void draw_hexahedron(BoundingHexahedron *frustum)
Given the BoundingHexahedron draw it using lines.
Definition: portalClipper.cxx:104
PortalClipper::draw_to
void draw_to(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Draws a line segment from the pen's last position (the last call to move_to or draw_to) to the indica...
Definition: portalClipper.I:66
PortalClipper::draw_lines
void draw_lines()
Draw all the lines in the buffer Cyan portal is the original geometry of the portal Yellow portal is ...
Definition: portalClipper.cxx:145
PortalClipper::prepare_portal
bool prepare_portal(const NodePath &node_path)
Given the portal draw the frustum with line segs for now.
Definition: portalClipper.cxx:203
PortalNode
A node in the scene graph that can hold a Portal Polygon, which is a rectangle.
Definition: portalNode.h:30
PortalNode::get_vertex
get_vertex
Returns the nth vertex of the portal polygon.
Definition: portalNode.h:67
SceneSetup
This object holds the camera position, etc., and other general setup information for rendering a part...
Definition: sceneSetup.h:32
SceneSetup::get_lens
const Lens * get_lens() const
Returns the particular Lens used for rendering.
Definition: sceneSetup.I:131
SceneSetup::get_cull_center
const NodePath & get_cull_center() const
Returns the point from which the culling operations will be performed.
Definition: sceneSetup.I:161
TransformState
Indicates a coordinate-system transform on vertices.
Definition: transformState.h:54
TransformState::get_mat
get_mat
Returns the matrix that describes the transform.
Definition: transformState.h:156
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
TypedObject::is_of_type
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28
pvector
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
colorAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
config_pgraph.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
cullFaceAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
cullHandler.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
cullTraverserData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
cullTraverser.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
dcast.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
depthOffsetAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
fogAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomLinestrips.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomPoints.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomVertexWriter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
portalClipper.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
renderModeAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
renderState.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
transformState.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.