cgv
Loading...
Searching...
No Matches
mesh_render_info.cxx
1#include <memory>
2#include "mesh_render_info.h"
3
4namespace cgv {
5 namespace render {
7 position_descr(cgv::render::element_descriptor_traits<vec3>::get_type_descriptor(vec3())),
8 tex_coords_descr(cgv::render::element_descriptor_traits<vec2>::get_type_descriptor(vec2()))
9{
12}
24void mesh_render_info::construct_index_buffers(cgv::render::context& ctx, const cgv::media::mesh::simple_mesh_base& mesh, std::vector<idx4_type>& _unique_quadruples, std::vector<idx_type>& per_corner_vertex_index, std::vector<idx_type>& edges_element_buffer, std::vector<idx_type>& triangles_element_buffer)
25{
26 include_tex_coords = attribute_is_used(attribute_type::texcoords);
27 include_normals = attribute_is_used(attribute_type::normal);
28 include_tangents = attribute_is_used(attribute_type::tangent);
29 include_colors = attribute_is_used(attribute_type::color);
30
31 // load material textures
32 for (unsigned i = 0; i < mesh.get_nr_materials(); ++i) {
34 ref_materials().back()->ensure_textures(ctx);
35 }
36
37 std::unique_ptr<std::vector<idx_type>> permutation;
38 bool sort_by_groups = mesh.get_nr_groups() > 0;
39 bool sort_by_materials = mesh.get_nr_materials() > 0;
40 if (sort_by_groups || sort_by_materials) {
41 permutation = std::make_unique<std::vector<idx_type>>();
42 mesh.sort_faces(*permutation, sort_by_groups, sort_by_materials);
43 }
44 mesh.merge_indices(per_corner_vertex_index, _unique_quadruples, &include_tex_coords, &include_normals, &include_tangents);
45 nr_vertices = _unique_quadruples.size();
46 mesh.extract_triangle_element_buffer(per_corner_vertex_index, triangles_element_buffer, permutation.get(),
48
49 nr_triangle_elements = triangles_element_buffer.size();
50 mesh.extract_wireframe_element_buffer(per_corner_vertex_index, edges_element_buffer);
51 nr_edge_elements = edges_element_buffer.size();
53}
54void mesh_render_info::construct_element_vbo(cgv::render::context& ctx, const std::vector<idx_type>& edge_element_buffer, const std::vector<idx_type>& triangle_element_buffer)
55{
57 cgv::render::vertex_buffer& vbe = *ref_vbos().back();
59 vbe.replace(ctx, 0, &edge_element_buffer.front(), edge_element_buffer.size());
60 vbe.replace(ctx, sizeof(idx_type)*edge_element_buffer.size(), &triangle_element_buffer.front(), triangle_element_buffer.size());
61}
66bool mesh_render_info::configure_vbos(cgv::render::context& ctx, const cgv::media::mesh::simple_mesh_base& mesh, const attribute_map& attribute_to_vbo_index_map, const std::vector<int>& dynamic_vbos)
67{
68 // convert indices of dynamic vbos into per vbo flag
69 for (int dvi : dynamic_vbos) {
70 if (vbo_config.size() <= dvi)
71 vbo_config.resize(dvi + 1);
72 vbo_config[dvi].is_dynamic = true;
73 }
74 // iterate attribute map in order of mesh attributes, ensure their vbo to have a dynamic flag and keep track of entry sizes
75 for (attribute_type at = attribute_type::begin; at < attribute_type::end; ++(int&)at) {
76 if (attribute_to_vbo_index_map.find(at) != attribute_to_vbo_index_map.end()) {
77 if (!mesh.has_attribute(at)) {
78 ctx.error(std::string("attempt to add attribute ") + mesh.get_attribute_name(at) + " to mesh_render_info although missing in mesh");
79 continue;
80 }
81 uint32_t vi = attribute_to_vbo_index_map.at(at);
82 if (vbo_config.size() <= vi)
83 vbo_config.resize(vi + 1);
84 per_attribute_vbo_config[at] = { vi, vbo_config[vi].stride };
85 vbo_config[vi].attributes = cgv::media::mesh::simple_mesh_base::AttributeFlags(vbo_config[vi].attributes | mesh.get_attribute_flag(at));
86 vbo_config[vi].stride += uint32_t(mesh.get_attribute_size(at));
87 }
88 }
89 // validate that all indexed or skipped vbos have mesh attributes assigned to
90 for (size_t vi = 0; vi < vbo_config.size(); ++vi) {
91 if (vbo_config[vi].stride == 0) {
92 ctx.error(std::string("vertex attribute vbo configuration with empty vbo ") + cgv::utils::to_string(vi));
93 return false;
94 }
95 }
96 return true;
97}
98bool mesh_render_info::bind(context& ctx, shader_program& prog, bool force_success, int aa_index)
99{
100 return render_info::bind(ctx, prog, force_success, 0);
101}
102bool mesh_render_info::bind_wireframe(context& ctx, shader_program& prog, bool force_success)
103{
104 wire_draw_call.prog = &prog;
105 return render_info::bind(ctx, prog, force_success, 1);
106}
108{
109 // construct aa with new aab for surface rendering
110 int aa_index = (int)ref_aas().size();
111 ref_aas().push_back(attribute_array());
112 ref_aas().push_back(attribute_array());
113
114 auto& aa = ref_aas()[aa_index];
115 auto& wire_aa = ref_aas()[aa_index + 1];
116
117 aa.aab_ptr = new cgv::render::attribute_array_binding();
118 aa.aab_ptr->create(ctx);
119
120 wire_aa.aab_ptr = new cgv::render::attribute_array_binding();
121 wire_aa.aab_ptr->create(ctx);
122
123 // set element and attribute pointers
124 aa.aab_ptr->set_element_array(ctx, *ref_vbos().back());
125 wire_aa.aab_ptr->set_element_array(ctx, *ref_vbos().back());
126 if (attribute_is_used(attribute_type::position)) {
127 const auto& avc = per_attribute_vbo_config[attribute_type::position];
128 aa.add_attribute(position_descr, avc.vbo_index, avc.offset, nr_vertices, vbo_config[avc.vbo_index].stride, cgv::render::VA_POSITION);
129 wire_aa.add_attribute(position_descr, avc.vbo_index, avc.offset, nr_vertices, vbo_config[avc.vbo_index].stride, cgv::render::VA_POSITION);
130 }
131 if (attribute_is_used(attribute_type::texcoords)) {
132 const auto& avc = per_attribute_vbo_config[attribute_type::texcoords];
133 aa.add_attribute(tex_coords_descr, avc.vbo_index, avc.offset, nr_vertices, vbo_config[avc.vbo_index].stride, cgv::render::VA_TEXCOORD);
134 wire_aa.add_attribute(tex_coords_descr, avc.vbo_index, avc.offset, nr_vertices, vbo_config[avc.vbo_index].stride, cgv::render::VA_TEXCOORD);
135 }
136 if (attribute_is_used(attribute_type::normal)) {
137 const auto& avc = per_attribute_vbo_config[attribute_type::normal];
138 aa.add_attribute(position_descr, avc.vbo_index, avc.offset, nr_vertices, vbo_config[avc.vbo_index].stride, cgv::render::VA_NORMAL);
139 wire_aa.add_attribute(position_descr, avc.vbo_index, avc.offset, nr_vertices, vbo_config[avc.vbo_index].stride, cgv::render::VA_NORMAL);
140 }
141 if (attribute_is_used(attribute_type::tangent)) {
142 const auto& avc = per_attribute_vbo_config[attribute_type::tangent];
143 aa.add_attribute(position_descr, avc.vbo_index, avc.offset, nr_vertices, vbo_config[avc.vbo_index].stride, cgv::render::VA_BY_NAME, "tangent");
144 wire_aa.add_attribute(position_descr, avc.vbo_index, avc.offset, nr_vertices, vbo_config[avc.vbo_index].stride, cgv::render::VA_BY_NAME, "tangent");
145 }
146 if (attribute_is_used(attribute_type::color)) {
147 static int nr_comps[] = { 4,4,3,4 };
149 cgv::render::type_descriptor ctd(type_ids[ct], nr_comps[ct], true);
150 const auto& avc = per_attribute_vbo_config[attribute_type::color];
151 aa.add_attribute(ctd, avc.vbo_index, avc.offset, nr_vertices, vbo_config[avc.vbo_index].stride, cgv::render::VA_COLOR);
152 wire_aa.add_attribute(ctd, avc.vbo_index, avc.offset, nr_vertices, vbo_config[avc.vbo_index].stride, cgv::render::VA_COLOR);
153 }
154 // construct draw call structure which is independent of mesh fragment
156 dc.aa_index = aa_index;
157 dc.primitive_type = PT_TRIANGLES;
158 dc.vertex_offset = 0;
159 dc.draw_call_type = cgv::render::RCT_INDEXED;
160 dc.index_type = cgv::type::info::TI_UINT32;
161 dc.instance_count = 1;
162 dc.prog = 0;
163 dc.material_index = -1;
164 dc.alpha_mode = AM_OPAQUE;
165 // in case of no fragments, generate a single draw call
166 if (material_primitive_start.empty()) {
167 dc.count = uint32_t(nr_triangle_elements);
168 dc.indices = (void*)(sizeof(idx_type) * nr_edge_elements);
169 ref_draw_calls().push_back(dc);
170 }
171 // otherwise, for each mesh fragment construct a draw call
172 else {
173 size_t fi;
174 for (fi = 0; fi < material_primitive_start.size(); ++fi) {
175 const auto& mps = material_primitive_start[fi];
176 size_t next_start = nr_triangle_elements;
177 if (fi + 1 < material_primitive_start.size())
178 next_start = material_primitive_start[fi + 1][2];
179 dc.count = uint32_t(next_start - mps[2]);
180 dc.indices = (void*)(sizeof(idx_type)*(nr_edge_elements+mps[2]));
181 dc.material_index = mps[0];
182 if (dc.material_index != -1) {
183 const auto& mat = *ref_materials()[dc.material_index];
184 if ((mat.get_transparency_index() != -1) ||
185 (mat.get_transparency() > 0.01f)) {
186 dc.alpha_mode = AM_MASK_AND_BLEND;
187 dc.alpha_cutoff = 0.02f;
188 }
189 else
190 dc.alpha_mode = AM_OPAQUE;
191 }
192 ref_draw_calls().push_back(dc);
193 }
194 }
195 // set draw call for wire frame rendering
196 wire_draw_call.aa_index = aa_index+1;
197 wire_draw_call.primitive_type = PT_LINES;
198 wire_draw_call.vertex_offset = 0;
199 wire_draw_call.draw_call_type = cgv::render::RCT_INDEXED;
200 wire_draw_call.count = uint32_t(nr_edge_elements);
202 wire_draw_call.indices = 0;
203 wire_draw_call.material_index = -1;
204 wire_draw_call.alpha_mode = AM_OPAQUE;
205 wire_draw_call.instance_count = 1;
206 wire_draw_call.prog = 0;
207}
209{
210 for (auto& dc : ref_draw_calls()) {
211 dc.instance_count = nr;
212 switch (dc.draw_call_type) {
213 case RCT_ARRAYS:
214 if (nr > 0)
215 dc.draw_call_type = RCT_ARRAYS_INSTANCED;
216 break;
217 case RCT_INDEXED:
218 if (nr > 0)
219 dc.draw_call_type = RCT_INDEXED_INSTANCED;
220 break;
221 case RCT_ARRAYS_INSTANCED:
222 if (nr == 0)
223 dc.draw_call_type = RCT_ARRAYS;
224 break;
225 case RCT_INDEXED_INSTANCED:
226 if (nr == 0)
227 dc.draw_call_type = RCT_INDEXED;
228 break;
229 }
230 }
231}
232void mesh_render_info::draw_primitive(cgv::render::context& ctx, size_t primitive_index, bool skip_opaque, bool skip_blended, bool use_materials)
233{
234 // extract indices of to be drawn calls
235 std::vector<size_t> dcis;
236 size_t dci = 0;
237 while (dci < draw_calls.size()) {
238 while (dci < draw_calls.size() && material_primitive_start[dci][1] != primitive_index)
239 ++dci;
240 if (skip_opaque)
241 while (dci < draw_calls.size() && (draw_calls[dci].alpha_mode & AM_BLEND) == 0)
242 ++dci;
243 if (skip_blended)
244 while (dci < draw_calls.size() && (draw_calls[dci].alpha_mode & AM_BLEND) != 0)
245 ++dci;
246 if (dci >= draw_calls.size())
247 break;
248 dcis.push_back(dci);
249 ++dci;
250 }
251 // draw extracted calls
252 draw_call* prev_dc = 0;
253 for (size_t i = 0; i < dcis.size(); ++i) {
254 draw_call* next_dc = i + 1 < dcis.size() ? &draw_calls[dcis[i + 1]] : 0;
255 draw(ctx, draw_calls[dcis[i]], prev_dc, next_dc, use_materials);
256 prev_dc = &draw_calls[dcis[i]];
257 }
258
259}
264 }
265}
ColorType get_color_storage_type() const
return storage type of colors, if no colors are allocated CT_RGBA8 is returned
coordinate type independent base class of simple mesh data structure that handles indices and colors.
Definition simple_mesh.h:27
const mat_type & get_material(size_t i) const
return const reference to i-th material
size_t get_nr_groups() const
return number of face groups
void merge_indices(std::vector< idx_type > &vertex_indices, std::vector< idx4_type > &unique_tuples, bool *include_tex_coords_ptr=0, bool *include_normals_ptr=0, bool *include_tangents_ptr=0) const
Transforms n individual vertex attribute indices into one list of unique index n-tuples.
void extract_wireframe_element_buffer(const std::vector< idx_type > &vertex_indices, std::vector< idx_type > &edge_element_buffer) const
Extract element array buffers for edges in wireframe.
size_t get_nr_materials() const
return number of materials in mesh
void sort_faces(std::vector< idx_type > &perm, bool by_group=true, bool by_material=true) const
Calculate a permutation of face indices which sorts them by group and/or material.
attribute_type
different mesh attributes
Definition simple_mesh.h:40
void extract_triangle_element_buffer(const std::vector< idx_type > &vertex_indices, std::vector< idx_type > &triangle_element_buffer, const std::vector< idx_type > *face_permutation_ptr=0, std::vector< idx3_type > *material_group_start_ptr=0) const
Extract element array buffers for triangulation.
the attribute_array_binding allows to define vertex attributes (i.e.
base class for all drawables, which is independent of the used rendering API.
Definition context.h:621
virtual void error(const std::string &message, const render_component *rc=0) const
error handling
Definition context.cxx:219
std::vector< idx3_type > material_primitive_start
index triple storing the material index, the primitive index and the offset (element index) in the tr...
std::map< attribute_type, attribute_configuration > per_attribute_vbo_config
for each mesh attribute that is used, map attribute type to the vbo index
std::vector< vbo_configuration > vbo_config
store for each vbo its configuration
void draw_wireframe(cgv::render::context &ctx)
draw array elements forming the edges of the wireframe
cgv::render::type_descriptor tex_coords_descr
type description of tex coordinate attribute
void construct_index_buffers(cgv::render::context &ctx, const cgv::media::mesh::simple_mesh_base &mesh, std::vector< idx4_type > &unique_quadruples, std::vector< idx_type > &per_corner_vertex_index, std::vector< idx_type > &edges_element_buffer, std::vector< idx_type > &triangles_element_buffer)
Prepare vertex attribute data creation by extraction of unique combinations of attribute indices.
bool include_tex_coords
store whether tex coords are in vbo
bool include_normals
store whether normals are in vbo
void set_nr_instances(unsigned nr)
set the number of to be drawn instances - in case of 0, instanced drawing is turned off
bool include_tangents
store whether tangents are in vbo
bool configure_vbos(cgv::render::context &ctx, const cgv::media::mesh::simple_mesh_base &mesh, const attribute_map &attribute_to_vbo_index_map, const std::vector< int > &dynamic_vbo_idx)
configure which attributes should be stored, in which vbos they go and which vbos should support dyna...
cgv::render::type_descriptor position_descr
type description of position attribute
void construct_element_vbo(cgv::render::context &ctx, const std::vector< idx_type > &edge_element_buffer, const std::vector< idx_type > &triangle_element_buffer)
Uploads the given element buffers into EBOs on the GPU.
size_t nr_vertices
number of vertices
void construct_draw_calls(cgv::render::context &ctx)
for each combination of primitive (face group of mesh) and material create and store one draw call
bool bind_wireframe(context &ctx, shader_program &prog, bool force_success)
bind all or specific aa to the passed shader program
cgv::media::ColorType ct
color type
bool attribute_is_used(attribute_type at) const
check whether a mesh attribute is used
mesh_render_info()
set vbo and vbe types
void draw_primitive(cgv::render::context &ctx, size_t primitive_index, bool skip_opaque=false, bool skip_blended=false, bool use_materials=true)
draw triangles of given mesh part or whole mesh in case part_index is not given (=-1)
size_t nr_edge_elements
number of edges in the wireframe representation
size_t element_size
size of single coordinate
bool bind(context &ctx, shader_program &prog, bool force_success, int aa_index=-1)
override to restrict bind function to first aa as second is used for wireframe rendering
draw_call wire_draw_call
draw call for wireframe rendering
bool include_colors
store whether colors are in vbo
std::map< attribute_type, uint32_t > attribute_map
type of map from mesh attribute to vbo index
void destruct(cgv::render::context &ctx)
destruct render mesh info and free vertex buffer objects
size_t nr_triangle_elements
number of triangles in the triangulation
std::vector< vertex_buffer * > & ref_vbos()
give write access to vbos
virtual bool bind(context &ctx, shader_program &prog, bool force_success, int aa_index=-1)
bind all or specific aa to the passed shader program
std::vector< textured_material * > & ref_materials()
give write access to materials
std::vector< draw_call > & ref_draw_calls()
give write access to draw calls
std::vector< attribute_array > & ref_aas()
give write access to aabs
void destruct(cgv::render::context &ctx)
destruct render mesh info and free vertex buffer objects
std::vector< draw_call > draw_calls
store vector of render calls
Definition render_info.h:90
cgv::type::uint32_type idx_type
define index type
Definition render_info.h:79
void draw(context &ctx, const draw_call &dc, const draw_call *prev_dc=0, const draw_call *next_dc=0, bool use_materials=true)
perform a single render call
a shader program combines several shader code fragments to a complete definition of the shading pipel...
class that extends obj_material with the management of textures
a vertex buffer is an unstructured memory block on the GPU.
bool create(const context &ctx, size_t size_in_bytes)
create empty vertex buffer of size size given in bytes
bool replace(const context &ctx, size_t buffer_offset_in_bytes, const T *array_ptr, size_t nr_elements)
replace part (starting at byte offset buffer_offset_in_bytes) or whole vertex buffer content from nr_...
@ VBT_INDICES
The buffer contains indices and will be bound to GL_ELEMENT_ARRAY_BUFFER.
Definition context.h:417
TypeId
ids for the different types and type constructs
Definition type_id.h:12
@ TI_FLT32
floating point type stored in 16 bits
Definition type_id.h:28
@ TI_UINT32
unsigned integer stored in 16 bits
Definition type_id.h:25
@ TI_UINT8
signed integer stored in 64 bits
Definition type_id.h:23
std::string to_string(const std::string &v, unsigned int w, unsigned int p, bool)
specialization of conversion from string to strings
the cgv namespace
Definition print.h:11
compact type description of data that can be sent to the context; convertible to int
Definition context.h:47