您的位置:首页 > 运维架构

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 )

根据上述获得内容就能得到想要的所有顶点,然后根据这些顶点构建三角面片即可

代码大致如下:
 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;

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: