1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
#region --- License ---
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
* See license.txt for license info
*/
#endregion
using System;
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace Examples.Shapes
{
// Abstract base class for procedurally generated geometry
//
// All classes derived from it must produce Counter-Clockwise (CCW) primitives.
// Derived classes must create a single VBO and IBO, without primitive restarts for strips.
// Uses an double-precision all-possible-attributes VertexT2dN3dV3d Array internally.
// Cannot directly use VBO, but has Get-methods to retrieve VBO-friendly data.
// Can use a Display List to prevent repeated immediate mode draws.
//
public abstract class DrawableShape: IDisposable
{
protected PrimitiveType PrimitiveMode;
protected VertexT2dN3dV3d[] VertexArray;
protected uint[] IndexArray;
public int GetTriangleCount
{
get
{
switch ( PrimitiveMode )
{
case PrimitiveType.Triangles:
if ( IndexArray != null )
{
return IndexArray.Length / 3;
} else
{
return VertexArray.Length / 3;
}
// break;
default: throw new NotImplementedException("Unknown primitive type.");
}
}
}
#region Display List
private bool UseDisplayList;
private int DisplayListHandle = 0;
#endregion Display List
public DrawableShape( bool useDisplayList )
{
UseDisplayList = useDisplayList;
PrimitiveMode = PrimitiveType.Triangles;
VertexArray = null;
IndexArray = null;
}
#region Convert to VBO
public void GetArraysforVBO(out PrimitiveType primitives, out VertexT2dN3dV3d[] vertices, out uint[] indices)
{
primitives = PrimitiveMode;
vertices = new VertexT2dN3dV3d[VertexArray.Length];
for (uint i = 0; i < VertexArray.Length; i++)
{
vertices[i].TexCoord = VertexArray[i].TexCoord;
vertices[i].Normal = VertexArray[i].Normal;
vertices[i].Position = VertexArray[i].Position;
}
indices = IndexArray;
}
public void GetArraysforVBO(out PrimitiveType primitives, out VertexT2fN3fV3f[] vertices, out uint[] indices)
{
primitives = PrimitiveMode;
vertices = new VertexT2fN3fV3f[VertexArray.Length];
for (uint i = 0; i < VertexArray.Length; i++)
{
vertices[i].TexCoord = (Vector2)VertexArray[i].TexCoord;
vertices[i].Normal = (Vector3)VertexArray[i].Normal;
vertices[i].Position = (Vector3)VertexArray[i].Position;
}
indices = IndexArray;
}
public void GetArraysforVBO(out PrimitiveType primitives, out VertexT2hN3hV3h[] vertices, out uint[] indices)
{
primitives = PrimitiveMode;
vertices = new VertexT2hN3hV3h[VertexArray.Length];
for (uint i = 0; i < VertexArray.Length; i++)
{
vertices[i].TexCoord = (Vector2h)VertexArray[i].TexCoord;
vertices[i].Normal = (Vector3h)VertexArray[i].Normal;
vertices[i].Position = (Vector3h)VertexArray[i].Position;
}
indices = IndexArray;
}
#endregion Convert to VBO
private void DrawImmediateMode()
{
GL.Begin( PrimitiveMode );
{
if ( IndexArray == null )
foreach ( VertexT2dN3dV3d v in VertexArray )
{
GL.TexCoord2( v.TexCoord.X, v.TexCoord.Y );
GL.Normal3( v.Normal.X, v.Normal.Y, v.Normal.Z );
GL.Vertex3( v.Position.X, v.Position.Y, v.Position.Z );
} else
{
for ( uint i = 0; i < IndexArray.Length; i++ )
{
uint index = IndexArray[i];
GL.TexCoord2( VertexArray[index].TexCoord.X, VertexArray[index].TexCoord.Y );
GL.Normal3( VertexArray[index].Normal.X, VertexArray[index].Normal.Y, VertexArray[index].Normal.Z );
GL.Vertex3( VertexArray[index].Position.X, VertexArray[index].Position.Y, VertexArray[index].Position.Z );
}
}
}
GL.End();
}
/// <summary>
/// Does not touch any state/matrices. Does call Begin/End and Vertex&Co.
/// Creates and compiles a display list if not present yet. Requires an OpenGL context.
/// </summary>
public void Draw()
{
if ( !UseDisplayList )
DrawImmediateMode();
else
if ( DisplayListHandle == 0 )
{
if ( VertexArray == null )
throw new Exception("Cannot draw null Vertex Array.");
DisplayListHandle = GL.GenLists( 1 );
GL.NewList( DisplayListHandle, ListMode.CompileAndExecute );
DrawImmediateMode();
GL.EndList();
} else
GL.CallList( DisplayListHandle );
}
#region IDisposable Members
/// <summary>
/// Removes reference to VertexArray and IndexArray.
/// Deletes the Display List, so it requires an OpenGL context.
/// The instance is effectively destroyed.
/// </summary>
public void Dispose()
{
if ( VertexArray != null )
VertexArray = null;
if ( IndexArray != null )
IndexArray = null;
if ( DisplayListHandle != 0 )
{
GL.DeleteLists( DisplayListHandle, 1 );
DisplayListHandle = 0;
}
}
#endregion
}
}
|