diff --git a/examples/gfx/solid.py b/examples/gfx/solid.py new file mode 100644 index 0000000000000000000000000000000000000000..1840068d410410c1b0394ae2becab4ba2dfe6c99 --- /dev/null +++ b/examples/gfx/solid.py @@ -0,0 +1,18 @@ +s=io.LoadSurface("../demos/data/sh2","msms") +scene.Add(gfx.Surface("s",s)) + +# alternative shading mode +scene.SetShadingMode("hf") + +# add outlines to surface +scene["s"].SetOutline(True) +scene["s"].SetOutlineMode(3) + +# turn on solid rendering +scene["s"].solid=True +scene["s"].solid_color=gfx.RGB(0.8,0.8,0.7) + +scene.AutoAutoslab(False) +scene.far=170 +scene.near=100 +scene.fog=False diff --git a/modules/gfx/pymod/export_gfx_obj.cc b/modules/gfx/pymod/export_gfx_obj.cc index 5f9ad7d1a4ecfc29a4b1aadf18b42c4d4f81e6e0..07d845636676fbd2c381ee1bbab25a4bf8aa0ca4 100644 --- a/modules/gfx/pymod/export_gfx_obj.cc +++ b/modules/gfx/pymod/export_gfx_obj.cc @@ -155,6 +155,8 @@ void export_GfxObj() .def("SetOpacity",&GfxObjBase::SetOpacity) .def("GetOpacity",&GfxObjBase::GetOpacity) .add_property("opacity",&GfxObjBase::GetOpacity,&GfxObjBase::SetOpacity) + .add_property("solid",&GfxObjBase::GetSolid,&GfxObjBase::SetSolid) + .add_property("solid_color",&GfxObjBase::GetSolidColor,&GfxObjBase::SetSolidColor) COLOR_BY_DEF() ; diff --git a/modules/gfx/src/gfx_object.cc b/modules/gfx/src/gfx_object.cc index f7e3b06a5af9a5b1962156db728b4556e331c98c..63003cd5bce9481772ed5d8f3f1e8aa919e2e7c8 100644 --- a/modules/gfx/src/gfx_object.cc +++ b/modules/gfx/src/gfx_object.cc @@ -64,6 +64,8 @@ GfxObj::GfxObj(const String& name): #else outline_mode_(1), #endif + solid_(false), + solid_color_(RGB(0.7,0.7,0.7)), c_ops_(), labels_(), use_occlusion_(false) @@ -128,6 +130,8 @@ void GfxObj::RenderGL(RenderPass pass) // there really needs to be a central place // where the va attributes are re-applied va_.SetOpacity(opacity_); + va_.SetSolid(solid_); + va_.SetSolidColor(solid_color_); } } if(IsVisible()) { @@ -375,6 +379,20 @@ void GfxObj::SetOpacity(float o) Scene::Instance().RequestRedraw(); } +void GfxObj::SetSolid(bool f) +{ + solid_=f; + va_.SetSolid(solid_); + Scene::Instance().RequestRedraw(); +} + +void GfxObj::SetSolidColor(const Color& c) +{ + solid_color_=c; + va_.SetSolidColor(solid_color_); + Scene::Instance().RequestRedraw(); +} + void GfxObj::ColorBy(const mol::EntityView& ev, const String& prop, const Gradient& g, float minv, float maxv) diff --git a/modules/gfx/src/gfx_object.hh b/modules/gfx/src/gfx_object.hh index fc906c35c9fdb7c563417c6785e5023d2dabe594..0b70065d7f820ca924ef07b3d2ad3005fe4e71b2 100644 --- a/modules/gfx/src/gfx_object.hh +++ b/modules/gfx/src/gfx_object.hh @@ -88,6 +88,11 @@ public: virtual Color GetOutlineExpandColor() const; virtual void SetOpacity(float f); virtual float GetOpacity() const {return opacity_;} + virtual void SetSolid(bool f); + virtual bool GetSolid() const {return solid_;} + virtual void SetSolidColor(const Color& c); + virtual Color GetSolidColor() const {return solid_color_;} + virtual void ColorBy(const mol::EntityView& ev, const String& prop, const Gradient& g, float minv, float maxv); @@ -242,6 +247,9 @@ public: bool outline_flag_; int outline_mode_; + bool solid_; + Color solid_color_; + boost::ptr_vector<gfx::ColorOp> c_ops_; TextPrimList labels_; diff --git a/modules/gfx/src/gfx_object_base.hh b/modules/gfx/src/gfx_object_base.hh index eb6c7c21743805e237377bc64e15ced0d61f3885..448de0cf2687781045e7b59bc72b145be0ee1c2d 100644 --- a/modules/gfx/src/gfx_object_base.hh +++ b/modules/gfx/src/gfx_object_base.hh @@ -117,6 +117,11 @@ class DLLEXPORT_OST_GFX GfxObjBase: public GfxNode /// \brief returns a value smaller than 1.0 if transparency is used in this object virtual float GetOpacity() const = 0; + virtual void SetSolid(bool f) = 0; + virtual bool GetSolid() const = 0; + virtual void SetSolidColor(const Color& c) = 0; + virtual Color GetSolidColor() const = 0; + /// \brief color each component based on the gradient-mapped property of /// the given entity virtual void ColorBy(const mol::EntityView& ev, diff --git a/modules/gfx/src/scene.hh b/modules/gfx/src/scene.hh index 02b3b3367b5933a10162d094bf89bc561b76a74e..f6f4c87f1544b091d0e51777b7b254501ae4d22b 100644 --- a/modules/gfx/src/scene.hh +++ b/modules/gfx/src/scene.hh @@ -174,6 +174,8 @@ class DLLEXPORT_OST_GFX Scene { // \brief get the field of view float GetFOV() const; + float GetAspect() const {return aspect_ratio_;} + /// \brief offset between near clipping plane and start of fog void SetFogNearOffset(float o); diff --git a/modules/gfx/src/vertex_array.cc b/modules/gfx/src/vertex_array.cc index b9c45e5a7ce54f274b2b1e0b029f100fd81772ec..155417b65e2cb2080bd6a5230ee30b936c3f5134 100644 --- a/modules/gfx/src/vertex_array.cc +++ b/modules/gfx/src/vertex_array.cc @@ -141,7 +141,6 @@ void IndexedVertexArray::SetOutlineMaterial(const Material& m) void IndexedVertexArray::SetOutlineExpandFactor(float f) { outline_exp_factor_=f;} void IndexedVertexArray::SetOutlineExpandColor(const Color& c) {outline_exp_color_=c;} - VertexID IndexedVertexArray::Add(const Vec3& vert, const Vec3& norm, const Color& col, @@ -494,7 +493,7 @@ void IndexedVertexArray::RenderGL() } else { glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); } - if(cull_face_) { + if(cull_face_ && !solid_) { glEnable(GL_CULL_FACE); } else { glDisable(GL_CULL_FACE); @@ -699,6 +698,8 @@ void IndexedVertexArray::Reset() outline_mat_update_=true; outline_exp_factor_=0.1; outline_exp_color_=Color(0,0,0); + solid_=false; + solid_color_=RGB(1,1,1); draw_normals_=false; use_tex_=false; } @@ -1095,6 +1096,8 @@ void IndexedVertexArray::copy(const IndexedVertexArray& va) outline_mat_update_=true; outline_exp_factor_=va.outline_exp_factor_; outline_exp_color_=va.outline_exp_color_; + solid_=va.solid_; + solid_color_=va.solid_color_; draw_normals_=va.draw_normals_; use_tex_=va.use_tex_; } @@ -1174,6 +1177,14 @@ bool IndexedVertexArray::prep_buff() void IndexedVertexArray::draw_ltq(bool use_buff) { + if(solid_) { + glClearStencil(0x0); + glClear(GL_STENCIL_BUFFER_BIT); + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS,0x0,0x1); + glStencilOp(GL_KEEP,GL_INVERT,GL_INVERT); + } + if(use_buff && !Scene::Instance().InOffscreenMode()) { #if OST_SHADER_SUPPORT_ENABLED #if 0 @@ -1230,8 +1241,35 @@ void IndexedVertexArray::draw_ltq(bool use_buff) glDrawElements(GL_LINES,line_index_list_.size(),GL_UNSIGNED_INT,&line_index_list_[0]); } } + + if(solid_) { + glStencilFunc(GL_EQUAL,0x1,0x1); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + float fov=Scene::Instance().GetFOV()*M_PI/180.0; + float znear=Scene::Instance().GetNear(); + float aspect=Scene::Instance().GetAspect(); + float rh=2.0*fabs(tan(fov)*znear); + float rw=rh*aspect; + float rz=-znear-0.1; + + glDisable(GL_LIGHTING); + + glBegin(GL_TRIANGLE_STRIP); + glColor3fv(solid_color_); + glNormal3f(0,0,1); + glVertex3f(-rw,-rh,rz); + glVertex3f(rw,-rh,rz); + glVertex3f(-rw,rh,rz); + glVertex3f(rw,rh,rz); + glEnd(); + glDisable(GL_STENCIL_TEST); + glPopMatrix(); + } } - + void IndexedVertexArray::draw_p(bool use_buff) { if(use_buff && !Scene::Instance().InOffscreenMode()) { @@ -1254,115 +1292,115 @@ void IndexedVertexArray::draw_p(bool use_buff) namespace { -struct AALineEntry { - float p0[3], p1[3]; - float edge0[3],edge1[3],edge2[3],edge3[3]; - float c0[4], c1[4]; - float z; -}; + struct AALineEntry { + float p0[3], p1[3]; + float edge0[3],edge1[3],edge2[3],edge3[3]; + float c0[4], c1[4]; + float z; + }; -typedef std::vector<AALineEntry> AALineList; + typedef std::vector<AALineEntry> AALineList; -struct AALineEntryLess -{ - bool operator()(const AALineEntry& e1, const AALineEntry& e2) + struct AALineEntryLess { - return e1.z<e2.z; - } -}; + bool operator()(const AALineEntry& e1, const AALineEntry& e2) + { + return e1.z<e2.z; + } + }; -/* - Adapted after Chan and Durand, "Fast Prefiltered Lines", - in GPU Gems 2 -*/ -void render_aalines(AALineList& line_list, float w, float r) -{ + /* + Adapted after Chan and Durand, "Fast Prefiltered Lines", + in GPU Gems 2 + */ + void render_aalines(AALineList& line_list, float w, float r) + { #if OST_SHADER_SUPPORT_ENABLED - static GLuint table_tex_id=0; - std::vector<unsigned char> tex_table(32); + static GLuint table_tex_id=0; + std::vector<unsigned char> tex_table(32); - if(table_tex_id==0) { - for(int i=0;i<32;++i) { - float x=static_cast<float>(i)/31.0; - tex_table[31-i]=static_cast<unsigned char>(255.0*exp(-4.0*x*x)); + if(table_tex_id==0) { + for(int i=0;i<32;++i) { + float x=static_cast<float>(i)/31.0; + tex_table[31-i]=static_cast<unsigned char>(255.0*exp(-4.0*x*x)); + } + glGenTextures(1,&table_tex_id); + glBindTexture(GL_TEXTURE_1D,table_tex_id); + glPixelStorei(GL_UNPACK_ALIGNMENT,1); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexImage1D(GL_TEXTURE_1D,0,GL_LUMINANCE,32,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,&tex_table[0]); } - glGenTextures(1,&table_tex_id); - glBindTexture(GL_TEXTURE_1D,table_tex_id); - glPixelStorei(GL_UNPACK_ALIGNMENT,1); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexImage1D(GL_TEXTURE_1D,0,GL_LUMINANCE,32,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,&tex_table[0]); - } - std::sort(line_list.begin(),line_list.end(),AALineEntryLess()); - - Shader::Instance().PushProgram(); - Shader::Instance().Activate("aaline"); + std::sort(line_list.begin(),line_list.end(),AALineEntryLess()); - glLineWidth(ceil((2.0f*r+w)*1.5)); + Shader::Instance().PushProgram(); + Shader::Instance().Activate("aaline"); - glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT); - glDisable(GL_NORMALIZE); - glDisable(GL_CULL_FACE); - glDisable(GL_LIGHTING); - glDisable(GL_COLOR_MATERIAL); - //glDisable(GL_DEPTH_TEST); - glDisable(GL_LINE_SMOOTH); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glDepthMask(0); - Shader::Instance().UpdateState(); - - GLuint cpr = Shader::Instance().GetCurrentProgram(); - GLint edge0_id = glGetUniformLocation(cpr,"edge0"); - GLint edge1_id = glGetUniformLocation(cpr,"edge1"); - GLint edge2_id = glGetUniformLocation(cpr,"edge2"); - GLint edge3_id = glGetUniformLocation(cpr,"edge3"); - GLint table_id = glGetUniformLocation(cpr,"table"); - - glActiveTexture(GL_TEXTURE0); - glDisable(GL_TEXTURE_2D); - glEnable(GL_TEXTURE_1D); - glBindTexture(GL_TEXTURE_1D,table_tex_id); - glUniform1i(table_id,0); - - for(AALineList::iterator it=line_list.begin(); - it!=line_list.end();++it) { - glUniform3fv(edge0_id,1,it->edge0); - glUniform3fv(edge1_id,1,it->edge1); - glUniform3fv(edge2_id,1,it->edge2); - glUniform3fv(edge3_id,1,it->edge3); - // glUniform cannot be inside a glBegin / glEnd - glBegin(GL_LINES); - glColor4fv(it->c0); - glVertex3fv(it->p0); - glColor4fv(it->c1); - glVertex3fv(it->p1); - glEnd(); - } + glLineWidth(ceil((2.0f*r+w)*1.5)); - glPopAttrib(); + glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT); + glDisable(GL_NORMALIZE); + glDisable(GL_CULL_FACE); + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + //glDisable(GL_DEPTH_TEST); + glDisable(GL_LINE_SMOOTH); + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glDepthMask(0); + Shader::Instance().UpdateState(); + + GLuint cpr = Shader::Instance().GetCurrentProgram(); + GLint edge0_id = glGetUniformLocation(cpr,"edge0"); + GLint edge1_id = glGetUniformLocation(cpr,"edge1"); + GLint edge2_id = glGetUniformLocation(cpr,"edge2"); + GLint edge3_id = glGetUniformLocation(cpr,"edge3"); + GLint table_id = glGetUniformLocation(cpr,"table"); - Shader::Instance().PopProgram(); + glActiveTexture(GL_TEXTURE0); + glDisable(GL_TEXTURE_2D); + glEnable(GL_TEXTURE_1D); + glBindTexture(GL_TEXTURE_1D,table_tex_id); + glUniform1i(table_id,0); + + for(AALineList::iterator it=line_list.begin(); + it!=line_list.end();++it) { + glUniform3fv(edge0_id,1,it->edge0); + glUniform3fv(edge1_id,1,it->edge1); + glUniform3fv(edge2_id,1,it->edge2); + glUniform3fv(edge3_id,1,it->edge3); + // glUniform cannot be inside a glBegin / glEnd + glBegin(GL_LINES); + glColor4fv(it->c0); + glVertex3fv(it->p0); + glColor4fv(it->c1); + glVertex3fv(it->p1); + glEnd(); + } + + glPopAttrib(); + + Shader::Instance().PopProgram(); #endif -} + } -Vec3 make_aaline_edge(const Vec2& c1, const Vec2& c0, float s) -{ - Vec3 nrvo(c1[1]-c0[1],c0[0]-c1[0],c1[0]*c0[1]-c0[0]*c1[1]); - nrvo*=1.0/(s*Length(c1-c0)); - return nrvo; -} + Vec3 make_aaline_edge(const Vec2& c1, const Vec2& c0, float s) + { + Vec3 nrvo(c1[1]-c0[1],c0[0]-c1[0],c1[0]*c0[1]-c0[0]*c1[1]); + nrvo*=1.0/(s*Length(c1-c0)); + return nrvo; + } } - + void IndexedVertexArray::draw_aalines() { #if OST_SHADER_SUPPORT_ENABLED float w=0.5*line_width_; float r=w; float hwr = 0.5*w+r; - + AALineList line_list; for(unsigned int i=0;i<line_index_list_.size();i+=2) { Entry& ve0 = entry_list_[line_index_list_[i]]; @@ -1381,26 +1419,26 @@ void IndexedVertexArray::draw_aalines() Vec3 e1=make_aaline_edge(c1,c2,r); Vec3 e2=make_aaline_edge(c2,c3,r); Vec3 e3=make_aaline_edge(c3,c0,r); - + // TODO: it should be possible to avoid the unproject and // pass the projected coordinates directly to GL, setting // modelview and projection to unity; requires handling of // the viewport though! Vec3 np1=Scene::Instance().UnProject(q0-Vec3(hwr*d),false); Vec3 np2=Scene::Instance().UnProject(q1+Vec3(hwr*d),false); - + AALineEntry le={{np1[0],np1[1],np1[2]}, - {np2[0],np2[1],np2[2]}, - {e0[0],e0[1],e0[2]}, - {e1[0],e1[1],e1[2]}, - {e2[0],e2[1],e2[2]}, - {e3[0],e3[1],e3[2]}, - {ve0.c[0],ve0.c[1],ve0.c[2],ve0.c[3]}, - {ve1.c[0],ve1.c[1],ve1.c[2],ve1.c[3]}, - -0.5*(q0[2]+q1[2])}; + {np2[0],np2[1],np2[2]}, + {e0[0],e0[1],e0[2]}, + {e1[0],e1[1],e1[2]}, + {e2[0],e2[1],e2[2]}, + {e3[0],e3[1],e3[2]}, + {ve0.c[0],ve0.c[1],ve0.c[2],ve0.c[3]}, + {ve1.c[0],ve1.c[1],ve1.c[2],ve1.c[3]}, + -0.5*(q0[2]+q1[2])}; line_list.push_back(le); } - + render_aalines(line_list,w,r); #endif } @@ -1434,11 +1472,11 @@ geom::AlignedCuboid IndexedVertexArray::GetBoundingBox() const return geom::AlignedCuboid(geom::Vec3(0,0,0),geom::Vec3(0,0,0)); } else { geom::Vec3 minc(std::numeric_limits<float>::max(), - std::numeric_limits<float>::max(), - std::numeric_limits<float>::max()); + std::numeric_limits<float>::max(), + std::numeric_limits<float>::max()); geom::Vec3 maxc(-std::numeric_limits<float>::max(), - -std::numeric_limits<float>::max(), - -std::numeric_limits<float>::max()); + -std::numeric_limits<float>::max(), + -std::numeric_limits<float>::max()); for(EntryList::const_iterator it=entry_list_.begin();it!=entry_list_.end();++it) { geom::Vec3 p(it->v[0],it->v[1],it->v[2]); minc=geom::Min(minc,p); diff --git a/modules/gfx/src/vertex_array.hh b/modules/gfx/src/vertex_array.hh index ee63c939aae475959cfa12963b730f7326392df6..539d871b775c6219a397c0ca4795a23baa8c402b 100644 --- a/modules/gfx/src/vertex_array.hh +++ b/modules/gfx/src/vertex_array.hh @@ -117,6 +117,11 @@ class DLLEXPORT_OST_GFX IndexedVertexArray { void SetOutlineExpandColor(const Color& c); Color GetOutlineExpandColor() const {return outline_exp_color_;} + void SetSolid(bool f) {solid_=f;} + bool GetSolid() const {return solid_;} + void SetSolidColor(const Color& c) {solid_color_=c;} + bool GetSolidcolor() const {return solid_color_;} + // vertex, normal, color and texcoord (T2F_C4F_N3F_V3F) VertexID Add(const geom::Vec3& vert, const geom::Vec3& norm, const Color& col, const geom::Vec2& tex=geom::Vec2()); @@ -233,7 +238,8 @@ class DLLEXPORT_OST_GFX IndexedVertexArray { unsigned int outline_mat_dlist_; float outline_exp_factor_; Color outline_exp_color_; - + bool solid_; + Color solid_color_; bool draw_normals_; bool use_tex_;