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 
7 module voxelman.model.vertex;
8 
9 import std.meta;
10 import voxelman.graphics.gl;
11 import voxelman.math;
12 
13 align(4) struct VertexPosColor(PosType, uint pos_size, ColType, uint col_size)
14 {
15 	static if (pos_size == 2)
16 	this(Pos, Col)(Pos x, Pos y, Col color)
17 	{
18 		this.position.arrayof = [x, y];
19 		this.color = Vector!(ColType, col_size)(color);
20 	}
21 
22 	static if (pos_size == 3)
23 	this(Pos, Col)(Pos x, Pos y, Pos z, Col color)
24 	{
25 		this.position.arrayof = [x, y, z];
26 		this.color = Vector!(ColType, col_size)(color);
27 	}
28 
29 	static if (pos_size == 3)
30 	this(Pos, Col)(Pos x, Pos y, Pos z, ColType[col_size] color)
31 	{
32 		this.position.arrayof = [x, y, z];
33 		this.color.arrayof = color;
34 	}
35 
36 	static if (col_size == 4 && is(ColType == ubyte))
37 	this(Vector!(PosType, pos_size) p, ColType[3] color)
38 	{
39 		this.position = p;
40 		this.color.arrayof = [color[0], color[1], color[2], 255];
41 	}
42 
43 	static if (col_size == 4 && is(ColType == ubyte))
44 	this(Vector!(PosType, pos_size) p, Vector!(ColType, 3) color)
45 	{
46 		this.position = p;
47 		this.color.arrayof = [color.r, color.g, color.b, 255];
48 	}
49 
50 	this(Vector!(PosType, pos_size) p, Vector!(ColType, col_size) color)
51 	{
52 		this.position = p;
53 		this.color = color;
54 	}
55 
56 	void addOffset(vec3 offset)
57 	{
58 		position += Vector!(PosType, pos_size)(offset);
59 	}
60 
61 	align(4):
62 	Vector!(PosType, pos_size) position;
63 	Vector!(ColType, col_size) color;
64 
65 	void toString()(scope void delegate(const(char)[]) sink) const
66 	{
67 		import std.format : formattedWrite;
68 		sink.formattedWrite("V!(%s,%s)(%s, %s)", stringof(PosType), stringof(ColType), position, color);
69 	}
70 
71 	static void setAttributes() {
72 		enum Size = typeof(this).sizeof;
73 		setupAttribute!(0, pos_size, PosType, false, true, Size, position.offsetof);
74 		setupAttribute!(1, col_size, ColType, true, true, Size, color.offsetof);
75 	}
76 }
77 
78 align(4) struct VertexPosUvColor(PosType, uint pos_size, UvType, uint uv_size, ColType, uint col_size)
79 {
80 	align(4):
81 	Vector!(PosType, pos_size) position;
82 	Vector!(UvType, uv_size) uv;
83 	Vector!(ColType, col_size) color;
84 
85 	void addOffset(vec3 offset)
86 	{
87 		position += Vector!(PosType, pos_size)(offset);
88 	}
89 
90 	void toString()(scope void delegate(const(char)[]) sink) const
91 	{
92 		import std.format : formattedWrite;
93 		sink.formattedWrite("V!(%s,%s,%s)(%s, %s, %s)",
94 			stringof(PosType), stringof(UvType), stringof(ColType),
95 			position, uv, color);
96 	}
97 
98 	static void setAttributes() {
99 		enum Size = typeof(this).sizeof;
100 		setupAttribute!(0, pos_size, PosType, false, true, Size, position.offsetof);
101 		setupAttribute!(1, uv_size, UvType, true, true, Size, uv.offsetof);
102 		setupAttribute!(2, col_size, ColType, true, true, Size, color.offsetof);
103 	}
104 }
105 
106 void setupAttribute(int index, int numComponents, AttrT, bool normalize, bool isFloatAttrib, int totalVertSize, int offset)()
107 {
108 	glEnableVertexAttribArray(index);
109 	static if (isFloatAttrib)
110 	{
111 		enum bool doPosNomalization = normalize && normalizeAttributeType!AttrT;
112 		checkgl!glVertexAttribPointer(index, numComponents, glTypeOf!AttrT, doPosNomalization, totalVertSize, cast(void*)offset);
113 	}
114 	else
115 	{
116 		static if (normalizeAttributeType!AttrT) // only if integer
117 			checkgl!glVertexAttribIPointer(index, numComponents, glTypeOf!AttrT, totalVertSize, cast(void*)offset);
118 		else
119 			checkgl!glVertexAttribPointer(index, numComponents, glTypeOf!AttrT, false, totalVertSize, cast(void*)offset);
120 	}
121 }
122 
123 enum glTypeOf(T) = glTypes[glTypeIndex!T];
124 enum normalizeAttributeType(T) = normalizeTypeTable[glTypeIndex!T];
125 
126 alias glTypeIndex(T) = staticIndexOf!(T,
127 	byte,  // GL_BYTE
128 	ubyte, // GL_UNSIGNED_BYTE
129 	short, // GL_SHORT
130 	ushort,// GL_UNSIGNED_SHORT
131 	int,   // GL_INT
132 	uint,  // GL_UNSIGNED_INT
133 	half,  // GL_HALF_FLOAT
134 	float, // GL_FLOAT
135 	double,// GL_DOUBLE
136 	);
137 
138 static immutable uint[] glTypes = [
139 	GL_BYTE,
140 	GL_UNSIGNED_BYTE,
141 	GL_SHORT,
142 	GL_UNSIGNED_SHORT,
143 	GL_INT,
144 	GL_UNSIGNED_INT,
145 	GL_HALF_FLOAT,
146 	GL_FLOAT,
147 	GL_DOUBLE,
148 ];
149 
150 static immutable bool[] normalizeTypeTable = [
151 	true,  // GL_BYTE
152 	true,  // GL_UNSIGNED_BYTE
153 	true,  // GL_SHORT
154 	true,  // GL_UNSIGNED_SHORT
155 	true,  // GL_INT
156 	true,  // GL_UNSIGNED_INT
157 	false, // GL_HALF_FLOAT
158 	false, // GL_FLOAT
159 	false, // GL_DOUBLE
160 ];