From e5eb661b0053e250942200ed43c6320ef860e34c Mon Sep 17 00:00:00 2001 From: ansgar <ansgar@5a81b35b-ba03-0410-adc8-b2c5c5119f08> Date: Wed, 28 Apr 2010 14:53:17 +0000 Subject: [PATCH] reverted all changes to the gfx module since r2007, except map_iso downsampling moved all these features to the new_gfx branch, including cpk fast spheres helix cylinders and flat beta strands ambient occlusion improved scene export and offscreen buffer handling fixes to shaders new GfxObj and GfxObjBase re-organization backbone trace/spline re-write vertex array fixes multisample extension detection git-svn-id: https://dng.biozentrum.unibas.ch/svn/openstructure/trunk@2130 5a81b35b-ba03-0410-adc8-b2c5c5119f08 --- modules/gfx/pymod/color_by_def.hh | 177 ++--- modules/gfx/pymod/export_entity.cc | 12 - modules/gfx/pymod/export_gfx_obj.cc | 97 +-- modules/gfx/pymod/export_render_options.cc | 6 - modules/gfx/pymod/export_scene.cc | 43 +- modules/gfx/pymod/glwin_base_proxy.hh | 3 - modules/gfx/pymod/wrap_gfx.cc | 13 +- modules/gfx/src/CMakeLists.txt | 17 +- modules/gfx/src/bitmap_io.cc | 8 +- modules/gfx/src/entity.cc | 68 +- modules/gfx/src/entity.hh | 9 - modules/gfx/src/gfx_node.cc | 6 - modules/gfx/src/gfx_node.hh | 1 - modules/gfx/src/gfx_object.cc | 747 +++++++++++------- modules/gfx/src/gfx_object.hh | 217 +++-- modules/gfx/src/gfx_prim.hh | 12 +- modules/gfx/src/glwin_base.hh | 4 - modules/gfx/src/impl/backbone_trace.cc | 257 +++--- modules/gfx/src/impl/backbone_trace.hh | 104 ++- modules/gfx/src/impl/cartoon_renderer.cc | 322 ++------ modules/gfx/src/impl/cartoon_renderer.hh | 27 +- modules/gfx/src/impl/debug_renderer.cc | 11 +- modules/gfx/src/impl/debug_renderer.hh | 2 +- modules/gfx/src/impl/entity_detail.cc | 186 +++-- modules/gfx/src/impl/entity_detail.hh | 35 +- modules/gfx/src/impl/entity_renderer.hh | 9 +- modules/gfx/src/impl/line_trace_renderer.cc | 65 +- modules/gfx/src/impl/line_trace_renderer.hh | 9 +- modules/gfx/src/impl/sline_renderer.cc | 41 +- modules/gfx/src/impl/sline_renderer.hh | 9 +- modules/gfx/src/impl/trace_renderer.cc | 177 ++++- modules/gfx/src/impl/trace_renderer.hh | 19 +- modules/gfx/src/impl/trace_renderer_base.cc | 78 +- modules/gfx/src/impl/trace_renderer_base.hh | 18 +- modules/gfx/src/offscreen_buffer.hh | 96 ++- modules/gfx/src/prim_list.cc | 23 +- modules/gfx/src/prim_list.hh | 8 - .../render_options/cartoon_render_options.cc | 31 +- .../render_options/cartoon_render_options.hh | 7 - .../src/render_options/cpk_render_options.cc | 2 +- modules/gfx/src/render_pass.hh | 4 +- modules/gfx/src/scene.cc | 281 ++----- modules/gfx/src/scene.hh | 36 +- modules/gfx/src/shader/fraglight_lf_fs.glsl | 30 +- modules/gfx/src/surface.cc | 84 +- modules/gfx/src/vertex_array.cc | 70 +- modules/gfx/src/vertex_array.hh | 34 +- modules/gui/pymod/scene/cpk_widget.py | 27 +- modules/gui/pymod/scene/hsc_widget.py | 61 +- 49 files changed, 1796 insertions(+), 1807 deletions(-) diff --git a/modules/gfx/pymod/color_by_def.hh b/modules/gfx/pymod/color_by_def.hh index d45bb327e..1c4643acd 100644 --- a/modules/gfx/pymod/color_by_def.hh +++ b/modules/gfx/pymod/color_by_def.hh @@ -22,16 +22,13 @@ #include <ost/config.hh> #include <ost/gfx/gfx_object.hh> -#if OST_IMG_ENABLED -#include <ost/img/alg/stat.hh> -#endif - using namespace ost; using namespace ost::gfx; namespace ost_gfx { -inline void color_by_e0(GfxObj* go, +#if OST_IMG_ENABLED +inline void color_by_01(GfxObj* go, const mol::EntityView& ev, const String& prop, const Gradient& g, float minv, float maxv) @@ -39,141 +36,117 @@ inline void color_by_e0(GfxObj* go, go->ColorBy(ev,prop,g,minv,maxv); } -inline void color_by_e1(GfxObj* go, - const mol::EntityView& ev, - const String& prop, - const Color& c1, const Color& c2, float minv, float maxv) +inline void color_by_02(GfxObj* go, + const ::img::MapHandle& mh, + const String& prop, + const Gradient& g, float minv, float maxv) { - Gradient g; - g.SetColorAt(0.0,c1); - g.SetColorAt(1.0,c2); - go->ColorBy(ev,prop,g,minv,maxv); + go->ColorBy(mh,prop,g,minv,maxv); } -inline void color_by_e2(GfxObj* go, - const mol::EntityHandle& eh, - const String& prop, - const Gradient& g, float minv, float maxv) + +inline void color_by_11(GfxObj* go, + const ::img::MapHandle& mh, + const String& prop, + const Gradient& g) { - go->ColorBy(eh.CreateFullView(),prop,g,minv,maxv); + go->ColorBy(mh,prop,g); } -inline void color_by_e3(GfxObj* go, - const mol::EntityHandle& eh, - const String& prop, - const Color& c1, const Color& c2, float minv, float maxv) +inline void color_by_12(GfxObj* go, + const ::img::MapHandle& mh, + const String& prop, + const Color& c1, const Color& c2) { - Gradient g; - g.SetColorAt(0.0,c1); - g.SetColorAt(1.0,c2); - go->ColorBy(eh.CreateFullView(),prop,g,minv,maxv); + go->ColorBy(mh,prop,c1,c2); } -inline void color_by_e4(GfxObj* go, - const mol::EntityView& ev, - const String& prop, - const Gradient& g) + +inline void color_by_04(GfxObj* go, + const ::img::MapHandle& mh, + const String& prop, + const Color& c1, const Color& c2, float minv, float maxv) { - std::pair<float,float> minmax = ev.GetMinMax(prop); - go->ColorBy(ev,prop,g,minmax.first, minmax.second); + go->ColorBy(mh,prop,c1,c2,minv,maxv); } -inline void color_by_e5(GfxObj* go, - const mol::EntityView& ev, - const String& prop, - const Color& c1, const Color& c2) +#endif + +inline void color_by_03(GfxObj* go, + const mol::EntityView& ev, + const String& prop, + const Color& c1, const Color& c2, float minv, float maxv) { - Gradient g; - g.SetColorAt(0.0,c1); - g.SetColorAt(1.0,c2); - std::pair<float,float> minmax = ev.GetMinMax(prop); - go->ColorBy(ev,prop,g,minmax.first, minmax.second); + go->ColorBy(ev,prop,c1,c2,minv,maxv); } -inline void color_by_e6(GfxObj* go, - const mol::EntityHandle& eh, - const String& prop, - const Gradient& g) + + +inline void color_by_05(GfxObj* go, + const mol::EntityHandle& eh, + const String& prop, + const Gradient& g, float minv, float maxv) { - color_by_e4(go,eh.CreateFullView(),prop,g); + go->ColorBy(eh,prop,g,minv,maxv); } -inline void color_by_e7(GfxObj* go, - const mol::EntityHandle& eh, - const String& prop, - const Color& c1, const Color& c2) +inline void color_by_06(GfxObj* go, + const mol::EntityHandle& eh, + const String& prop, + const Color& c1, const Color& c2, float minv, float maxv) { - color_by_e5(go,eh.CreateFullView(),prop,c1,c2); + go->ColorBy(eh,prop,c1,c2,minv,maxv); } -#if OST_IMG_ENABLED -inline void color_by_m0(GfxObj* go, - const ::img::MapHandle& mh, - const String& prop, - const Gradient& g, float minv, float maxv) -{ - go->ColorBy(mh,prop,g,minv,maxv); +inline void color_by_07(GfxObj* go, + const mol::EntityView& ev, + const String& prop, + const Gradient& g){ + go->ColorBy(ev,prop,g); } -inline void color_by_m1(GfxObj* go, - const ::img::MapHandle& mh, - const String& prop, - const Gradient& g) +inline void color_by_08(GfxObj* go, + const mol::EntityView& ev, + const String& prop, + const Color& c1, const Color& c2) { - ost::img::alg::Stat stat; - mh.Apply(stat); - float min = static_cast<float>(stat.GetMinimum()); - float max = static_cast<float>(stat.GetMaximum()); - std::pair<float,float> minmax = std::make_pair(min,max); - go->ColorBy(mh,prop,g,minmax.first, minmax.second); + go->ColorBy(ev,prop,c1,c2); } -inline void color_by_m2(GfxObj* go, - const ::img::MapHandle& mh, - const String& prop, - const Color& c1, const Color& c2) +inline void color_by_09(GfxObj* go, + const mol::EntityHandle& ev, + const String& prop, + const Gradient& g) { - Gradient g; - g.SetColorAt(0.0,c1); - g.SetColorAt(1.0,c2); - ost::img::alg::Stat stat; - mh.Apply(stat); - float min = static_cast<float>(stat.GetMinimum()); - float max = static_cast<float>(stat.GetMaximum()); - std::pair<float,float> minmax = std::make_pair(min,max); - go->ColorBy(mh,prop,g,minmax.first, minmax.second); + go->ColorBy(ev,prop,g); } -inline void color_by_m3(GfxObj* go, - const ::img::MapHandle& mh, - const String& prop, - const Color& c1, const Color& c2, float minv, float maxv) +inline void color_by_10(GfxObj* go, + const mol::EntityHandle& ev, + const String& prop, + const Color& c1, const Color& c2) { - Gradient g; - g.SetColorAt(0.0,c1); - g.SetColorAt(1.0,c2); - go->ColorBy(mh,prop,g,minv, maxv); + go->ColorBy(ev,prop,c1,c2); } -#endif } #define COLOR_BY_DEF_STD() \ - .def("ColorBy",ost_gfx::color_by_e0)\ - .def("ColorBy",ost_gfx::color_by_e1)\ - .def("ColorBy",ost_gfx::color_by_e2)\ - .def("ColorBy",ost_gfx::color_by_e3)\ - .def("ColorBy",ost_gfx::color_by_e4)\ - .def("ColorBy",ost_gfx::color_by_e5)\ - .def("ColorBy",ost_gfx::color_by_e6)\ - .def("ColorBy",ost_gfx::color_by_e7) + .def("ColorBy",ost_gfx::color_by_03)\ + .def("ColorBy",ost_gfx::color_by_05)\ + .def("ColorBy",ost_gfx::color_by_06)\ + .def("ColorBy",ost_gfx::color_by_07)\ + .def("ColorBy",ost_gfx::color_by_08)\ + .def("ColorBy",ost_gfx::color_by_09)\ + .def("ColorBy",ost_gfx::color_by_10) #if OST_IMG_ENABLED # define COLOR_BY_DEF_MAP() \ - .def("ColorBy",ost_gfx::color_by_m0)\ - .def("ColorBy",ost_gfx::color_by_m1)\ - .def("ColorBy",ost_gfx::color_by_m2)\ - .def("ColorBy",ost_gfx::color_by_m3) + .def("ColorBy",ost_gfx::color_by_01)\ + .def("ColorBy",ost_gfx::color_by_02)\ + .def("ColorBy",ost_gfx::color_by_04)\ + .def("ColorBy",ost_gfx::color_by_11)\ + .def("ColorBy",ost_gfx::color_by_12) #else # define COLOR_BY_DEF_MAP() #endif diff --git a/modules/gfx/pymod/export_entity.cc b/modules/gfx/pymod/export_entity.cc index 8d80170fb..23e341b04 100644 --- a/modules/gfx/pymod/export_entity.cc +++ b/modules/gfx/pymod/export_entity.cc @@ -92,16 +92,6 @@ void color_by_08(Entity* e, e->ColorBy(prop,c1,c2); } -// temporary, see comment in gfx/entity.hh -void detail_color_by_02(Entity* e, - const String& prop, - const Gradient& gradient, - float minv,float maxv) -{ - e->DetailColorBy(prop,gradient,minv,maxv); -} - - void radius_by_01(Entity* e, const String& prop, float rmin,float rmax, @@ -255,7 +245,6 @@ void export_Entity() .add_property("selection", &Entity::GetSelection, &Entity::SetSelection) .def("GetView", &Entity::GetView) - .def("UpdateView", &Entity::UpdateView) .def("GetRenderModeName", &Entity::GetRenderModeName) .def("GetNotEmptyRenderModes", &Entity::GetNotEmptyRenderModes) .def("SetRenderMode", set_rm1, arg("keep")=false) @@ -272,7 +261,6 @@ void export_Entity() .def("ColorBy", color_by_06) .def("ColorBy", color_by_07) .def("ColorBy", color_by_08) - .def("DetailColorBy", detail_color_by_02) COLOR_BY_DEF() .def("RadiusBy", radius_by_01) .def("RadiusBy", radius_by_02) diff --git a/modules/gfx/pymod/export_gfx_obj.cc b/modules/gfx/pymod/export_gfx_obj.cc index 3a0f4d7be..18e3454ee 100644 --- a/modules/gfx/pymod/export_gfx_obj.cc +++ b/modules/gfx/pymod/export_gfx_obj.cc @@ -25,77 +25,60 @@ using namespace ost::gfx; #include "color_by_def.hh" -namespace { - // convenience for python - void set_mat_amb2(GfxObjBase* b, float c) {b->SetMatAmb(Color(c,c,c,1.0));} - void set_mat_diff2(GfxObjBase* b, float c) {b->SetMatDiff(Color(c,c,c,1.0));} - void set_mat_spec2(GfxObjBase* b, float c) {b->SetMatSpec(Color(c,c,c,1.0));} - void set_mat_emm2(GfxObjBase* b, float c) {b->SetMatEmm(Color(c,c,c,1.0));} - void set_mat1(GfxObjBase* b, float a, float d, float s, float p) - { - set_mat_amb2(b,a); - set_mat_diff2(b,d); - set_mat_spec2(b,s); - b->SetMatShin(p); - set_mat_emm2(b,0.0); - } - void set_mat2(GfxObjBase* b, Color a, Color d, Color s, float p) - { - b->SetMatAmb(a); - b->SetMatDiff(d); - b->SetMatSpec(s); - b->SetMatShin(p); - set_mat_emm2(b,0.0); - } -} - void export_GfxObj() { - class_<GfxObjBase, bases<GfxNode>, boost::noncopyable>("GfxObjBase",no_init) - .def("SetMatAmb",&GfxObjBase::SetMatAmb) + void (GfxObj::* set_mat_amb1)(const Color&) = &GfxObj::SetMatAmb; + void (GfxObj::* set_mat_amb2)(float) = &GfxObj::SetMatAmb; + void (GfxObj::* set_mat_diff1)(const Color&) = &GfxObj::SetMatDiff; + void (GfxObj::* set_mat_diff2)(float) = &GfxObj::SetMatDiff; + void (GfxObj::* set_mat_spec1)(const Color&) = &GfxObj::SetMatSpec; + void (GfxObj::* set_mat_spec2)(float) = &GfxObj::SetMatSpec; + void (GfxObj::* set_mat_emm1)(const Color&) = &GfxObj::SetMatEmm; + void (GfxObj::* set_mat_emm2)(float) = &GfxObj::SetMatEmm; + void (GfxObj::* set_mat1)(const Color&,const Color&, + const Color&, float) = &GfxObj::SetMat; + void (GfxObj::* set_mat2)(float,float,float,float) = &GfxObj::SetMat; + + class_<GfxObj, bases<GfxNode>, boost::noncopyable>("GfxObj",no_init) + .def("GetCenter",&GfxObj::GetCenter) + .def("SetRenderMode", &GfxObj::SetRenderMode) + .def("GetRenderMode", &GfxObj::GetRenderMode) + .def("SetLineWidth", &GfxObj::SetLineWidth) + .def("GetLineWidth", &GfxObj::GetLineWidth) + .def("SetLineHalo",&GfxObj::SetLineHalo) + .def("GetLineHalo",&GfxObj::GetLineHalo) + .def("SetSphereDetail",&GfxObj::SetSphereDetail) + .def("SetArcDetail",&GfxObj::SetArcDetail) + .def("SetSplineDetail",&GfxObj::SetSplineDetail) + .def("SetMatAmb",set_mat_amb1) .def("SetMatAmb",set_mat_amb2) - .def("SetMatDiff",&GfxObjBase::SetMatDiff) + .def("SetMatDiff",set_mat_diff1) .def("SetMatDiff",set_mat_diff2) - .def("SetMatSpec",&GfxObjBase::SetMatSpec) + .def("GetTF", &GfxObj::GetTF, return_value_policy<copy_const_reference>()) + .def("SetTF", &GfxObj::SetTF) + .def("SetMatSpec",set_mat_spec1) .def("SetMatSpec",set_mat_spec2) - .def("SetMatEmm",&GfxObjBase::SetMatEmm) + .def("SetMatEmm",set_mat_emm1) .def("SetMatEmm",set_mat_emm2) - .def("SetMatShin",&GfxObjBase::SetMatShin) + .def("SetMatShin",&GfxObj::SetMatShin) .def("SetMat",set_mat1) .def("SetMat",set_mat2) - .def("ContextSwitch", &GfxObjBase::ContextSwitch) - .def("SetRenderMode", &GfxObjBase::SetRenderMode) - .def("GetRenderMode", &GfxObjBase::GetRenderMode) - .def("GetCenter",&GfxObjBase::GetCenter) - .def("SetLineWidth", &GfxObjBase::SetLineWidth) - .def("SetPolyMode",&GfxObjBase::SetPolyMode) - .def("AALines",&GfxObjBase::AALines) - .def("SetLineHalo",&GfxObjBase::SetLineHalo) - .def("Outline",&GfxObjBase::Outline) - .def("SetOutlineMode",&GfxObjBase::SetOutlineMode) - .def("SetOutlineExpandFactor",&GfxObjBase::SetOutlineExpandFactor) - .def("SetOutlineExpandColor",&GfxObjBase::SetOutlineExpandColor) - .def("AmbientOcclusion",&GfxObjBase::AmbientOcclusion) - .def("SetAmbientLocalWeight",&GfxObjBase::SetAmbientLocalWeight) - .def("SetAmbientOcclusionWeight",&GfxObjBase::SetAmbientOcclusionWeight) - .def("SetOpacity",&GfxObjBase::SetOpacity) - .add_property("center", &GfxObjBase::GetCenter) - COLOR_BY_DEF() - ; - - class_<GfxObj, bases<GfxObjBase>, boost::noncopyable>("GfxObj",no_init) - .def("GetTF", &GfxObj::GetTF, return_value_policy<copy_const_reference>()) - .def("SetTF", &GfxObj::SetTF) + .def("SetPolyMode",&GfxObj::SetPolyMode) + .def("SetAALines",&GfxObj::SetAALines) + .def("SetOpacity",&GfxObj::SetOpacity) + .def("GetOpacity",&GfxObj::GetOpacity) .def("FlagRebuild",&GfxObj::FlagRebuild) .def("FlagRefresh",&GfxObj::FlagRefresh) .def("SetNormalSmoothFactor",&GfxObj::SetNormalSmoothFactor) .def("GetNormalSmoothFactor",&GfxObj::GetNormalSmoothFactor) + .def("SetOutlineMode",&GfxObj::SetOutlineMode) + .def("SetOutlineExpandFactor",&GfxObj::SetOutlineExpandFactor) + .def("SetOutlineExpandColor",&GfxObj::SetOutlineExpandColor) .def("SmoothVertices",&GfxObj::SmoothVertices) + .def("AmbientOcclusion",&GfxObj::AmbientOcclusion) .def("Debug",&GfxObj::Debug) - .def("GetAALines",&GfxObj::GetAALines) - .def("GetLineWidth",&GfxObj::GetLineWidth) - .def("GetLineHalo",&GfxObj::GetLineHalo) - .def("GetOpacity",&GfxObj::GetOpacity) + .add_property("center", &GfxObj::GetCenter) + COLOR_BY_DEF() ; register_ptr_to_python<GfxObjP>(); diff --git a/modules/gfx/pymod/export_render_options.cc b/modules/gfx/pymod/export_render_options.cc index 51e9829c7..b27e55c46 100644 --- a/modules/gfx/pymod/export_render_options.cc +++ b/modules/gfx/pymod/export_render_options.cc @@ -102,8 +102,6 @@ void export_RenderOptions() .def("GetHelixEcc", &CartoonRenderOptions::GetHelixEcc) .def("SetHelixProfileType", &CartoonRenderOptions::SetHelixProfileType) .def("GetHelixProfileType", &CartoonRenderOptions::GetHelixProfileType) - .def("SetHelixMode", &CartoonRenderOptions::SetHelixMode) - .def("GetHelixMode", &CartoonRenderOptions::GetHelixMode) .def("SetStrandWidth", &CartoonRenderOptions::SetStrandWidth) .def("GetStrandWidth", &CartoonRenderOptions::GetStrandWidth) .def("SetStrandThickness", &CartoonRenderOptions::SetStrandThickness) @@ -112,8 +110,6 @@ void export_RenderOptions() .def("GetStrandEcc", &CartoonRenderOptions::GetStrandEcc) .def("SetStrandProfileType", &CartoonRenderOptions::SetStrandProfileType) .def("GetStrandProfileType", &CartoonRenderOptions::GetStrandProfileType) - .def("SetStrandMode", &CartoonRenderOptions::SetStrandMode) - .def("GetStrandMode", &CartoonRenderOptions::GetStrandMode) ; class_<TraceRenderOptions, boost::shared_ptr<TraceRenderOptions>, bases<RenderOptions>, boost::noncopyable>("TraceRenderOptions") @@ -123,8 +119,6 @@ void export_RenderOptions() .def("GetNormalSmoothFactor", &TraceRenderOptions::GetNormalSmoothFactor) .def("SetTubeRadius", &TraceRenderOptions::SetTubeRadius) .def("GetTubeRadius", &TraceRenderOptions::GetTubeRadius) - .def("SetRadius", &TraceRenderOptions::SetTubeRadius) - .def("GetRadius", &TraceRenderOptions::GetTubeRadius) ; } diff --git a/modules/gfx/pymod/export_scene.cc b/modules/gfx/pymod/export_scene.cc index d87d76308..9cae54473 100644 --- a/modules/gfx/pymod/export_scene.cc +++ b/modules/gfx/pymod/export_scene.cc @@ -33,6 +33,7 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(scene_autoslab_overloads, BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(scene_export_pov_overloads, Scene::ExportPov, 1,2) void (Scene::*apply)(const InputEvent&, bool)=&Scene::Apply; +namespace { Scene* get_scene() { @@ -48,13 +49,16 @@ GfxObjP scene_getitem(Scene* scene, const String& item) return scene->operator[](item); } -} // anon ns +} +} void export_Scene() { def("Scene",get_scene,return_value_policy<reference_existing_object>()); + def("set_offscreen_mode",&Scene::SetOffscreenMode); + // will be removed... def("PickAtom", &pick_atom); @@ -87,9 +91,16 @@ void export_Scene() .def("RenderGL", &Scene::RenderGL) .def("Resize", &Scene::Resize) .def("SetBackground", &Scene::SetBackground) + .add_property("center", &Scene::GetCenter, &Scene::SetCenter) + .add_property("near", &Scene::GetNear, &Scene::SetNear) + .add_property("far", &Scene::GetFar, &Scene::SetFar) .def("SetNearFar",&Scene::SetNearFar) .def("SetFog",&Scene::SetFog) .def("SetFogColor",&Scene::SetFogColor) + .add_property("fog_near_offset", &Scene::GetFogNearOffset, + &Scene::SetFogNearOffset) + .add_property("fog_far_offset", &Scene::GetFogFarOffset, + &Scene::SetFogFarOffset) .def("SetFOV",&Scene::SetFOV) .def("GetFOV",&Scene::GetFOV) .def("SetFogOffsets",&Scene::SetFogOffsets) @@ -117,36 +128,8 @@ void export_Scene() .def("SetShadow",&Scene::SetShadow) .def("SetShadowQuality",&Scene::SetShadowQuality) .def("AttachObserver",&Scene::AttachObserver) - .def("StartOffscreenMode",&Scene::StartOffscreenMode) - .def("StopOffscreenMode",&Scene::StopOffscreenMode) - .def("__getitem__",scene_getitem) - .add_property("bg", - &Scene::GetBackground, - &Scene::SetBackground) - .add_property("center", &Scene::GetCenter, &Scene::SetCenter) - .add_property("near", &Scene::GetNear, &Scene::SetNear) - .add_property("far", &Scene::GetFar, &Scene::SetFar) - .add_property("fov", &Scene::GetFOV, &Scene::SetFOV) - .add_property("fog", &Scene::GetFog, &Scene::SetFog) - .add_property("fogcol", &Scene::GetFogColor, &Scene::SetFogColor) - .add_property("fogno", - &Scene::GetFogNearOffset, - &Scene::SetFogNearOffset) - .add_property("fogfo", - &Scene::GetFogFarOffset, - &Scene::SetFogFarOffset) - .add_property("smode", - &Scene::GetSelectionMode, - &Scene::SetSelectionMode) - // deprecated python properties! .add_property("selection_mode", &Scene::GetSelectionMode, &Scene::SetSelectionMode) - .add_property("fog_near_offset", - &Scene::GetFogNearOffset, - &Scene::SetFogNearOffset) - .add_property("fog_far_offset", - &Scene::GetFogFarOffset, - &Scene::SetFogFarOffset) - + .def("__getitem__",scene_getitem) ; } diff --git a/modules/gfx/pymod/glwin_base_proxy.hh b/modules/gfx/pymod/glwin_base_proxy.hh index 8bfea675a..6c73fd142 100644 --- a/modules/gfx/pymod/glwin_base_proxy.hh +++ b/modules/gfx/pymod/glwin_base_proxy.hh @@ -26,9 +26,6 @@ public: virtual void StatusMessage(const String& m) { call_method<void, const String>(self, "StatusMessage", m); } - virtual bool HasMultisample() const { - return call_method<bool>(self,"HasMultisample"); - } private: PyObject* self; diff --git a/modules/gfx/pymod/wrap_gfx.cc b/modules/gfx/pymod/wrap_gfx.cc index 1c8ca0065..dd2049702 100644 --- a/modules/gfx/pymod/wrap_gfx.cc +++ b/modules/gfx/pymod/wrap_gfx.cc @@ -23,9 +23,7 @@ using namespace boost::python; #include <ost/gfx/prim_list.hh> #include <ost/gfx/gradient.hh> #include <ost/gfx/gfx_test_object.hh> -#if OST_SHADER_SUPPORT_ENABLED -#include <ost/gfx/shader.hh> -#endif + #include <boost/python/suite/indexing/vector_indexing_suite.hpp> extern void export_Scene(); @@ -172,15 +170,6 @@ BOOST_PYTHON_MODULE(_gfx) .def("GetRel", &Stop::GetRel) ; -#if OST_SHADER_SUPPORT_ENABLED - class_<Shader, boost::noncopyable>("Shader", no_init) - .def("Instance",&Shader::Instance, - return_value_policy<reference_existing_object>()).staticmethod("Instance") - .def("PushProgram",&Shader::PushProgram) - .def("PopProgram",&Shader::PopProgram) - .def("Activate",&Shader::Activate) - ; -#endif export_primitives(); } diff --git a/modules/gfx/src/CMakeLists.txt b/modules/gfx/src/CMakeLists.txt index 9f3d471ff..c07798109 100644 --- a/modules/gfx/src/CMakeLists.txt +++ b/modules/gfx/src/CMakeLists.txt @@ -10,7 +10,6 @@ gfx_fw.hh gfx_node.hh gfx_node_fw.hh gfx_node_visitor.hh -gfx_object_base.hh gfx_object.hh gfx_object_fw.hh gfx_prim.hh @@ -90,6 +89,7 @@ set(OST_GFX_SOURCES bitmap_io.cc color.cc primitives.cc +offscreen_buffer.cc entity.cc symmetry_node.cc @@ -173,21 +173,6 @@ else() set(OST_GFX_MAP_SOURCES "") endif() -if (UNIX AND NOT APPLE) - list(APPEND OST_GFX_SOURCES impl/glx_offscreen_buffer.cc) - list(APPEND OST_GFX_IMPL_HEADERS glx_offscreen_buffer.hh) -endif() - -if (APPLE) - list(APPEND OST_GFX_SOURCES impl/cgl_offscreen_buffer.cc) - list(APPEND OST_GFX_IMPL_HEADERS cgl_offscreen_buffer.hh) -endif() - -if(WIN32) - list(APPEND OST_GFX_SOURCES impl/wgl_offscreen_buffer.cc) - list(APPEND OST_GFX_IMPL_HEADERS wgl_offscreen_buffer.hh) -endif() - if (USE_SHADER) message("Compiling with Shader Support") list(APPEND OST_GFX_SOURCES shader.cc) diff --git a/modules/gfx/src/bitmap_io.cc b/modules/gfx/src/bitmap_io.cc index 677b602c6..8de3d7ea0 100644 --- a/modules/gfx/src/bitmap_io.cc +++ b/modules/gfx/src/bitmap_io.cc @@ -38,8 +38,7 @@ void export_png(const String& filename, unsigned int width, unsigned int height, LOGN_ERROR("error opening" << filename << " for exporting"); return; } - - LOGN_DEBUG("creating png write struct"); + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { @@ -48,7 +47,6 @@ void export_png(const String& filename, unsigned int width, unsigned int height, return; } - LOGN_DEBUG("creating png info struct"); png_infop info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); @@ -74,24 +72,20 @@ void export_png(const String& filename, unsigned int width, unsigned int height, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - LOGN_DEBUG("writing png info"); png_write_info(png_ptr, info_ptr); png_bytep* row_pointers = new png_bytep[height]; png_byte* png_data = data; - LOGN_DEBUG("assigning png row pointers"); for(uint i=0;i<height;++i){ row_pointers[height-i-1]=&png_data[i*4*width]; } - LOGN_DEBUG("writing png image"); png_write_image(png_ptr, row_pointers); delete []row_pointers; - LOGN_DEBUG("finalizing png write"); png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, (png_infopp)NULL); diff --git a/modules/gfx/src/entity.cc b/modules/gfx/src/entity.cc index 25d63fd4a..f7b924c13 100644 --- a/modules/gfx/src/entity.cc +++ b/modules/gfx/src/entity.cc @@ -105,9 +105,8 @@ Entity::Entity(const String& name, impl::EntityRenderer* Entity::GetOrCreateRenderer(RenderMode::Type rm) { - RendererMap::iterator rit = renderer_.find(rm); - if(rit!=renderer_.end()) { - return rit->second; + if (renderer_.find(rm)!=renderer_.end()) { + return renderer_.find(rm)->second; } impl::EntityRenderer* r=NULL; switch (rm) { @@ -118,22 +117,22 @@ impl::EntityRenderer* Entity::GetOrCreateRenderer(RenderMode::Type rm) r=new impl::CustomRenderer(); break; case RenderMode::SLINE: - r=new impl::SlineRenderer(&trace_); + r=new impl::SlineRenderer(trace_); break; case RenderMode::LINE_TRACE: - r=new impl::LineTraceRenderer(&trace_); + r=new impl::LineTraceRenderer(trace_); break; case RenderMode::TRACE: - r=new impl::TraceRenderer(&trace_); + r=new impl::TraceRenderer(trace_); break; case RenderMode::HSC: - r=new impl::CartoonRenderer(&trace_,false); + r=new impl::CartoonRenderer(trace_); break; case RenderMode::CPK: r=new impl::CPKRenderer(); break; case RenderMode::TUBE: - r=new impl::CartoonRenderer(&trace_, true); + r=new impl::CartoonRenderer(trace_, true); break; default: return 0; @@ -145,14 +144,11 @@ impl::EntityRenderer* Entity::GetOrCreateRenderer(RenderMode::Type rm) void Entity::init(RenderMode::Type rm) { // TODO replace with def mat for this gfx obj type - SetMatAmb(Color(0,0,0)); - SetMatDiff(Color(1,1,1)); - SetMatSpec(Color(0.7,0.7,0.7)); - SetMatShin(96); + SetMat(0.0,1.0,0.8,96.0); update_view_=true; render_mode_=rm; - trace_.ResetView(this->GetView()); + trace_.SetView(this->GetView()); sel_=this->GetView().CreateEmptyView(); impl::EntityRenderer* r=this->GetOrCreateRenderer(rm); if(!r) return; @@ -201,18 +197,6 @@ void Entity::SetBlurFactors(float bf1,float bf2) void Entity::Rebuild() { geom::Vec3 delta=GetTF().GetTrans()-GetTF().GetCenter(); - - if(update_view_) { - EntityView nv=this->GetView(); - for (RendererMap::iterator i=renderer_.begin(), - e=renderer_.end(); i!=e; ++i) { - i->second->ClearViews(); - i->second->AddView(nv); - i->second->UpdateViews(); - i->second->PrepareRendering(); - } - } - this->ReapplyColorOps(); FlagRebuild(); geom::Vec3 center=this->GetCenter(); @@ -341,15 +325,16 @@ void Entity::CustomRenderGL(RenderPass pass) e=renderer_.end(); i!=e; ++i) { impl::EntityRenderer* r=i->second; if(r->IsEnabled()){ - if(pass==STANDARD_RENDER_PASS || pass==OPAQUE_RENDER_PASS) { - r->Render(pass); - if(pass==STANDARD_RENDER_PASS && outline_flag_) { - r->VA().SetOutlineMode(outline_mode_); + switch(pass) { + case STANDARD_RENDER_PASS: + case OPAQUE_RENDER_PASS: r->Render(pass); - r->VA().SetOutlineMode(0); - } - } else if(pass==GLOW_RENDER_PASS && r->HasSelection()) { - r->Render(pass); + break; + case GLOW_RENDER_PASS: + if (r->HasSelection()) { + r->Render(pass); + } + break; } } } @@ -780,16 +765,6 @@ void Entity::ColorBy(const String& prop, this->Apply(glop); } -void Entity::DetailColorBy(const String& prop, - const Gradient& gradient, - float minv,float maxv, - mol::Prop::Level level) -{ - GradientLevelColorOp glop = GradientLevelColorOp("",prop, gradient,minv,maxv,level); - glop.SetMask(DETAIL_COLOR); - this->Apply(glop); -} - void Entity::ColorBy(const String& prop, const Color& c1, const Color& c2, float minv, float maxv, @@ -973,11 +948,4 @@ void Entity::ReapplyColorOps() GfxObj::ReapplyColorOps(); } -void Entity::UpdateView() -{ - update_view_=true; - Rebuild(); - UpdatePositions(); -} - }} // ns diff --git a/modules/gfx/src/entity.hh b/modules/gfx/src/entity.hh index c0b3c3a9f..368445df0 100644 --- a/modules/gfx/src/entity.hh +++ b/modules/gfx/src/entity.hh @@ -199,12 +199,6 @@ public: float minv,float maxv, mol::Prop::Level hint=mol::Prop::UNSPECIFIED); - // temporary, should be incorporated with ColorBy - void DetailColorBy(const String& prop, - const Gradient& gradient, - float minv,float maxv, - mol::Prop::Level hint=mol::Prop::UNSPECIFIED); - // convenience void ColorBy(const String& prop, const Gradient& gradient, @@ -263,9 +257,6 @@ public: void ApplyOptions(RenderMode::Type render_mode, RenderOptionsPtr& render_options); bool HasSelection() const; - - void UpdateView(); - protected: virtual void CustomPreRenderGL(bool flag); diff --git a/modules/gfx/src/gfx_node.cc b/modules/gfx/src/gfx_node.cc index 395658e96..f3a61c11e 100644 --- a/modules/gfx/src/gfx_node.cc +++ b/modules/gfx/src/gfx_node.cc @@ -160,11 +160,5 @@ bool GfxNode::IsVisible() const return show_; } -void GfxNode::ContextSwitch() -{ - for(GfxNodeVector::iterator it =node_vector_.begin();it!=node_vector_.end();++it) { - (*it)->ContextSwitch(); - } -} }} // ns diff --git a/modules/gfx/src/gfx_node.hh b/modules/gfx/src/gfx_node.hh index eb4fcc2bb..0f7ecc2d0 100644 --- a/modules/gfx/src/gfx_node.hh +++ b/modules/gfx/src/gfx_node.hh @@ -95,7 +95,6 @@ class DLLEXPORT_OST_GFX GfxNode: public boost::enable_shared_from_this<GfxNode> // return visibility state bool IsVisible() const; - virtual void ContextSwitch(); private: GfxNode(const GfxNode& o); diff --git a/modules/gfx/src/gfx_object.cc b/modules/gfx/src/gfx_object.cc index 4231be8dc..0a28a7e6e 100644 --- a/modules/gfx/src/gfx_object.cc +++ b/modules/gfx/src/gfx_object.cc @@ -41,7 +41,7 @@ namespace ost { namespace gfx { GfxObj::GfxObj(const String& name): - GfxObjBase(name), + GfxNode(name), va_(), render_mode_(RenderMode::SIMPLE), debug_flags_(0), @@ -49,6 +49,9 @@ GfxObj::GfxObj(const String& name): rebuild_(true), refresh_(false), line_width_(2.0), + sphere_detail_(4), + arc_detail_(4), + spline_detail_(8), poly_mode_(2), aalines_flag_(false), line_halo_(0.0), @@ -57,22 +60,64 @@ GfxObj::GfxObj(const String& name): mat_update_(true), opacity_(1.0), smoothf_(0.0), - outline_flag_(false), - outline_mode_(1), + omode_(0), c_ops_(), labels_(), use_occlusion_(false) { } -GfxObj::GfxObj(const GfxObj&): - GfxObjBase("") // to make the compiler happy +GfxObj::~GfxObj() +{} + +GfxObj::GfxObj(const GfxObj& o): + GfxNode("") // to make the compiler happy {} GfxObj& GfxObj::operator=(const GfxObj&) {return *this;} -//////////////////////////////////////// -// the GfxNode interface +void GfxObj::Apply(GfxNodeVisitor& v, GfxNodeVisitor::Stack st) +{ + v.VisitObject(this,st); +} + +int GfxObj::GetType() const +{ + return 1; +} + +geom::AlignedCuboid GfxObj::GetBoundingBox() const +{ + return geom::AlignedCuboid(geom::Vec3(),geom::Vec3()); +} + +void GfxObj::ProcessLimits(geom::Vec3& minc, geom::Vec3& maxc, + const mol::Transform& tf) const +{ + try { + geom::AlignedCuboid coord_limits=this->GetBoundingBox(); + // update min/max by transforming all 8 corners of the bounding box and + // comparing it against the current min/max + geom::Vec3 mmin=coord_limits.GetMin(); + geom::Vec3 mmax=coord_limits.GetMax(); + geom::Vec3 t1=tf.Apply(geom::Vec3(mmin[0], mmin[1], mmin[2])); + geom::Vec3 t2=tf.Apply(geom::Vec3(mmin[0], mmax[1], mmin[2])); + geom::Vec3 t3=tf.Apply(geom::Vec3(mmax[0], mmax[1], mmin[2])); + geom::Vec3 t4=tf.Apply(geom::Vec3(mmax[0], mmin[1], mmin[2])); + geom::Vec3 t5=tf.Apply(geom::Vec3(mmin[0], mmin[1], mmax[2])); + geom::Vec3 t6=tf.Apply(geom::Vec3(mmin[0], mmax[1], mmax[2])); + geom::Vec3 t7=tf.Apply(geom::Vec3(mmax[0], mmax[1], mmax[2])); + geom::Vec3 t8=tf.Apply(geom::Vec3(mmax[0], mmin[1], mmax[2])); + minc = geom::Min(minc, geom::Min(t1, geom::Min(t2, geom::Min(t3, + geom::Min(t4, geom::Min(t5, geom::Min(t6, + geom::Min(t7, t8)))))))); + maxc = geom::Max(maxc, geom::Max(t1, geom::Max(t2, geom::Max(t3, + geom::Max(t4, geom::Max(t5, geom::Max(t6, + geom::Max(t7, t8)))))))); + } catch(Error& e) { + // in case the object is empty... + } +} GfxNodeP GfxObj::Copy() const { @@ -85,6 +130,9 @@ void GfxObj::DeepSwap(GfxObj& go) std::swap(transform_,go.transform_); std::swap(rebuild_,go.rebuild_); std::swap(refresh_,go.refresh_); + std::swap(sphere_detail_,go.sphere_detail_); + std::swap(arc_detail_,go.arc_detail_); + std::swap(spline_detail_,go.spline_detail_); std::swap(poly_mode_,go.poly_mode_); std::swap(aalines_flag_,go.aalines_flag_); std::swap(line_halo_,go.line_halo_); @@ -93,132 +141,95 @@ void GfxObj::DeepSwap(GfxObj& go) std::swap(mat_update_,go.mat_update_); std::swap(opacity_,go.opacity_); std::swap(smoothf_,go.smoothf_); - std::swap(outline_flag_,go.outline_flag_); - std::swap(outline_mode_,go.outline_mode_); - std::swap(c_ops_,go.c_ops_); - std::swap(labels_,go.labels_); - std::swap(use_occlusion_,go.use_occlusion_); -} - -void GfxObj::RenderGL(RenderPass pass) -{ - LOGN_TRACE("object " << GetName() << ": RenderGL()"); - - if(pass==0) { - if(mat_update_) { - LOGN_TRACE("updating material display list"); - if(mat_dlist_==0) { - mat_dlist_=glGenLists(1); - } - glNewList(mat_dlist_,GL_COMPILE); - mat_.RenderGL(); - glEndList(); - mat_update_=false; - } - - if(rebuild_ || refresh_) { - PreRenderGL(rebuild_); - rebuild_=false; - refresh_=false; - } - } - if(IsVisible()) { - LOGN_TRACE("applying local transformation"); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glMultMatrix(transform_.GetTransposedMatrix().Data()); - if(Scene::Instance().InOffscreenMode()) { - LOGN_TRACE("applying material"); - mat_.RenderGL(); - } else { - LOGN_TRACE("applying material display list"); - glCallList(mat_dlist_); - } - LOGN_TRACE("calling custom render gl pass " << pass); - - CustomRenderGL(pass); - - if(pass==0 && outline_flag_>0) { - va_.SetOutlineMode(outline_mode_); - CustomRenderGL(pass); - va_.SetOutlineMode(0); - } - - if(pass==1) { - LOGN_TRACE("drawing labels"); - render_labels(); - } - - glPopMatrix(); - } } +void GfxObj::CustomRenderGL(RenderPass pass) {} +void GfxObj::CustomPreRenderGL(bool flag) {} -void GfxObj::RenderPov(PovState& pov) -{ - if(IsVisible()) { - pov.start_obj(GetName(),1.0,1.0,1.0); - // apply local transformation - // using transform_ - if(rebuild_ || refresh_) { - PreRenderGL(true); - } - CustomRenderPov(pov); - pov.end_obj(); - } -} +void GfxObj::CustomRenderPov(PovState& pov) {} -void GfxObj::Apply(GfxNodeVisitor& v, GfxNodeVisitor::Stack st) +void GfxObj::RefreshVA(IndexedVertexArray& va) { - v.VisitObject(this,st); + va.SetLineWidth(GetLineWidth()); + va.SetPolyMode(GetPolyMode()); + va.SetAALines(GetAALines()); + va.SetLineHalo(GetLineHalo()); + va.DrawNormals(debug_flags_&0x1); + va.SetPolyMode(debug_flags_&0x2 ? 1 : 2); + va.UseAmbient(use_occlusion_); + va.FlagRefresh(); } -int GfxObj::GetType() const +void GfxObj::OnInput(const InputEvent& e) { - return 1; -} + geom::Mat3 rot=gfx::Scene::Instance().GetTransform().GetRot(); + geom::Vec3 cam_trans=gfx::Scene::Instance().GetTransform().GetTrans(); + float x=e.GetDelta()*M_PI/180.0; + bool transformed=false; + if (e.GetCommand()==INPUT_COMMAND_ROTX) { + transformed=true; + transform_.SetRot(AxisRotation(geom::Vec3(1,0,0)*rot,x)*transform_.GetRot()); + } else if(e.GetCommand()==INPUT_COMMAND_ROTY) { + transformed=true; + transform_.SetRot(AxisRotation(geom::Vec3(0,1,0)*rot,x)*transform_.GetRot()); + } else if(e.GetCommand()==INPUT_COMMAND_ROTZ) { + transformed=true; + transform_.SetRot(AxisRotation(geom::Vec3(0,0,1)*rot,x)*transform_.GetRot()); + } else if(e.GetCommand()==INPUT_COMMAND_TRANSX || + e.GetCommand()==INPUT_COMMAND_TRANSY) { + + double mm[]={1,0,0,0, + 0,1,0,0, + 0,0,1,0, + transform_.GetTrans()[0]-cam_trans[0], + transform_.GetTrans()[1]-cam_trans[1], + transform_.GetTrans()[2]-cam_trans[2], 1}; + double pm[16]; + glGetDoublev(GL_PROJECTION_MATRIX,pm); + GLint vp[4]; + glGetIntegerv(GL_VIEWPORT,vp); + double wx,wy,wz; + gluProject(0.0,0.0,0.0,mm,pm,vp,&wx,&wy,&wz); + double ox,oy,oz; + gluUnProject(wx+1.0,wy+1.0,wz,mm,pm,vp,&ox,&oy,&oz); -//////////////////////////////////////// -// now for the GfxObjBase interface -void GfxObj::SetMatAmb(const Color& c) -{ - mat_.SetAmb(c); - mat_update_=true; - Scene::Instance().RequestRedraw(); + float fx=ox; + float fy=oy; + geom::Vec3 trans=transform_.GetTrans(); + transformed=true; + if (e.GetCommand()==INPUT_COMMAND_TRANSX) { + trans+=geom::Vec3(-fx*e.GetDelta(), 0.0, 0.0)*rot; + } else { + trans+=geom::Vec3(0.0, -fy*e.GetDelta(), 0.0)*rot; + } + transform_.SetTrans(trans); + } + if (transformed) { + GfxObjP obj=dyn_cast<GfxObj>(this->shared_from_this()); + Scene::Instance().NodeTransformed(obj); + } } -void GfxObj::SetMatDiff(const Color& c) +const mol::Transform& GfxObj::GetTF() const { - mat_.SetDiff(c); - mat_update_=true; - Scene::Instance().RequestRedraw(); + return transform_; } -void GfxObj::SetMatSpec(const Color& c) -{ - mat_.SetSpec(c); - mat_update_=true; - Scene::Instance().RequestRedraw(); -} -void GfxObj::SetMatShin(float s) +void GfxObj::SetTF(const mol::Transform& tf) { - mat_.SetShin(s); - mat_update_=true; - Scene::Instance().RequestRedraw(); + transform_=tf; } -void GfxObj::SetMatEmm(const Color& c) +geom::Vec3 GfxObj::GetCenter() const { - mat_.SetEmm(c); - mat_update_=true; - Scene::Instance().RequestRedraw(); + return this->GetBoundingBox().GetCenter(); } -void GfxObj::ContextSwitch() +bool GfxObj::OnSelect(const geom::Line3& l, geom::Vec3& result, + float zlim, bool pick_flag) { - FlagRebuild(); - GfxNode::ContextSwitch(); + return false; } void GfxObj::SetRenderMode(RenderMode::Type m) @@ -234,248 +245,197 @@ RenderMode::Type GfxObj::GetRenderMode() const return render_mode_; } -geom::Vec3 GfxObj::GetCenter() const +void GfxObj::FlagRebuild() { - return this->GetBoundingBox().GetCenter(); + rebuild_=true; + Scene::Instance().RequestRedraw(); } -void GfxObj::SetLineWidth(float w) +void GfxObj::FlagRefresh() { - va_.SetLineWidth(w); - line_width_=std::max(float(0.01),w); - FlagRefresh(); - Scene::Instance().RenderModeChanged(GetName()); + refresh_=true; + Scene::Instance().RequestRedraw(); } -void GfxObj::SetPolyMode(unsigned int m) +void GfxObj::SetNormalSmoothFactor(float smoothf) { - if(m==poly_mode_) return; - poly_mode_=std::min((unsigned int)2,m); - va_.SetPolyMode(poly_mode_); - FlagRefresh(); + smoothf_=smoothf; + FlagRebuild(); } -void GfxObj::AALines(bool f) +float GfxObj::GetNormalSmoothFactor() const { - if(f==aalines_flag_) return; - va_.SetAALines(f); - aalines_flag_=f; - FlagRefresh(); + return smoothf_; } -void GfxObj::SetLineHalo(float f) +void GfxObj::OnRenderModeChange() { - va_.SetLineHalo(f); - line_halo_=f; - FlagRefresh(); + Scene::Instance().ObjectChanged(GetName()); + Scene::Instance().RenderModeChanged(GetName()); } -void GfxObj::Outline(bool f) +void GfxObj::SetLineWidth(float w) { - outline_flag_=f; + line_width_=std::max(float(0.01),w); FlagRefresh(); - if(f) { - outline_mode_=std::min(3,std::max(1,outline_mode_)); - } - Scene::Instance().RequestRedraw(); -} - -void GfxObj::SetOutlineMode(int m) -{ - outline_mode_=m; - if(outline_flag_) { - FlagRefresh(); - Scene::Instance().RequestRedraw(); - } + Scene::Instance().RenderModeChanged(GetName()); } -void GfxObj::SetOutlineExpandFactor(float f) +float GfxObj::GetLineWidth() const { - va_.SetOutlineExpandFactor(f); + return line_width_; } -void GfxObj::SetOutlineExpandColor(const Color& c) +void GfxObj::SetSphereDetail(unsigned int d) { - va_.SetOutlineExpandColor(c); -} - -void GfxObj::AmbientOcclusion(bool f) -{ - va_.UseAmbient(f); - Scene::Instance().RequestRedraw(); -} - -void GfxObj::SetAmbientLocalWeight(float w) -{ - va_.AmbientLocalWeight(w); - Scene::Instance().RequestRedraw(); + if(d==sphere_detail_) return; + sphere_detail_=d; + FlagRebuild(); } -void GfxObj::SetAmbientOcclusionWeight(float w) +unsigned int GfxObj::GetSphereDetail() const { - va_.AmbientOcclusionWeight(w); - Scene::Instance().RequestRedraw(); + return sphere_detail_; } -void GfxObj::SetOpacity(float o) +void GfxObj::SetArcDetail(unsigned int d) { - opacity_=o; + if(d==arc_detail_) return; + arc_detail_=d; FlagRebuild(); } -void GfxObj::ColorBy(const mol::EntityView& ev, - const String& prop, - const Gradient& g, float minv, float maxv) +unsigned int GfxObj::GetArcDetail() const { - LOGN_VERBOSE("ColorBy not implemented for this gfx object"); + return arc_detail_; } -#if OST_IMG_ENABLED -void GfxObj::ColorBy(const img::MapHandle& mh, - const String& prop, - const Gradient& g, float minv, float maxv) +void GfxObj::SetSplineDetail(unsigned int d) { - LOGN_VERBOSE("ColorBy not implemented for this gfx object"); -} -#endif - -////////////////////////////////////////////////// -// and now for the rest of the GfxObj interface - -geom::AlignedCuboid GfxObj::GetBoundingBox() const -{ - return geom::AlignedCuboid(geom::Vec3(),geom::Vec3()); + if(d==spline_detail_) return; + spline_detail_=d; + FlagRebuild(); } -void GfxObj::ProcessLimits(geom::Vec3& minc, geom::Vec3& maxc, - const mol::Transform& tf) const +unsigned int GfxObj::GetSplineDetail() const { - try { - geom::AlignedCuboid coord_limits=this->GetBoundingBox(); - // update min/max by transforming all 8 corners of the bounding box and - // comparing it against the current min/max - geom::Vec3 mmin=coord_limits.GetMin(); - geom::Vec3 mmax=coord_limits.GetMax(); - geom::Vec3 t1=tf.Apply(geom::Vec3(mmin[0], mmin[1], mmin[2])); - geom::Vec3 t2=tf.Apply(geom::Vec3(mmin[0], mmax[1], mmin[2])); - geom::Vec3 t3=tf.Apply(geom::Vec3(mmax[0], mmax[1], mmin[2])); - geom::Vec3 t4=tf.Apply(geom::Vec3(mmax[0], mmin[1], mmin[2])); - geom::Vec3 t5=tf.Apply(geom::Vec3(mmin[0], mmin[1], mmax[2])); - geom::Vec3 t6=tf.Apply(geom::Vec3(mmin[0], mmax[1], mmax[2])); - geom::Vec3 t7=tf.Apply(geom::Vec3(mmax[0], mmax[1], mmax[2])); - geom::Vec3 t8=tf.Apply(geom::Vec3(mmax[0], mmin[1], mmax[2])); - minc = geom::Min(minc, geom::Min(t1, geom::Min(t2, geom::Min(t3, - geom::Min(t4, geom::Min(t5, geom::Min(t6, - geom::Min(t7, t8)))))))); - maxc = geom::Max(maxc, geom::Max(t1, geom::Max(t2, geom::Max(t3, - geom::Max(t4, geom::Max(t5, geom::Max(t6, - geom::Max(t7, t8)))))))); - } catch(Error& e) { - // in case the object is empty... - } + return spline_detail_; } - -void GfxObj::CustomRenderGL(RenderPass pass) {} - -void GfxObj::CustomPreRenderGL(bool flag) {} - -void GfxObj::CustomRenderPov(PovState& pov) {} - -bool GfxObj::OnSelect(const geom::Line3& l, geom::Vec3& result, - float zlim, bool pick_flag) +void GfxObj::SetPolyMode(unsigned int m) { - return false; + if(m==poly_mode_) return; + poly_mode_=std::min((unsigned int)2,m); + FlagRefresh(); } -void GfxObj::OnInput(const InputEvent& e) +unsigned int GfxObj::GetPolyMode() const { - geom::Mat3 rot=gfx::Scene::Instance().GetTransform().GetRot(); - geom::Vec3 cam_trans=gfx::Scene::Instance().GetTransform().GetTrans(); - float x=e.GetDelta()*M_PI/180.0; - bool transformed=false; - if (e.GetCommand()==INPUT_COMMAND_ROTX) { - transformed=true; - transform_.SetRot(AxisRotation(geom::Vec3(1,0,0)*rot,x)*transform_.GetRot()); - } else if(e.GetCommand()==INPUT_COMMAND_ROTY) { - transformed=true; - transform_.SetRot(AxisRotation(geom::Vec3(0,1,0)*rot,x)*transform_.GetRot()); - } else if(e.GetCommand()==INPUT_COMMAND_ROTZ) { - transformed=true; - transform_.SetRot(AxisRotation(geom::Vec3(0,0,1)*rot,x)*transform_.GetRot()); - } else if(e.GetCommand()==INPUT_COMMAND_TRANSX || - e.GetCommand()==INPUT_COMMAND_TRANSY) { - - double mm[]={1,0,0,0, - 0,1,0,0, - 0,0,1,0, - transform_.GetTrans()[0]-cam_trans[0], - transform_.GetTrans()[1]-cam_trans[1], - transform_.GetTrans()[2]-cam_trans[2], 1}; - double pm[16]; - glGetDoublev(GL_PROJECTION_MATRIX,pm); - GLint vp[4]; - glGetIntegerv(GL_VIEWPORT,vp); - double wx,wy,wz; - gluProject(0.0,0.0,0.0,mm,pm,vp,&wx,&wy,&wz); - double ox,oy,oz; - gluUnProject(wx+1.0,wy+1.0,wz,mm,pm,vp,&ox,&oy,&oz); + return poly_mode_; +} - float fx=ox; - float fy=oy; - geom::Vec3 trans=transform_.GetTrans(); - transformed=true; - if (e.GetCommand()==INPUT_COMMAND_TRANSX) { - trans+=geom::Vec3(-fx*e.GetDelta(), 0.0, 0.0)*rot; - } else { - trans+=geom::Vec3(0.0, -fy*e.GetDelta(), 0.0)*rot; - } - transform_.SetTrans(trans); - } - if (transformed) { - GfxObjP obj=dyn_cast<GfxObj>(this->shared_from_this()); - Scene::Instance().NodeTransformed(obj); - } +void GfxObj::SetAALines(bool f) +{ + if(f==aalines_flag_) return; + aalines_flag_=f; + FlagRefresh(); } -const mol::Transform& GfxObj::GetTF() const +bool GfxObj::GetAALines() const { - return transform_; + return aalines_flag_; } +void GfxObj::SetLineHalo(float f) +{ + line_halo_=f; + FlagRefresh(); +} -void GfxObj::SetTF(const mol::Transform& tf) +float GfxObj::GetLineHalo() const { - transform_=tf; + return line_halo_; } -void GfxObj::FlagRebuild() +void GfxObj::SetOutlineMode(int m) { - rebuild_=true; - Scene::Instance().RequestRedraw(); + omode_=m; + FlagRefresh(); } -void GfxObj::FlagRefresh() +void GfxObj::SetOutlineExpandFactor(float f) { - refresh_=true; - Scene::Instance().RequestRedraw(); + va_.SetOutlineExpandFactor(f); } -void GfxObj::SetNormalSmoothFactor(float smoothf) +void GfxObj::SetOutlineExpandColor(const Color& c) { - smoothf_=smoothf; - FlagRebuild(); + va_.SetOutlineExpandColor(c); } -float GfxObj::GetNormalSmoothFactor() const +void GfxObj::RenderGL(RenderPass pass) { - return smoothf_; + LOGN_TRACE("object " << GetName() << ": RenderGL()"); + + if(pass==0) { + if(mat_update_) { + LOGN_TRACE("updating material display list"); + if(mat_dlist_==0) { + mat_dlist_=glGenLists(1); + } + glNewList(mat_dlist_,GL_COMPILE); + mat_.RenderGL(); + glEndList(); + mat_update_=false; + } + + if(rebuild_ || refresh_) { + PreRenderGL(rebuild_); + rebuild_=false; + refresh_=false; + } + } + if(IsVisible()) { + LOGN_TRACE("applying local transformation"); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glMultMatrix(transform_.GetTransposedMatrix().Data()); + if(Scene::Instance().InOffscreenMode()) { + LOGN_TRACE("applying material"); + mat_.RenderGL(); + } else { + LOGN_TRACE("applying material display list"); + glCallList(mat_dlist_); + } + LOGN_TRACE("calling custom render gl pass " << pass); + + CustomRenderGL(pass); + + if(pass==0 && omode_>0) { + va_.SetOutlineMode(omode_); + CustomRenderGL(pass); + va_.SetOutlineMode(0); + } + + if(pass==1) { + LOGN_TRACE("drawing labels"); + render_labels(); + } + + glPopMatrix(); + } } -void GfxObj::OnRenderModeChange() + +void GfxObj::RenderPov(PovState& pov) { - Scene::Instance().ObjectChanged(GetName()); - Scene::Instance().RenderModeChanged(GetName()); + if(IsVisible()) { + pov.start_obj(GetName(),1.0,1.0,1.0); + // apply local transformation + // using transform_ + CustomRenderPov(pov); + pov.end_obj(); + } } void GfxObj::PreRenderGL(bool f) @@ -486,7 +446,6 @@ void GfxObj::PreRenderGL(bool f) void GfxObj::Clear() { - va_.Clear(); } Color GfxObj::Ele2Color(const String& ele) @@ -528,6 +487,90 @@ void GfxObj::ClearLabels() labels_.clear(); } +void GfxObj::SetMatAmb(const Color& c) +{ + mat_.SetAmb(c); + mat_update_=true; + Scene::Instance().RequestRedraw(); +} + +void GfxObj::SetMatAmb(float c) +{ + mat_.SetAmb(c); + mat_update_=true; + Scene::Instance().RequestRedraw(); +} + +void GfxObj::SetMatDiff(const Color& c) +{ + mat_.SetDiff(c); + mat_update_=true; + Scene::Instance().RequestRedraw(); +} + +void GfxObj::SetMatDiff(float c) +{ + mat_.SetDiff(c); + mat_update_=true; + Scene::Instance().RequestRedraw(); +} + +void GfxObj::SetMatSpec(const Color& c) +{ + mat_.SetSpec(c); + mat_update_=true; + Scene::Instance().RequestRedraw(); +} + +void GfxObj::SetMatSpec(float c) +{ + mat_.SetSpec(c); + mat_update_=true; + Scene::Instance().RequestRedraw(); +} + +void GfxObj::SetMatShin(float s) +{ + mat_.SetShin(s); + mat_update_=true; + Scene::Instance().RequestRedraw(); +} + +void GfxObj::SetMatEmm(const Color& c) +{ + mat_.SetEmm(c); + mat_update_=true; + Scene::Instance().RequestRedraw(); +} + +void GfxObj::SetMatEmm(float c) +{ + mat_.SetEmm(c); + mat_update_=true; + Scene::Instance().RequestRedraw(); +} + +void GfxObj::SetMat(const Color& amb, const Color& diff, const Color& spec, float shin) +{ + SetMatAmb(amb); + SetMatDiff(diff); + SetMatSpec(spec); + SetMatShin(shin); + SetMatEmm(0.0); + mat_update_=true; + Scene::Instance().RequestRedraw(); +} + +void GfxObj::SetMat(float amb, float diff, float spec, float shin) +{ + SetMatAmb(amb); + SetMatDiff(diff); + SetMatSpec(spec); + SetMatShin(shin); + SetMatEmm(0.0); + mat_update_=true; + Scene::Instance().RequestRedraw(); +} Material GfxObj::GetMaterial() const { @@ -551,12 +594,139 @@ void GfxObj::GLCleanup() void GfxObj::OnGLCleanup() {} +void GfxObj::SetOpacity(float o) +{ + opacity_=o; + FlagRebuild(); +} + +float GfxObj::GetOpacity() const +{ + return opacity_; +} + void GfxObj::SmoothVertices(float smoothf) { va_.SmoothVertices(smoothf); FlagRefresh(); } +void GfxObj::AmbientOcclusion(bool f) +{ + use_occlusion_=f; + va_.UseAmbient(f); + Scene::Instance().RequestRedraw(); +} + +void GfxObj::ColorBy(const mol::EntityView& ev, + const String& prop, + const Gradient& g, float minv, float maxv) +{ + LOGN_VERBOSE("ColorBy not implemented for this gfx object"); +} + + +void GfxObj::ColorBy(const mol::EntityView& ev, + const String& prop, + const Color& c1, const Color& c2, float minv, float maxv) +{ + Gradient g; + g.SetColorAt(0.0,c1); + g.SetColorAt(1.0,c2); + this->ColorBy(ev,prop,g,minv,maxv); +} + +#if OST_IMG_ENABLED +void GfxObj::ColorBy(const img::MapHandle& mh, + const String& prop, + const Gradient& g, float minv, float maxv) +{ + LOGN_VERBOSE("ColorBy not implemented for this gfx object"); +} + +void GfxObj::ColorBy(const img::MapHandle& mh, + const String& prop, + const Color& c1, const Color& c2, float minv, float maxv) +{ + Gradient g; + g.SetColorAt(0.0,c1); + g.SetColorAt(1.0,c2); + this->ColorBy(mh,prop,g,minv,maxv); +} + +void GfxObj::ColorBy(const img::MapHandle& mh, + const String& prop, + const Gradient& g) +{ + ost::img::alg::Stat stat; + mh.Apply(stat); + float min = static_cast<float>(stat.GetMinimum()); + float max = static_cast<float>(stat.GetMaximum()); + std::pair<float,float> minmax = std::make_pair(min,max); + this->ColorBy(mh,prop,g,minmax.first, minmax.second); +} + +void GfxObj::ColorBy(const img::MapHandle& mh, + const String& prop, + const Color& c1, const Color& c2) +{ + ost::img::alg::Stat stat; + mh.Apply(stat); + float min = static_cast<float>(stat.GetMinimum()); + float max = static_cast<float>(stat.GetMaximum()); + std::pair<float,float> minmax = std::make_pair(min,max); + this->ColorBy(mh,prop,c1,c2,minmax.first, minmax.second); +} + +#endif //OST_IMG_ENABLED + +void GfxObj::ColorBy(const mol::EntityHandle& eh, + const String& prop, + const Gradient& g, float minv, float maxv) +{ + this->ColorBy(eh.CreateFullView(),prop,g,minv,maxv); +} + +void GfxObj::ColorBy(const mol::EntityHandle& eh, + const String& prop, + const Color& c1, const Color& c2, float minv, float maxv) +{ + Gradient g; + g.SetColorAt(0.0,c1); + g.SetColorAt(1.0,c2); + this->ColorBy(eh,prop,g,minv,maxv); +} + +void GfxObj::ColorBy(const mol::EntityView& ev, + const String& prop, + const Gradient& g) +{ + std::pair<float,float> minmax = ev.GetMinMax(prop); + this->ColorBy(ev,prop,g,minmax.first, minmax.second); +} + +void GfxObj::ColorBy(const mol::EntityView& ev, + const String& prop, + const Color& c1, const Color& c2) +{ + std::pair<float,float> minmax = ev.GetMinMax(prop); + this->ColorBy(ev,prop,c1,c2,minmax.first, minmax.second); +} + +void GfxObj::ColorBy(const mol::EntityHandle& eh, + const String& prop, + const Gradient& g) +{ + this->ColorBy(eh.CreateFullView(),prop,g); +} + +void GfxObj::ColorBy(const mol::EntityHandle& eh, + const String& prop, + const Color& c1, const Color& c2) +{ + this->ColorBy(eh.CreateFullView(),prop,c1,c2); +} + namespace { float normalize(float v, float min_v, float max_v) @@ -591,9 +761,4 @@ void GfxObj::CleanColorOps(){ c_ops_.release(); } -void GfxObj::Debug(unsigned int flags) -{ - va_.DrawNormals(flags & 0x1); -} - }} // ns diff --git a/modules/gfx/src/gfx_object.hh b/modules/gfx/src/gfx_object.hh index 0b9322542..5a4bd4877 100644 --- a/modules/gfx/src/gfx_object.hh +++ b/modules/gfx/src/gfx_object.hh @@ -33,67 +33,58 @@ #include <ost/config.hh> #include <ost/gfx/module_config.hh> +#include <ost/gfx/color_ops/color_op.hh> + +#include <ost/geom/geom.hh> +#include <ost/mol/entity_handle.hh> +#include <ost/mol/entity_view.hh> #include <ost/mol/transform.hh> + +#if OST_IMG_ENABLED +# include <ost/img/map.hh> +#endif + #include "gfx_object_fw.hh" -#include "gfx_object_base.hh" +#include "gfx_node.hh" #include "gfx_prim.hh" #include "vertex_array.hh" #include "input.hh" +#include "render_mode.hh" +#include "material.hh" +#include "gradient.hh" + namespace ost { namespace gfx { class Scene; // fw decl -/// \brief main class for all graphic objects -class DLLEXPORT_OST_GFX GfxObj: public GfxObjBase +/// \brief Base class for all graphical rendering objects +class DLLEXPORT_OST_GFX GfxObj: public GfxNode { + public: GfxObj(const String& name); + virtual ~GfxObj(); - // gfx node interface virtual GfxNodeP Copy() const; - virtual void DeepSwap(GfxObj& go); - virtual void RenderGL(RenderPass pass); - virtual void RenderPov(PovState& pov); + virtual void Apply(GfxNodeVisitor& v,GfxNodeVisitor::Stack st); + virtual int GetType() const; - // - - // gfx obj base interface - virtual void SetMatAmb(const Color& c); - virtual void SetMatDiff(const Color& c); - virtual void SetMatSpec(const Color& c); - virtual void SetMatShin(float s); - virtual void SetMatEmm(const Color& c); - virtual void ContextSwitch(); - virtual void SetRenderMode(RenderMode::Type m); - virtual RenderMode::Type GetRenderMode() const; - virtual geom::Vec3 GetCenter() const; - virtual void SetLineWidth(float w); - virtual void SetPolyMode(unsigned int m); - virtual void AALines(bool f); - virtual void SetLineHalo(float f); - virtual void Outline(bool f); - virtual void SetOutlineMode(int m); - virtual void SetOutlineExpandFactor(float f); - virtual void SetOutlineExpandColor(const Color& c); - virtual void AmbientOcclusion(bool f); - virtual void SetAmbientLocalWeight(float w); - virtual void SetAmbientOcclusionWeight(float w); - virtual void SetOpacity(float f); - virtual void ColorBy(const mol::EntityView& ev, - const String& prop, - const Gradient& g, float minv, float maxv); -#if OST_IMG_ENABLED - virtual void ColorBy(const img::MapHandle& mh, - const String& prop, - const Gradient& g,float minv, float maxv); -#endif - // end of gfx obj base interface + virtual void RenderGL(RenderPass pass); + + virtual void RenderPov(PovState& pov); - // new gfx obj virtual interface starts here + void Clear(); + + /// \brief get transform + const mol::Transform& GetTF() const; + /// \brief set transform + void SetTF(const mol::Transform& tf); + + virtual geom::Vec3 GetCenter() const; /// \brief returns the left-bottom-front and the right-top-back corner /// that encompasses all graphical elements in this object @@ -107,10 +98,8 @@ public: virtual void ProcessLimits(geom::Vec3& minc, geom::Vec3& maxc, const mol::Transform& tf) const; - // implemented in derived classes for the actual GL rendering virtual void CustomRenderGL(RenderPass pass); - // implemented in derived classes for the actual POVray export virtual void CustomRenderPov(PovState& pov); // handle pick (select) event @@ -127,20 +116,43 @@ public: // input event entry point virtual void OnInput(const InputEvent& e); - - // informs derived class that render mode has changes + + virtual void DeepSwap(GfxObj& go); + virtual void OnRenderModeChange(); virtual void OnGLCleanup(); - // - /// \brief removes all graphical elements - void Clear(); - - /// \brief get transform - const mol::Transform& GetTF() const; - /// \brief set transform - void SetTF(const mol::Transform& tf); + /// \brief change render mode + virtual void SetRenderMode(RenderMode::Type m); + /// \brief current render mode + RenderMode::Type GetRenderMode() const; + + /// \brief set line width + void SetLineWidth(float w); + /// \brief get line width + float GetLineWidth() const; + + void SetSphereDetail(unsigned int d); + unsigned int GetSphereDetail() const; + + // subdivions per 90deg + void SetArcDetail(unsigned int d); + unsigned int GetArcDetail() const; + + void SetSplineDetail(unsigned int d); + unsigned int GetSplineDetail() const; + + void SetPolyMode(unsigned int m); + unsigned int GetPolyMode() const; + + // sophisticated line anti-aliasing, requires shader + void SetAALines(bool f); + bool GetAALines() const; + + void SetLineHalo(float f); + float GetLineHalo() const; + // add a label at the given position void AddLabel(const String& s, const geom::Vec3& pos, const Color& col, float psize); // convenience method @@ -149,38 +161,112 @@ public: void AddLabel(const String& s, const geom::Vec3& pos, float psize); // convenience method void AddLabel(const String& s, const geom::Vec3& pos); + // remove all labels void ClearLabels(); + void SetMatAmb(const Color& c); + void SetMatAmb(float c); + void SetMatDiff(const Color& c); + void SetMatDiff(float c); + void SetMatSpec(const Color& c); + void SetMatSpec(float c); + void SetMatShin(float s); + void SetMatEmm(const Color& c); + void SetMatEmm(float c); + void SetMat(const Color& amb, const Color& diff, const Color& spec, float shin); + void SetMat(float amb, float diff, float spec, float shin); + + void SetOpacity(float o); + float GetOpacity() const; + + static Color Ele2Color(const String& ele); + void FlagRebuild(); void FlagRefresh(); - bool GetAALines() const {return aalines_flag_;} - float GetLineWidth() const {return line_width_;} - float GetLineHalo() const {return line_halo_;} - float GetOpacity() const {return opacity_;} - void SetNormalSmoothFactor(float smoothf); float GetNormalSmoothFactor() const; Material GetMaterial() const; void SetMaterial(const Material& m); + void SetOutlineMode(int m); + void SetOutlineExpandFactor(float f); + void SetOutlineExpandColor(const Color& c); + // experimental, don't use void SmoothVertices(float smoothf); + // experimental, don't use + void AmbientOcclusion(bool f); void GLCleanup(); - // this really should not be here - static Color Ele2Color(const String& ele); + /// \brief color each component based on the gradient-mapped property of + /// the given entity + virtual void ColorBy(const mol::EntityView& ev, + const String& prop, + const Gradient& g, float minv, float maxv); + + /// \brief convenience method + void ColorBy(const mol::EntityView& ev, + const String& prop, + const Color& c1, const Color& c2, float minv, float maxv); + + /// \brief convenience method + void ColorBy(const mol::EntityHandle& eh, + const String& prop, + const Gradient& g, float minv, float maxv); + /// \brief convenience method + void ColorBy(const mol::EntityHandle& eh, + const String& prop, + const Color& c1, const Color& c2, float minv, float maxv); + // convenience method + void ColorBy(const mol::EntityView& ev, + const String& prop, + const Gradient& g); + // convenience method + void ColorBy(const mol::EntityView& ev, + const String& prop, + const Color& c1, const Color& c2); + // convenience method + void ColorBy(const mol::EntityHandle& ev, + const String& prop, + const Gradient& g); + // convenience method + void ColorBy(const mol::EntityHandle& ev, + const String& prop, + const Color& c1, const Color& c2); +#if OST_IMG_ENABLED + // convenience method + void ColorBy(const img::MapHandle& mh, + const String& prop, + const Gradient& g); + // convenience method + void ColorBy(const img::MapHandle& mh, + const String& prop, + const Color& c1, const Color& c2); + // dito for maps + virtual void ColorBy(const img::MapHandle& mh, + const String& prop, + const Gradient& g,float minv, float maxv); + // convenience method + void ColorBy(const img::MapHandle& mh, + const String& prop, + const Color& c1, const Color& c2, float minv, float maxv); +#endif - void Debug(unsigned int flags); + void Debug(unsigned int flags) {debug_flags_=flags; RefreshVA();} protected: void PreRenderGL(bool flag); virtual void CustomPreRenderGL(bool flag); + void RefreshVA(IndexedVertexArray& va); + + virtual void RefreshVA() {RefreshVA(va_);} + private: GfxObj(const GfxObj& o); GfxObj& operator=(const GfxObj&); @@ -189,16 +275,19 @@ public: void AppendColorOp(gfx::ColorOp* op); void CleanColorOps(); void ReapplyColorOps(); - void render_labels() const; IndexedVertexArray va_; RenderMode::Type render_mode_; unsigned int debug_flags_; + private: mol::Transform transform_; bool rebuild_; bool refresh_; float line_width_; + unsigned int sphere_detail_; + unsigned int arc_detail_; + unsigned int spline_detail_; unsigned int poly_mode_; bool aalines_flag_; float line_halo_; @@ -209,12 +298,12 @@ public: float opacity_; float smoothf_; - bool outline_flag_; - int outline_mode_; + int omode_; boost::ptr_vector<gfx::ColorOp> c_ops_; TextPrimList labels_; + void render_labels() const; bool use_occlusion_; }; diff --git a/modules/gfx/src/gfx_prim.hh b/modules/gfx/src/gfx_prim.hh index aead54653..1ec2bc25a 100644 --- a/modules/gfx/src/gfx_prim.hh +++ b/modules/gfx/src/gfx_prim.hh @@ -48,19 +48,13 @@ typedef std::vector<SpherePrim> SpherePrimList; struct CylinderPrim { CylinderPrim(): - start(),end(),radius(1.0),color1(),color2(),length(1.0),rotmat(),rotmat_t() + start(),end(),radius(1.0),color(),length(1.0),rotmat(),rotmat_t() { calc_rotmat(); } CylinderPrim(const geom::Vec3& st, const geom::Vec3& en, float rad, const Color& col): - start(st),end(en),radius(rad),color1(col),color2(col),length(geom::Length(end-start)),rotmat(),rotmat_t() - { - calc_rotmat(); - } - - CylinderPrim(const geom::Vec3& st, const geom::Vec3& en, float rad, const Color& col1, const Color& col2): - start(st),end(en),radius(rad),color1(col1),color2(col2),length(geom::Length(end-start)),rotmat(),rotmat_t() + start(st),end(en),radius(rad),color(col),length(geom::Length(end-start)),rotmat(),rotmat_t() { calc_rotmat(); } @@ -69,7 +63,7 @@ struct CylinderPrim { geom::Vec3 start,end; float radius; - Color color1, color2; + Color color; float length; geom::Mat3 rotmat; geom::Mat3 rotmat_t; diff --git a/modules/gfx/src/glwin_base.hh b/modules/gfx/src/glwin_base.hh index 996ed2ba1..69ce40525 100644 --- a/modules/gfx/src/glwin_base.hh +++ b/modules/gfx/src/glwin_base.hh @@ -33,15 +33,11 @@ class DLLEXPORT_OST_GFX GLWinBase { public: virtual ~GLWinBase() {} - virtual void MakeActive() {} - virtual void DoRefresh() = 0; virtual void StatusMessage(const String& m) = 0; virtual void SetStereo(bool s) = 0; - - virtual bool HasMultisample() const = 0; }; }} diff --git a/modules/gfx/src/impl/backbone_trace.cc b/modules/gfx/src/impl/backbone_trace.cc index fb4b714cc..c61fd23a5 100644 --- a/modules/gfx/src/impl/backbone_trace.cc +++ b/modules/gfx/src/impl/backbone_trace.cc @@ -39,7 +39,7 @@ public: { if(last_chain_ && chain!=last_chain_) { if(!list_.empty()) { - backbone_trace_->AddNodeEntryList(list_); + backbone_trace_->AddNodeList(list_); list_.clear(); } last_chain_=chain; @@ -51,15 +51,15 @@ public: { if(!mol::InSequence(last_residue_,res)) { if(!list_.empty()) { - backbone_trace_->AddNodeEntryList(list_); + backbone_trace_->AddNodeList(list_); list_.clear(); } } // determine atom to add to list mol::AtomHandle ca = res.GetCentralAtom(); if (ca) { - NodeEntry entry={ca, GfxObj::Ele2Color(ca.GetAtomProps().element), - GfxObj::Ele2Color(ca.GetAtomProps().element), + NodeEntry entry={ca, GfxObj::Ele2Color(ca.GetElement()), + GfxObj::Ele2Color(ca.GetElement()), geom::Vec3(0.0,0.0,0.0), // this will be set by the gfx trace obj res.GetCentralNormal(), 1.0, @@ -76,7 +76,7 @@ public: virtual void OnExit() { if (!list_.empty()) { - backbone_trace_->AddNodeEntryList(list_); + backbone_trace_->AddNodeList(list_); list_.clear(); } } @@ -87,19 +87,95 @@ private: NodeEntryList list_; }; -BackboneTrace::BackboneTrace() -{} - BackboneTrace::BackboneTrace(const mol::EntityView& ent) { view_=ent; - Rebuild(); + TraceBuilder trace(this); + if (view_) { + view_.Apply(trace); + } } -void BackboneTrace::ResetView(const mol::EntityView& ent) +BackboneTrace::BackboneTrace() +{ + +} + +void BackboneTrace::SetView(const mol::EntityView& ent) { view_=ent; - Rebuild(); + if (view_) { + node_list_list_.clear(); + TraceBuilder trace(this); + view_.Apply(trace); + } +} + +void BackboneTrace::AddNodeList(const NodeEntryList& l) +{ + if(l.size()>=3) { + node_list_list_.push_back(l); + // assign direction and normal vectors for each entry + // they are composed of the i-1 -> i and i->i+1 directions + // + // this same algorithm is used in the spline generation, so + // perhaps all of this here is not necessary ?! + // + NodeEntry* e0=&node_list_list_.back()[0]; + NodeEntry* e1=&node_list_list_.back()[1]; + NodeEntry* e2=&node_list_list_.back()[2]; + geom::Vec3 p0 = e0->atom.GetPos(); + geom::Vec3 p1 = e1->atom.GetPos(); + geom::Vec3 p2 = e2->atom.GetPos(); + + e0->direction=geom::Normalize(p1-p0); + // e0->normal is set afterwards to normal of second one + // backup residue normal + e0->v1 = e0->normal; + + //reference normal to avoid twisting + geom::Vec3 nref=geom::Normalize(geom::Cross(p0-p1,p2-p1)); + + // start loop with the second + unsigned int i=1; + for(;i<node_list_list_.back().size()-1;++i) { + geom::Vec3 p10 = p0-p1; + geom::Vec3 p12 = p2-p1; + if(p10==-p12 || p10==p12) p12+=geom::Vec3(0.001,0.001,0.001); + e1->v1=e1->normal; + // twist avoidance + if(geom::Dot(e0->v1,e1->v1)<0.0) { + e1->v1=-e1->v1; + } + e1->normal=geom::Normalize(geom::Cross(p10,p12)); + float omega=0.5*acos(geom::Dot(geom::Normalize(p10),geom::Normalize(p12))); + geom::Vec3 orth=geom::AxisRotation(e1->normal, -omega)*p12; + e1->direction=geom::Normalize(geom::Cross(e1->normal,orth)); + + // align normals to avoid twisting + //if(geom::Dot(e1->normal,nref)<0.0) e1->normal=-e1->normal; + //nref=e1->normal; + // skip over shift for the last iteration + if(i==node_list_list_.back().size()-2) break; + // shift to i+1 for next iteration + e0=&node_list_list_.back()[i]; + e1=&node_list_list_.back()[i+1]; + e2=&node_list_list_.back()[i+2]; + p0 = e0->atom.GetPos(); + p1 = e1->atom.GetPos(); + p2 = e2->atom.GetPos(); + } + // finish remaining values + // i is at size-2 due to break statement above + node_list_list_.back()[0].normal=node_list_list_.back()[1].normal; + node_list_list_.back()[i+1].direction=geom::Normalize(p2-p1); + node_list_list_.back()[i+1].v1=node_list_list_.back()[i+1].normal; + if (geom::Dot(node_list_list_.back()[i].v1, + node_list_list_.back()[i+1].v1)<0.0) { + node_list_list_.back()[i+1].v1=-node_list_list_.back()[i+1].v1; + } + node_list_list_.back()[i+1].normal=node_list_list_.back()[i].normal; + } } int BackboneTrace::GetListCount() const @@ -119,104 +195,97 @@ NodeEntryList& BackboneTrace::GetList(int index) void BackboneTrace::Rebuild() { - if (view_) { - node_list_list_.clear(); - TraceBuilder trace(this); - view_.Apply(trace); - } + TraceBuilder trace(this); + view_.Apply(trace); } -void BackboneTrace::AddNodeEntryList(const NodeEntryList& l) +NodeListSubset::NodeListSubset(BackboneTrace& trace, int index): + trace_(trace), list_index_(index), at_start_(0), at_end_(0) { - if(l.size()>=3) { - node_list_list_.push_back(l); - PrepList(node_list_list_.back()); - } } -void BackboneTrace::PrepList(NodeEntryList& nelist) -{ - // assign direction and normal vectors for each entry - // they are composed of the i-1 -> i and i->i+1 directions - // - // this same algorithm is used in the spline generation, so - // perhaps all of this here is not necessary ?! - // - NodeEntry* e0=&nelist[0]; - NodeEntry* e1=&nelist[1]; - NodeEntry* e2=&nelist[2]; - geom::Vec3 p0 = e0->atom.GetPos(); - geom::Vec3 p1 = e1->atom.GetPos(); - geom::Vec3 p2 = e2->atom.GetPos(); - - e0->direction=geom::Normalize(p1-p0); - // e0->normal is set afterwards to normal of second one - // backup residue normal - e0->v1 = e0->normal; - - //reference normal to avoid twisting - geom::Vec3 nref=geom::Normalize(geom::Cross(p0-p1,p2-p1)); +TraceSubset::TraceSubset(BackboneTrace& trace, + const mol::EntityView& view, int n): + trace_(trace), overshoot_(n) +{ + this->Update(view); +} + +TraceSubset::TraceSubset(BackboneTrace& trace, int n): + trace_(trace), overshoot_(n) +{ - // start loop with the second - unsigned int i=1; - for(;i<nelist.size()-1;++i) { - geom::Vec3 p10 = p0-p1; - geom::Vec3 p12 = p2-p1; - if(p10==-p12 || p10==p12) p12+=geom::Vec3(0.001,0.001,0.001); - e1->v1=e1->normal; - // twist avoidance - if(geom::Dot(e0->v1,e1->v1)<0.0) { - e1->v1=-e1->v1; +} + + +void TraceSubset::NodeListEnd(NodeListSubset& nl, int c, int s) +{ + if (nl.GetSize()>0) { + int n=std::min(s-(nl.indices_.back()+1), overshoot_); + nl.at_end_=n; + while (n>0) { + nl.indices_.push_back(nl.indices_.back()+1); + --n; } - e1->normal=geom::Normalize(geom::Cross(p10,p12)); - float omega=0.5*acos(geom::Dot(geom::Normalize(p10),geom::Normalize(p12))); - geom::Vec3 orth=geom::AxisRotation(e1->normal, -omega)*p12; - e1->direction=geom::Normalize(geom::Cross(e1->normal,orth)); - - // align normals to avoid twisting - //if(geom::Dot(e1->normal,nref)<0.0) e1->normal=-e1->normal; - //nref=e1->normal; - // skip over shift for the last iteration - if(i==nelist.size()-2) break; - // shift to i+1 for next iteration - e0=&nelist[i]; - e1=&nelist[i+1]; - e2=&nelist[i+2]; - p0 = e0->atom.GetPos(); - p1 = e1->atom.GetPos(); - p2 = e2->atom.GetPos(); } - // finish remaining values - // i is at size-2 due to break statement above - nelist[0].normal=nelist[1].normal; - nelist[i+1].direction=geom::Normalize(p2-p1); - nelist[i+1].v1=nelist[i+1].normal; - if (geom::Dot(nelist[i].v1, - nelist[i+1].v1)<0.0) { - nelist[i+1].v1=-nelist[i+1].v1; +} + +void TraceSubset::NodeListStart(NodeListSubset& nl, int c) +{ + if (nl.GetSize()==0 && c>0) { + for (int i=std::max(0,c-overshoot_); i<c; ++i) { + nl.indices_.push_back(i); + } + nl.at_start_=nl.indices_.size(); } - nelist[i+1].normal=nelist[i].normal; } -BackboneTrace BackboneTrace::CreateSubset(const mol::EntityView& subview) + +void TraceSubset::Update(const mol::EntityView& view) { - BackboneTrace nrvo; - nrvo.view_=subview; - nrvo.node_list_list_.clear(); - for(NodeEntryListList::const_iterator nitnit=node_list_list_.begin();nitnit!=node_list_list_.end();++nitnit) { - NodeEntryList new_nlist; - const NodeEntryList& nlist=*nitnit; - for(NodeEntryList::const_iterator nit=nlist.begin();nit!=nlist.end();++nit) { - if(subview.FindAtom(nit->atom).IsValid()) { - new_nlist.push_back(*nit); + + lists_.clear(); + if (!view.IsValid()) { + return; + } + for (int i=0; i<trace_.GetListCount(); ++i) { + const NodeEntryList& l=trace_.GetList(i); + int c=0; + NodeEntryList::const_iterator j=l.begin(),e=l.end(); + NodeListSubset curr(trace_, i); + while (j!=e) { + while (j!=e && view.FindAtom(j->atom)) { + if (curr.indices_.empty()) { + this->NodeListStart(curr, c); + } + curr.indices_.push_back(c); + ++j; ++c; + } + if (curr.GetSize()) { + this->NodeListEnd(curr, curr.indices_.back(), l.size()); + lists_.push_back(curr); + curr=NodeListSubset(trace_, i); + } else { + ++c; ++j; } - } - if(!new_nlist.empty()) { - nrvo.node_list_list_.push_back(new_nlist); } } - return nrvo; } -}}} // ns +NodeListSubset& NodeListSubset::operator=(const NodeListSubset& rhs) +{ + trace_=rhs.trace_; + list_index_=rhs.list_index_; + indices_=rhs.indices_; + return *this; +} + +TraceSubset& TraceSubset::operator=(const TraceSubset& rhs) +{ + trace_=rhs.trace_; + lists_=rhs.lists_; + overshoot_=rhs.overshoot_; + return *this; +} +}}} diff --git a/modules/gfx/src/impl/backbone_trace.hh b/modules/gfx/src/impl/backbone_trace.hh index debcc54b5..c6663f12c 100644 --- a/modules/gfx/src/impl/backbone_trace.hh +++ b/modules/gfx/src/impl/backbone_trace.hh @@ -40,41 +40,99 @@ class BackboneTraceBuilder; class DLLEXPORT_OST_GFX BackboneTrace { public: - // empty trace - BackboneTrace(); - - // initialize with a view, and build BackboneTrace(const mol::EntityView& ent); - - // number of node-lists + BackboneTrace(); + int GetListCount() const; - - // grab a list + const NodeEntryList& GetList(int index) const; - // grab a list NodeEntryList& GetList(int index); - - // reset the view and rebuild - void ResetView(const mol::EntityView& ent); - - // used internally - adds a finished nodelist - void AddNodeEntryList(const NodeEntryList& entries); - // used internally - calculates some derived values for a nodelist - static void PrepList(NodeEntryList& nelist); - - // re-creates internal nodelist-list based on view - void Rebuild(); + void SetView(const mol::EntityView& ent); + + // used internally + void AddNodeList(const NodeEntryList& entries); - // extract portions of this backbone trace for a subview - // this is faster then re-generating a trace - BackboneTrace CreateSubset(const mol::EntityView& subview); + void Rebuild(); private: mol::EntityView view_; NodeEntryListList node_list_list_; }; +/// \internal +/// \brief a subset of a node list +class DLLEXPORT_OST_GFX NodeListSubset { +public: + friend class TraceSubset; + + NodeListSubset(BackboneTrace& trace, int index); + + int GetSize() const + { + return indices_.size(); + } + int AtStart() const + { + return at_start_; + } + + int AtEnd() const + { + return at_end_; + } + const NodeEntry& operator [](int index) const + { + assert(index>=0 && index<static_cast<int>(indices_.size())); + return trace_.GetList(list_index_)[indices_[index]]; + } + NodeEntry& operator [](int index) + { + assert(index>=0 && index<static_cast<int>(indices_.size())); + return trace_.GetList(list_index_)[indices_[index]]; + } + NodeListSubset& operator=(const NodeListSubset& rhs); +private: + BackboneTrace& trace_; + int list_index_; +protected: + std::vector<int> indices_; + int at_start_; + int at_end_; +}; + +/// \brief a subset of the trace +class DLLEXPORT_OST_GFX TraceSubset { +public: + TraceSubset(BackboneTrace& trace, const mol::EntityView& view, int n); + TraceSubset(BackboneTrace& trace, int n); + + const NodeListSubset& operator[](int index) const + { + return lists_[index]; + } + + NodeListSubset& operator[](int index) + { + return lists_[index]; + } + + int GetSize() const + { + return lists_.size(); + } + void SetOvershoot(int n) { overshoot_=n; } + int GetOvershoot() const { return overshoot_; } + TraceSubset& operator=(const TraceSubset& rhs); + void Update(const mol::EntityView& view); +private: + void NodeListStart(NodeListSubset& nl, int c); + void NodeListEnd(NodeListSubset& nl, int c, int s); + BackboneTrace& trace_; + std::vector<NodeListSubset> lists_; + int overshoot_; +}; + }}} #endif diff --git a/modules/gfx/src/impl/cartoon_renderer.cc b/modules/gfx/src/impl/cartoon_renderer.cc index f4a52b7ee..08f0a0c3e 100644 --- a/modules/gfx/src/impl/cartoon_renderer.cc +++ b/modules/gfx/src/impl/cartoon_renderer.cc @@ -16,17 +16,8 @@ // along with this library; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //------------------------------------------------------------------------------ - -/* - Author: Ansgar Philippsen -*/ - #include "cartoon_renderer.hh" -#include <Eigen/Core> -#include <Eigen/Array> -#include <Eigen/SVD> -#include <Eigen/LU> #include <ost/gfx/entity.hh> #include <ost/gfx/impl/tabulated_trig.hh> @@ -39,11 +30,16 @@ static const unsigned int MAX_ARC_DETAIL=12; using namespace impl; -CartoonRenderer::CartoonRenderer(BackboneTrace* trace, bool force_tube): +CartoonRenderer::CartoonRenderer(BackboneTrace& trace, bool force_tube): TraceRendererBase(trace, 3), force_tube_(force_tube), options_(new CartoonRenderOptions(force_tube)) { - this->SetName(force_tube ? "Smooth Tube" : "Helix & Strand Cartoon"); +if(force_tube){ + this->SetName("Smooth Tube"); +} +else{ + this->SetName("Helix & Strand Cartoon"); +} } void CartoonRenderer::SetForceTube(bool force_tube) @@ -51,14 +47,13 @@ void CartoonRenderer::SetForceTube(bool force_tube) force_tube_ = force_tube; } -void CartoonRenderer::PrepareRendering(const BackboneTrace& subset, +void CartoonRenderer::PrepareRendering(TraceSubset& subset, IndexedVertexArray& va, SplineEntryListList& spline_list_list, bool is_sel) { int spline_detail=std::max((unsigned int) 1, options_->GetSplineDetail()); const Color& sel_clr=this->GetSelectionColor(); - SplineEntryListList tmp_sll; if(options_!=NULL){ va.Clear(); va.SetLighting(true); @@ -66,43 +61,45 @@ void CartoonRenderer::PrepareRendering(const BackboneTrace& subset, va.SetColorMaterial(true); va.SetMode(0x4); va.SetPolyMode(options_->GetPolyMode()); - for (int node_list=0; node_list<subset.GetListCount(); ++node_list) { + spline_list_list.clear(); + for (int node_list=0; node_list<subset.GetSize(); ++node_list) { // first build the spline - SplineEntryList spl; - const NodeEntryList& nl=subset.GetList(node_list); - for (unsigned int i=0; i<nl.size();++i) { + Spline spl; + const NodeListSubset& nl=subset[node_list]; + for (int i=0; i<nl.GetSize();++i) { int type=0; const NodeEntry& entry=nl[i]; if(!force_tube_) { mol::ResidueHandle resh = entry.atom.GetResidue(); mol::SecStructure sst=resh.GetSecStructure(); + mol::ResidueHandle resh2 = resh.GetNext(); + mol::SecStructure sst2=mol::SecStructure(mol::SecStructure::COIL); + if (resh2.IsValid()) { + sst2=resh2.GetSecStructure(); + } if(sst.IsHelical()) { type=1; } else if(sst.IsExtended()) { - type=2; + if(!sst2.IsExtended()) { + type=3; // end of strand + } else { + type=2; + } } } - SplineEntry ee(entry.atom.GetPos(),entry.direction, - entry.normal, entry.rad, - is_sel ? sel_clr : entry.color1, - is_sel ? sel_clr : entry.color2, type); + SplineEntry& ee = spl.AddEntry(entry.atom.GetPos(),entry.direction, + entry.normal, entry.rad, + is_sel ? sel_clr : entry.color1, + is_sel ? sel_clr : entry.color2, type); ee.v1 = entry.v1; - spl.push_back(ee); - } - if(!spl.empty()) { - tmp_sll.push_back(spl); } + spline_list_list.push_back(spl.Generate(spline_detail)); + // now create the shape around the interpolated pathway } - FudgeSplineObj(va,tmp_sll); - spline_list_list.clear(); - for(SplineEntryListList::const_iterator sit=tmp_sll.begin();sit!=tmp_sll.end();++sit) { - spline_list_list.push_back(Spline::Generate(*sit,spline_detail)); - } - RebuildSplineObj(va, spline_list_list, is_sel); - //va.SmoothNormals(options_->GetNormalSmoothFactor()); + RebuildSplineObj(spline_list_list.back(), va, spline_list_list, subset, is_sel); + va.SmoothNormals(options_->GetNormalSmoothFactor()); } } - void CartoonRenderer::PrepareRendering() { TraceRendererBase::PrepareRendering(); @@ -117,6 +114,8 @@ void CartoonRenderer::PrepareRendering() state_=0; } +void CartoonRenderer::Render(){} + bool CartoonRenderer::CanSetOptions(RenderOptionsPtr& render_options) { return render_options.get()->GetRenderMode()==RenderMode::HSC; @@ -132,258 +131,95 @@ RenderOptionsPtr CartoonRenderer::GetOptions() return options_; } -namespace { - typedef Eigen::Matrix<Real,3,1> EVec3; - typedef Eigen::Matrix<Real,3,3> EMat3; - typedef Eigen::Matrix<Real,1,3> ERVec3; - typedef Eigen::Matrix<Real,Eigen::Dynamic,Eigen::Dynamic> EMatX; - typedef Eigen::Matrix<Real,1,Eigen::Dynamic> ERVecX; - - ERVec3 to_eigen(const geom::Vec3& v) - { - EVec3 nrvo=EVec3::Zero(); - nrvo[0]=v[0]; nrvo[1]=v[1]; nrvo[2]=v[2]; - return nrvo; - } - - std::pair<geom::Vec3,geom::Vec3> fit_helix(const std::vector<geom::Vec3>& points) - { - if(points.size()<4) { - return std::make_pair(points.front(),points.back()); - } - geom::Vec3 cen(0.0,0.0,0.0); - for(unsigned int i=0;i<points.size();++i) cen+=points[i]; - cen/=static_cast<float>(points.size()); - - EMatX A=EMatX::Zero(points.size(),3); - for(unsigned int i=0;i<points.size();++i) { - A.row(i)=to_eigen(points[i]-cen); - } - - Eigen::SVD<EMatX> svd(A); - EMatX V=svd.matrixV(); - geom::Vec3 ax(V(0,0),V(1,0),V(2,0)); - - geom::Vec3 p1=cen+ax*(-geom::Dot(cen,ax)+geom::Dot(points.front(),ax))/geom::Length2(ax); - geom::Vec3 p2=cen+ax*(-geom::Dot(cen,ax)+geom::Dot(points.back(),ax))/geom::Length2(ax); - - return std::make_pair(p1,p2); - } - -} // ns - -void CartoonRenderer::FudgeSplineObj(IndexedVertexArray& va, SplineEntryListList& olistlist) -{ - SplineEntryListList nlistlist; - SplineEntryList nlist; - - for(unsigned int llc=0;llc<olistlist.size();++llc) { - SplineEntryList olist = olistlist[llc]; - for(unsigned int lc=0;lc<olist.size();++lc) { - if(olist.at(lc).type==1 && options_->GetHelixMode()==1) { - if(options_->GetHelixMode()==1) { - // cylindrical helix - // collect all CA positions - std::vector<geom::Vec3> points; - SplineEntry tmp_end(olist.at(lc)); - unsigned int lstart=lc; - for(;lc<olist.size() && olist.at(lc).type==1;++lc) { - points.push_back(olist.at(lc).position); - } - unsigned int lend=lc-1; - if(lend-lstart<3) { - // this is a short helix, may as well not bother - for(unsigned int i=lstart;i<=lend;++i) { - nlist.push_back(olist[i]); - nlist.back().type=0; - } - } else { - // fit points to a cylinder - std::pair<geom::Vec3,geom::Vec3> cyl=fit_helix(points); - - // extend the current spline to start of cyl - geom::Vec3 cyl_dir = geom::Normalize(cyl.second-cyl.first); - - if(lstart>0) { - SplineEntry tmp_end(olist[lstart]); - tmp_end.type=0; - tmp_end.position=cyl.first; - tmp_end.direction=cyl_dir; - tmp_end.color1=olist[lstart-1].color1; - tmp_end.color2=olist[lstart-1].color2; - tmp_end.normal=geom::Normalize(geom::Cross(cyl_dir,geom::Cross(tmp_end.normal,cyl_dir))); - if(geom::Dot(tmp_end.normal,olist[lstart].normal)<0.0) { - tmp_end.normal=-tmp_end.normal; - } - nlist.push_back(tmp_end); - - // break nodelist - nlistlist.push_back(nlist); - nlist.clear(); - } - - if(lend+1<olist.size()) { - // and get going with an entry at the end of the cylinder - SplineEntry tmp_start(olist[lend]); - tmp_start.type=0; - tmp_start.position=cyl.second; - tmp_start.direction=cyl_dir; - tmp_start.color1=olist[lend+1].color1; - tmp_start.color2=olist[lend+1].color2; - tmp_start.normal=geom::Normalize(geom::Cross(cyl_dir,geom::Cross(tmp_start.normal,cyl_dir))); - if(geom::Dot(tmp_start.normal,olist[lstart].normal)<0.0) { - tmp_start.normal=-tmp_start.normal; - } - nlist.push_back(tmp_start); - } - - // and finally make the cylinder - va.AddCylinder(CylinderPrim(cyl.first,cyl.second, - options_->GetHelixWidth(), - olist[lstart].color1, - olist[lend].color1), - options_->GetArcDetail(),true); - } - } else { // helix mode 0 - // just copy them over - for(;lc<olist.size() && olist.at(lc).type==1;++lc) { - nlist.push_back(olist.at(lc)); - } - } - } else if(olist.at(lc).type==2) { - // strand - unsigned int kstart=nlist.size(); - unsigned int kend=kstart; - for(;lc<olist.size() && olist.at(lc).type==2;++lc,++kend) { - nlist.push_back(olist.at(lc)); - } - kend-=1; - nlist[kend].type=3; // mark end of strand - - if(options_->GetStrandMode()==1 && kend>kstart) { - nlist[kend-1].type=3; - nlist[kend].type=5; - // smooth the strands - nlist[kstart].direction = geom::Normalize(nlist[kend].position-nlist[kstart].position); - nlist[kend].direction=nlist[kstart].direction; - float invf=1.0/static_cast<float>(kend-kstart); - for(unsigned int k=kstart;k<=kend;++k) { - float f = static_cast<float>(k-kstart)*invf; - nlist[k].position=nlist[kstart].position+f*(nlist[kend].position-nlist[kstart].position); - nlist[k].direction=nlist[kstart].direction; - geom::Vec3 tmpn=geom::Normalize(nlist[kstart].normal+f*(nlist[kend].normal-nlist[kstart].normal)); - geom::Vec3 tmpx=geom::Normalize(geom::Cross(nlist[kstart].direction,tmpn)); - nlist[k].normal=geom::Normalize(geom::Cross(tmpx,nlist[kstart].direction)); - } - // break nodelist, re-start at arrow tip - if(lc+1<olist.size()) { - nlistlist.push_back(nlist); - nlist.clear(); - nlist.push_back(nlistlist.back().back()); - nlist.back().type=0; - nlist.back().color1=olist[lc+1].color1; - nlist.back().color2=olist[lc+1].color2; - } - } - } - if(lc<olist.size()) { - nlist.push_back(olist.at(lc)); - } - } - if(!nlist.empty()) { - nlistlist.push_back(nlist); - nlist.clear(); - } - } - olistlist.swap(nlistlist); -} - -void CartoonRenderer::RebuildSplineObj(IndexedVertexArray& va, - const SplineEntryListList& spline_list_list, - bool is_sel) +void CartoonRenderer::RebuildSplineObj(const SplineEntryList& l, + IndexedVertexArray& va, + SplineEntryListList& spline_list_list, + const TraceSubset& subset, bool is_sel) { unsigned int detail = std::min(MAX_ARC_DETAIL, std::max(options_->GetArcDetail(), (unsigned int)1)); + int spline_detail=std::max((unsigned int) 1, options_->GetSplineDetail()); std::vector<TraceProfile> profiles; float factor=is_sel ? 0.2 : 0.0; profiles.push_back(GetCircProfile(detail, options_->GetTubeRadius()*options_->GetTubeRatio()+factor, options_->GetTubeRadius()+factor, options_->GetTubeProfileType(), - 1.0)); // profile 0 = tube + 1.0)); // tube if (!force_tube_) { profiles.push_back(GetCircProfile(detail, options_->GetHelixWidth()+factor, options_->GetHelixThickness()+factor, options_->GetHelixProfileType(), - options_->GetHelixEcc())); // profile 1 = helix + options_->GetHelixEcc())); // helix profiles.push_back(GetCircProfile(detail, options_->GetStrandWidth()+factor, options_->GetStrandThickness()+factor, options_->GetStrandProfileType(), - options_->GetStrandEcc())); // profile 2 = strand - profiles.push_back(profiles.back()); // profile 3==2, strand - + options_->GetStrandEcc())); // strand profiles.push_back(GetCircProfile(detail, - 1.7*options_->GetStrandWidth()+factor, - 1.1*options_->GetStrandThickness()+factor, - options_->GetStrandProfileType(), - options_->GetStrandEcc())); // profile 4 = arrow start + 0.1*options_->GetStrandWidth()+factor, + options_->GetStrandThickness()+factor, + options_->GetTubeProfileType(), + 1.0)); // arrow end, tube profile profiles.push_back(GetCircProfile(detail, - 0.01*options_->GetStrandWidth()+factor, + 1.7*options_->GetStrandWidth()+factor, 1.1*options_->GetStrandThickness()+factor, options_->GetStrandProfileType(), - options_->GetStrandEcc())); // profile 5 = arrow end - + options_->GetStrandEcc())); // arrow start } // iterate over all spline segments - for(SplineEntryListList::const_iterator it=spline_list_list.begin(); + for(SplineEntryListList::iterator it=spline_list_list.begin(); it<spline_list_list.end();++it) { /* for each spline segment, transform the profile according to the normal and direction and assemble it together with the last transformed profile into a graphical segment */ - SplineEntryList slist=*it; - if(slist.empty()) continue; - TraceProfile tprof1=TransformAndAddProfile(profiles,slist[0],va); - CapProfile(tprof1,slist[0],true,va); + SplineEntryList& slist=*it; + const NodeListSubset& nl=subset[it-spline_list_list.begin()]; + int sit=0, send=slist.size()-spline_detail+1; + if (nl.AtStart()>0) { + sit+=nl.AtStart()*spline_detail-spline_detail/2; + } + if (nl.AtEnd()>0) { + send-=nl.AtEnd()*spline_detail-spline_detail/2; + } + TraceProfile tprof1=TransformAndAddProfile(profiles,slist[sit],va); + CapProfile(tprof1,slist[sit],true,va); TraceProfile tprof2; - unsigned int sc=1; - for (; sc<slist.size(); ++sc) { - if(slist.at(sc).type==3) { - if(slist.at(sc-1).type==2) { - // boundary to arrow - SplineEntry se(slist[sc]); - tprof2=TransformAndAddProfile(profiles,se, va); - AssembleProfile(tprof1,tprof2,va); - tprof1=tprof2; - se.type=2; - se.type1=4; - se.type2=4; - tprof2=TransformAndAddProfile(profiles,se, va); - } else { - SplineEntry se(slist.at(sc)); - se.type1=4; - if(options_->GetStrandMode()==1) se.type2=5; - tprof2=TransformAndAddProfile(profiles,se, va); - } + SplineEntry& last_se=slist[send-1]; + for (int sc=sit+1; sc<send; ++sc) { + if(slist[sc-1].type==2 && slist[sc].type==3) { + // arrow on last strand segment + // type1 is already set to 4 (Spline::Generate), + // hence just insert single bridging profile + SplineEntry se(slist[sc]); + se.type=last_se.type; + se.type1=last_se.type1; + se.type2=last_se.type2; + tprof2=TransformAndAddProfile(profiles,se, va); + AssembleProfile(tprof1,tprof2,va); + tprof1=tprof2; + tprof2=TransformAndAddProfile(profiles,slist[sc], va); + last_se=slist[sc]; } else { - tprof2=TransformAndAddProfile(profiles,slist.at(sc), va); + tprof2=TransformAndAddProfile(profiles,slist[sc], va); } AssembleProfile(tprof1,tprof2,va); tprof1=tprof2; + last_se=slist[sc]; } - CapProfile(tprof1,slist.at(sc-1),false,va); + CapProfile(tprof1,slist[send-1],false,va); } } + + TraceProfile CartoonRenderer::TransformAndAddProfile(const std::vector<TraceProfile>& profiles, const SplineEntry& se, IndexedVertexArray& va) { - assert(se.type1>=0 && se.type1<=5); - assert(se.type2>=0 && se.type2<=5); TraceProfile prof1 = profiles[se.type1]; TraceProfile prof2 = profiles[se.type2]; diff --git a/modules/gfx/src/impl/cartoon_renderer.hh b/modules/gfx/src/impl/cartoon_renderer.hh index d8a98f761..ff9097e5c 100644 --- a/modules/gfx/src/impl/cartoon_renderer.hh +++ b/modules/gfx/src/impl/cartoon_renderer.hh @@ -16,11 +16,6 @@ // along with this library; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //------------------------------------------------------------------------------ - -/* - Author: Ansgar Philippsen -*/ - #ifndef OST_GFX_CARTOON_RENDERER_HH #define OST_GFX_CARTOON_RENDERER_HH @@ -39,26 +34,25 @@ namespace ost { namespace gfx { namespace impl { /// \internal class DLLEXPORT_OST_GFX CartoonRenderer: public TraceRendererBase { public: - CartoonRenderer(BackboneTrace* trace, bool force_tube=false); - virtual ~CartoonRenderer(); + CartoonRenderer(BackboneTrace& trace, bool force_tube=false); virtual void PrepareRendering(); + virtual void Render(); virtual bool CanSetOptions(RenderOptionsPtr& render_options); virtual void SetOptions(RenderOptionsPtr& render_options); virtual RenderOptionsPtr GetOptions(); + virtual void SetForceTube(bool force_tube); - -private: - void PrepareRendering(const BackboneTrace& subset, IndexedVertexArray& va, - SplineEntryListList& spline_list_list, bool is_sel); - void FudgeSplineObj(IndexedVertexArray&, SplineEntryListList&); - void RebuildSplineObj(IndexedVertexArray& va, - const SplineEntryListList& spline_list_list, - bool is_sel); + virtual ~CartoonRenderer(); + +private: + void RebuildSplineObj(const SplineEntryList& l, IndexedVertexArray& va, + SplineEntryListList& spline_list_list, + const TraceSubset& subset, bool is_sel); void CapProfile(const impl::TraceProfile& p, const impl::SplineEntry& se, @@ -72,6 +66,9 @@ private: const SplineEntry& se, IndexedVertexArray& va); + void PrepareRendering(TraceSubset& subset, IndexedVertexArray& va, + SplineEntryListList& spline_list_list, bool is_sel); + TraceProfile GetCircProfile(unsigned int detail, float rx, float ry, unsigned int type, float ecc); bool force_tube_; diff --git a/modules/gfx/src/impl/debug_renderer.cc b/modules/gfx/src/impl/debug_renderer.cc index c77dca568..918117400 100644 --- a/modules/gfx/src/impl/debug_renderer.cc +++ b/modules/gfx/src/impl/debug_renderer.cc @@ -33,7 +33,7 @@ namespace gfx { using namespace impl; using namespace mol; -DebugRenderer::DebugRenderer(BackboneTrace* trace): +DebugRenderer::DebugRenderer(BackboneTrace& trace): TraceRendererBase(trace, 2), options_(new SlineRenderOptions()) { this->SetName("Debug"); } @@ -51,7 +51,7 @@ void DebugRenderer::PrepareRendering() for(NodeEntryListList::const_iterator ll_it=node_list_list_->begin();ll_it!=node_list_list_->end();++ll_it) { - SplineEntryList spl; + Spline spl; for(NodeEntryList::const_iterator it=(*ll_it).begin();it!=(*ll_it).end();++it) { int type=0; ResidueHandle resh = it->atom.GetResidue(); @@ -62,13 +62,12 @@ void DebugRenderer::PrepareRendering() type=2; } - SplineEntry ee(it->atom.GetPos(),it->direction,it->normal, - it->rad,it->color1,it->color2,type); + SplineEntry& ee = spl.AddEntry(it->atom.GetPos(),it->direction,it->normal, + it->rad,it->color1,it->color2,type); ee.v1 = it->v1; - spl.push_back(ee); } - SplineEntryList sel = Spline::Generate(spl,std::max((unsigned int) 1,options_->GetSplineDetail())); + SplineEntryList sel = spl.Generate(std::max((unsigned int) 1,options_->GetSplineDetail())); SplineEntryList::const_iterator sit = sel.begin(); geom::Vec3 ap = sit->position; diff --git a/modules/gfx/src/impl/debug_renderer.hh b/modules/gfx/src/impl/debug_renderer.hh index 3a2b6e79a..206f592dd 100644 --- a/modules/gfx/src/impl/debug_renderer.hh +++ b/modules/gfx/src/impl/debug_renderer.hh @@ -30,7 +30,7 @@ namespace ost { namespace gfx { namespace impl { class DLLEXPORT_OST_GFX DebugRenderer: public TraceRendererBase { public: - DebugRenderer(BackboneTrace* trace); + DebugRenderer(BackboneTrace& trace); virtual void PrepareRendering(); virtual void Render(); diff --git a/modules/gfx/src/impl/entity_detail.cc b/modules/gfx/src/impl/entity_detail.cc index 4d2857b4b..ccc160078 100644 --- a/modules/gfx/src/impl/entity_detail.cc +++ b/modules/gfx/src/impl/entity_detail.cc @@ -87,41 +87,85 @@ void GfxView::AddBond(const BondHandle& b) } +void SplineEntry::ToQuat() +{ + // assert orthonormal system + // TODO: this seems broken + geom::Vec3 dir = geom::Normalize(direction); + geom::Vec3 norm0 = geom::Normalize(normal); + geom::Vec3 norm2 = geom::Cross(dir,norm0); + geom::Vec3 norm1 = geom::Cross(norm2,dir); + geom::Mat3 rmat(dir[0],norm1[0],norm2[0], + dir[1],norm1[1],norm2[1], + dir[2],norm1[2],norm2[2]); + + geom::Quat quat(rmat); + quat_value[0]=quat.w; + quat_value[1]=quat.x; + quat_value[2]=quat.y; + quat_value[3]=quat.z; +} + +void SplineEntry::FromQuat() +{ + /* + assert orthornormal system since direction was + probably adjusted for curvature + */ + // TODO: this seems broken + geom::Quat quat(quat_value[0],quat_value[1],quat_value[2],quat_value[3]); + geom::Mat3 rmat = quat.ToRotationMatrix(); + geom::Vec3 norm0 = geom::Normalize(geom::Vec3(rmat(0,1),rmat(1,1),rmat(2,1))); + geom::Vec3 dir = geom::Normalize(direction); + geom::Vec3 norm2 = geom::Normalize(geom::Cross(dir,norm0)); + normal = geom::Normalize(geom::Cross(norm2,dir)); +} + //////////////////////////// +Spline::Spline(): + entry_list_() +{} + + +SplineEntry& Spline::AddEntry(const geom::Vec3& pos, const geom::Vec3& dir, const geom::Vec3& normal, float rad, const Color& c1, const Color& c2, int type) +{ + entry_list_.push_back(SplineEntry(pos, + geom::Normalize(dir), + geom::Normalize(normal), + rad,c1,c2,type)); + entry_list_.back().ToQuat(); + return entry_list_.back(); +} + static int bsplineGen(float *x,float *y, int n, float yp1, float ypn, float *y2); static int bsplineGet(float *xa, float *ya, float *y2a, int n, float x, float *y); #define SPLINE_ENTRY_INTERPOLATE(COMPONENT) \ for(int c=0;c<size;++c) { \ - yc[c]=entry_list.at(c). COMPONENT ; \ + yc[c]=entry_list_[c]. COMPONENT ; \ } \ bsplineGen(xp,yp,size,1.0e30,1.0e30,y2p); \ - for(int c=0;c<size-1;++c) { \ + for(int c=0;c<size;++c) { \ for(int d=0;d<nsub;++d) { \ float u=static_cast<float>(c*nsub+d)*i_nsub; \ float v=0.0; \ bsplineGet(xp,yp,y2p,size,u,&v); \ - sublist.at(c*nsub+d). COMPONENT = v; \ + sublist[c*nsub+d]. COMPONENT = v; \ } \ - float u=static_cast<float>((size-1)*nsub)*i_nsub; \ - float v=0.0; \ - bsplineGet(xp,yp,y2p,size,u,&v); \ - sublist.at((size-1)*nsub). COMPONENT = v; \ } -SplineEntryList Spline::Generate(const SplineEntryList& entry_list, int nsub) +SplineEntryList Spline::Generate(int nsub) const { if(nsub<=0) { - return entry_list; + return entry_list_; } - int size=entry_list.size(); - if (size<2) { - return entry_list; + int size=entry_list_.size(); + if (size==0) { + return entry_list_; } - // we want to go to the last point, but not beyond - int ipsize=(size-1)*nsub+1; + int ipsize=(size)*nsub; float i_nsub=1.0/static_cast<float>(nsub); std::vector<float> xc(size); std::vector<float> yc(size); @@ -140,8 +184,9 @@ SplineEntryList Spline::Generate(const SplineEntryList& entry_list, int nsub) // create sublist with enough entries SplineEntryList sublist(ipsize); - // interpolate color + // interpolate internal quaternion and color for(int k=0;k<4;++k) { + SPLINE_ENTRY_INTERPOLATE(quat_value[k]); SPLINE_ENTRY_INTERPOLATE(color1[k]); SPLINE_ENTRY_INTERPOLATE(color2[k]); } @@ -158,14 +203,14 @@ SplineEntryList Spline::Generate(const SplineEntryList& entry_list, int nsub) // assign direction and normal // entity trace has the same algorithm - geom::Vec3 p0 = sublist.at(0).position; - geom::Vec3 p1 = sublist.at(1).position; - geom::Vec3 p2 = ipsize>2 ? sublist.at(2).position : p1+(p1-p0); + geom::Vec3 p0 = sublist[0].position; + geom::Vec3 p1 = sublist[1].position; + geom::Vec3 p2 = sublist[2].position; // normal of 0 is set at the end - sublist.at(0).direction=geom::Normalize(p1-p0); - sublist.at(0).v1=geom::Normalize(sublist.at(0).v1); - geom::Vec3 orth = geom::Cross(sublist.at(0).direction,sublist.at(0).v1); - sublist.at(0).v0 = geom::Normalize(geom::Cross(orth,sublist.at(0).direction)); + sublist[0].direction=geom::Normalize(p1-p0); + sublist[0].v1=geom::Normalize(sublist[0].v1); + geom::Vec3 orth = geom::Cross(sublist[0].direction,sublist[0].v1); + sublist[0].v0 = geom::Normalize(geom::Cross(orth,sublist[0].direction)); // reference normal to avoid twisting //geom::Vec3 nref=geom::Normalize(geom::Cross(p0-p1,p2-p1)); @@ -175,83 +220,88 @@ SplineEntryList Spline::Generate(const SplineEntryList& entry_list, int nsub) geom::Vec3 p12 = p2-p1; // correction for perfectly aligned consecutive directions if(p10==-p12 || p10==p12) p12+=geom::Vec3(0.001,0.001,0.001); - sublist.at(i).normal=geom::Normalize(geom::Cross(p10,p12)); + sublist[i].normal=geom::Normalize(geom::Cross(p10,p12)); // paranoid error checking due to occasional roundoff troubles float cosw = geom::Dot(geom::Normalize(p10),geom::Normalize(p12)); cosw = std::min(float(1.0),std::max(float(-1.0),cosw)); float omega=0.5*acos(cosw); - orth=geom::AxisRotation(sublist.at(i).normal, -omega)*p12; - sublist.at(i).direction=geom::Normalize(geom::Cross(sublist.at(i).normal,orth)); + orth=geom::AxisRotation(sublist[i].normal, -omega)*p12; + sublist[i].direction=geom::Normalize(geom::Cross(sublist[i].normal,orth)); // twist avoidance - sublist.at(i).v1=geom::Normalize(sublist.at(i).v1); - orth = geom::Cross(sublist.at(i).direction,sublist.at(i).v1); - sublist.at(i).v0 = geom::Normalize(geom::Cross(orth,sublist.at(i).direction)); - if(geom::Dot(sublist.at(i-1).v0,sublist.at(i).v0)<0.0) { - sublist.at(i).v0=-sublist.at(i).v0; - //sublist.at(i).nflip = !sublist.at(i).nflip; + sublist[i].v1=geom::Normalize(sublist[i].v1); + orth = geom::Cross(sublist[i].direction,sublist[i].v1); + sublist[i].v0 = geom::Normalize(geom::Cross(orth,sublist[i].direction)); + if(geom::Dot(sublist[i-1].v0,sublist[i].v0)<0.0) { + sublist[i].v0=-sublist[i].v0; + //sublist[i].nflip = !sublist[i].nflip; } // avoid twisting - //if(geom::Dot(sublist.at(i).normal,nref)<0.0) sublist.at(i).normal=-sublist.at(i).normal; - //nref=sublist.at(i).normal; + //if(geom::Dot(sublist[i].normal,nref)<0.0) sublist[i].normal=-sublist[i].normal; + //nref=sublist[i].normal; // skip over shift for the last iteration if(i==sublist.size()-2) break; // shift to i+1 for next iteration - p0 = sublist.at(i).position; - p1 = sublist.at(i+1).position; - p2 = sublist.at(i+2).position; + p0 = sublist[i].position; + p1 = sublist[i+1].position; + p2 = sublist[i+2].position; } // assign remaining ones - sublist.at(0).normal=sublist.at(1).normal; - sublist.at(i+1).direction=geom::Normalize(p2-p1); - sublist.at(i+1).normal=sublist.at(i).normal; - sublist.at(i+1).v1=geom::Normalize(sublist.at(i+1).v1); - orth = geom::Cross(sublist.at(i+1).direction,sublist.at(i+1).v1); - sublist.at(i+1).v0 = geom::Normalize(geom::Cross(orth,sublist.at(i+1).direction)); + sublist[0].normal=sublist[1].normal; + sublist[i+1].direction=geom::Normalize(p2-p1); + sublist[i+1].normal=sublist[i].normal; + sublist[i+1].v1=geom::Normalize(sublist[i+1].v1); + orth = geom::Cross(sublist[i+1].direction,sublist[i+1].v1); + sublist[i+1].v0 = geom::Normalize(geom::Cross(orth,sublist[i+1].direction)); // hack // TODO: merge this with above routine for(unsigned int i=0;i<sublist.size()-1;++i) { - sublist.at(i).normal = sublist.at(i).v0; + sublist[i].normal = sublist[i].v0; } // finally the non-interpolated type // with some tweaks for proper strand rendering - for(int c=0;c<size-1;++c) { - int type1=entry_list[c].type; - int type2=entry_list[std::min(c+1,size-1)].type; + for(int c=0;c<size;++c) { for(int d=0;d<nsub;++d) { - sublist.at(c*nsub+d).type=entry_list[c].type; - sublist.at(c*nsub+d).type1=type1; - sublist.at(c*nsub+d).type2=type2; - sublist.at(c*nsub+d).frac=float(d)/float(nsub); + sublist[c*nsub+d].type=entry_list_[c].type; + int type1=entry_list_[c].type; + int type2=entry_list_[std::min(c+1,size-1)].type; + //int type0=entry_list_[std::max(0,c-1)].type; + if(type1==2 && type2==3) { + type1=2; + type2=2; + } else if(type1==3) { + type1=4; + // uncommenting this causes the strand arrows + // to blend into a tip instead of the n+1 + // profile - gives visual artefacts + //type2=3; + } + sublist[c*nsub+d].type1=type1; + sublist[c*nsub+d].type2=type2; + sublist[c*nsub+d].frac=float(d)/float(nsub); } } - int type1=entry_list.back().type; - int type2=type1; - sublist.back().type=entry_list.back().type; - sublist.back().type1=type1; - sublist.back().type2=type2; - sublist.back().frac=0.0; // the nflip flags for helices for correct inside/outside assignment int c=0; bool nflip=false; - while(c<nsub*(size-1)) { + while(c<nsub*size-1) { int cstart=c; - if(sublist.at(c).type==1 && sublist.at(c+1).type==1) { - geom::Vec3 n = geom::Normalize(geom::Cross(sublist.at(c).normal, - sublist.at(c).direction)); - geom::Vec3 p0 = sublist.at(c).position+n; - geom::Vec3 q0 = sublist.at(c).position-n; + if(sublist[c].type==1 && sublist[c+1].type==1) { + geom::Vec3 n = geom::Normalize(geom::Cross(sublist[c].normal, + sublist[c].direction)); + geom::Vec3 p0 = sublist[c].position+n; + geom::Vec3 q0 = sublist[c].position-n; float psum=0.0; float qsum=0.0; ++c; - while(sublist.at(c).type==1 && c<nsub*size) { - n = geom::Normalize(geom::Cross(sublist.at(c).normal, - sublist.at(c).direction)); - geom::Vec3 p1 = sublist.at(c).position+n; - geom::Vec3 q1 = sublist.at(c).position-n; + while(sublist[c].type==1 && c<nsub*size) { + n = geom::Normalize(geom::Cross(sublist[c].normal, + sublist[c].direction)); + geom::Vec3 p1 = sublist[c].position+n; + geom::Vec3 q1 = sublist[c].position-n; psum+=Length(p1-p0); qsum+=Length(q1-q0); p0=p1; @@ -261,7 +311,7 @@ SplineEntryList Spline::Generate(const SplineEntryList& entry_list, int nsub) nflip = qsum>psum; for(int cc=cstart;cc<c;++cc) { - sublist.at(c).nflip=nflip; + sublist[cc].nflip=nflip; } } else { ++c; diff --git a/modules/gfx/src/impl/entity_detail.hh b/modules/gfx/src/impl/entity_detail.hh index a077d2d54..7cf19d622 100644 --- a/modules/gfx/src/impl/entity_detail.hh +++ b/modules/gfx/src/impl/entity_detail.hh @@ -115,14 +115,7 @@ struct DLLEXPORT_OST_GFX SplineEntry { color1(1.0,1.0,1.0,1.0), color2(1.0,1.0,1.0,1.0), rad(1.0), - type(0), - type1(0), - type2(0), - frac(0.0), - v0(1.0,0.0,0.0), - v1(0.0,1.0,0.0), - v2(0.0,0.0,1.0), - nflip(false) + type(0) { } SplineEntry(const geom::Vec3& p, @@ -130,17 +123,22 @@ struct DLLEXPORT_OST_GFX SplineEntry { const geom::Vec3& n, float r, const Color& c1, const Color& c2, - unsigned int t): + int t): position(p),direction(d),normal(n),color1(c1),color2(c2),rad(r),type(t), type1(t),type2(t),frac(0.0),v0(),v1(),v2(),nflip(false) { } + void ToQuat(); + + void FromQuat(); + geom::Vec3 position,direction,normal; Color color1, color2; + float quat_value[4]; float rad; - unsigned int type; - unsigned int type1, type2; + int type; + int type1, type2; float frac; geom::Vec3 v0,v1,v2; // helper vectors bool nflip; @@ -151,7 +149,20 @@ typedef std::vector<SplineEntryList> SplineEntryListList; class DLLEXPORT_OST_GFX Spline { public: - static SplineEntryList Generate(const SplineEntryList& entry_list,int nsub); + +public: + // ctor + Spline(); + + // add entry at a given position, with direction and normal vectors + SplineEntry& AddEntry(const geom::Vec3& pos, const geom::Vec3& dir, + const geom::Vec3& normal, float r, const Color& col1, + const Color& col2, int type); + + SplineEntryList Generate(int nsub) const; + +private: + SplineEntryList entry_list_; }; }}} // ns diff --git a/modules/gfx/src/impl/entity_renderer.hh b/modules/gfx/src/impl/entity_renderer.hh index 4d90f97e0..28a932abf 100644 --- a/modules/gfx/src/impl/entity_renderer.hh +++ b/modules/gfx/src/impl/entity_renderer.hh @@ -24,8 +24,8 @@ */ -#if defined(GetAtomProps) -#undef GetAtomProps +#if defined(GetProp) +#undef GetProp #endif #include <vector> @@ -160,8 +160,6 @@ public: void FlagPositionsDirty(); void Debug(unsigned int flags); - - IndexedVertexArray& VA() {return va_;} protected: virtual void SetName(const String& name); @@ -180,13 +178,12 @@ protected: DirtyFlags sel_state_; DirtyFlags state_; unsigned int debug_flags_; - float opacity_; }; //Simplify color ops struct ByElementGetCol { Color ColorOfAtom(mol::AtomHandle& atom) const{ - return GfxObj::Ele2Color(atom.GetElement()); + return GfxObj::Ele2Color(atom.GetAtomProps().element); } }; diff --git a/modules/gfx/src/impl/line_trace_renderer.cc b/modules/gfx/src/impl/line_trace_renderer.cc index 45e2b63fa..b0279b71f 100644 --- a/modules/gfx/src/impl/line_trace_renderer.cc +++ b/modules/gfx/src/impl/line_trace_renderer.cc @@ -17,16 +17,12 @@ // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //------------------------------------------------------------------------------ -/* - Authors: Marco Biasini, Ansgar Philippsen -*/ - #include "line_trace_renderer.hh" #include <ost/gfx/entity.hh> namespace ost { namespace gfx { namespace impl { -LineTraceRenderer::LineTraceRenderer(BackboneTrace* trace): +LineTraceRenderer::LineTraceRenderer(BackboneTrace& trace): TraceRendererBase(trace, 1), options_(new LineTraceRenderOptions()) { this->SetName("Fast Trace"); @@ -45,9 +41,10 @@ void LineTraceRenderer::PrepareRendering() } } -void LineTraceRenderer::PrepareRendering(const BackboneTrace& trace_subset, +void LineTraceRenderer::PrepareRendering(TraceSubset& trace_subset, IndexedVertexArray& va, bool is_sel) { + const Color& sel_clr=this->GetSelectionColor(); if(options_!=NULL){ va.Clear(); @@ -59,27 +56,54 @@ void LineTraceRenderer::PrepareRendering(const BackboneTrace& trace_subset, va.SetLineWidth(options_->GetLineWidth()); va.SetPointSize(options_->GetLineWidth()); va.SetAALines(options_->GetAALines()); - for (int node_list=0; node_list<trace_subset.GetListCount(); ++node_list) { - const NodeEntryList& nl=trace_subset.GetList(node_list); - - if (nl.size()<2) { - continue; + for (int node_list=0; node_list<trace_subset.GetSize(); ++node_list) { + const NodeListSubset& nl=trace_subset[node_list]; + + if (nl.GetSize()==2) { + VertexID p0, p1; + if (nl.AtStart()==0) { + p0=va.Add(nl[0].atom.GetPos(), geom::Vec3(), + is_sel ? sel_clr : nl[0].color1); + p1=va.Add((nl[0].atom.GetPos()+nl[1].atom.GetPos())/2, + geom::Vec3(), is_sel ? sel_clr : nl[1].color1); + } else { + p0=va.Add((nl[0].atom.GetPos()+nl[1].atom.GetPos())/2, + geom::Vec3(), is_sel ? sel_clr : nl[0].color1); + p1=va.Add(nl[1].atom.GetPos(), + geom::Vec3(), is_sel ? sel_clr : nl[1].color1); + } + va.AddLine(p0, p1); + continue; } - - VertexID p0=va.Add(nl[0].atom.GetPos(), geom::Vec3(), - is_sel ? sel_clr : nl[0].color1); - - for (unsigned int i=1; i<nl.size()-1;++i) { + if (nl.GetSize()<3) { + continue; + } + VertexID p0; + if (nl.AtStart()==0) { + p0=va.Add(nl[0].atom.GetPos(), geom::Vec3(), + is_sel ? sel_clr : nl[0].color1); + } else { + p0=va.Add((nl[0].atom.GetPos()+nl[1].atom.GetPos())/2, + geom::Vec3(), is_sel ? sel_clr : nl[0].color1); + } + for (int i=1; i<nl.GetSize()-1;++i) { const NodeEntry& entry=nl[i]; VertexID p1 =va.Add(entry.atom.GetPos(), geom::Vec3(), is_sel ? sel_clr : entry.color1); va.AddLine(p0, p1); p0=p1; } - const NodeEntry& entry=nl.back(); - VertexID p1 =va.Add(entry.atom.GetPos(), geom::Vec3(), - is_sel ? sel_clr : entry.color1); - va.AddLine(p0, p1); + const NodeEntry& entry=nl[nl.GetSize()-1]; + if (nl.AtEnd()==0) { + VertexID p1 =va.Add(entry.atom.GetPos(), geom::Vec3(), + is_sel ? sel_clr : entry.color1); + va.AddLine(p0, p1); + } else { + geom::Vec3 p=(entry.atom.GetPos()+nl[nl.GetSize()-2].atom.GetPos())*0.5; + VertexID p1 =va.Add(p, geom::Vec3(), + is_sel ? sel_clr : entry.color1); + va.AddLine(p0, p1); + } } } sel_state_=0; @@ -88,6 +112,7 @@ void LineTraceRenderer::PrepareRendering(const BackboneTrace& trace_subset, void LineTraceRenderer::Render() { + } bool LineTraceRenderer::CanSetOptions(RenderOptionsPtr& render_options) diff --git a/modules/gfx/src/impl/line_trace_renderer.hh b/modules/gfx/src/impl/line_trace_renderer.hh index fc2a2ad87..d4b904e0f 100644 --- a/modules/gfx/src/impl/line_trace_renderer.hh +++ b/modules/gfx/src/impl/line_trace_renderer.hh @@ -16,11 +16,6 @@ // along with this library; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //------------------------------------------------------------------------------ - -/* - Authors: Marco Biasini, Ansgar Philippsen -*/ - #ifndef OST_GFX_IMPL_LINE_TRACE_RENDERER_HH #define OST_GFX_IMPL_LINE_TRACE_RENDERER_HH @@ -41,10 +36,10 @@ using namespace impl; /// \internal class DLLEXPORT_OST_GFX LineTraceRenderer: public TraceRendererBase { public: - LineTraceRenderer(BackboneTrace* trace); + LineTraceRenderer(BackboneTrace& trace); virtual void PrepareRendering(); - virtual void PrepareRendering(const BackboneTrace& trace_subset, + virtual void PrepareRendering(TraceSubset& trace_subset, IndexedVertexArray& va, bool is_sel); virtual void Render(); diff --git a/modules/gfx/src/impl/sline_renderer.cc b/modules/gfx/src/impl/sline_renderer.cc index 7ae7f937a..6d1fe022d 100644 --- a/modules/gfx/src/impl/sline_renderer.cc +++ b/modules/gfx/src/impl/sline_renderer.cc @@ -16,18 +16,13 @@ // along with this library; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //------------------------------------------------------------------------------ - -/* - Authors: Marco Biasini, Ansgar Philippsen -*/ - #include "sline_renderer.hh" #include <ost/gfx/entity.hh> namespace ost { namespace gfx { namespace impl { -SlineRenderer::SlineRenderer(BackboneTrace* trace): +SlineRenderer::SlineRenderer(BackboneTrace& trace): TraceRendererBase(trace, 3), options_(new SlineRenderOptions()) { this->SetName("Fast Spline"); @@ -45,7 +40,7 @@ void SlineRenderer::PrepareRendering() } } -void SlineRenderer::PrepareRendering(const BackboneTrace& trace_subset, +void SlineRenderer::PrepareRendering(TraceSubset& trace_subset, IndexedVertexArray& va, bool is_sel) { const Color& sel_clr=this->GetSelectionColor(); @@ -61,24 +56,30 @@ void SlineRenderer::PrepareRendering(const BackboneTrace& trace_subset, va.SetLineWidth(options_->GetLineWidth()); va.SetPointSize(options_->GetLineWidth()); va.SetAALines(options_->GetAALines()); - for (int node_list=0; node_list<trace_subset.GetListCount(); ++node_list) { + for (int node_list=0; node_list<trace_subset.GetSize(); ++node_list) { // first build the spline - SplineEntryList spl; - const NodeEntryList& nl=trace_subset.GetList(node_list); - if(nl.empty()) continue; - for (unsigned int i=0; i<nl.size();++i) { + Spline spl; + const NodeListSubset& nl=trace_subset[node_list]; + assert(nl.GetSize() && "node list subset with zero eles encountered!"); + for (int i=0; i<nl.GetSize();++i) { const NodeEntry& entry=nl[i]; - SplineEntry ee(entry.atom.GetPos(), entry.direction, - entry.normal, entry.rad, - is_sel ? sel_clr : entry.color1, - is_sel ? sel_clr : entry.color2, 0); + SplineEntry& ee = spl.AddEntry(entry.atom.GetPos(), entry.direction, + entry.normal, entry.rad, + is_sel ? sel_clr : entry.color1, + is_sel ? sel_clr : entry.color2, 0); ee.v1 = entry.v1; - spl.push_back(ee); } - SplineEntryList sel = Spline::Generate(spl,spline_detail); - SplineEntryList::const_iterator sit=sel.begin(); + SplineEntryList sel = spl.Generate(spline_detail); + SplineEntryList::const_iterator sit=sel.begin(), + send=sel.end()-spline_detail+1; + if (nl.AtStart()>0) { + sit+=nl.AtStart()*spline_detail-spline_detail/2; + } + if (nl.AtEnd()>0) { + send-=nl.AtEnd()*spline_detail-spline_detail/2; + } VertexID p0=va.Add(sit->position, geom::Vec3(),sit->color1); - for (++sit; sit!=sel.end(); ++sit) { + for (++sit; sit<send; ++sit) { VertexID p1 = va.Add(sit->position, geom::Vec3(),sit->color1); va.AddLine(p0,p1); p0=p1; diff --git a/modules/gfx/src/impl/sline_renderer.hh b/modules/gfx/src/impl/sline_renderer.hh index 4c08ba3b0..b264fc4b6 100644 --- a/modules/gfx/src/impl/sline_renderer.hh +++ b/modules/gfx/src/impl/sline_renderer.hh @@ -16,11 +16,6 @@ // along with this library; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //------------------------------------------------------------------------------ - -/* - Authors: Marco Biasini, Ansgar Philippsen -*/ - #ifndef OST_GFX_SLINE_RENDERER_HH #define OST_GFX_SLINE_RENDERER_HH @@ -37,7 +32,7 @@ namespace ost { namespace gfx { namespace impl { /// \internal class DLLEXPORT_OST_GFX SlineRenderer: public TraceRendererBase { public: - SlineRenderer(BackboneTrace* trace); + SlineRenderer(BackboneTrace& trace); virtual void PrepareRendering(); @@ -48,7 +43,7 @@ public: virtual ~SlineRenderer(); private: - void PrepareRendering(const BackboneTrace& subset, IndexedVertexArray& va, + void PrepareRendering(TraceSubset& subset, IndexedVertexArray& va, bool is_sel); SlineRenderOptionsPtr options_; }; diff --git a/modules/gfx/src/impl/trace_renderer.cc b/modules/gfx/src/impl/trace_renderer.cc index eacf3f0a9..29691cc1d 100644 --- a/modules/gfx/src/impl/trace_renderer.cc +++ b/modules/gfx/src/impl/trace_renderer.cc @@ -17,10 +17,6 @@ // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //------------------------------------------------------------------------------ -/* - Authors: Marco Biasini, Ansgar Philippsen -*/ - #include <ost/gfx/entity.hh> #include <ost/gfx/povray.hh> @@ -29,7 +25,7 @@ namespace ost { namespace gfx { namespace impl { -TraceRenderer::TraceRenderer(BackboneTrace* trace): +TraceRenderer::TraceRenderer(BackboneTrace& trace): TraceRendererBase(trace, 1), options_(new TraceRenderOptions()) { this->SetName("Trace"); @@ -47,7 +43,8 @@ void TraceRenderer::PrepareRendering() } } -void TraceRenderer::PrepareRendering(BackboneTrace& trace_subset, +#if 1 +void TraceRenderer::PrepareRendering(TraceSubset& trace_subset, IndexedVertexArray& va, bool is_sel) { float plus=is_sel ? 0.05: 0.0; @@ -58,14 +55,14 @@ void TraceRenderer::PrepareRendering(BackboneTrace& trace_subset, va.SetCullFace(true); va.SetColorMaterial(true); va.SetTwoSided(false); - for (int node_list=0; node_list<trace_subset.GetListCount(); ++node_list) { - const NodeEntryList& nl=trace_subset.GetList(node_list); + for (int node_list=0; node_list<trace_subset.GetSize(); ++node_list) { + const NodeListSubset& nl=trace_subset[node_list]; mol::AtomHandle a1=nl[0].atom; va.AddSphere(SpherePrim(a1.GetPos(), options_->GetTubeRadius()+plus, is_sel ? sel_clr : nl[0].color1), options_->GetArcDetail()); - for(unsigned int i=1;i<nl.size();++i) { + for(int i=1;i<nl.GetSize();++i) { mol::AtomHandle a2=nl[i].atom; va.AddSphere(SpherePrim(a2.GetPos(), options_->GetTubeRadius()+plus, @@ -86,18 +83,169 @@ void TraceRenderer::PrepareRendering(BackboneTrace& trace_subset, state_=0; } +#else + +void TraceRenderer::PrepareRendering(TraceSubset& trace_subset, + IndexedVertexArray& va, bool is_sel) +{ + const Color& sel_clr=this->GetSelectionColor(); + float radius=options_->GetTubeRadius(); + if (is_sel) { + radius+=0.1; + } + int n=8*options_->GetArcDetail(); + if(options_!=NULL) { + va.SetLighting(true); + va.SetCullFace(false); + for (int node_list=0; node_list<trace_subset.GetSize(); ++node_list) { + const NodeListSubset& nl=trace_subset[node_list]; + geom::Vec3 cursor_pos; + geom::Mat3 cursor_ori; + if (nl.GetSize()==2) { + VertexID p0, p1; + if (nl.AtStart()==0) { + p0=va.Add(nl[0].atom.GetPos(), geom::Vec3(), + is_sel ? sel_clr : nl[0].color1); + p1=va.Add((nl[0].atom.GetPos()+nl[1].atom.GetPos())/2, + geom::Vec3(), is_sel ? sel_clr : nl[1].color1); + } else { + p0=va.Add((nl[0].atom.GetPos()+nl[1].atom.GetPos())/2, + geom::Vec3(), is_sel ? sel_clr : nl[0].color1); + p1=va.Add(nl[1].atom.GetPos(), + geom::Vec3(), is_sel ? sel_clr : nl[1].color1); + } + va.AddLine(p0, p1); + continue; + } + if (nl.GetSize()<3) { + continue; + } + VertexID p0; + geom::Vec3 z=geom::Normalize(nl[1].atom.GetPos()-nl[0].atom.GetPos()); + geom::Vec3 y=geom::OrthogonalVector(z); + geom::Vec3 x=geom::Cross(y, z); + cursor_ori=geom::Mat3(x[0], y[0], z[0], x[1], y[1], z[1], + x[2], y[2], z[2]); + if (nl.AtStart()==0) { + cursor_pos=nl[0].atom.GetPos(); + } else { + cursor_pos=(nl[0].atom.GetPos()+nl[1].atom.GetPos())/2; + } + p0=this->AddCappedProfile(va, is_sel? sel_clr : nl[0].color1, + cursor_pos, cursor_ori, radius, true, n); + for (int i=1; i<nl.GetSize()-1;++i) { + const NodeEntry& entry=nl[i]; + geom::Vec3 old_dir=geom::Normalize(entry.atom.GetPos()-cursor_pos); + cursor_pos=entry.atom.GetPos(); + + geom::Vec3 z=geom::Normalize(nl[i+1].atom.GetPos()-cursor_pos); + geom::Vec3 y=geom::Normalize(geom::Cross(z, cursor_ori.GetCol(0))); + geom::Vec3 x=geom::Normalize(geom::Cross(y, z)); + geom::Vec3 iz=geom::Normalize(cursor_ori.GetCol(2)+z); + + geom::Vec3 iy=geom::Normalize(geom::Cross(cursor_ori.GetCol(2), z)); + geom::Vec3 ix=geom::Normalize(geom::Cross(iy, iz)); + + geom::Mat3 i_ori=geom::Mat3(ix[0], iy[0], iz[0], ix[1], iy[1], iz[1], + ix[2], iy[2], iz[2]); + cursor_ori=geom::Mat3(x[0], y[0], z[0], x[1], y[1], z[1], + x[2], y[2], z[2]); + // TODO. The intersection of two cylinders is an ellipse. Use an + // elliptic profile instead of a circular profile. + VertexID p1=this->AddCircularProfile(va, is_sel ? sel_clr : entry.color1, + cursor_pos, i_ori, radius, n); + this->ConnectProfiles(p0, p1, n, old_dir, va); + p0=p1; + } + const NodeEntry& entry=nl[nl.GetSize()-1]; + if (nl.AtEnd()==0) { + cursor_pos=entry.atom.GetPos(); + } else { + cursor_pos=(entry.atom.GetPos()+nl[nl.GetSize()-2].atom.GetPos())*0.5; + } + VertexID p1 =this->AddCappedProfile(va, is_sel ? sel_clr : entry.color1, + cursor_pos, cursor_ori, + radius, false, n); + this->ConnectProfiles(p0, p1, n, cursor_ori.GetCol(2), va); + } + } + sel_state_=0; + state_=0; +} +#endif + +VertexID TraceRenderer::AddCappedProfile(IndexedVertexArray& va, + const Color& color, + const geom::Vec3& center, + const geom::Mat3& ori, float radius, + bool flip_normal, + int n) +{ + VertexID center_id=va.Add(center, geom::Vec3(), color); + VertexID first=this->AddCircularProfile(va, color, center, ori, radius, n); + for (int i=0; i<n; ++i) { + va.AddTriN(center_id, first+i, first+((i+1) % n)); + } + return first; +} + +VertexID TraceRenderer::AddCircularProfile(IndexedVertexArray& va, + const Color& color, + const geom::Vec3& center, + const geom::Mat3& ori, + float radius, + int n) +{ + float delta_angle=2*M_PI/n; + VertexID f=0; + geom::Vec3 normal=ori.GetRow(2); + for (int i=0; i<n; ++i) { + geom::Vec3 normal=ori*geom::Vec3(cos(i*delta_angle), + sin(i*delta_angle), 0.0); + VertexID x=va.Add(center+normal*radius, normal, color); + if (i==0) { + f=x; + } + } + return f; +} + +void TraceRenderer::ConnectProfiles(VertexID prof0, VertexID prof1, int n, + const geom::Vec3& dir, + IndexedVertexArray& va) +{ + // avoid twisting + int off=0; + float best=0.0; + geom::Vec3 pp=va.GetVert(prof0); + for (int i=0; i<n; ++i) { + geom::Vec3 dir2=geom::Normalize(va.GetVert(prof1+i)-pp); + float dot=fabs(geom::Dot(dir, dir2)); + if (best<dot) { + best=dot; + off=i; + } + } + for (int i=0; i<n; ++i) { + VertexID i1=prof1+((i+off) % n), i2=prof1+((i+off+1) % n); + VertexID i3=prof0+i, i4=prof0+((i+1)%n); + va.AddTriN(i1, i2, i3); + va.AddTriN(i2, i3, i4); + } +} + void TraceRenderer::RenderPov(PovState& pov, const std::string& name) { pov.write_merge_or_union(name); - for (int node_list=0; node_list<trace_subset_.GetListCount(); ++node_list) { - const NodeEntryList& nl=trace_subset_.GetList(node_list); + for (int node_list=0; node_list<trace_subset_.GetSize(); ++node_list) { + const NodeListSubset& nl=trace_subset_[node_list]; geom::Vec3 p0=nl[0].atom.GetPos(); float rad0=0.2; Color col0=nl[0].color1; pov.write_sphere(p0,rad0,col0,name); - for (unsigned int i=1; i<nl.size();++i) { + for (int i=1; i<nl.GetSize();++i) { geom::Vec3 p1=nl[i].atom.GetPos(); float rad1=0.2; Color col1=nl[i].color1; @@ -114,6 +262,11 @@ void TraceRenderer::RenderPov(PovState& pov, const std::string& name) pov.inc() << " }\n"; } +void TraceRenderer::Render() +{ + +} + bool TraceRenderer::CanSetOptions(RenderOptionsPtr& render_options) { return render_options.get()->GetRenderMode()==RenderMode::TRACE; diff --git a/modules/gfx/src/impl/trace_renderer.hh b/modules/gfx/src/impl/trace_renderer.hh index e8f9cff3b..77cb8d3da 100644 --- a/modules/gfx/src/impl/trace_renderer.hh +++ b/modules/gfx/src/impl/trace_renderer.hh @@ -20,9 +20,8 @@ #define OST_GFX_IMPL_TRACE_RENDERER_HH /* - Authors: Marco Biasini, Ansgar Philippsen -*/ - + Author: Marco Biasini + */ #include <ost/gfx/impl/backbone_trace.hh> #include <ost/gfx/impl/entity_detail.hh> #include <ost/gfx/impl/trace_renderer_base.hh> @@ -38,12 +37,12 @@ using namespace impl; /// \internal class DLLEXPORT_OST_GFX TraceRenderer: public TraceRendererBase { public: - TraceRenderer(BackboneTrace* trace); + TraceRenderer(BackboneTrace& trace); virtual void PrepareRendering(); - virtual void PrepareRendering(BackboneTrace& trace_subset, + virtual void PrepareRendering(TraceSubset& trace_subset, IndexedVertexArray& va, bool is_sel); - + virtual void Render(); virtual void RenderPov(PovState& pov, const std::string& name); virtual bool CanSetOptions(RenderOptionsPtr& render_options); @@ -52,6 +51,14 @@ public: virtual ~TraceRenderer(); private: + VertexID AddCappedProfile(IndexedVertexArray& va, const Color& color, + const geom::Vec3& center, const geom::Mat3& ori, + float radius, bool flip_normal, int n); + VertexID AddCircularProfile(IndexedVertexArray& va, const Color& color, + const geom::Vec3& center, const geom::Mat3& ori, + float radius, int n); + void ConnectProfiles(VertexID prof1, VertexID prof2, int n, + const geom::Vec3& dir, IndexedVertexArray& va); TraceRenderOptionsPtr options_; }; diff --git a/modules/gfx/src/impl/trace_renderer_base.cc b/modules/gfx/src/impl/trace_renderer_base.cc index 9231e929c..46084a880 100644 --- a/modules/gfx/src/impl/trace_renderer_base.cc +++ b/modules/gfx/src/impl/trace_renderer_base.cc @@ -17,10 +17,6 @@ // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //------------------------------------------------------------------------------ -/* - Authors: Marco Biasini, Ansgar Philippsen -*/ - #include <ost/gfx/scene.hh> #include "trace_renderer_base.hh" @@ -38,15 +34,15 @@ void set_node_entry_color(NodeEntry& e, ColorMask mask, } template <typename T1> -inline void apply_color_op(TraceRendererBase* rend, BackboneTrace& trace_subset, T1 get_col, const ColorOp& op) +inline void apply_color_op(TraceRendererBase* rend, TraceSubset& trace_subset, T1 get_col, const ColorOp& op) { rend->UpdateViews(); ColorMask mask = op.GetMask(); if(op.IsSelectionOnly()){ mol::Query q(op.GetSelection()); - for (int node_list=0; node_list<trace_subset.GetListCount(); ++node_list) { - NodeEntryList& nl=trace_subset.GetList(node_list); - for (unsigned int i=0; i<nl.size();++i) { + for (int node_list=0; node_list<trace_subset.GetSize(); ++node_list) { + NodeListSubset& nl=trace_subset[node_list]; + for (int i=0; i<nl.GetSize();++i) { if (q.IsAtomSelected(nl[i].atom)) { Color clr =get_col.ColorOfAtom(nl[i].atom); set_node_entry_color(nl[i],mask,clr); @@ -56,9 +52,9 @@ inline void apply_color_op(TraceRendererBase* rend, BackboneTrace& trace_subset, } else{ mol::EntityView view = op.GetView(); - for (int node_list=0; node_list<trace_subset.GetListCount(); ++node_list) { - NodeEntryList& nl=trace_subset.GetList(node_list); - for (unsigned int i=0; i<nl.size();++i) { + for (int node_list=0; node_list<trace_subset.GetSize(); ++node_list) { + NodeListSubset& nl=trace_subset[node_list]; + for (int i=0; i<nl.GetSize();++i) { if(view.FindAtom(nl[i].atom)){ Color clr =get_col.ColorOfAtom(nl[i].atom); set_node_entry_color(nl[i],mask,clr); @@ -71,8 +67,8 @@ inline void apply_color_op(TraceRendererBase* rend, BackboneTrace& trace_subset, } //ns -TraceRendererBase::TraceRendererBase(BackboneTrace* trace, int n): - trace_(trace), trace_subset_(*trace), sel_subset_() +TraceRendererBase::TraceRendererBase(BackboneTrace& trace, int n): + trace_(trace), trace_subset_(trace, n), sel_subset_(trace, n) { } @@ -84,37 +80,44 @@ void TraceRendererBase::UpdateViews() { if (state_ & DIRTY_VIEW) { mol::EntityView view=this->GetEffectiveView(); - trace_subset_=trace_->CreateSubset(view); + trace_subset_.Update(view); state_&=~DIRTY_VIEW; } if (this->HasSelection() && (sel_state_ & DIRTY_VIEW)) { - sel_subset_ = trace_->CreateSubset(sel_); + sel_subset_.Update(sel_); sel_state_&=~DIRTY_VIEW; } } geom::AlignedCuboid TraceRendererBase::GetBoundingBox() const { - geom::Vec3 mmin(std::numeric_limits<float>::max(), - std::numeric_limits<float>::max(), - std::numeric_limits<float>::max()); - geom::Vec3 mmax(-std::numeric_limits<float>::max(), - -std::numeric_limits<float>::max(), - -std::numeric_limits<float>::max()); - + geom::Vec3 mmin, mmax; assert(!(state_ & DIRTY_VIEW)); - for (int node_list=0; node_list<trace_subset_.GetListCount(); ++node_list) { - const NodeEntryList& nl=trace_subset_.GetList(node_list); - for (unsigned int i=0; i<nl.size();++i) { + bool empty=true; + for (int node_list=0; node_list<trace_subset_.GetSize(); ++node_list) { + // first build the spline + Spline spl; + const NodeListSubset& nl=trace_subset_[node_list]; + for (int i=0; i<nl.GetSize();++i) { const NodeEntry& entry=nl[i]; + empty=false; geom::Vec3 p=entry.atom.GetPos(); - mmin=geom::Min(mmin, p); - mmax=geom::Max(mmax, p); + if (node_list+i==0) { + mmin=p; + mmax=p; + } else { + mmin=geom::Min(mmin, p); + mmax=geom::Max(mmax, p); + } } } + if (empty) { + throw Error("Can't calculate bounding box of empty renderer"); + } return geom::AlignedCuboid(mmin, mmax); } + void TraceRendererBase::Apply(const gfx::ByElementColorOp& op) { apply_color_op(this,trace_subset_,ByElementGetCol(),op); @@ -149,16 +152,16 @@ void TraceRendererBase::Apply(const gfx::EntityViewColorOp& op) bool TraceRendererBase::HasDataToRender() const { assert(!(state_ & DIRTY_VIEW)); - return this->trace_subset_.GetListCount()>0; + return this->trace_subset_.GetSize()>0; } void TraceRendererBase::set_node_colors(const Color& col, const mol::Query& q, ColorMask mask) { this->UpdateViews(); - for (int node_list=0; node_list<trace_subset_.GetListCount(); ++node_list) { - NodeEntryList& nl=trace_subset_.GetList(node_list); - for (unsigned int i=0; i<nl.size();++i) { + for (int node_list=0; node_list<trace_subset_.GetSize(); ++node_list) { + NodeListSubset& nl=trace_subset_[node_list]; + for (int i=0; i<nl.GetSize();++i) { if(q.IsAtomSelected(nl[i].atom)) { set_node_entry_color(nl[i],mask,col); } @@ -167,6 +170,13 @@ void TraceRendererBase::set_node_colors(const Color& col, const mol::Query& q, state_|=DIRTY_VA; } +void TraceRendererBase::set_node_entry_color(NodeEntry& e, ColorMask mask, + const Color& c) +{ + if (mask & MAIN_COLOR) e.color1=c; + if (mask & DETAIL_COLOR) e.color2=c; +} + void TraceRendererBase::PickAtom(const geom::Line3& line, Real line_width, mol::AtomHandle& picked_atom) { @@ -180,9 +190,9 @@ void TraceRendererBase::PickAtom(const geom::Line3& line, Real line_width, } mol::AtomHandle atom; - for (int node_list=0; node_list<trace_subset_.GetListCount(); ++node_list) { - NodeEntryList& nl=trace_subset_.GetList(node_list); - for (unsigned int i=0; i<nl.size();++i) { + for (int node_list=0; node_list<trace_subset_.GetSize(); ++node_list) { + NodeListSubset& nl=trace_subset_[node_list]; + for (int i=0; i<nl.GetSize();++i) { geom::Vec3 p=nl[i].atom.GetPos(); float dist = geom::Distance(line, p); if(dist<=max_dist) { diff --git a/modules/gfx/src/impl/trace_renderer_base.hh b/modules/gfx/src/impl/trace_renderer_base.hh index 36e3b9602..b102e1cc2 100644 --- a/modules/gfx/src/impl/trace_renderer_base.hh +++ b/modules/gfx/src/impl/trace_renderer_base.hh @@ -20,8 +20,8 @@ #define OST_GFX_IMPL_TRACE_RENDERER_BASE_HH /* - Authors: Marco Biasini, Ansgar Philippsen -*/ + Author: Marco Biasini + */ #include <ost/gfx/module_config.hh> #include <ost/gfx/impl/entity_renderer.hh> @@ -35,11 +35,11 @@ namespace ost { namespace gfx { namespace impl { /// \ref "line trace" LineTraceRenderer and /// \ref "smooth trace" SlineRenderer. /// -/// All trace-based entity renderers share a common instance of BackboneTrace -/// (which is held by gfx::Entity); it encapulates a smoothed C-alpha trace. +/// The trace-based entity renderer share a common instance of BackboneTrace +/// that encapulates a smoothed C-alpha trace. class DLLEXPORT_OST_GFX TraceRendererBase : public EntityRenderer { public: - TraceRendererBase(BackboneTrace* trace, int overshoot); + TraceRendererBase(BackboneTrace& trace, int overshoot); virtual geom::AlignedCuboid GetBoundingBox() const; @@ -63,10 +63,12 @@ public: protected: void set_node_colors(const Color& c, const mol::Query& q, ColorMask mask); + void set_node_entry_color(NodeEntry& e, ColorMask mask, const Color& c); + - BackboneTrace* trace_; - BackboneTrace trace_subset_; - BackboneTrace sel_subset_; + BackboneTrace& trace_; + TraceSubset trace_subset_; + TraceSubset sel_subset_; }; }}} diff --git a/modules/gfx/src/offscreen_buffer.hh b/modules/gfx/src/offscreen_buffer.hh index df2ca183f..c033d8816 100644 --- a/modules/gfx/src/offscreen_buffer.hh +++ b/modules/gfx/src/offscreen_buffer.hh @@ -22,54 +22,86 @@ /* Wraps GL offscreen rendering per platform - boilerplate header, includes platform dependent stuff + Authors: Ansgar Philippsen, Marco Biasini */ -#include <vector> +#include <ost/gfx/gl_include.hh> + +#if defined(__linux__) +# include <GL/glx.h> +#elif defined(__APPLE__) +# include <OpenGL/OpenGL.h> +//#elif defined(_WIN32) +//# include <ost/gfx/GL/wglew.h> +#endif + +#ifdef Complex +# undef Complex +#endif namespace ost { namespace gfx { -class OffscreenBufferFormat -{ +/// \brief offscreen management +class OffscreenBuffer { public: - OffscreenBufferFormat(): cbits(8),abits(8),dbits(12),accum(false),multisample(false),samples(0) {} + + /// \brief singleton interface + static OffscreenBuffer& Instance(); - unsigned int cbits,abits,dbits; // color, alpha, depth bits - bool accum; - bool multisample; - unsigned int samples; -}; + /// \brief activate offscreen context for rendering + bool Begin(); + /// \brief switch back to normal rendering context + bool End(); + /// \ brief resize offscreen rendering context + bool Resize(unsigned int width, unsigned int height); -}} // ns + /// \brief returns true if offscreen rendering context is available + bool IsValid() const; -/* - instead of creating an abstract base class and - making runtime polymorphic classes for each - platform, we do a bit more typing and copy - the minimal interface to each of the platform - specific OffscreenBuffer implementations + /// \brief returns true between Begin/End bracket + bool IsActive() const; - OffscreenBuffer interface: +private: + OffscreenBuffer(int width, int height, int r_bits, int b_bits, + int g_bits, int a_bits, int depth_bits); - OffscreenBuffer(unsigned int width, unsigned int height, const OffscreenBufferFormat& f, bool shared=true); - bool Resize(unsigned int w, unsigned int h); - bool MakeActive(); - bool IsActive(); - bool IsValid(); -*/ + OffscreenBuffer(const OffscreenBuffer& b) {} + OffscreenBuffer& operator=(const OffscreenBuffer& b) {return *this;} + + int width_; + int height_; + bool valid_; + bool active_; #if defined(__linux__) -#include "impl/glx_offscreen_buffer.hh" + Display* dpy_; + GLXFBConfig* fbconfig_; + GLXPbuffer pbuffer_; + GLXContext context_; + GLXContext old_context_; + GLXDrawable old_dr1_; + GLXDrawable old_dr2_; + #elif defined(__APPLE__) -#include "impl/cgl_offscreen_buffer.hh" + + CGLPBufferObj pbuffer_; + CGLContextObj context_; + CGLPixelFormatObj pix_format_; + CGLContextObj old_context_; + #elif defined(_WIN32) -#include "impl/wgl_offscreen_buffer.hh" -#else -#error platform not found for offscreen rendering +/* HPBUFFERARB pbuffer_; + HGLRC context_; //rendering context + HGLRC old_context_; + + HDC dev_context_;//device context + HDC old_dev_context_; + */ #endif + + GLint old_vp_[4]; +}; -#ifdef Complex -# undef Complex -#endif +}} #endif diff --git a/modules/gfx/src/prim_list.cc b/modules/gfx/src/prim_list.cc index 4c2395c14..2302dc7fe 100644 --- a/modules/gfx/src/prim_list.cc +++ b/modules/gfx/src/prim_list.cc @@ -31,9 +31,7 @@ PrimList::PrimList(const String& name): points_(), lines_(), radius_(0.5), - diameter_(0.5), - sphere_detail_(4), - arc_detail_(4) + diameter_(0.5) {} void PrimList::Clear() @@ -97,6 +95,8 @@ void PrimList::CustomPreRenderGL(bool flag) } else { render_simple(); } + } else { + RefreshVA(va_); } } @@ -155,28 +155,12 @@ void PrimList::SetDiameter(float d) { diameter_=d; Scene::Instance().RequestRedraw(); - FlagRebuild(); } void PrimList::SetRadius(float r) { radius_=r; Scene::Instance().RequestRedraw(); - FlagRebuild(); -} - -void PrimList::SetSphereDetail(unsigned int d) -{ - sphere_detail_=d; - Scene::Instance().RequestRedraw(); - FlagRebuild(); -} - -void PrimList::SetArcDetail(unsigned int d) -{ - arc_detail_=d; - Scene::Instance().RequestRedraw(); - FlagRebuild(); } void PrimList::SetColor(const Color& c) @@ -185,7 +169,6 @@ void PrimList::SetColor(const Color& c) it->color=c; } Scene::Instance().RequestRedraw(); - FlagRebuild(); } diff --git a/modules/gfx/src/prim_list.hh b/modules/gfx/src/prim_list.hh index fbac2cffc..1de40d7f9 100644 --- a/modules/gfx/src/prim_list.hh +++ b/modules/gfx/src/prim_list.hh @@ -98,12 +98,6 @@ class DLLEXPORT_OST_GFX PrimList: public GfxObj /// \brief set global prims color, overriding individual ones void SetColor(const Color& c); - void SetSphereDetail(unsigned int d); - unsigned int GetSphereDetail() const {return sphere_detail_;} - - void SetArcDetail(unsigned int d); - unsigned int GetArcDetail() const {return arc_detail_;} - protected: virtual void CustomPreRenderGL(bool flag); @@ -112,8 +106,6 @@ class DLLEXPORT_OST_GFX PrimList: public GfxObj LineEntryList lines_; float radius_; float diameter_; - unsigned int sphere_detail_; - unsigned int arc_detail_; void render_simple(); void render_custom(); diff --git a/modules/gfx/src/render_options/cartoon_render_options.cc b/modules/gfx/src/render_options/cartoon_render_options.cc index f50d28a5b..da5d2e703 100644 --- a/modules/gfx/src/render_options/cartoon_render_options.cc +++ b/modules/gfx/src/render_options/cartoon_render_options.cc @@ -39,12 +39,10 @@ CartoonRenderOptions::CartoonRenderOptions(bool force_tube): helix_thickness_(0.2), helix_ecc_(0.3), helix_profile_(1), - helix_mode_(0), strand_width_(1.2), strand_thickness_(0.2), strand_ecc_(0.3), - strand_profile_(1), - strand_mode_(0) + strand_profile_(1) {} RenderMode::Type CartoonRenderOptions::GetRenderMode(){ @@ -68,17 +66,12 @@ void CartoonRenderOptions::ApplyRenderOptions(RenderOptionsPtr render_options){ smooth_factor_=options->GetNormalSmoothFactor(); tube_radius_=options->GetTubeRadius(); tube_ratio_=options->GetTubeRatio(); - tube_profile_=options->GetTubeProfileType(); helix_width_=options->GetHelixWidth(); helix_thickness_=options->GetHelixThickness(); helix_ecc_=options->GetHelixEcc(); - helix_profile_=options->GetHelixProfileType(); - helix_mode_=options->GetHelixMode(); strand_width_=options->GetStrandWidth(); strand_thickness_=options->GetStrandThickness(); strand_ecc_=options->GetStrandEcc(); - strand_profile_=options->GetStrandProfileType(); - strand_mode_=options->GetStrandMode(); this->NotifyStateChange(); } @@ -203,17 +196,6 @@ void CartoonRenderOptions::SetHelixProfileType(unsigned int t) this->NotifyStateChange(); } -unsigned int CartoonRenderOptions::GetHelixMode() const -{ - return helix_mode_; -} - -void CartoonRenderOptions::SetHelixMode(unsigned int m) -{ - helix_mode_=m; - this->NotifyStateChange(); -} - void CartoonRenderOptions::SetStrandWidth(float strand_width){ if(strand_width_ != strand_width){ strand_width_= strand_width>0.0 ? strand_width : strand_width_; @@ -258,17 +240,6 @@ void CartoonRenderOptions::SetStrandProfileType(unsigned int t) this->NotifyStateChange(); } -unsigned int CartoonRenderOptions::GetStrandMode() const -{ - return strand_mode_; -} - -void CartoonRenderOptions::SetStrandMode(unsigned int m) -{ - strand_mode_=m; - this->NotifyStateChange(); -} - float CartoonRenderOptions::GetMaxRad() const{ float max_rad=std::max(float(3.0),tube_radius_*tube_ratio_); max_rad=std::max(max_rad,tube_radius_); diff --git a/modules/gfx/src/render_options/cartoon_render_options.hh b/modules/gfx/src/render_options/cartoon_render_options.hh index 98f490430..092fafe69 100644 --- a/modules/gfx/src/render_options/cartoon_render_options.hh +++ b/modules/gfx/src/render_options/cartoon_render_options.hh @@ -67,8 +67,6 @@ public: virtual float GetHelixEcc() const; virtual unsigned int GetHelixProfileType() const; virtual void SetHelixProfileType(unsigned int); - virtual unsigned int GetHelixMode() const; - virtual void SetHelixMode(unsigned int); virtual void SetStrandWidth(float strand_width); virtual float GetStrandWidth() const; @@ -78,8 +76,6 @@ public: virtual float GetStrandEcc() const; virtual unsigned int GetStrandProfileType() const; virtual void SetStrandProfileType(unsigned int); - virtual unsigned int GetStrandMode() const; - virtual void SetStrandMode(unsigned int); float GetMaxRad() const; @@ -100,13 +96,10 @@ private: float helix_thickness_; float helix_ecc_; unsigned int helix_profile_; - unsigned int helix_mode_; float strand_width_; float strand_thickness_; float strand_ecc_; unsigned int strand_profile_; - unsigned int strand_mode_; - }; typedef boost::shared_ptr<CartoonRenderOptions> CartoonRenderOptionsPtr; diff --git a/modules/gfx/src/render_options/cpk_render_options.cc b/modules/gfx/src/render_options/cpk_render_options.cc index 797fcf760..611db0f48 100644 --- a/modules/gfx/src/render_options/cpk_render_options.cc +++ b/modules/gfx/src/render_options/cpk_render_options.cc @@ -28,7 +28,7 @@ namespace gfx { CPKRenderOptions::CPKRenderOptions(): sphere_detail_(4) { #if OST_SHADER_SUPPORT_ENABLED - cpk_mode_=0; + cpk_mode_=1; #else cpk_mode_=0; #endif diff --git a/modules/gfx/src/render_pass.hh b/modules/gfx/src/render_pass.hh index 00c5f7c23..dd7a34a33 100644 --- a/modules/gfx/src/render_pass.hh +++ b/modules/gfx/src/render_pass.hh @@ -33,10 +33,8 @@ typedef enum { /// \brief renders objects with solid color as used for shadow map /// generation OPAQUE_RENDER_PASS, - /// \ brief for transparent objects - TRANSPARENT_RENDER_PASS } RenderPass; }} -#endif +#endif \ No newline at end of file diff --git a/modules/gfx/src/scene.cc b/modules/gfx/src/scene.cc index 4ded0a30c..c85abc13d 100644 --- a/modules/gfx/src/scene.cc +++ b/modules/gfx/src/scene.cc @@ -42,6 +42,7 @@ #include "gl_helper.hh" #include <ost/config.hh> +#include "offscreen_buffer.hh" #include "scene.hh" #include "input.hh" #include "gfx_node.hh" @@ -50,7 +51,6 @@ #include "bitmap_io.hh" #include "entity.hh" #include "povray.hh" -#include "offscreen_buffer.hh" #if OST_SHADER_SUPPORT_ENABLED # include "shader.hh" @@ -115,7 +115,6 @@ Scene::Scene(): texture_id_(), auto_autoslab_(true), offscreen_flag_(false), - main_offscreen_buffer_(0), selection_mode_(1), test_flag_(false), tmp_tex_(), @@ -144,11 +143,6 @@ void Scene::SetFog(bool f) RequestRedraw(); } -bool Scene::GetFog() const -{ - return fog_flag_; -} - void Scene::SetFogColor(const Color& c) { GLfloat fogc[]={c.Red(),c.Green(),c.Blue(),1.0}; @@ -157,11 +151,6 @@ void Scene::SetFogColor(const Color& c) RequestRedraw(); } -Color Scene::GetFogColor() const -{ - return fog_color_; -} - void Scene::SetShadow(bool f) { shadow_flag_=f; @@ -192,10 +181,9 @@ void set_light_dir(Vec3 ld) void Scene::InitGL() { - LOGN_DEBUG("scene: initializing GL state"); + LOG_DEBUG("scene: initializing GL state" << std::endl); #if OST_SHADER_SUPPORT_ENABLED - LOGN_DEBUG("scene: shader pre-gl"); Shader::Instance().PreGLInit(); #endif @@ -246,29 +234,9 @@ void Scene::InitGL() glShadeModel(GL_SMOOTH); // line and point anti-aliasing - -#if OST_SHADER_SUPPORT_ENABLED - GLint mbufs,msamples; - glGetIntegerv(GL_SAMPLE_BUFFERS, &mbufs); - glGetIntegerv(GL_SAMPLES, &msamples); - - if(mbufs>0 && msamples>0) { - LOGN_VERBOSE("enabling multisampling with: " << msamples << " samples"); - glDisable(GL_LINE_SMOOTH); - glDisable(GL_POINT_SMOOTH); - glDisable(GL_POLYGON_SMOOTH); - glEnable(GL_MULTISAMPLE); - } else { - glEnable(GL_LINE_SMOOTH); - glDisable(GL_POINT_SMOOTH); - glDisable(GL_POLYGON_SMOOTH); - } -#else glEnable(GL_LINE_SMOOTH); glDisable(GL_POINT_SMOOTH); glDisable(GL_POLYGON_SMOOTH); -#endif - // rendering hints glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glHint(GL_FOG_HINT, GL_NICEST); @@ -281,7 +249,6 @@ void Scene::InitGL() // glDrawBuffer(GL_BACK); // initialize shaders #if OST_SHADER_SUPPORT_ENABLED - LOGN_DEBUG("scene: shader setup"); Shader::Instance().Setup(); Shader::Instance().Activate("fraglight"); @@ -293,7 +260,7 @@ void Scene::InitGL() void Scene::RequestRedraw() { - if (win_ && !offscreen_flag_) { + if (win_) { win_->DoRefresh(); } } @@ -311,11 +278,6 @@ void Scene::SetBackground(const Color& c) RequestRedraw(); } -Color Scene::GetBackground() const -{ - return background_; -} - Viewport Scene::GetViewport() const { Viewport vp; @@ -344,7 +306,6 @@ void Scene::SetCenter(const Vec3& cen) float delta_z = tcen[2]-transform_.GetTrans()[2]; transform_.SetCenter(cen); - transform_.SetTrans(Vec3(0,0,transform_.GetTrans()[2])); SetNearFar(znear_+delta_z,zfar_+delta_z); RequestRedraw(); } @@ -545,37 +506,6 @@ namespace { GfxObjP node; }; -#if 0 - struct RegexFindObj: public GfxNodeVisitor { - RegexFindObj(const String& rs): reg(), valid(false), node() { - try { - reg = boost::regex(rs); - valid = true; - } catch (boost::regex_error& e) { - LOGN_ERROR("invalid regex"); - } - } - - virtual bool VisitNode(GfxNode* n, const Stack& st) { - return true; - } - - virtual void VisitObject(GfxObj* o, const Stack& st) { - if(boost::regex_match(o->GetName(),reg)) { - GfxNodeP nn = o->shared_from_this(); - GfxObjP oo = dyn_cast<GfxObj>(nn); - if(oo) { - olist.push_back(oo); - } - } - } - - boost::regex reg; - bool valid; - std::vector<GfxObjP> olist; - }; -#endif - struct FindNode2: public GfxNodeVisitor { FindNode2(GfxNodeP n): node(n), found(false) {} virtual bool VisitNode(GfxNode* n, const Stack& st) { @@ -615,14 +545,6 @@ void Scene::Add(const GfxNodeP& n, bool redraw) } LOG_DEBUG("scene: graphical object added @" << n.get() << std::endl); - - if(root_node_->GetChildCount()==0) { - GfxObjP go = boost::dynamic_pointer_cast<GfxObj>(n); - if(go) { - SetCenter(go->GetCenter()); - } - } - root_node_->Add(n); if (redraw) { this->RequestRedraw(); @@ -1201,54 +1123,24 @@ uint Scene::GetSelectionMode() const return selection_mode_; } -void Scene::StartOffscreenMode(unsigned int width, unsigned int height) -{ - if(main_offscreen_buffer_) return; - main_offscreen_buffer_ = new OffscreenBuffer(width,height,OffscreenBufferFormat(),true); +namespace { - if(!main_offscreen_buffer_->IsValid()) { - LOGN_ERROR("error during offscreen buffer creation"); - delete main_offscreen_buffer_; - main_offscreen_buffer_=0; - return; +struct OffscreenSwitcher +{ + OffscreenSwitcher() + { + LOGN_TRACE("offscreen begin"); + OffscreenBuffer::Instance().Begin(); } - old_vp_[0]=vp_width_; - old_vp_[1]=vp_height_; - main_offscreen_buffer_->MakeActive(); - offscreen_flag_=true; - root_node_->ContextSwitch(); -#if OST_SHADER_SUPPORT_ENABLED - String shader_name = Shader::Instance().GetCurrentName(); -#endif - LOGN_DEBUG("initializing GL"); - this->InitGL(); - LOGN_DEBUG("setting viewport"); - Resize(width,height); - LOGN_DEBUG("updating fog settings"); - update_fog(); - glDrawBuffer(GL_FRONT); -#if OST_SHADER_SUPPORT_ENABLED - LOGN_DEBUG("activating shader"); - Shader::Instance().Activate(shader_name); -#endif -} - -void Scene::StopOffscreenMode() -{ - if(main_offscreen_buffer_) { - if (win_) { - win_->MakeActive(); - } - delete main_offscreen_buffer_; - main_offscreen_buffer_=0; - Scene::Instance().SetViewport(old_vp_[0],old_vp_[1]); - offscreen_flag_=false; - root_node_->ContextSwitch(); - glDrawBuffer(GL_BACK); - update_fog(); + ~OffscreenSwitcher() + { + LOGN_TRACE("offscreen end"); + OffscreenBuffer::Instance().End(); } -} +}; + +} // anon ns void Scene::Export(const String& fname, unsigned int width, unsigned int height, bool transparent) @@ -1264,101 +1156,61 @@ void Scene::Export(const String& fname, unsigned int width, return; } - GLint old_vp[4]; - glGetIntegerv(GL_VIEWPORT,old_vp); - bool old_flag=offscreen_flag_; - if(!main_offscreen_buffer_) { - try { - LOGN_DEBUG("creating a " << width <<"x" << height << " offscreen rendering buffer"); - OffscreenBuffer ob(width,height,OffscreenBufferFormat(),true); - - if(!ob.IsValid()) { - LOGN_ERROR("error during offscreen buffer creation"); - return; - } - - ob.MakeActive(); - offscreen_flag_=true; -#if 1 -#if OST_SHADER_SUPPORT_ENABLED - String shader_name = Shader::Instance().GetCurrentName(); -#endif - LOGN_DEBUG("initializing GL"); - this->InitGL(); - LOGN_DEBUG("setting viewport"); - SetViewport(width,height); - LOGN_DEBUG("reseting projection"); - ResetProjection(); - LOGN_DEBUG("updating fog settings"); - update_fog(); - glDrawBuffer(GL_FRONT); + offscreen_flag_=true; + LOGN_TRACE("offscreen resize"); + OffscreenBuffer::Instance().Resize(width, height); + try { + // ensures that context is switched back when this goes out of scope + OffscreenSwitcher offscreen_switch; #if OST_SHADER_SUPPORT_ENABLED - LOGN_DEBUG("activating shader"); - Shader::Instance().Activate(shader_name); + String shader_name = Shader::Instance().GetCurrentName(); #endif - root_node_->ContextSwitch(); + LOGN_TRACE("initializing GL"); + this->InitGL(); + LOGN_TRACE("setting viewport"); + SetViewport(width,height); + LOGN_TRACE("reseting projection"); + ResetProjection(); + LOGN_TRACE("updating fog settings"); + update_fog(); + glDrawBuffer(GL_FRONT); + //this->flag_all_dirty(); +#if OST_SHADER_SUPPORT_ENABLED + LOGN_TRACE("activating shader"); + Shader::Instance().Activate(shader_name); #endif - } catch (std::exception& e) { - LOGN_ERROR("exception during offscreen rendering initialization: " << e.what()); - throw; + LOGN_TRACE("doing rendering"); + this->RenderGL(); + // make sure drawing operations are finished + glFinish(); + boost::shared_array<uchar> img_data(new uchar[width*height*4]); + + LOGN_TRACE("setting background transparency"); + if (transparent) { + glPixelTransferf(GL_ALPHA_BIAS, 0.0); + } else { + // shift alpha channel by one to make sure pixels are read out as opaque + glPixelTransferf(GL_ALPHA_BIAS, 1.0); } - } else { - LOGN_DEBUG("using active main offscreen buffer"); - } - LOGN_DEBUG("rendering into offscreen buffer"); - this->RenderGL(); - // make sure drawing operations are finished - glFlush(); - glFinish(); - unsigned int width2=width; - unsigned int height2=height; - if(main_offscreen_buffer_!=NULL) { - // use settings from active main buffer - width2=old_vp[2]; - height2=old_vp[3]; - } - boost::shared_array<uchar> img_data(new uchar[width2*height2*4]); - - LOGN_DEBUG("setting background transparency"); - if (transparent) { - glPixelTransferf(GL_ALPHA_BIAS, 0.0); - } else { - // shift alpha channel by one to make sure pixels are read out as opaque - glPixelTransferf(GL_ALPHA_BIAS, 1.0); - } - - LOGN_DEBUG("reading framebuffer pixels"); - glReadBuffer(GL_FRONT); - glReadPixels(0,0,width2,height2,GL_RGBA,GL_UNSIGNED_BYTE,img_data.get()); + LOGN_TRACE("reading framebuffer pixels"); + glReadBuffer(GL_FRONT); + glReadPixels(0,0,width,height,GL_RGBA,GL_UNSIGNED_BYTE,img_data.get()); - LOGN_DEBUG("calling bitmap export"); - BitmapExport(fname,ext,width2,height2,img_data.get()); - - if(!main_offscreen_buffer_) { - LOGN_DEBUG("switching back to main context"); - if (!win_) { - return; - } - win_->MakeActive(); - Scene::Instance().SetViewport(old_vp[2],old_vp[3]); - offscreen_flag_=old_flag; - root_node_->ContextSwitch(); - glDrawBuffer(GL_BACK); - LOGN_DEBUG("updating fog"); - update_fog(); - } else { - // nothing needs to happen here, main offscreen buffer was active, and stays active - } + LOGN_DEBUG("calling bitmap export"); + BitmapExport(fname,ext,width,height,img_data.get()); + } catch (...) { + // noop + } // offscreen_switch goes out of scope + offscreen_flag_=false; + glDrawBuffer(GL_BACK); + LOGN_TRACE("updating fog"); + update_fog(); } void Scene::Export(const String& fname, bool transparent) { - if(!win_ && !main_offscreen_buffer_) { - LOGN_ERROR("Export without dimensions either requires an interactive session \nor an active offscreen mode (scene.StartOffscreenMode(W,H))"); - return; - } int d_index=fname.rfind('.'); if (d_index==-1) { LOGN_ERROR("no file extension specified"); @@ -1372,12 +1224,6 @@ void Scene::Export(const String& fname, bool transparent) GLint vp[4]; glGetIntegerv(GL_VIEWPORT,vp); - if(main_offscreen_buffer_) { - this->RenderGL(); - glFlush(); - glFinish(); - } - if (transparent) { glPixelTransferf(GL_ALPHA_BIAS, 0.0); } else { @@ -1703,6 +1549,11 @@ bool Scene::InOffscreenMode() const return offscreen_flag_; } +void Scene::SetOffscreenMode() +{ + OffscreenBuffer::Instance().Begin(); +} + float Scene::ElapsedTime() const { #ifndef _MSC_VER diff --git a/modules/gfx/src/scene.hh b/modules/gfx/src/scene.hh index 6c88204d2..d86e46a6a 100644 --- a/modules/gfx/src/scene.hh +++ b/modules/gfx/src/scene.hh @@ -46,7 +46,6 @@ namespace ost { namespace gfx { class InputEvent; -class OffscreenBuffer; typedef std::vector<SceneObserver*> SceneObserverList; @@ -93,15 +92,9 @@ class DLLEXPORT_OST_GFX Scene { /// \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 on and off void SetShadow(bool f); @@ -191,15 +184,13 @@ class DLLEXPORT_OST_GFX Scene { /// \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 + /// \brief export scene into povray files names fname.pov and fname.inc void ExportPov(const std::string& fname, const std::string& wdir="."); //@} /// \brief entry point for gui events (internal use) @@ -234,9 +225,6 @@ class DLLEXPORT_OST_GFX Scene { /// \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); @@ -323,27 +311,15 @@ class DLLEXPORT_OST_GFX Scene { bool InOffscreenMode() const; + /// \brief internal use + static void SetOffscreenMode(); + /// \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 - */ - void StartOffscreenMode(unsigned int w, unsigned int h); - /// \brief stops offline rendering in interactive mode - void StopOffscreenMode(); // temporary interface void ActivateShader(const String& name); @@ -406,9 +382,7 @@ private: GLuint texture_id_; 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 + bool offscreen_flag_; uint selection_mode_; diff --git a/modules/gfx/src/shader/fraglight_lf_fs.glsl b/modules/gfx/src/shader/fraglight_lf_fs.glsl index ad34b9f40..7ffec79b8 100644 --- a/modules/gfx/src/shader/fraglight_lf_fs.glsl +++ b/modules/gfx/src/shader/fraglight_lf_fs.glsl @@ -2,7 +2,6 @@ uniform bool lighting_flag; uniform bool two_sided_flag; uniform bool fog_flag; uniform bool occlusion_flag; -uniform vec2 ambient_weight; varying vec4 ambient_color; // copy from basic_fl_vs ! @@ -35,34 +34,31 @@ void main() vec4 amb = vec4(0.0); vec4 diff = vec4(0.0); vec4 spec = vec4(0.0); + vec4 color = vec4(0.0); - vec4 color = gl_Color; + /* + For ambient occlusion, this blends the local ambient color together with + the fragment color at intensity given my the ambient material settings; + ambient_color defaults to gl_Color, so for non ambient-occluded scenes, + this is a noop + */ + vec4 diff_color = gl_Color; if(occlusion_flag) { - /* - For ambient occlusion and local coloring, two effects are possible. - (1) Blending of the original fragment color and the accumulated - color of the neighbouring fragments, by ambient_weight[0]. - (2) Attenuating the resulting color intensity by the ambient occlusion, - modulated by ambient_weight[1] - Only the rgb values are affected, fragment opacity is unchanged - */ - - color.rgb = mix(gl_Color.rgb,ambient_color.rgb,ambient_weight[0]); - color.rgb = mix(color.rgb,ambient_color.aaa*color.rgb,ambient_weight[1]); + diff_color.rgb = mix(gl_Color.rgb,ambient_color.rgb,gl_FrontMaterial.ambient.rgb); } if(DirectionalLight(normal, gl_FrontMaterial.shininess, amb, diff, spec)) { color = gl_FrontLightModelProduct.sceneColor + - (amb * gl_FrontMaterial.ambient * color) + - (diff * gl_FrontMaterial.diffuse * color) + + (amb * gl_FrontMaterial.diffuse * diff_color * ambient_color.a) + + (diff * gl_FrontMaterial.diffuse * diff_color) + (spec * gl_FrontMaterial.specular); } else { DirectionalLight(-normal, gl_BackMaterial.shininess, amb, diff, spec); color = gl_BackLightModelProduct.sceneColor + - (amb * gl_BackMaterial.ambient * color) + - (diff * gl_BackMaterial.diffuse * color) + + (amb * gl_BackMaterial.ambient * diff_color * ambient_color.a) + + (diff * gl_BackMaterial.diffuse * diff_color) + (spec * gl_BackMaterial.specular); } diff --git a/modules/gfx/src/surface.cc b/modules/gfx/src/surface.cc index 40db431fe..e0d08cdc1 100644 --- a/modules/gfx/src/surface.cc +++ b/modules/gfx/src/surface.cc @@ -43,10 +43,7 @@ Surface::Surface(const String& name, const mol::SurfaceHandle& sh): recalc_bb_(true) { // TODO replace with def mat for this gfx obj type - SetMatAmb(Color(0,0,0)); - SetMatDiff(Color(1,1,1)); - SetMatSpec(Color(0.2,0.2,0.2)); - SetMatShin(48); + SetMat(0.0,1.0,0.2,48.0); Rebuild(); } @@ -167,11 +164,10 @@ geom::AlignedCuboid Surface::GetBoundingBox() const void Surface::CustomPreRenderGL(bool flag) { - va_.FlagRefresh(); if(flag) { //Rebuild(); } else { - //RefreshVA(va_); + RefreshVA(va_); } } @@ -248,29 +244,28 @@ void Surface::ColorBy(const String& prop, void Surface::Apply(const gfx::UniformColorOp& op, bool store){ if(store){ - UniformColorOp* op_ptr = new UniformColorOp(op); + UniformColorOp* op_ptr = new UniformColorOp(op); this->AppendColorOp(op_ptr); } mol::Query q(op.GetSelection()); gfx::Color col = op.GetColor(); if(op.GetSelection()=="") { - for(VMap::const_iterator it=vmap_.begin();it!=vmap_.end();++it) { - va_.SetColor(it->second,col); - } + for(VMap::const_iterator it=vmap_.begin();it!=vmap_.end();++it) { + va_.SetColor(it->second,col); + } } else { - for(VMap::const_iterator it=vmap_.begin();it!=vmap_.end();++it) { - mol::AtomHandle ah = sh_.GetVertex(it->first).atom; - if(ah.IsValid()) { - if(q.IsAtomSelected(ah)) { - va_.SetColor(it->second,col); - } - } - } + for(VMap::const_iterator it=vmap_.begin();it!=vmap_.end();++it) { + mol::AtomHandle ah = sh_.GetVertex(it->first).atom; + if(ah.IsValid()) { + if(q.IsAtomSelected(ah)) { + va_.SetColor(it->second,col); + } + } + } } FlagRefresh(); } -void Surface::Apply(const gfx::BasicGradientColorOp& op, bool store) -{ +void Surface::Apply(const gfx::BasicGradientColorOp& op, bool store){ if(store){ BasicGradientColorOp* op_ptr = new BasicGradientColorOp(op); this->AppendColorOp(op_ptr); @@ -284,24 +279,23 @@ void Surface::Apply(const gfx::BasicGradientColorOp& op, bool store) mol::EntityPropertyMapper epm(prop, level); std::vector<std::pair<VertexID,float> > v2v; for(VMap::const_iterator it=vmap_.begin();it!=vmap_.end();++it) { - mol::AtomHandle ah = sh_.GetVertex(it->first).atom; - if(ah.IsValid()) { - float v = epm.Get(ah); - v2v.push_back(std::make_pair(it->second,v)); - minv=std::min(minv,v); - maxv=std::max(maxv,v); - } + mol::AtomHandle ah = sh_.GetVertex(it->first).atom; + if(ah.IsValid()) { + float v = epm.Get(ah); + v2v.push_back(std::make_pair(it->second,v)); + minv=std::min(minv,v); + maxv=std::max(maxv,v); + } } - + // reuse values for speed optimization for(std::vector<std::pair<VertexID,float> >::const_iterator it=v2v.begin();it!=v2v.end();++it) { - va_.SetColor(it->first,gradient.GetColorAt(normalize(it->second,minv,maxv))); + va_.SetColor(it->first,gradient.GetColorAt(normalize(it->second,minv,maxv))); } FlagRefresh(); } -void Surface::Apply(const gfx::GradientLevelColorOp& op, bool store) -{ +void Surface::Apply(const gfx::GradientLevelColorOp& op, bool store){ if(store){ GradientLevelColorOp* op_ptr = new GradientLevelColorOp(op); this->AppendColorOp(op_ptr); @@ -315,16 +309,15 @@ void Surface::Apply(const gfx::GradientLevelColorOp& op, bool store) // for the attached atoms mol::EntityPropertyMapper epm(prop, level); for(VMap::const_iterator it=vmap_.begin();it!=vmap_.end();++it) { - mol::AtomHandle ah = sh_.GetVertex(it->first).atom; - if(ah.IsValid()) { - va_.SetColor(it->second,gradient.GetColorAt(normalize(epm.Get(ah),minv,maxv))); - } + mol::AtomHandle ah = sh_.GetVertex(it->first).atom; + if(ah.IsValid()) { + va_.SetColor(it->second,gradient.GetColorAt(normalize(epm.Get(ah),minv,maxv))); + } } FlagRefresh(); } -void Surface::Apply(const gfx::EntityViewColorOp& op, bool store) -{ +void Surface::Apply(const gfx::EntityViewColorOp& op, bool store){ if(store){ EntityViewColorOp* op_ptr = new EntityViewColorOp(op); this->AppendColorOp(op_ptr); @@ -335,15 +328,14 @@ void Surface::Apply(const gfx::EntityViewColorOp& op, bool store) float minv = op.GetMinV(); float maxv = op.GetMaxV(); for(VMap::const_iterator it=vmap_.begin();it!=vmap_.end();++it) { - va_.SetColor(it->second,impl::MappedProperty(ev,prop,g,minv,maxv, - sh_.GetVertex(it->first).position)); + va_.SetColor(it->second,impl::MappedProperty(ev,prop,g,minv,maxv, + sh_.GetVertex(it->first).position)); } FlagRefresh(); } - + #if OST_IMG_ENABLED -void Surface::Apply(const gfx::MapHandleColorOp& op, bool store) -{ +void Surface::Apply(const gfx::MapHandleColorOp& op, bool store){ if(store){ MapHandleColorOp* op_ptr = new MapHandleColorOp(op); this->AppendColorOp(op_ptr); @@ -354,19 +346,17 @@ void Surface::Apply(const gfx::MapHandleColorOp& op, bool store) float minv = op.GetMinV(); float maxv = op.GetMaxV(); for(VMap::const_iterator it=vmap_.begin();it!=vmap_.end();++it) { - va_.SetColor(it->second,impl::MappedProperty(mh,prop,g,minv,maxv,sh_.GetVertex(it->first).position)); + va_.SetColor(it->second,impl::MappedProperty(mh,prop,g,minv,maxv,sh_.GetVertex(it->first).position)); } FlagRefresh(); } #endif //OST_IMG_ENABLED -void Surface::CleanColorOps() -{ +void Surface::CleanColorOps(){ GfxObj::CleanColorOps(); } -void Surface::ReapplyColorOps() -{ +void Surface::ReapplyColorOps(){ GfxObj::ReapplyColorOps(); } diff --git a/modules/gfx/src/vertex_array.cc b/modules/gfx/src/vertex_array.cc index 06d9123ee..970c09887 100644 --- a/modules/gfx/src/vertex_array.cc +++ b/modules/gfx/src/vertex_array.cc @@ -77,7 +77,7 @@ IndexedVertexArray::Entry::Entry(const Vec3& vv, const Vec3& nn, const Color& cc IndexedVertexArray::IndexedVertexArray() { initialized_=false; - Reset(); // replaces ctor initialization list + Clear(); // replaces ctor initialization list } IndexedVertexArray::~IndexedVertexArray() @@ -249,7 +249,7 @@ void IndexedVertexArray::AddIcoSphere(const SpherePrim& prim, unsigned int detai } } -void IndexedVertexArray::AddCylinder(const CylinderPrim& prim, unsigned int detail,bool cap) +void IndexedVertexArray::AddCylinder(const CylinderPrim& prim, unsigned int detail) { dirty_=true; ambient_dirty_=true; @@ -259,54 +259,33 @@ void IndexedVertexArray::AddCylinder(const CylinderPrim& prim, unsigned int deta const std::vector<Vec3>& vlist = detail::GetPrebuildCyl(level); Vec3 off(0.0,0.0,prim.length); - - Vec3 cn0 = cap ? prim.rotmat* geom::Vec3(0.0,0.0,-1.0) : Vec3(); - Vec3 cn1 = -cn0; - VertexID cid0 = cap ? Add(prim.start, cn0 , prim.color1) : 0; - VertexID cid7 = cap ? Add(prim.rotmat * off + prim.start, cn1, prim.color2) : 0; // prepare first vertices to add std::vector<Vec3>::const_iterator it=vlist.begin(); Vec3 v0 = (*it); Vec3 n0 = prim.rotmat * v0; v0*=prim.radius; - VertexID id1 = Add(prim.rotmat * v0 + prim.start, n0, prim.color1); - VertexID id2 = Add(prim.rotmat * (v0+off) + prim.start, n0, prim.color2); - VertexID cid1 = cap ? Add(prim.rotmat * v0 + prim.start, cn0, prim.color1) : 0; - VertexID cid2 = cap ? Add(prim.rotmat * (v0+off) + prim.start, cn1, prim.color2) : 0; + VertexID id1 = Add(prim.rotmat * v0 + prim.start, n0, prim.color); + VertexID id2 = Add(prim.rotmat * (v0+off) + prim.start, n0, prim.color); // now for the loop around the circle VertexID id3=id1; VertexID id4=id2; - VertexID cid3=cid1; - VertexID cid4=cid2; ++it; for(;it!=vlist.end();++it) { v0 = (*it); n0 = prim.rotmat * v0; v0 *= prim.radius; - VertexID id5 = Add(prim.rotmat * v0 + prim.start, n0, prim.color1); - VertexID id6 = Add(prim.rotmat * (v0+off) + prim.start, n0, prim.color2); + VertexID id5 = Add(prim.rotmat * v0 + prim.start, n0, prim.color); + VertexID id6 = Add(prim.rotmat * (v0+off) + prim.start, n0, prim.color); AddTri(id3,id5,id4); AddTri(id5,id6,id4); - if(cap) { - VertexID cid5 = Add(prim.rotmat * v0 + prim.start, cn0, prim.color1); - VertexID cid6 = Add(prim.rotmat * (v0+off) + prim.start, cn1, prim.color2); - AddTri(cid0,cid5,cid3); - AddTri(cid7,cid4,cid6); - cid3=cid5; - cid4=cid6; - } id3=id5; id4=id6; } // and finally close the circle AddTri(id3,id1,id4); AddTri(id1,id2,id4); - if(cap) { - AddTri(cid0,cid1,cid3); - AddTri(cid7,cid4,cid2); - } } Vec3 IndexedVertexArray::GetVert(VertexID id) const @@ -368,9 +347,7 @@ void IndexedVertexArray::RenderGL() if(!initialized_) { LOGN_DUMP("initializing vertex array lists"); #if OST_SHADER_SUPPORT_ENABLED - if(!Scene::Instance().InOffscreenMode()) { - glGenBuffers(7,buffer_id_); - } + glGenBuffers(7,buffer_id_); #endif outline_mat_dlist_=glGenLists(1); initialized_=true; @@ -392,7 +369,6 @@ void IndexedVertexArray::RenderGL() use_buff=prep_buff(); } if(!use_buff) { - LOGN_DUMP("buffer not available"); glBindBuffer(GL_ARRAY_BUFFER,0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); } else { @@ -468,11 +444,6 @@ void IndexedVertexArray::RenderGL() #if OST_SHADER_SUPPORT_ENABLED if(use_ambient_ && !ambient_data_.empty()) { glUniform1i(glGetUniformLocation(Shader::Instance().GetCurrentProgram(),"occlusion_flag"),1); - glUniform2f(glGetUniformLocation(Shader::Instance().GetCurrentProgram(),"ambient_weight"), - local_ambient_weight_, - ambient_occlusion_weight_); - } else { - glUniform1i(glGetUniformLocation(Shader::Instance().GetCurrentProgram(),"occlusion_flag"),0); } #endif } @@ -540,6 +511,12 @@ void IndexedVertexArray::RenderGL() } } +#if OST_SHADER_SUPPORT_ENABLED + if(use_ambient_) { + glUniform1i(glGetUniformLocation(Shader::Instance().GetCurrentProgram(),"occlusion_flag"),0); + } +#endif + if(draw_normals_) { //glColor3f(1,0,0); glBegin(GL_LINES); @@ -562,16 +539,13 @@ void IndexedVertexArray::RenderGL() namespace { unsigned int col_to_index(float* c) { - // don't look too closely - I am lacking sufficient caffeine to do this more elegantly - int ret= std::max(0,std::min<int>(511,static_cast<int>(round(c[0]*7.0f))*64+static_cast<int>(round(c[1]*7.0f))*8+static_cast<unsigned int>(round(c[2]*7.0f)))); - return static_cast<unsigned int>(ret); + return static_cast<unsigned int>(c[0]*7.0)*64+static_cast<unsigned int>(c[1]*7.0)*8+static_cast<unsigned int>(c[2]*7.0); } } void IndexedVertexArray::RenderPov(PovState& pov, const std::string& name) { if(entry_list_.empty()) return; - pov.inc() << "mesh2 {\n"; pov.inc() << " vertex_vectors { " << entry_list_.size() << ",\n"; @@ -633,7 +607,7 @@ void IndexedVertexArray::RenderPov(PovState& pov, const std::string& name) pov.inc() << "}\n"; } -void IndexedVertexArray::Clear() +void IndexedVertexArray::Clear() { dirty_=true; ambient_dirty_=true; @@ -642,13 +616,6 @@ void IndexedVertexArray::Clear() tri_index_list_.clear(); line_index_list_.clear(); ntentry_list_.clear(); - ambient_data_.clear(); - use_ambient_=false; -} - -void IndexedVertexArray::Reset() -{ - Clear(); mode_=0x4; poly_mode_=2; lighting_=true; @@ -666,8 +633,8 @@ void IndexedVertexArray::Reset() outline_exp_factor_=0.1; outline_exp_color_=Color(0,0,0); draw_normals_=false; - local_ambient_weight_=0.3; - ambient_occlusion_weight_=1.0; + use_ambient_=false; + ambient_data_.clear(); } void IndexedVertexArray::FlagRefresh() @@ -1095,13 +1062,10 @@ void IndexedVertexArray::copy(const IndexedVertexArray& va) draw_normals_=va.draw_normals_; use_ambient_=va.use_ambient_; ambient_data_=va.ambient_data_; - local_ambient_weight_=va.local_ambient_weight_; - ambient_occlusion_weight_=va.ambient_occlusion_weight_; } bool IndexedVertexArray::prep_buff() { - if(Scene::Instance().InOffscreenMode()) return false; #if OST_SHADER_SUPPORT_ENABLED glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); diff --git a/modules/gfx/src/vertex_array.hh b/modules/gfx/src/vertex_array.hh index 3279eafad..eed4d2a7f 100644 --- a/modules/gfx/src/vertex_array.hh +++ b/modules/gfx/src/vertex_array.hh @@ -134,7 +134,7 @@ class DLLEXPORT_OST_GFX IndexedVertexArray { // add an icosahedral based sphere with the given params to the va void AddIcoSphere(const SpherePrim& prim, unsigned int detail); - void AddCylinder(const CylinderPrim& prim, unsigned int detail,bool cap=false); + void AddCylinder(const CylinderPrim& prim, unsigned int detail); geom::Vec3 GetVert(VertexID id) const; void SetVert(VertexID id, const geom::Vec3& vert); @@ -151,33 +151,13 @@ class DLLEXPORT_OST_GFX IndexedVertexArray { // POVray export void RenderPov(PovState& pov, const std::string& name); - // turn on ambient lighting, first call may take a while - void UseAmbient(bool f); - - // see fraglight_lf_fs shader - void AmbientLocalWeight(float w) {local_ambient_weight_=w;} - // see fraglight_lf_fs shader - void AmbientOcclusionWeight(float w) {ambient_occlusion_weight_=w;} - - Color GetAmbientColor(VertexID id) const; - void SetAmbientColor(VertexID id, const Color& col); - - // only removes the drawing elements + void Clear(); - // removes all elements and resets internal state to default - void Reset(); - - // forces re-calculation of some buffered features void FlagRefresh(); - // for debugging, draw all normals + void CalcNormals(float smoothf); void DrawNormals(bool f); - // NOTE: all methods below could be delegated to the outside, - // using the GetEntries() and Get*Indices() member functions - - // experimental, do not use - void CalcNormals(float smoothf); // experimental, do not use void CalcFullNormals(); // experimental, do not use @@ -186,13 +166,17 @@ class DLLEXPORT_OST_GFX IndexedVertexArray { void NPatch(); // experimental, do not use void SmoothVertices(float smoothf); - + // experimental, do not use + void UseAmbient(bool f); const EntryList& GetEntries() const {return entry_list_;} const IndexList& GetQuadIndices() const {return quad_index_list_;} const IndexList& GetTriIndices() const {return tri_index_list_;} const IndexList& GetLineIndices() const {return line_index_list_;} + Color GetAmbientColor(VertexID id) const; + void SetAmbientColor(VertexID id, const Color& col); + private: bool initialized_; @@ -230,8 +214,6 @@ class DLLEXPORT_OST_GFX IndexedVertexArray { bool use_ambient_; bool ambient_dirty_; std::vector<float> ambient_data_; - float local_ambient_weight_; - float ambient_occlusion_weight_; void copy(const IndexedVertexArray& va); bool prep_buff(); diff --git a/modules/gui/pymod/scene/cpk_widget.py b/modules/gui/pymod/scene/cpk_widget.py index 7df408743..5f6c7de3c 100644 --- a/modules/gui/pymod/scene/cpk_widget.py +++ b/modules/gui/pymod/scene/cpk_widget.py @@ -42,45 +42,28 @@ class CPKWidget(RenderModeWidget): self.sphere_spinbox_ = QtGui.QSpinBox() self.sphere_spinbox_.setRange(min_sphere_detail, max_sphere_detail) - - cpk_mode_label = QtGui.QLabel("Rendering Mode") - self.cpk_mode_ = QtGui.QComboBox() - self.cpk_mode_.addItem("Triangles") - self.cpk_mode_.addItem("Fast Spheres (exp") - self.cpk_mode_.addItem("Fast Spheres ++ (exp)") - + cpk_label = QtGui.QLabel(self.text_) font = cpk_label.font() font.setBold(True) sphere_label = QtGui.QLabel("Sphere Detail") grid = QtGui.QGridLayout() - row=0 - grid.addWidget(cpk_label,row,0,1,1) - row+=1 - grid.addWidget(sphere_label, row, 0, 1, 3) - grid.addWidget(self.sphere_spinbox_, row, 2, 1, 1) - row+=1 - grid.addWidget(cpk_mode_label,row,0,1,1) - grid.addWidget(self.cpk_mode_,row,3,1,2) - row+=1 - grid.setRowStretch(row,1) + grid.addWidget(cpk_label,0,0,1,1) + grid.addWidget(sphere_label, 1, 0, 1, 3) + grid.addWidget(self.sphere_spinbox_, 1, 2, 1, 1) + grid.setRowStretch(2,1) self.setLayout(grid) QtCore.QObject.connect(self.sphere_spinbox_, QtCore.SIGNAL("valueChanged(int)"), self.UpdateSphereDetail) - QtCore.QObject.connect(self.cpk_mode_, QtCore.SIGNAL("currentIndexChanged(int)"), self.UpdateCPKMode) self.setMinimumSize(250,60) def UpdateSphereDetail(self, value): self.GetOptions().SetSphereDetail(value) - - def UpdateCPKMode(self, value): - self.GetOptions().SetCPKMode(value) def UpdateGui(self,options): self.sphere_spinbox_.setValue(options.GetSphereDetail()) - self.cpk_mode_.setCurrentIndex(options.GetCPKMode()) def GetText(self): return self.text_ diff --git a/modules/gui/pymod/scene/hsc_widget.py b/modules/gui/pymod/scene/hsc_widget.py index dd63750b0..b5f716a0a 100644 --- a/modules/gui/pymod/scene/hsc_widget.py +++ b/modules/gui/pymod/scene/hsc_widget.py @@ -23,7 +23,7 @@ from ost import gfx from PyQt4 import QtCore, QtGui from render_mode_widget import RenderModeWidget -# HSC Render Options +#Tube Render Options class HSCWidget(RenderModeWidget): def __init__(self, parent=None): RenderModeWidget.__init__(self, parent) @@ -55,7 +55,7 @@ class HSCWidget(RenderModeWidget): min_profile=0 max_profile=4 - + #########UI########## #Poly Mode @@ -119,41 +119,48 @@ class HSCWidget(RenderModeWidget): font = helix_label.font() font.setBold(True) - helix_mode_label = QtGui.QLabel("Helix Mode") - self.helix_mode_cb_ = QtGui.QComboBox() - self.helix_mode_cb_.addItem("Spiral") - self.helix_mode_cb_.addItem("Cylinder") - + #Helix Radius radius_helix_label = QtGui.QLabel("Width") + self.width_helix_spinbox_ = QtGui.QDoubleSpinBox() self.width_helix_spinbox_.setRange(min_width, max_width) self.width_helix_spinbox_.setDecimals(1) self.width_helix_spinbox_.setSingleStep(0.1) + self.width_helix_slider_ = QtGui.QSlider(QtCore.Qt.Horizontal, self) self.width_helix_slider_.setRange(min_width*10.0, max_width*10.0) self.width_helix_slider_.setTickPosition(QtGui.QSlider.NoTicks) self.width_helix_slider_.setTickInterval(1) + + #Helix Ratio ratio_helix_label = QtGui.QLabel("Thickness") + self.thickness_helix_spinbox_ = QtGui.QDoubleSpinBox() self.thickness_helix_spinbox_.setRange(min_ratio,max_ratio) self.thickness_helix_spinbox_.setDecimals(1) self.thickness_helix_spinbox_.setSingleStep(0.1) + self.thickness_helix_slider_ = QtGui.QSlider(QtCore.Qt.Horizontal, self) self.thickness_helix_slider_.setRange(min_ratio*10.0,max_ratio*10.0) self.thickness_helix_slider_.setTickPosition(QtGui.QSlider.NoTicks) self.thickness_helix_slider_.setTickInterval(1) + + #Helix ECC ecc_helix_label = QtGui.QLabel("ECC") + self.ecc_helix_spinbox_ = QtGui.QDoubleSpinBox() self.ecc_helix_spinbox_.setRange(min_ecc,max_ecc) self.ecc_helix_spinbox_.setDecimals(1) self.ecc_helix_spinbox_.setSingleStep(0.1) + self.ecc_helix_slider_ = QtGui.QSlider(QtCore.Qt.Horizontal, self) self.ecc_helix_slider_.setRange(min_ecc*10,max_ecc*10) self.ecc_helix_slider_.setTickPosition(QtGui.QSlider.NoTicks) self.ecc_helix_slider_.setTickInterval(1) + # Helix Profile Type helix_profile_label = QtGui.QLabel("Helix Profile Type") self.helix_profile_spinbox_ = QtGui.QSpinBox() self.helix_profile_spinbox_.setRange(min_profile, max_profile) @@ -163,47 +170,52 @@ class HSCWidget(RenderModeWidget): font = strand_label.font() font.setBold(1) - strand_mode_label = QtGui.QLabel("Strand Mode") - self.strand_mode_cb_ = QtGui.QComboBox() - self.strand_mode_cb_.addItem("Curved") - self.strand_mode_cb_.addItem("Straight") - + #Strand Radius radius_strand_label = QtGui.QLabel("Width") + self.width_strand_spinbox_ = QtGui.QDoubleSpinBox() self.width_strand_spinbox_.setRange(min_width, max_width) self.width_strand_spinbox_.setDecimals(1) self.width_strand_spinbox_.setSingleStep(0.1) + self.width_strand_slider_ = QtGui.QSlider(QtCore.Qt.Horizontal, self) self.width_strand_slider_.setRange(min_width*10, max_width*10) self.width_strand_slider_.setTickPosition(QtGui.QSlider.NoTicks) self.width_strand_slider_.setTickInterval(1) - + + #Strand Ratio ratio_strand_label = QtGui.QLabel("Thickness") + self.thickness_strand_spinbox_ = QtGui.QDoubleSpinBox() self.thickness_strand_spinbox_.setRange(min_ratio,max_ratio) self.thickness_strand_spinbox_.setDecimals(1) self.thickness_strand_spinbox_.setSingleStep(0.1) + self.thickness_strand_slider_ = QtGui.QSlider(QtCore.Qt.Horizontal, self) self.thickness_strand_slider_.setRange(min_ratio*10,max_ratio*10) self.thickness_strand_slider_.setTickPosition(QtGui.QSlider.NoTicks) self.thickness_strand_slider_.setTickInterval(1) + + #Strand ECC ecc_strand_label = QtGui.QLabel("ECC") + self.ecc_strand_spinbox_ = QtGui.QDoubleSpinBox() self.ecc_strand_spinbox_.setRange(min_ecc,max_ecc) self.ecc_strand_spinbox_.setDecimals(1) self.ecc_strand_spinbox_.setSingleStep(0.1) + self.ecc_strand_slider_ = QtGui.QSlider(QtCore.Qt.Horizontal, self) self.ecc_strand_slider_.setRange(min_ecc*10,max_ecc*10) self.ecc_strand_slider_.setTickPosition(QtGui.QSlider.NoTicks) self.ecc_strand_slider_.setTickInterval(1) + # Strand Profile Type strand_profile_label = QtGui.QLabel("Strand Profile Type") self.strand_profile_spinbox_ = QtGui.QSpinBox() self.strand_profile_spinbox_.setRange(min_profile, max_profile) - # layout row=1 grid = QtGui.QGridLayout() grid.addWidget(poly_mode_label,row,0,1,1) @@ -230,9 +242,6 @@ class HSCWidget(RenderModeWidget): row+=1 grid.addWidget(helix_label, row, 0, 1, 3) row+=1 - grid.addWidget(helix_mode_label,row,0,1,1) - grid.addWidget(self.helix_mode_cb_,row,3,1,2) - row+=1 grid.addWidget(radius_helix_label, row, 0, 1, 1) grid.addWidget(self.width_helix_slider_, row, 1, 1, 3) grid.addWidget(self.width_helix_spinbox_, row, 4, 1, 1) @@ -250,9 +259,6 @@ class HSCWidget(RenderModeWidget): row+=1 grid.addWidget(strand_label, row, 0, 1, 3) row+=1 - grid.addWidget(strand_mode_label,row,0,1,1) - grid.addWidget(self.strand_mode_cb_,row,3,1,2) - row+=1 grid.addWidget(radius_strand_label, row, 0, 1, 1) grid.addWidget(self.width_strand_slider_, row, 1, 1, 3) grid.addWidget(self.width_strand_spinbox_, row, 4, 1, 1) @@ -270,8 +276,7 @@ class HSCWidget(RenderModeWidget): grid.setRowStretch(row+1,1) self.setLayout(grid) - - # signals + QtCore.QObject.connect(self.spline_spinbox_, QtCore.SIGNAL("valueChanged(int)"), self.UpdateSplineDetail) QtCore.QObject.connect(self.arc_spinbox_, QtCore.SIGNAL("valueChanged(int)"), self.UpdateArcDetail) QtCore.QObject.connect(self.poly_mode_cb_, QtCore.SIGNAL("currentIndexChanged(int)"), self.UpdatePolyMode) @@ -282,7 +287,6 @@ class HSCWidget(RenderModeWidget): QtCore.QObject.connect(self.thickness_tube_slider_, QtCore.SIGNAL("valueChanged(int)"), self.UpdateSliderTubeRatio) QtCore.QObject.connect(self.tube_profile_spinbox_, QtCore.SIGNAL("valueChanged(int)"), self.UpdateTubeProfileType) - QtCore.QObject.connect(self.helix_mode_cb_, QtCore.SIGNAL("currentIndexChanged(int)"), self.UpdateHelixMode) QtCore.QObject.connect(self.width_helix_spinbox_, QtCore.SIGNAL("valueChanged(double)"), self.UpdateHelixWidth) QtCore.QObject.connect(self.width_helix_slider_, QtCore.SIGNAL("valueChanged(int)"), self.UpdateSliderHelixWidth) QtCore.QObject.connect(self.thickness_helix_spinbox_, QtCore.SIGNAL("valueChanged(double)"), self.UpdateHelixThickness) @@ -291,7 +295,6 @@ class HSCWidget(RenderModeWidget): QtCore.QObject.connect(self.ecc_helix_slider_, QtCore.SIGNAL("valueChanged(int)"), self.UpdateSliderHelixEcc) QtCore.QObject.connect(self.helix_profile_spinbox_, QtCore.SIGNAL("valueChanged(int)"), self.UpdateHelixProfileType) - QtCore.QObject.connect(self.strand_mode_cb_, QtCore.SIGNAL("currentIndexChanged(int)"), self.UpdateStrandMode) QtCore.QObject.connect(self.width_strand_spinbox_, QtCore.SIGNAL("valueChanged(double)"), self.UpdateStrandWidth) QtCore.QObject.connect(self.width_strand_slider_, QtCore.SIGNAL("valueChanged(int)"), self.UpdateSliderStrandWidth) QtCore.QObject.connect(self.thickness_strand_spinbox_, QtCore.SIGNAL("valueChanged(double)"), self.UpdateStrandThickness) @@ -311,14 +314,10 @@ class HSCWidget(RenderModeWidget): self.UpdateTubeRadiusGui(options.GetTubeRadius()) self.UpdateTubeRatioGui(options.GetTubeRatio()) self.tube_profile_spinbox_.setValue(options.GetTubeProfileType()) - - self.helix_mode_cb_.setCurrentIndex(options.GetHelixMode()) self.UpdateHelixWidthGui(options.GetHelixWidth()) self.UpdateHelixThicknessGui(options.GetHelixThickness()) self.UpdateHelixEccGui(options.GetHelixEcc()) self.helix_profile_spinbox_.setValue(options.GetHelixProfileType()) - - self.strand_mode_cb_.setCurrentIndex(options.GetStrandMode()) self.UpdateStrandWidthGui(options.GetStrandWidth()) self.UpdateStrandThicknessGui(options.GetStrandThickness()) self.UpdateStrandEccGui(options.GetStrandEcc()) @@ -348,9 +347,6 @@ class HSCWidget(RenderModeWidget): def UpdateTubeProfileType(self, value): self.GetOptions().SetTubeProfileType(value) - def UpdateHelixMode(self, value): - self.GetOptions().SetHelixMode(value) - def UpdateHelixWidth(self, value): self.GetOptions().SetHelixWidth(value) @@ -372,9 +368,6 @@ class HSCWidget(RenderModeWidget): def UpdateSliderHelixEcc(self, value): self.GetOptions().SetHelixEcc(value/10.0) - def UpdateStrandMode(self, value): - self.GetOptions().SetStrandMode(value) - def UpdateStrandWidth(self, value): self.GetOptions().SetStrandWidth(value) -- GitLab