diff --git a/include/renderable.h b/include/renderable.h index 0c0e770b..0cae9b77 100644 --- a/include/renderable.h +++ b/include/renderable.h @@ -37,6 +37,8 @@ enum EHighlightMode eFace = 1 << 0, /*! Full highlighting. */ ePrimitive = 1 << 1, + ePrimitiveWire = 1 << 2, //always draw wire for primitives + eFaceWire = 1 << 3, //wire for selected faces }; enum EStyle diff --git a/radiant/brush.h b/radiant/brush.h index bf97b001..c3bf307a 100644 --- a/radiant/brush.h +++ b/radiant/brush.h @@ -2680,8 +2680,10 @@ bool intersectVolume( const VolumeTest& volume, const Matrix4& localToWorld ) co void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { if ( !m_face->isFiltered() && m_face->contributes() && intersectVolume( volume, localToWorld ) ) { renderer.PushState(); + renderer.Highlight( Renderer::ePrimitiveWire ); if ( selectedComponents() ) { renderer.Highlight( Renderer::eFace ); + renderer.Highlight( Renderer::eFaceWire ); } m_face->render( renderer, localToWorld ); renderer.PopState(); diff --git a/radiant/camwindow.cpp b/radiant/camwindow.cpp index 876fb511..49094dc3 100644 --- a/radiant/camwindow.cpp +++ b/radiant/camwindow.cpp @@ -80,6 +80,7 @@ struct camwindow_globals_private_t bool m_bCamDiscrete; bool m_bCubicClipping; int m_nStrafeMode; + bool m_bFaceWire; camwindow_globals_private_t() : m_nMoveSpeed( 100 ), @@ -88,7 +89,8 @@ struct camwindow_globals_private_t m_bCamInverseMouse( false ), m_bCamDiscrete( true ), m_bCubicClipping( false ), - m_nStrafeMode( 3 ){ + m_nStrafeMode( 3 ), + m_bFaceWire( true ){ } }; @@ -118,6 +120,7 @@ enum camera_draw_mode cd_wire, cd_solid, cd_texture, + cd_texture_plus_wire, cd_lighting }; @@ -699,8 +702,10 @@ int m_PositionDragCursorY; guint m_freemove_handle_focusout; +static Shader* m_state_select0; static Shader* m_state_select1; -static Shader* m_state_select2; +static Shader* m_state_wire; +static Shader* m_state_facewire; FreezePointer m_freezePointer; @@ -742,12 +747,16 @@ void queue_draw(){ void draw(); static void captureStates(){ + m_state_facewire = GlobalShaderCache().capture( "$CAM_FACEWIRE" ); + m_state_wire = GlobalShaderCache().capture( "$CAM_WIRE" ); + m_state_select0 = GlobalShaderCache().capture( "$CAM_OVERLAY" ); m_state_select1 = GlobalShaderCache().capture( "$CAM_HIGHLIGHT" ); - m_state_select2 = GlobalShaderCache().capture( "$CAM_OVERLAY" ); } static void releaseStates(){ GlobalShaderCache().release( "$CAM_HIGHLIGHT" ); GlobalShaderCache().release( "$CAM_OVERLAY" ); + GlobalShaderCache().release( "$CAM_WIRE" ); + GlobalShaderCache().release( "$CAM_FACEWIRE" ); } camera_t& getCamera(){ @@ -774,8 +783,10 @@ void Cam_Draw(); typedef MemberCaller CamWndQueueDraw; +Shader* CamWnd::m_state_select0 = 0; Shader* CamWnd::m_state_select1 = 0; -Shader* CamWnd::m_state_select2 = 0; +Shader* CamWnd::m_state_wire = 0; +Shader* CamWnd::m_state_facewire = 0; CamWnd* NewCamWnd(){ return new CamWnd; @@ -1529,13 +1540,17 @@ struct state_type std::vector m_state_stack; RenderStateFlags m_globalstate; +Shader* m_state_facewire; +Shader* m_state_wire; Shader* m_state_select0; Shader* m_state_select1; const Vector3& m_viewer; public: -CamRenderer( RenderStateFlags globalstate, Shader* select0, Shader* select1, const Vector3& viewer ) : +CamRenderer( RenderStateFlags globalstate, Shader* facewire, Shader* wire, Shader* select0, Shader* select1, const Vector3& viewer ) : m_globalstate( globalstate ), + m_state_facewire( facewire ), + m_state_wire( wire ), m_state_select0( select0 ), m_state_select1( select1 ), m_viewer( viewer ){ @@ -1572,8 +1587,14 @@ void addRenderable( const OpenGLRenderable& renderable, const Matrix4& world ){ if ( m_state_stack.back().m_highlight & ePrimitive ) { m_state_select0->addRenderable( renderable, world, m_state_stack.back().m_lights ); } + else if ( m_state_wire && m_state_stack.back().m_highlight & ePrimitiveWire ) { + m_state_wire->addRenderable( renderable, world, m_state_stack.back().m_lights ); + } if ( m_state_stack.back().m_highlight & eFace ) { m_state_select1->addRenderable( renderable, world, m_state_stack.back().m_lights ); + if ( m_state_facewire && m_state_stack.back().m_highlight & eFaceWire ) { + m_state_facewire->addRenderable( renderable, world, m_state_stack.back().m_lights ); + } } m_state_stack.back().m_state->addRenderable( renderable, world, m_state_stack.back().m_lights ); @@ -1683,6 +1704,7 @@ void CamWnd::Cam_Draw(){ | RENDER_SCALED; break; case cd_texture: + case cd_texture_plus_wire: globalstate |= RENDER_FILL | RENDER_LIGHTING | RENDER_TEXTURE @@ -1709,7 +1731,7 @@ void CamWnd::Cam_Draw(){ // } { - CamRenderer renderer( globalstate, m_state_select2, m_state_select1, m_view.getViewer() ); + CamRenderer renderer( globalstate, g_camwindow_globals_private.m_bFaceWire ? m_state_facewire : 0, m_Camera.draw_mode == cd_texture_plus_wire ? m_state_wire : 0, m_state_select0, m_state_select1, m_view.getViewer() ); Scene_Render( renderer, m_view ); @@ -2030,6 +2052,9 @@ void RenderModeImport( int value ){ CamWnd_SetMode( cd_texture ); break; case 3: + CamWnd_SetMode( cd_texture_plus_wire ); + break; + case 4: CamWnd_SetMode( cd_lighting ); break; default: @@ -2050,9 +2075,12 @@ void RenderModeExport( const IntImportCallback& importer ){ case cd_texture: importer( 2 ); break; - case cd_lighting: + case cd_texture_plus_wire: importer( 3 ); break; + case cd_lighting: + importer( 4 ); + break; } } typedef FreeCaller1 RenderModeExportCaller; @@ -2081,9 +2109,14 @@ void Camera_constructPreferences( PreferencesPage& page ){ FreeCaller1(), BoolExportCaller( g_camwindow_globals_private.m_bCubicClipping ) ); + page.appendCheckBox( + "", "Selected faces wire", + BoolImportCaller( g_camwindow_globals_private.m_bFaceWire ), + BoolExportCaller( g_camwindow_globals_private.m_bFaceWire ) + ); if ( g_pGameDescription->mGameType == "doom3" ) { - const char* render_mode[] = { "Wireframe", "Flatshade", "Textured", "Lighting" }; + const char* render_mode[] = { "Wireframe", "Flatshade", "Textured", "Textured+Wire", "Lighting" }; page.appendCombo( "Render Mode", @@ -2094,7 +2127,7 @@ void Camera_constructPreferences( PreferencesPage& page ){ } else { - const char* render_mode[] = { "Wireframe", "Flatshade", "Textured" }; + const char* render_mode[] = { "Wireframe", "Flatshade", "Textured", "Textured+Wire" }; page.appendCombo( "Render Mode", @@ -2213,6 +2246,7 @@ void CamWnd_Construct(){ 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( "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 ) ); GlobalPreferenceSystem().registerPreference( "fieldOfView", FloatImportStringCaller( camera_t::fieldOfView ), FloatExportStringCaller( camera_t::fieldOfView ) ); diff --git a/radiant/patch.h b/radiant/patch.h index 7348791c..180df2b7 100644 --- a/radiant/patch.h +++ b/radiant/patch.h @@ -1477,6 +1477,7 @@ void render( Renderer& renderer, const VolumeTest& volume ) const { void renderSolid( Renderer& renderer, const VolumeTest& volume ) const { m_patch.evaluateTransform(); renderer.setLights( *m_lightList ); + renderer.Highlight( Renderer::ePrimitiveWire ); m_patch.render_solid( renderer, volume, localToWorld() ); renderComponentsSelected( renderer, volume ); diff --git a/radiant/renderstate.cpp b/radiant/renderstate.cpp index 7759cea6..8889c250 100644 --- a/radiant/renderstate.cpp +++ b/radiant/renderstate.cpp @@ -2259,6 +2259,34 @@ void OpenGLShader::construct( const char* name ){ hiddenLine.m_linestipple_factor = 2; #endif } + else if ( string_equal( name + 1, "CAM_WIRE" ) ) { + state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE;// | RENDER_OFFSETLINE; + state.m_colour[0] = 0.75; + state.m_colour[1] = 0.75; + state.m_colour[2] = 0.75; + state.m_linewidth = 0.5; + state.m_sort = OpenGLState::eSortOverlayFirst + 1; + state.m_depthfunc = GL_LEQUAL; + } + else if ( string_equal( name + 1, "CAM_FACEWIRE" ) ) { + state.m_colour[0] = g_xywindow_globals.color_selbrushes[0]; + state.m_colour[1] = g_xywindow_globals.color_selbrushes[1]; + state.m_colour[2] = g_xywindow_globals.color_selbrushes[2]; + state.m_colour[3] = 1; + state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_OFFSETLINE; + state.m_sort = OpenGLState::eSortOverlayFirst + 2; + state.m_depthfunc = GL_LEQUAL; + + OpenGLState& hiddenLine = appendDefaultPass(); + hiddenLine.m_colour[0] = g_xywindow_globals.color_selbrushes[0]; + hiddenLine.m_colour[1] = g_xywindow_globals.color_selbrushes[1]; + hiddenLine.m_colour[2] = g_xywindow_globals.color_selbrushes[2]; + hiddenLine.m_colour[3] = 1; + hiddenLine.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_OFFSETLINE | RENDER_LINESTIPPLE; + hiddenLine.m_sort = OpenGLState::eSortOverlayFirst + 1; + hiddenLine.m_depthfunc = GL_GREATER; + hiddenLine.m_linestipple_factor = 2; + } else if ( string_equal( name + 1, "XY_OVERLAY" ) ) { state.m_colour[0] = g_xywindow_globals.color_selbrushes[0]; state.m_colour[1] = g_xywindow_globals.color_selbrushes[1];