OPENGL: 多边形网格化(tessellation)

虽然在OpenGL中可以使用glBegin(GL_POLYGON)来画一个多边形,但是它只能实现简单的凸多边形。对于一些复杂的多边形,比如凹多边形,或者有实心有空心的多边形,OpenGL的glBegin(GL_POLYGON)就不能满足需求了。通常可以采用一种叫做"分格化"的方法来画复杂的多边形。

1. 实现方法

要用分格化的方法画多边形,步骤如下:

  a. gluNewTess(); //创建一个新的分格化对象
  b. gluTessCallback(); //注册回调函数,完成分格化的一些操作,照着写就行了。
  c. gluTessProperty(); //可有可无的,设置一些分格化的属性值
  d. gluTessBeginPolygon(); //开始画多边形
      draw polygon...//在这里画多边形,一个一个点画就可以,最后一个点会和第一个点自动连接起来
      gluTessEdnPolygon(); //结束画多边形
  e. gluDeleteTess(); //删除分格化对象


2. 代码

用C#写了个OpenTK 的Tessallation调用类,代码如下:

使用时需要在项目中添加引用OpenTK.Compatibility.dll。

 

using System;
using System.Collections.Generic;
using OpenTK;
using OpenTK.Graphics;
using System.Runtime.InteropServices;

namespace Render
{
    public static class Tessellation
    {
        //Define the signatures for the callback functions, and declare the callbacks.
        delegate void BeginCallbackDelegate(BeginMode mode);
        delegate void EndCallbackDelegate();
        delegate void VertexCallbackDelegate(IntPtr v);
        delegate void ErrorCallbackDelegate(OpenTK.Graphics.GluErrorCode code);
        unsafe delegate void CombineCallbackDelegate(
            [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)]double[] coordinates,
            [MarshalAs(UnmanagedType.LPArray, SizeConst = 4)]double*[] vertexData,
            [MarshalAs(UnmanagedType.LPArray, SizeConst = 4)]float[] weight,
            double** dataOut);

        static bool InvalidPolygon;
        static IntPtr tess;
        static unsafe double*[] combineData;
        static int data_index = 0;

        unsafe static public bool Triangulate(List<Vector3> vertexes)
        {
            tess = Glu.NewTess();

            //register tesselation callbacks
            Glu.TessCallback(tess, TessCallback.TessVertex, new VertexCallbackDelegate(VertexCallback));
            Glu.TessCallback(tess, TessCallback.TessBegin, new BeginCallbackDelegate(BeginCallback));
            Glu.TessCallback(tess, TessCallback.TessEnd, new EndCallbackDelegate(EndCallback));
            Glu.TessCallback(tess, TessCallback.TessError, new ErrorCallbackDelegate(ErrorCallback));
            Glu.TessCallback(tess, TessCallback.TessCombine, new CombineCallbackDelegate(CombineCallback));
            
            //plot polygon
            Glu.TessBeginPolygon(tess, IntPtr.Zero);
            Glu.TessBeginContour(tess);

            GL.Normal3(Vector3.Cross(vertexes[1] - vertexes[0], vertexes[2] - vertexes[0]));
            for (int i= 0; i< vertexes.Count; i++)
            {
                double[] position = new double[3] { vertexes[i].X, vertexes[i].Y, vertexes[i].Z };
                Glu.TessVertex(tess, position, position);
            }
            Glu.TessEndContour(tess);
            
            if (InvalidPolygon)
            {
                //destroy the tesselation object
                Glu.DeleteTess(tess);
                tess = IntPtr.Zero;

                return false; //error in polygon definition
            }
            else
            {
                // end polygon
                Glu.TessEndPolygon(tess);

                //destroy the tessellation object
                Glu.DeleteTess(tess);
                tess = IntPtr.Zero;

                //The Indices object is now valid
                return true;
            }
        }

        static void BeginCallback(BeginMode mode)
        {
            GL.Begin(mode);
        }

        static void EndCallback()
        {
            GL.End();
        }

        static void VertexCallback(IntPtr v)
        {
            unsafe { GL.Vertex3((double*)v); }
        }

        static void ErrorCallback(OpenTK.Graphics.GluErrorCode code)
        {
            //some error ocurred, mark this triangulation as invalid
            InvalidPolygon = true;
        }

        unsafe static void CombineCallback(double[] coordinates, double*[] data, float[] weight, double** dataOut)
        {   
            //This means the polygon is self-intersecting
            InvalidPolygon = true;
        }


    }
}

 

 

posted @ 2013-03-02 19:11  马语者  阅读(8462)  评论(2编辑  收藏  举报