Opengl ES 线的三角化
2016-05-06 12:06
381 查看
本文主要讨论将线扩展成2d线面的算法
如上图所示将p0p1这条直线 扩展成面 很简单
Vec2f line = p1 - p0
Vec2f normal = Vec2f( -line.y, line.x).normalized().
Vec2f a = p0 - thickness * normal;
Vec2f b = p0 + thickness * normal;
Vec2f c = p1 - thickness * normal;
Vec2f d = p1 + thickness * normal;
如果是直线这么处理就可以了,但是如果有多段线,我们还需要计算交点的地方
首先我们先求出 t
Vec2f
t = ( (p2-p1).normalized() + (p1-p0).normalized() ).normalized()
其次 在求出m
Vec2f m = Vec2f( -t.y,t.x )
最后再求出d的长度
float
d = thickness / miter.dot( normal )
根据上述获得内容就能得到想要的所有顶点,然后根据这些顶点构建三角面片即可
代码大致如下:
效果大致如下
请注意 以上过程在两段线夹角比较小的时候会出问题,所以请慎用..
geos库中
也有方法提供
测试代码如下
注意 以上生成的顶点数组 还要进行三角剖分(推荐使用gpc),然后再以trianglelist的绘制,或者用以下的算法构建顶点数组
如上图所示将p0p1这条直线 扩展成面 很简单
Vec2f line = p1 - p0
Vec2f normal = Vec2f( -line.y, line.x).normalized().
Vec2f a = p0 - thickness * normal;
Vec2f b = p0 + thickness * normal;
Vec2f c = p1 - thickness * normal;
Vec2f d = p1 + thickness * normal;
如果是直线这么处理就可以了,但是如果有多段线,我们还需要计算交点的地方
首先我们先求出 t
Vec2f
t = ( (p2-p1).normalized() + (p1-p0).normalized() ).normalized()
其次 在求出m
Vec2f m = Vec2f( -t.y,t.x )
最后再求出d的长度
float
d = thickness / miter.dot( normal )
根据上述获得内容就能得到想要的所有顶点,然后根据这些顶点构建三角面片即可
代码大致如下:
void trianglePolyLine( const Vec2f &p0, const Vec2f &p1, const Vec2f &p2, const Vec2f &p3 , PosArray &vtx, IndexArray &indices,double radius) { if(p1 == p2) return; Vec2f line = (p2 - p1).normalize(); Vec2f normal = Vec2f(-line.Y, line.X).normalize(); Vec2f tangent1 = (p0 == p1) ? line : ((p1-p0).normalize() + line).normalize(); Vec2f tangent2 = (p2 == p3) ? line : ((p3-p2).normalize() + line).normalize(); Vec2f miter1 = Vec2f(-tangent1.Y, tangent1.X); Vec2f miter2 = Vec2f(-tangent2.Y, tangent2.X); float length1 = radius / normal.dotProduct(miter1); float length2 = radius / normal.dotProduct(miter2); if(true) { Vec2f bg1(p1 - length1 * miter1); Vec2f ed1(p2 - length2 * miter2); Vec2f bg2(p1 + length1 * miter1); Vec2f ed2(p2 + length2 * miter2); int len = vtx.size(); vtx.push_back(Vector3df(bg1.X, bg1.Y,0)); vtx.push_back(Vector3df(ed1.X, ed1.Y,0)); vtx.push_back(Vector3df(bg2.X, bg2.Y,0)); vtx.push_back(Vector3df(ed2.X, ed2.Y,0)); indices.push_back( len + 0 ); indices.push_back( len + 1 ); indices.push_back( len + 2 ); indices.push_back( len + 1 ); indices.push_back( len + 2 ); indices.push_back( len + 3 ); } }调用代码如下
for(int i = 0;i<vertexes.size();++i) { int a = ((i-1) < 0) ? 0 : (i-1); int b = i; int c = ((i+1) >= vertexes.size()) ? vertexes.size()-1 : (i+1); int d = ((i+2) >= vertexes.size()) ? vertexes.size()-1 : (i+2); trianglePolyLine( vertexes[a], vertexes[b], vertexes[c], vertexis[d],pts,indices,raidus ); }vertexes表示多段线,mesh表示构建的顶点数组 讲次数组直接以GL_Lines绘制
效果大致如下
请注意 以上过程在两段线夹角比较小的时候会出问题,所以请慎用..
geos库中
也有方法提供
测试代码如下
static void createPolyline(PosArray &arr) { const float len = 100.0; geos::geom::GeometryFactory factroy; CoordinateArraySequenceFactory csf; CoordinateSequence *cs1 = (csf.create(3,2)); cs1->setAt(Coordinate(-len,0,0),0); cs1->setAt(Coordinate(-len,len,0),1); cs1->setAt(Coordinate(len,len,0),2); std::auto_ptr<LineString> ring1(factroy.createLineString(cs1)) ; std::auto_ptr<Geometry> p(ring1->buffer(10)); std::auto_ptr<CoordinateSequence> pcs(p->getCoordinates()); for(int i = 0; i < pcs->getSize(); ++i) { Coordinate co = pcs->getAt(i); arr.push_back(Vector3df(co.x,co.y,0)); } }
注意 以上生成的顶点数组 还要进行三角剖分(推荐使用gpc),然后再以trianglelist的绘制,或者用以下的算法构建顶点数组
struct SDrawVertexColor { Vector3df pos; SColor4f color; }; typedef std::vector<SDrawVertexColor> PosClrArray; tpyedef std::vector<int> IndexArray; void PolyLine( const Vector3df *pPoints, int nPoints, PosClrArray *outarray, u32 color, IndexArray *idx, float lineWidth,int zidx /*=0*/) { if(NULL == pPoints || nPoints<2 || NULL == outarray || lineWidth < 1e-6) return; u32 i_idx = outarray->size(); Vector2df a,b,aR,aL,bR,bL; Vector2df abP,abV,tmp; Vector3df LindS1[10]; Vector3df LindE1[10]; SDrawVertexColor vertexAcc; vertexAcc.color =SColor4f(color); for ( u32 i=1; i < nPoints; ++i ) { b = ToVector2d(pPoints[i-1]); a = ToVector2d(pPoints[i]); abP = a-b; abP.normalize(); abV = rotateBy90(abP); aR = a + abV * lineWidth; aL = a - abV * lineWidth; bR = b + abV * lineWidth; bL = b - abV * lineWidth; // 添加第一个点的左右点 LindS1[0] = ToVector3d(b,zidx); LindS1[1] = ToVector3d(bR,zidx); LindS1[2] = ToVector3d(bL,zidx); LindS1[3] = ToVector3d(b - abP * lineWidth,zidx); LindS1[4] = ToVector3d(b + (-abP+abV)*0.707f * lineWidth,zidx); LindS1[5] = ToVector3d(b + (-abP-abV)*0.707f * lineWidth,zidx); LindS1[6] = ToVector3d(b + ((-abP+abV)*0.707f+abV)*0.541f *lineWidth,zidx); LindS1[7] = ToVector3d(b + ((-abP+abV)*0.707f-abP)*0.541f *lineWidth,zidx); LindS1[8] = ToVector3d(b + ((-abP-abV)*0.707f-abP)*0.541f *lineWidth,zidx); LindS1[9] = ToVector3d(b + ((-abP-abV)*0.707f-abV)*0.541f *lineWidth,zidx); // 添加最后一个点的左右点 LindE1[0] = ToVector3d(a,zidx); LindE1[1] = ToVector3d(aR,zidx); LindE1[2] = ToVector3d(aL,zidx); LindE1[3] = ToVector3d(a + abP * lineWidth,zidx); LindE1[4] = ToVector3d(a + (abP-abV)*0.707f * lineWidth,zidx); LindE1[5] = ToVector3d(a + (abP+abV)*0.707f * lineWidth,zidx); LindE1[6] = ToVector3d(a + ((abP-abV)*0.707f-abV)*0.541f *lineWidth,zidx); LindE1[7] = ToVector3d(a + ((abP-abV)*0.707f+abP)*0.541f *lineWidth,zidx); LindE1[8] = ToVector3d(a + ((abP+abV)*0.707f+abP)*0.541f *lineWidth,zidx); LindE1[9] = ToVector3d(a + ((abP+abV)*0.707f+abV)*0.541f *lineWidth,zidx); for (int j=0;j<10;++j) { vertexAcc.pos = LindS1[j];outarray->push_back(vertexAcc); } idx->push_back(u32(i_idx + 1)); idx->push_back(u32(i_idx + 0)); idx->push_back(u32(i_idx + 6)); idx->push_back(u32(i_idx + 6)); idx->push_back(u32(i_idx + 0)); idx->push_back(u32(i_idx + 4)); idx->push_back(u32(i_idx + 4)); idx->push_back(u32(i_idx + 0)); idx->push_back(u32(i_idx + 7)); idx->push_back(u32(i_idx + 7)); idx->push_back(u32(i_idx + 0)); idx->push_back(u32(i_idx + 3)); idx->push_back(u32(i_idx + 3)); idx->push_back(u32(i_idx + 0)); idx->push_back(u32(i_idx + 8)); idx->push_back(u32(i_idx + 8)); idx->push_back(u32(i_idx + 0)); idx->push_back(u32(i_idx + 5)); idx->push_back(u32(i_idx + 5)); idx->push_back(u32(i_idx + 0)); idx->push_back(u32(i_idx + 9)); idx->push_back(u32(i_idx + 9)); idx->push_back(u32(i_idx + 0)); idx->push_back(u32(i_idx + 2)); u32 m_idx = i_idx+10; for (int j=0;j<10;++j) { vertexAcc.pos = LindE1[j];outarray->push_back(vertexAcc); } idx->push_back(u32(m_idx + 1)); idx->push_back(u32(m_idx + 0)); idx->push_back(u32(m_idx + 9)); idx->push_back(u32(m_idx + 9)); idx->push_back(u32(m_idx + 0)); idx->push_back(u32(m_idx + 5)); idx->push_back(u32(m_idx + 5)); idx->push_back(u32(m_idx + 0)); idx->push_back(u32(m_idx + 8)); idx->push_back(u32(m_idx + 8)); idx->push_back(u32(m_idx + 0)); idx->push_back(u32(m_idx + 3)); idx->push_back(u32(m_idx + 3)); idx->push_back(u32(m_idx + 0)); idx->push_back(u32(m_idx + 7)); idx->push_back(u32(m_idx + 7)); idx->push_back(u32(m_idx + 0)); idx->push_back(u32(m_idx + 4)); idx->push_back(u32(m_idx + 4)); idx->push_back(u32(m_idx + 0)); idx->push_back(u32(m_idx + 6)); idx->push_back(u32(m_idx + 6)); idx->push_back(u32(m_idx + 0)); idx->push_back(u32(m_idx + 2)); idx->push_back(u32(i_idx + 1)); idx->push_back(u32(i_idx + 12)); idx->push_back(u32(i_idx + 11)); idx->push_back(u32(i_idx + 1)); idx->push_back(u32(i_idx + 2)); idx->push_back(u32(i_idx + 12)); i_idx += 20; } }
相关文章推荐
- 如何解决ROS "roscore command not found"
- iptables模板
- Linux原始套接字学习总结
- ActiveMQ实现负载均衡+高可用部署方案
- Linux主机之间权限访问与开通
- 王高利:在apache2.4上配置awstats后没权限,显示源码问题,报错总结
- linux Rootkit
- ios 架构之谈
- TortoiseGit使用密钥连接服务器
- Linux_CentOS6.5安装vncserver实现图形化访问
- [nginx] 网上最全面nginx教程(近100篇文章整理)
- centos 7 mysql 离线安装教程
- 杀死Linux中的defunct进程(僵尸进程)的方法指南
- Shader之学习笔记四
- mybatis获取xml文件中property对应的column
- Docker教程:Docker镜像导出及迁移
- shell awk高级应用
- Docker教程:Docker镜像导出及迁移
- NSTimer、 NSTask、 NSThread 和 NSRunloop 之间的区别
- zabbix图中中文乱码解决