1 module ws.gl.batch;
2 
3 import ws.gl.gl, ws.exception, ws.io;
4 
5 __gshared:
6 
7 
8 class Batch {
9 	
10 	alias float[2] tex;
11 	alias float[3] vec;
12 	alias float[4] color;
13 	
14 	void begin(int verts, uint type = GL_TRIANGLES){
15 		assert(gl.active());
16 		verticeCount = verts;
17 		currentVert = 0;
18 		this.type = type;
19 		glGenVertexArrays(1, cast(uint*)&vao);
20 		glBindVertexArray(vao);
21 	}
22 	
23 	void finish(){
24 		assert(!done);
25 		foreach(array; arrays){
26 			glBindBuffer(GL_ARRAY_BUFFER, array.globj);
27 			glUnmapBuffer(GL_ARRAY_BUFFER);
28 		}
29 
30 		glBindVertexArray(vao);
31 
32 		foreach(array; arrays){
33 			glBindBuffer(GL_ARRAY_BUFFER, array.globj);
34 			glEnableVertexAttribArray(array.attributeId),
35 			glVertexAttribPointer(array.attributeId, array.size, GL_FLOAT, GL_FALSE, 0, null);
36 		}
37 
38 		done = true;
39 		glBindVertexArray(0);
40 	}
41 	
42 	void draw(){
43 		if(!done)
44 			return;
45 		glBindVertexArray(vao);
46 		glDrawArrays(type, 0, verticeCount);
47 		//glBindVertexArray(0);
48 	}
49 
50 	void add(vec pos){
51 		addVertex(pos);
52 		currentVert++;
53 	}
54 
55 	void addPoint(vec pos, color col){
56 		addVertex(pos);
57 		addColor(col);
58 		currentVert++;
59 	}
60 
61 	void addPoint(vec pos, vec normal){
62 		addVertex(pos);
63 		addNormal(normal);
64 		currentVert++;
65 	}
66 
67 	void addPoint(vec pos, vec normal, color col){
68 		addVertex(pos);
69 		addNormal(normal);
70 		addColor(col);
71 		currentVert++;
72 	}
73 
74 	void addPoint(vec pos, tex t){
75 		addVertex(pos);
76 		addTex(t);
77 		currentVert++;
78 	}
79 
80 	void addPoint(vec pos, vec normal, tex t){
81 		addVertex(pos);
82 		addNormal(normal);
83 		addTex(t);
84 		currentVert++;
85 	}
86 
87 	/*~this(){
88 		glDeleteVertexArrays(1, &vao);
89 	}*/
90 	
91 	void updateVertices(float[] data, size_t pos = 0, size_t length = 1){
92 		glBindBuffer(GL_ARRAY_BUFFER, vertices.globj);
93 		glBufferSubData(GL_ARRAY_BUFFER, pos*3*float.sizeof, length*3*float.sizeof, data.ptr);
94 	} 
95 	
96 	protected:
97 		
98 		uint vao;
99 		uint type;
100 		
101 		bool done = false;
102 		int verticeCount = 0;
103 		int currentVert = 0;
104 		
105 		class Array {
106 			this(int size, uint attributeId){
107 				assert(!done);
108 				assert(vao);
109 				this.size = size;
110 				this.attributeId = attributeId;
111 				glGenBuffers(1, cast(uint*)&globj);
112 				glBindBuffer(GL_ARRAY_BUFFER, globj);
113 				glBufferData(GL_ARRAY_BUFFER, float.sizeof*size*verticeCount, null, GL_DYNAMIC_DRAW);
114 				glBindBuffer(GL_ARRAY_BUFFER, globj);
115 				array = cast(float*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
116 				arrays ~= this;
117 				//gl.check();
118 				if(!array)
119 					exception("Failed to create array buffer");
120 			}
121 			float* array = null;
122 			uint globj = 0;
123 			uint size;
124 			uint attributeId;
125 			/*~this(){
126 				glDeleteBuffers(1, &globj);
127 			}*/
128 		}
129 		
130 		Array vertices;
131 		Array normals;
132 		Array colors;
133 		Array texCoords;
134 		Array[] arrays;
135 	
136 		void addVertex(vec v){
137 			if(!vertices)
138 				vertices = new Array(3, gl.attributeVertex);
139 			float* o = vertices.array+currentVert*3;
140 			/+
141 			o[0] = v[0];
142 			o[1] = v[1];
143 			o[2] = v[2];
144 			+/
145 			o[0..3] = v[0..3];
146 		}
147 
148 		void addNormal(vec v){
149 			if(!normals)
150 				normals = new Array(3, gl.attributeNormal);
151 			float* o = normals.array+currentVert*3;
152 			/+
153 			o[0] = v[0];
154 			o[1] = v[1];
155 			o[2] = v[2];
156 			+/
157 			o[0..3] = v[0..3];
158 		}
159 
160 		void addColor(color c){
161 			if(!colors)
162 				colors = new Array(4, gl.attributeColor);
163 			float* o = colors.array+currentVert*4;
164 			o[0] = c[0];
165 			o[1] = c[1];
166 			o[2] = c[2];
167 			o[3] = c[3];
168 		}
169 
170 		void addTex(tex t){
171 			if(!texCoords)
172 				texCoords = new Array(2, gl.attributeTexture);
173 			texCoords.array[currentVert*2] = t[0];
174 			texCoords.array[currentVert*2+1] = t[1];
175 		}
176 
177 }