/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include "mg/Tolerance.h" #include "mg/AttribedGel.h" #include "mg/DNameControl.h" #include "mg/BPointSeq.h" #include "mg/Curve.h" #include "mg/LBRep.h" #include "mg/SPointSeq.h" #include "mg/Surface.h" #include "mg/Plane.h" #include "mg/MGStl.h" #include "topo/Complex.h" #include "topo/CellBase.h" #include "topo/Edge.h" #include "topo/Loop.h" #include "topo/Face.h" #include "tl2/TL2Triangles.h" #include "mgGL/glslprogram.h" #include "mgGL/VBO.h" ///////////////////////////////////////////////////////////////////////////// /// Vertex Buffer Object Class. ///mgVBOに対して描画データ作成後の情報を保持するためのクラス。 ///mgVBOはmgVBOLeafとmgVBO自身をelementとして保持する。 ///mgVBOをelementとするのはMGGroupまたはMGShellのメンバーデータの表示情報を ///保持するため //Draw an arrow symbol with implementation of OpenGL. //data[0] is the origin of the arrow, data[1] is the top of the arrow, //data[2], [3] are two bottoms of arrowhead. void mgVBO::drawArrow(const MGPosition pos[4]){ Begin(GL_LINES); Vertex3dv(pos[0].data()); Vertex3dv(pos[1].data()); Vertex3dv(pos[1].data()); Vertex3dv(pos[2].data()); Vertex3dv(pos[1].data()); Vertex3dv(pos[3].data()); End(); } /// Draw an object of class MGBox, by wireframe. void mgVBO::drawBox(const MGBox& box){ int sd = box.sdim(); const MGInterval& x = box[0]; const MGInterval& y = box[1]; double x0=x.low_point(), x1=x.high_point(); double y0=y.low_point(), y1=y.high_point(); if(sd == 2){ Begin(GL_LINE_LOOP); Vertex3d(x0, y0, 0.); Vertex3d(x1, y0, 0.); Vertex3d(x1, y1, 0.); Vertex3d(x0, y1, 0.); End(); return; }else if(sd == 3){ const MGInterval& z = box[2]; double z0=z.low_point(), z1=z.high_point(); Begin(GL_LINES); Vertex3d(x0, y0, z0); Vertex3d(x1, y0, z0); Vertex3d(x1, y0, z0); Vertex3d(x1, y1, z0); Vertex3d(x1, y1, z0); Vertex3d(x0, y1, z0); Vertex3d(x0, y1, z1); Vertex3d(x0, y0, z1); // Vertex3d(x0, y0, z1); Vertex3d(x1, y0, z1); Vertex3d(x1, y0, z1); Vertex3d(x1, y1, z1); Vertex3d(x1, y1, z1); Vertex3d(x0, y1, z1); Vertex3d(x0, y1, z1); Vertex3d(x0, y0, z1); // Vertex3d(x0, y0, z0); Vertex3d(x0, y0, z1); Vertex3d(x1, y0, z0); Vertex3d(x1, y0, z1); Vertex3d(x1, y1, z0); Vertex3d(x1, y1, z1); Vertex3d(x1, y0, z0); Vertex3d(x1, y0, z1); End(); } } /// Draw a control points, dotted lines shall be drawn /// between point[i-1] and point[i], for i = 1, .., length()-1. void mgVBO::drawPointSeq( const MGBPointSeq& bp, bool draw_points //True if points be drawn. ){ drawPolyline(bp); if(draw_points){ int n=bp.length(); for(int i = 0; i < n; i++){ drawPoint(bp(i)); } } } void mgVBO::drawPointSeq( const MGSPointSeq& sp, bool draw_points //True if points be drawn. ){ int i, nu = sp.length_u(), nv = sp.length_v(); for(i = 0; i < nu; i++){ Begin(GL_LINE_STRIP); for(int j = 0; j < nv; j++){ Vertex3d(sp(i,j,0),sp(i,j,1),sp(i,j,2)); } End(); } for(i = 0; i < nv; i++){ Begin(GL_LINE_STRIP); for(int j = 0; j < nu; j++){ Vertex3d(sp(j,i,0),sp(j,i,1),sp(j,i,2)); } End(); } if(draw_points){ for(int i = 0; i < nu; i++){ for(int j = 0; j < nv; j++){ drawPoint(sp(i, j)); } } } } //Draw 3D point(vertex) in world coordinates. //The object is converted to point(s) and is drawn. //This is valid only for topology objects or MGPoint. void mgVBO::draw3DVertex(const MGObject& obj){ obj.draw3DVertex(*this); } void mgVBO::draw3DVertex_in_star(const MGComplex& obj){ obj.draw3DVertex_in_star(*this); } void mgVBO::draw3DVertex_in_star(const MGCellBase& obj){ obj.draw3DVertex_in_star(*this); } ///Draw 3D curve in the topology's star cell world coordinates. ///The object is converted to curve(s) and is drawn. void mgVBO::drawWire_in_star(const MGComplex& obj){ obj.draw3DVertex_in_star(*this); } void mgVBO::drawWire_in_star(const MGCellBase& obj){ obj.draw3DVertex_in_star(*this); } ///Draw curvature variation graph so-called Hige. ///Function's return value is the maximum length of the graph. double mgVBO::drawCurvaGraph( const MGCurve& curve, double scale, int density, bool use_radius, bool getLength/// 0); MGUnit_vector T, N, B; double curva, torsion, length=-1.; double revdens = 1. / density; MGPosition pos(3); MGVector v(curve.start_point()); // v : vertex of the hige's polyline const MGKnotVector& kv = curve.knot_vector(); if(!use_radius) scale*=-1.; if(!getLength) Begin(GL_LINES); for(int i = kv.order()-1; i < kv.bdim(); i++){ double t = kv[i]; const double& tp1 = kv[i+1]; MGInterval iv(t,tp1); double dt = (tp1-t)*revdens; for(int j = 0; j < density; j++, t += dt){ if(!getLength) Vertex3dv(v.data()); pos = curve.eval(t); // pos : on the curve curve.Frenet_frame(t, T, N, B, curva, torsion); // N is from pos to the center of the osculating circle at pos. if(use_radius) curva=1./curva; if(length=1.f) drawPointWithColor(x,y,z,size,innerSize); } void mgVBO::drawPoint(const MGPosition& pos,double size){ drawPoint(pos[0], pos[1], pos[2],size); } void mgVBO::drawPointInverseColor(double x,double y,double z,double size){ const MGColor* inner=&MGColor::get_instance(MGColor::White); float outer[4]; glGetFloatv(GL_CURRENT_COLOR,outer); MGColor outclr(outer[0],outer[1],outer[2],outer[3]); if(size<=0.) size=mgVBOElement::getDefaultPointSize(); float innerSize=(float)size-2.f; if(innerSize>=1.f) drawPointWithColor(x,y,z,size,innerSize,&outclr,inner); } void mgVBO::drawPointInverseColor(const MGPosition& pos,double size){ drawPointInverseColor(pos[0],pos[1],pos[2],size); } void mgVBO::drawPointWithColor(double x,double y,double z, double outerSize, double innerSize, const MGColor* colorInner, const MGColor* colorOuter ){ Begin(GL_POINTS); if(colorOuter) setStaticAttribColor(*colorOuter);//Outer color. setStaticAttribPointSize((float)outerSize); Vertex3d(x,y,z); End(); if(innerSize>=1.f){ const MGColor* inner=colorInner; if(!inner) inner=&MGColor::get_instance(MGColor::White); Begin(GL_POINTS); setStaticAttribColor(*inner);//Inner color. setStaticAttribPointSize((float)innerSize); Vertex3d(x,y,z); End(); } } void mgVBO::drawPointWithColor(const MGPosition& pos, double outerSize, double innerSize, const MGColor* colorInner, const MGColor* colorOuter ){ drawPointWithColor(pos[0], pos[1], pos[2], outerSize,innerSize, colorInner,colorOuter); } ///draw points sequence ipos with 2 colors, inner and outer. void mgVBO::drawPoints( const MGColor& boundary_color, const MGColor& inner_color, const std::vector& ipos, double size ){ if(ipos.size()<=0) return; if(size<=0.) size=mgVBOElement::getDefaultPointSize(); std::vector::const_iterator i,ibegin=ipos.begin(), iend=ipos.end(); Begin(GL_POINTS); setStaticAttribColor(boundary_color); setStaticAttribPointSize((float)size);// for(i=ibegin; i!=iend; i++) Vertex(*i); End(); Begin(GL_POINTS); setStaticAttribColor(inner_color); setStaticAttribPointSize((float)size-2.f);// for(i=ibegin; i!=iend; i++) Vertex(*i); End(); } ///Draw a polyline using openGL functions. ///The last argument must end with nullptr. void mgVBO::drawOpenPolyline(const MGPosition* P0, ...){ const MGPosition* Pi=P0; va_list args; va_start(args, P0); Begin(GL_LINE_STRIP); while(Pi){ const MGPosition& P=*Pi; Vertex3d(P[0],P[1],P[2]); Pi = va_arg(args, const MGPosition*); } End(); va_end(args); } ///Draw a polyline using openGL functions. ///The last argument must end with nullptr. void mgVBO::drawClosedPolyline(const MGPosition* P0, ...){ const MGPosition* Pi=P0; va_list args; va_start(args, P0); Begin(GL_LINE_LOOP); while(Pi){ const MGPosition& P=*Pi; Vertex3d(P[0],P[1],P[2]); Pi = va_arg(args, const MGPosition*); } End(); va_end(args); } ///Draw a polyline using openGL functions. ///When clodes=true, 1st and last points will be connected. void mgVBO::drawPolyline(const MGBPointSeq& line, bool closed){ int n = line.length(); if(n<=0) return; int kind=GL_LINE_STRIP; if(closed) kind=GL_LINE_LOOP; Begin(kind); for(int i = 0; i < n; i++){ Vertex3d(line(i,0),line(i,1),line(i,2)); } End(); } ///Draw a polyline using openGL functions. ///When cloded=true, 1st and last points will be connected. void mgVBO::drawPolyline(const std::vector& line, bool closed){ int kind=GL_LINE_STRIP; if(closed) kind=GL_LINE_LOOP; size_t n(line.size()); if(n<=0) return; Begin(kind); for(size_t i = 0; i < n; i++){ const MGPosition& Pi=line[i]; Vertex3d(Pi[0],Pi[1],Pi[2]); } End(); } ///Draw a polyline using openGL functions. ///When cloded=true, 1st and last points will be connected. void mgVBO::drawPolyline(size_t nPoints, const MGPosition line[], bool closed){ int kind=GL_LINE_STRIP; if(closed) kind=GL_LINE_LOOP; if(nPoints<=0) return; Begin(kind); for(size_t i = 0; i < nPoints; i++){ const MGPosition& Pi=line[i]; Vertex3d(Pi[0],Pi[1],Pi[2]); } End(); } ///Draw a line from start to end. void mgVBO::drawStraight(const MGPosition& end, const MGPosition& start){ Begin(GL_LINE_STRIP); Vertex3d(start[0],start[1],start[2]); Vertex3d(end[0],end[1],end[2]); End(); } //Draw an object in its parameter space(MGDraw_in_parameter_space). //This is valid only for Surface, Face, Loop, Edge. void mgVBO::drawObjInParameterSpace(const MGObject& obj){ const MGSurface* sf=dynamic_cast(&obj); if(sf){ const MGPlane* pl=dynamic_cast(sf); if(pl) return;//Plane will not be drawn. MGBox uv=sf->param_range(); double u0=uv[0].low_point(), u1=uv[0].high_point(); double v0=uv[1].low_point(), v1=uv[1].high_point(); Begin(GL_LINE_STRIP); Vertex3d(u0, v0, 0.); Vertex3d(u1, v0, 0.); Vertex3d(u1, v1, 0.); Vertex3d(u0, v1, 0.); Vertex3d(u0, v0, 0.); End(); drawPoint(u0, v0, 0.); drawPoint(u1, v0, 0.); drawPoint(u1, v1, 0.); drawPoint(u0, v1, 0.); return; } const MGFace* f=dynamic_cast(&obj); if(f){ if(f->hasOuterBoundaryLoop()){ const MGLoop& ol=*(f->loop(int(0))); ol.drawWire(*this); }else{ MGPvector crvs=f->outer_boundary_param(); size_t n=crvs.size(); for(size_t i=0; idrawWire(*this); } int i,if0; int nib=f->number_of_inner_boundaries(if0); for(i=0; iloop(if0))->drawWire(*this); int nlp=f->number_of_boundaries(); for(; if0loop(if0))->drawWire(*this); for(i=0; iloop(i)); draw3DVertex(lp); } return; } const MGLoop* lp=dynamic_cast(&obj); if(lp){ lp->drawWire(*this); draw3DVertex(*lp); return; } const MGEdge* edg=dynamic_cast(&obj); if(edg){ edg->drawWire(*this); draw3DVertex(*edg); return; } } ///Draw a rectangle. ///(param_rectangle) void mgVBO::drawRectangle( const MGBox& box //Box to draw. ){ double u0=box[0].low_point(), u1=box[0].high_point(); double v0=box[1].low_point(), v1=box[1].high_point(); Begin(GL_LINE_LOOP); Vertex3d(u0, v0, 0.); Vertex3d(u1, v0, 0.); Vertex3d(u1, v1, 0.); Vertex3d(u0, v1, 0.); End(); } /* ///OpenGL display for the tessellation lines drawn in world view. void mgVBO::drawWTess( const mgTLData& tld //tessellation data. ){ const mgTLTriangles& tris=tld.triangles(); const MGSurface& surf=tld.surface(); const mgTLPoints& tlpoints=tld.tlpoints(); mgTLTriangles::const_triIterator i=tris.begin(), ie=tris.end(); for(; i!=ie; i++){ const mgTLTriangle& tri=**i; if(tri.size()<3) continue;//If number of vertices are less than 3. if(tri.getGeometryType()==mgTESTRIANG_FAN){ mgTLTriangle::CIndexItr j=tri.begin(), je=tri.end(); MGPosition pivot=surf.eval(tlpoints[*j++]); MGPosition pre=surf.eval(tlpoints[*j++]); MGPosition aft=surf.eval(tlpoints[*j++]); Begin(GL_LINE_LOOP); Vertex3dv(pivot.data()); Vertex3dv(pre.data()); Vertex3dv(aft.data()); End(); for(;j!=je; j++){ pre=aft; aft=surf.eval(tlpoints[*j]); Begin(GL_LINE_STRIP); Vertex3dv(pre.data()); Vertex3dv(aft.data()); Vertex3dv(pivot.data()); End(); } }else{ mgTLTriangle::CIndexItr j=tri.begin(), je=tri.end(); MGPosition pre=surf.eval(tlpoints[*j++]); MGPosition current=surf.eval(tlpoints[*j++]); MGPosition aft=surf.eval(tlpoints[*j++]); Begin(GL_LINE_LOOP); Vertex3dv(current.data()); Vertex3dv(pre.data()); Vertex3dv(aft.data()); End(); for(;j!=je; j++){ pre=current; current=aft; aft=surf.eval(tlpoints[*j]); Begin(GL_LINE_STRIP); Vertex3dv(current.data()); Vertex3dv(aft.data()); Vertex3dv(pre.data()); End(); } } } } ///OpenGL display for the tessellation lines drawn in parameter view. void mgVBO::drawPTess( const mgTLData& tld //tessellation data. ){ const mgTLTriangles& tris=tld.triangles(); const mgTLPoints& tlpoints=tld.tlpoints(); mgTLTriangles::const_triIterator i=tris.begin(), ie=tris.end(); for(; i!=ie; i++){ const mgTLTriangle& tri=**i; if(tri.size()<3) continue;//If number of vertices are less than 3. if(tri.getGeometryType()==mgTESTRIANG_FAN){ mgTLTriangle::CIndexItr j=tri.begin(), je=tri.end(); const double* pivot=tlpoints[*j++].data(); const double* pre=tlpoints[*j++].data(); const double* aft=tlpoints[*j++].data(); Begin(GL_LINE_LOOP); Vertex2dv(pivot); Vertex2dv(pre); Vertex2dv(aft); End(); for(;j!=je; j++){ pre=aft; aft=tlpoints[*j].data(); Begin(GL_LINE_STRIP); Vertex2dv(pre); Vertex2dv(aft); Vertex2dv(pivot); End(); } }else{ mgTLTriangle::CIndexItr j=tri.begin(), je=tri.end(); const double* pre=tlpoints[*j++].data(); const double* current=tlpoints[*j++].data(); const double* aft=tlpoints[*j++].data(); Begin(GL_LINE_LOOP); Vertex2dv(current); Vertex2dv(pre); Vertex2dv(aft); End(); for(;j!=je; j++){ pre=current; current=aft; aft=tlpoints[*j].data(); Begin(GL_LINE_STRIP); Vertex2dv(current); Vertex2dv(aft); Vertex2dv(pre); End(); } } } }*/ /// void getCurvature( const MGSurface& surf, const MGPosition& uv, MGCL::SURFACE_CURVATURE_KIND kind, MGPosition& curvaData///< (0)=curvature, (1-3)=normal, (4-6)=point data. ){ double curvature[4]; MGUnit_vector N; surf.curvatures(uv,curvature,N); curvaData.resize(7); curvaData(0)=curvature[kind]; curvaData.store_at(1,N,0,3); curvaData.store_at(4,surf.eval(uv),0,3); } /// Renders curvatures mapping that comes into colorful image. /// A point whose curvature is within [lower, upper], the color varies. void mgVBO::drawSurfaceCurvature( const mgTL2Triangles& tld, MGCL::SURFACE_CURVATURE_KIND kind, double lower, double upper //minimum and maximum value of the curvatures of the kind. ){ assert(tld.get_kind()==MGCL::UV); const MGSurface* surfP=tld.surface(); assert(surfP); const MGSurface& surf=*surfP; double mzero=MGTolerance::mach_zero(); if(upper-lower<=2.*mzero){ upper+=mzero; lower-=mzero; } const double R[3] = {1.0, 0.0, 0.0}; const double Y[3] = {1.0, 1.0, 0.0}; const double G[3] = {0.0, 1.0, 0.0}; const double C[3] = {0.0, 1.0, 1.0}; const double B[3] = {0.0, 0.0, 1.0}; MGBPointSeq bp(5, 3); bp.store_at(4, R); bp.store_at(3, Y); bp.store_at(2, G); bp.store_at(1, C); bp.store_at(0, B); int err = 0; MGLBRep color(bp, 2); color.change_range(lower, upper); //const mgTLTriangles& tris=tld.triangles(); mgTL2Triangles::const_iterator i=tld.begin(), ie=tld.end(); for(; i!=ie; ++i){ const mgTL2Triangle& tri=**i; if(tri.size()<3) continue; mgTL2Triangle::const_iterator j=tri.begin(), je=tri.end(); GLenum triType=(tri.getGeometryType()==mgTESTRIANG_FAN)? GL_TRIANGLE_FAN : GL_TRIANGLE_STRIP; Begin(triType, mgVBO::WIRE); for(;j!=je; ++j){ const MGPosition& uv=*j; MGPosition curvaDataj; getCurvature(surf,uv,kind,curvaDataj); //Nomal. Normal3d(curvaDataj[1],curvaDataj[2],curvaDataj[3]); //Curvature color. double curvature = curvaDataj[0]; if(curvature > upper) curvature = upper; else if(curvature < lower) curvature = lower; Color3dv(color.eval(curvature).data()); //Position data. Vertex3d(curvaDataj[4],curvaDataj[5],curvaDataj[6]); } End(GL_FILL); } } /// Renders curvatures mapping that comes into colorful image. /// A point whose curvature is within [lower, upper], the color varies. void mgVBO::drawSurfaceCurvature( const std::vector& tldvec,///::const_iterator datai=tldvec.begin(), dataie=tldvec.end(); for(; datai!=dataie; datai++){ drawSurfaceCurvature(*datai,kind,lower,upper); } } /// MGStlオブジェクトを描画する void mgVBO::drawSTL( const MGStl& stl, // 描画するMGStlオブジェクト ELEMENT_TARGET target,///& vertices = stl.positions(); const std::vector& normals = stl.normals(); Begin(GL_TRIANGLES,target);// 描画を開始 size_t nTriang(normals.size()); // 三角形の個数だけループ int indices[3]; for(int j = 0; size_t(j) < nTriang; j++){ stl.GetVertIndices(j, indices); if(polygonMode==GL_FILL){// シェーディングを行う場合 const double* normalP=normals[j].data(); Normal3dv(normalP); Normal3dv(normalP); Normal3dv(normalP); } // 頂点のインデックスを元に頂点の座標を取得する const MGPosition& position1 = vertices[indices[0]]; const MGPosition& position2 = vertices[indices[1]]; const MGPosition& position3 = vertices[indices[2]]; Vertex3dv(position1.data()); Vertex3dv(position2.data()); Vertex3dv(position3.data()); } End(polygonMode); } ///OpenGL shading display of a tesselated data tris. void mgVBO::drawShade( const mgTL2Triangles& tris, ELEMENT_TARGET target,///3){ Normal3dv(Pdata+3); } if(nsd==2){ Vertex2dv(Pdata); }else{ Vertex3dv(Pdata); } } End(polygonMode); } } ///OpenGL shading display of a tesselated data tris. void mgVBO::drawShade( const std::vector& trisVector,///::const_iterator i=trisVector.begin(), iend=trisVector.end(); for(; i!=iend; i++) drawShade(*i,target,polygonMode); }