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;
174 Lens *lens = projector_node->get_lens();
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());
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);
674 Thread *current_thread = Thread::get_current_thread();
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;
get_geom_state
Returns the RenderState associated with the nth geom of the node.
bool is_at_end() const
Returns true if the reader or writer is currently at the end of the list of vertices,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A basic node of the scene graph or data graph.
PandaNode * node() const
Returns the node traversed to so far.
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
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 ...
A base class for any number of different kinds of lenses, linear and otherwise.
virtual PandaNode * make_copy() const
Returns a newly-allocated Node that is a shallow copy of this one.
set_state
Sets the complete RenderState that will be applied to all nodes at this level and below.
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.
bool is_empty() const
Returns true if the NodePath contains no nodes.
A node that contains a Lens.
get_near
Returns the position of the near plane (or cylinder, sphere, whatever).
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,...
void set_projector(const NodePath &projector)
Specifies the LensNode that is to serve as the projector for this screen.
This collects together the pieces of data that are accumulated for each node while walking the scene ...
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn't completely bogus.
Defines a series of triangle strips.
This is a class designed to support low-overhead traversals of the complete scene graph,...
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 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,...
get_num_children
Returns the number of child nodes this node has.
get_current_thread
Returns a pointer to the currently-executing Thread object.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual Geom * make_copy() const
Returns a newly-allocated Geom that is a shallow copy of this one.
void remove_all_children(Thread *current_thread=Thread::get_current_thread())
Removes all the children from the node at once, including stashed children.
get_node_path
Constructs and returns an actual NodePath that represents the same path we have just traversed.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A container for geometry primitives.
const LVecBase3 & get_data3()
Returns the data associated with the read row, expressed as a 3-component value, and advances the rea...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
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 (...
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data)
This function will be called during the cull traversal to perform any additional operations that shou...
A ProjectionScreen implements a simple system for projective texturing.
PT(GeomNode) ProjectionScreen
Synthesizes a polygon mesh based on the projection area of the indicated projector.
virtual PandaNode * make_copy() const
Returns a newly-allocated PandaNode that is a shallow copy of this one.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void recompute()
Recomputes all the UV's for geometry below the ProjectionScreen node, as if the texture were projecte...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaNode * node() const
Returns the referenced node of the path.
void set_vertex_data(const GeomVertexData *data)
Replaces the Geom's underlying vertex data table with a completely new table.
get_num_geoms
Returns the number of geoms in the node.
A thread; that is, a lightweight process.
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
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 (...
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_child
Returns the nth child node of this node.
TypeHandle is the identifier used to differentiate C++ class types.
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
This is a sequence number that increments monotonically.
bool recompute_if_stale()
Calls recompute() only if the relative transform between the ProjectionScreen and the projector has c...
virtual bool is_geom_node() const
A simple downcast check.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
get_far
Returns the position of the far plane (or cylinder, sphere, whatever).
A node that holds Geom objects, renderable pieces of geometry.
A node that renders only one of its children, according to the user's indication.
This object provides the functionality of both a GeomVertexReader and a GeomVertexWriter,...
virtual bool safe_to_flatten() const
Returns true if it is generally safe to flatten out this particular kind of PandaNode by duplicating ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.