mirror of
https://github.com/minetest/irrlicht.git
synced 2024-11-18 00:08:20 +01:00
Fix indices, inverted models, & multiple models failing to load
Fix embedded textures causing a model not to load Add todo Add another todo Push current (broken) prototyping Fix missing bracket Make a single array object work Convert hard array into dynamic vector Simplify semantics Remove "new" Add blocker for vscode environment changes Disable non-dynamic prototyping Add comment Add more informative debug & disable it Add additional items to gitignore Add debug info for scalar value Output even more debug info Make textures render correctly Insert the indices properly Update .gitignore Disable y flip Make a reusable vertex buffer :) Disallow embedded textures More disable Set up implementation for contiguous model Add a note More automation & framework Final framework before stepping into function overhaul Hold track of current_index Integrate iterators More integration Rename, it's going to need 2 counters Correctly offset the count to the right Sync normals with positions Time to use a tuple Set up other counters Do return value Do input passing Make (somewhat) working contiguous model Add getter for translation data Add debug info for future utilization Update .gitignore More debug Update .gitignore Update .gitignore Remove all debug info & clean up Delete this thing Automate everything & put it into spec Spaces into tabs Remove array include as build test Fix the gitignore
This commit is contained in:
parent
b47858cf80
commit
2d4f1ce35e
@ -10,6 +10,8 @@
|
|||||||
#include "SColor.h"
|
#include "SColor.h"
|
||||||
#include "SMesh.h"
|
#include "SMesh.h"
|
||||||
#include "vector3d.h"
|
#include "vector3d.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
#define TINYGLTF_IMPLEMENTATION
|
#define TINYGLTF_IMPLEMENTATION
|
||||||
#include <tiny_gltf.h>
|
#include <tiny_gltf.h>
|
||||||
@ -52,6 +54,13 @@ private:
|
|||||||
std::size_t m_offset;
|
std::size_t m_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A helper function to disable tinygltf embedded image loading
|
||||||
|
bool turn_off_textures_hack(tinygltf::Image *a, const int b, std::string *c,
|
||||||
|
std::string *d, int e, int f, const unsigned char * g,int h, void *user_pointer)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -61,13 +70,22 @@ namespace scene
|
|||||||
static bool tryParseGLTF(io::IReadFile* file, tinygltf::Model& model)
|
static bool tryParseGLTF(io::IReadFile* file, tinygltf::Model& model)
|
||||||
{
|
{
|
||||||
tinygltf::TinyGLTF loader {};
|
tinygltf::TinyGLTF loader {};
|
||||||
|
|
||||||
|
// Stop embedded textures from making model fail to load
|
||||||
|
void *the_void = 0;
|
||||||
|
loader.SetImageLoader(turn_off_textures_hack, the_void);
|
||||||
|
|
||||||
std::string err {};
|
std::string err {};
|
||||||
std::string warn {};
|
std::string warn {};
|
||||||
|
|
||||||
auto buf = std::make_unique<char[]>(file->getSize());
|
auto buf = std::make_unique<char[]>(file->getSize());
|
||||||
file->read(buf.get(), file->getSize());
|
file->read(buf.get(), file->getSize());
|
||||||
return loader.LoadASCIIFromString(
|
|
||||||
&model, &err, &warn, buf.get(), file->getSize(), "", 1);
|
if (err != "" || warn != "") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return loader.LoadASCIIFromString(&model, &err, &warn, buf.get(), file->getSize(), "", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
@ -84,9 +102,7 @@ static T readPrimitive(const BufferOffset& readFrom)
|
|||||||
|
|
||||||
static core::vector2df readVec2DF(const BufferOffset& readFrom)
|
static core::vector2df readVec2DF(const BufferOffset& readFrom)
|
||||||
{
|
{
|
||||||
return core::vector2df(
|
return core::vector2df( readPrimitive<float>(readFrom), readPrimitive<float>( BufferOffset( readFrom, sizeof(float) ) ) );
|
||||||
readPrimitive<float>(readFrom),
|
|
||||||
readPrimitive<float>(BufferOffset(readFrom, sizeof(float))));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,16 +117,6 @@ static core::vector3df readVec3DF(const BufferOffset& readFrom,
|
|||||||
-scale * readPrimitive<float>(BufferOffset(readFrom, 2 * sizeof(float))));
|
-scale * readPrimitive<float>(BufferOffset(readFrom, 2 * sizeof(float))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16* readIndices(const BufferOffset& readFrom, const std::size_t count)
|
|
||||||
{
|
|
||||||
auto* indices = new u16[count]{};
|
|
||||||
for (std::size_t i = 0; i < count; ++i) {
|
|
||||||
indices[i] = readPrimitive<u16>(BufferOffset(readFrom, i * sizeof(u16)));
|
|
||||||
}
|
|
||||||
return indices;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
float getScale(const tinygltf::Model& model)
|
float getScale(const tinygltf::Model& model)
|
||||||
{
|
{
|
||||||
if (model.nodes[0].scale.size() > 0) {
|
if (model.nodes[0].scale.size() > 0) {
|
||||||
@ -119,82 +125,82 @@ float getScale(const tinygltf::Model& model)
|
|||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copyPositions(const tinygltf::Model& model,
|
|
||||||
const Span<video::S3DVertex> vertices,
|
|
||||||
const std::size_t accessorId)
|
|
||||||
|
|
||||||
|
static void copyPositions(const tinygltf::Model& model, const Span<video::S3DVertex> vertices, const std::size_t accessorId)
|
||||||
{
|
{
|
||||||
const auto& view = model.bufferViews[
|
|
||||||
model.accessors[accessorId].bufferView];
|
const auto& view = model.bufferViews[ model.accessors[accessorId].bufferView];
|
||||||
const auto& buffer = model.buffers[view.buffer];
|
const auto& buffer = model.buffers[view.buffer];
|
||||||
for (std::size_t i = 0; i < model.accessors[accessorId].count; ++i) {
|
const auto count = model.accessors[accessorId].count;
|
||||||
const auto v = readVec3DF(BufferOffset(
|
|
||||||
buffer.data, view.byteOffset + 3 * sizeof(float) * i),
|
float scale = getScale(model);
|
||||||
getScale(model));
|
|
||||||
|
for (std::size_t i = 0; i < count; i++) {
|
||||||
|
const auto v = readVec3DF(BufferOffset( buffer.data, view.byteOffset + (3 * sizeof(float) * i)), scale);
|
||||||
vertices.buffer[i].Pos = v;
|
vertices.buffer[i].Pos = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copyNormals(const tinygltf::Model& model,
|
static void copyNormals(const tinygltf::Model& model, const Span<video::S3DVertex> vertices, const std::size_t accessorId)
|
||||||
const Span<video::S3DVertex> vertices,
|
|
||||||
const std::size_t accessorId)
|
|
||||||
{
|
{
|
||||||
const auto& view = model.bufferViews[
|
const auto& view = model.bufferViews[model.accessors[accessorId].bufferView];
|
||||||
model.accessors[accessorId].bufferView];
|
|
||||||
const auto& buffer = model.buffers[view.buffer];
|
const auto& buffer = model.buffers[view.buffer];
|
||||||
for (std::size_t i = 0; i < model.accessors[accessorId].count; ++i) {
|
const auto count = model.accessors[accessorId].count;
|
||||||
const auto n = readVec3DF(BufferOffset(
|
|
||||||
buffer.data, view.byteOffset + 3 * sizeof(float) * i));
|
for (std::size_t i = 0; i < count; ++i) {
|
||||||
|
const auto n = readVec3DF(BufferOffset( buffer.data, view.byteOffset + 3 * sizeof(float) * i ));
|
||||||
vertices.buffer[i].Normal = n;
|
vertices.buffer[i].Normal = n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copyTCoords(const tinygltf::Model& model,
|
static void copyTCoords(const tinygltf::Model& model, const Span<video::S3DVertex> vertices, const std::size_t accessorId)
|
||||||
const Span<video::S3DVertex> vertices,
|
|
||||||
const std::size_t accessorId)
|
|
||||||
{
|
{
|
||||||
const auto& view = model.bufferViews[
|
const auto& view = model.bufferViews[ model.accessors[accessorId].bufferView ];
|
||||||
model.accessors[accessorId].bufferView];
|
|
||||||
const auto& buffer = model.buffers[view.buffer];
|
const auto& buffer = model.buffers[view.buffer];
|
||||||
for (std::size_t i = 0; i < model.accessors[accessorId].count; ++i) {
|
const auto count = model.accessors[accessorId].count;
|
||||||
const auto t = readVec2DF(BufferOffset(
|
|
||||||
buffer.data, view.byteOffset + 2 * sizeof(float) * i));
|
for (std::size_t i = 0; i < count; ++i) {
|
||||||
|
const auto t = readVec2DF(BufferOffset(buffer.data, view.byteOffset + 2 * sizeof(float) * i));
|
||||||
vertices.buffer[i].TCoords = t;
|
vertices.buffer[i].TCoords = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static video::S3DVertex* getVertices(const tinygltf::Model& model,
|
static void getIndices(const tinygltf::Model& model, const std::size_t accessorId, std::vector<u16> *indicesBuffer)
|
||||||
const std::size_t accessorId)
|
|
||||||
{
|
{
|
||||||
auto* vertexBuffer = new video::S3DVertex[
|
const auto& view = model.bufferViews[model.accessors[accessorId].bufferView];
|
||||||
model.accessors[accessorId].count]{};
|
const auto& modelIndices = model.buffers[view.buffer];
|
||||||
Span<video::S3DVertex> vertices{
|
|
||||||
vertexBuffer, model.accessors[accessorId].count};
|
|
||||||
copyPositions(model, vertices, accessorId);
|
|
||||||
|
|
||||||
const auto normalsField
|
auto bufferobject = BufferOffset(modelIndices.data, view.byteOffset);
|
||||||
= model.meshes[0].primitives[0].attributes.find("NORMAL");
|
auto count = model.accessors[accessorId].count;
|
||||||
if (normalsField != model.meshes[0].primitives[0].attributes.end()) {
|
|
||||||
copyNormals(model, vertices, normalsField->second);
|
for (std::size_t i = 0; i < count; i++) {
|
||||||
|
auto current = readPrimitive<u16>(BufferOffset(bufferobject, i * sizeof(u16)));
|
||||||
|
// Inverse the order of indices
|
||||||
|
indicesBuffer->insert(indicesBuffer->begin(), current);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto tCoordsField
|
|
||||||
= model.meshes[0].primitives[0].attributes.find("TEXCOORD_0");
|
|
||||||
if (tCoordsField != model.meshes[0].primitives[0].attributes.end()) {
|
|
||||||
copyTCoords(model, vertices, tCoordsField->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
return vertexBuffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16* getIndices(const tinygltf::Model& model,
|
// Returns a tuple of the current counts (current_vertex_index, current_normals_index, current_tcoords_index)
|
||||||
const std::size_t accessorId)
|
static void getVertices
|
||||||
|
( const tinygltf::Model& model, const std::size_t accessorId, Span<video::S3DVertex> *verticesBuffer,
|
||||||
|
std::size_t mesh_index, std::size_t primitive_index )
|
||||||
{
|
{
|
||||||
const auto& view = model.bufferViews[
|
copyPositions(model, *verticesBuffer, accessorId);
|
||||||
model.accessors[accessorId].bufferView];
|
|
||||||
const auto& indicesBuffer = model.buffers[view.buffer];
|
const auto normalsField = model.meshes[mesh_index].primitives[primitive_index].attributes.find("NORMAL");
|
||||||
return readIndices(
|
|
||||||
BufferOffset(indicesBuffer.data, view.byteOffset),
|
if (normalsField != model.meshes[mesh_index].primitives[primitive_index].attributes.end()) {
|
||||||
model.accessors[accessorId].count);
|
copyNormals(model, *verticesBuffer, normalsField->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto tCoordsField = model.meshes[mesh_index].primitives[primitive_index].attributes.find("TEXCOORD_0");
|
||||||
|
|
||||||
|
if (tCoordsField != model.meshes[mesh_index].primitives[primitive_index].attributes.end()) {
|
||||||
|
copyTCoords(model, *verticesBuffer, tCoordsField->second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CGLTFMeshFileLoader::CGLTFMeshFileLoader()
|
CGLTFMeshFileLoader::CGLTFMeshFileLoader()
|
||||||
@ -215,22 +221,41 @@ IAnimatedMesh* CGLTFMeshFileLoader::createMesh(io::IReadFile* file)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto indicesAccessorId =
|
// Create the base mesh
|
||||||
model.meshes[0].primitives[0].indices;
|
|
||||||
const auto positionAccessorId =
|
|
||||||
model.meshes[0].primitives[0].attributes["POSITION"];
|
|
||||||
|
|
||||||
auto* indices = getIndices(model, indicesAccessorId);
|
|
||||||
auto* vertices = getVertices(model, positionAccessorId);
|
|
||||||
|
|
||||||
SMeshBuffer* meshbuf { new SMeshBuffer {} };
|
|
||||||
|
|
||||||
meshbuf->append(vertices, model.accessors[positionAccessorId].count,
|
|
||||||
indices, model.accessors[indicesAccessorId].count);
|
|
||||||
|
|
||||||
SMesh* mesh { new SMesh {} };
|
SMesh* mesh { new SMesh {} };
|
||||||
mesh->addMeshBuffer(meshbuf);
|
|
||||||
|
|
||||||
|
// Iterate models
|
||||||
|
for (std::size_t mesh_index = 0; mesh_index < model.meshes.size(); mesh_index++) {
|
||||||
|
// Iterate primitives
|
||||||
|
for (std::size_t primitive_index = 0; primitive_index < model.meshes[mesh_index].primitives.size(); primitive_index++) {
|
||||||
|
|
||||||
|
const auto positionAccessorId = model.meshes[mesh_index].primitives[primitive_index].attributes["POSITION"];
|
||||||
|
const auto indicesAccessorId = model.meshes[mesh_index].primitives[primitive_index].indices;
|
||||||
|
|
||||||
|
// Creates counts for preallocation
|
||||||
|
std::size_t vertices_count = model.accessors[positionAccessorId].count;
|
||||||
|
|
||||||
|
// We must count to create containers for the data
|
||||||
|
// Create new buffer for vertices, positions, and normals. Will loop through this soon
|
||||||
|
auto* vertexBuffer = new video::S3DVertex[vertices_count]{};
|
||||||
|
// This is used to copy data into the vertexBuffer
|
||||||
|
Span<video::S3DVertex> verticesBuffer{ vertexBuffer, vertices_count };
|
||||||
|
// Create dynamic indices buffer so it's easier to work with
|
||||||
|
std::vector<u16> indicesBuffer;
|
||||||
|
|
||||||
|
getIndices(model, indicesAccessorId, &indicesBuffer);
|
||||||
|
getVertices(model, positionAccessorId, &verticesBuffer, mesh_index, primitive_index);
|
||||||
|
|
||||||
|
// Create the mesh buffer
|
||||||
|
SMeshBuffer* meshbuf { new SMeshBuffer {} };
|
||||||
|
meshbuf->append(vertexBuffer, vertices_count, indicesBuffer.data(), indicesBuffer.size());
|
||||||
|
|
||||||
|
mesh->addMeshBuffer(meshbuf);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the mesh animations
|
||||||
SAnimatedMesh* animatedMesh { new SAnimatedMesh {} };
|
SAnimatedMesh* animatedMesh { new SAnimatedMesh {} };
|
||||||
animatedMesh->addMesh(mesh);
|
animatedMesh->addMesh(mesh);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user