1 #pragma once
2 
3 #include <mbgl/programs/program.hpp>
4 #include <mbgl/programs/attributes.hpp>
5 #include <mbgl/programs/uniforms.hpp>
6 #include <mbgl/shaders/collision_box.hpp>
7 #include <mbgl/shaders/collision_circle.hpp>
8 #include <mbgl/style/properties.hpp>
9 #include <mbgl/util/geometry.hpp>
10 
11 #include <cmath>
12 
13 namespace mbgl {
14 
15 using CollisionBoxLayoutAttributes = gl::Attributes<
16     attributes::a_pos,
17     attributes::a_anchor_pos,
18     attributes::a_extrude>;
19 
20 struct CollisionBoxDynamicAttributes : gl::Attributes<attributes::a_placed> {
vertexmbgl::CollisionBoxDynamicAttributes21     static Vertex vertex(bool placed, bool notUsed) {
22         return Vertex {
23             {{ static_cast<uint8_t>(placed), static_cast<uint8_t>(notUsed)  }}
24         };
25     }
26 };
27 
28 class CollisionBoxProgram : public Program<
29     shaders::collision_box,
30     gl::Line,
31     gl::ConcatenateAttributes<CollisionBoxLayoutAttributes, CollisionBoxDynamicAttributes>,
32     gl::Uniforms<
33         uniforms::u_matrix,
34         uniforms::u_extrude_scale,
35         uniforms::u_camera_to_center_distance>,
36     style::Properties<>>
37 {
38 public:
39     using Program::Program;
40 
vertex(Point<float> a,Point<float> anchor,Point<float> o)41     static CollisionBoxLayoutAttributes::Vertex vertex(Point<float> a, Point<float> anchor, Point<float> o) {
42         return CollisionBoxLayoutAttributes::Vertex {
43             {{
44                 static_cast<int16_t>(a.x),
45                 static_cast<int16_t>(a.y)
46             }},
47             {{
48                 static_cast<int16_t>(anchor.x),
49                 static_cast<int16_t>(anchor.y)
50             }},
51             {{
52                 static_cast<int16_t>(::round(o.x)),
53                 static_cast<int16_t>(::round(o.y))
54             }}
55         };
56     }
57 
58 	template <class DrawMode>
draw(gl::Context & context,DrawMode drawMode,gl::DepthMode depthMode,gl::StencilMode stencilMode,gl::ColorMode colorMode,const UniformValues & uniformValues,const gl::VertexBuffer<CollisionBoxLayoutAttributes::Vertex> & layoutVertexBuffer,const gl::VertexBuffer<CollisionBoxDynamicAttributes::Vertex> & dynamicVertexBuffer,const gl::IndexBuffer<DrawMode> & indexBuffer,const SegmentVector<Attributes> & segments,const PaintPropertyBinders & paintPropertyBinders,const typename PaintProperties::PossiblyEvaluated & currentProperties,float currentZoom,const std::string & layerID)59     void draw(gl::Context& context,
60               DrawMode drawMode,
61               gl::DepthMode depthMode,
62               gl::StencilMode stencilMode,
63               gl::ColorMode colorMode,
64               const UniformValues& uniformValues,
65               const gl::VertexBuffer<CollisionBoxLayoutAttributes::Vertex>& layoutVertexBuffer,
66               const gl::VertexBuffer<CollisionBoxDynamicAttributes::Vertex>& dynamicVertexBuffer,
67               const gl::IndexBuffer<DrawMode>& indexBuffer,
68               const SegmentVector<Attributes>& segments,
69               const PaintPropertyBinders& paintPropertyBinders,
70               const typename PaintProperties::PossiblyEvaluated& currentProperties,
71               float currentZoom,
72               const std::string& layerID) {
73         typename AllUniforms::Values allUniformValues = uniformValues
74             .concat(paintPropertyBinders.uniformValues(currentZoom, currentProperties));
75 
76         typename Attributes::Bindings allAttributeBindings = CollisionBoxLayoutAttributes::bindings(layoutVertexBuffer)
77             .concat(CollisionBoxDynamicAttributes::bindings(dynamicVertexBuffer))
78             .concat(paintPropertyBinders.attributeBindings(currentProperties));
79 
80         assert(layoutVertexBuffer.vertexCount == dynamicVertexBuffer.vertexCount);
81 
82         for (auto& segment : segments) {
83             auto vertexArrayIt = segment.vertexArrays.find(layerID);
84 
85             if (vertexArrayIt == segment.vertexArrays.end()) {
86                 vertexArrayIt = segment.vertexArrays.emplace(layerID, context.createVertexArray()).first;
87             }
88 
89             program.draw(
90                     context,
91                     std::move(drawMode),
92                     std::move(depthMode),
93                     std::move(stencilMode),
94                     std::move(colorMode),
95                     allUniformValues,
96                     vertexArrayIt->second,
97                     Attributes::offsetBindings(allAttributeBindings, segment.vertexOffset),
98                     indexBuffer,
99                     segment.indexOffset,
100                     segment.indexLength);
101         }
102     }
103 };
104 
105 
106 class CollisionCircleProgram : public Program<
107     shaders::collision_circle,
108     gl::Triangle,
109     gl::ConcatenateAttributes<CollisionBoxLayoutAttributes, CollisionBoxDynamicAttributes>,
110     gl::Uniforms<
111         uniforms::u_matrix,
112         uniforms::u_extrude_scale,
113         uniforms::u_overscale_factor,
114         uniforms::u_camera_to_center_distance>,
115     style::Properties<>>
116 {
117 public:
118     using Program::Program;
119 
vertex(Point<float> a,Point<float> anchor,Point<float> o)120     static CollisionBoxLayoutAttributes::Vertex vertex(Point<float> a, Point<float> anchor, Point<float> o) {
121         return CollisionBoxLayoutAttributes::Vertex {
122             {{
123                 static_cast<int16_t>(a.x),
124                 static_cast<int16_t>(a.y)
125             }},
126             {{
127                 static_cast<int16_t>(anchor.x),
128                 static_cast<int16_t>(anchor.y)
129             }},
130             {{
131                 static_cast<int16_t>(::round(o.x)),
132                 static_cast<int16_t>(::round(o.y))
133             }}
134         };
135     }
136 
137     template <class DrawMode>
draw(gl::Context & context,DrawMode drawMode,gl::DepthMode depthMode,gl::StencilMode stencilMode,gl::ColorMode colorMode,const UniformValues & uniformValues,const gl::VertexBuffer<CollisionBoxLayoutAttributes::Vertex> & layoutVertexBuffer,const gl::VertexBuffer<CollisionBoxDynamicAttributes::Vertex> & dynamicVertexBuffer,const gl::IndexBuffer<DrawMode> & indexBuffer,const SegmentVector<Attributes> & segments,const PaintPropertyBinders & paintPropertyBinders,const typename PaintProperties::PossiblyEvaluated & currentProperties,float currentZoom,const std::string & layerID)138     void draw(gl::Context& context,
139               DrawMode drawMode,
140               gl::DepthMode depthMode,
141               gl::StencilMode stencilMode,
142               gl::ColorMode colorMode,
143               const UniformValues& uniformValues,
144               const gl::VertexBuffer<CollisionBoxLayoutAttributes::Vertex>& layoutVertexBuffer,
145               const gl::VertexBuffer<CollisionBoxDynamicAttributes::Vertex>& dynamicVertexBuffer,
146               const gl::IndexBuffer<DrawMode>& indexBuffer,
147               const SegmentVector<Attributes>& segments,
148               const PaintPropertyBinders& paintPropertyBinders,
149               const typename PaintProperties::PossiblyEvaluated& currentProperties,
150               float currentZoom,
151               const std::string& layerID) {
152         typename AllUniforms::Values allUniformValues = uniformValues
153             .concat(paintPropertyBinders.uniformValues(currentZoom, currentProperties));
154 
155         typename Attributes::Bindings allAttributeBindings = CollisionBoxLayoutAttributes::bindings(layoutVertexBuffer)
156             .concat(CollisionBoxDynamicAttributes::bindings(dynamicVertexBuffer))
157             .concat(paintPropertyBinders.attributeBindings(currentProperties));
158 
159         for (auto& segment : segments) {
160             auto vertexArrayIt = segment.vertexArrays.find(layerID);
161 
162             if (vertexArrayIt == segment.vertexArrays.end()) {
163                 vertexArrayIt = segment.vertexArrays.emplace(layerID, context.createVertexArray()).first;
164             }
165 
166             program.draw(
167                     context,
168                     std::move(drawMode),
169                     std::move(depthMode),
170                     std::move(stencilMode),
171                     std::move(colorMode),
172                     allUniformValues,
173                     vertexArrayIt->second,
174                     Attributes::offsetBindings(allAttributeBindings, segment.vertexOffset),
175                     indexBuffer,
176                     segment.indexOffset,
177                     segment.indexLength);
178         }
179     }
180 };
181 
182 using CollisionBoxVertex = CollisionBoxProgram::LayoutVertex;
183 
184 } // namespace mbgl
185