3 #if defined(LUG_SYSTEM_ANDROID) 4 #include <android/asset_manager.h> 10 #include <gltf2/Exceptions.hpp> 24 static void*
getBufferViewData(
const gltf2::Asset& asset,
const gltf2::Accessor& accessor) {
25 const gltf2::BufferView& bufferView = asset.bufferViews[accessor.bufferView];
26 const gltf2::Buffer& buffer = asset.buffers[bufferView.buffer];
29 LUG_LOG.error(
"GltfLoader::createMesh Buffer data can't be null");
34 return buffer.data + bufferView.byteOffset + accessor.byteOffset;
38 uint32_t componentSize = 0;
39 switch (accessor.componentType) {
40 case gltf2::Accessor::ComponentType::Byte:
41 componentSize =
sizeof(char);
43 case gltf2::Accessor::ComponentType::UnsignedByte:
44 componentSize =
sizeof(
unsigned char);
46 case gltf2::Accessor::ComponentType::Short:
47 componentSize =
sizeof(short);
49 case gltf2::Accessor::ComponentType::UnsignedShort:
50 componentSize =
sizeof(
unsigned short);
52 case gltf2::Accessor::ComponentType::UnsignedInt:
53 componentSize =
sizeof(
unsigned int);
55 case gltf2::Accessor::ComponentType::Float:
56 componentSize =
sizeof(float);
61 switch (accessor.type) {
62 case gltf2::Accessor::Type::Scalar:
64 case gltf2::Accessor::Type::Vec2:
65 return componentSize * 2;
66 case gltf2::Accessor::Type::Vec3:
67 return componentSize * 3;
68 case gltf2::Accessor::Type::Vec4:
69 return componentSize * 4;
70 case gltf2::Accessor::Type::Mat2:
71 return componentSize * 4;
72 case gltf2::Accessor::Type::Mat3:
73 return componentSize * 9;
74 case gltf2::Accessor::Type::Mat4:
75 return componentSize * 16;
82 const gltf2::Texture& gltfTexture = asset.textures[index];
90 if (gltfTexture.source != -1) {
92 if (!textureBuilder.
addLayer(asset.images[gltfTexture.source].uri)) {
93 LUG_LOG.error(
"GltfLoader::createTexture: Can't load the texture \"{}\"", asset.images[gltfTexture.source].uri);
98 if (gltfTexture.sampler != -1) {
99 const gltf2::Sampler& sampler = asset.samplers[gltfTexture.sampler];
101 switch(sampler.magFilter) {
102 case gltf2::Sampler::MagFilter::None:
104 case gltf2::Sampler::MagFilter::Nearest:
107 case gltf2::Sampler::MagFilter::Linear:
112 switch(sampler.minFilter) {
113 case gltf2::Sampler::MinFilter::None:
115 case gltf2::Sampler::MinFilter::Nearest:
118 case gltf2::Sampler::MinFilter::Linear:
121 case gltf2::Sampler::MinFilter::NearestMipMapNearest:
125 case gltf2::Sampler::MinFilter::LinearMipMapNearest:
129 case gltf2::Sampler::MinFilter::NearestMipMapLinear:
133 case gltf2::Sampler::MinFilter::LinearMipMapLinear:
139 switch(sampler.wrapS) {
140 case gltf2::Sampler::WrappingMode::ClampToEdge:
143 case gltf2::Sampler::WrappingMode::MirroredRepeat:
146 case gltf2::Sampler::WrappingMode::Repeat:
151 switch(sampler.wrapT) {
152 case gltf2::Sampler::WrappingMode::ClampToEdge:
155 case gltf2::Sampler::WrappingMode::MirroredRepeat:
158 case gltf2::Sampler::WrappingMode::Repeat:
165 return loadedAssets.
textures[index];
177 const gltf2::Material& gltfMaterial = asset.materials[index];
181 materialBuilder.
setName(gltfMaterial.name);
184 gltfMaterial.pbr.baseColorFactor[0],
185 gltfMaterial.pbr.baseColorFactor[1],
186 gltfMaterial.pbr.baseColorFactor[2],
187 gltfMaterial.pbr.baseColorFactor[3]
190 if (gltfMaterial.pbr.baseColorTexture.index != -1) {
193 LUG_LOG.error(
"GltfLoader::createMaterial Can't create the texture resource");
203 if (gltfMaterial.pbr.metallicRoughnessTexture.index != -1) {
206 LUG_LOG.error(
"GltfLoader::createMaterial Can't create the texture resource");
213 if (gltfMaterial.normalTexture.index != -1) {
216 LUG_LOG.error(
"GltfLoader::createMaterial Can't create the texture resource");
220 materialBuilder.
setNormalTexture(texture, gltfMaterial.normalTexture.texCoord);
223 if (gltfMaterial.occlusionTexture.index != -1) {
226 LUG_LOG.error(
"GltfLoader::createMaterial Can't create the texture resource");
233 if (gltfMaterial.emissiveTexture.index != -1) {
236 LUG_LOG.error(
"GltfLoader::createMaterial Can't create the texture resource");
244 gltfMaterial.emissiveFactor[0],
245 gltfMaterial.emissiveFactor[1],
246 gltfMaterial.emissiveFactor[2]
265 Math::Vec3f* data =
new Math::Vec3f[accessorCount];
267 uint32_t trianglesCount = accessorCount / 3;
268 uint32_t positionsIdx = 0;
269 for (uint32_t i = 0; i < trianglesCount; ++i) {
270 Math::Vec3f a{positions[positionsIdx], positions[positionsIdx + 1], positions[positionsIdx + 2]};
271 Math::Vec3f b{positions[positionsIdx + 3], positions[positionsIdx + 4], positions[positionsIdx + 5]};
272 Math::Vec3f c{positions[positionsIdx + 6], positions[positionsIdx + 7], positions[positionsIdx + 8]};
273 Math::Vec3f edge1 = b - a;
274 Math::Vec3f edge2 = c - a;
276 data[i++] =
cross(edge1, edge2);
283 const gltf2::Mesh& gltfMesh = asset.meshes[index];
285 if (loadedAssets.
meshes[index]) {
286 return loadedAssets.
meshes[index];
290 meshBuilder.
setName(gltfMesh.name);
292 for (
const gltf2::Primitive& gltfPrimitive : gltfMesh.primitives) {
296 switch (gltfPrimitive.mode) {
297 case gltf2::Primitive::Mode::Points:
300 case gltf2::Primitive::Mode::Lines:
303 case gltf2::Primitive::Mode::LineLoop:
304 LUG_LOG.error(
"GltfLoader::createMesh Unsupported mode LineLoop");
306 case gltf2::Primitive::Mode::LineStrip:
309 case gltf2::Primitive::Mode::Triangles:
312 case gltf2::Primitive::Mode::TriangleStrip:
315 case gltf2::Primitive::Mode::TriangleFan:
321 if (gltfPrimitive.indices != -1) {
322 const gltf2::Accessor& accessor = asset.accessors[gltfPrimitive.indices];
340 uint32_t accessorCount{0};
342 bool hasNormals =
false;
344 for (
auto& attribute : gltfPrimitive.attributes) {
346 if (attribute.first ==
"POSITION") {
348 }
else if (attribute.first ==
"NORMAL") {
351 }
else if (attribute.first ==
"TANGENT") {
353 }
else if (attribute.first.find(
"TEXCOORD_") != std::string::npos) {
355 }
else if (attribute.first.find(
"COLOR_") != std::string::npos) {
358 LUG_LOG.warn(
"GltfLoader::createMesh Unsupported attribute {}", attribute.first);
363 const gltf2::Accessor& accessor = asset.accessors[attribute.second];
371 positions.data = data;
372 positions.accessorCount = accessor.count;
379 void* data =
generateNormals((
float*)positions.data, positions.accessorCount);
384 data,
sizeof(Math::Vec3f), positions.accessorCount,
392 LUG_LOG.error(
"GltfLoader::createMesh Can't create the material resource");
402 return loadedAssets.
meshes[index];
406 const gltf2::Node& gltfNode = asset.nodes[index];
411 if (gltfNode.mesh != -1) {
414 LUG_LOG.error(
"GltfLoader::createNode Can't create the mesh resource");
421 gltfNode.translation[0],
422 gltfNode.translation[1],
423 gltfNode.translation[2]
427 gltfNode.rotation[3],
428 gltfNode.rotation[0],
429 gltfNode.rotation[1],
439 for (uint32_t nodeIdx : gltfNode.children) {
440 if (!
createNode(renderer, asset, loadedAssets, nodeIdx, *node)) {
451 #if defined(LUG_SYSTEM_ANDROID) 454 asset = gltf2::load(filename);
458 }
catch (gltf2::MisformattedException&
e) {
459 LUG_LOG.error(
"GltfLoader::loadFile Can't load the file \"{}\": {}", filename, e.what());
466 loadedAssets.
textures.resize(asset.textures.size());
467 loadedAssets.
materials.resize(asset.materials.size());
468 loadedAssets.
meshes.resize(asset.meshes.size());
471 if (asset.scene == -1) {
474 const gltf2::Scene& gltfScene = asset.scenes[asset.scene];
477 sceneBuilder.
setName(gltfScene.name);
481 LUG_LOG.error(
"GltfLoader::loadFile Can't create the scene resource");
485 for (uint32_t nodeIdx : gltfScene.nodes) {
Resource::SharedPtr< Render::Mesh > build()
void setName(const std::string &name)
Sets the name.
Class for loading a type of file.
Resource::SharedPtr< Render::Material > createMaterial(Renderer &renderer, const gltf2::Asset &asset, GltfLoader::LoadedAssets &loadedAssets, int32_t index)
void setOcclusionTexture(Resource::SharedPtr< Render::Texture > texture, uint32_t texCoord=0, float strength=1.0f)
void attachChild(Node &child)
PrimitiveSet * addPrimitiveSet()
Adds a primitive set to the builder and returns it.
void setMetallicRoughnessTexture(Resource::SharedPtr< Render::Texture > texture, uint32_t texCoord=0)
Tangent (VEC4<FLOAT> w component is a sign value (-1 or +1) indicating handedness of the tangent basi...
void scale(const Math::Vec3f &scale)
void setMinFilter(Render::Texture::Filter minFilter)
void setRoughnessFactor(float factor)
void setMaterial(Resource::SharedPtr< Render::Material > material)
void setName(const std::string &name)
Sets the name.
std::vector< Resource::SharedPtr< Render::Texture > > textures
Resource::SharedPtr< Render::Mesh > createMesh(Renderer &renderer, const gltf2::Asset &asset, GltfLoader::LoadedAssets &loadedAssets, int32_t index)
void setRotation(float angle, const Math::Vec3f &axis, TransformSpace space=TransformSpace::Local)
The first two vertices define the first segment, with subsequent pairs of vertices each defining one ...
void setWrapS(Render::Texture::WrappingMode wrapS)
void addAttributeBuffer(const void *data, uint32_t elementSize, uint32_t elementsCount, Render::Mesh::PrimitiveSet::Attribute::Type type)
void setMetallicFactor(float factor)
constexpr Vector< 3, T > cross(const Vector< 3, T > &lhs, const Vector< 3, T > &rhs)
Dummy class for a shared pointer.
std::vector< Resource::SharedPtr< Render::Material > > materials
Resource::SharedPtr< Render::Material > build()
Resource::SharedPtr< Render::Texture > createTexture(Renderer &renderer, const gltf2::Asset &asset, GltfLoader::LoadedAssets &loadedAssets, int32_t index)
void attachMeshInstance(Resource::SharedPtr< Render::Mesh > mesh, Resource::SharedPtr< Render::Material > material=nullptr)
void setMagFilter(Render::Texture::Filter magFilter)
std::vector< Resource::SharedPtr< Render::Mesh > > meshes
static void * getBufferViewData(const gltf2::Asset &asset, const gltf2::Accessor &accessor)
void setBaseColorTexture(Resource::SharedPtr< Render::Texture > texture, uint32_t texCoord=0)
void setEmissiveTexture(Resource::SharedPtr< Render::Texture > texture, uint32_t texCoord=0)
bool addLayer(const std::string &filename, bool hdr=false)
void setWrapT(Render::Texture::WrappingMode wrapT)
static ANativeActivity * activity
Resource::SharedPtr< Render::Material > defaultMaterial
void setEmissiveFactor(const Math::Vec3f &factor)
Node * createSceneNode(const std::string &name)
static SharedPtr< T > cast(const SharedPtr< RhsT > &rhs)
Dynamic casting of a SharedPtr to another one (RhsT to T)
Resource::SharedPtr< Resource > loadFile(const std::string &filename) override final
Loads a glTF ressource from a file.
static void * generateNormals(float *positions, uint32_t accessorCount)
bool createNode(Renderer &renderer, const gltf2::Asset &asset, GltfLoader::LoadedAssets &loadedAssets, int32_t index, Scene::Node &parent)
void setMipMapFilter(Render::Texture::Filter mipMapFilter)
Resource::SharedPtr< lug::Graphics::Scene::Scene > build()
Resource::SharedPtr< Render::Material > createDefaultMaterial(Renderer &renderer, GltfLoader::LoadedAssets &loadedAssets)
void setName(const std::string &name)
Sets the name.
void setPosition(const Math::Vec3f &position, TransformSpace space=TransformSpace::Local)
The first vertex specifies the first segment’s start point while the second vertex specifies the fir...
void setMode(Render::Mesh::PrimitiveSet::Mode mode)
GltfLoader(Renderer &renderer)
void setNormalTexture(Resource::SharedPtr< Render::Texture > texture, uint32_t texCoord=0, float scale=1.0f)
Each vertex defines a separate point.
Resource::SharedPtr< Render::Texture > build()
void setBaseColorFactor(const Math::Vec4f &factor)
Quaternion< float > Quatf
static uint32_t getAttributeSize(const gltf2::Accessor &accessor)