Something went wrong on our end
-
Ansgar Philippsen authoredAnsgar Philippsen authored
scene.hh 13.82 KiB
//------------------------------------------------------------------------------
// This file is part of the OpenStructure project <www.openstructure.org>
//
// Copyright (C) 2008-2010 by the OpenStructure authors
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 3.0 of the License, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//------------------------------------------------------------------------------
#ifndef OST_SCENE_HH
#define OST_SCENE_HH
/*
Author: Ansgar Philippsen
*/
#include <map>
#include <stack>
#include <vector>
#include <boost/shared_array.hpp>
#include <ost/gfx/module_config.hh>
#include <ost/mol/transform.hh>
#include "gl_include.hh"
#include "color.hh"
#include "gfx_object_fw.hh"
#include "gfx_node_fw.hh"
#include "gfx_node_visitor.hh"
#include "selection.hh"
#include "glwin_base.hh"
#include "scene_observer.hh"
#include "gfx_prim.hh"
#include "povray_fw.hh"
namespace ost { namespace gfx {
class InputEvent;
class OffscreenBuffer;
typedef std::vector<SceneObserver*> SceneObserverList;
struct Viewport {
int x;
int y;
int width;
int height;
};
namespace impl {class SceneFX;}
/// \brief main class for organization and root for the graphical display
///
/// The scene manages graphical objects for rendering. Typical graphical objects
/// include \ref gfx::Entity "entities", \ref gfx::MapIso "isocontoured maps",
/// \ref gfx::MapSlab "density slabs", \ref gfx::Surface "molecular surfaces",
/// or \ref gfx::Primitive "primitives" such as \ref gfx::Cuboid "cuboids",
/// \ref gfx::Quad "quads" and \ref gfx::PrimList "lines". The nodes are
/// organized in a tree-like structure whose root
/// can obtained with GetRootNode().
///
/// The center of the eye is controlled with SetCenter() and CenterOn().
///
/// By default, the near and far clipping planes are adjusted such that they
/// contain all visible objects in the scene. This behaviour can be turned of by
/// disabling the AutoAutoslab(). The near and far clipping plane can then be
/// adjusted manually.
class DLLEXPORT_OST_GFX Scene {
friend class impl::SceneFX;
private:
// TODO: this struct may be the seed for a proper
// refactoring of the scene it into a management
// and a view part
struct SceneViewStackEntry {
mol::Transform transform;
float fov;
float znear,zfar;
};
typedef std::stack<SceneViewStackEntry> SceneViewStack;
public:
static Scene& Instance();
/// \brief turn fog on or off
void SetFog(bool f);
/// \brief check fog status
bool GetFog() const;
/// \brief set the fog color
void SetFogColor(const Color& c);
/// \brief get the fog color
Color GetFogColor() const;
/// \brief turn shadow mapping on and off
void SetShadow(bool f);
/// \brief get shadow mapping status
bool GetShadow() const;
/// \brief shadow quality from 0 (low) to 3 (high), default=1
void SetShadowQuality(int q);
void SetShadowWeight(float w);
void SetDepthDarkening(bool f);
void SetDepthDarkeningWeight(float f);
void SetAmbientOcclusion(bool f);
bool GetAmbientOcclusion() const;
void SetAmbientOcclusionWeight(float f);
void SetAmbientOcclusionMode(uint m);
void SetAmbientOcclusionQuality(uint q);
/// \brief select shading mode
/// one of fallback, basic, default, hf, toon1, toon2
void SetShadingMode(const std::string& smode);
/// \name clipping planes
//@{
/// \brief get near clipping plane
float GetNear() const;
/// \brief set near clipping plane
void SetNear(float n);
/// \brief get far clipping plane
float GetFar() const;
/// \brief set far clipping plane
void SetFar(float f);
/// \brief set near and far clipping plane at once
void SetNearFar(float n, float f);
/// \brief set field of view angle
void SetFOV(float f);
// \brief get the field of view
float GetFOV() const;
/// \brief offset between near clipping plane and start of fog
void SetFogNearOffset(float o);
/// \sa SetFogNearOffset
float GetFogNearOffset() const;
/// \brief offset between far clipping plane and end of fog
void SetFogFarOffset(float o);
/// \sa SetFogFarOffset
float GetFogFarOffset() const;
/// \brief convenciene function to set fog near and far offset
void SetFogOffsets(float no, float fo);
/// \brief adjust near and far clipping plane to fit visible objects
void Autoslab(bool fast=false, bool redraw=true);
// \brief adjust clipping planes to fix maximal extent of all objects
// even under rotation
void AutoslabMax();
/// \brief turn on automatic auto-slabbing (using the fast bounding box alg)
void AutoAutoslab(bool f);
//@}
/// \brief switch stereo mode
/*
0=off
1=quad-buffered
2=interlaced stereo
*/
void Stereo(unsigned int);
int GetStereo() const {return stereo_;}
/// \brief invert stereo eyes for stereo mode=0
void SetStereoInverted(bool f);
/// \brief stereo view mode, 0=center, 1=left, 2=right
void SetStereoView(unsigned int);
void SetStereoEyeDist(float);
void SetStereoEyeOff(float);
/// \brief set main light direction
void SetLightDir(const geom::Vec3& dir);
/// \brief set ambient, diffuse and specular light color
void SetLightProp(const Color& amb, const Color& diff, const Color& spec);
/// \brief set ambient, diffuse and specular light intensity
void SetLightProp(float amb, float diff, float spec);
/// \brief set the selection mode
/*
bad style for now: 0=(reserved), 1=atom, 2=residue, 3=chain, 4=bond, 5=torsion
*/
void SetSelectionMode(uint m);
uint GetSelectionMode() const;
/// \name Export
//@}
/// \brief export scene into a bitmap, rendering into offscreen of given size
/// if a main offscreen buffer is active (\sa StartOffscreenMode), then the
/// dimensions here are ignored
void Export(const String& fname, unsigned int w,
unsigned int h, bool transparent=true);
/// \brief export snapshot of current scene
void Export(const String& fname, bool transparent=true);
/// \brief export scene into povray files named fname.pov and fname.inc
void ExportPov(const std::string& fname, const std::string& wdir=".");
//@}
/// \brief entry point for gui events (internal use)
void OnInput(const InputEvent& e);
/// \brief initialize OpenGL after context has been setup (internal use)
void InitGL(bool full=true);
/// \brief handle new viewport size (internal use)
void Resize(int w, int h);
/// \brief pick at given mouse coords
void Pick(int mx, int my, int mask);
float GetDefaultTextSize();
/// \brief pick atom at given mouse coord
std::pair<GfxObjP, mol::AtomHandle> PickAtom(int mx, int my);
/// \brief render all gl objects (internal use)
void RenderGL();
/// \brief request redraw of gl scene
void RequestRedraw();
/// \brief send status message to gui
void StatusMessage(const String& s);
/// \brief set the viewport; the mapping to the visible window (internal use)
void SetViewport(int w, int h);
/// \brief set background color
void SetBackground(const Color& c);
/// \brief get background color
Color GetBackground() const;
/// \brief center rotation on the given point
void SetCenter(const geom::Vec3& cen);
/// \brief retrieve center
geom::Vec3 GetCenter() const;
/// \brief center on object of given name
void CenterOn(const String& s);
/// \brief center given object
void CenterOn(const GfxObjP& s);
/// \brief calculate projection of a point into the scene
geom::Vec3 Project(const geom::Vec3& v, bool ignore_vp=false) const;
/// \brief calculate unprojected point out of the scene
geom::Vec3 UnProject(const geom::Vec3& v, bool ignore_vp=false) const;
/// \brief return bounding box of scene under given transform
geom::AlignedCuboid GetBoundingBox(const mol::Transform& tf) const;
/// \brief get full underlying transformation
mol::Transform GetTransform() const;
/// \brief set transform
void SetTransform(const mol::Transform& t);
/// \brief returns a compact, internal representation of the scene orientation
geom::Mat4 GetRTC() const;
/// \brief sets a previously retrieved orientation
void SetRTC(const geom::Mat4& rtc);
/// \brief push the current orientation onto a stack
void PushView();
/// \brief retrieve a previously pushed orientation
void PopView();
/// brief re-generates the projection matrix (internal use)
void ResetProjection();
/// \brief gui glue interface (internal use)
void Register(GLWinBase* win);
/// \brief gui glue interface (internal use)
void Unregister(GLWinBase* win);
/// \name scene graph
//@{
/// \brief add graphical object to scene
void Add(const GfxNodeP& go, bool redraw=true);
/// \brief remove graphical object from scene
/// remove graphical object from the scene
void Remove(const GfxNodeP& go);
/// remove graphical object from the scene
void Remove(const String& name);
/// \brief remove all objects from the scene
void RemoveAll();
/// \brief rename an existing graphical object
/// defunct for now
bool Rename(const String& old_name, const String& new_name);
/// \brief retrieve gfx object by name
GfxObjP operator[](const String& name);
/// \brief whether the scene contains a node of the given name
bool HasNode(const String& name) const;
/// \brief actual event handling for scene (internal use)
void Apply(const InputEvent& ie, bool request_redraw=true);
/// \brief apply node visitor to root node
void Apply(GfxNodeVisitor& v) const;
/// \brief get total number of nodes in scene
///
/// To obtain the number of top-level nodes, use GfxNode::GetChildCount() of
/// the root node
size_t GetNodeCount() const;
/// \brief get root node of scene graph
GfxNodeP GetRootNode() const;
//@}
/// \brief observer interface (internal use)
void AttachObserver(SceneObserver* o);
/// \brief observer interface (internal use)
void DetachObserver(SceneObserver* o);
bool InOffscreenMode() const;
/// \brief switch into test mode (internal use)
void SetTestMode(bool t);
float ElapsedTime() const;
Viewport GetViewport() const;
/*!
This method has two different tasks.
During interactive rendering, it facilitates export
into an offscreen buffer with Scene::Export(file,width,height)
by avoiding repeated initializations of the GL state, e.g.
during animation rendering.
During batch mode, this is the only way to get meaningful
functionality with the gfx module
returns true upon success and false upon failure
*/
bool StartOffscreenMode(unsigned int w, unsigned int h);
/// \brief stops offline rendering in interactive mode
void StopOffscreenMode();
void SetBlur(uint n);
void BlurSnapshot();
void RenderText(const TextPrim& t);
geom::Vec3 GetLightDir() const {return light_dir_;}
geom::Mat3 GetLightRot() const {return light_rot_;}
void SetBeacon(int wx, int wy);
void SetBeaconOff();
protected:
friend class GfxObj;
friend class GfxNode;
// TODO: this is really a hack and not clean communication
friend class Entity;
void ObjectChanged(const String& name);
void SelectionChanged(const String& name, const mol::EntityView& sel);
void NodeTransformed(const GfxObjP& object);
void NodeAdded(const GfxNodeP& node);
void RenderModeChanged(const String& name);
private:
template <typename ACTION>
void NotifyObservers(const ACTION& action) {
std::for_each(observers_.begin(), observers_.end(), action);
}
Scene();
Scene(const Scene&) {}
Scene& operator=(const Scene&) {return *this;}
GLWinBase* win_; // target gl window
mutable GfxNodeP root_node_; // mutable is slightly hackish
SceneObserverList observers_;
mol::Transform transform_; // overall modelview transformation
bool gl_init_;
float fov_; // field of view
float znear_,zfar_; // near and far clipping plane
float fnear_,ffar_; // fog near and far offsets
unsigned int vp_width_,vp_height_; // viewport
SceneViewStack scene_view_stack_;
float aspect_ratio_; // aspect ratio for viewport
Color background_; // background (clear) color
geom::Vec3 light_dir_; // infinite light source direction
geom::Mat3 light_rot_; // transform needed for the shadow map
Color light_amb_;
Color light_diff_;
Color light_spec_;
bool axis_flag_;
bool fog_flag_;
Color fog_color_;
bool auto_autoslab_;
bool offscreen_flag_; // a simple indicator whether in offscreen mode or not
OffscreenBuffer* main_offscreen_buffer_; // not null if a main offscreen buffer is present
uint old_vp_[2]; // used by the offline rendering code
std::string def_shading_mode_;
uint selection_mode_;
bool test_flag_;
std::vector<unsigned char> tmp_tex_;
GLuint glyph_tex_id_;
std::vector<geom::Vec2> glyph_map_;
float def_text_size_;
uint blur_count_;
std::vector<boost::shared_array<unsigned char> > blur_buffer_;
unsigned int stereo_;
bool stereo_inverted_;
unsigned int stereo_eye_;
float stereo_eye_dist_,stereo_eye_off_;
unsigned int scene_left_tex_;
unsigned int scene_right_tex_;
void set_near(float n);
void set_far(float f);
void update_fog();
void flag_all_dirty();
void prep_glyphs();
void prep_blur();
void stereo_projection(unsigned int view);
void render_scene();
void render_glow();
void render_stereo();
bool IsNameAvailable(String name);
};
}} // ns
#endif