-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmesh.cs
123 lines (101 loc) · 4.19 KB
/
mesh.cs
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
using System;
using System.Runtime.InteropServices;
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace Template_P3 {
// mesh and loader based on work by JTalton; http://www.opentk.com/node/642
public class Mesh
{
// data members
public ObjVertex[] vertices; // vertex positions, model space
public ObjTriangle[] triangles; // triangles (3 vertex indices)
public ObjQuad[] quads; // quads (4 vertex indices)
int vertexBufferId; // vertex buffer
int triangleBufferId; // triangle buffer
int quadBufferId; // quad buffer
// constructor
public Mesh( string fileName )
{
MeshLoader loader = new MeshLoader();
loader.Load( this, fileName );
}
// initialization; called during first render
public void Prepare( Shader shader )
{
if (vertexBufferId == 0)
{
// generate interleaved vertex data (uv/normal/position (total 8 floats) per vertex)
GL.GenBuffers( 1, out vertexBufferId );
GL.BindBuffer( BufferTarget.ArrayBuffer, vertexBufferId );
GL.BufferData( BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * Marshal.SizeOf( typeof( ObjVertex ) )), vertices, BufferUsageHint.StaticDraw );
// generate triangle index array
GL.GenBuffers( 1, out triangleBufferId );
GL.BindBuffer( BufferTarget.ElementArrayBuffer, triangleBufferId );
GL.BufferData( BufferTarget.ElementArrayBuffer, (IntPtr)(triangles.Length * Marshal.SizeOf( typeof( ObjTriangle ) )), triangles, BufferUsageHint.StaticDraw );
// generate quad index array
GL.GenBuffers( 1, out quadBufferId );
GL.BindBuffer( BufferTarget.ElementArrayBuffer, quadBufferId );
GL.BufferData( BufferTarget.ElementArrayBuffer, (IntPtr)(quads.Length * Marshal.SizeOf( typeof( ObjQuad ) )), quads, BufferUsageHint.StaticDraw );
}
}
// render the mesh using the supplied shader and matrix
public void Render( Shader shader, Matrix4 transform, Matrix4 toWorld, Texture texture )
{
// on first run, prepare buffers
Prepare( shader );
// safety dance
GL.PushClientAttrib( ClientAttribMask.ClientVertexArrayBit );
// enable texture
int texLoc = GL.GetUniformLocation( shader.programID, "pixels" );
GL.Uniform1( texLoc, 0 );
GL.ActiveTexture( TextureUnit.Texture0 );
GL.BindTexture( TextureTarget.Texture2D, texture.id );
// enable shader
GL.UseProgram( shader.programID );
// pass transform to vertex shader
GL.UniformMatrix4( shader.uniform_mview, false, ref transform );
GL.UniformMatrix4(shader.uniform_2wrld, false, ref toWorld);
// enable position, normal and uv attributes
GL.EnableVertexAttribArray( shader.attribute_vpos );
GL.EnableVertexAttribArray( shader.attribute_vnrm );
GL.EnableVertexAttribArray( shader.attribute_vuvs );
// bind interleaved vertex data
GL.EnableClientState( ArrayCap.VertexArray );
GL.BindBuffer( BufferTarget.ArrayBuffer, vertexBufferId );
GL.InterleavedArrays( InterleavedArrayFormat.T2fN3fV3f, Marshal.SizeOf( typeof( ObjVertex ) ), IntPtr.Zero );
// link vertex attributes to shader parameters
GL.VertexAttribPointer( shader.attribute_vuvs, 2, VertexAttribPointerType.Float, false, 32, 0 );
GL.VertexAttribPointer( shader.attribute_vnrm, 3, VertexAttribPointerType.Float, true, 32, 2 * 4 );
GL.VertexAttribPointer( shader.attribute_vpos, 3, VertexAttribPointerType.Float, false, 32, 5 * 4 );
// bind triangle index data and render
GL.BindBuffer( BufferTarget.ElementArrayBuffer, triangleBufferId );
GL.DrawArrays( PrimitiveType.Triangles, 0, triangles.Length * 3 );
// bind quad index data and render
if (quads.Length > 0)
{
GL.BindBuffer( BufferTarget.ElementArrayBuffer, quadBufferId );
GL.DrawArrays( PrimitiveType.Quads, 0, quads.Length * 4 );
}
// restore previous OpenGL state
GL.UseProgram( 0 );
GL.PopClientAttrib();
}
// layout of a single vertex
[StructLayout(LayoutKind.Sequential)] public struct ObjVertex
{
public Vector2 TexCoord;
public Vector3 Normal;
public Vector3 Vertex;
}
// layout of a single triangle
[StructLayout(LayoutKind.Sequential)] public struct ObjTriangle
{
public int Index0, Index1, Index2;
}
// layout of a single quad
[StructLayout(LayoutKind.Sequential)] public struct ObjQuad
{
public int Index0, Index1, Index2, Index3;
}
}
} // namespace Template_P3