1#include <cgv/utils/file.h>
2#include <cgv/media/image/image_reader.h>
3#include <cgv_gl/gl/gl.h>
4#include "gltf_support.h"
12 case GL_NEAREST:
return cgv::render::TF_NEAREST;
13 case GL_LINEAR:
return cgv::render::TF_LINEAR;
14 case GL_NEAREST_MIPMAP_NEAREST:
return cgv::render::TF_NEAREST_MIPMAP_NEAREST;
15 case GL_LINEAR_MIPMAP_NEAREST:
return cgv::render::TF_LINEAR_MIPMAP_NEAREST;
16 case GL_NEAREST_MIPMAP_LINEAR:
return cgv::render::TF_NEAREST_MIPMAP_LINEAR;
17 case GL_LINEAR_MIPMAP_LINEAR:
return cgv::render::TF_LINEAR_MIPMAP_LINEAR;
18 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
return cgv::render::TF_ANISOTROP;
20 return cgv::render::TF_LAST;
26 case GL_REPEAT:
return cgv::render::TW_REPEAT;
27 case GL_CLAMP:
return cgv::render::TW_CLAMP;
28 case GL_CLAMP_TO_EDGE:
return cgv::render::TW_CLAMP_TO_EDGE;
29 case GL_CLAMP_TO_BORDER:
return cgv::render::TW_CLAMP_TO_BORDER;
30 case GL_MIRROR_CLAMP_EXT:
return cgv::render::TW_MIRROR_CLAMP;
31 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
return cgv::render::TW_MIRROR_CLAMP_TO_EDGE;
32 case GL_MIRROR_CLAMP_TO_BORDER_EXT:
return cgv::render::TW_MIRROR_CLAMP_TO_BORDER;
33 case GL_MIRRORED_REPEAT:
return cgv::render::TW_MIRRORED_REPEAT;
35 return cgv::render::TW_LAST;
41 case GL_POINTS:
return cgv::render::PT_POINTS;
42 case GL_LINES:
return cgv::render::PT_LINES;
43 case GL_LINES_ADJACENCY:
return cgv::render::PT_LINES_ADJACENCY;
44 case GL_LINE_STRIP:
return cgv::render::PT_LINE_STRIP;
45 case GL_LINE_STRIP_ADJACENCY:
return cgv::render::PT_LINE_STRIP_ADJACENCY;
46 case GL_LINE_LOOP:
return cgv::render::PT_LINE_LOOP;
47 case GL_TRIANGLES:
return cgv::render::PT_TRIANGLES;
48 case GL_TRIANGLES_ADJACENCY:
return cgv::render::PT_TRIANGLES_ADJACENCY;
49 case GL_TRIANGLE_STRIP:
return cgv::render::PT_TRIANGLE_STRIP;
50 case GL_TRIANGLE_STRIP_ADJACENCY:
return cgv::render::PT_TRIANGLE_STRIP_ADJACENCY;
51 case GL_TRIANGLE_FAN:
return cgv::render::PT_TRIANGLE_FAN;
52 case GL_QUADS:
return cgv::render::PT_QUADS;
53 case GL_QUAD_STRIP:
return cgv::render::PT_QUAD_STRIP;
54 case GL_POLYGON:
return cgv::render::PT_POLYGON;
56 return cgv::render::PT_LAST;
62 switch (accessor.componentType) {
71 switch (accessor.type)
73 case fx::gltf::Accessor::Type::Mat2: td.element_type = cgv::render::ET_MATRIX; td.nr_columns = td.nr_rows = 2;
break;
74 case fx::gltf::Accessor::Type::Mat3: td.element_type = cgv::render::ET_MATRIX; td.nr_columns = td.nr_rows = 3;
break;
75 case fx::gltf::Accessor::Type::Mat4: td.element_type = cgv::render::ET_MATRIX; td.nr_columns = td.nr_rows = 4;
break;
76 case fx::gltf::Accessor::Type::Scalar:td.element_type = cgv::render::ET_VALUE; td.nr_columns = td.nr_rows = 1;
break;
77 case fx::gltf::Accessor::Type::Vec2: td.element_type = cgv::render::ET_VECTOR; td.nr_columns = 1; td.nr_rows = 2;
break;
78 case fx::gltf::Accessor::Type::Vec3: td.element_type = cgv::render::ET_VECTOR; td.nr_columns = 1; td.nr_rows = 3;
break;
79 case fx::gltf::Accessor::Type::Vec4: td.element_type = cgv::render::ET_VECTOR; td.nr_columns = 1; td.nr_rows = 4;
break;
81 td.normalize = accessor.normalized;
82 td.is_row_major =
false;
89 cgv::render::VertexAttributeID va_id,
const std::string& name =
"")
92 aa.add_attribute(get_element_type(accessor), bufferView.buffer,
93 bufferView.byteOffset + accessor.byteOffset, accessor.count,
94 bufferView.byteStride, va_id, name);
104 for (
const auto& M : doc.meshes) {
105 for (
const auto& p : M.primitives) {
106 for (
const auto& a : p.attributes) {
107 if (a.first ==
"POSITION") {
109 if (accessor.componentType != fx::gltf::Accessor::ComponentType::Float)
112 const uint8_t* data_ptr = &doc.buffers[bufferView.buffer].data[0] + accessor.byteOffset + bufferView.byteOffset;
113 vertex_count += accessor.count;
114 for (
size_t i = 0; i < accessor.count; ++i) {
115 switch (accessor.type) {
116 case fx::gltf::Accessor::Type::Vec2:
119 case fx::gltf::Accessor::Type::Vec3:
122 case fx::gltf::Accessor::Type::Vec4:
124 reinterpret_cast<const vec4*
>(data_ptr) + i));
137 std::string file_path = cgv::utils::file::get_path(file_name);
140 std::cerr <<
"need valid context for read_gltf" << std::endl;
147 for (
const auto& b : doc.buffers) {
149 vbo->
create(ctx, &b.data[0], b.byteLength);
154 std::vector<cgv::data::data_view*> dvs;
155 std::vector<cgv::data::data_format*> dfs;
156 for (
const auto& i : doc.images) {
157 if (i.IsEmbeddedResource()) {
158 std::cerr <<
"could not deal with embedded image" << std::endl;
164 std::string image_file_name = file_path +
"/" + i.uri;
165 if (!ir.
open(image_file_name)) {
166 std::cerr <<
"could not open image " << image_file_name << std::endl;
171 std::cerr <<
"could not read image " << image_file_name << std::endl;
179 for (
const auto& t : doc.textures) {
181 tex->
create(ctx, *dvs[t.source]);
182 const auto& s = doc.samplers[t.sampler];
183 if (s.magFilter != fx::gltf::Sampler::MagFilter::None)
185 if (s.minFilter != fx::gltf::Sampler::MinFilter::None)
187 tex->
set_wrap_s(map_gl_to_tex_wrap(GLenum(s.wrapS)));
188 tex->
set_wrap_t(map_gl_to_tex_wrap(GLenum(s.wrapT)));
193 for (
const auto& m : doc.materials) {
197 bool found_KHR_mat =
false;
198 m.extensionsAndExtras.count(
"extensions");
199 if (m.extensionsAndExtras.count(
"extensions")) {
200 auto& ext = m.extensionsAndExtras[
"extensions"];
201 if (ext.count(
"KHR_materials_pbrSpecularGlossiness")) {
202 auto& mat = ext[
"KHR_materials_pbrSpecularGlossiness"];
203 found_KHR_mat =
true;
204 if (mat.count(
"diffuseFactor")) {
205 auto& df = mat[
"diffuseFactor"];
206 tm->set_diffuse_reflectance(
rgb(
207 df[0].get<float>(), df[1].get<float>(), df[2].get<float>()));
208 tm->set_transparency(1.0f - df[3].get<float>());
210 if (mat.count(
"diffuseTexture")) {
212 tm->set_diffuse_index(ti);
214 if (mat.count(
"glossinessFactor"))
215 tm->set_roughness(1 - mat[
"glossinessFactor"].get<float>());
216 if (mat.count(
"specularFactor")) {
217 auto& sf = mat[
"specularFactor"];
218 tm->set_diffuse_reflectance(
rgb(
219 sf[0].get<float>(), sf[1].get<float>(), sf[2].get<float>()));
221 if (mat.count(
"specularGlossinessTexture")) {
223 tm->set_specular_index(ti);
227 if (!found_KHR_mat) {
228 tm->set_diffuse_reflectance(
rgb(
229 m.pbrMetallicRoughness.baseColorFactor[0],
230 m.pbrMetallicRoughness.baseColorFactor[1],
231 m.pbrMetallicRoughness.baseColorFactor[2]));
232 tm->set_transparency(1.0f - m.pbrMetallicRoughness.baseColorFactor[3]);
233 if (m.pbrMetallicRoughness.baseColorTexture.index != -1) {
235 tm->set_diffuse_index(ti);
237 tm->set_roughness(m.pbrMetallicRoughness.roughnessFactor);
238 tm->set_metalness(m.pbrMetallicRoughness.metallicFactor);
239 if (m.pbrMetallicRoughness.metallicRoughnessTexture.index != -1) {
241 tm->set_roughness_index(ti);
242 tm->set_metalness_index(ti);
244 if (m.alphaMode == fx::gltf::Material::AlphaMode::Mask)
245 tm->
set_alpha_test(cgv::render::textured_material::AT_GREATER, m.alphaCutoff);
246 tm->set_emission(
rgba(
249 m.emissiveFactor[2]));
250 if (m.emissiveTexture.index != -1) {
252 tm->set_emission_index(ti);
259 for (
const auto& M : doc.meshes) {
260 for (
const auto& p : M.primitives) {
266 for (
const auto& a : p.attributes) {
267 if (a.first ==
"POSITION") {
268 add_attribute(aa, doc, doc.accessors[a.second], cgv::render::VA_POSITION);
269 dc.count = doc.accessors[a.second].count;
271 else if (a.first ==
"NORMAL")
272 add_attribute(aa, doc, doc.accessors[a.second], cgv::render::VA_NORMAL);
273 else if (a.first ==
"TANGENT")
274 add_attribute(aa, doc, doc.accessors[a.second], cgv::render::VA_BY_NAME,
"tangent");
275 else if (a.first ==
"TEXCOORD_0")
276 add_attribute(aa, doc, doc.accessors[a.second], cgv::render::VA_TEXCOORD);
279 dc.aa_index = uint32_t(R.
ref_aas().size() - 1);
280 dc.instance_count = 1;
281 dc.draw_call_type = cgv::render::RCT_ARRAYS;
282 dc.vertex_offset = 0;
283 if (p.indices >= 0) {
284 dc.draw_call_type = cgv::render::RCT_INDEXED;
287 dc.count = accessor.count;
288 R.
ref_aas().back().aab_ptr->set_element_array(ctx, *R.
ref_vbos()[bufferView.buffer]);
289 if (accessor.type != fx::gltf::Accessor::Type::Scalar) {
290 std::cerr <<
"index type must by scalar" << std::endl;
293 switch (accessor.componentType) {
294 case fx::gltf::Accessor::ComponentType::UnsignedByte:
297 case fx::gltf::Accessor::ComponentType::UnsignedShort:
300 case fx::gltf::Accessor::ComponentType::UnsignedInt:
304 std::cerr <<
"index component type must be unsigned integer type" << std::endl;
307 dc.indices = (
void*)(
unsigned long long)(accessor.byteOffset + bufferView.byteOffset);
309 dc.primitive_type = map_gl_to_primitive_type(GLenum(p.mode));
310 if (p.material >= 0) {
311 dc.material_index = p.material;
312 dc.alpha_mode = cgv::render::AlphaMode(doc.materials[p.material].alphaMode);
313 dc.alpha_cutoff = doc.materials[p.material].alphaCutoff;
317 dc.material_index = -1;
318 dc.alpha_mode = cgv::render::AM_OPAQUE;
319 dc.alpha_cutoff = 0.0f;
331 std::string file_path = cgv::utils::file::get_path(file_name);
335 std::vector<std::string> image_file_names;
336 for (
const auto& i : doc.images) {
337 if (i.IsEmbeddedResource()) {
338 std::cerr <<
"cannot not deal with embedded image" << std::endl;
342 image_file_names.push_back(file_path +
"/" + i.uri);
346 for (
const auto& m : doc.materials) {
349 mm.set_diffuse_reflectance(
rgba(
350 m.pbrMetallicRoughness.baseColorFactor[0],
351 m.pbrMetallicRoughness.baseColorFactor[1],
352 m.pbrMetallicRoughness.baseColorFactor[2],
353 m.pbrMetallicRoughness.baseColorFactor[3]));
354 if (m.pbrMetallicRoughness.baseColorTexture.index != -1) {
355 int ii = mm.add_image_file(image_file_names[
356 doc.textures[m.pbrMetallicRoughness.baseColorTexture.index].source]);
357 mm.set_diffuse_index(ii);
359 mm.set_roughness(m.pbrMetallicRoughness.roughnessFactor);
360 mm.set_metalness(m.pbrMetallicRoughness.metallicFactor);
361 if (m.pbrMetallicRoughness.metallicRoughnessTexture.index != -1) {
362 int ii = mm.add_image_file(image_file_names[
363 doc.textures[m.pbrMetallicRoughness.metallicRoughnessTexture.index].source]);
364 mm.set_roughness_index(ii);
365 mm.set_metalness_index(ii);
367 mm.set_emission(
rgba(
370 m.emissiveFactor[2]));
371 if (m.emissiveTexture.index != -1) {
372 int ii = mm.add_image_file(image_file_names[
373 doc.textures[m.emissiveTexture.index].source]);
374 mm.set_emission_index(ii);
380 for (
const auto& M : doc.meshes) {
381 if (mesh_index != -1 && (&M - &doc.meshes[0]) != mesh_index)
384 for (
const auto& p : M.primitives) {
385 if (primitive_index != -1 && (&p - &M.primitives[0]) != primitive_index)
390 int ni = mesh.get_nr_normals();
391 int ti = mesh.get_nr_tex_coords();
393 bool has_nmls =
false;
394 bool has_tcs =
false;
395 for (
const auto& a : p.attributes) {
399 const uint8_t* data_ptr = &buffer.data[accessor.byteOffset + bufferView.byteOffset];
400 const float* float_ptr =
reinterpret_cast<const float*
>(data_ptr);
401 if (a.first ==
"POSITION") {
402 for (
size_t i = 0; i < accessor.count; ++i) {
407 else if (a.first ==
"NORMAL") {
409 for (
size_t i = 0; i < accessor.count; ++i) {
414 else if (a.first ==
"TEXCOORD_0") {
416 for (
size_t i = 0; i < accessor.count; ++i) {
423 if (p.indices >= 0) {
427 const uint8_t* data_ptr = &buffer.data[accessor.byteOffset + bufferView.byteOffset];
428 const uint16_t* ushort_ptr =
reinterpret_cast<const uint16_t*
>(data_ptr);
429 const uint32_t* uint_ptr =
reinterpret_cast<const uint32_t*
>(data_ptr);
430 if (p.mode == fx::gltf::Primitive::Mode::Triangles) {
432 for (
size_t i = 0; i < accessor.count; ++i) {
439 switch (accessor.componentType) {
440 case fx::gltf::Accessor::ComponentType::UnsignedByte: idx = data_ptr[i];
break;
441 case fx::gltf::Accessor::ComponentType::UnsignedShort: idx = ushort_ptr[i];
break;
442 case fx::gltf::Accessor::ComponentType::UnsignedInt: idx = uint_ptr[i];
break;
444 mesh.
new_corner(pi + idx, has_nmls ? ni + idx : -1, has_tcs ? ti + idx : -1);
the data view gives access to a data array of one, two, three or four dimensions.
void set_name(std::string o)
set the name of the material
the attribute_array_binding allows to define vertex attributes (i.e.
bool create(const context &ctx)
create the attribute array binding object
base class for all drawables, which is independent of the used rendering API.
virtual bool make_current() const =0
make the current context current if possible
the mesh_render_info structure manages vertex buffer objects for attribute and element buffers as wel...
std::vector< vertex_buffer * > & ref_vbos()
give write access to vbos
std::vector< texture * > & ref_textures()
give write access to texture
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
the texture class encapsulates all functionality independent of the rendering api.
void set_mag_filter(TextureFilter _mag_filter)
set the magnification filter
bool create(const context &ctx, TextureType _tt=TT_UNDEF, unsigned width=-1, unsigned height=-1, unsigned depth=-1)
create the texture of dimension and resolution specified in the data format base class.
void set_wrap_t(TextureWrap _wrap_t)
set the texture wrap behaviour in t direction
void set_wrap_s(TextureWrap _wrap_s)
set the texture wrap behaviour in s direction
void set_min_filter(TextureFilter _min_filter, float _anisotropy=2.0f)
set the minification filters, if minification is set to TF_ANISOTROP, the second floating point param...
class that extends obj_material with the management of textures
void set_alpha_test(AlphaTestFunc _alpha_test_func=AT_GREATER, float _alpha_threshold=0.0f)
configure the alpha test that is performed in case alpha values are given in the textures
int add_texture_reference(cgv::render::texture &tex)
add a reference to a new texture that is managed outside of this class and return its index
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
TextureFilter
different texture filter
TextureWrap
different texture wrap modes
bool build_render_info(const std::string &file_name, const fx::gltf::Document &doc, cgv::render::context &ctx, cgv::render::render_info &R)
construct render info from gltf document
void extract_mesh(const std::string &file_name, const fx::gltf::Document &doc, cgv::media::mesh::simple_mesh< float > &mesh, int mesh_index, int primitive_index)
extract simple mesh form gltf document
void extract_additional_information(const fx::gltf::Document &doc, box3 &box, size_t &vertex_count)
extract bounding box and vertex count from gltf document
bool write_gltf(const std::string &file_name, const cgv::render::render_info &R)
NOT IMPLEMENTED YET.
PrimitiveType
different primitive types
@ TI_INT16
signed integer stored in 8 bits
@ TI_FLT32
floating point type stored in 16 bits
@ TI_UINT32
unsigned integer stored in 16 bits
@ TI_UINT8
signed integer stored in 64 bits
@ TI_UINT16
unsigned integer stored in 8 bits
std::string to_string(const std::string &v, unsigned int w, unsigned int p, bool)
specialization of conversion from string to strings
cgv::media::color< float, cgv::media::RGB, cgv::media::OPACITY > rgba
declare rgba color type with 32 bit components
cgv::media::color< float, cgv::media::RGB > rgb
declare rgb color type with 32 bit components
cgv::math::fvec< float, 3 > vec3
declare type of 3d single precision floating point vectors
compact type description of data that can be sent to the context; convertible to int