33 ProjectionScreen(
const std::string &name) :
PandaNode(name)
37 _texcoord_name = InternalName::get_texcoord();
39 _has_undist_lut =
false;
40 _invert_uvs = project_invert_uvs;
43 _vignette_color.set(0.0f, 0.0f, 0.0f, 1.0f);
44 _frame_color.set(1.0f, 1.0f, 1.0f, 1.0f);
45 _computed_rel_top_mat =
false;
47 _auto_recompute =
true;
63 _projector(copy._projector),
64 _projector_node(copy._projector_node),
65 _texcoord_name(copy._texcoord_name),
66 _vignette_on(copy._vignette_on),
67 _vignette_color(copy._vignette_color),
68 _frame_color(copy._frame_color),
69 _auto_recompute(copy._auto_recompute)
71 _computed_rel_top_mat =
false;
105 if (_auto_recompute) {
121 _projector_node =
nullptr;
122 _projector = projector;
124 nassertv(projector.
node()->
is_of_type(LensNode::get_class_type()));
154 generate_screen(
const NodePath &projector,
const std::string &screen_name,
155 int num_x_verts,
int num_y_verts, PN_stdfloat distance,
156 PN_stdfloat fill_ratio) {
161 nassertr(projector_node->
get_lens() !=
nullptr,
nullptr);
173 int num_verts = num_x_verts * num_y_verts;
177 PN_stdfloat x_scale = 2.0f / (num_x_verts - 1);
178 PN_stdfloat y_scale = 2.0f / (num_y_verts - 1);
186 for (
int yi = 0; yi < num_y_verts; yi++) {
187 for (
int xi = 0; xi < num_x_verts; xi++) {
188 LPoint2 film = LPoint2((PN_stdfloat)xi * x_scale - 1.0f,
189 (PN_stdfloat)yi * y_scale - 1.0f);
194 LPoint3 near_point, far_point;
195 lens->
extrude(film, near_point, far_point);
196 LPoint3 point = near_point + t * (far_point - near_point);
204 normal.
add_data3(-normalize(norm * rel_mat));
207 nassertr(vdata->get_num_rows() == num_verts,
nullptr);
215 for (ti = 1; ti < num_y_verts; ti++) {
216 strip->add_vertex(ti * num_x_verts);
217 for (si = 1; si < num_x_verts; si++) {
218 strip->add_vertex((ti - 1) * num_x_verts + (si-1));
219 strip->add_vertex(ti * num_x_verts + si);
221 strip->add_vertex((ti - 1) * num_x_verts + (num_x_verts-1));
222 strip->close_primitive();
226 geom->add_primitive(strip);
228 geom_node->add_geom(geom);
241 int num_x_verts,
int num_y_verts, PN_stdfloat distance,
242 PN_stdfloat fill_ratio) {
248 generate_screen(projector, screen_name, num_x_verts, num_y_verts,
249 distance, fill_ratio);
250 add_child(geom_node);
268 nassertr(!this_np.
is_empty() && this_np.
node() ==
this,
nullptr);
273 nassertr(camera_node->
get_lens() !=
nullptr,
nullptr);
281 bool computed_rel_mat =
false;
282 make_mesh_children(top, this_np, camera, rel_mat, computed_rel_mat);
298 do_recompute(this_np);
319 nassertr(!this_np.
is_empty() && this_np.
node() ==
this,
false);
321 if (_projector_node !=
nullptr &&
322 _projector_node->get_lens() !=
nullptr) {
323 UpdateSeq lens_change = _projector_node->get_lens()->get_last_change();
324 if (_stale || lens_change != _projector_lens_change) {
331 const LMatrix4 &top_mat = transform->
get_mat();
332 if (!_rel_top_mat.almost_equal(top_mat)) {
333 _rel_top_mat = top_mat;
334 _computed_rel_top_mat =
true;
335 do_recompute(this_np);
347 void ProjectionScreen::
348 do_recompute(
const NodePath &this_np) {
349 if (_projector_node !=
nullptr &&
350 _projector_node->get_lens() !=
nullptr) {
352 recompute_node(this_np, _rel_top_mat, _computed_rel_top_mat);
354 _computed_rel_top_mat =
false;
356 _projector_lens_change = _projector_node->get_lens()->get_last_change();
366 void ProjectionScreen::
368 bool &computed_rel_mat) {
371 recompute_geom_node(np, rel_mat, computed_rel_mat);
379 int i = DCAST(
SwitchNode, node)->get_visible_child();
382 recompute_child(
WorkingNodePath(np, child), rel_mat, computed_rel_mat);
388 for (
int i = 0; i < num_children; i++) {
390 recompute_child(
WorkingNodePath(np, child), rel_mat, computed_rel_mat);
399 void ProjectionScreen::
401 bool &computed_rel_mat) {
408 LMatrix4 new_rel_mat;
409 bool computed_new_rel_mat =
false;
411 if (distort_cat.is_spam()) {
413 <<
"Saving rel_mat " << (
void *)&new_rel_mat <<
" at " << np <<
"\n";
416 recompute_node(np, new_rel_mat, computed_new_rel_mat);
421 recompute_node(np, rel_mat, computed_rel_mat);
428 void ProjectionScreen::
430 bool &computed_rel_mat) {
432 if (!computed_rel_mat) {
436 computed_rel_mat =
true;
438 if (distort_cat.is_spam()) {
440 <<
"Computing rel_mat " << (
void *)&rel_mat <<
" at " << np <<
"\n";
442 <<
" " << rel_mat <<
"\n";
445 if (distort_cat.is_spam()) {
447 <<
"Applying rel_mat " << (
void *)&rel_mat <<
" to " << np <<
"\n";
452 for (
int i = 0; i < num_geoms; i++) {
453 PT(
Geom) geom = node->modify_geom(i);
455 <<
" " << *node <<
" got geom " << geom
456 <<
", cache_ref = " << geom->get_cache_ref_count() <<
"\n";
458 recompute_geom(geom, rel_mat);
465 void ProjectionScreen::
466 recompute_geom(
Geom *geom,
const LMatrix4 &rel_mat) {
467 static const LMatrix4 lens_to_uv
468 (0.5f, 0.0f, 0.0f, 0.0f,
469 0.0f, 0.5f, 0.0f, 0.0f,
470 0.0f, 0.0f, 1.0f, 0.0f,
471 0.5f, 0.5f, 0.0f, 1.0f);
473 static const LMatrix4 lens_to_uv_inverted
474 (0.5f, 0.0f, 0.0f, 0.0f,
475 0.0f,-0.5f, 0.0f, 0.0f,
476 0.0f, 0.0f, 1.0f, 0.0f,
477 0.5f, 0.5f, 0.0f, 1.0f);
481 Lens *lens = _projector_node->get_lens();
482 nassertv(lens !=
nullptr);
484 const LMatrix4 &to_uv = _invert_uvs ? lens_to_uv_inverted : lens_to_uv;
487 CPT(
GeomVertexData) vdata = geom->get_animated_vertex_data(
true, current_thread);
490 if (!vformat->has_column(_texcoord_name) || (_texcoord_3d && vformat->get_column(_texcoord_name)->get_num_components() < 3)) {
492 vdata = vdata->replace_column
493 (_texcoord_name, 3, Geom::NT_stdfloat, Geom::C_texcoord);
496 if (_vignette_on && !vdata->has_column(InternalName::get_color())) {
498 vdata = vdata->replace_column
499 (InternalName::get_color(), 1, Geom::NT_packed_dabc, Geom::C_color);
509 CPT(
GeomVertexData) animated_vdata = geom->get_animated_vertex_data(
true, current_thread);
513 GeomVertexReader vertex(animated_vdata, InternalName::get_vertex(), current_thread);
516 color.set_column(InternalName::get_color());
519 while (!vertex.is_at_end()) {
520 LVertex vert = vertex.get_data3();
523 LPoint3 vert3d = vert * rel_mat;
524 LPoint3 film(0.0f, 0.0f, 0.0f);
525 bool good = lens->
project(vert3d, film);
529 LPoint3 uvw = film * to_uv;
531 if (good && _has_undist_lut) {
543 uvw = LCAST(PN_stdfloat, p);
544 uvw[1] = 1.0 - uvw[1];
547 texcoord.set_data3(uvw);
553 color.set_data4(_frame_color);
555 color.set_data4(_vignette_color);
570 LMatrix4 &rel_mat,
bool &computed_rel_mat) {
575 new_node = make_mesh_geom_node(np, camera, rel_mat, computed_rel_mat);
578 new_node->clear_transform();
582 new_node =
new PandaNode(node->get_name());
583 new_node->set_state(node->get_state());
587 result_parent->add_child(new_node);
588 make_mesh_children(new_node, np, camera, rel_mat, computed_rel_mat);
596 void ProjectionScreen::
599 LMatrix4 &rel_mat,
bool &computed_rel_mat) {
602 for (
int i = 0; i < num_children; i++) {
610 LMatrix4 new_rel_mat;
611 bool computed_new_rel_mat =
false;
612 new_child = make_mesh_node(new_node,
WorkingNodePath(np, child), camera,
613 new_rel_mat, computed_new_rel_mat);
618 new_child = make_mesh_node(new_node,
WorkingNodePath(np, child), camera,
619 rel_mat, computed_rel_mat);
622 if (new_child !=
nullptr) {
624 new_child->
set_state(child->get_state());
635 LMatrix4 &rel_mat,
bool &computed_rel_mat) {
640 if (!computed_rel_mat) {
644 computed_rel_mat =
true;
648 for (
int i = 0; i < num_geoms; i++) {
649 const Geom *geom = node->get_geom(i);
651 make_mesh_geom(geom, lens_node->
get_lens(), rel_mat);
652 if (new_geom !=
nullptr) {
666 make_mesh_geom(
const Geom *geom,
Lens *lens, LMatrix4 &rel_mat) {
667 static const LMatrix4 lens_to_uv
668 (0.5f, 0.0f, 0.0f, 0.0f,
669 0.0f, 0.5f, 0.0f, 0.0f,
670 0.0f, 0.0f, 1.0f, 0.0f,
671 0.5f, 0.5f, 0.0f, 1.0f);
672 static const LMatrix4 uv_to_lens = invert(lens_to_uv);
676 new_geom->
set_vertex_data(new_geom->get_animated_vertex_data(
false, current_thread));
684 LPoint3 vert3d = vert * rel_mat;
685 LPoint3 film(0.0f, 0.0f, 0.0f);
686 bool good = lens->
project(vert3d, film);
688 if (good && _has_undist_lut) {
692 LPoint3 uvw = film * lens_to_uv;
700 uvw = LCAST(PN_stdfloat, p);
701 uvw[1] = 1.0 - uvw[1];
704 film = uvw * uv_to_lens;
This collects together the pieces of data that are accumulated for each node while walking the scene ...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
A node that holds Geom objects, renderable pieces of geometry.
get_num_geoms
Returns the number of geoms in the node.
get_geom_state
Returns the RenderState associated with the nth geom of the node.
Defines a series of triangle strips.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
const LVecBase3 & get_data3()
Returns the data associated with the read row, expressed as a 3-component value, and advances the rea...
This object provides the functionality of both a GeomVertexReader and a GeomVertexWriter,...
bool is_at_end() const
Returns true if the reader or writer is currently at the end of the list of vertices,...
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
void set_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.
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.
virtual Geom * make_copy() const
Returns a newly-allocated Geom that is a shallow copy of this one.
void set_vertex_data(const GeomVertexData *data)
Replaces the Geom's underlying vertex data table with a completely new table.
A node that contains a Lens.
Lens * get_lens(int index=0) const
Returns a pointer to the particular Lens associated with this LensNode, or NULL if there is not yet a...
A base class for any number of different kinds of lenses, linear and otherwise.
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,...
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 (...
get_far
Returns the position of the far plane (or cylinder, sphere, whatever).
bool extrude_vec(const LPoint2 &point2d, LVector3 &vec3d) const
Given a 2-d point in the range (-1,1) in both dimensions, where (0,0) is the center of the lens and (...
get_near
Returns the position of the near plane (or cylinder, sphere, whatever).
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
static NodePath any_path(PandaNode *node, Thread *current_thread=Thread::get_current_thread())
Returns a new NodePath that represents any arbitrary path from the root to the indicated node.
bool is_empty() const
Returns true if the NodePath contains no nodes.
PandaNode * node() const
Returns the referenced node of the path.
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
A basic node of the scene graph or data graph.
virtual bool is_geom_node() const
A simple downcast check.
void remove_all_children(Thread *current_thread=Thread::get_current_thread())
Removes all the children from the node at once, including stashed children.
get_child
Returns the nth child node of this node.
set_state
Sets the complete RenderState that will be applied to all nodes at this level and below.
virtual PandaNode * make_copy() const
Returns a newly-allocated PandaNode that is a shallow copy of this one.
virtual bool safe_to_flatten() const
Returns true if it is generally safe to flatten out this particular kind of PandaNode by duplicating ...
get_num_children
Returns the number of child nodes this node has.
bool calc_bilinear_point(LPoint3f &result, PN_float32 x, PN_float32 y) const
Computes the weighted average of the four nearest points to the floating- point index (x,...
A ProjectionScreen implements a simple system for projective texturing.
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data)
This function will be called during the cull traversal to perform any additional operations that shou...
virtual PandaNode * make_copy() const
Returns a newly-allocated Node that is a shallow copy of this one.
void recompute()
Recomputes all the UV's for geometry below the ProjectionScreen node, as if the texture were projecte...
bool recompute_if_stale()
Calls recompute() only if the relative transform between the ProjectionScreen and the projector has c...
void set_projector(const NodePath &projector)
Specifies the LensNode that is to serve as the projector for this screen.
void regenerate_screen(const NodePath &projector, const std::string &screen_name, int num_x_verts, int num_y_verts, PN_stdfloat distance, PN_stdfloat fill_ratio)
Removes all the children from the ProjectionScreen node, and adds the newly generated child returned ...
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn't completely bogus.
A node that renders only one of its children, according to the user's indication.
A thread; that is, a lightweight process.
get_current_thread
Returns a pointer to the currently-executing Thread object.
TypeHandle is the identifier used to differentiate C++ class types.
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
This is a sequence number that increments monotonically.
This is a class designed to support low-overhead traversals of the complete scene graph,...
PandaNode * node() const
Returns the node traversed to so far.
get_node_path
Constructs and returns an actual NodePath that represents the same path we have just traversed.
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.
PT(GeomNode) ProjectionScreen
Synthesizes a polygon mesh based on the projection area of the indicated projector.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.