misc...
	* render scene to FBO to get following options:
		preferences->camera->MSAA (def = 8 samples)
		preferences->orthographic->MSAA (def = 8 samples)
		coloured camera POV icon w/o rerendering the scene
		coloured rectangular selector box w/o rerendering the scene
	* fallback to glCopyTexImage2D (NPoT), if FBO isn't available
This commit is contained in:
Garux 2017-08-02 09:52:30 +03:00
parent 2e3529798d
commit e14027e117
5 changed files with 512 additions and 166 deletions

View File

@ -67,71 +67,56 @@ inline rectangle_t rectangle_from_area( const float min[2], const float max[2],
return rectangle_t( botleft.x, botleft.y, topright.x - botleft.x, topright.y - botleft.y );
}
class XORRectangle
{
rectangle_t m_rectangle;
GtkWidget* m_widget;
class XORRectangle {
public:
XORRectangle( GtkWidget* widget ) : m_widget( widget ){
}
~XORRectangle(){
}
void set( rectangle_t rectangle ){
if ( GTK_WIDGET_REALIZED( m_widget ) ) {
if( m_rectangle.w != rectangle.w || m_rectangle.h != rectangle.h ){
//if( !(m_rectangle.w == 0 && m_rectangle.h == 0 && rectangle.w == 0 && rectangle.h == 0) ){
//globalOutputStream() << "m_x" << m_rectangle.x << " m_y" << m_rectangle.y << " m_w" << m_rectangle.w << " m_h" << m_rectangle.h << "\n";
//globalOutputStream() << "__x" << rectangle.x << " __y" << rectangle.y << " __w" << rectangle.w << " __h" << rectangle.h << "\n";
if ( glwidget_make_current( m_widget ) != FALSE ) {
GlobalOpenGL_debugAssertNoErrors();
gint width, height;
gdk_gl_drawable_get_size( gtk_widget_get_gl_drawable( m_widget ), &width, &height );
glViewport( 0, 0, width, height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0, width, 0, height, -100, 100 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
glDisable( GL_DEPTH_TEST );
glDrawBuffer( GL_FRONT );
glEnable( GL_BLEND );
glBlendFunc( GL_ONE_MINUS_DST_COLOR, GL_ZERO );
glLineWidth( 2 );
glColor3f( 1, 1, 1 );
glDisable( GL_TEXTURE_2D );
glBegin( GL_LINE_LOOP );
glVertex2f( m_rectangle.x, m_rectangle.y + m_rectangle.h );
glVertex2f( m_rectangle.x + m_rectangle.w, m_rectangle.y + m_rectangle.h );
glVertex2f( m_rectangle.x + m_rectangle.w, m_rectangle.y );
glVertex2f( m_rectangle.x, m_rectangle.y );
glEnd();
glBegin( GL_LINE_LOOP );
glVertex2f( rectangle.x, rectangle.y + rectangle.h );
glVertex2f( rectangle.x + rectangle.w, rectangle.y + rectangle.h );
glVertex2f( rectangle.x + rectangle.w, rectangle.y );
glVertex2f( rectangle.x, rectangle.y );
glEnd();
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glDrawBuffer( GL_BACK );
GlobalOpenGL_debugAssertNoErrors();
//glwidget_swap_buffers( m_widget );
glwidget_make_current( m_widget );
}
}
m_rectangle = rectangle;
XORRectangle() {
}
~XORRectangle() {
}
void set( rectangle_t rectangle ) {
if( rectangle.w != 0.f && rectangle.h != 0.f ) {
GlobalOpenGL_debugAssertNoErrors();
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
glDisable( GL_DEPTH_TEST );
glDisable( GL_TEXTURE_2D );
if( GlobalOpenGL().GL_1_3() ) {
glDisable( GL_MULTISAMPLE );
}
glEnable( GL_BLEND );
glBlendFunc( GL_ONE, GL_ONE );
//glColor4f( 0.94902f / 5.f, 0.396078f / 5.f, 0.133333f / 5.f, .2f );
glColor3f( 1.f / 10.f, .5f / 10.f, 0.f );
glBegin( GL_QUADS );
glVertex2f( rectangle.x, rectangle.y + rectangle.h );
glVertex2f( rectangle.x + rectangle.w, rectangle.y + rectangle.h );
glVertex2f( rectangle.x + rectangle.w, rectangle.y );
glVertex2f( rectangle.x, rectangle.y );
glEnd();
glDisable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glLineWidth( 1 );
//glColor3f( 0.94902f, 0.396078f, 0.133333f );
glColor3f( 1.f, .5f, 0.f );
glBegin( GL_LINE_LOOP );
glVertex2f( rectangle.x, rectangle.y + rectangle.h );
glVertex2f( rectangle.x + rectangle.w, rectangle.y + rectangle.h );
glVertex2f( rectangle.x + rectangle.w, rectangle.y );
glVertex2f( rectangle.x, rectangle.y );
glEnd();
if( GlobalOpenGL().GL_1_3() ) {
glEnable( GL_MULTISAMPLE );
}
GlobalOpenGL_debugAssertNoErrors();
}
}
}
};

View File

@ -1197,5 +1197,235 @@ inline void ArbitraryMeshTriangle_sumTangents( ArbitraryMeshVertex& a, Arbitrary
reinterpret_cast<Vector3&>( c.bitangent ) += t;
}
namespace {
///////////////////////////////////////////////////////////////////////////////
// check FBO completeness
///////////////////////////////////////////////////////////////////////////////
bool checkFramebufferStatus() {
// check FBO status
GLenum status = glCheckFramebufferStatus( GL_FRAMEBUFFER );
switch( status ) {
case GL_FRAMEBUFFER_COMPLETE:
// globalErrorStream() << "Framebuffer complete.\n";
return true;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
globalErrorStream() << "[ERROR] Framebuffer incomplete: Attachment is NOT complete.\n";
return false;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
globalErrorStream() << "[ERROR] Framebuffer incomplete: No image is attached to FBO.\n";
return false;
/*
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
globalErrorStream() << "[ERROR] Framebuffer incomplete: Attached images have different dimensions.\n";
return false;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
globalErrorStream() << "[ERROR] Framebuffer incomplete: Color attached images have different internal formats.\n";
return false;
*/
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
globalErrorStream() << "[ERROR] Framebuffer incomplete: Draw buffer.\n";
return false;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
globalErrorStream() << "[ERROR] Framebuffer incomplete: Read buffer.\n";
return false;
case GL_FRAMEBUFFER_UNSUPPORTED:
globalErrorStream() << "[ERROR] Framebuffer incomplete: Unsupported by FBO implementation.\n";
return false;
default:
globalErrorStream() << "[ERROR] Framebuffer incomplete: Unknown error.\n";
return false;
}
}
} //namespace
class FBO
{
public:
FBO():
_constructed( false ),
_has_depth( false ),
_width( 0 ),
_height( 0 ),
_fbo( 0 ),
_tex( 0 ),
_depth( 0 ),
_color( 0 ){
}
virtual ~FBO(){
reset( 0, 0, 0, false );
}
virtual void reset( int width, int height, int samples, bool has_depth ){
_width = width;
_height = height;
_samples = samples;
_has_depth = has_depth;
if( _depth )
glDeleteRenderbuffers( 1, &_depth );
_depth = 0;
if( _color )
glDeleteRenderbuffers( 1, &_color );
_color = 0;
if( _fbo )
glDeleteFramebuffers( 1, &_fbo );
_fbo = 0;
_constructed = false;
}
virtual void start(){
// if ( GlobalOpenGL().GL_1_3() ) {
// glDisable( GL_MULTISAMPLE );
// }
if( !_constructed ){
construct();
}
glBindFramebuffer( GL_FRAMEBUFFER, _fbo );
}
virtual void save(){
blit();
}
virtual void blit(){
glBindFramebuffer( GL_READ_FRAMEBUFFER, _fbo );
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 );
//glDrawBuffer( GL_BACK );
glBlitFramebuffer( 0, 0, _width, _height, 0, 0, _width, _height, GL_COLOR_BUFFER_BIT, GL_NEAREST );
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
}
protected:
bool _constructed;
bool _has_depth;
int _width;
int _height;
int _samples;
GLuint _fbo;
GLuint _tex;
GLuint _depth;
GLuint _color;
virtual void construct() {
int curSamples;
glGetIntegerv( GL_SAMPLES, &curSamples );
if( curSamples > 0 && _samples != 0 ){
_samples = curSamples;
}
else{
int maxSamples;
glGetIntegerv( GL_MAX_SAMPLES, &maxSamples );
if( _samples > maxSamples ){
_samples = maxSamples;
}
}
glGenFramebuffers( 1, &_fbo );
glBindFramebuffer( GL_FRAMEBUFFER, _fbo );
// Color buffer
glGenRenderbuffers( 1, &_color );
glBindRenderbuffer( GL_RENDERBUFFER, _color );
glRenderbufferStorageMultisample( GL_RENDERBUFFER, _samples, GL_RGBA8, _width, _height );
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _color );
if( _has_depth ){
// Depth buffer
glGenRenderbuffers( 1, &_depth );
glBindRenderbuffer( GL_RENDERBUFFER, _depth );
glRenderbufferStorageMultisample( GL_RENDERBUFFER, _samples, GL_DEPTH_COMPONENT, _width, _height );
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depth );
}
if( !checkFramebufferStatus() && _samples > 0 ){
globalErrorStream() << "Falling back to no multisampling.\n";
_samples = 0;
reset( _width, _height, 0, _has_depth );
construct();
}
_constructed = true;
}
private:
};
class FBO_fallback : public FBO
{
public:
~FBO_fallback(){
reset( 0, 0, 0, false );
}
void reset( int width, int height, int samples, bool has_depth ){
_width = width;
_height = height;
if( _tex )
glDeleteTextures( 1, &_tex );
_tex = 0;
_constructed = false;
}
void start(){
if( !_constructed ){
construct();
}
}
void save(){
glBindTexture( GL_TEXTURE_2D, _tex );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 0, 0, _width, _height, 0 );
//glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_nWidth, m_nHeight );
glBindTexture( GL_TEXTURE_2D, 0 );
}
void blit(){
glViewport( 0, 0, _width, _height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0, _width, 0, _height, -100, 100 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glDisable( GL_LINE_STIPPLE );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glDisableClientState( GL_NORMAL_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
glDisable( GL_LIGHTING );
glDisable( GL_COLOR_MATERIAL );
glDisable( GL_DEPTH_TEST );
glDisable( GL_TEXTURE_1D );
glEnable( GL_TEXTURE_2D );
glDisable( GL_BLEND );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
glBindTexture( GL_TEXTURE_2D, _tex );
glColor4f( 1.0, 1.0, 1.0, 1.0 );
glBegin( GL_QUADS );
glTexCoord2f( 0, 0 );
glVertex3f( 0, 0, 0 );
glTexCoord2f( 0, 1 );
glVertex3f( 0, _height, 0 );
glTexCoord2f( 1, 1 );
glVertex3f( _width, _height, 0 );
glTexCoord2f( 1, 0 );
glVertex3f( _width, 0, 0 );
glEnd();
glBindTexture( GL_TEXTURE_2D, 0 );
}
protected:
void construct() {
glGenTextures( 1, &_tex );
_constructed = true;
}
private:
};
#endif

View File

@ -81,6 +81,7 @@ struct camwindow_globals_private_t
bool m_bCubicClipping;
int m_nStrafeMode;
bool m_bFaceWire;
int m_MSAA;
camwindow_globals_private_t() :
m_nMoveSpeed( 100 ),
@ -90,7 +91,8 @@ struct camwindow_globals_private_t
m_bCamDiscrete( true ),
m_bCubicClipping( false ),
m_nStrafeMode( 3 ),
m_bFaceWire( true ){
m_bFaceWire( true ),
m_MSAA( 8 ){
}
};
@ -710,6 +712,7 @@ static Shader* m_state_facewire;
FreezePointer m_freezePointer;
public:
FBO* m_fbo;
GtkWidget* m_gl_widget;
GtkWindow* m_parent;
@ -940,7 +943,30 @@ gboolean mousecontrol_button_press( GtkWidget* widget, GdkEventButton* event, Ca
void camwnd_update_xor_rectangle( CamWnd& self, rect_t area ){
if ( GTK_WIDGET_VISIBLE( self.m_gl_widget ) ) {
self.m_XORRectangle.set( rectangle_from_area( area.min, area.max, self.getCamera().width, self.getCamera().height ) );
if ( glwidget_make_current( self.m_gl_widget ) != FALSE ) {
if ( Map_Valid( g_map ) && ScreenUpdates_Enabled() ) {
GlobalOpenGL_debugAssertNoErrors();
glDrawBuffer( GL_FRONT );
self.m_fbo->blit();
glViewport( 0, 0, self.getCamera().width, self.getCamera().height );
// set up viewpoint
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0, self.getCamera().width, 0, self.getCamera().height, -100, 100 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
self.m_XORRectangle.set( rectangle_from_area( area.min, area.max, self.getCamera().width, self.getCamera().height ) );
glDrawBuffer( GL_BACK );
GlobalOpenGL_debugAssertNoErrors();
glwidget_make_current( self.m_gl_widget );
}
}
}
}
@ -1048,6 +1074,7 @@ gboolean wheelmove_scroll( GtkWidget* widget, GdkEventScroll* event, CamWnd* cam
}
gboolean camera_size_allocate( GtkWidget* widget, GtkAllocation* allocation, CamWnd* camwnd ){
camwnd->m_fbo->reset( allocation->width, allocation->height, g_camwindow_globals_private.m_MSAA, true );
camwnd->getCamera().width = allocation->width;
camwnd->getCamera().height = allocation->height;
Camera_updateProjection( camwnd->getCamera() );
@ -1347,7 +1374,6 @@ CamWnd::CamWnd() :
m_cameraview( m_Camera, &m_view, ReferenceCaller<CamWnd, CamWnd_Update>( *this ) ),
m_gl_widget( glwidget_new( TRUE ) ),
m_window_observer( NewWindowObserver() ),
m_XORRectangle( m_gl_widget ),
m_deferredDraw( WidgetQueueDrawCaller( *m_gl_widget ) ),
m_deferred_motion( selection_motion, m_window_observer ),
m_deferred_motion_freemove( selection_motion_freemove, this ),
@ -1357,6 +1383,8 @@ CamWnd::CamWnd() :
m_freelook_button_press_handler( 0 ),
m_freelook_button_release_handler( 0 ),
m_drawing( false ){
m_fbo = GlobalOpenGL().support_ARB_framebuffer_object? new FBO : new FBO_fallback;
m_bFreeMove = false;
GlobalWindowObservers_add( m_window_observer );
@ -1398,6 +1426,8 @@ CamWnd::~CamWnd(){
gtk_widget_unref( m_gl_widget );
delete m_fbo;
m_window_observer->release();
}
@ -1637,6 +1667,8 @@ void ShowStatsToggle(){
void CamWnd::Cam_Draw(){
// globalOutputStream() << "Cam_Draw()\n";
m_fbo->start();
glViewport( 0, 0, m_Camera.width, m_Camera.height );
#if 0
GLint viewprt[4];
@ -1797,6 +1829,8 @@ void CamWnd::Cam_Draw(){
// bind back to the default texture so that we don't have problems
// elsewhere using/modifying texture maps between contexts
glBindTexture( GL_TEXTURE_2D, 0 );
m_fbo->save();
}
void CamWnd::draw(){
@ -1810,7 +1844,7 @@ void CamWnd::draw(){
GlobalOpenGL_debugAssertNoErrors();
//qglFinish();
m_XORRectangle.set( rectangle_t() );
//m_XORRectangle.set( rectangle_t() );
}
glwidget_swap_buffers( m_gl_widget );
@ -2085,6 +2119,28 @@ void RenderModeExport( const IntImportCallback& importer ){
}
typedef FreeCaller1<const IntImportCallback&, RenderModeExport> RenderModeExportCaller;
void CamMSAAImport( int value ){
g_camwindow_globals_private.m_MSAA = value ? 1 << value : value;
if ( g_camwnd != 0 ) {
g_camwnd->m_fbo->reset( g_camwnd->getCamera().width, g_camwnd->getCamera().height, g_camwindow_globals_private.m_MSAA, true );
}
}
typedef FreeCaller1<int, CamMSAAImport> MSAAImportCaller;
void CamMSAAExport( const IntImportCallback& importer ){
if( g_camwindow_globals_private.m_MSAA <= 0 ){
importer( 0 );
}
else{
int exponent = 1;
while( !( ( g_camwindow_globals_private.m_MSAA >> exponent ) & 1 ) ){
++exponent;
}
importer( exponent );
}
}
typedef FreeCaller1<const IntImportCallback&, CamMSAAExport> MSAAExportCaller;
void fieldOfViewImport( float value ){
camera_t::fieldOfView = value;
if( g_camwnd ){
@ -2137,6 +2193,17 @@ void Camera_constructPreferences( PreferencesPage& page ){
);
}
if( GlobalOpenGL().support_ARB_framebuffer_object ){
const char* samples[] = { "0", "2", "4", "8", "16", "32" };
page.appendCombo(
"MSAA",
STRING_ARRAY_RANGE( samples ),
IntImportCallback( MSAAImportCaller() ),
IntExportCallback( MSAAExportCaller() )
);
}
const char* strafe_mode[] = { "None", "Up", "Forward", "Both", "Both Inverted" };
page.appendCombo(
@ -2245,6 +2312,7 @@ void CamWnd_Construct(){
GlobalPreferenceSystem().registerPreference( "SI_Colors4", Vector3ImportStringCaller( g_camwindow_globals.color_cameraback ), Vector3ExportStringCaller( g_camwindow_globals.color_cameraback ) );
GlobalPreferenceSystem().registerPreference( "SI_Colors12", Vector3ImportStringCaller( g_camwindow_globals.color_selbrushes3d ), Vector3ExportStringCaller( g_camwindow_globals.color_selbrushes3d ) );
GlobalPreferenceSystem().registerPreference( "CameraRenderMode", makeIntStringImportCallback( RenderModeImportCaller() ), makeIntStringExportCallback( RenderModeExportCaller() ) );
GlobalPreferenceSystem().registerPreference( "CameraMSAA", IntImportStringCaller( g_camwindow_globals_private.m_MSAA ), IntExportStringCaller( g_camwindow_globals_private.m_MSAA ) );
GlobalPreferenceSystem().registerPreference( "StrafeMode", IntImportStringCaller( g_camwindow_globals_private.m_nStrafeMode ), IntExportStringCaller( g_camwindow_globals_private.m_nStrafeMode ) );
GlobalPreferenceSystem().registerPreference( "CameraFaceWire", BoolImportStringCaller( g_camwindow_globals_private.m_bFaceWire ), BoolExportStringCaller( g_camwindow_globals_private.m_bFaceWire ) );
GlobalPreferenceSystem().registerPreference( "3DZoomInToPointer", BoolImportStringCaller( g_camwindow_globals.m_bZoomInToPointer ), BoolExportStringCaller( g_camwindow_globals.m_bZoomInToPointer ) );

View File

@ -71,6 +71,8 @@
#include "grid.h"
#include "windowobservers.h"
#include "render.h"
void LoadTextureRGBA( qtexture_t* q, unsigned char* pPixels, int nWidth, int nHeight );
// d1223m
@ -354,6 +356,8 @@ struct xywindow_globals_private_t
bool m_bChaseMouse;
bool m_bSizePaint;
int m_MSAA;
xywindow_globals_private_t() :
d_showgrid( true ),
@ -369,7 +373,8 @@ struct xywindow_globals_private_t
// m_bCamXYUpdate( true ),
m_bChaseMouse( true ),
m_bSizePaint( true ){
m_bSizePaint( true ),
m_MSAA( 8 ){
}
};
@ -743,16 +748,31 @@ Shader* XYWnd::m_state_selected = 0;
void xy_update_xor_rectangle( XYWnd& self, rect_t area ){
if ( GTK_WIDGET_VISIBLE( self.GetWidget() ) ) {
rectangle_t rect = rectangle_from_area( area.min, area.max, self.Width(), self.Height() );
// int nDim1 = ( self.GetViewType() == YZ ) ? 1 : 0;
// int nDim2 = ( self.GetViewType() == XY ) ? 1 : 2;
// rect.x /= self.Scale();
// rect.y /= self.Scale();
// rect.w /= self.Scale();
// rect.h /= self.Scale();
// rect.x += self.GetOrigin()[nDim1];
// rect.y += self.GetOrigin()[nDim2];
self.m_XORRectangle.set( rect );
if ( glwidget_make_current( self.GetWidget() ) != FALSE ) {
if ( Map_Valid( g_map ) && ScreenUpdates_Enabled() ) {
GlobalOpenGL_debugAssertNoErrors();
glDrawBuffer( GL_FRONT );
self.m_fbo->blit();
glViewport( 0, 0, self.Width(), self.Height() );
// set up viewpoint
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0, self.Width(), 0, self.Height(), -100, 100 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
rectangle_t rect = rectangle_from_area( area.min, area.max, self.Width(), self.Height() );
self.m_XORRectangle.set( rect );
glDrawBuffer( GL_BACK );
GlobalOpenGL_debugAssertNoErrors();
glwidget_make_current( self.GetWidget() );
}
}
}
}
@ -817,6 +837,7 @@ gboolean xywnd_wheel_scroll( GtkWidget* widget, GdkEventScroll* event, XYWnd* xy
}
gboolean xywnd_size_allocate( GtkWidget* widget, GtkAllocation* allocation, XYWnd* xywnd ){
xywnd->m_fbo->reset( allocation->width, allocation->height, g_xywindow_globals_private.m_MSAA, false );
xywnd->m_nWidth = allocation->width;
xywnd->m_nHeight = allocation->height;
xywnd->updateProjection();
@ -831,7 +852,7 @@ gboolean xywnd_expose( GtkWidget* widget, GdkEventExpose* event, XYWnd* xywnd ){
xywnd->XY_Draw();
GlobalOpenGL_debugAssertNoErrors();
xywnd->m_XORRectangle.set( rectangle_t() );
//xywnd->m_XORRectangle.set( rectangle_t() );
}
glwidget_swap_buffers( xywnd->GetWidget() );
}
@ -852,8 +873,9 @@ XYWnd::XYWnd() :
m_deferred_motion( xywnd_motion, this ),
m_parent( 0 ),
m_window_observer( NewWindowObserver() ),
m_XORRectangle( m_gl_widget ),
m_chasemouse_handler( 0 ){
m_fbo = GlobalOpenGL().support_ARB_framebuffer_object? new FBO : new FBO_fallback;
m_bActive = false;
m_buttonstate = 0;
@ -918,6 +940,8 @@ XYWnd::XYWnd() :
XYWnd::~XYWnd(){
onDestroyed();
delete m_fbo;
if ( m_mnuDrop != 0 ) {
gtk_widget_destroy( GTK_WIDGET( m_mnuDrop ) );
m_mnuDrop = 0;
@ -1774,13 +1798,14 @@ void XYWnd::XY_DrawAxis( void ){
Vector3 colourX = ( m_viewType == YZ ) ? g_xywindow_globals.AxisColorY : g_xywindow_globals.AxisColorX;
Vector3 colourY = ( m_viewType == XY ) ? g_xywindow_globals.AxisColorY : g_xywindow_globals.AxisColorZ;
#if 0 //gray for nonActive
if( !Active() ){
float grayX = vector3_dot( colourX, Vector3( 0.2989, 0.5870, 0.1140 ) );
float grayY = vector3_dot( colourY, Vector3( 0.2989, 0.5870, 0.1140 ) );
colourX[0] = colourX[1] = colourX[2] = grayX;
colourY[0] = colourY[1] = colourY[2] = grayY;
}
#endif
// draw two lines with corresponding axis colors to highlight current view
// horizontal line: nDim1 color
glLineWidth( 2 );
@ -1854,6 +1879,7 @@ void XYWnd::RenderActive( void ){
glVertex2f( 0.5, m_nHeight - 0.5 );
glEnd();
}
#if 0 //gray for nonActive
// we do this part (the old way) only if show_axis is disabled
if ( !g_xywindow_globals_private.show_axis ) {
glMatrixMode( GL_PROJECTION );
@ -1902,7 +1928,7 @@ void XYWnd::RenderActive( void ){
XYWnd::XY_DrawAxis();
}
#endif
glDrawBuffer( GL_BACK );
GlobalOpenGL_debugAssertNoErrors();
glwidget_make_current( m_gl_widget );
@ -2277,42 +2303,44 @@ void XYWnd::XY_DrawBlockGrid(){
}
void XYWnd::DrawCameraIcon( const Vector3& origin, const Vector3& angles ){
Cam.fov = 48 / m_fScale;
Cam.box = 16 / m_fScale;
float x, y, fov, box;
double a;
fov = 48 / m_fScale;
box = 16 / m_fScale;
// globalOutputStream() << "pitch " << angles[CAMERA_PITCH] << " yaw " << angles[CAMERA_YAW] << "\n";
if ( m_viewType == XY ) {
Cam.x = origin[0];
Cam.y = origin[1];
Cam.a = degrees_to_radians( angles[CAMERA_YAW] );
x = origin[0];
y = origin[1];
a = degrees_to_radians( angles[CAMERA_YAW] );
}
else if ( m_viewType == YZ ) {
Cam.x = origin[1];
Cam.y = origin[2];
Cam.a = degrees_to_radians( ( angles[CAMERA_YAW] > 180 ) ? ( 180.0f - angles[CAMERA_PITCH] ) : angles[CAMERA_PITCH] );
x = origin[1];
y = origin[2];
a = degrees_to_radians( ( angles[CAMERA_YAW] > 180 ) ? ( 180.0f - angles[CAMERA_PITCH] ) : angles[CAMERA_PITCH] );
}
else
{
Cam.x = origin[0];
Cam.y = origin[2];
Cam.a = degrees_to_radians( ( angles[CAMERA_YAW] < 270 && angles[CAMERA_YAW] > 90 ) ? ( 180.0f - angles[CAMERA_PITCH] ) : angles[CAMERA_PITCH] );
x = origin[0];
y = origin[2];
a = degrees_to_radians( ( angles[CAMERA_YAW] < 270 && angles[CAMERA_YAW] > 90 ) ? ( 180.0f - angles[CAMERA_PITCH] ) : angles[CAMERA_PITCH] );
}
//glColor3f( 0.0, 0.0, 1.0 );
glColor3f( 1.0, 1.0, 1.0 );
glColor3f( 0.0, 0.0, 1.0 );
glBegin( GL_LINE_STRIP );
glVertex3f( Cam.x - Cam.box,Cam.y,0 );
glVertex3f( Cam.x,Cam.y + ( Cam.box / 2 ),0 );
glVertex3f( Cam.x + Cam.box,Cam.y,0 );
glVertex3f( Cam.x,Cam.y - ( Cam.box / 2 ),0 );
glVertex3f( Cam.x - Cam.box,Cam.y,0 );
glVertex3f( Cam.x + Cam.box,Cam.y,0 );
glVertex3f( x - box,y,0 );
glVertex3f( x,y + ( box / 2 ),0 );
glVertex3f( x + box,y,0 );
glVertex3f( x,y - ( box / 2 ),0 );
glVertex3f( x - box,y,0 );
glVertex3f( x + box,y,0 );
glEnd();
glBegin( GL_LINE_STRIP );
glVertex3f( Cam.x + static_cast<float>( Cam.fov * cos( Cam.a + c_pi / 4 ) ), Cam.y + static_cast<float>( Cam.fov * sin( Cam.a + c_pi / 4 ) ), 0 );
glVertex3f( Cam.x, Cam.y, 0 );
glVertex3f( Cam.x + static_cast<float>( Cam.fov * cos( Cam.a - c_pi / 4 ) ), Cam.y + static_cast<float>( Cam.fov * sin( Cam.a - c_pi / 4 ) ), 0 );
glVertex3f( x + static_cast<float>( fov * cos( a + c_pi / 4 ) ), y + static_cast<float>( fov * sin( a + c_pi / 4 ) ), 0 );
glVertex3f( x, y, 0 );
glVertex3f( x + static_cast<float>( fov * cos( a - c_pi / 4 ) ), y + static_cast<float>( fov * sin( a - c_pi / 4 ) ), 0 );
glEnd();
}
@ -2321,58 +2349,36 @@ void XYWnd::UpdateCameraIcon( void ){
if ( glwidget_make_current( m_gl_widget ) != FALSE ) {
if ( Map_Valid( g_map ) && ScreenUpdates_Enabled() ) {
GlobalOpenGL_debugAssertNoErrors();
glDrawBuffer( GL_FRONT );
{
// clear
glViewport( 0, 0, m_nWidth, m_nHeight );
// set up viewpoint
glMatrixMode( GL_PROJECTION );
glLoadMatrixf( reinterpret_cast<const float*>( &m_projection ) );
m_fbo->blit();
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glScalef( m_fScale, m_fScale, 1 );
int nDim1 = ( m_viewType == YZ ) ? 1 : 0;
int nDim2 = ( m_viewType == XY ) ? 1 : 2;
glTranslatef( -m_vOrigin[nDim1], -m_vOrigin[nDim2], 0 );
glViewport( 0, 0, m_nWidth, m_nHeight );
// set up viewpoint
glMatrixMode( GL_PROJECTION );
glLoadMatrixf( reinterpret_cast<const float*>( &m_projection ) );
glDisable( GL_LINE_STIPPLE );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glDisableClientState( GL_NORMAL_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
glDisable( GL_TEXTURE_2D );
glDisable( GL_LIGHTING );
glDisable( GL_COLOR_MATERIAL );
glDisable( GL_DEPTH_TEST );
glDisable( GL_TEXTURE_1D );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glScalef( m_fScale, m_fScale, 1 );
int nDim1 = ( m_viewType == YZ ) ? 1 : 0;
int nDim2 = ( m_viewType == XY ) ? 1 : 2;
glTranslatef( -m_vOrigin[nDim1], -m_vOrigin[nDim2], 0 );
glEnable( GL_BLEND );
glBlendFunc( GL_ONE_MINUS_DST_COLOR, GL_ZERO );
glDisable( GL_LINE_STIPPLE );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glDisableClientState( GL_NORMAL_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
glDisable( GL_TEXTURE_2D );
glDisable( GL_LIGHTING );
glDisable( GL_COLOR_MATERIAL );
glDisable( GL_DEPTH_TEST );
glDisable( GL_TEXTURE_1D );
//glColor3f( 0.0, 0.0, 1.0 );
glColor3f( 1.0, 1.0, 1.0 );
glBegin( GL_LINE_STRIP );
glVertex3f( Cam.x - Cam.box,Cam.y,0 );
glVertex3f( Cam.x,Cam.y + ( Cam.box / 2 ),0 );
glVertex3f( Cam.x + Cam.box,Cam.y,0 );
glVertex3f( Cam.x,Cam.y - ( Cam.box / 2 ),0 );
glVertex3f( Cam.x - Cam.box,Cam.y,0 );
glVertex3f( Cam.x + Cam.box,Cam.y,0 );
glEnd();
glBegin( GL_LINE_STRIP );
glVertex3f( Cam.x + static_cast<float>( Cam.fov * cos( Cam.a + c_pi / 4 ) ), Cam.y + static_cast<float>( Cam.fov * sin( Cam.a + c_pi / 4 ) ), 0 );
glVertex3f( Cam.x, Cam.y, 0 );
glVertex3f( Cam.x + static_cast<float>( Cam.fov * cos( Cam.a - c_pi / 4 ) ), Cam.y + static_cast<float>( Cam.fov * sin( Cam.a - c_pi / 4 ) ), 0 );
glEnd();
XYWnd::DrawCameraIcon( Camera_getOrigin( *g_pParentWnd->GetCamWnd() ), Camera_getAngles( *g_pParentWnd->GetCamWnd() ) );
glDisable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
}
XYWnd::DrawCameraIcon( Camera_getOrigin( *g_pParentWnd->GetCamWnd() ), Camera_getAngles( *g_pParentWnd->GetCamWnd() ) );
glDrawBuffer( GL_BACK );
GlobalOpenGL_debugAssertNoErrors();
glwidget_make_current( m_gl_widget );
}
@ -2680,6 +2686,17 @@ void XYWnd::updateModelview(){
void XYWnd::XY_Draw(){
// globalOutputStream() << "XY_Draw()\n";
/*
int maxSamples;
glGetIntegerv(GL_MAX_SAMPLES,&maxSamples);
globalOutputStream() << maxSamples << " GL_MAX_SAMPLES\n";
int curSamples;
glGetIntegerv(GL_SAMPLE_BUFFERS,&curSamples);
globalOutputStream() << curSamples << " GL_SAMPLE_BUFFERS\n";
glGetIntegerv(GL_SAMPLES,&curSamples);
globalOutputStream() << curSamples << " GL_SAMPLES\n";
*/
m_fbo->start();
//
// clear
//
@ -2812,18 +2829,14 @@ void XYWnd::XY_Draw(){
GlobalOpenGL_debugAssertNoErrors();
// reset modelview
glLoadIdentity();
glScalef( m_fScale, m_fScale, 1 );
glTranslatef( -m_vOrigin[nDim1], -m_vOrigin[nDim2], 0 );
{
// reset modelview
glLoadIdentity();
glScalef( m_fScale, m_fScale, 1 );
glTranslatef( -m_vOrigin[nDim1], -m_vOrigin[nDim2], 0 );
glEnable( GL_BLEND );
glBlendFunc( GL_ONE_MINUS_DST_COLOR, GL_ZERO );
DrawCameraIcon( Camera_getOrigin( *g_pParentWnd->GetCamWnd() ), Camera_getAngles( *g_pParentWnd->GetCamWnd() ) );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glDisable( GL_BLEND );
Feedback_draw2D( m_viewType );
Feedback_draw2D( m_viewType );
}
if ( g_xywindow_globals_private.show_outline ) {
if ( Active() ) {
@ -2884,6 +2897,20 @@ void XYWnd::XY_Draw(){
m_render_time.start();
}
m_fbo->save();
{
// reset modelview
glMatrixMode( GL_PROJECTION );
glLoadMatrixf( reinterpret_cast<const float*>( &m_projection ) );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glScalef( m_fScale, m_fScale, 1 );
glTranslatef( -m_vOrigin[nDim1], -m_vOrigin[nDim2], 0 );
DrawCameraIcon( Camera_getOrigin( *g_pParentWnd->GetCamWnd() ), Camera_getAngles( *g_pParentWnd->GetCamWnd() ) );
}
GlobalOpenGL_debugAssertNoErrors();
glFinish();
@ -3266,6 +3293,34 @@ void ToggleShowGrid(){
XY_UpdateAllWindows();
}
void MSAAImport( int value ){
g_xywindow_globals_private.m_MSAA = value ? 1 << value : value;
if ( g_pParentWnd->GetXYWnd() ) {
g_pParentWnd->GetXYWnd()->m_fbo->reset( g_pParentWnd->GetXYWnd()->Width(), g_pParentWnd->GetXYWnd()->Height(), g_xywindow_globals_private.m_MSAA, false );
}
if ( g_pParentWnd->GetXZWnd() ) {
g_pParentWnd->GetXZWnd()->m_fbo->reset( g_pParentWnd->GetXZWnd()->Width(), g_pParentWnd->GetXZWnd()->Height(), g_xywindow_globals_private.m_MSAA, false );
}
if ( g_pParentWnd->GetYZWnd() ) {
g_pParentWnd->GetYZWnd()->m_fbo->reset( g_pParentWnd->GetYZWnd()->Width(), g_pParentWnd->GetYZWnd()->Height(), g_xywindow_globals_private.m_MSAA, false );
}
}
typedef FreeCaller1<int, MSAAImport> MSAAImportCaller;
void MSAAExport( const IntImportCallback& importer ){
if( g_xywindow_globals_private.m_MSAA <= 0 ){
importer( 0 );
}
else{
int exponent = 1;
while( !( ( g_xywindow_globals_private.m_MSAA >> exponent ) & 1 ) ){
++exponent;
}
importer( exponent );
}
}
typedef FreeCaller1<const IntImportCallback&, MSAAExport> MSAAExportCaller;
void XYShow_registerCommands(){
GlobalToggles_insert( "ToggleSizePaint", FreeCaller<ToggleShowSizeInfo>(), ToggleItem::AddCallbackCaller( g_show_size_item ), Accelerator( 'J' ) );
@ -3296,6 +3351,17 @@ void Orthographic_constructPreferences( PreferencesPage& page ){
page.appendCheckBox( "", "Chase mouse during drags", g_xywindow_globals_private.m_bChaseMouse );
// page.appendCheckBox( "", "Update views on camera move", g_xywindow_globals_private.m_bCamXYUpdate );
page.appendCheckBox( "", "Zoom In to Mouse pointer", g_xywindow_globals.m_bZoomInToPointer );
if( GlobalOpenGL().support_ARB_framebuffer_object ){
const char* samples[] = { "0", "2", "4", "8", "16", "32" };
page.appendCombo(
"MSAA",
STRING_ARRAY_RANGE( samples ),
IntImportCallback( MSAAImportCaller() ),
IntExportCallback( MSAAExportCaller() )
);
}
}
void Orthographic_constructPage( PreferenceGroup& group ){
PreferencesPage page( group.createPage( "Orthographic", "Orthographic View Preferences" ) );
@ -3354,6 +3420,7 @@ void XYWindow_Construct(){
GlobalPreferenceSystem().registerPreference( "ClipCaulk", BoolImportStringCaller( g_clip_useCaulk ), BoolExportStringCaller( g_clip_useCaulk ) );
// GlobalPreferenceSystem().registerPreference( "NewRightClick", BoolImportStringCaller( g_xywindow_globals.m_bRightClick ), BoolExportStringCaller( g_xywindow_globals.m_bRightClick ) );
GlobalPreferenceSystem().registerPreference( "XYMSAA", IntImportStringCaller( g_xywindow_globals_private.m_MSAA ), IntExportStringCaller( g_xywindow_globals_private.m_MSAA ) );
GlobalPreferenceSystem().registerPreference( "2DZoomInToPointer", BoolImportStringCaller( g_xywindow_globals.m_bZoomInToPointer ), BoolExportStringCaller( g_xywindow_globals.m_bZoomInToPointer ) );
GlobalPreferenceSystem().registerPreference( "ChaseMouse", BoolImportStringCaller( g_xywindow_globals_private.m_bChaseMouse ), BoolExportStringCaller( g_xywindow_globals_private.m_bChaseMouse ) );
GlobalPreferenceSystem().registerPreference( "SizePainting", BoolImportStringCaller( g_xywindow_globals_private.m_bSizePaint ), BoolExportStringCaller( g_xywindow_globals_private.m_bSizePaint ) );

View File

@ -66,6 +66,7 @@ inline const char* ViewType_getTitle( VIEWTYPE viewtype ){
}
#include "timer.h"
class FBO;
class XYWnd
{
@ -76,6 +77,7 @@ guint m_exposeHandler;
DeferredDraw m_deferredDraw;
DeferredMotion m_deferred_motion;
public:
FBO* m_fbo;
GtkWindow* m_parent;
XYWnd();
~XYWnd();
@ -147,12 +149,6 @@ void SetActive( bool b ){
bool Active(){
return m_bActive;
};
struct camera_icon_t
{
float x, y, fov, box;
double a;
};
camera_icon_t Cam;
void UpdateCameraIcon();