side-by-side stereo

This commit is contained in:
David Rose 2010-07-19 18:43:24 +00:00
parent 9a3d16b1c5
commit 9124513b82
20 changed files with 956 additions and 437 deletions

View File

@ -1084,10 +1084,11 @@ class ShowBase(DirectObject.DirectObject):
win = self.win
if win != None and win.hasSize():
if(win.getYSize() == 0 or win.getXSize() == 0):
#flub the aspect since we can't actually see anything
return 1
aspectRatio = float(win.getXSize()) / float(win.getYSize())
# Temporary hasattr for old Pandas
if not hasattr(win, 'getSbsLeftXSize'):
aspectRatio = float(win.getXSize()) / float(win.getYSize())
else:
aspectRatio = float(win.getSbsLeftXSize()) / float(win.getSbsLeftYSize())
else:
if win == None or not hasattr(win, "getRequestedProperties"):
@ -1405,6 +1406,16 @@ class ShowBase(DirectObject.DirectObject):
name = win.getInputDeviceName(i)
mk = self.dataRoot.attachNewNode(MouseAndKeyboard(win, i, name))
mw = mk.attachNewNode(MouseWatcher("watcher%s" % (i)))
# Temporary hasattr for old Pandas
if hasattr(win, 'getSideBySideStereo') and win.getSideBySideStereo():
# If the window has side-by-side stereo enabled, then
# we should constrain the MouseWatcher to the window's
# DisplayRegion. This will enable the MouseWatcher to
# track the left and right halves of the screen
# individually.
mw.node().setDisplayRegion(win.getOverlayDisplayRegion())
mb = mw.node().getModifierButtons()
mb.addButton(KeyboardButton.shift())
mb.addButton(KeyboardButton.control())
@ -1438,7 +1449,7 @@ class ShowBase(DirectObject.DirectObject):
aspectRatio = self.getAspectRatio()
# Scale the smiley face to 32x32 pixels.
height = self.win.getYSize()
height = self.win.getSbsLeftYSize()
lilsmiley.setScale(
32.0 / height / aspectRatio,
1.0, 32.0 / height)
@ -2543,9 +2554,13 @@ class ShowBase(DirectObject.DirectObject):
# If anybody needs to update their GUI, put a callback on this event
messenger.send("aspectRatioChanged")
if win.getXSize() > 0 and win.getYSize() > 0:
# Temporary hasattr for old Pandas
if not hasattr(win, 'getSbsLeftXSize'):
self.pixel2d.setScale(2.0 / win.getXSize(), 1.0, 2.0 / win.getYSize())
self.pixel2dp.setScale(2.0 / win.getXSize(), 1.0, 2.0 / win.getYSize())
else:
self.pixel2d.setScale(2.0 / win.getSbsLeftXSize(), 1.0, 2.0 / win.getSbsLeftYSize())
self.pixel2dp.setScale(2.0 / win.getSbsLeftXSize(), 1.0, 2.0 / win.getSbsLeftYSize())
def userExit(self):
# The user has requested we exit the program. Deal with this.

View File

