Panda3D
Loading...
Searching...
No Matches
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
33using std::endl;
34using std::max;
35using std::min;
36
37TypeHandle PortalClipper::_type_handle;
38
39/**
40 *
41 */
42PortalClipper::
43PortalClipper(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 */
59PortalClipper::
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 */
69move_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 */
84draw_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 */
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 */
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 */
145draw_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 */
203prepare_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}
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This defines a bounding convex hexahedron.
get_point
Returns the nth vertex of the hexahedron.
Defines a series of line strips.
A node that holds Geom objects, renderable pieces of geometry.
Definition geomNode.h:34
Defines a series of disconnected points.
Definition geomPoints.h:23
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
static const GeomVertexFormat * get_v3cp()
Returns a standard vertex format with a packed color and a 3-component vertex position.
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
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.
A container for geometry primitives.
Definition geom.h:54
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
A base class for any number of different kinds of lenses, linear and otherwise.
Definition lens.h:41
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
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
get_coordinate_system
Returns the coordinate system that all 3-d computations are performed within for this Lens.
Definition lens.h:74
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition nodePath.h:159
PandaNode * node() const
Returns the referenced node of the path.
Definition nodePath.I:227
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
Definition nodePath.cxx:794
A basic node of the scene graph or data graph.
Definition pandaNode.h:65
void move_to(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Moves the pen to the given point without drawing a line.
void draw_current_portal()
_portal_node is the current portal, draw it.
bool is_facing_view(const LPlane &portal_plane)
checks if the portal plane (in camera space) is facing the camera's near plane
void draw_hexahedron(BoundingHexahedron *frustum)
Given the BoundingHexahedron draw it using lines.
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...
void draw_lines()
Draw all the lines in the buffer Cyan portal is the original geometry of the portal Yellow portal is ...
bool prepare_portal(const NodePath &node_path)
Given the portal draw the frustum with line segs for now.
A node in the scene graph that can hold a Portal Polygon, which is a rectangle.
Definition portalNode.h:30
get_vertex
Returns the nth vertex of the portal polygon.
Definition portalNode.h:67
This object holds the camera position, etc., and other general setup information for rendering a part...
Definition sceneSetup.h:32
const Lens * get_lens() const
Returns the particular Lens used for rendering.
Definition sceneSetup.I:131
const NodePath & get_cull_center() const
Returns the point from which the culling operations will be performed.
Definition sceneSetup.I:161
Indicates a coordinate-system transform on vertices.
get_mat
Returns the matrix that describes the transform.
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition typedObject.I:28
This is our own Panda specialization on the default STL vector.
Definition pvector.h:42
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.