side-by-side stereo
This commit is contained in:
parent
9a3d16b1c5
commit
9124513b82
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 "
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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 ©) :
|
||||
_l(copy._l),
|
||||
_r(copy._r),
|
||||
_b(copy._b),
|
||||
_t(copy._t),
|
||||
_dimensions(copy._dimensions),
|
||||
_pl(copy._pl),
|
||||
_pr(copy._pr),
|
||||
_pb(copy._pb),
|
||||
|
|
|
|||
|
|
@ -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 ©);
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ©);
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue