1 /**
2 Copyright: Copyright (c) 2016-2018 Andrey Penechko.
3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 module voxelman.graphics.batch;
7 
8 import voxelman.container.buffer;
9 import voxelman.model.vertex;
10 import voxelman.geometry;
11 import voxelman.math;
12 import voxelman.graphics;
13 
14 alias ColoredVertex = VertexPosColor!(float, 3, ubyte, 4);
15 
16 struct Batch
17 {
18 	Buffer!ColoredVertex triBuffer;
19 	Buffer!ColoredVertex lineBuffer;
20 	Buffer!ColoredVertex pointBuffer;
21 
22 	void putSolidMesh(VertRange)(VertRange vertices, vec3 offset)
23 	{
24 		putMesh(triBuffer, vertices, offset);
25 	}
26 
27 	/// Creates a batch with a centered cube with 3 radiuses (not dimensions).
28 	static Batch cube(T)(Vector!(T, 3) halfSize, Color4ub color, bool fill)
29 	{
30 		Batch b;
31 		b.putCube(-halfSize, halfSize * 2, color, fill);
32 		return b;
33 	}
34 
35 	/// Creates a batch with a centered cube with 3 radiuses (not dimensions) and offset.
36 	static Batch cube(T)(Vector!(T, 3) halfSize, Color4ub color, bool fill, Vector!(T, 3) offset)
37 	{
38 		Batch b;
39 		b.putCube(-halfSize + offset, halfSize * 2, color, fill);
40 		return b;
41 	}
42 
43 	/// Creates a batch with a centered cube with 3 radiuses (not dimensions) where all dimensions are 1/32th (1 pixel in a 32x32 texture).
44 	static Batch cube32(T)(Vector!(T, 3) halfSize, Color4ub color, bool fill)
45 	{
46 		Batch b;
47 		b.putCube(-halfSize / 32.0, halfSize / 16.0, color, fill);
48 		return b;
49 	}
50 
51 	/// Creates a batch with a centered cube with 3 radiuses (not dimensions) and offset where all dimensions are 1/32th (1 pixel in a 32x32 texture).
52 	static Batch cube32(T)(Vector!(T, 3) halfSize, Color4ub color, bool fill, Vector!(T, 3) offset)
53 	{
54 		Batch b;
55 		b.putCube((-halfSize + offset) / 32.0, halfSize / 16.0, color, fill);
56 		return b;
57 	}
58 
59 	void putCube(T1, T2)(Vector!(T1, 3) pos, Vector!(T2, 3) size, Color4ub color, bool fill)
60 	{
61 		if (fill)
62 			putFilledBlock(triBuffer, vec3(pos), vec3(size), color);
63 		else
64 			putLineBlock(lineBuffer, vec3(pos), vec3(size), color);
65 	}
66 
67 	void putCubeFace(T1, T2)(Vector!(T1, 3) cubePos, Vector!(T2, 3) size, CubeSide side, Color4ub color, bool fill)
68 	{
69 		if (fill)
70 			putFilledSide(triBuffer, cubePos, size, side, color);
71 		else
72 			putLineSide(lineBuffer, cubePos, size, side, color);
73 	}
74 
75 	void putLine(T1, T2)(Vector!(T1, 3) start, Vector!(T2, 3) end, Color4ub color)
76 	{
77 		lineBuffer.put(
78 			ColoredVertex(start, color),
79 			ColoredVertex(end, color));
80 	}
81 
82 	void putLine(T1, T2)(Vector!(T1, 3) start, Vector!(T2, 3) end, Color4ub color1, Color4ub color2)
83 	{
84 		lineBuffer.put(
85 			ColoredVertex(start, color1),
86 			ColoredVertex(end, color2));
87 	}
88 
89 	void putLineVolumetric(T1, T2)(Vector!(T1, 3) start, Vector!(T2, 3) end, Color4ub color)
90 	{
91 		lineBuffer.put(
92 			ColoredVertex(start, color),
93 			ColoredVertex(end, color));
94 	}
95 
96 	void putPoint(T)(Vector!(T, 3) pos, Color4ub color)
97 	{
98 		pointBuffer.put(ColoredVertex(pos, color));
99 	}
100 
101 	void put3dGrid(T1, T2)(Vector!(T1, 3) pos, ivec3 count, Vector!(T2, 3) offset, Color4ub color)
102 	{
103 		// x
104 		foreach(i; 0..count.y)
105 		foreach(j; 0..count.z)
106 		{
107 			float y = pos.y + i * offset.y;
108 			float z = pos.z + j * offset.z;
109 			vec3 start = vec3(pos.x, y, z);
110 			vec3 end = vec3(pos.x + (count.x-1) * offset.x, y, z);
111 			putLine(start, end, color);
112 		}
113 
114 		// y
115 		foreach(i; 0..count.x)
116 		foreach(j; 0..count.z)
117 		{
118 			float x = pos.x + i * offset.x;
119 			float z = pos.z + j * offset.z;
120 			vec3 start = vec3(x, pos.y, z);
121 			vec3 end = vec3(x, pos.y + (count.y-1) * offset.y, z);
122 			putLine(start, end, color);
123 		}
124 
125 		// z
126 		foreach(i; 0..count.x)
127 		foreach(j; 0..count.y)
128 		{
129 			float x = pos.x + i * offset.x;
130 			float y = pos.y + j * offset.y;
131 			vec3 start = vec3(x, y, pos.z);
132 			vec3 end = vec3(x, y, pos.z + (count.z-1) * offset.z);
133 			putLine(start, end, color);
134 		}
135 	}
136 
137 	void reset()
138 	{
139 		triBuffer.clear();
140 		lineBuffer.clear();
141 		pointBuffer.clear();
142 	}
143 }
144 
145 void putMesh(V, VertRange)(ref Buffer!V output, VertRange vertices, vec3 offset)
146 {
147 	foreach(vert; vertices)
148 	{
149 		vert.addOffset(offset);
150 		output.put(vert);
151 	}
152 }