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.world.block.shape;
7 
8 import voxelman.log;
9 import voxelman.core.config;
10 
11 import slope = voxelman.world.mesh.tables.slope;
12 
13 /*
14 block shapes:
15 
16 empty		empty x6
17 full		full x6
18 half		full + empty + half x4
19 stairs		stairs x2 + half x2 + fullx2
20 slope		slope x2 + full x2 + empty x2
21 corner		slope x3 + empty x3
22 inner		slope x3 + full x3
23 pyramid		slope x2 + full x1 + empty x3
24 
25 side masks:
26 
27 empty
28 full
29 half
30 slope
31 stairs
32 
33 corners: (1 corner has mesh, 0 has no mesh)
34 
35 empty		0 x8
36 full		1 x8
37 half		1 x4 + 0 x4
38 stairs		1 x6 + 0 x2
39 slope		1 x6 + 0 x2
40 corner		1 x4 + 0 x4
41 inner		1 x7 + 0 x1
42 pyramid		1 x5 + 0 x5
43 
44 has middle piece
45 
46 empty		no
47 full		no
48 half		yes
49 stairs		yes
50 slope		yes
51 corner		yes
52 inner		yes
53 pyramid		yes
54 */
55 
56 // index is side shape
57 // value is
58 ubyte[] blockSideCorners = [
59 	// 3210 corners
60 	0b_0000, // empty
61 	0b_1111, // full
62 	0b_0110, // half
63 	0b_0111, // slope
64 	0b_0111, // stairs
65 ];
66 
67 enum NUM_SIDE_MASKS = ShapeSideMask.max + 1;
68 
69 enum ShapeSideMask : ubyte
70 {
71 	empty,
72 	water,
73 	full,
74 	half,
75 	slope0, // top-left
76 	slope1, // bot-left
77 	slope2, // bot-right
78 	slope3, // top-right
79 	stairs,
80 }
81 
82 struct ShapeSide
83 {
84 	ShapeSideMask mask;
85 	ubyte rotation;
86 }
87 
88 struct BlockShape
89 {
90 	ShapeSideMask[6] sideMasks;
91 	ubyte corners; // bits are corners
92 	bool hasGeometry;
93 	bool hasInternalGeometry;
94 }
95 
96 import std.range : repeat, take;
97 import std.array : array;
98 const ShapeSideMask[6] fullShapeSides = ShapeSideMask.full.repeat.take(6).array;
99 const ShapeSideMask[6] waterShapeSides = ShapeSideMask.water.repeat.take(6).array;
100 const ShapeSideMask[6] emptyShapeSides = ShapeSideMask.empty.repeat.take(6).array;
101 
102 const BlockShape unknownShape = BlockShape(fullShapeSides, 0b_0000_0000, false, false);
103 const BlockShape fullShape = BlockShape(fullShapeSides, 0b_1111_1111, true, false);
104 const BlockShape waterShape = BlockShape(waterShapeSides, 0b_1111_1111, false, false);
105 const BlockShape emptyShape = BlockShape(emptyShapeSides, 0b_0000_0000, false, false);
106 
107 BlockShape slopeShapeFromMeta(BlockMetadata metadata)
108 {
109 	return slope.metaToShapeTable[metadata];
110 }
111 
112 /*
113 struct SideIntersectionTable
114 {
115 	ubyte[] table;
116 	size_t numTypes;
117 
118 	/// Returns true if current shape side is visible
119 	pragma(inline, true)
120 	bool get(const ShapeSideMask current, const ShapeSideMask other)
121 	{
122 		size_t index = current * numTypes + other;
123 		return (table[index>>3] & (1 << (index & 0b111))) != 0;
124 	}
125 
126 	void set(const ShapeSideMask current, const ShapeSideMask other)
127 	{
128 		size_t index = current * numTypes + other;
129 		table[index>>3] |= (1 << (index & 0b111));
130 	}
131 
132 	void reset(const ShapeSideMask current, const ShapeSideMask other)
133 	{
134 		size_t index = current * numTypes + other;
135 		table[index>>3] &= ~(1 << (index & 0b111));
136 	}
137 }
138 
139 SideIntersectionTable sideIntersectionTable(size_t numTypes)
140 {
141 	size_t tableBits = numTypes * numTypes;
142 	size_t tableBytes = tableBits/8 + 1;
143 	return SideIntersectionTable(new ubyte[tableBytes], numTypes);
144 }*/
145 
146 struct SideIntersectionTable
147 {
148 	bool[] table;
149 	size_t numTypes;
150 
151 	/// Returns true if current shape side is visible
152 	pragma(inline, true)
153 	bool get(const ShapeSideMask current, const ShapeSideMask other)
154 	{
155 		size_t index = current * numTypes + other;
156 		return table[index];
157 	}
158 
159 	void set(const ShapeSideMask current, const ShapeSideMask other)
160 	{
161 		size_t index = current * numTypes + other;
162 		table[index] = true;
163 	}
164 
165 	void reset(const ShapeSideMask current, const ShapeSideMask other)
166 	{
167 		size_t index = current * numTypes + other;
168 		table[index] = false;
169 	}
170 }
171 
172 SideIntersectionTable sideIntersectionTable(size_t numTypes)
173 {
174 	size_t tableBits = numTypes * numTypes;
175 	//size_t tableBytes = tableBits/8 + 1;
176 	return SideIntersectionTable(new bool[tableBits], numTypes);
177 }