00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "portalClipper.h"
00016 #include "cullTraverser.h"
00017 #include "cullTraverserData.h"
00018 #include "transformState.h"
00019 #include "renderState.h"
00020 #include "fogAttrib.h"
00021 #include "cullHandler.h"
00022 #include "dcast.h"
00023 #include "geomNode.h"
00024 #include "config_pgraph.h"
00025 #include "boundingSphere.h"
00026 #include "colorAttrib.h"
00027 #include "renderModeAttrib.h"
00028 #include "cullFaceAttrib.h"
00029 #include "depthOffsetAttrib.h"
00030 #include "geomVertexWriter.h"
00031 #include "geomLinestrips.h"
00032 #include "geomPoints.h"
00033
00034 TypeHandle PortalClipper::_type_handle;
00035
00036
00037
00038
00039
00040
00041 PortalClipper::
00042 PortalClipper(GeometricBoundingVolume *frustum, SceneSetup *scene_setup):
00043 _reduced_viewport_min(-1,-1),
00044 _reduced_viewport_max(1,1),
00045 _clip_state(0)
00046 {
00047 _previous = new GeomNode("my_frustum");
00048
00049 _view_frustum = _reduced_frustum = DCAST(BoundingHexahedron, frustum);
00050
00051
00052 _scene_setup = scene_setup;
00053 }
00054
00055
00056
00057
00058
00059
00060 PortalClipper::
00061 ~PortalClipper() {
00062 }
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 void PortalClipper::
00073 move_to(const LVecBase3 &v) {
00074
00075 SegmentList segs;
00076 segs.push_back(Point(v, _color));
00077
00078
00079 _list.push_back(segs);
00080 }
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 void PortalClipper::
00092 draw_to(const LVecBase3 &v) {
00093 if (_list.empty()) {
00094
00095 move_to(v);
00096
00097 } else {
00098
00099
00100 SegmentList &segs = _list.back();
00101
00102
00103 segs.push_back(Point(v, _color));
00104 }
00105 }
00106
00107
00108
00109
00110
00111
00112
00113 void PortalClipper::
00114 draw_hexahedron(BoundingHexahedron *frustum) {
00115
00116 move_to(frustum->get_point(0));
00117 draw_to(frustum->get_point(1));
00118 draw_to(frustum->get_point(2));
00119 draw_to(frustum->get_point(3));
00120
00121 move_to(frustum->get_point(4));
00122 draw_to(frustum->get_point(0));
00123 draw_to(frustum->get_point(3));
00124 draw_to(frustum->get_point(7));
00125
00126 move_to(frustum->get_point(5));
00127 draw_to(frustum->get_point(4));
00128 draw_to(frustum->get_point(7));
00129 draw_to(frustum->get_point(6));
00130
00131 move_to(frustum->get_point(1));
00132 draw_to(frustum->get_point(5));
00133 draw_to(frustum->get_point(6));
00134 draw_to(frustum->get_point(2));
00135 }
00136
00137
00138
00139
00140
00141
00142 void PortalClipper::
00143 draw_current_portal()
00144 {
00145 move_to(_portal_node->get_vertex(0));
00146 draw_to(_portal_node->get_vertex(1));
00147 draw_to(_portal_node->get_vertex(2));
00148 draw_to(_portal_node->get_vertex(3));
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 void PortalClipper::
00161 draw_lines() {
00162 if (!_list.empty()) {
00163 _created_data = NULL;
00164
00165 PT(GeomVertexData) vdata = new GeomVertexData
00166 ("portal", GeomVertexFormat::get_v3cp(), Geom::UH_static);
00167 GeomVertexWriter vertex(vdata, InternalName::get_vertex());
00168 GeomVertexWriter color(vdata, InternalName::get_color());
00169
00170 PT(GeomLinestrips) lines = new GeomLinestrips(Geom::UH_static);
00171 PT(GeomPoints) points = new GeomPoints(Geom::UH_static);
00172
00173 int v = 0;
00174 LineList::const_iterator ll;
00175 SegmentList::const_iterator sl;
00176
00177 for (ll = _list.begin(); ll != _list.end(); ll++) {
00178 const SegmentList &segs = (*ll);
00179
00180 if (segs.size() < 2) {
00181
00182 for (sl = segs.begin(); sl != segs.end(); sl++) {
00183 points->add_vertex(v);
00184 vertex.add_data3((*sl)._point);
00185 color.add_data4((*sl)._color);
00186 v++;
00187 }
00188 points->close_primitive();
00189
00190 } else {
00191
00192
00193 for (sl = segs.begin(); sl != segs.end(); sl++) {
00194 lines->add_vertex(v);
00195 vertex.add_data3((*sl)._point);
00196 color.add_data4((*sl)._color);
00197 v++;
00198 }
00199 lines->close_primitive();
00200 }
00201 }
00202
00203 if (lines->get_num_vertices() != 0) {
00204 PT(Geom) geom = new Geom(vdata);
00205 geom->add_primitive(lines);
00206 _previous->add_geom(geom);
00207 }
00208 if (points->get_num_vertices() != 0) {
00209 PT(Geom) geom = new Geom(vdata);
00210 geom->add_primitive(points);
00211 _previous->add_geom(geom);
00212 }
00213 }
00214 }
00215
00216
00217
00218
00219
00220
00221 bool PortalClipper::
00222 prepare_portal(const NodePath &node_path)
00223 {
00224
00225 PandaNode *node = node_path.node();
00226 _portal_node = NULL;
00227 if (node->is_of_type(PortalNode::get_class_type())) {
00228 _portal_node = DCAST(PortalNode, node);
00229 }
00230
00231
00232 portal_cat.spam() << *_portal_node << endl;
00233
00234
00235 CPT(TransformState) ctransform = node_path.get_transform(_scene_setup->get_cull_center());
00236
00237 LMatrix4 cmat = ctransform->get_mat();
00238 portal_cat.spam() << cmat << endl;
00239
00240 LVertex temp[4];
00241 temp[0] = _portal_node->get_vertex(0);
00242 temp[1] = _portal_node->get_vertex(1);
00243 temp[2] = _portal_node->get_vertex(2);
00244 temp[3] = _portal_node->get_vertex(3);
00245
00246 portal_cat.spam() << "before transformation to camera space" << endl;
00247 portal_cat.spam() << temp[0] << endl;
00248 portal_cat.spam() << temp[1] << endl;
00249 portal_cat.spam() << temp[2] << endl;
00250 portal_cat.spam() << temp[3] << endl;
00251
00252 temp[0] = temp[0]*cmat;
00253 temp[1] = temp[1]*cmat;
00254 temp[2] = temp[2]*cmat;
00255 temp[3] = temp[3]*cmat;
00256
00257 LPlane portal_plane(temp[0], temp[1], temp[2]);
00258 if (!is_facing_view(portal_plane)) {
00259 portal_cat.debug() << "portal failed 1st level test (isn't facing the camera)\n";
00260 return false;
00261 }
00262
00263 portal_cat.spam() << "after transformation to camera space" << endl;
00264 portal_cat.spam() << temp[0] << endl;
00265 portal_cat.spam() << temp[1] << endl;
00266 portal_cat.spam() << temp[2] << endl;
00267 portal_cat.spam() << temp[3] << endl;
00268
00269
00270
00271
00272 const Lens *lens = _scene_setup->get_lens();
00273 LVector3 forward = LVector3::forward(lens->get_coordinate_system());
00274 int forward_axis;
00275 if (forward[1]) {
00276 forward_axis = 1;
00277 }
00278 else if (forward[2]) {
00279 forward_axis = 2;
00280 }
00281 else {
00282 forward_axis = 0;
00283 }
00284 if ((temp[0][forward_axis] * forward[forward_axis] <= 0) ||
00285 (temp[1][forward_axis] * forward[forward_axis] <= 0) ||
00286 (temp[2][forward_axis] * forward[forward_axis] <= 0) ||
00287 (temp[3][forward_axis] * forward[forward_axis] <= 0)) {
00288 portal_cat.debug() << "portal intersects with center of projection.." << endl;
00289 return true;
00290 }
00291
00292
00293 LPoint3 projected_coords[4];
00294 lens->project(temp[0], projected_coords[0]);
00295 lens->project(temp[1], projected_coords[1]);
00296 lens->project(temp[2], projected_coords[2]);
00297 lens->project(temp[3], projected_coords[3]);
00298
00299 portal_cat.spam() << "after projection to 2d" << endl;
00300 portal_cat.spam() << projected_coords[0] << endl;
00301 portal_cat.spam() << projected_coords[1] << endl;
00302 portal_cat.spam() << projected_coords[2] << endl;
00303 portal_cat.spam() << projected_coords[3] << endl;
00304
00305
00306 PN_stdfloat min_x, max_x, min_y, max_y;
00307 min_x = min(min(min(projected_coords[0][0], projected_coords[1][0]), projected_coords[2][0]), projected_coords[3][0]);
00308 max_x = max(max(max(projected_coords[0][0], projected_coords[1][0]), projected_coords[2][0]), projected_coords[3][0]);
00309 min_y = min(min(min(projected_coords[0][1], projected_coords[1][1]), projected_coords[2][1]), projected_coords[3][1]);
00310 max_y = max(max(max(projected_coords[0][1], projected_coords[1][1]), projected_coords[2][1]), projected_coords[3][1]);
00311
00312 portal_cat.spam() << "min_x " << min_x << ";max_x " << max_x << ";min_y " << min_y << ";max_y " << max_y << endl;
00313
00314
00315 min_x = max(min_x, _reduced_viewport_min[0]);
00316 min_y = max(min_y, _reduced_viewport_min[1]);
00317 max_x = min(max_x, _reduced_viewport_max[0]);
00318 max_y = min(max_y, _reduced_viewport_max[1]);
00319
00320 portal_cat.spam() << "after clipping: min_x " << min_x << ";max_x " << max_x << ";min_y " << min_y << ";max_y " << max_y << endl;
00321
00322 if ((min_x >= max_x) || (min_y >= max_y)) {
00323 portal_cat.debug() << "portal got clipped away \n";
00324 return false;
00325 }
00326
00327
00328 _reduced_viewport_min.set(min_x, min_y);
00329 _reduced_viewport_max.set(max_x, max_y);
00330
00331
00332 LPoint3 near_point[4];
00333 LPoint3 far_point[4];
00334 lens->extrude(LPoint2(min_x, min_y), near_point[0], far_point[0]);
00335 lens->extrude(LPoint2(max_x, min_y), near_point[1], far_point[1]);
00336 lens->extrude(LPoint2(max_x, max_y), near_point[2], far_point[2]);
00337 lens->extrude(LPoint2(min_x, max_y), near_point[3], far_point[3]);
00338
00339
00340 _reduced_frustum = new BoundingHexahedron(far_point[0], far_point[1], far_point[2], far_point[3],
00341 near_point[0], near_point[1], near_point[2], near_point[3]);
00342
00343 portal_cat.debug() << *_reduced_frustum << endl;
00344
00345
00346 if (debug_portal_cull) {
00347
00348 _color = LColor(0,0,1,1);
00349 draw_hexahedron(DCAST(BoundingHexahedron, _reduced_frustum));
00350
00351
00352 _color = LColor(1,1,0,1);
00353 move_to((near_point[0]*0.99+far_point[0]*0.01));
00354 draw_to((near_point[1]*0.99+far_point[1]*0.01));
00355 draw_to((near_point[2]*0.99+far_point[2]*0.01));
00356 draw_to((near_point[3]*0.99+far_point[3]*0.01));
00357 draw_to((near_point[0]*0.99+far_point[0]*0.01));
00358
00359
00360 _color = LColor(0,1,1,1);
00361 move_to(temp[0]);
00362 draw_to(temp[1]);
00363 draw_to(temp[2]);
00364 draw_to(temp[3]);
00365 draw_to(temp[0]);
00366 }
00367
00368 return true;
00369 }
00370