diff --git a/modules/gfx/pymod/CMakeLists.txt b/modules/gfx/pymod/CMakeLists.txt index f77be27fc82cce5dd22cba2dcc8cc4d520c55688..0fcc9a8ed304044934f7c7e2b67a51ff873c3f5c 100644 --- a/modules/gfx/pymod/CMakeLists.txt +++ b/modules/gfx/pymod/CMakeLists.txt @@ -7,6 +7,7 @@ set(OST_GFX_PYMOD_SOURCES export_entity.cc export_surface.cc export_primitives.cc + export_primlist.cc export_scene_observer.cc export_render_options.cc export_color_ops.cc diff --git a/modules/gfx/pymod/__init__.py b/modules/gfx/pymod/__init__.py index e9276ead1f891aaf801571c8084756bb4a818ade..8fbbedeaff78baf5424bdeebe80bba9db094f3b2 100644 --- a/modules/gfx/pymod/__init__.py +++ b/modules/gfx/pymod/__init__.py @@ -59,11 +59,11 @@ def Stereo(mode,flip=None,alg=None): :type param: int """ if(flip): - _gfx.Scene().SetStereoFlip(flip) + Scene().SetStereoFlip(flip) if(alg): - _gfx.Scene().SetStereoAlg(alg) + Scene().SetStereoAlg(alg) - _gfx.Scene().SetStereoMode(mode) + Scene().SetStereoMode(mode) def FitToScreen(gfx_ent, width=None, height=None, margin=0.05): """ @@ -184,3 +184,59 @@ def _Match(scene, pattern="*"): return GfxNodeListProxy(_Recurse("", Scene().root_node, pattern)) SceneSingleton.Match=_Match + +def _to_vec3(p): + import ost.geom + if isinstance(p,ost.geom.Vec3): + return p + else: + try: + return ost.geom.Vec3(p[0],p[1],p[2]) + except: + raise TypeError("expected either a sequence or a geom.Vec3 object") + + +def _primlist_add_point(self,pos,col=None): + pos=_to_vec3(pos) + if not col: + col=WHITE + self._add_point(pos,col) + +def _primlist_add_line(self,pos1,pos2,col=None,col1=None,col2=None): + pos1=_to_vec3(pos1) + pos2=_to_vec3(pos2) + if not col: + col=WHITE + if not col1: + col1=col + if not col2: + col2=col + self._add_line(pos1,pos2,col1,col2) + +def _primlist_add_sphere(self,cen,rad=1.0,col=None): + pos=_to_vec3(cen) + if not col: + col=WHITE + self._add_sphere(pos,rad,col) + +def _primlist_add_cyl(self,pos1,pos2,rad=None,rad1=None,rad2=None,col=None,col1=None,col2=None): + pos1=_to_vec3(pos1) + pos2=_to_vec3(pos2) + if rad is None: + rad=1.0 + if rad1 is None: + rad1=rad + if rad2 is None: + rad2=rad + if not col: + col=WHITE + if not col1: + col1=col + if not col2: + col2=col + self._add_cyl(pos1,pos2,rad1,rad2,col1,col2) + +PrimList.AddPoint=_primlist_add_point +PrimList.AddLine=_primlist_add_line +PrimList.AddSphere=_primlist_add_sphere +PrimList.AddCyl=_primlist_add_cyl diff --git a/modules/gfx/pymod/export_primlist.cc b/modules/gfx/pymod/export_primlist.cc new file mode 100644 index 0000000000000000000000000000000000000000..1456d157e595fc5cfe2467ecbfe048e099a8282e --- /dev/null +++ b/modules/gfx/pymod/export_primlist.cc @@ -0,0 +1,39 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#include <boost/python.hpp> +using namespace boost::python; + +#include <ost/gfx/prim_list.hh> +using namespace ost; +using namespace ost::gfx; + +void export_primlist() +{ + class_<PrimList, bases<GfxObj>, PrimListP, boost::noncopyable>("PrimList", init<const String& >()) + .def("Clear",&PrimList::Clear) + .def("_add_line",&PrimList::AddLine) + .def("_add_point",&PrimList::AddPoint) + .def("_add_sphere",&PrimList::AddSphere) + .def("_add_cyl",&PrimList::AddCyl) + .def("SetColor",&PrimList::SetColor) + .def("SetDiameter",&PrimList::SetDiameter) + .def("SetRadius",&PrimList::SetRadius) + ; + +} diff --git a/modules/gfx/pymod/wrap_gfx.cc b/modules/gfx/pymod/wrap_gfx.cc index c6b37a25baee7e27adbd42eeb54df4024e818785..4be1d63f23896a87f29549a6b8a287c0d0f6463d 100644 --- a/modules/gfx/pymod/wrap_gfx.cc +++ b/modules/gfx/pymod/wrap_gfx.cc @@ -34,6 +34,7 @@ extern void export_GfxNode(); extern void export_GfxObj(); extern void export_Entity(); extern void export_Surface(); +extern void export_primlist(); extern void export_primitives(); #if OST_IMG_ENABLED extern void export_Map(); @@ -134,17 +135,8 @@ BOOST_PYTHON_MODULE(_ost_gfx) class_<InputEvent>("InputEvent", init<InputDevice, InputCommand, float>()) .def(init<InputDevice,InputCommand,int,int,float>()) ; - class_<PrimList, bases<GfxObj>, PrimListP, boost::noncopyable>("PrimList", init<const String& >()) - .def("Clear",&PrimList::Clear) - .def("AddLine",&PrimList::AddLine) - .def("AddPoint",&PrimList::AddPoint) - .def("SetColor",&PrimList::SetColor) - .def("SetDiameter",&PrimList::SetDiameter) - .def("SetRadius",&PrimList::SetRadius) - ; class_<GfxTestObj, bases<GfxObj>, boost::noncopyable>("GfxTestObj", init<>()); - class_<Color>("Color",init<>()) .def(init<float, float, float, optional<float> >()) @@ -189,6 +181,7 @@ BOOST_PYTHON_MODULE(_ost_gfx) #endif export_primitives(); + export_primlist(); } diff --git a/modules/gfx/src/gfx_prim.hh b/modules/gfx/src/gfx_prim.hh index c88a92368de0b9bc15ae5319e0e535e9569a96f7..d3b97cec8bb5bf6c7b9c249d0ddaf23507151305 100644 --- a/modules/gfx/src/gfx_prim.hh +++ b/modules/gfx/src/gfx_prim.hh @@ -48,19 +48,46 @@ typedef std::vector<SpherePrim> SpherePrimList; struct CylinderPrim { CylinderPrim(): - start(),end(),radius(1.0),color1(),color2(),length(1.0),rotmat(),rotmat_t() + start(), end(), + radius1(1.0), radius2(1.0), + color1(), color2(), + 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() + start(st), end(en), + radius1(rad), radius2(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), + radius1(rad), radius2(rad), + color1(col1), color2(col2), + length(geom::Length(end-start)), rotmat(), rotmat_t() + { + calc_rotmat(); + } + + CylinderPrim(const geom::Vec3& st, const geom::Vec3& en, float rad1, float rad2, const Color& col): + start(st), end(en), + radius1(rad1), radius2(rad2), + color1(col), color2(col), + length(geom::Length(end-start)), rotmat(), rotmat_t() + { + calc_rotmat(); + } + + CylinderPrim(const geom::Vec3& st, const geom::Vec3& en, float rad1, float rad2, const Color& col1, const Color& col2): + start(st), end(en), + radius1(rad1), radius2(rad2), + color1(col1), color2(col2), + length(geom::Length(end-start)), rotmat(), rotmat_t() { calc_rotmat(); } @@ -68,7 +95,7 @@ struct CylinderPrim { void calc_rotmat(); geom::Vec3 start,end; - float radius; + float radius1,radius2; Color color1, color2; float length; geom::Mat3 rotmat; @@ -77,7 +104,6 @@ struct CylinderPrim { typedef std::vector<CylinderPrim> CylinderPrimList; - struct TextPrim { TextPrim(): str(""), position(),color(),points(1.0) {} TextPrim(const String& s, const geom::Vec3& p, const Color& c, float ps): diff --git a/modules/gfx/src/prim_list.cc b/modules/gfx/src/prim_list.cc index 5486ccaed82dcecbce81d9d3b56fcc4a00abe314..95ed64cfb640e5390e3e2871dff1af381797a4bb 100644 --- a/modules/gfx/src/prim_list.cc +++ b/modules/gfx/src/prim_list.cc @@ -33,19 +33,36 @@ PrimList::PrimList(const String& name): GfxObj(name), points_(), lines_(), - radius_(0.5), + spheres_(), + cyls_(), sphere_detail_(4), - arc_detail_(4) + arc_detail_(4), + simple_va_() {} void PrimList::Clear() { points_.clear(); lines_.clear(); + spheres_.clear(); + cyls_.clear(); Scene::Instance().RequestRedraw(); this->FlagRebuild(); } + +geom::AlignedCuboid PrimList::GetBoundingBox() const +{ + geom::Vec3 minc(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()); + ProcessLimits(minc,maxc,mol::Transform()); + return geom::AlignedCuboid(minc,maxc); +} + void PrimList::ProcessLimits(geom::Vec3& minc, geom::Vec3& maxc, const mol::Transform& tf) const { @@ -62,6 +79,19 @@ void PrimList::ProcessLimits(geom::Vec3& minc, geom::Vec3& maxc, minc=geom::Min(minc,tpos); maxc=geom::Max(maxc,tpos); } + for(PointEntryList::const_iterator it=spheres_.begin();it!=spheres_.end();++it) { + geom::Vec3 tpos = tf.Apply(it->pos); + minc=geom::Min(minc,tpos); + maxc=geom::Max(maxc,tpos); + } + for(LineEntryList::const_iterator it=cyls_.begin();it!=cyls_.end();++it) { + geom::Vec3 tpos = tf.Apply(it->pos1); + minc=geom::Min(minc,tpos); + maxc=geom::Max(maxc,tpos); + tpos = tf.Apply(it->pos2); + minc=geom::Min(minc,tpos); + maxc=geom::Max(maxc,tpos); + } minc-=1.0; maxc+=1.0; } @@ -69,71 +99,45 @@ void PrimList::ProcessLimits(geom::Vec3& minc, geom::Vec3& maxc, geom::Vec3 PrimList::GetCenter() const { geom::Vec3 cen; + size_t sum=0; for(PointEntryList::const_iterator it=points_.begin();it!=points_.end();++it) { cen+=it->pos; } + sum+=points_.size(); for(LineEntryList::const_iterator it=lines_.begin();it!=lines_.end();++it) { cen+=0.5*(it->pos1+it->pos2); } - if(!lines_.empty() || !points_.empty()) { - cen/=static_cast<float>(points_.size()+lines_.size()); + sum+=lines_.size(); + for(PointEntryList::const_iterator it=spheres_.begin();it!=spheres_.end();++it) { + cen+=it->pos; + } + sum+=spheres_.size(); + for(LineEntryList::const_iterator it=cyls_.begin();it!=cyls_.end();++it) { + cen+=0.5*(it->pos1+it->pos2); + } + sum+=cyls_.size(); + if(sum>0) { + cen/=static_cast<float>(sum); } return cen; } void PrimList::OnRenderModeChange() { - if(GetRenderMode()==RenderMode::CUSTOM) { - render_custom(); - } else { - render_simple(); - } - // this does not work - //GfxObj::OnRenderModeChange(); + // noop } void PrimList::CustomPreRenderGL(bool flag) { - if(flag) { - if(GetRenderMode()==RenderMode::CUSTOM) { - render_custom(); - } else { - render_simple(); - } - } -} - -namespace { - -struct AALineEntry { - float p0[3],p1[3]; - float edge0[3],edge1[3],edge2[3],edge3[3]; - float color[4]; - float z; -}; - -geom::Vec3 make_edge(const geom::Vec2& c1, const geom::Vec2& c0, float s) -{ - geom::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; -} - -struct AALineEntryLess -{ - bool operator()(const AALineEntry& e1, const AALineEntry& e2) - { - // provides back-to-front sorting - return e1.z<e2.z; - } -}; - + prep_va(); + prep_simple_va(); } void PrimList::CustomRenderGL(RenderPass pass) { if(pass==STANDARD_RENDER_PASS || pass==TRANSPARENT_RENDER_PASS) { va_.RenderGL(); + simple_va_.RenderGL(); } } @@ -143,44 +147,62 @@ void PrimList::CustomRenderPov(PovState& pov) pov.write_merge_or_union(GetName()); for(PointEntryList::const_iterator it=points_.begin();it!=points_.end();++it) { - pov.write_sphere(it->pos,radius_,it->color,GetName()); + pov.write_sphere(it->pos,0.1,it->col,GetName()); } for(LineEntryList::const_iterator it=lines_.begin();it!=lines_.end();++it) { - pov.write_sphere(it->pos1,radius_,it->color,GetName()); - pov.write_sphere(it->pos2,radius_,it->color,GetName()); - pov.write_cyl(it->pos1,it->pos2,radius_,it->color,GetName(),true); + pov.write_sphere(it->pos1,0.1,it->col1,GetName()); + pov.write_sphere(it->pos2,0.1,it->col2,GetName()); + pov.write_cyl(it->pos1,it->pos2,0.1,it->col1,GetName(),true); + } + for(PointEntryList::const_iterator it=spheres_.begin();it!=spheres_.end();++it) { + pov.write_sphere(it->pos,it->rad,it->col,GetName()); + } + for(LineEntryList::const_iterator it=cyls_.begin();it!=cyls_.end();++it) { + pov.write_sphere(it->pos1,it->rad1,it->col1,GetName()); + pov.write_sphere(it->pos2,it->rad2,it->col2,GetName()); + pov.write_cyl(it->pos1,it->pos2,it->rad1,it->col1,GetName(),true); } pov.inc() << " }\n"; } -void PrimList::AddPoint(geom::Vec3& p, const Color& col) +void PrimList::AddPoint(const geom::Vec3& p, const Color& col) { - points_.push_back(PointEntry(p,col)); + points_.push_back(PointEntry(p, 0.0, col)); Scene::Instance().RequestRedraw(); FlagRebuild(); } -void PrimList::AddLine(geom::Vec3& p1, geom::Vec3& p2, const Color& col) +void PrimList::AddLine(const geom::Vec3& p1, const geom::Vec3& p2, const Color& col1, const Color& col2) { - lines_.push_back(LineEntry(p1,p2,col)); + lines_.push_back(LineEntry(p1,p2,0.0,0.0,col1,col2)); Scene::Instance().RequestRedraw(); FlagRebuild(); } -void PrimList::SetDiameter(float d) +void PrimList::AddSphere(const geom::Vec3& c, float r, const Color& col) { - radius_=d*0.5; + spheres_.push_back(PointEntry(c, r, col)); Scene::Instance().RequestRedraw(); FlagRebuild(); } -void PrimList::SetRadius(float r) +void PrimList::AddCyl(const geom::Vec3& p1, const geom::Vec3& p2, float r1, float r2, const Color& col1, const Color& col2) { - radius_=r; + cyls_.push_back(LineEntry(p1, p2, r1, r2, col1, col2)); Scene::Instance().RequestRedraw(); FlagRebuild(); } +void PrimList::SetDiameter(float d) +{ + LOG_WARNING("PrimList::SetDiameter is defunct"); +} + +void PrimList::SetRadius(float r) +{ + LOG_WARNING("PrimList::SetDiameter is defunct"); +} + void PrimList::SetSphereDetail(unsigned int d) { sphere_detail_=d; @@ -197,8 +219,19 @@ void PrimList::SetArcDetail(unsigned int d) void PrimList::SetColor(const Color& c) { + for(PointEntryList::iterator it=points_.begin();it!=points_.end();++it) { + it->col=c; + } for(LineEntryList::iterator it=lines_.begin();it!=lines_.end();++it) { - it->color=c; + it->col1=c; + it->col2=c; + } + for(PointEntryList::iterator it=spheres_.begin();it!=spheres_.end();++it) { + it->col=c; + } + for(LineEntryList::iterator it=cyls_.begin();it!=cyls_.end();++it) { + it->col1=c; + it->col2=c; } Scene::Instance().RequestRedraw(); FlagRebuild(); @@ -208,28 +241,29 @@ void PrimList::SetColor(const Color& c) //////////////////////////////// // private methods -void PrimList::render_simple() +void PrimList::prep_simple_va() { - va_.Clear(); - va_.SetLighting(false); - va_.SetCullFace(false); - va_.SetColorMaterial(false); - va_.SetMode(0x3); - va_.SetTwoSided(true); - va_.SetAALines(GetAALines()); + simple_va_.Clear(); + simple_va_.SetLighting(false); + simple_va_.SetCullFace(false); + simple_va_.SetColorMaterial(false); + simple_va_.SetMode(0x3); + simple_va_.SetTwoSided(true); + simple_va_.SetAALines(GetAALines()); + simple_va_.SetOpacity(GetOpacity()); for(PointEntryList::const_iterator it=points_.begin();it!=points_.end();++it) { - va_.Add(it->pos,geom::Vec3(),it->color); + simple_va_.Add(it->pos,geom::Vec3(),it->col); } for(LineEntryList::const_iterator it=lines_.begin();it!=lines_.end();++it) { - VertexID id0 = va_.Add(it->pos1,geom::Vec3(),it->color); - VertexID id1 = va_.Add(it->pos2,geom::Vec3(),it->color); - va_.AddLine(id0,id1); + VertexID id0 = simple_va_.Add(it->pos1,geom::Vec3(),it->col1); + VertexID id1 = simple_va_.Add(it->pos2,geom::Vec3(),it->col2); + simple_va_.AddLine(id0,id1); } } -void PrimList::render_custom() +void PrimList::prep_va() { va_.Clear(); va_.SetLighting(true); @@ -237,18 +271,15 @@ void PrimList::render_custom() va_.SetColorMaterial(true); va_.SetMode(0x4); - for(PointEntryList::const_iterator it=points_.begin();it!=points_.end();++it) { - va_.AddSphere(SpherePrim(it->pos, radius_, it->color), + for(PointEntryList::const_iterator it=spheres_.begin();it!=spheres_.end();++it) { + va_.AddSphere(SpherePrim(it->pos, it->rad, it->col), GetSphereDetail()); } - for(LineEntryList::const_iterator it=lines_.begin();it!=lines_.end();++it) { - va_.AddSphere(SpherePrim(it->pos1, radius_, it->color), - GetSphereDetail()); - va_.AddSphere(SpherePrim(it->pos2, radius_, it->color), - GetSphereDetail()); - va_.AddCylinder(CylinderPrim(it->pos1,it->pos2,radius_,it->color), - GetArcDetail()); + for(LineEntryList::const_iterator it=cyls_.begin();it!=cyls_.end();++it) { + va_.AddCylinder(CylinderPrim(it->pos1, it->pos2, it->rad1, it->rad2, it->col1, it->col2), + GetArcDetail(), + true); } } diff --git a/modules/gfx/src/prim_list.hh b/modules/gfx/src/prim_list.hh index daba0e7e50439122f919fc922678d636be32f5bb..bf8fb98ed8ea345c97b408b96d782d609282bc41 100644 --- a/modules/gfx/src/prim_list.hh +++ b/modules/gfx/src/prim_list.hh @@ -35,33 +35,27 @@ class PrimList; typedef boost::shared_ptr<PrimList> PrimListP; -/// \brief rudimentary graphical lines rendering. -/// -/// The primitives may be rendered either with gfx::RenderMode::SIMPLE or -/// gfx::RenderMode::CUSTOM. The render mode can be changed with -/// GfxObj::SetRenderMode(). -/// /// \see gfx::Cuboid, \ref primitives.py "Displaying Lines and Quads", /// gfx::Quad, \ref gradient.py "Gradient Example", /// \ref random_lines.py "Random Lines" class DLLEXPORT_OST_GFX PrimList: public GfxObj { struct PointEntry { - PointEntry(const geom::Vec3& p, const Color& c): - pos(p), color(c) {} + PointEntry(const geom::Vec3& p, float r, const Color& c): + pos(p), rad(r), col(c) {} geom::Vec3 pos; - Color color; - geom::Mat3 rotmat; + float rad; + Color col; }; typedef std::vector<PointEntry> PointEntryList; struct LineEntry { - LineEntry(const geom::Vec3& p1, const geom::Vec3& p2, const Color& c): - pos1(p1), pos2(p2), color(c) {} - geom::Vec3 pos1,pos2; - Color color; - geom::Mat3 rotmat; + LineEntry(const geom::Vec3& p1, const geom::Vec3& p2, float r1, float r2, const Color& c1, const Color& c2): + pos1(p1), pos2(p2), rad1(r1), rad2(r2), col1(c1), col2(c2) {} + geom::Vec3 pos1, pos2; + float rad1, rad2; + Color col1, col2; }; typedef std::vector<LineEntry> LineEntryList; @@ -70,6 +64,8 @@ class DLLEXPORT_OST_GFX PrimList: public GfxObj /// \brief create new prim list PrimList(const String& name); + virtual geom::AlignedCuboid GetBoundingBox() const; + virtual void ProcessLimits(geom::Vec3& minc, geom::Vec3& maxc, const mol::Transform& tf) const; /// \brief get center @@ -81,19 +77,49 @@ class DLLEXPORT_OST_GFX PrimList: public GfxObj virtual void OnRenderModeChange(); - /// \brief clear all prims + /// \brief clear all prims void Clear(); - /// \brief add line as defined by two endpoints - void AddPoint(geom::Vec3& p, const Color& col=Color()); + /*! + \brief add point + + python interface: + + PrimList.AddPoint(pos, color=gfx.Color()) + */ + void AddPoint(const geom::Vec3& p, const Color& col); + + /*! + \brief add line + + Python interface: + + PrimList.AddLine(pos1,pos2,col=gfx.WHITE,col1=gfx.WHITE,col2=gfx.WHITE) + */ + void AddLine(const geom::Vec3& p1, const geom::Vec3& p2, const Color& col1, const Color& col2); - /// \brief add line as defined by two endpoints - void AddLine(geom::Vec3& p1, geom::Vec3& p2, const Color& col=Color()); + /*! + \brief add sphere - /// \brief cylinder diameter for custom rendering mode + Python interface: + + PrimList.AddSphere(cen,rad,col=gfx.WHITE) + */ + void AddSphere(const geom::Vec3& cen, float rad, const Color& col); + + /*! + \brief add cylinder + + Python interface: + + PrimList.AddCyl(pos1,pos2,rad=1.0,rad1=1.0,rad2=1.0,col=gfx.WHITE,col1=gfx.WHITE,col2=gfx.WHITE) + */ + void AddCyl(const geom::Vec3& p0, const geom::Vec3& p1, float r1, float r2, const Color& col1, const Color& col2); + + /// defunct void SetDiameter(float d); - /// \brief sphere radius for points in custom rendering mode + /// defunct void SetRadius(float r); /// \brief set global prims color, overriding individual ones @@ -105,19 +131,23 @@ class DLLEXPORT_OST_GFX PrimList: public GfxObj void SetArcDetail(unsigned int d); unsigned int GetArcDetail() const {return arc_detail_;} + // TODO: add point and line pixel width + protected: virtual void CustomPreRenderGL(bool flag); private: PointEntryList points_; LineEntryList lines_; - float radius_; - float diameter_; + PointEntryList spheres_; + LineEntryList cyls_; unsigned int sphere_detail_; unsigned int arc_detail_; + + IndexedVertexArray simple_va_; - void render_simple(); - void render_custom(); + void prep_simple_va(); + void prep_va(); }; /// \example primitives.py diff --git a/modules/gfx/src/vertex_array.cc b/modules/gfx/src/vertex_array.cc index da764f97f8d808fc4fd7b7cc1b6ac3b9516e9476..ab6db586b8f97c96f963da4c4314fe0f2f17f657 100644 --- a/modules/gfx/src/vertex_array.cc +++ b/modules/gfx/src/vertex_array.cc @@ -78,7 +78,7 @@ IndexedVertexArray::IndexedVertexArray() { initialized_=false; Reset(); // replaces ctor initialization list - glGenTextures(1,&tex_id_); + //glGenTextures(1,&tex_id_); } IndexedVertexArray::~IndexedVertexArray() @@ -88,7 +88,7 @@ IndexedVertexArray::~IndexedVertexArray() IndexedVertexArray::IndexedVertexArray(const IndexedVertexArray& va) { copy(va); - glGenTextures(1,&tex_id_); + //glGenTextures(1,&tex_id_); } IndexedVertexArray& IndexedVertexArray::operator=(const IndexedVertexArray& va) @@ -248,7 +248,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, bool cap) { dirty_=true; @@ -266,12 +266,19 @@ void IndexedVertexArray::AddCylinder(const CylinderPrim& prim, unsigned int deta // prepare first vertices to add std::vector<Vec3>::const_iterator it=vlist.begin(); Vec3 v0 = (*it); - Vec3 n0 = prim.rotmat * v0; - v0*=prim.radius; + bool slant=(prim.radius1!=prim.radius2); + // adjust for slant + float beta = slant ? atan2(prim.radius1-prim.radius2,prim.length) : 0.0; + float cosb = slant ? cos(beta) : 1.0; + float sinb = slant ? sin(beta) : 0.0; + Vec3 n0 = slant ? prim.rotmat * (cosb*v0+geom::Vec3(0.0,0.0,sinb)) : prim.rotmat*v0; + + v0*=prim.radius1; + Vec3 v1 = (*it)*prim.radius2+off; VertexID id1 = Add(prim.rotmat * v0 + prim.start, n0, prim.color1); - VertexID id2 = Add(prim.rotmat * (v0+off) + prim.start, n0, prim.color2); + VertexID id2 = Add(prim.rotmat * v1 + 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 cid2 = cap ? Add(prim.rotmat * v1 + prim.start, cn1, prim.color2) : 0; // now for the loop around the circle VertexID id3=id1; @@ -281,15 +288,16 @@ void IndexedVertexArray::AddCylinder(const CylinderPrim& prim, unsigned int deta ++it; for(;it!=vlist.end();++it) { v0 = (*it); - n0 = prim.rotmat * v0; - v0 *= prim.radius; + Vec3 n0 = slant ? prim.rotmat * (cosb*v0+geom::Vec3(0.0,0.0,sinb)) : prim.rotmat*v0; + v0 *= prim.radius1; + Vec3 v1 = (*it)*prim.radius2+off; VertexID id5 = Add(prim.rotmat * v0 + prim.start, n0, prim.color1); - VertexID id6 = Add(prim.rotmat * (v0+off) + prim.start, n0, prim.color2); + VertexID id6 = Add(prim.rotmat * v1 + prim.start, n0, prim.color2); 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); + VertexID cid6 = Add(prim.rotmat * v1 + prim.start, cn1, prim.color2); AddTri(cid0,cid5,cid3); AddTri(cid7,cid4,cid6); cid3=cid5; diff --git a/modules/gfx/tests/CMakeLists.txt b/modules/gfx/tests/CMakeLists.txt index 469122e944ac2e30911ce45a1517110d7f19641d..c87cf918355421e221365f43a8592691b7d567d0 100644 --- a/modules/gfx/tests/CMakeLists.txt +++ b/modules/gfx/tests/CMakeLists.txt @@ -1,6 +1,7 @@ set(OST_GFX_UNIT_TESTS tests.cc test_gfx_node.cc + test_primlist.py ) if (ENABLE_IMG) list(APPEND OST_GFX_UNIT_TESTS test_map_octree.cc) diff --git a/modules/gfx/tests/test_primlist.py b/modules/gfx/tests/test_primlist.py new file mode 100644 index 0000000000000000000000000000000000000000..82fd4a376e284e0526b5f79fb28af5df300349f2 --- /dev/null +++ b/modules/gfx/tests/test_primlist.py @@ -0,0 +1,27 @@ +import unittest +if __name__== '__main__': + import sys + sys.path.insert(0,"../../../stage/lib64/openstructure/") + +import ost +import ost.gfx +import ost.geom + +class TestPrimList(unittest.TestCase): + def setUp(self): + pass + + def test_(self): + pl=ost.gfx.PrimList("foo") + pl.AddPoint([0,0,0]) + pl.AddPoint(ost.geom.Vec3(1,2,3),col=ost.gfx.RED) + pl.AddLine([0,0,0],[1,2,3]) + pl.AddLine(ost.geom.Vec3(0,0,0),ost.geom.Vec3(1,2,3),col=ost.gfx.BLUE) + pl.AddSphere([0,0,0],rad=2.0) + pl.AddSphere(ost.geom.Vec3(1,2,3),col=ost.gfx.RED,rad=3.0) + pl.AddCyl([0,0,0],[1,2,3],rad=0.5,col=ost.gfx.YELLOW) + pl.AddCyl(ost.geom.Vec3(0,0,0),ost.geom.Vec3(1,2,3),rad1=0.5,rad2=0.1,col1=ost.gfx.BLUE,col2=ost.gfx.GREEN) + +if __name__== '__main__': + unittest.main() +