@ -225,6 +225,26 @@ ConfigVariableString red_blue_stereo_colors
"'green', 'cyan', 'magenta', 'yellow', or 'alpha', or a union "
"of two or more words separated by a vertical pipe (|)."));
ConfigVariableBool side_by_side_stereo
("side-by-side-stereo", false,
PRC_DESC("Set this true to create windows with side-by-side stereo mode enabled "
"by default, if the framebuffer does not support true stereo "
"rendering."));
ConfigVariableDouble sbs_left_dimensions
("sbs-left-dimensions", "0.0 0.5 0.0 1.0",
PRC_DESC("Defines the default region of the window that is used for the "
"left eye, when side-by-side stereo is enabled. This is a set of "
"four numbers, in the form left right top bottom, similar to a "
"normal DisplayRegion layout."));
ConfigVariableDouble sbs_right_dimensions
("sbs-right-dimensions", "0.5 1.0 0.0 1.0",
PRC_DESC("Defines the default region of the window that is used for the "
"right eye, when side-by-side stereo is enabled. This is a set of "
"four numbers, in the form left right top bottom, similar to a "
"normal DisplayRegion layout."));
ConfigVariableBool default_stereo_camera
("default-stereo-camera", true,
PRC_DESC("When this is true, the default DisplayRegion created for "

View File

@ -59,6 +59,9 @@ extern EXPCL_PANDA_DISPLAY ConfigVariableBool copy_texture_inverted;
extern EXPCL_PANDA_DISPLAY ConfigVariableBool window_inverted;
extern EXPCL_PANDA_DISPLAY ConfigVariableBool red_blue_stereo;
extern EXPCL_PANDA_DISPLAY ConfigVariableString red_blue_stereo_colors;
extern EXPCL_PANDA_DISPLAY ConfigVariableBool side_by_side_stereo;
extern EXPCL_PANDA_DISPLAY ConfigVariableDouble sbs_left_dimensions;
extern EXPCL_PANDA_DISPLAY ConfigVariableDouble sbs_right_dimensions;
extern EXPCL_PANDA_DISPLAY ConfigVariableBool default_stereo_camera;
extern EXPCL_PANDA_DISPLAY ConfigVariableBool color_scale_via_lighting;
extern EXPCL_PANDA_DISPLAY ConfigVariableBool alpha_scale_via_texture;

View File

@ -48,10 +48,23 @@ get_lens_index() const {
INLINE void DisplayRegion::
get_dimensions(float &l, float &r, float &b, float &t) const {
CDReader cdata(_cycler);
l = cdata->_l;
r = cdata->_r;
b = cdata->_b;
t = cdata->_t;
l = cdata->_dimensions[0];
r = cdata->_dimensions[1];
b = cdata->_dimensions[2];
t = cdata->_dimensions[3];
}
///////////////////////////////////////////////////////////////////
// Function: DisplayRegion::get_dimensions
// Access: Published
// Description: Retrieves the coordinates of the DisplayRegion's
// rectangle within its GraphicsOutput. These numbers
// will be in the range [0..1].
////////////////////////////////////////////////////////////////////
INLINE LVecBase4f DisplayRegion::
get_dimensions() const {
CDReader cdata(_cycler);
return cdata->_dimensions;
}
////////////////////////////////////////////////////////////////////
@ -64,7 +77,7 @@ get_dimensions(float &l, float &r, float &b, float &t) const {
INLINE float DisplayRegion::
get_left() const {
CDReader cdata(_cycler);
return cdata->_l;
return cdata->_dimensions[0];
}
////////////////////////////////////////////////////////////////////
@ -77,7 +90,7 @@ get_left() const {
INLINE float DisplayRegion::
get_right() const {
CDReader cdata(_cycler);
return cdata->_r;
return cdata->_dimensions[1];
}
////////////////////////////////////////////////////////////////////
@ -90,7 +103,7 @@ get_right() const {
INLINE float DisplayRegion::
get_bottom() const {
CDReader cdata(_cycler);
return cdata->_b;
return cdata->_dimensions[2];
}
////////////////////////////////////////////////////////////////////
@ -103,7 +116,21 @@ get_bottom() const {
INLINE float DisplayRegion::
get_top() const {
CDReader cdata(_cycler);
return cdata->_t;
return cdata->_dimensions[3];
}
////////////////////////////////////////////////////////////////////
// Function: DisplayRegion::set_dimensions
// Access: Published, Virtual
// Description: Changes the portion of the framebuffer this
// DisplayRegion corresponds to. The parameters range
// from 0 to 1, where 0,0 is the lower left corner and
// 1,1 is the upper right; (0, 1, 0, 1) represents the
// whole screen.
////////////////////////////////////////////////////////////////////
INLINE void DisplayRegion::
set_dimensions(float l, float r, float b, float t) {
set_dimensions(LVecBase4f(l, r, b, t));
}
////////////////////////////////////////////////////////////////////
@ -586,10 +613,22 @@ is_any_clear_active() const {
////////////////////////////////////////////////////////////////////
INLINE void DisplayRegionPipelineReader::
get_dimensions(float &l, float &r, float &b, float &t) const {
l = _cdata->_l;
r = _cdata->_r;
b = _cdata->_b;
t = _cdata->_t;
l = _cdata->_dimensions[0];
r = _cdata->_dimensions[1];
b = _cdata->_dimensions[2];
t = _cdata->_dimensions[3];
}
////////////////////////////////////////////////////////////////////
// Function: DisplayRegionPipelineReader::get_dimensions
// Access: Public
// Description: Retrieves the coordinates of the DisplayRegion's
// rectangle within its GraphicsOutput. These numbers
// will be in the range [0..1].
////////////////////////////////////////////////////////////////////
INLINE const LVecBase4f &DisplayRegionPipelineReader::
get_dimensions() const {
return _cdata->_dimensions;
}
////////////////////////////////////////////////////////////////////
@ -601,7 +640,7 @@ get_dimensions(float &l, float &r, float &b, float &t) const {
////////////////////////////////////////////////////////////////////
INLINE float DisplayRegionPipelineReader::
get_left() const {
return _cdata->_l;
return _cdata->_dimensions[0];
}
////////////////////////////////////////////////////////////////////
@ -613,7 +652,7 @@ get_left() const {
////////////////////////////////////////////////////////////////////
INLINE float DisplayRegionPipelineReader::
get_right() const {
return _cdata->_r;
return _cdata->_dimensions[1];
}
////////////////////////////////////////////////////////////////////
@ -625,7 +664,7 @@ get_right() const {
////////////////////////////////////////////////////////////////////
INLINE float DisplayRegionPipelineReader::
get_bottom() const {
return _cdata->_b;
return _cdata->_dimensions[2];
}
////////////////////////////////////////////////////////////////////
@ -637,7 +676,7 @@ get_bottom() const {
////////////////////////////////////////////////////////////////////
INLINE float DisplayRegionPipelineReader::
get_top() const {
return _cdata->_t;
return _cdata->_dimensions[3];
}
////////////////////////////////////////////////////////////////////

View File

@ -32,7 +32,7 @@ TypeHandle DisplayRegionPipelineReader::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
DisplayRegion::
DisplayRegion(GraphicsOutput *window, float l, float r, float b, float t) :
DisplayRegion(GraphicsOutput *window, const LVecBase4f &dimensions) :
_window(window),
_incomplete_render(true),
_texture_reload_priority(0),
@ -41,7 +41,7 @@ DisplayRegion(GraphicsOutput *window, float l, float r, float b, float t) :
{
_screenshot_buffer_type = window->get_draw_buffer_type();
_draw_buffer_type = window->get_draw_buffer_type();
set_dimensions(l, r, b, t);
set_dimensions(dimensions);
compute_pixels_all_stages();
}
@ -124,15 +124,12 @@ set_lens_index(int index) {
// whole screen.
////////////////////////////////////////////////////////////////////
void DisplayRegion::
set_dimensions(float l, float r, float b, float t) {
set_dimensions(const LVecBase4f &dimensions) {
int pipeline_stage = Thread::get_current_pipeline_stage();
nassertv(pipeline_stage == 0);
CDWriter cdata(_cycler);
cdata->_l = l;
cdata->_r = r;
cdata->_b = b;
cdata->_t = t;
cdata->_dimensions = dimensions;
if (_window != (GraphicsOutput *)NULL && _window->has_size()) {
do_compute_pixels(_window->get_fb_x_size(), _window->get_fb_y_size(), cdata);
@ -382,8 +379,7 @@ set_cube_map_index(int cube_map_index) {
void DisplayRegion::
output(ostream &out) const {
CDReader cdata(_cycler);
out << "DisplayRegion(" << cdata->_l << " " << cdata->_r << " "
<< cdata->_b << " " << cdata->_t << ")=pixels(" << cdata->_pl
out << "DisplayRegion(" << cdata->_dimensions << ")=pixels(" << cdata->_pl
<< " " << cdata->_pr << " " << cdata->_pb << " " << cdata->_pt
<< ")";
}
@ -699,23 +695,23 @@ do_compute_pixels(int x_size, int y_size, CData *cdata) {
<< "DisplayRegion::do_compute_pixels(" << x_size << ", " << y_size << ")\n";
}
cdata->_pl = int((cdata->_l * x_size) + 0.5);
cdata->_pr = int((cdata->_r * x_size) + 0.5);
cdata->_pl = int((cdata->_dimensions[0] * x_size) + 0.5);
cdata->_pr = int((cdata->_dimensions[1] * x_size) + 0.5);
nassertv(_window != (GraphicsOutput *)NULL);
if (_window->get_inverted()) {
// The window is inverted; compute the DisplayRegion accordingly.
cdata->_pb = int(((1.0f - cdata->_t) * y_size) + 0.5);
cdata->_pt = int(((1.0f - cdata->_b) * y_size) + 0.5);
cdata->_pbi = int((cdata->_t * y_size) + 0.5);
cdata->_pti = int((cdata->_b * y_size) + 0.5);
cdata->_pb = int(((1.0f - cdata->_dimensions[3]) * y_size) + 0.5);
cdata->_pt = int(((1.0f - cdata->_dimensions[2]) * y_size) + 0.5);
cdata->_pbi = int((cdata->_dimensions[3] * y_size) + 0.5);
cdata->_pti = int((cdata->_dimensions[2] * y_size) + 0.5);
} else {
// The window is normal.
cdata->_pb = int((cdata->_b * y_size) + 0.5);
cdata->_pt = int((cdata->_t * y_size) + 0.5);
cdata->_pbi = int(((1.0f - cdata->_b) * y_size) + 0.5);
cdata->_pti = int(((1.0f - cdata->_t) * y_size) + 0.5);
cdata->_pb = int((cdata->_dimensions[2] * y_size) + 0.5);
cdata->_pt = int((cdata->_dimensions[3] * y_size) + 0.5);
cdata->_pbi = int(((1.0f - cdata->_dimensions[2]) * y_size) + 0.5);
cdata->_pti = int(((1.0f - cdata->_dimensions[3]) * y_size) + 0.5);
}
}
@ -750,7 +746,7 @@ set_active_index(int index) {
////////////////////////////////////////////////////////////////////
DisplayRegion::CData::
CData() :
_l(0.), _r(1.), _b(0.), _t(1.),
_dimensions(0.0f, 1.0f, 0.0f, 1.0f),
_pl(0), _pr(0), _pb(0), _pt(0),
_pbi(0), _pti(0), _lens_index(0),
_camera_node((Camera *)NULL),
@ -768,10 +764,7 @@ CData() :
////////////////////////////////////////////////////////////////////
DisplayRegion::CData::
CData(const DisplayRegion::CData &copy) :
_l(copy._l),
_r(copy._r),
_b(copy._b),
_t(copy._t),
_dimensions(copy._dimensions),
_pl(copy._pl),
_pr(copy._pr),
_pb(copy._pb),

View File

@ -37,6 +37,7 @@
#include "pStatCollector.h"
#include "cullTraverser.h"
#include "callbackObject.h"
#include "luse.h"
class GraphicsOutput;
class GraphicsPipe;
@ -58,8 +59,7 @@ class CullTraverser;
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_DISPLAY DisplayRegion : public DisplayRegionBase, public DrawableRegion {
protected:
DisplayRegion(GraphicsOutput *window,
float l, float r, float b, float t);
DisplayRegion(GraphicsOutput *window, const LVecBase4f &dimensions);
private:
DisplayRegion(const DisplayRegion &copy);
@ -73,11 +73,13 @@ public:
PUBLISHED:
INLINE void get_dimensions(float &l, float &r, float &b, float &t) const;
INLINE LVecBase4f get_dimensions() const;
INLINE float get_left() const;
INLINE float get_right() const;
INLINE float get_bottom() const;
INLINE float get_top() const;
virtual void set_dimensions(float l, float r, float b, float t);
INLINE void set_dimensions(float l, float r, float b, float t);
virtual void set_dimensions(const LVecBase4f &dimensions);
INLINE GraphicsOutput *get_window() const;
GraphicsPipe *get_pipe() const;
@ -184,10 +186,7 @@ private:
return DisplayRegion::get_class_type();
}
float _l;
float _r;
float _b;
float _t;
LVecBase4f _dimensions; // left, right, bottom, top
int _pl;
int _pr;
@ -284,6 +283,7 @@ public:
INLINE bool is_any_clear_active() const;
INLINE void get_dimensions(float &l, float &r, float &b, float &t) const;
INLINE const LVecBase4f &get_dimensions() const;
INLINE float get_left() const;
INLINE float get_right() const;
INLINE float get_bottom() const;

View File

@ -30,7 +30,7 @@ GraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
const WindowProperties &win_prop, int flags,
GraphicsStateGuardian *gsg,
GraphicsOutput *host) :
GraphicsOutput(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
GraphicsOutput(engine, pipe, name, fb_prop, win_prop, flags, gsg, host, false)
{
#ifdef DO_MEMORY_USAGE
MemoryUsage::update_type(this, this);
@ -41,7 +41,7 @@ GraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
<< "Creating new offscreen buffer " << get_name() << "\n";
}
_default_display_region->compute_pixels(_x_size, _y_size);
_overlay_display_region->compute_pixels(_x_size, _y_size);
_open_request = OR_none;
}

View File

@ -209,6 +209,66 @@ get_fb_y_size() const {
return max(int(_y_size * get_pixel_factor()), 1);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::get_sbs_left_x_size
// Access: Published
// Description: If side-by-side stereo is enabled, this returns the
// pixel width of the left eye, based on scaling
// get_x_size() by get_sbs_left_dimensions(). If
// side-by-side stereo is not enabled, this returns the
// same as get_x_size().
////////////////////////////////////////////////////////////////////
INLINE int GraphicsOutput::
get_sbs_left_x_size() const {
float left_w = _sbs_left_dimensions[1] - _sbs_left_dimensions[0];
return max(int(_x_size * left_w), 1);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::get_sbs_left_y_size
// Access: Published
// Description: If side-by-side stereo is enabled, this returns the
// pixel height of the left eye, based on scaling
// get_y_size() by get_sbs_left_dimensions(). If
// side-by-side stereo is not enabled, this returns the
// same as get_y_size().
////////////////////////////////////////////////////////////////////
INLINE int GraphicsOutput::
get_sbs_left_y_size() const {
float left_h = _sbs_left_dimensions[3] - _sbs_left_dimensions[2];
return max(int(_y_size * left_h), 1);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::get_sbs_right_x_size
// Access: Published
// Description: If side-by-side stereo is enabled, this returns the
// pixel width of the right eye, based on scaling
// get_x_size() by get_sbs_right_dimensions(). If
// side-by-side stereo is not enabled, this returns the
// same as get_x_size().
////////////////////////////////////////////////////////////////////
INLINE int GraphicsOutput::
get_sbs_right_x_size() const {
float right_w = _sbs_right_dimensions[1] - _sbs_right_dimensions[0];
return max(int(_x_size * right_w), 1);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::get_sbs_right_y_size
// Access: Published
// Description: If side-by-side stereo is enabled, this returns the
// pixel height of the right eye, based on scaling
// get_y_size() by get_sbs_right_dimensions(). If
// side-by-side stereo is not enabled, this returns the
// same as get_y_size().
////////////////////////////////////////////////////////////////////
INLINE int GraphicsOutput::
get_sbs_right_y_size() const {
float right_h = _sbs_right_dimensions[3] - _sbs_right_dimensions[2];
return max(int(_y_size * right_h), 1);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::has_size
// Access: Published
@ -355,6 +415,43 @@ get_right_eye_color_mask() const {
return _right_eye_color_mask;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::get_side_by_side_stereo
// Access: Published
// Description: Returns whether side-by-side stereo mode is in effect for
// this particular window. See set_side_by_side_stereo().
////////////////////////////////////////////////////////////////////
INLINE bool GraphicsOutput::
get_side_by_side_stereo() const {
return _side_by_side_stereo;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::get_sbs_left_dimensions
// Access: Published
// Description: Returns the effective sub-region of the window for
// displaying the left channel, if side-by-side stereo
// mode is in effect for the window. See
// set_side_by_side_stereo().
////////////////////////////////////////////////////////////////////
INLINE const LVecBase4f &GraphicsOutput::
get_sbs_left_dimensions() const {
return _sbs_left_dimensions;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::get_sbs_right_dimensions
// Access: Published
// Description: Returns the effective sub-region of the window for
// displaying the right channel, if side-by-side stereo
// mode is in effect for the window. See
// set_side_by_side_stereo().
////////////////////////////////////////////////////////////////////
INLINE const LVecBase4f &GraphicsOutput::
get_sbs_right_dimensions() const {
return _sbs_right_dimensions;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::get_fb_properties
// Access: Published
@ -375,7 +472,7 @@ get_fb_properties() const {
////////////////////////////////////////////////////////////////////
INLINE bool GraphicsOutput::
is_stereo() const {
return _red_blue_stereo || _fb_properties.is_stereo();
return _red_blue_stereo || _side_by_side_stereo || _fb_properties.is_stereo();
}
////////////////////////////////////////////////////////////////////
@ -505,20 +602,61 @@ make_display_region() {
return make_display_region(0.0f, 1.0f, 0.0f, 1.0f);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::make_display_region
// Access: Published
// Description: Creates a new DisplayRegion that covers the indicated
// sub-rectangle within the window. The range on all
// parameters is 0..1.
//
// If is_stereo() is true for this window, and
// default-stereo-camera is configured true, this
// actually makes a StereoDisplayRegion. Call
// make_mono_display_region() or
// make_stereo_display_region() if you want to insist on
// one or the other.
////////////////////////////////////////////////////////////////////
DisplayRegion *GraphicsOutput::
make_display_region(float l, float r, float b, float t) {
return make_display_region(LVecBase4f(l, r, b, t));
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::make_mono_display_region
// Access: Published
// Description: Creates a new DisplayRegion that covers the entire
// window.
//
// This always returns a mono DisplayRegion, even if
// is_stereo() is true.
// This generally returns a mono DisplayRegion, even if
// is_stereo() is true. However, if side-by-side stereo
// is enabled, this will return a StereoDisplayRegion
// whose two eyes are both set to SC_mono. (This is
// necessary because in side-by-side stereo mode, it is
// necessary to draw even mono DisplayRegions twice).
////////////////////////////////////////////////////////////////////
INLINE DisplayRegion *GraphicsOutput::
make_mono_display_region() {
return make_mono_display_region(0.0f, 1.0f, 0.0f, 1.0f);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::make_mono_display_region
// Access: Published
// Description: Creates a new DisplayRegion that covers the entire
// window.
//
// This generally returns a mono DisplayRegion, even if
// is_stereo() is true. However, if side-by-side stereo
// is enabled, this will return a StereoDisplayRegion
// whose two eyes are both set to SC_mono. (This is
// necessary because in side-by-side stereo mode, it is
// necessary to draw even mono DisplayRegions twice).
////////////////////////////////////////////////////////////////////
INLINE DisplayRegion *GraphicsOutput::
make_mono_display_region(float l, float r, float b, float t) {
return make_mono_display_region(LVecBase4f(l, r, b, t));
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::make_stereo_display_region
// Access: Published
@ -533,6 +671,41 @@ make_stereo_display_region() {
return make_stereo_display_region(0.0f, 1.0f, 0.0f, 1.0f);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::make_stereo_display_region
// Access: Published
// Description: Creates a new DisplayRegion that covers the entire
// window.
//
// This always returns a stereo DisplayRegion, even if
// is_stereo() is false.
////////////////////////////////////////////////////////////////////
INLINE StereoDisplayRegion *GraphicsOutput::
make_stereo_display_region(float l, float r, float b, float t) {
return make_stereo_display_region(LVecBase4f(l, r, b, t));
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::get_overlay_display_region
// Access: Published
// Description: Returns the special "overlay" DisplayRegion that is
// created for each window or buffer. This
// DisplayRegion covers the entire window, but cannot be
// used for rendering. It is a placeholder only, to
// indicate the dimensions of the window, and is usually
// used internally for purposes such as clearing the
// window, or grabbing a screenshot of the window.
//
// There are very few applications that require access
// to this DisplayRegion. Normally, you should create
// your own DisplayRegion that covers the window, if you
// want to render to the window.
////////////////////////////////////////////////////////////////////
INLINE DisplayRegion *GraphicsOutput::
get_overlay_display_region() const {
return _overlay_display_region;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::make_screenshot_filename
// Access: Published, Static
@ -563,7 +736,7 @@ make_screenshot_filename(const string &prefix) {
////////////////////////////////////////////////////////////////////
INLINE Filename GraphicsOutput::
save_screenshot_default(const string &prefix) {
return _default_display_region->save_screenshot_default(prefix);
return _overlay_display_region->save_screenshot_default(prefix);
}
////////////////////////////////////////////////////////////////////
@ -578,7 +751,7 @@ save_screenshot_default(const string &prefix) {
////////////////////////////////////////////////////////////////////
INLINE bool GraphicsOutput::
save_screenshot(const Filename &filename, const string &image_comment) {
return _default_display_region->save_screenshot(filename, image_comment);
return _overlay_display_region->save_screenshot(filename, image_comment);
}
////////////////////////////////////////////////////////////////////
@ -590,7 +763,7 @@ save_screenshot(const Filename &filename, const string &image_comment) {
////////////////////////////////////////////////////////////////////
INLINE bool GraphicsOutput::
get_screenshot(PNMImage &image) {
return _default_display_region->get_screenshot(image);
return _overlay_display_region->get_screenshot(image);
}
////////////////////////////////////////////////////////////////////

View File

@ -74,7 +74,8 @@ GraphicsOutput(GraphicsEngine *engine, GraphicsPipe *pipe,
const WindowProperties &win_prop,
int flags,
GraphicsStateGuardian *gsg,
GraphicsOutput *host) :
GraphicsOutput *host,
bool default_stereo_flags) :
_lock("GraphicsOutput"),
_cull_window_pcollector(_cull_pcollector, name),
_draw_window_pcollector(_draw_pcollector, name)
@ -109,6 +110,9 @@ GraphicsOutput(GraphicsEngine *engine, GraphicsPipe *pipe,
_red_blue_stereo = false;
_left_eye_color_mask = 0x0f;
_right_eye_color_mask = 0x0f;
_side_by_side_stereo = false;
_sbs_left_dimensions.set(0.0f, 1.0f, 0.0f, 1.0f);
_sbs_right_dimensions.set(0.0f, 1.0f, 0.0f, 1.0f);
_delete_flag = false;
_texture_card = 0;
_trigger_copy = false;
@ -119,11 +123,28 @@ GraphicsOutput(GraphicsEngine *engine, GraphicsPipe *pipe,
_draw_buffer_type = RenderBuffer::T_back;
}
if (default_stereo_flags) {
// Check the config variables to see if we should make this a
// "stereo" buffer or window.
_red_blue_stereo = red_blue_stereo && !fb_prop.is_stereo();
if (_red_blue_stereo) {
_left_eye_color_mask = parse_color_mask(red_blue_stereo_colors.get_word(0));
_right_eye_color_mask = parse_color_mask(red_blue_stereo_colors.get_word(1));
}
_side_by_side_stereo = side_by_side_stereo && !fb_prop.is_stereo();
if (_side_by_side_stereo) {
_sbs_left_dimensions.set(sbs_left_dimensions[0], sbs_left_dimensions[1],
sbs_left_dimensions[2], sbs_left_dimensions[3]);
_sbs_right_dimensions.set(sbs_right_dimensions[0], sbs_right_dimensions[1],
sbs_right_dimensions[2], sbs_right_dimensions[3]);
}
}
// We start out with one DisplayRegion that covers the whole window,
// which we may use internally for full-window operations like
// clear() and get_screenshot().
_default_display_region = make_mono_display_region(0.0f, 1.0f, 0.0f, 1.0f);
_default_display_region->set_active(false);
_overlay_display_region = make_mono_display_region(0.0f, 1.0f, 0.0f, 1.0f);
_overlay_display_region->set_active(false);
_display_regions_stale = false;
@ -206,7 +227,7 @@ GraphicsOutput::
_total_display_regions.clear();
_active_display_regions.clear();
_default_display_region = NULL;
_overlay_display_region = NULL;
}
////////////////////////////////////////////////////////////////////
@ -442,6 +463,64 @@ set_inverted(bool inverted) {
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::set_side_by_side_stereo
// Access: Published
// Description: Enables side-by-side stereo mode on this particular
// window. When side-by-side stereo mode is in effect,
// DisplayRegions that have the "left" channel set will
// render on the part of the window specified by
// sbs_left_dimensions (typically the left half: (0,
// 0.5, 0, 1)), while DisplayRegions that have the
// "right" channel set will render on the part of the
// window specified by sbs_right_dimensions (typically
// the right half: (0.5, 1, 0, 1)).
//
// This is commonly used in a dual-monitor mode, where a
// window is opened that spans two monitors, and each
// monitor represents a different eye.
////////////////////////////////////////////////////////////////////
void GraphicsOutput::
set_side_by_side_stereo(bool side_by_side_stereo) {
LVecBase4f left, right;
left.set(sbs_left_dimensions[0], sbs_left_dimensions[1],
sbs_left_dimensions[2], sbs_left_dimensions[3]);
right.set(sbs_right_dimensions[0], sbs_right_dimensions[1],
sbs_right_dimensions[2], sbs_right_dimensions[3]);
set_side_by_side_stereo(side_by_side_stereo, left, right);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::set_side_by_side_stereo
// Access: Published
// Description: Enables side-by-side stereo mode on this particular
// window. When side-by-side stereo mode is in effect,
// DisplayRegions that have the "left" channel set will
// render on the part of the window specified by
// sbs_left_dimensions (typically the left half: (0,
// 0.5, 0, 1)), while DisplayRegions that have the
// "right" channel set will render on the part of the
// window specified by sbs_right_dimensions (typically
// the right half: (0.5, 1, 0, 1)).
//
// This is commonly used in a dual-monitor mode, where a
// window is opened that spans two monitors, and each
// monitor represents a different eye.
////////////////////////////////////////////////////////////////////
void GraphicsOutput::
set_side_by_side_stereo(bool side_by_side_stereo,
const LVecBase4f &sbs_left_dimensions,
const LVecBase4f &sbs_right_dimensions) {
_side_by_side_stereo = side_by_side_stereo;
if (_side_by_side_stereo) {
_sbs_left_dimensions = sbs_left_dimensions;
_sbs_right_dimensions = sbs_right_dimensions;
} else {
_sbs_left_dimensions.set(0.0f, 1.0f, 0.0f, 1.0f);
_sbs_right_dimensions.set(0.0f, 1.0f, 0.0f, 1.0f);
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::set_sort
// Access: Published, Virtual
@ -473,11 +552,11 @@ set_sort(int sort) {
// one or the other.
////////////////////////////////////////////////////////////////////
DisplayRegion *GraphicsOutput::
make_display_region(float l, float r, float b, float t) {
make_display_region(const LVecBase4f &dimensions) {
if (is_stereo() && default_stereo_camera) {
return make_stereo_display_region(l, r, b, t);
return make_stereo_display_region(dimensions);
} else {
return make_mono_display_region(l, r, b, t);
return make_mono_display_region(dimensions);
}
}
@ -488,12 +567,23 @@ make_display_region(float l, float r, float b, float t) {
// sub-rectangle within the window. The range on all
// parameters is 0..1.
//
// This always returns a mono DisplayRegion, even if
// is_stereo() is true.
// This generally returns a mono DisplayRegion, even if
// is_stereo() is true. However, if side-by-side stereo
// is enabled, this will return a StereoDisplayRegion
// whose two eyes are both set to SC_mono. (This is
// necessary because in side-by-side stereo mode, it is
// necessary to draw even mono DisplayRegions twice).
////////////////////////////////////////////////////////////////////
DisplayRegion *GraphicsOutput::
make_mono_display_region(float l, float r, float b, float t) {
return add_display_region(new DisplayRegion(this, l, r, b, t));
make_mono_display_region(const LVecBase4f &dimensions) {
if (_side_by_side_stereo) {
StereoDisplayRegion *dr = make_stereo_display_region(dimensions);
dr->get_left_eye()->set_stereo_channel(Lens::SC_mono);
dr->get_right_eye()->set_stereo_channel(Lens::SC_mono);
return dr;
}
return add_display_region(new DisplayRegion(this, dimensions));
}
////////////////////////////////////////////////////////////////////
@ -507,11 +597,40 @@ make_mono_display_region(float l, float r, float b, float t) {
// is_stereo() is false.
////////////////////////////////////////////////////////////////////
StereoDisplayRegion *GraphicsOutput::
make_stereo_display_region(float l, float r, float b, float t) {
PT(DisplayRegion) left = new DisplayRegion(this, l, r, b, t);
PT(DisplayRegion) right = new DisplayRegion(this, l, r, b, t);
make_stereo_display_region(const LVecBase4f &dimensions) {
PT(DisplayRegion) left, right;
PT(StereoDisplayRegion) stereo = new StereoDisplayRegion(this, l, r, b, t,
if (_side_by_side_stereo) {
// On a side-by-side stereo window, each eye gets the
// corresponding dimensions of its own sub-region.
float left_l = _sbs_left_dimensions[0];
float left_b = _sbs_left_dimensions[2];
float left_w = _sbs_left_dimensions[1] - _sbs_left_dimensions[0];
float left_h = _sbs_left_dimensions[3] - _sbs_left_dimensions[2];
LVecBase4f left_dimensions(dimensions[0] * left_w + left_l,
dimensions[1] * left_w + left_l,
dimensions[2] * left_h + left_b,
dimensions[3] * left_h + left_b);
left = new DisplayRegion(this, left_dimensions);
float right_l = _sbs_right_dimensions[0];
float right_b = _sbs_right_dimensions[2];
float right_w = _sbs_right_dimensions[1] - _sbs_right_dimensions[0];
float right_h = _sbs_right_dimensions[3] - _sbs_right_dimensions[2];
LVecBase4f right_dimensions(dimensions[0] * right_w + right_l,
dimensions[1] * right_w + right_l,
dimensions[2] * right_h + right_b,
dimensions[3] * right_h + right_b);
right = new DisplayRegion(this, right_dimensions);
} else {
// Not a side-by-side stereo window; thus, both the left and right
// eyes are the same region: the region specified.
left = new DisplayRegion(this, dimensions);
right = new DisplayRegion(this, dimensions);
}
PT(StereoDisplayRegion) stereo = new StereoDisplayRegion(this, dimensions,
left, right);
add_display_region(stereo);
add_display_region(left);
@ -533,7 +652,7 @@ bool GraphicsOutput::
remove_display_region(DisplayRegion *display_region) {
LightMutexHolder holder(_lock);
nassertr(display_region != _default_display_region, false);
nassertr(display_region != _overlay_display_region, false);
if (display_region->is_stereo()) {
StereoDisplayRegion *sdr;
@ -560,17 +679,42 @@ remove_all_display_regions() {
dri != _total_display_regions.end();
++dri) {
DisplayRegion *display_region = (*dri);
if (display_region != _default_display_region) {
if (display_region != _overlay_display_region) {
// Let's aggressively clean up the display region too.
display_region->cleanup();
display_region->_window = NULL;
}
}
_total_display_regions.clear();
_total_display_regions.push_back(_default_display_region);
_total_display_regions.push_back(_overlay_display_region);
_display_regions_stale = true;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::set_overlay_display_region
// Access: Published
// Description: Replaces the special "overlay" DisplayRegion that is
// created for each window or buffer. See
// get_overlay_display_region(). This must be a new
// DisplayRegion that has already been created for this
// window, for instance via a call to
// make_mono_display_region(). You are responsible for
// ensuring that the new DisplayRegion covers the entire
// window. The previous overlay display region is not
// automatically removed; you must explicitly call
// remove_display_region() on it after replacing it with
// this method, if you wish it to be removed.
//
// Normally, there is no reason to change the overlay
// DisplayRegion, so this method should be used only
// in very unusual circumstances.
////////////////////////////////////////////////////////////////////
void GraphicsOutput::
set_overlay_display_region(DisplayRegion *display_region) {
nassertv(display_region->get_window() == this);
_overlay_display_region = display_region;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::get_num_display_regions
// Access: Published
@ -653,128 +797,6 @@ get_active_display_region(int n) const {
return result;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOuput::create_texture_card_vdata
// Access: Private
// Description: Generates a GeomVertexData for a texture card.
////////////////////////////////////////////////////////////////////
PT(GeomVertexData) GraphicsOutput::
create_texture_card_vdata(int x, int y) {
float xhi = 1.0;
float yhi = 1.0;
if (Texture::get_textures_power_2() != ATS_none) {
int xru = Texture::up_to_power_2(x);
int yru = Texture::up_to_power_2(y);
xhi = (x * 1.0f) / xru;
yhi = (y * 1.0f) / yru;
}
CPT(GeomVertexFormat) format = GeomVertexFormat::get_v3n3t2();
PT(GeomVertexData) vdata = new GeomVertexData
("card", format, Geom::UH_static);
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
GeomVertexWriter normal(vdata, InternalName::get_normal());
vertex.add_data3f(Vertexf::rfu(-1.0f, 0.0f, 1.0f));
vertex.add_data3f(Vertexf::rfu(-1.0f, 0.0f, -1.0f));
vertex.add_data3f(Vertexf::rfu( 1.0f, 0.0f, 1.0f));
vertex.add_data3f(Vertexf::rfu( 1.0f, 0.0f, -1.0f));
texcoord.add_data2f( 0.0f, yhi);
texcoord.add_data2f( 0.0f, 0.0f);
texcoord.add_data2f( xhi, yhi);
texcoord.add_data2f( xhi, 0.0f);
normal.add_data3f(LVector3f::back());
normal.add_data3f(LVector3f::back());
normal.add_data3f(LVector3f::back());
normal.add_data3f(LVector3f::back());
return vdata;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::set_size_and_recalc
// Access: Public
// Description: Changes the x_size and y_size, then recalculates
// structures that depend on size. The recalculation
// currently includes:
// - compute_pixels on all the graphics regions.
// - updating the texture card, if one is present.
////////////////////////////////////////////////////////////////////
void GraphicsOutput::
set_size_and_recalc(int x, int y) {
_x_size = x;
_y_size = y;
_has_size = true;
int fb_x_size = get_fb_x_size();
int fb_y_size = get_fb_y_size();
TotalDisplayRegions::iterator dri;
for (dri = _total_display_regions.begin();
dri != _total_display_regions.end();
++dri) {
(*dri)->compute_pixels_all_stages(fb_x_size, fb_y_size);
}
if (_texture_card != 0) {
_texture_card->set_vertex_data(create_texture_card_vdata(x, y));
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::get_texture_card
// Access: Published
// Description: Returns a PandaNode containing a square polygon.
// The dimensions are (-1,0,-1) to (1,0,1). The texture
// coordinates are such that the texture of this
// GraphicsOutput is aligned properly to the polygon.
// The GraphicsOutput promises to surgically update
// the Geom inside the PandaNode if necessary to maintain
// this invariant.
//
// Each invocation of this function returns a freshly-
// allocated PandaNode. You can therefore safely modify
// the RenderAttribs of the PandaNode. The
// PandaNode is initially textured with the texture
// of this GraphicOutput.
////////////////////////////////////////////////////////////////////
NodePath GraphicsOutput::
get_texture_card() {
if (_texture_card == 0) {
PT(GeomVertexData) vdata = create_texture_card_vdata(_x_size, _y_size);
PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
strip->set_shade_model(Geom::SM_uniform);
strip->add_next_vertices(4);
strip->close_primitive();
_texture_card = new Geom(vdata);
_texture_card->add_primitive(strip);
}
PT(GeomNode) gnode = new GeomNode("texture card");
gnode->add_geom(_texture_card);
NodePath path(gnode);
// The texture card, by default, is textured with the first
// render-to-texture output texture. Depth and stencil
// textures are ignored. The user can freely alter the
// card's texture attrib.
for (int i=0; i<count_textures(); i++) {
Texture *texture = get_texture(i);
if ((texture->get_format() != Texture::F_depth_stencil)) {
path.set_texture(texture, 0);
break;
}
}
return path;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::make_texture_buffer
// Access: Published
@ -929,6 +951,75 @@ make_cube_map(const string &name, int size, NodePath &camera_rig,
return buffer;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::get_texture_card
// Access: Published
// Description: Returns a PandaNode containing a square polygon.
// The dimensions are (-1,0,-1) to (1,0,1). The texture
// coordinates are such that the texture of this
// GraphicsOutput is aligned properly to the polygon.
// The GraphicsOutput promises to surgically update
// the Geom inside the PandaNode if necessary to maintain
// this invariant.
//
// Each invocation of this function returns a freshly-
// allocated PandaNode. You can therefore safely modify
// the RenderAttribs of the PandaNode. The
// PandaNode is initially textured with the texture
// of this GraphicOutput.
////////////////////////////////////////////////////////////////////
NodePath GraphicsOutput::
get_texture_card() {
if (_texture_card == 0) {
PT(GeomVertexData) vdata = create_texture_card_vdata(_x_size, _y_size);
PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
strip->set_shade_model(Geom::SM_uniform);
strip->add_next_vertices(4);
strip->close_primitive();
_texture_card = new Geom(vdata);
_texture_card->add_primitive(strip);
}
PT(GeomNode) gnode = new GeomNode("texture card");
gnode->add_geom(_texture_card);
NodePath path(gnode);
// The texture card, by default, is textured with the first
// render-to-texture output texture. Depth and stencil
// textures are ignored. The user can freely alter the
// card's texture attrib.
for (int i=0; i<count_textures(); i++) {
Texture *texture = get_texture(i);
if ((texture->get_format() != Texture::F_depth_stencil)) {
path.set_texture(texture, 0);
break;
}
}
return path;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::share_depth_buffer
// Access: Published, Virtual
// Description: Will attempt to use the depth buffer of the input
// graphics_output. The buffer sizes must be exactly
// the same.
////////////////////////////////////////////////////////////////////
bool GraphicsOutput::
share_depth_buffer(GraphicsOutput *graphics_output) {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::unshare_depth_buffer
// Access: Published, Virtual
// Description: Discontinue sharing the depth buffer.
////////////////////////////////////////////////////////////////////
void GraphicsOutput::
unshare_depth_buffer() {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::get_host
// Access: Public, Virtual
@ -1004,71 +1095,33 @@ clear_pipe() {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::begin_frame
// Access: Public, Virtual
// Description: This function will be called within the draw thread
// before beginning rendering for a given frame. It
// should do whatever setup is required, and return true
// if the frame should be rendered, or false if it
// should be skipped.
////////////////////////////////////////////////////////////////////
bool GraphicsOutput::
begin_frame(FrameMode mode, Thread *current_thread) {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::end_frame
// Access: Public, Virtual
// Description: This function will be called within the draw thread
// after rendering is completed for a given frame. It
// should do whatever finalization is required.
// Function: GraphicsOutput::set_size_and_recalc
// Access: Public
// Description: Changes the x_size and y_size, then recalculates
// structures that depend on size. The recalculation
// currently includes:
// - compute_pixels on all the graphics regions.
// - updating the texture card, if one is present.
////////////////////////////////////////////////////////////////////
void GraphicsOutput::
end_frame(FrameMode mode, Thread *current_thread) {
}
set_size_and_recalc(int x, int y) {
_x_size = x;
_y_size = y;
_has_size = true;
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::pixel_factor_changed
// Access: Published, Virtual
// Description: Called internally when the pixel factor changes.
////////////////////////////////////////////////////////////////////
void GraphicsOutput::
pixel_factor_changed() {
if (_has_size) {
set_size_and_recalc(_x_size, _y_size);
}
}
int fb_x_size = get_fb_x_size();
int fb_y_size = get_fb_y_size();
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::prepare_for_deletion
// Access: Protected
// Description: Set the delete flag, and do the usual cleanup
// activities associated with that.
////////////////////////////////////////////////////////////////////
void GraphicsOutput::
prepare_for_deletion() {
_active = false;
_delete_flag = true;
// We have to be sure to remove all of the display regions
// immediately, so that circular reference counts can be cleared
// up (each display region keeps a pointer to a CullResult,
// which can hold all sorts of pointers).
remove_all_display_regions();
// If we were rendering directly to texture, we can't delete the
// buffer until the texture is gone too.
for (int i=0; i<count_textures(); i++) {
if (get_rtm_mode(i) == RTM_bind_or_copy) {
_hold_textures.push_back(get_texture(i));
}
TotalDisplayRegions::iterator dri;
for (dri = _total_display_regions.begin();
dri != _total_display_regions.end();
++dri) {
(*dri)->compute_pixels_all_stages(fb_x_size, fb_y_size);
}
// We have to be sure to clear the _textures pointers, though, or
// we'll end up holding a reference to the textures forever.
clear_render_textures();
if (_texture_card != 0) {
_texture_card->set_vertex_data(create_texture_card_vdata(x, y));
}
}
////////////////////////////////////////////////////////////////////
@ -1092,82 +1145,35 @@ clear(Thread *current_thread) {
nassertv(_gsg != (GraphicsStateGuardian *)NULL);
DisplayRegionPipelineReader dr_reader(_default_display_region, current_thread);
DisplayRegionPipelineReader dr_reader(_overlay_display_region, current_thread);
_gsg->prepare_display_region(&dr_reader, Lens::SC_mono);
_gsg->clear(this);
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::copy_to_textures
// Access: Protected
// Description: For all textures marked RTM_copy_texture,
// RTM_copy_ram, RTM_triggered_copy_texture, or
// RTM_triggered_copy_ram, do the necessary copies.
//
// Returns true if all copies are successful, false
// otherwise.
// Function: GraphicsOutput::begin_frame
// Access: Public, Virtual
// Description: This function will be called within the draw thread
// before beginning rendering for a given frame. It
// should do whatever setup is required, and return true
// if the frame should be rendered, or false if it
// should be skipped.
////////////////////////////////////////////////////////////////////
bool GraphicsOutput::
copy_to_textures() {
bool okflag = true;
for (int i = 0; i < count_textures(); ++i) {
RenderTextureMode rtm_mode = get_rtm_mode(i);
if ((rtm_mode == RTM_none) || (rtm_mode == RTM_bind_or_copy)) {
continue;
}
begin_frame(FrameMode mode, Thread *current_thread) {
return false;
}
Texture *texture = get_texture(i);
PStatTimer timer(_copy_texture_pcollector);
nassertr(has_texture(), false);
if ((rtm_mode == RTM_copy_texture)||
(rtm_mode == RTM_copy_ram)||
((rtm_mode == RTM_triggered_copy_texture)&&(_trigger_copy))||
((rtm_mode == RTM_triggered_copy_ram)&&(_trigger_copy))) {
if (display_cat.is_debug()) {
display_cat.debug()
<< "Copying texture for " << get_name() << " at frame end.\n";
display_cat.debug()
<< "cube_map_index = " << _cube_map_index << "\n";
}
int plane = get_texture_plane(i);
RenderBuffer buffer(_gsg, DrawableRegion::get_renderbuffer_type(plane));
if (plane == RTP_color) {
buffer = _gsg->get_render_buffer(get_draw_buffer_type(),
get_fb_properties());
}
bool copied = false;
if (_cube_map_dr != (DisplayRegion *)NULL) {
if ((rtm_mode == RTM_copy_ram)||(rtm_mode == RTM_triggered_copy_ram)) {
copied =
_gsg->framebuffer_copy_to_ram(texture, _cube_map_index,
_cube_map_dr, buffer);
} else {
copied =
_gsg->framebuffer_copy_to_texture(texture, _cube_map_index,
_cube_map_dr, buffer);
}
} else {
if ((rtm_mode == RTM_copy_ram)||(rtm_mode == RTM_triggered_copy_ram)) {
copied =
_gsg->framebuffer_copy_to_ram(texture, _cube_map_index,
_default_display_region, buffer);
} else {
copied =
_gsg->framebuffer_copy_to_texture(texture, _cube_map_index,
_default_display_region, buffer);
}
}
if (!copied) {
okflag = false;
}
}
}
_trigger_copy = false;
return okflag;
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::end_frame
// Access: Public, Virtual
// Description: This function will be called within the draw thread
// after rendering is completed for a given frame. It
// should do whatever finalization is required.
////////////////////////////////////////////////////////////////////
void GraphicsOutput::
end_frame(FrameMode mode, Thread *current_thread) {
}
////////////////////////////////////////////////////////////////////
@ -1299,6 +1305,164 @@ void GraphicsOutput::
process_events() {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::pixel_factor_changed
// Access: Published, Virtual
// Description: Called internally when the pixel factor changes.
////////////////////////////////////////////////////////////////////
void GraphicsOutput::
pixel_factor_changed() {
if (_has_size) {
set_size_and_recalc(_x_size, _y_size);
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::prepare_for_deletion
// Access: Protected
// Description: Set the delete flag, and do the usual cleanup
// activities associated with that.
////////////////////////////////////////////////////////////////////
void GraphicsOutput::
prepare_for_deletion() {
_active = false;
_delete_flag = true;
// We have to be sure to remove all of the display regions
// immediately, so that circular reference counts can be cleared
// up (each display region keeps a pointer to a CullResult,
// which can hold all sorts of pointers).
remove_all_display_regions();
// If we were rendering directly to texture, we can't delete the
// buffer until the texture is gone too.
for (int i=0; i<count_textures(); i++) {
if (get_rtm_mode(i) == RTM_bind_or_copy) {
_hold_textures.push_back(get_texture(i));
}
}
// We have to be sure to clear the _textures pointers, though, or
// we'll end up holding a reference to the textures forever.
clear_render_textures();
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::copy_to_textures
// Access: Protected
// Description: For all textures marked RTM_copy_texture,
// RTM_copy_ram, RTM_triggered_copy_texture, or
// RTM_triggered_copy_ram, do the necessary copies.
//
// Returns true if all copies are successful, false
// otherwise.
////////////////////////////////////////////////////////////////////
bool GraphicsOutput::
copy_to_textures() {
bool okflag = true;
for (int i = 0; i < count_textures(); ++i) {
RenderTextureMode rtm_mode = get_rtm_mode(i);
if ((rtm_mode == RTM_none) || (rtm_mode == RTM_bind_or_copy)) {
continue;
}
Texture *texture = get_texture(i);
PStatTimer timer(_copy_texture_pcollector);
nassertr(has_texture(), false);
if ((rtm_mode == RTM_copy_texture)||
(rtm_mode == RTM_copy_ram)||
((rtm_mode == RTM_triggered_copy_texture)&&(_trigger_copy))||
((rtm_mode == RTM_triggered_copy_ram)&&(_trigger_copy))) {
if (display_cat.is_debug()) {
display_cat.debug()
<< "Copying texture for " << get_name() << " at frame end.\n";
display_cat.debug()
<< "cube_map_index = " << _cube_map_index << "\n";
}
int plane = get_texture_plane(i);
RenderBuffer buffer(_gsg, DrawableRegion::get_renderbuffer_type(plane));
if (plane == RTP_color) {
buffer = _gsg->get_render_buffer(get_draw_buffer_type(),
get_fb_properties());
}
bool copied = false;
if (_cube_map_dr != (DisplayRegion *)NULL) {
if ((rtm_mode == RTM_copy_ram)||(rtm_mode == RTM_triggered_copy_ram)) {
copied =
_gsg->framebuffer_copy_to_ram(texture, _cube_map_index,
_cube_map_dr, buffer);
} else {
copied =
_gsg->framebuffer_copy_to_texture(texture, _cube_map_index,
_cube_map_dr, buffer);
}
} else {
if ((rtm_mode == RTM_copy_ram)||(rtm_mode == RTM_triggered_copy_ram)) {
copied =
_gsg->framebuffer_copy_to_ram(texture, _cube_map_index,
_overlay_display_region, buffer);
} else {
copied =
_gsg->framebuffer_copy_to_texture(texture, _cube_map_index,
_overlay_display_region, buffer);
}
}
if (!copied) {
okflag = false;
}
}
}
_trigger_copy = false;
return okflag;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOuput::create_texture_card_vdata
// Access: Private
// Description: Generates a GeomVertexData for a texture card.
////////////////////////////////////////////////////////////////////
PT(GeomVertexData) GraphicsOutput::
create_texture_card_vdata(int x, int y) {
float xhi = 1.0;
float yhi = 1.0;
if (Texture::get_textures_power_2() != ATS_none) {
int xru = Texture::up_to_power_2(x);
int yru = Texture::up_to_power_2(y);
xhi = (x * 1.0f) / xru;
yhi = (y * 1.0f) / yru;
}
CPT(GeomVertexFormat) format = GeomVertexFormat::get_v3n3t2();
PT(GeomVertexData) vdata = new GeomVertexData
("card", format, Geom::UH_static);
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
GeomVertexWriter normal(vdata, InternalName::get_normal());
vertex.add_data3f(Vertexf::rfu(-1.0f, 0.0f, 1.0f));
vertex.add_data3f(Vertexf::rfu(-1.0f, 0.0f, -1.0f));
vertex.add_data3f(Vertexf::rfu( 1.0f, 0.0f, 1.0f));
vertex.add_data3f(Vertexf::rfu( 1.0f, 0.0f, -1.0f));
texcoord.add_data2f( 0.0f, yhi);
texcoord.add_data2f( 0.0f, 0.0f);
texcoord.add_data2f( xhi, yhi);
texcoord.add_data2f( xhi, 0.0f);
normal.add_data3f(LVector3f::back());
normal.add_data3f(LVector3f::back());
normal.add_data3f(LVector3f::back());
normal.add_data3f(LVector3f::back());
return vdata;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::add_display_region
// Access: Private
@ -1322,7 +1486,7 @@ add_display_region(DisplayRegion *display_region) {
////////////////////////////////////////////////////////////////////
bool GraphicsOutput::
do_remove_display_region(DisplayRegion *display_region) {
nassertr(display_region != _default_display_region, false);
nassertr(display_region != _overlay_display_region, false);
PT(DisplayRegion) drp = display_region;
TotalDisplayRegions::iterator dri =
@ -1374,6 +1538,56 @@ do_determine_display_regions() {
stable_sort(_active_display_regions.begin(), _active_display_regions.end(), IndirectLess<DisplayRegion>());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::parse_color_mask
// Access: Private, Static
// Description: Parses one of the keywords in the
// red-blue-stereo-colors Config.prc variable, and
// returns the corresponding bitmask.
//
// These bitmask values are taken from ColorWriteAttrib.
////////////////////////////////////////////////////////////////////
unsigned int GraphicsOutput::
parse_color_mask(const string &word) {
unsigned int result = 0;
vector_string components;
tokenize(word, components, "|");
vector_string::const_iterator ci;
for (ci = components.begin(); ci != components.end(); ++ci) {
string w = downcase(*ci);
if (w == "red" || w == "r") {
result |= 0x001;
} else if (w == "green" || w == "g") {
result |= 0x002;
} else if (w == "blue" || w == "b") {
result |= 0x004;
} else if (w == "yellow" || w == "y") {
result |= 0x003;
} else if (w == "magenta" || w == "m") {
result |= 0x005;
} else if (w == "cyan" || w == "c") {
result |= 0x006;
} else if (w == "alpha" || w == "a") {
result |= 0x008;
} else if (w == "off") {
} else {
display_cat.warning()
<< "Invalid color in red-blue-stereo-colors: " << (*ci) << "\n";
}
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::FrameMode output operator
// Description:
@ -1391,25 +1605,3 @@ operator << (ostream &out, GraphicsOutput::FrameMode fm) {
return out << "(**invalid GraphicsOutput::FrameMode(" << (int)fm << ")**)";
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::share_depth_buffer
// Access: Published, Virtual
// Description: Will attempt to use the depth buffer of the input
// graphics_output. The buffer sizes must be exactly
// the same.
////////////////////////////////////////////////////////////////////
bool GraphicsOutput::
share_depth_buffer(GraphicsOutput *graphics_output) {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::unshare_depth_buffer
// Access: Published, Virtual
// Description: Discontinue sharing the depth buffer.
////////////////////////////////////////////////////////////////////
void GraphicsOutput::
unshare_depth_buffer() {
}

View File

@ -24,7 +24,7 @@
#include "drawableRegion.h"
#include "renderBuffer.h"
#include "graphicsOutputBase.h"
#include "luse.h"
#include "typedWritableReferenceCount.h"
#include "pandaNode.h"
#include "pStatCollector.h"
@ -67,7 +67,8 @@ protected:
const FrameBufferProperties &fb_prop,
const WindowProperties &win_prop, int flags,
GraphicsStateGuardian *gsg,
GraphicsOutput *host);
GraphicsOutput *host,
bool default_stereo_flags);
private:
GraphicsOutput(const GraphicsOutput &copy);
@ -111,6 +112,10 @@ PUBLISHED:
INLINE int get_y_size() const;
INLINE int get_fb_x_size() const;
INLINE int get_fb_y_size() const;
INLINE int get_sbs_left_x_size() const;
INLINE int get_sbs_left_y_size() const;
INLINE int get_sbs_right_x_size() const;
INLINE int get_sbs_right_y_size() const;
INLINE bool has_size() const;
INLINE bool is_valid() const;
@ -130,6 +135,14 @@ PUBLISHED:
INLINE unsigned int get_left_eye_color_mask() const;
INLINE unsigned int get_right_eye_color_mask() const;
void set_side_by_side_stereo(bool side_by_side_stereo);
void set_side_by_side_stereo(bool side_by_side_stereo,
const LVecBase4f &sbs_left_dimensions,
const LVecBase4f &sbs_right_dimensions);
INLINE bool get_side_by_side_stereo() const;
INLINE const LVecBase4f &get_sbs_left_dimensions() const;
INLINE const LVecBase4f &get_sbs_right_dimensions() const;
INLINE const FrameBufferProperties &get_fb_properties() const;
INLINE bool is_stereo() const;
@ -146,14 +159,20 @@ PUBLISHED:
INLINE void trigger_copy();
INLINE DisplayRegion *make_display_region();
DisplayRegion *make_display_region(float l, float r, float b, float t);
INLINE DisplayRegion *make_display_region(float l, float r, float b, float t);
DisplayRegion *make_display_region(const LVecBase4f &dimensions);
INLINE DisplayRegion *make_mono_display_region();
DisplayRegion *make_mono_display_region(float l, float r, float b, float t);
INLINE DisplayRegion *make_mono_display_region(float l, float r, float b, float t);
DisplayRegion *make_mono_display_region(const LVecBase4f &dimensions);
INLINE StereoDisplayRegion *make_stereo_display_region();
StereoDisplayRegion *make_stereo_display_region(float l, float r, float b, float t);
INLINE StereoDisplayRegion *make_stereo_display_region(float l, float r, float b, float t);
StereoDisplayRegion *make_stereo_display_region(const LVecBase4f &dimensions);
bool remove_display_region(DisplayRegion *display_region);
void remove_all_display_regions();
INLINE DisplayRegion *get_overlay_display_region() const;
void set_overlay_display_region(DisplayRegion *display_region);
int get_num_display_regions() const;
PT(DisplayRegion) get_display_region(int n) const;
MAKE_SEQ(get_display_regions, get_num_display_regions, get_display_region);
@ -233,8 +252,20 @@ protected:
INLINE void clear_cube_map_selection();
INLINE void trigger_flip();
protected:
private:
PT(GeomVertexData) create_texture_card_vdata(int x, int y);
DisplayRegion *add_display_region(DisplayRegion *display_region);
bool do_remove_display_region(DisplayRegion *display_region);
INLINE void win_display_regions_changed();
INLINE void determine_display_regions() const;
void do_determine_display_regions();
static unsigned int parse_color_mask(const string &word);
protected:
class RenderTexture {
public:
PT(Texture) _texture;
@ -256,16 +287,6 @@ protected:
bool _trigger_copy;
private:
PT(GeomVertexData) create_texture_card_vdata(int x, int y);
DisplayRegion *add_display_region(DisplayRegion *display_region);
bool do_remove_display_region(DisplayRegion *display_region);
INLINE void win_display_regions_changed();
INLINE void determine_display_regions() const;
void do_determine_display_regions();
int _sort;
int _child_sort;
bool _got_child_sort;
@ -278,6 +299,9 @@ protected:
bool _red_blue_stereo;
unsigned int _left_eye_color_mask;
unsigned int _right_eye_color_mask;
bool _side_by_side_stereo;
LVecBase4f _sbs_left_dimensions;
LVecBase4f _sbs_right_dimensions;
bool _delete_flag;
// These weak pointers are used to keep track of whether the
@ -289,7 +313,7 @@ protected:
protected:
LightMutex _lock;
// protects _display_regions.
PT(DisplayRegion) _default_display_region;
PT(DisplayRegion) _overlay_display_region;
typedef pvector< PT(DisplayRegion) > TotalDisplayRegions;
TotalDisplayRegions _total_display_regions;
typedef pvector<DisplayRegion *> ActiveDisplayRegions;

View File

@ -1273,8 +1273,8 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4f
// Description: Return a pointer to struct ShaderPtrData
////////////////////////////////////////////////////////////////////
const Shader::ShaderPtrData *GraphicsStateGuardian::
fetch_ptr_parameter(const Shader::ShaderPtrSpec& spec){
return (_target_shader->get_shader_input_ptr(spec._arg));
fetch_ptr_parameter(const Shader::ShaderPtrSpec& spec) {
return (_target_shader->get_shader_input_ptr(spec._arg));
}
////////////////////////////////////////////////////////////////////

View File

@ -140,9 +140,6 @@ protected:
void system_changed_properties(const WindowProperties &properties);
void system_changed_size(int x_size, int y_size);
private:
static unsigned int parse_color_mask(const string &word);
protected:
INLINE void add_input_device(const GraphicsWindowInputDevice &device);
typedef vector_GraphicsWindowInputDevice InputDevices;

View File

@ -30,7 +30,7 @@ ParasiteBuffer(GraphicsOutput *host, const string &name,
GraphicsOutput(host->get_engine(), host->get_pipe(),
name, host->get_fb_properties(),
WindowProperties::size(x_size, y_size), flags,
host->get_gsg(), host)
host->get_gsg(), host, false)
{
#ifdef DO_MEMORY_USAGE
MemoryUsage::update_type(this, this);
@ -52,7 +52,7 @@ ParasiteBuffer(GraphicsOutput *host, const string &name,
_x_size = x_size;
_y_size = y_size;
_has_size = true;
_default_display_region->compute_pixels(_x_size, _y_size);
_overlay_display_region->compute_pixels(_x_size, _y_size);
_is_valid = true;
set_inverted(host->get_gsg()->get_copy_texture_inverted());

View File

@ -24,9 +24,9 @@ TypeHandle StereoDisplayRegion::_type_handle;
////////////////////////////////////////////////////////////////////
StereoDisplayRegion::
StereoDisplayRegion(GraphicsOutput *window,
float l, float r, float b, float t,
const LVecBase4f &dimensions,
DisplayRegion *left, DisplayRegion *right) :
DisplayRegion(window, l, r, b, t),
DisplayRegion(window, dimensions),
_left_eye(left),
_right_eye(right)
{
@ -115,10 +115,10 @@ set_pixel_zoom(float pixel_zoom) {
// indicated dimensions.
////////////////////////////////////////////////////////////////////
void StereoDisplayRegion::
set_dimensions(float l, float r, float b, float t) {
DisplayRegion::set_dimensions(l, r, b, t);
_left_eye->set_dimensions(l, r, b, t);
_right_eye->set_dimensions(l, r, b, t);
set_dimensions(const LVecBase4f &dimensions) {
DisplayRegion::set_dimensions(dimensions);
_left_eye->set_dimensions(dimensions);
_right_eye->set_dimensions(dimensions);
}
////////////////////////////////////////////////////////////////////

View File

@ -37,7 +37,7 @@
class EXPCL_PANDA_DISPLAY StereoDisplayRegion : public DisplayRegion {
protected:
StereoDisplayRegion(GraphicsOutput *window,
float l, float r, float b, float t,
const LVecBase4f &dimensions,
DisplayRegion *left, DisplayRegion *right);
public:
@ -51,7 +51,7 @@ PUBLISHED:
virtual void set_pixel_zoom(float pixel_zoom);
// Inherited from DisplayRegion
virtual void set_dimensions(float l, float r, float b, float t);
virtual void set_dimensions(const LVecBase4f &dimensions);
virtual bool is_stereo() const;
virtual void set_camera(const NodePath &camera);
virtual void set_active(bool active);

View File

@ -192,7 +192,7 @@ begin_flip() {
bool copied =
_gsg->framebuffer_copy_to_ram(_texture, -1,
_default_display_region, buffer);
_overlay_display_region, buffer);
if (copied) {
CPTA_uchar image = _texture->get_ram_image();

View File

@ -336,8 +336,8 @@ get_aspect_2d() {
this_aspect_ratio = 1.0f;
if (_window->has_size()) {
int x_size = _window->get_x_size();
int y_size = _window->get_y_size();
int x_size = _window->get_sbs_left_x_size();
int y_size = _window->get_sbs_left_y_size();
if (y_size != 0) {
this_aspect_ratio = (float)x_size / (float)y_size;
}
@ -370,7 +370,16 @@ get_mouse() {
// Another advantage to using a MouseWatcher is that the PGTop of
// aspect2d likes it better.
PT(MouseWatcher) mw = new MouseWatcher("watcher");
mw->set_display_region(_display_region_3d);
if (_window->get_side_by_side_stereo()) {
// If the window has side-by-side stereo enabled, then
// we should constrain the MouseWatcher to the window's
// DisplayRegion. This will enable the MouseWatcher to
// track the left and right halves of the screen
// individually.
mw->set_display_region(_window->get_overlay_display_region());
}
_mouse = mouse.attach_new_node(mw);
}
return _mouse;
@ -806,8 +815,8 @@ adjust_aspect_ratio() {
this_aspect_ratio = 1.0f;
if (_window->has_size()) {
x_size = _window->get_x_size();
y_size = _window->get_y_size();
x_size = _window->get_sbs_left_x_size();
y_size = _window->get_sbs_left_y_size();
if (y_size != 0) {
this_aspect_ratio = (float)x_size / (float)y_size;
}
@ -1151,8 +1160,8 @@ make_camera() {
// Otherwise, infer the aspect ratio from the window size. This
// does assume we have square pixels on our output device.
if (_window->has_size()) {
int x_size = _window->get_x_size();
int y_size = _window->get_y_size();
int x_size = _window->get_sbs_left_x_size();
int y_size = _window->get_sbs_left_y_size();
if (y_size != 0) {
lens->set_film_size(x_size, y_size);
}

View File

@ -151,20 +151,36 @@ triangulate() {
*/
choose_idx = 0;
// cerr << "got " << num_segments << " segments\n";
/*
cerr << "got " << num_segments << " segments\n";
for (i = 1; i < (int)seg.size(); ++i) {
segment_t &s = seg[i];
printf(" %d. (%g %g), (%g %g)\n", i, s.v0.x, s.v0.y, s.v1.x, s.v1.y);
printf(" root0 = %d, root1 = %d\n", s.root0, s.root1);
printf(" next = %d, prev = %d\n", s.next, s.prev);
}
*/
construct_trapezoids(num_segments);
while (construct_trapezoids(num_segments) != 0) {
// If there's an error, re-shuffle the index and try again.
Randomizer randomizer;
for (i = 0; i < num_segments; ++i) {
int j = randomizer.random_int(num_segments);
nassertv(j >= 0 && j < num_segments);
int t = permute[i];
permute[i] = permute[j];
permute[j] = t;
}
choose_idx = 0;
// cerr << "got " << tr.size() - 1 << " trapezoids\n";
/*
cerr << "got " << num_segments << " segments\n";
for (i = 1; i < (int)seg.size(); ++i) {
segment_t &s = seg[i];
printf(" %d. (%g %g), (%g %g)\n", i, s.v0.x, s.v0.y, s.v1.x, s.v1.y);
printf(" root0 = %d, root1 = %d\n", s.root0, s.root1);
printf(" next = %d, prev = %d\n", s.next, s.prev);
}
}
cerr << "got " << tr.size() - 1 << " trapezoids\n";
for (i = 1; i < (int)tr.size(); ++i) {
trap_t &t = tr[i];
cerr << " " << i << ". state = " << t.state << "\n";
@ -173,21 +189,17 @@ triangulate() {
cerr << " hi = " << t.hi.x << " " << t.hi.y << " lo = "
<< t.lo.x << " " << t.lo.y << "\n";
}
*/
int nmonpoly = monotonate_trapezoids(num_segments);
// cerr << "got " << nmonpoly << " monotone polygons\n";
cerr << "got " << nmonpoly << " monotone polygons\n";
triangulate_monotone_polygons(num_segments, nmonpoly);
/*
Result::iterator ri;
for (ri = _result.begin(); ri != _result.end(); ++ri) {
cerr << "tri: " << (*ri)._v0 << " " << (*ri)._v1 << " "
<< (*ri)._v2 << "\n";
}
*/
}
////////////////////////////////////////////////////////////////////
@ -822,7 +834,7 @@ merge_trapezoids(int segnum, int tfirst, int tlast, int side) {
int Triangulator::
add_segment(int segnum) {
// cerr << "add_segment(" << segnum << ")\n";
cerr << "add_segment(" << segnum << ")\n";
segment_t s;
// segment_t *so = &seg[segnum];
@ -1011,8 +1023,9 @@ add_segment(int segnum) {
if ((tr[t].d0 <= 0) && (tr[t].d1 <= 0)) /* case cannot arise */
{
/* Actually, this case does sometimes arise. Huh. */
fprintf(stderr, "add_segment: error\n");
break;
return 1;
}
/* only one trapezoid below. partition t into two and make the */
@ -1445,7 +1458,7 @@ find_new_roots(int segnum) {
/* Main routine to perform trapezoidation */
int Triangulator::
construct_trapezoids(int nseg) {
// cerr << "construct_trapezoids(" << nseg << ")\n";
cerr << "construct_trapezoids(" << nseg << ")\n";
int i;
int root, h;
@ -1462,7 +1475,10 @@ construct_trapezoids(int nseg) {
for (h = 1; h <= math_logstar_n(nseg); h++)
{
for (i = math_N(nseg, h -1) + 1; i <= math_N(nseg, h); i++) {
add_segment(choose_segment());
if (add_segment(choose_segment()) != 0) {
// error in add_segment.
return 1;
}
}
/* Find a new root for each of the segment endpoints */
@ -2129,7 +2145,7 @@ triangulate_single_polygon(int nvert, int posmax, int side) {
int ri;
int endv, tmp, vpos;
// cerr << "triangulate_single_polygon(" << nvert << ", " << posmax << ", " << side << ")\n";
cerr << "triangulate_single_polygon(" << nvert << ", " << posmax << ", " << side << ")\n";
if (side == TRI_RHS) /* RHS segment is a single segment */
{
@ -2160,6 +2176,8 @@ triangulate_single_polygon(int nvert, int posmax, int side) {
while ((v != endv) || (ri > 1))
{
cerr << " v = " << v << " ri = " << ri << " rc = " << rc.size()
<< " _result = " << _result.size() << "\n";
if (v <= 0) {
// Something went wrong.
return;

View File

@ -25,6 +25,7 @@
#include "dataNodeTransmit.h"
#include "transformState.h"
#include "displayRegion.h"
#include "stereoDisplayRegion.h"
#include "geomVertexWriter.h"
#include "geomLinestrips.h"
#include "geomPoints.h"
@ -1415,8 +1416,8 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
DCAST_INTO_V(xy, input.get_data(_xy_input).get_ptr());
DCAST_INTO_V(pixel_xy, input.get_data(_pixel_xy_input).get_ptr());
const LVecBase2f &f = xy->get_value();
const LVecBase2f &p = pixel_xy->get_value();
LVecBase2f f = xy->get_value();
LVecBase2f p = pixel_xy->get_value();
// Asad: determine if mouse moved from last position
const LVecBase2f &last_f = _xy->get_value();
@ -1427,41 +1428,16 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
if (_display_region != (DisplayRegion *)NULL) {
// If we've got a display region, constrain the mouse to it.
DisplayRegionPipelineReader dr_reader(_display_region, current_thread);
float left, right, bottom, top;
dr_reader.get_dimensions(left, right, bottom, top);
if (constrain_display_region(_display_region, f, p, current_thread)) {
set_mouse(f, p);
// Need to translate this into DisplayRegion [0, 1] space
float x = (f[0] + 1.0f) / 2.0f;
float y = (f[1] + 1.0f) / 2.0f;
if (x < left || x >= right ||
y < bottom || y >= top) {
} else {
// The mouse is outside the display region, even though it's
// within the window. This is considered not having a mouse.
set_no_mouse();
// This also means we should suppress mouse button events below us.
_internal_suppress |= MouseWatcherRegion::SF_mouse_button;
} else {
// The mouse is within the display region; rescale it.
// Scale in DR space
float xp = (x - left) / (right - left);
// Translate back into [-1, 1] space
float xpp = (xp * 2.0f) - 1.0f;
float yp = (y - bottom) / (top - bottom);
float ypp = (yp * 2.0f) - 1.0f;
int xo, yo, w, h;
dr_reader.get_region_pixels_i(xo, yo, w, h);
LVecBase2f new_f(xpp, ypp);
LVecBase2f new_p(p[0] - xo, p[1] - yo);
set_mouse(new_f, new_p);
}
} else {
@ -1678,3 +1654,59 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
output.set_data(_button_events_output, EventParameter(_button_events));
}
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcher::constrain_display_region
// Access: Private, Static
// Description: Constrains the mouse coordinates to within the
// indicated DisplayRegion. If the mouse pointer does
// indeed fall within the DisplayRegion, rescales f and
// p correspondingly, and returns true. If the mouse
// pointer does not fall within the DisplayRegion,
// leaves f and p unchanged, and returns false.
////////////////////////////////////////////////////////////////////
bool MouseWatcher::
constrain_display_region(DisplayRegion *display_region,
LVecBase2f &f, LVecBase2f &p,
Thread *current_thread) {
// If it's a stereo DisplayRegion, we should actually call this
// method twice, once for each eye, in case we have side-by-side
// stereo.
if (display_region->is_stereo()) {
StereoDisplayRegion *stereo_display_region;
DCAST_INTO_R(stereo_display_region, display_region, false);
return constrain_display_region(stereo_display_region->get_left_eye(), f, p, current_thread) ||
constrain_display_region(stereo_display_region->get_right_eye(), f, p, current_thread);
}
DisplayRegionPipelineReader dr_reader(display_region, current_thread);
float left, right, bottom, top;
dr_reader.get_dimensions(left, right, bottom, top);
// Need to translate this into DisplayRegion [0, 1] space
float x = (f[0] + 1.0f) / 2.0f;
float y = (f[1] + 1.0f) / 2.0f;
if (x < left || x >= right ||
y < bottom || y >= top) {
// The mouse is outside the display region.
return false;
}
// The mouse is within the display region; rescale it.
// Scale in DR space
float xp = (x - left) / (right - left);
// Translate back into [-1, 1] space
float xpp = (xp * 2.0f) - 1.0f;
float yp = (y - bottom) / (top - bottom);
float ypp = (yp * 2.0f) - 1.0f;
int xo, yo, w, h;
dr_reader.get_region_pixels_i(xo, yo, w, h);
f.set(xpp, ypp);
p.set(p[0] - xo, p[1] - yo);
return true;
}

View File

@ -206,6 +206,10 @@ private:
void consider_keyboard_suppress(const MouseWatcherRegion *region);
void discard_excess_trail_log();
void update_trail_node();
static bool constrain_display_region(DisplayRegion *display_region,
LVecBase2f &f, LVecBase2f &p,
Thread *current_thread);
private:
// This wants to be a set, but because you cannot export sets across