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
33 using std::endl;
34 using std::max;
35 using std::min;
36
37 TypeHandle 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 */
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_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:794
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
SceneSetup
This object holds the camera position, etc., and other general setup information for rendering a part...
Definition sceneSetup.h:32
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:168
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
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.