15 #include "projectionScreen.h" 17 #include "transformState.h" 18 #include "workingNodePath.h" 19 #include "switchNode.h" 21 #include "geomTristrips.h" 22 #include "geomVertexWriter.h" 23 #include "geomVertexReader.h" 24 #include "geomVertexRewriter.h" 25 #include "config_distort.h" 26 #include "cullTraverserData.h" 36 ProjectionScreen(
const string &name) :
PandaNode(name)
40 _texcoord_name = InternalName::get_texcoord();
42 _has_undist_lut =
false;
43 _invert_uvs = project_invert_uvs;
46 _vignette_color.set(0.0f, 0.0f, 0.0f, 1.0f);
47 _frame_color.set(1.0f, 1.0f, 1.0f, 1.0f);
48 _computed_rel_top_mat =
false;
50 _auto_recompute =
true;
70 _projector(copy._projector),
71 _projector_node(copy._projector_node),
72 _texcoord_name(copy._texcoord_name),
73 _vignette_on(copy._vignette_on),
74 _vignette_color(copy._vignette_color),
75 _frame_color(copy._frame_color),
76 _auto_recompute(copy._auto_recompute)
78 _computed_rel_top_mat =
false;
122 if (_auto_recompute) {
143 _projector = projector;
145 nassertv(projector.
node()->
is_of_type(LensNode::get_class_type()));
183 generate_screen(
const NodePath &projector,
const string &screen_name,
184 int num_x_verts,
int num_y_verts, PN_stdfloat distance,
185 PN_stdfloat fill_ratio) {
190 nassertr(projector_node->get_lens() != NULL, NULL);
202 int num_verts = num_x_verts * num_y_verts;
203 Lens *lens = projector_node->get_lens();
206 PN_stdfloat x_scale = 2.0f / (num_x_verts - 1);
207 PN_stdfloat y_scale = 2.0f / (num_y_verts - 1);
210 (
"projectionScreen", GeomVertexFormat::get_v3n3(),
215 for (
int yi = 0; yi < num_y_verts; yi++) {
216 for (
int xi = 0; xi < num_x_verts; xi++) {
218 (PN_stdfloat)yi * y_scale - 1.0f);
224 lens->
extrude(film, near_point, far_point);
225 LPoint3 point = near_point + t * (far_point - near_point);
233 normal.
add_data3(-normalize(norm * rel_mat));
236 nassertr(vdata->get_num_rows() == num_verts, NULL);
244 for (ti = 1; ti < num_y_verts; ti++) {
245 strip->add_vertex(ti * num_x_verts);
246 for (si = 1; si < num_x_verts; si++) {
247 strip->add_vertex((ti - 1) * num_x_verts + (si-1));
248 strip->add_vertex(ti * num_x_verts + si);
250 strip->add_vertex((ti - 1) * num_x_verts + (num_x_verts-1));
251 strip->close_primitive();
257 geom_node->add_geom(geom);
273 int num_x_verts,
int num_y_verts, PN_stdfloat distance,
274 PN_stdfloat fill_ratio) {
280 generate_screen(projector, screen_name, num_x_verts, num_y_verts,
281 distance, fill_ratio);
282 add_child(geom_node);
306 nassertr(!this_np.
is_empty() && this_np.
node() ==
this, NULL);
311 nassertr(camera_node->get_lens() != (
Lens *)NULL, NULL);
319 bool computed_rel_mat =
false;
320 make_mesh_children(top, this_np, camera, rel_mat, computed_rel_mat);
341 do_recompute(this_np);
370 nassertr(!this_np.
is_empty() && this_np.
node() ==
this,
false);
372 if (_projector_node != (
LensNode *)NULL &&
373 _projector_node->get_lens() != (
Lens *)NULL) {
374 UpdateSeq lens_change = _projector_node->get_lens()->get_last_change();
375 if (_stale || lens_change != _projector_lens_change) {
381 CPT(TransformState) transform = this_np.
get_transform(_projector);
382 const LMatrix4 &top_mat = transform->get_mat();
384 _rel_top_mat = top_mat;
385 _computed_rel_top_mat =
true;
386 do_recompute(this_np);
400 void ProjectionScreen::
401 do_recompute(
const NodePath &this_np) {
402 if (_projector_node != (
LensNode *)NULL &&
403 _projector_node->get_lens() != (
Lens *)NULL) {
405 recompute_node(this_np, _rel_top_mat, _computed_rel_top_mat);
407 _computed_rel_top_mat =
false;
409 _projector_lens_change = _projector_node->get_lens()->get_last_change();
422 void ProjectionScreen::
424 bool &computed_rel_mat) {
427 recompute_geom_node(np, rel_mat, computed_rel_mat);
435 int i = DCAST(
SwitchNode, node)->get_visible_child();
438 recompute_child(
WorkingNodePath(np, child), rel_mat, computed_rel_mat);
444 for (
int i = 0; i < num_children; i++) {
446 recompute_child(
WorkingNodePath(np, child), rel_mat, computed_rel_mat);
458 void ProjectionScreen::
460 bool &computed_rel_mat) {
463 const TransformState *transform = child->get_transform();
464 if (!transform->is_identity()) {
468 bool computed_new_rel_mat =
false;
470 if (distort_cat.is_spam()) {
472 <<
"Saving rel_mat " << (
void *)&new_rel_mat <<
" at " << np <<
"\n";
475 recompute_node(np, new_rel_mat, computed_new_rel_mat);
480 recompute_node(np, rel_mat, computed_rel_mat);
489 void ProjectionScreen::
491 bool &computed_rel_mat) {
493 if (!computed_rel_mat) {
497 computed_rel_mat =
true;
499 if (distort_cat.is_spam()) {
501 <<
"Computing rel_mat " << (
void *)&rel_mat <<
" at " << np <<
"\n";
503 <<
" " << rel_mat <<
"\n";
506 if (distort_cat.is_spam()) {
508 <<
"Applying rel_mat " << (
void *)&rel_mat <<
" to " << np <<
"\n";
513 for (
int i = 0; i < num_geoms; i++) {
514 PT(
Geom) geom = node->modify_geom(i);
516 <<
" " << *node <<
" got geom " << geom
519 recompute_geom(geom, rel_mat);
528 void ProjectionScreen::
531 (0.5f, 0.0f, 0.0f, 0.0f,
532 0.0f, 0.5f, 0.0f, 0.0f,
533 0.0f, 0.0f, 1.0f, 0.0f,
534 0.5f, 0.5f, 0.0f, 1.0f);
536 static const LMatrix4 lens_to_uv_inverted
537 (0.5f, 0.0f, 0.0f, 0.0f,
538 0.0f,-0.5f, 0.0f, 0.0f,
539 0.0f, 0.0f, 1.0f, 0.0f,
540 0.5f, 0.5f, 0.0f, 1.0f);
544 Lens *lens = _projector_node->get_lens();
545 nassertv(lens != (
Lens *)NULL);
547 const LMatrix4 &to_uv = _invert_uvs ? lens_to_uv_inverted : lens_to_uv;
550 CPT(
GeomVertexData) vdata = geom->get_vertex_data(current_thread);
551 vdata = vdata->animate_vertices(
true, current_thread);
553 CPT(GeomVertexFormat) vformat = vdata->get_format();
554 if (!vformat->has_column(_texcoord_name) || (_texcoord_3d && vformat->get_column(_texcoord_name)->get_num_components() < 3)) {
556 vdata = vdata->replace_column
557 (_texcoord_name, 3, Geom::NT_stdfloat, Geom::C_texcoord);
560 if (_vignette_on && !vdata->has_column(InternalName::get_color())) {
562 vdata = vdata->replace_column
563 (InternalName::get_color(), 1, Geom::NT_packed_dabc, Geom::C_color);
573 CPT(
GeomVertexData) animated_vdata = geom->get_vertex_data(current_thread)->animate_vertices(
true, current_thread);
577 GeomVertexReader vertex(animated_vdata, InternalName::get_vertex(), current_thread);
587 LPoint3 vert3d = vert * rel_mat;
588 LPoint3 film(0.0f, 0.0f, 0.0f);
589 bool good = lens->
project(vert3d, film);
595 if (good && _has_undist_lut) {
608 uvw = LCAST(PN_stdfloat, p);
609 uvw[1] = 1.0 - uvw[1];
638 LMatrix4 &rel_mat,
bool &computed_rel_mat) {
643 new_node = make_mesh_geom_node(np, camera, rel_mat, computed_rel_mat);
646 new_node->clear_transform();
650 new_node =
new PandaNode(node->get_name());
655 result_parent->add_child(new_node);
656 make_mesh_children(new_node, np, camera, rel_mat, computed_rel_mat);
666 void ProjectionScreen::
669 LMatrix4 &rel_mat,
bool &computed_rel_mat) {
672 for (
int i = 0; i < num_children; i++) {
676 const TransformState *transform = child->get_transform();
677 if (!transform->is_identity()) {
681 bool computed_new_rel_mat =
false;
682 new_child = make_mesh_node(new_node,
WorkingNodePath(np, child), camera,
683 new_rel_mat, computed_new_rel_mat);
688 new_child = make_mesh_node(new_node,
WorkingNodePath(np, child), camera,
689 rel_mat, computed_rel_mat);
692 if (new_child != NULL) {
695 new_child->
set_state(child->get_state());
709 LMatrix4 &rel_mat,
bool &computed_rel_mat) {
714 if (!computed_rel_mat) {
718 computed_rel_mat =
true;
722 for (
int i = 0; i < num_geoms; i++) {
723 const Geom *geom = node->get_geom(i);
725 make_mesh_geom(geom, lens_node->get_lens(), rel_mat);
726 if (new_geom != (
Geom *)NULL) {
742 PT(
Geom) ProjectionScreen::
745 (0.5f, 0.0f, 0.0f, 0.0f,
746 0.0f, 0.5f, 0.0f, 0.0f,
747 0.0f, 0.0f, 1.0f, 0.0f,
748 0.5f, 0.5f, 0.0f, 1.0f);
749 static const LMatrix4 uv_to_lens = invert(lens_to_uv);
754 new_geom->set_vertex_data(vdata->animate_vertices(
false, current_thread));
755 vdata = new_geom->modify_vertex_data();
762 LPoint3 vert3d = vert * rel_mat;
763 LPoint3 film(0.0f, 0.0f, 0.0f);
764 bool good = lens->
project(vert3d, film);
766 if (good && _has_undist_lut) {
770 LPoint3 uvw = film * lens_to_uv;
778 uvw = LCAST(PN_stdfloat, p);
779 uvw[1] = 1.0 - uvw[1];
782 film = uvw * uv_to_lens;
const RenderState * get_geom_state(int n) const
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, false otherwise.
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...
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn't completely bogus.
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.
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.
bool almost_equal(const LMatrix4f &other, float threshold) const
Returns true if two matrices are memberwise equal within a specified tolerance.
int get_num_children(Thread *current_thread=Thread::get_current_thread()) const
Returns the number of child nodes this node has.
A node that contains a Lens.
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...
PandaNode * get_child(int n, Thread *current_thread=Thread::get_current_thread()) const
Returns the nth child node of this node.
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 ...
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
Defines a series of triangle strips.
void add_primitive(const GeomPrimitive *primitive)
Adds a new GeomPrimitive structure to the Geom object.
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
int get_num_geoms() const
Returns the number of geoms in the node.
int get_cache_ref_count() const
Returns the current reference count.
This is a class designed to support low-overhead traversals of the complete scene graph...
void regenerate_screen(const NodePath &projector, const 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 ...
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
PN_stdfloat get_near() const
Returns the position of the near plane (or cylinder, sphere, whatever).
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,1) in both dimensions, where (0,0) is the center of the lens and (-1,-1) is the lower-left corner.
NodePath get_node_path() const
Constructs and returns an actual NodePath that represents the same path we have just traversed...
virtual Geom * make_copy() const
Returns a newly-allocated Geom that is a shallow copy of this one.
This is a 4-by-4 transform matrix.
void remove_all_children(Thread *current_thread=Thread::get_current_thread())
Removes all the children from the node at once, including stashed children.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
A container for geometry primitives.
void set_state(const RenderState *state, Thread *current_thread=Thread::get_current_thread())
Sets the complete RenderState that will be applied to all nodes at this level and below...
const LVecBase3 & get_data3()
Returns the data associated with the read row, expressed as a 3-component value, and advances the rea...
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 (...
void set_data4(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat w)
Sets the write row to a particular 4-component value, and advances the write row. ...
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.
virtual PandaNode * make_copy() const
Returns a newly-allocated PandaNode 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...
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.
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 is_at_end() const
Returns true if the reader is currently at the end of the list of vertices, false otherwise...
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 set_column(int column)
Sets up the writer to use the nth data type of the GeomVertexFormat, numbering from 0...
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
This is a two-component point in space.
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...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling...
PN_stdfloat get_far() const
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, combined together into one convenient package.
virtual bool safe_to_flatten() const
Returns true if it is generally safe to flatten out this particular kind of PandaNode by duplicating ...