zoukankan      html  css  js  c++  java
  • 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;
            }
    
    
        }
    }
  • 相关阅读:
    中断 异常 系统调用的比较
    线性结构-线性表
    数据结构引例
    友链
    投喂
    给出两个单词(start和end)与一个字典,找出从start到end的最短转换序列
    C++类内存分布
    内存的堆分配和栈分配 & 字符数组,字符指针,Sizeof总结
    C++内存管理学习笔记(7)
    C++内存管理学习笔记(6)
  • 原文地址:https://www.cnblogs.com/xpvincent/p/2940341.html
Copyright © 2011-2022 走看看