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;
        }


    }
}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM