1 /**
2 Copyright: Copyright (c) 2014-2016 Andrey Penechko.
3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 
7 module voxelman.utils.renderutils;
8 
9 import std.experimental.logger;
10 
11 import derelict.opengl3.gl3;
12 import voxelman.container.buffer;
13 import voxelman.math;
14 import voxelman.model.vertex;
15 
16 import voxelman.block.utils : Side, faces;
17 
18 alias ColoredVertex = VertexPosColor!(float, ubyte);
19 
20 alias Color3ub = Vector!(ubyte, 3);
21 
22 enum Colors : Color3ub
23 {
24 	black = Color3ub(0, 0, 0),
25 	white = Color3ub(255, 255, 255),
26 	red = Color3ub(255, 0, 0),
27 	green = Color3ub(0, 255, 0),
28 	blue = Color3ub(0, 0, 255),
29 	cyan = Color3ub(0, 255, 255),
30 	magenta = Color3ub(255, 0, 255),
31 	yellow = Color3ub(255, 255, 0),
32 	gray = Color3ub(128, 128, 128),
33 }
34 
35 
36 Color3ub[] colorsArray =
37 [
38 Colors.black, Colors.white, Colors.red,
39 Colors.green, Colors.blue, Colors.cyan,
40 Colors.magenta, Colors.yellow
41 ];
42 
43 struct Batch
44 {
45 	Buffer!ColoredVertex triBuffer;
46 	Buffer!ColoredVertex lineBuffer;
47 	Buffer!ColoredVertex pointBuffer;
48 
49 	void putCube(vec3 pos, vec3 size, Color3ub color, bool fill)
50 	{
51 		if (fill)
52 			putFilledBlock(triBuffer, pos, size, color);
53 		else
54 			putLineBlock(lineBuffer, pos, size, color);
55 	}
56 
57 	void putCubeFace(vec3 cubePos, vec3 size, Side side, Color3ub color, bool fill)
58 	{
59 		if (fill)
60 			putFilledSide(triBuffer, cubePos, size, side, color);
61 		else
62 			putLineSide(lineBuffer, cubePos, size, side, color);
63 	}
64 
65 	void putLine(vec3 start, vec3 end, Color3ub color)
66 	{
67 		lineBuffer.put(
68 			ColoredVertex(start, color),
69 			ColoredVertex(end, color));
70 	}
71 
72 	void putPoint(vec3 pos, Color3ub color)
73 	{
74 		pointBuffer.put(ColoredVertex(pos, color));
75 	}
76 
77 	void put3dGrid(vec3 pos, ivec3 count, vec3 offset, Color3ub color)
78 	{
79 		// x
80 		foreach(i; 0..count.y)
81 		foreach(j; 0..count.z)
82 		{
83 			float y = pos.y + i * offset.y;
84 			float z = pos.z + j * offset.z;
85 			vec3 start = vec3(pos.x, y, z);
86 			vec3 end = vec3(pos.x + (count.x-1) * offset.x, y, z);
87 			putLine(start, end, color);
88 		}
89 
90 		// y
91 		foreach(i; 0..count.x)
92 		foreach(j; 0..count.z)
93 		{
94 			float x = pos.x + i * offset.x;
95 			float z = pos.z + j * offset.z;
96 			vec3 start = vec3(x, pos.y, z);
97 			vec3 end = vec3(x, pos.y + (count.y-1) * offset.y, z);
98 			putLine(start, end, color);
99 		}
100 
101 		// z
102 		foreach(i; 0..count.x)
103 		foreach(j; 0..count.y)
104 		{
105 			float x = pos.x + i * offset.x;
106 			float y = pos.y + j * offset.y;
107 			vec3 start = vec3(x, y, pos.z);
108 			vec3 end = vec3(x, y, pos.z + (count.z-1) * offset.z);
109 			putLine(start, end, color);
110 		}
111 	}
112 
113 	void reset()
114 	{
115 		triBuffer.clear();
116 		lineBuffer.clear();
117 		pointBuffer.clear();
118 	}
119 }
120 
121 void putFilledBlock(ref Buffer!ColoredVertex output, vec3 pos, vec3 size, Color3ub color)
122 {
123 	output.reserve(6 * 6); // 6 faces, 6 points per edge
124 
125 	for (size_t i = 0; i!=18*6; i+=3)
126 	{
127 		auto v = ColoredVertex(
128 			faces[i  ]*size.x + pos.x,
129 			faces[i+1]*size.y + pos.y,
130 			faces[i+2]*size.z + pos.z,
131 			color);
132 		output.put(v);
133 	}
134 }
135 
136 void putLineBlock(ref Buffer!ColoredVertex output, vec3 pos, vec3 size, Color3ub color)
137 {
138 	output.reserve(12 * 2); // 12 edges, 2 points per edge
139 
140 	for (size_t i = 0; i!=12*2*3; i+=3)
141 	{
142 		auto v = ColoredVertex(
143 			cubeLines[i  ]*size.x + pos.x,
144 			cubeLines[i+1]*size.y + pos.y,
145 			cubeLines[i+2]*size.z + pos.z,
146 			color);
147 		output.put(v);
148 	}
149 }
150 
151 void putFilledSide(ref Buffer!ColoredVertex output, vec3 pos, vec3 size, Side side, Color3ub color)
152 {
153 	output.reserve(6);
154 
155 	for (size_t i = side * 18; i!=side*18+18; i+=3)
156 	{
157 		auto v = ColoredVertex(
158 			faces[i  ]*size.x + pos.x,
159 			faces[i+1]*size.y + pos.y,
160 			faces[i+2]*size.z + pos.z,
161 			color);
162 		output.put(v);
163 	}
164 }
165 
166 void putLineSide(ref Buffer!ColoredVertex output, vec3 pos, vec3 size, Side side, Color3ub color)
167 {
168 	output.reserve(8); // 4 edges, 2 points per edge
169 
170 	for (size_t i = side * 24; i!=side*24+24; i+=3)
171 	{
172 		auto v = ColoredVertex(
173 			cubeLineSides[i  ]*size.x + pos.x,
174 			cubeLineSides[i+1]*size.y + pos.y,
175 			cubeLineSides[i+2]*size.z + pos.z,
176 			color);
177 		output.put(v);
178 	}
179 }
180 
181 immutable ubyte[] cubeLines =
182 [
183 	0, 0, 0,  1, 0, 0,
184 	1, 0, 0,  1, 0, 1,
185 	1, 0, 1,  0, 0, 1,
186 	0, 0, 1,  0, 0, 0,
187 
188 	0, 1, 0,  1, 1, 0,
189 	1, 1, 0,  1, 1, 1,
190 	1, 1, 1,  0, 1, 1,
191 	0, 1, 1,  0, 1, 0,
192 
193 	0, 0, 0,  0, 1, 0,
194 	1, 0, 0,  1, 1, 0,
195 	1, 0, 1,  1, 1, 1,
196 	0, 0, 1,  0, 1, 1,
197 ];
198 
199 immutable ubyte[] cubeLineSides =
200 [
201 	0, 0, 0, // zneg
202 	1, 0, 0,
203 	0, 1, 0,
204 	1, 1, 0,
205 	0, 0, 0,
206 	0, 1, 0,
207 	1, 0, 0,
208 	1, 1, 0,
209 
210 	0, 0, 1, // zpos
211 	1, 0, 1,
212 	0, 1, 1,
213 	1, 1, 1,
214 	0, 0, 1,
215 	0, 1, 1,
216 	1, 0, 1,
217 	1, 1, 1,
218 
219 	1, 0, 0, // xpos
220 	1, 0, 1,
221 	1, 1, 0,
222 	1, 1, 1,
223 	1, 0, 0,
224 	1, 1, 0,
225 	1, 0, 1,
226 	1, 1, 1,
227 
228 	0, 0, 0, // xneg
229 	0, 0, 1,
230 	0, 1, 0,
231 	0, 1, 1,
232 	0, 0, 0,
233 	0, 1, 0,
234 	0, 0, 1,
235 	0, 1, 1,
236 
237 	1, 1, 1, // ypos
238 	0, 1, 1,
239 	1, 1, 0,
240 	0, 1, 0,
241 	1, 1, 1,
242 	1, 1, 0,
243 	0, 1, 1,
244 	0, 1, 0,
245 
246 	1, 0, 1, // yneg
247 	0, 0, 1,
248 	1, 0, 0,
249 	0, 0, 0,
250 	1, 0, 1,
251 	1, 0, 0,
252 	0, 0, 1,
253 	0, 0, 0,
254 ];