33ProjectionScreen(
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()));
154generate_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);
347void ProjectionScreen::
348do_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();
366void 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);
399void 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);
428void 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);
454 if (distort_cat.is_debug()) {
456 <<
" " << *node <<
" got geom " << geom
457 <<
", cache_ref = " << geom->get_cache_ref_count() <<
"\n";
460 recompute_geom(geom, rel_mat);
467void ProjectionScreen::
468recompute_geom(
Geom *geom,
const LMatrix4 &rel_mat) {
469 static const LMatrix4 lens_to_uv
470 (0.5f, 0.0f, 0.0f, 0.0f,
471 0.0f, 0.5f, 0.0f, 0.0f,
472 0.0f, 0.0f, 1.0f, 0.0f,
473 0.5f, 0.5f, 0.0f, 1.0f);
475 static const LMatrix4 lens_to_uv_inverted
476 (0.5f, 0.0f, 0.0f, 0.0f,
477 0.0f,-0.5f, 0.0f, 0.0f,
478 0.0f, 0.0f, 1.0f, 0.0f,
479 0.5f, 0.5f, 0.0f, 1.0f);
483 Lens *lens = _projector_node->get_lens();
484 nassertv(lens !=
nullptr);
486 const LMatrix4 &to_uv = _invert_uvs ? lens_to_uv_inverted : lens_to_uv;
489 CPT(
GeomVertexData) vdata = geom->get_animated_vertex_data(
true, current_thread);
492 if (!vformat->has_column(_texcoord_name) || (_texcoord_3d && vformat->get_column(_texcoord_name)->get_num_components() < 3)) {
494 vdata = vdata->replace_column
495 (_texcoord_name, 3, Geom::NT_stdfloat, Geom::C_texcoord);
498 if (_vignette_on && !vdata->has_column(InternalName::get_color())) {
500 vdata = vdata->replace_column
501 (InternalName::get_color(), 1, Geom::NT_packed_dabc, Geom::C_color);
511 CPT(
GeomVertexData) animated_vdata = geom->get_animated_vertex_data(
true, current_thread);
515 GeomVertexReader vertex(animated_vdata, InternalName::get_vertex(), current_thread);
518 color.set_column(InternalName::get_color());
521 while (!vertex.is_at_end()) {
522 LVertex vert = vertex.get_data3();
525 LPoint3 vert3d = vert * rel_mat;
526 LPoint3 film(0.0f, 0.0f, 0.0f);
527 bool good = lens->
project(vert3d, film);
531 LPoint3 uvw = film * to_uv;
533 if (good && _has_undist_lut) {
545 uvw = LCAST(PN_stdfloat, p);
546 uvw[1] = 1.0 - uvw[1];
549 texcoord.set_data3(uvw);
555 color.set_data4(_frame_color);
557 color.set_data4(_vignette_color);
572 LMatrix4 &rel_mat,
bool &computed_rel_mat) {
577 new_node = make_mesh_geom_node(np, camera, rel_mat, computed_rel_mat);
580 new_node->clear_transform();
584 new_node =
new PandaNode(node->get_name());
585 new_node->set_state(node->get_state());
589 result_parent->add_child(new_node);
590 make_mesh_children(new_node, np, camera, rel_mat, computed_rel_mat);
598void ProjectionScreen::
601 LMatrix4 &rel_mat,
bool &computed_rel_mat) {
604 for (
int i = 0; i < num_children; i++) {
612 LMatrix4 new_rel_mat;
613 bool computed_new_rel_mat =
false;
614 new_child = make_mesh_node(new_node,
WorkingNodePath(np, child), camera,
615 new_rel_mat, computed_new_rel_mat);
620 new_child = make_mesh_node(new_node,
WorkingNodePath(np, child), camera,
621 rel_mat, computed_rel_mat);
624 if (new_child !=
nullptr) {
626 new_child->
set_state(child->get_state());
637 LMatrix4 &rel_mat,
bool &computed_rel_mat) {
642 if (!computed_rel_mat) {
646 computed_rel_mat =
true;
650 for (
int i = 0; i < num_geoms; i++) {
651 const Geom *geom = node->get_geom(i);
653 make_mesh_geom(geom, lens_node->
get_lens(), rel_mat);
654 if (new_geom !=
nullptr) {
668make_mesh_geom(
const Geom *geom,
Lens *lens, LMatrix4 &rel_mat) {
669 static const LMatrix4 lens_to_uv
670 (0.5f, 0.0f, 0.0f, 0.0f,
671 0.0f, 0.5f, 0.0f, 0.0f,
672 0.0f, 0.0f, 1.0f, 0.0f,
673 0.5f, 0.5f, 0.0f, 1.0f);
674 static const LMatrix4 uv_to_lens = invert(lens_to_uv);
678 new_geom->
set_vertex_data(new_geom->get_animated_vertex_data(
false, current_thread));
686 LPoint3 vert3d = vert * rel_mat;
687 LPoint3 film(0.0f, 0.0f, 0.0f);
688 bool good = lens->
project(vert3d, film);
690 if (good && _has_undist_lut) {
694 LPoint3 uvw = film * lens_to_uv;
702 uvw = LCAST(PN_stdfloat, p);
703 uvw[1] = 1.0 - uvw[1];
706 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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.