mirror of
https://github.com/danule222/xrbDS.git
synced 2025-06-18 14:25:33 -04:00
Implement runtime texture loading
This commit is contained in:
parent
f22b9e1bb6
commit
cb1d89065f
@ -5,9 +5,30 @@
|
|||||||
|
|
||||||
MeshFilter::MeshFilter(const FString &path) {
|
MeshFilter::MeshFilter(const FString &path) {
|
||||||
// Load the mesh from the file
|
// Load the mesh from the file
|
||||||
auto vertices = Utils::File::ReadObjFile(path);
|
auto [shapes, materials] = Utils::File::ReadObjFile(path);
|
||||||
|
|
||||||
mesh = LoadResource<Mesh>(vertices);
|
TVector<PtrShr<Texture>> textures;
|
||||||
|
for (const auto &material : materials) {
|
||||||
|
auto texture_binary = Utils::File::ReadBinaryFile<unsigned int>(
|
||||||
|
path.substr(0, path.find_last_of("/"))
|
||||||
|
.append("/")
|
||||||
|
.append(material.diffuse_texname.substr(
|
||||||
|
0, material.diffuse_texname.find_last_of(".")))
|
||||||
|
.append(".img.bin"));
|
||||||
|
|
||||||
|
// auto palette_binary = Utils::File::ReadBinaryFile<unsigned short>(
|
||||||
|
// path.substr(0, path.find_last_of("/"))
|
||||||
|
// .append("/")
|
||||||
|
// .append(material.diffuse_texname.substr(
|
||||||
|
// 0, material.diffuse_texname.find_last_of(".")))
|
||||||
|
// .append(".pal.bin"));
|
||||||
|
|
||||||
|
auto palette_binary = TVector<unsigned short>();
|
||||||
|
|
||||||
|
textures.push_back(LoadResource<Texture>(texture_binary, palette_binary));
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh = LoadResource<Mesh>(shapes, materials, textures);
|
||||||
}
|
}
|
||||||
|
|
||||||
PtrUnq<MeshFilter> MeshFilter::Initialize(const FString &path) {
|
PtrUnq<MeshFilter> MeshFilter::Initialize(const FString &path) {
|
||||||
|
@ -44,12 +44,19 @@ PtrUnq<Engine> &Engine::GetInstance() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Engine::run() {
|
void Engine::run() {
|
||||||
// TEST ------------------------
|
Renderer::GetInstance();
|
||||||
|
|
||||||
|
// TEST ------------------------
|
||||||
// Create a MeshInstance3D
|
// Create a MeshInstance3D
|
||||||
PtrShr<MeshInstance3D> meshInstance =
|
PtrShr<MeshInstance3D> meshInstance =
|
||||||
NewNode<MeshInstance3D>("meshes/mococo/mococo.obj");
|
NewNode<MeshInstance3D>("meshes/mococo/mococo.obj");
|
||||||
|
|
||||||
|
// PtrShr<MeshInstance3D> meshIPnstance =
|
||||||
|
// NewNode<MeshInstance3D>("meshes/cube/cube-tex.obj");
|
||||||
|
|
||||||
|
// PtrShr<MeshInstance3D> meshInstance =
|
||||||
|
// NewNode<MeshInstance3D>("meshes/quad/quad.obj");
|
||||||
|
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
|
|
||||||
while (pmMainLoop()) {
|
while (pmMainLoop()) {
|
||||||
@ -63,6 +70,9 @@ void Engine::processInput() { Input::Update(); }
|
|||||||
|
|
||||||
void Engine::update() {
|
void Engine::update() {
|
||||||
// Update
|
// Update
|
||||||
|
if (Input::IsButtonDown(EButton::A)) {
|
||||||
|
iprintf("A button pressed\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::render() {
|
void Engine::render() {
|
||||||
@ -84,8 +94,7 @@ void Engine::render() {
|
|||||||
|
|
||||||
Engine::Engine() {
|
Engine::Engine() {
|
||||||
// Initialize nitroFS
|
// Initialize nitroFS
|
||||||
char nitroFSPath[32];
|
char nitroFSPath[] = {"assets"};
|
||||||
strcpy(nitroFSPath, "assets");
|
|
||||||
char *nitroFSPathptr = nitroFSPath;
|
char *nitroFSPathptr = nitroFSPath;
|
||||||
if (!nitroFSInit(&nitroFSPathptr))
|
if (!nitroFSInit(&nitroFSPathptr))
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#include <nds.h>
|
#include <nds.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "input/input.h"
|
||||||
|
|
||||||
PtrUnq<Renderer> Renderer::Instance;
|
PtrUnq<Renderer> Renderer::Instance;
|
||||||
|
|
||||||
PtrUnq<Renderer> &Renderer::GetInstance() {
|
PtrUnq<Renderer> &Renderer::GetInstance() {
|
||||||
@ -16,34 +18,45 @@ PtrUnq<Renderer> &Renderer::GetInstance() {
|
|||||||
return Instance;
|
return Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TEST -------------------
|
||||||
|
float rotation = 45.f;
|
||||||
|
// TEST -------------------
|
||||||
void Renderer::beginFrame() {
|
void Renderer::beginFrame() {
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
gluPerspective(70, 256.0 / 192.0, 0.1, 100);
|
gluPerspective(70, 256.0 / 192.0, 0.1, 100);
|
||||||
|
// glPolyFmt(POLY_ALPHA(31) | POLY_CULL_BACK);
|
||||||
|
|
||||||
|
// glMatrixMode(GL_TEXTURE);
|
||||||
|
// glLoadIdentity();
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glPushMatrix(); // Save the current matrix state
|
|
||||||
|
|
||||||
glPolyFmt(POLY_ALPHA(31) | POLY_CULL_BACK);
|
|
||||||
|
|
||||||
glLoadIdentity(); // Load the identity matrix
|
glLoadIdentity(); // Load the identity matrix
|
||||||
|
|
||||||
|
// TEST -------------------
|
||||||
|
if (Input::IsButtonHeld(EButton::LEFT))
|
||||||
|
rotation++;
|
||||||
|
if (Input::IsButtonHeld(EButton::RIGHT))
|
||||||
|
rotation--;
|
||||||
|
// TEST -------------------
|
||||||
|
|
||||||
// Render scene
|
// Render scene
|
||||||
glTranslatef(0.f, 0.f, -4.f); // Move the camera back
|
glTranslatef(0.f, -.75f, -2.f); // Move the camera back
|
||||||
glRotatef(45, 1, 1, 0); // Rotation
|
glRotatef(rotation, 1, 1, 0); // Rotation
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::render(const Transform &transform,
|
void Renderer::render(const Transform &transform,
|
||||||
const MeshFilter &meshFilter) {
|
const MeshFilter &meshFilter) {
|
||||||
// drawCube(1.0f); // Draw a cube
|
glPolyFmt(POLY_ALPHA(31) | POLY_CULL_BACK);
|
||||||
|
glBindTexture(0, meshFilter.getMesh()->getTextures()[0]->getId());
|
||||||
glBegin(GL_TRIANGLES);
|
glBegin(GL_TRIANGLES);
|
||||||
|
|
||||||
for (const auto &shapes : meshFilter.getMesh()->getVertices()) {
|
glColor3b(255, 255, 255);
|
||||||
for (const auto &vertex : shapes) {
|
for (const auto &shape : meshFilter.getMesh()->getShapes()) {
|
||||||
glColor3f(1.0, 0.0, 0.0); // Red
|
for (const auto &vertex : shape.vertices) {
|
||||||
glVertex3f(vertex.position.x, vertex.position.y, vertex.position.z);
|
// glNormal3f(vertex.normal.x, vertex.normal.y, vertex.normal.z);
|
||||||
glNormal3f(vertex.normal.x, vertex.normal.y, vertex.normal.z);
|
|
||||||
glTexCoord2f(vertex.texCoords.x, vertex.texCoords.y);
|
glTexCoord2f(vertex.texCoords.x, vertex.texCoords.y);
|
||||||
|
glVertex3f(vertex.position.x, vertex.position.y, vertex.position.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,19 +123,30 @@ void Renderer::drawCube(float size) {
|
|||||||
|
|
||||||
Renderer::Renderer() {
|
Renderer::Renderer() {
|
||||||
// Initialize the video subsystem
|
// Initialize the video subsystem
|
||||||
lcdMainOnTop(); // Set the main screen on top
|
lcdMainOnTop(); // Set the main screen on top
|
||||||
videoSetMode(MODE_0_3D); // Set 3D rendering mode
|
videoSetMode(MODE_0_3D); // Set 3D rendering mode
|
||||||
videoSetModeSub(MODE_5_2D); // Set 2D rendering mode for the sub-screen
|
videoSetModeSub(MODE_5_2D); // Set 2D rendering mode for the sub-screen
|
||||||
vramSetBankA(VRAM_A_MAIN_BG); // Allocate VRAM for textures
|
vramSetBankB(VRAM_B_TEXTURE);
|
||||||
|
vramSetBankC(VRAM_C_TEXTURE);
|
||||||
|
vramSetBankD(VRAM_D_TEXTURE);
|
||||||
|
vramSetBankE(VRAM_E_TEX_PALETTE);
|
||||||
|
vramSetBankF(VRAM_F_LCD);
|
||||||
|
// vramSetBankG(VRAM_G_TEX_PALETTE);
|
||||||
|
|
||||||
// Initialize the 3D engine
|
// Initialize the 3D engine
|
||||||
glInit();
|
glInit();
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
glViewport(0, 0, 255, 191); // Set viewport
|
||||||
glEnable(GL_ANTIALIAS);
|
glEnable(GL_ANTIALIAS);
|
||||||
glClearColor(0, 0, 0, 31); // Set clear color (black)
|
glClearColor(0, 0, 0, 31); // Set clear color (black)
|
||||||
glClearPolyID(63); // Set default polygon ID
|
glClearPolyID(63); // Set default polygon ID
|
||||||
glClearDepth(GL_MAX_DEPTH); // Set clear depth
|
glClearDepth(GL_MAX_DEPTH); // Set clear depth
|
||||||
glViewport(0, 0, 255, 191); // Set viewport
|
glEnable(GL_BLEND);
|
||||||
|
|
||||||
|
vramSetBankA(VRAM_A_TEXTURE); // Allocate VRAM for textures
|
||||||
|
vramSetBankB(VRAM_B_LCD);
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
|
consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 23, 2, false, true);
|
||||||
consoleDemoInit();
|
consoleDemoInit();
|
||||||
}
|
}
|
||||||
|
@ -4,20 +4,20 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
// Static members
|
// Static members
|
||||||
u32 Input::KeysHeldState = 0;
|
u32 Input::ButtonsHeldState = 0;
|
||||||
u32 Input::KeysDownState = 0;
|
u32 Input::ButtonsDownState = 0;
|
||||||
u32 Input::KeysUpState = 0;
|
u32 Input::ButtonsUpState = 0;
|
||||||
|
|
||||||
void Input::Update() {
|
void Input::Update() {
|
||||||
// Update key states
|
// Update key states
|
||||||
scanKeys();
|
scanKeys();
|
||||||
KeysHeldState = keysHeld();
|
ButtonsHeldState = keysHeld();
|
||||||
KeysDownState = keysDown();
|
ButtonsDownState = keysDown();
|
||||||
KeysUpState = keysUp();
|
ButtonsUpState = keysUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Input::IsKeyHeld(EKey key) { return KeysHeldState & key; }
|
bool Input::IsButtonHeld(EButton key) { return ButtonsHeldState & key; }
|
||||||
|
|
||||||
bool Input::IsKeyDown(EKey key) { return KeysDownState & key; }
|
bool Input::IsButtonDown(EButton key) { return ButtonsDownState & key; }
|
||||||
|
|
||||||
bool Input::IsKeyUp(EKey key) { return KeysUpState & key; }
|
bool Input::IsButtonUp(EButton key) { return ButtonsUpState & key; }
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
#include "resources/mesh.h"
|
#include "resources/mesh.h"
|
||||||
|
|
||||||
Mesh Mesh::Load(const TVector<TVector<FVertex>> &vertices) {
|
Mesh Mesh::Load(const TVector<FShape> &shapes,
|
||||||
return std::move(Mesh(vertices));
|
const TVector<FMaterial> &materials,
|
||||||
|
const TVector<PtrShr<Texture>> &textures) {
|
||||||
|
return std::move(Mesh(shapes, materials, textures));
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh::Mesh(const TVector<TVector<FVertex>> &vertices)
|
Mesh::Mesh(const TVector<FShape> &shapes, const TVector<FMaterial> &materials,
|
||||||
: Super(), vertices(vertices) {}
|
const TVector<PtrShr<Texture>> &textures)
|
||||||
|
: Super(), shapes(shapes), materials(materials), textures(textures) {}
|
27
engine/resources/texture.cpp
Normal file
27
engine/resources/texture.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include "resources/texture.h"
|
||||||
|
|
||||||
|
#include <nds/arm9/videoGL.h>
|
||||||
|
|
||||||
|
Texture::~Texture() {
|
||||||
|
// TODO: Check what the hell is happening here
|
||||||
|
// glBindTexture(0, id);
|
||||||
|
// glColorTableEXT(0, 0, 0, 0, 0, nullptr);
|
||||||
|
// glDeleteTextures(1, &id);
|
||||||
|
|
||||||
|
// iprintf("Texture %d deleted\n", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture Texture::Load(TVector<unsigned int> &data,
|
||||||
|
TVector<unsigned short> &palette) {
|
||||||
|
return Texture(data, palette);
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture::Texture(TVector<unsigned int> &data, TVector<unsigned short> &palette)
|
||||||
|
: Super() {
|
||||||
|
glGenTextures(1, &id);
|
||||||
|
glBindTexture(0, id);
|
||||||
|
// TODO: Manage different texture formats
|
||||||
|
glTexImage2D(0, 0, GL_RGBA, TEXTURE_SIZE_128, TEXTURE_SIZE_128, 0,
|
||||||
|
TEXGEN_TEXCOORD, (u8 *)data.data());
|
||||||
|
// glColorTableEXT(0, 0, 32, 0, 0, (u16 *)palette.data());
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#define TINYOBJLOADER_IMPLEMENTATION
|
#define TINYOBJLOADER_IMPLEMENTATION
|
||||||
#include "tiny_obj_loader.h"
|
#include "tiny_obj_loader.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace Utils::File {
|
namespace Utils::File {
|
||||||
|
|
||||||
@ -11,15 +12,13 @@ FString ReadTextFile(const FString &path) {
|
|||||||
FString result;
|
FString result;
|
||||||
FILE *f = fopen(AssetPath(path).c_str(), "rb");
|
FILE *f = fopen(AssetPath(path).c_str(), "rb");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
iprintf("No se pudo abrir el archivo\n");
|
// TODO: iprintf("No se pudo abrir el archivo\n");
|
||||||
} else {
|
} else {
|
||||||
iprintf("Archivo abierto\n");
|
|
||||||
|
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
size_t size = ftell(f);
|
size_t size = ftell(f);
|
||||||
rewind(f);
|
rewind(f);
|
||||||
|
|
||||||
TVector<uint8_t> buffer(size);
|
TVector<u8> buffer(size);
|
||||||
fread(buffer.data(), 1, size, f);
|
fread(buffer.data(), 1, size, f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
@ -30,28 +29,29 @@ FString ReadTextFile(const FString &path) {
|
|||||||
return std::move(result);
|
return std::move(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TVector<TVector<FVertex>> ReadObjFile(const FString &path) {
|
TTuple<TVector<FShape>, TVector<FMaterial>> ReadObjFile(const FString &path) {
|
||||||
|
FString nitroPath = AssetPath(path);
|
||||||
|
FString baseFolder =
|
||||||
|
nitroPath.substr(0, nitroPath.find_last_of("/")).append("/");
|
||||||
|
|
||||||
tinyobj::attrib_t attrib;
|
tinyobj::attrib_t attrib;
|
||||||
TVector<tinyobj::shape_t> shapes;
|
TVector<tinyobj::shape_t> shapes;
|
||||||
TVector<tinyobj::material_t> materials;
|
TVector<tinyobj::material_t> materials;
|
||||||
FString err;
|
FString err;
|
||||||
|
|
||||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err,
|
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err,
|
||||||
AssetPath(path).c_str(),
|
nitroPath.c_str(), baseFolder.c_str(), true);
|
||||||
AssetPath(path + "/..").c_str(), true);
|
|
||||||
|
|
||||||
if (ret)
|
if (!ret) {
|
||||||
iprintf("Cargado correctamente\n");
|
// TODO: print error
|
||||||
else
|
return {TVector<FShape>(), TVector<FMaterial>()};
|
||||||
iprintf("Error al cargar el archivo: %s\n", err.c_str());
|
}
|
||||||
|
|
||||||
iprintf("Numero de materiales: %d\n", materials.size());
|
TVector<FShape> shape_vertices;
|
||||||
|
|
||||||
TVector<TVector<FVertex>> vertices;
|
|
||||||
|
|
||||||
// Loop over shapes
|
// Loop over shapes
|
||||||
for (size_t s = 0; s < shapes.size(); s++) {
|
for (size_t s = 0; s < shapes.size(); s++) {
|
||||||
vertices.push_back({});
|
shape_vertices.push_back({});
|
||||||
// Loop over faces(polygon)
|
// Loop over faces(polygon)
|
||||||
size_t index_offset = 0;
|
size_t index_offset = 0;
|
||||||
for (size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) {
|
for (size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) {
|
||||||
@ -88,20 +88,23 @@ TVector<TVector<FVertex>> ReadObjFile(const FString &path) {
|
|||||||
tinyobj::real_t ty =
|
tinyobj::real_t ty =
|
||||||
attrib.texcoords[2 * size_t(idx.texcoord_index) + 1];
|
attrib.texcoords[2 * size_t(idx.texcoord_index) + 1];
|
||||||
|
|
||||||
|
// I lost 3 days bacause of this :')
|
||||||
|
ty = 1.0f - std::clamp(ty, 0.0f, 1.0f);
|
||||||
|
|
||||||
texCoords = FVector2(tx, ty);
|
texCoords = FVector2(tx, ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
vertices[s].push_back(FVertex(positions, normals, texCoords));
|
shape_vertices[s].vertices.push_back(
|
||||||
|
FVertex(positions, normals, texCoords));
|
||||||
}
|
}
|
||||||
|
|
||||||
index_offset += fv;
|
index_offset += fv;
|
||||||
|
|
||||||
// per-face material
|
// per-face material
|
||||||
// shapes[s].mesh.material_ids[f];
|
// shape_materials.push_back(materials[shapes[s].mesh.material_ids[f]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::move(vertices);
|
return {shape_vertices, materials};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Utils::File
|
} // namespace Utils::File
|
||||||
|
@ -23,6 +23,7 @@ THE SOFTWARE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
//
|
//
|
||||||
|
// xrbDS 0.1 : Change TINYOBJ_SSCANF_BUFFER_SIZE to 512
|
||||||
// version 1.0.6 : Add TINYOBJLOADER_USE_DOUBLE option(#124)
|
// version 1.0.6 : Add TINYOBJLOADER_USE_DOUBLE option(#124)
|
||||||
// version 1.0.5 : Ignore `Tr` when `d` exists in MTL(#43)
|
// version 1.0.5 : Ignore `Tr` when `d` exists in MTL(#43)
|
||||||
// version 1.0.4 : Support multiple filenames for 'mtllib'(#112)
|
// version 1.0.4 : Support multiple filenames for 'mtllib'(#112)
|
||||||
@ -98,15 +99,15 @@ namespace tinyobj {
|
|||||||
// cube_left | cube_right
|
// cube_left | cube_right
|
||||||
|
|
||||||
#ifdef TINYOBJLOADER_USE_DOUBLE
|
#ifdef TINYOBJLOADER_USE_DOUBLE
|
||||||
//#pragma message "using double"
|
// #pragma message "using double"
|
||||||
typedef double real_t;
|
typedef double real_t;
|
||||||
#else
|
#else
|
||||||
//#pragma message "using float"
|
// #pragma message "using float"
|
||||||
typedef float real_t;
|
typedef float real_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TEXTURE_TYPE_NONE, // default
|
TEXTURE_TYPE_NONE, // default
|
||||||
TEXTURE_TYPE_SPHERE,
|
TEXTURE_TYPE_SPHERE,
|
||||||
TEXTURE_TYPE_CUBE_TOP,
|
TEXTURE_TYPE_CUBE_TOP,
|
||||||
TEXTURE_TYPE_CUBE_BOTTOM,
|
TEXTURE_TYPE_CUBE_BOTTOM,
|
||||||
@ -118,18 +119,18 @@ typedef enum {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
texture_type_t type; // -type (default TEXTURE_TYPE_NONE)
|
texture_type_t type; // -type (default TEXTURE_TYPE_NONE)
|
||||||
real_t sharpness; // -boost (default 1.0?)
|
real_t sharpness; // -boost (default 1.0?)
|
||||||
real_t brightness; // base_value in -mm option (default 0)
|
real_t brightness; // base_value in -mm option (default 0)
|
||||||
real_t contrast; // gain_value in -mm option (default 1)
|
real_t contrast; // gain_value in -mm option (default 1)
|
||||||
real_t origin_offset[3]; // -o u [v [w]] (default 0 0 0)
|
real_t origin_offset[3]; // -o u [v [w]] (default 0 0 0)
|
||||||
real_t scale[3]; // -s u [v [w]] (default 1 1 1)
|
real_t scale[3]; // -s u [v [w]] (default 1 1 1)
|
||||||
real_t turbulence[3]; // -t u [v [w]] (default 0 0 0)
|
real_t turbulence[3]; // -t u [v [w]] (default 0 0 0)
|
||||||
// int texture_resolution; // -texres resolution (default = ?) TODO
|
// int texture_resolution; // -texres resolution (default = ?) TODO
|
||||||
bool clamp; // -clamp (default false)
|
bool clamp; // -clamp (default false)
|
||||||
char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm')
|
char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm')
|
||||||
bool blendu; // -blendu (default on)
|
bool blendu; // -blendu (default on)
|
||||||
bool blendv; // -blendv (default on)
|
bool blendv; // -blendv (default on)
|
||||||
real_t bump_multiplier; // -bm (for bump maps only, default 1.0)
|
real_t bump_multiplier; // -bm (for bump maps only, default 1.0)
|
||||||
} texture_option_t;
|
} texture_option_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -141,20 +142,20 @@ typedef struct {
|
|||||||
real_t transmittance[3];
|
real_t transmittance[3];
|
||||||
real_t emission[3];
|
real_t emission[3];
|
||||||
real_t shininess;
|
real_t shininess;
|
||||||
real_t ior; // index of refraction
|
real_t ior; // index of refraction
|
||||||
real_t dissolve; // 1 == opaque; 0 == fully transparent
|
real_t dissolve; // 1 == opaque; 0 == fully transparent
|
||||||
// illumination model (see http://www.fileformat.info/format/material/)
|
// illumination model (see http://www.fileformat.info/format/material/)
|
||||||
int illum;
|
int illum;
|
||||||
|
|
||||||
int dummy; // Suppress padding warning.
|
int dummy; // Suppress padding warning.
|
||||||
|
|
||||||
std::string ambient_texname; // map_Ka
|
std::string ambient_texname; // map_Ka
|
||||||
std::string diffuse_texname; // map_Kd
|
std::string diffuse_texname; // map_Kd
|
||||||
std::string specular_texname; // map_Ks
|
std::string specular_texname; // map_Ks
|
||||||
std::string specular_highlight_texname; // map_Ns
|
std::string specular_highlight_texname; // map_Ns
|
||||||
std::string bump_texname; // map_bump, bump
|
std::string bump_texname; // map_bump, bump
|
||||||
std::string displacement_texname; // disp
|
std::string displacement_texname; // disp
|
||||||
std::string alpha_texname; // map_d
|
std::string alpha_texname; // map_d
|
||||||
|
|
||||||
texture_option_t ambient_texopt;
|
texture_option_t ambient_texopt;
|
||||||
texture_option_t diffuse_texopt;
|
texture_option_t diffuse_texopt;
|
||||||
@ -166,20 +167,20 @@ typedef struct {
|
|||||||
|
|
||||||
// PBR extension
|
// PBR extension
|
||||||
// http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr
|
// http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr
|
||||||
real_t roughness; // [0, 1] default 0
|
real_t roughness; // [0, 1] default 0
|
||||||
real_t metallic; // [0, 1] default 0
|
real_t metallic; // [0, 1] default 0
|
||||||
real_t sheen; // [0, 1] default 0
|
real_t sheen; // [0, 1] default 0
|
||||||
real_t clearcoat_thickness; // [0, 1] default 0
|
real_t clearcoat_thickness; // [0, 1] default 0
|
||||||
real_t clearcoat_roughness; // [0, 1] default 0
|
real_t clearcoat_roughness; // [0, 1] default 0
|
||||||
real_t anisotropy; // aniso. [0, 1] default 0
|
real_t anisotropy; // aniso. [0, 1] default 0
|
||||||
real_t anisotropy_rotation; // anisor. [0, 1] default 0
|
real_t anisotropy_rotation; // anisor. [0, 1] default 0
|
||||||
real_t pad0;
|
real_t pad0;
|
||||||
real_t pad1;
|
real_t pad1;
|
||||||
std::string roughness_texname; // map_Pr
|
std::string roughness_texname; // map_Pr
|
||||||
std::string metallic_texname; // map_Pm
|
std::string metallic_texname; // map_Pm
|
||||||
std::string sheen_texname; // map_Ps
|
std::string sheen_texname; // map_Ps
|
||||||
std::string emissive_texname; // map_Ke
|
std::string emissive_texname; // map_Ke
|
||||||
std::string normal_texname; // norm. For normal mapping.
|
std::string normal_texname; // norm. For normal mapping.
|
||||||
|
|
||||||
texture_option_t roughness_texopt;
|
texture_option_t roughness_texopt;
|
||||||
texture_option_t metallic_texopt;
|
texture_option_t metallic_texopt;
|
||||||
@ -210,11 +211,11 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
std::vector<index_t> indices;
|
std::vector<index_t> indices;
|
||||||
std::vector<unsigned char> num_face_vertices; // The number of vertices per
|
std::vector<unsigned char> num_face_vertices; // The number of vertices per
|
||||||
// face. 3 = polygon, 4 = quad,
|
// face. 3 = polygon, 4 = quad,
|
||||||
// ... Up to 255.
|
// ... Up to 255.
|
||||||
std::vector<int> material_ids; // per-face material ID
|
std::vector<int> material_ids; // per-face material ID
|
||||||
std::vector<tag_t> tags; // SubD tag
|
std::vector<tag_t> tags; // SubD tag
|
||||||
} mesh_t;
|
} mesh_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -224,9 +225,9 @@ typedef struct {
|
|||||||
|
|
||||||
// Vertex attributes
|
// Vertex attributes
|
||||||
typedef struct {
|
typedef struct {
|
||||||
std::vector<real_t> vertices; // 'v'
|
std::vector<real_t> vertices; // 'v'
|
||||||
std::vector<real_t> normals; // 'vn'
|
std::vector<real_t> normals; // 'vn'
|
||||||
std::vector<real_t> texcoords; // 'vt'
|
std::vector<real_t> texcoords; // 'vt'
|
||||||
} attrib_t;
|
} attrib_t;
|
||||||
|
|
||||||
typedef struct callback_t_ {
|
typedef struct callback_t_ {
|
||||||
@ -254,18 +255,12 @@ typedef struct callback_t_ {
|
|||||||
void (*object_cb)(void *user_data, const char *name);
|
void (*object_cb)(void *user_data, const char *name);
|
||||||
|
|
||||||
callback_t_()
|
callback_t_()
|
||||||
: vertex_cb(NULL),
|
: vertex_cb(NULL), normal_cb(NULL), texcoord_cb(NULL), index_cb(NULL),
|
||||||
normal_cb(NULL),
|
usemtl_cb(NULL), mtllib_cb(NULL), group_cb(NULL), object_cb(NULL) {}
|
||||||
texcoord_cb(NULL),
|
|
||||||
index_cb(NULL),
|
|
||||||
usemtl_cb(NULL),
|
|
||||||
mtllib_cb(NULL),
|
|
||||||
group_cb(NULL),
|
|
||||||
object_cb(NULL) {}
|
|
||||||
} callback_t;
|
} callback_t;
|
||||||
|
|
||||||
class MaterialReader {
|
class MaterialReader {
|
||||||
public:
|
public:
|
||||||
MaterialReader() {}
|
MaterialReader() {}
|
||||||
virtual ~MaterialReader();
|
virtual ~MaterialReader();
|
||||||
|
|
||||||
@ -276,7 +271,7 @@ class MaterialReader {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class MaterialFileReader : public MaterialReader {
|
class MaterialFileReader : public MaterialReader {
|
||||||
public:
|
public:
|
||||||
explicit MaterialFileReader(const std::string &mtl_basedir)
|
explicit MaterialFileReader(const std::string &mtl_basedir)
|
||||||
: m_mtlBaseDir(mtl_basedir) {}
|
: m_mtlBaseDir(mtl_basedir) {}
|
||||||
virtual ~MaterialFileReader() {}
|
virtual ~MaterialFileReader() {}
|
||||||
@ -284,12 +279,12 @@ class MaterialFileReader : public MaterialReader {
|
|||||||
std::vector<material_t> *materials,
|
std::vector<material_t> *materials,
|
||||||
std::map<std::string, int> *matMap, std::string *err);
|
std::map<std::string, int> *matMap, std::string *err);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_mtlBaseDir;
|
std::string m_mtlBaseDir;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MaterialStreamReader : public MaterialReader {
|
class MaterialStreamReader : public MaterialReader {
|
||||||
public:
|
public:
|
||||||
explicit MaterialStreamReader(std::istream &inStream)
|
explicit MaterialStreamReader(std::istream &inStream)
|
||||||
: m_inStream(inStream) {}
|
: m_inStream(inStream) {}
|
||||||
virtual ~MaterialStreamReader() {}
|
virtual ~MaterialStreamReader() {}
|
||||||
@ -297,7 +292,7 @@ class MaterialStreamReader : public MaterialReader {
|
|||||||
std::vector<material_t> *materials,
|
std::vector<material_t> *materials,
|
||||||
std::map<std::string, int> *matMap, std::string *err);
|
std::map<std::string, int> *matMap, std::string *err);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::istream &m_inStream;
|
std::istream &m_inStream;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -341,9 +336,9 @@ void LoadMtl(std::map<std::string, int> *material_map,
|
|||||||
std::vector<material_t> *materials, std::istream *inStream,
|
std::vector<material_t> *materials, std::istream *inStream,
|
||||||
std::string *warning);
|
std::string *warning);
|
||||||
|
|
||||||
} // namespace tinyobj
|
} // namespace tinyobj
|
||||||
|
|
||||||
#endif // TINY_OBJ_LOADER_H_
|
#endif // TINY_OBJ_LOADER_H_
|
||||||
|
|
||||||
#ifdef TINYOBJLOADER_IMPLEMENTATION
|
#ifdef TINYOBJLOADER_IMPLEMENTATION
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@ -361,7 +356,7 @@ namespace tinyobj {
|
|||||||
|
|
||||||
MaterialReader::~MaterialReader() {}
|
MaterialReader::~MaterialReader() {}
|
||||||
|
|
||||||
#define TINYOBJ_SSCANF_BUFFER_SIZE (4096)
|
#define TINYOBJ_SSCANF_BUFFER_SIZE (512)
|
||||||
|
|
||||||
struct vertex_index {
|
struct vertex_index {
|
||||||
int v_idx, vt_idx, vn_idx;
|
int v_idx, vt_idx, vn_idx;
|
||||||
@ -401,31 +396,35 @@ static std::istream &safeGetline(std::istream &is, std::string &t) {
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
int c = sb->sbumpc();
|
int c = sb->sbumpc();
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '\n':
|
case '\n':
|
||||||
return is;
|
return is;
|
||||||
case '\r':
|
case '\r':
|
||||||
if (sb->sgetc() == '\n') sb->sbumpc();
|
if (sb->sgetc() == '\n')
|
||||||
return is;
|
sb->sbumpc();
|
||||||
case EOF:
|
return is;
|
||||||
// Also handle the case when the last line has no line ending
|
case EOF:
|
||||||
if (t.empty()) is.setstate(std::ios::eofbit);
|
// Also handle the case when the last line has no line ending
|
||||||
return is;
|
if (t.empty())
|
||||||
default:
|
is.setstate(std::ios::eofbit);
|
||||||
t += static_cast<char>(c);
|
return is;
|
||||||
|
default:
|
||||||
|
t += static_cast<char>(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t'))
|
#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t'))
|
||||||
#define IS_DIGIT(x) \
|
#define IS_DIGIT(x) \
|
||||||
(static_cast<unsigned int>((x) - '0') < static_cast<unsigned int>(10))
|
(static_cast<unsigned int>((x) - '0') < static_cast<unsigned int>(10))
|
||||||
#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0'))
|
#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0'))
|
||||||
|
|
||||||
// Make index zero-base, and also support relative index.
|
// Make index zero-base, and also support relative index.
|
||||||
static inline int fixIndex(int idx, int n) {
|
static inline int fixIndex(int idx, int n) {
|
||||||
if (idx > 0) return idx - 1;
|
if (idx > 0)
|
||||||
if (idx == 0) return 0;
|
return idx - 1;
|
||||||
return n + idx; // negative value = relative
|
if (idx == 0)
|
||||||
|
return 0;
|
||||||
|
return n + idx; // negative value = relative
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline std::string parseString(const char **token) {
|
static inline std::string parseString(const char **token) {
|
||||||
@ -521,9 +520,11 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We must make sure we actually got something.
|
// We must make sure we actually got something.
|
||||||
if (read == 0) goto fail;
|
if (read == 0)
|
||||||
|
goto fail;
|
||||||
// We allow numbers of form "#", "###" etc.
|
// We allow numbers of form "#", "###" etc.
|
||||||
if (!end_not_reached) goto assemble;
|
if (!end_not_reached)
|
||||||
|
goto assemble;
|
||||||
|
|
||||||
// Read the decimal part.
|
// Read the decimal part.
|
||||||
if (*curr == '.') {
|
if (*curr == '.') {
|
||||||
@ -548,7 +549,8 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) {
|
|||||||
goto assemble;
|
goto assemble;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!end_not_reached) goto assemble;
|
if (!end_not_reached)
|
||||||
|
goto assemble;
|
||||||
|
|
||||||
// Read the exponent part.
|
// Read the exponent part.
|
||||||
if (*curr == 'e' || *curr == 'E') {
|
if (*curr == 'e' || *curr == 'E') {
|
||||||
@ -574,13 +576,14 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) {
|
|||||||
end_not_reached = (curr != s_end);
|
end_not_reached = (curr != s_end);
|
||||||
}
|
}
|
||||||
exponent *= (exp_sign == '+' ? 1 : -1);
|
exponent *= (exp_sign == '+' ? 1 : -1);
|
||||||
if (read == 0) goto fail;
|
if (read == 0)
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
assemble:
|
assemble:
|
||||||
*result =
|
*result = (sign == '+' ? 1 : -1) *
|
||||||
(sign == '+' ? 1 : -1) *
|
(exponent ? std::ldexp(mantissa * std::pow(5.0, exponent), exponent)
|
||||||
(exponent ? std::ldexp(mantissa * std::pow(5.0, exponent), exponent) : mantissa);
|
: mantissa);
|
||||||
return true;
|
return true;
|
||||||
fail:
|
fail:
|
||||||
return false;
|
return false;
|
||||||
@ -597,16 +600,16 @@ static inline real_t parseReal(const char **token, double default_value = 0.0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void parseReal2(real_t *x, real_t *y, const char **token,
|
static inline void parseReal2(real_t *x, real_t *y, const char **token,
|
||||||
const double default_x = 0.0,
|
const double default_x = 0.0,
|
||||||
const double default_y = 0.0) {
|
const double default_y = 0.0) {
|
||||||
(*x) = parseReal(token, default_x);
|
(*x) = parseReal(token, default_x);
|
||||||
(*y) = parseReal(token, default_y);
|
(*y) = parseReal(token, default_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void parseReal3(real_t *x, real_t *y, real_t *z, const char **token,
|
static inline void parseReal3(real_t *x, real_t *y, real_t *z,
|
||||||
const double default_x = 0.0,
|
const char **token, const double default_x = 0.0,
|
||||||
const double default_y = 0.0,
|
const double default_y = 0.0,
|
||||||
const double default_z = 0.0) {
|
const double default_z = 0.0) {
|
||||||
(*x) = parseReal(token, default_x);
|
(*x) = parseReal(token, default_x);
|
||||||
(*y) = parseReal(token, default_y);
|
(*y) = parseReal(token, default_y);
|
||||||
(*z) = parseReal(token, default_z);
|
(*z) = parseReal(token, default_z);
|
||||||
@ -638,8 +641,9 @@ static inline bool parseOnOff(const char **token, bool default_value = true) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline texture_type_t parseTextureType(
|
static inline texture_type_t
|
||||||
const char **token, texture_type_t default_value = TEXTURE_TYPE_NONE) {
|
parseTextureType(const char **token,
|
||||||
|
texture_type_t default_value = TEXTURE_TYPE_NONE) {
|
||||||
(*token) += strspn((*token), " \t");
|
(*token) += strspn((*token), " \t");
|
||||||
const char *end = (*token) + strcspn((*token), " \t\r");
|
const char *end = (*token) + strcspn((*token), " \t\r");
|
||||||
texture_type_t ty = default_value;
|
texture_type_t ty = default_value;
|
||||||
@ -715,7 +719,7 @@ static vertex_index parseTriple(const char **token, int vsize, int vnsize,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// i/j/k
|
// i/j/k
|
||||||
(*token)++; // skip '/'
|
(*token)++; // skip '/'
|
||||||
vi.vn_idx = fixIndex(atoi((*token)), vnsize);
|
vi.vn_idx = fixIndex(atoi((*token)), vnsize);
|
||||||
(*token) += strcspn((*token), "/ \t\r");
|
(*token) += strcspn((*token), "/ \t\r");
|
||||||
return vi;
|
return vi;
|
||||||
@ -723,7 +727,7 @@ static vertex_index parseTriple(const char **token, int vsize, int vnsize,
|
|||||||
|
|
||||||
// Parse raw triples: i, i/j/k, i//k, i/j
|
// Parse raw triples: i, i/j/k, i//k, i/j
|
||||||
static vertex_index parseRawTriple(const char **token) {
|
static vertex_index parseRawTriple(const char **token) {
|
||||||
vertex_index vi(static_cast<int>(0)); // 0 is an invalid index in OBJ
|
vertex_index vi(static_cast<int>(0)); // 0 is an invalid index in OBJ
|
||||||
|
|
||||||
vi.v_idx = atoi((*token));
|
vi.v_idx = atoi((*token));
|
||||||
(*token) += strcspn((*token), "/ \t\r");
|
(*token) += strcspn((*token), "/ \t\r");
|
||||||
@ -748,7 +752,7 @@ static vertex_index parseRawTriple(const char **token) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// i/j/k
|
// i/j/k
|
||||||
(*token)++; // skip '/'
|
(*token)++; // skip '/'
|
||||||
vi.vn_idx = atoi((*token));
|
vi.vn_idx = atoi((*token));
|
||||||
(*token) += strcspn((*token), "/ \t\r");
|
(*token) += strcspn((*token), "/ \t\r");
|
||||||
return vi;
|
return vi;
|
||||||
@ -785,7 +789,7 @@ static bool ParseTextureNameAndOption(std::string *texname,
|
|||||||
texopt->turbulence[2] = 0.0f;
|
texopt->turbulence[2] = 0.0f;
|
||||||
texopt->type = TEXTURE_TYPE_NONE;
|
texopt->type = TEXTURE_TYPE_NONE;
|
||||||
|
|
||||||
const char *token = linebuf; // Assume line ends with NULL
|
const char *token = linebuf; // Assume line ends with NULL
|
||||||
|
|
||||||
while (!IS_NEW_LINE((*token))) {
|
while (!IS_NEW_LINE((*token))) {
|
||||||
if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) {
|
if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) {
|
||||||
@ -806,15 +810,15 @@ static bool ParseTextureNameAndOption(std::string *texname,
|
|||||||
} else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) {
|
} else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) {
|
||||||
token += 3;
|
token += 3;
|
||||||
parseReal3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]),
|
parseReal3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]),
|
||||||
&(texopt->origin_offset[2]), &token);
|
&(texopt->origin_offset[2]), &token);
|
||||||
} else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) {
|
} else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) {
|
||||||
token += 3;
|
token += 3;
|
||||||
parseReal3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]),
|
parseReal3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]),
|
||||||
&token, 1.0, 1.0, 1.0);
|
&token, 1.0, 1.0, 1.0);
|
||||||
} else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) {
|
} else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) {
|
||||||
token += 3;
|
token += 3;
|
||||||
parseReal3(&(texopt->turbulence[0]), &(texopt->turbulence[1]),
|
parseReal3(&(texopt->turbulence[0]), &(texopt->turbulence[1]),
|
||||||
&(texopt->turbulence[2]), &token);
|
&(texopt->turbulence[2]), &token);
|
||||||
} else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) {
|
} else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) {
|
||||||
token += 5;
|
token += 5;
|
||||||
texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE);
|
texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE);
|
||||||
@ -822,7 +826,7 @@ static bool ParseTextureNameAndOption(std::string *texname,
|
|||||||
token += 9;
|
token += 9;
|
||||||
token += strspn(token, " \t");
|
token += strspn(token, " \t");
|
||||||
const char *end = token + strcspn(token, " \t\r");
|
const char *end = token + strcspn(token, " \t\r");
|
||||||
if ((end - token) == 1) { // Assume one char for -imfchan
|
if ((end - token) == 1) { // Assume one char for -imfchan
|
||||||
texopt->imfchan = (*token);
|
texopt->imfchan = (*token);
|
||||||
}
|
}
|
||||||
token = end;
|
token = end;
|
||||||
@ -831,12 +835,12 @@ static bool ParseTextureNameAndOption(std::string *texname,
|
|||||||
parseReal2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0);
|
parseReal2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0);
|
||||||
} else {
|
} else {
|
||||||
// Assume texture filename
|
// Assume texture filename
|
||||||
token += strspn(token, " \t"); // skip space
|
token += strspn(token, " \t"); // skip space
|
||||||
size_t len = strcspn(token, " \t\r"); // untile next space
|
size_t len = strcspn(token, " \t\r"); // untile next space
|
||||||
texture_name = std::string(token, token + len);
|
texture_name = std::string(token, token + len);
|
||||||
token += len;
|
token += len;
|
||||||
|
|
||||||
token += strspn(token, " \t"); // skip space
|
token += strspn(token, " \t"); // skip space
|
||||||
|
|
||||||
found_texname = true;
|
found_texname = true;
|
||||||
}
|
}
|
||||||
@ -887,10 +891,11 @@ static void InitMaterial(material_t *material) {
|
|||||||
material->unknown_parameter.clear();
|
material->unknown_parameter.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool exportFaceGroupToShape(
|
static bool
|
||||||
shape_t *shape, const std::vector<std::vector<vertex_index> > &faceGroup,
|
exportFaceGroupToShape(shape_t *shape,
|
||||||
const std::vector<tag_t> &tags, const int material_id,
|
const std::vector<std::vector<vertex_index>> &faceGroup,
|
||||||
const std::string &name, bool triangulate) {
|
const std::vector<tag_t> &tags, const int material_id,
|
||||||
|
const std::string &name, bool triangulate) {
|
||||||
if (faceGroup.empty()) {
|
if (faceGroup.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -940,7 +945,7 @@ static bool exportFaceGroupToShape(
|
|||||||
|
|
||||||
shape->mesh.num_face_vertices.push_back(
|
shape->mesh.num_face_vertices.push_back(
|
||||||
static_cast<unsigned char>(npolys));
|
static_cast<unsigned char>(npolys));
|
||||||
shape->mesh.material_ids.push_back(material_id); // per face
|
shape->mesh.material_ids.push_back(material_id); // per face
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1004,9 +1009,11 @@ void LoadMtl(std::map<std::string, int> *material_map,
|
|||||||
token += strspn(token, " \t");
|
token += strspn(token, " \t");
|
||||||
|
|
||||||
assert(token);
|
assert(token);
|
||||||
if (token[0] == '\0') continue; // empty line
|
if (token[0] == '\0')
|
||||||
|
continue; // empty line
|
||||||
|
|
||||||
if (token[0] == '#') continue; // comment line
|
if (token[0] == '#')
|
||||||
|
continue; // comment line
|
||||||
|
|
||||||
// new mtl
|
// new mtl
|
||||||
if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) {
|
if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) {
|
||||||
@ -1305,7 +1312,7 @@ void LoadMtl(std::map<std::string, int> *material_map,
|
|||||||
token += 5;
|
token += 5;
|
||||||
ParseTextureNameAndOption(
|
ParseTextureNameAndOption(
|
||||||
&(material.normal_texname), &(material.normal_texopt), token,
|
&(material.normal_texname), &(material.normal_texopt), token,
|
||||||
/* is_bump */ false); // @fixme { is_bump will be true? }
|
/* is_bump */ false); // @fixme { is_bump will be true? }
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1431,7 +1438,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
std::vector<real_t> vn;
|
std::vector<real_t> vn;
|
||||||
std::vector<real_t> vt;
|
std::vector<real_t> vt;
|
||||||
std::vector<tag_t> tags;
|
std::vector<tag_t> tags;
|
||||||
std::vector<std::vector<vertex_index> > faceGroup;
|
std::vector<std::vector<vertex_index>> faceGroup;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
// material
|
// material
|
||||||
@ -1464,9 +1471,11 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
token += strspn(token, " \t");
|
token += strspn(token, " \t");
|
||||||
|
|
||||||
assert(token);
|
assert(token);
|
||||||
if (token[0] == '\0') continue; // empty line
|
if (token[0] == '\0')
|
||||||
|
continue; // empty line
|
||||||
|
|
||||||
if (token[0] == '#') continue; // comment line
|
if (token[0] == '#')
|
||||||
|
continue; // comment line
|
||||||
|
|
||||||
// vertex
|
// vertex
|
||||||
if (token[0] == 'v' && IS_SPACE((token[1]))) {
|
if (token[0] == 'v' && IS_SPACE((token[1]))) {
|
||||||
@ -1564,9 +1573,8 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
|
|
||||||
if (filenames.empty()) {
|
if (filenames.empty()) {
|
||||||
if (err) {
|
if (err) {
|
||||||
(*err) +=
|
(*err) += "WARN: Looks like empty filename for mtllib. Use default "
|
||||||
"WARN: Looks like empty filename for mtllib. Use default "
|
"material. \n";
|
||||||
"material. \n";
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
@ -1575,7 +1583,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
bool ok = (*readMatFn)(filenames[s].c_str(), materials,
|
bool ok = (*readMatFn)(filenames[s].c_str(), materials,
|
||||||
&material_map, &err_mtl);
|
&material_map, &err_mtl);
|
||||||
if (err && (!err_mtl.empty())) {
|
if (err && (!err_mtl.empty())) {
|
||||||
(*err) += err_mtl; // This should be warn message.
|
(*err) += err_mtl; // This should be warn message.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
@ -1586,9 +1594,8 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
if (err) {
|
if (err) {
|
||||||
(*err) +=
|
(*err) += "WARN: Failed to load material file(s). Use default "
|
||||||
"WARN: Failed to load material file(s). Use default "
|
"material.\n";
|
||||||
"material.\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1617,7 +1624,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
while (!IS_NEW_LINE(token[0])) {
|
while (!IS_NEW_LINE(token[0])) {
|
||||||
std::string str = parseString(&token);
|
std::string str = parseString(&token);
|
||||||
names.push_back(str);
|
names.push_back(str);
|
||||||
token += strspn(token, " \t\r"); // skip tag
|
token += strspn(token, " \t\r"); // skip tag
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(names.size() > 0);
|
assert(names.size() > 0);
|
||||||
@ -1716,7 +1723,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
if (ret || shape.mesh.indices.size()) {
|
if (ret || shape.mesh.indices.size()) {
|
||||||
shapes->push_back(shape);
|
shapes->push_back(shape);
|
||||||
}
|
}
|
||||||
faceGroup.clear(); // for safety
|
faceGroup.clear(); // for safety
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
(*err) += errss.str();
|
(*err) += errss.str();
|
||||||
@ -1737,7 +1744,7 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
|||||||
|
|
||||||
// material
|
// material
|
||||||
std::map<std::string, int> material_map;
|
std::map<std::string, int> material_map;
|
||||||
int material_id = -1; // -1 = invalid
|
int material_id = -1; // -1 = invalid
|
||||||
|
|
||||||
std::vector<index_t> indices;
|
std::vector<index_t> indices;
|
||||||
std::vector<material_t> materials;
|
std::vector<material_t> materials;
|
||||||
@ -1770,14 +1777,16 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
|||||||
token += strspn(token, " \t");
|
token += strspn(token, " \t");
|
||||||
|
|
||||||
assert(token);
|
assert(token);
|
||||||
if (token[0] == '\0') continue; // empty line
|
if (token[0] == '\0')
|
||||||
|
continue; // empty line
|
||||||
|
|
||||||
if (token[0] == '#') continue; // comment line
|
if (token[0] == '#')
|
||||||
|
continue; // comment line
|
||||||
|
|
||||||
// vertex
|
// vertex
|
||||||
if (token[0] == 'v' && IS_SPACE((token[1]))) {
|
if (token[0] == 'v' && IS_SPACE((token[1]))) {
|
||||||
token += 2;
|
token += 2;
|
||||||
real_t x, y, z, w; // w is optional. default = 1.0
|
real_t x, y, z, w; // w is optional. default = 1.0
|
||||||
parseV(&x, &y, &z, &w, &token);
|
parseV(&x, &y, &z, &w, &token);
|
||||||
if (callback.vertex_cb) {
|
if (callback.vertex_cb) {
|
||||||
callback.vertex_cb(user_data, x, y, z, w);
|
callback.vertex_cb(user_data, x, y, z, w);
|
||||||
@ -1799,7 +1808,7 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
|||||||
// texcoord
|
// texcoord
|
||||||
if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) {
|
if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) {
|
||||||
token += 3;
|
token += 3;
|
||||||
real_t x, y, z; // y and z are optional. default = 0.0
|
real_t x, y, z; // y and z are optional. default = 0.0
|
||||||
parseReal3(&x, &y, &z, &token);
|
parseReal3(&x, &y, &z, &token);
|
||||||
if (callback.texcoord_cb) {
|
if (callback.texcoord_cb) {
|
||||||
callback.texcoord_cb(user_data, x, y, z);
|
callback.texcoord_cb(user_data, x, y, z);
|
||||||
@ -1873,9 +1882,8 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
|||||||
|
|
||||||
if (filenames.empty()) {
|
if (filenames.empty()) {
|
||||||
if (err) {
|
if (err) {
|
||||||
(*err) +=
|
(*err) += "WARN: Looks like empty filename for mtllib. Use default "
|
||||||
"WARN: Looks like empty filename for mtllib. Use default "
|
"material. \n";
|
||||||
"material. \n";
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
@ -1884,7 +1892,7 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
|||||||
bool ok = (*readMatFn)(filenames[s].c_str(), &materials,
|
bool ok = (*readMatFn)(filenames[s].c_str(), &materials,
|
||||||
&material_map, &err_mtl);
|
&material_map, &err_mtl);
|
||||||
if (err && (!err_mtl.empty())) {
|
if (err && (!err_mtl.empty())) {
|
||||||
(*err) += err_mtl; // This should be warn message.
|
(*err) += err_mtl; // This should be warn message.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
@ -1895,9 +1903,8 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
|||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
if (err) {
|
if (err) {
|
||||||
(*err) +=
|
(*err) += "WARN: Failed to load material file(s). Use default "
|
||||||
"WARN: Failed to load material file(s). Use default "
|
"material.\n";
|
||||||
"material.\n";
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (callback.mtllib_cb) {
|
if (callback.mtllib_cb) {
|
||||||
@ -1918,7 +1925,7 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
|||||||
while (!IS_NEW_LINE(token[0])) {
|
while (!IS_NEW_LINE(token[0])) {
|
||||||
std::string str = parseString(&token);
|
std::string str = parseString(&token);
|
||||||
names.push_back(str);
|
names.push_back(str);
|
||||||
token += strspn(token, " \t\r"); // skip tag
|
token += strspn(token, " \t\r"); // skip tag
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(names.size() > 0);
|
assert(names.size() > 0);
|
||||||
@ -1967,7 +1974,7 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // @todo
|
#if 0 // @todo
|
||||||
if (token[0] == 't' && IS_SPACE(token[1])) {
|
if (token[0] == 't' && IS_SPACE(token[1])) {
|
||||||
tag_t tag;
|
tag_t tag;
|
||||||
|
|
||||||
@ -2024,6 +2031,6 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} // namespace tinyobj
|
} // namespace tinyobj
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -19,9 +19,11 @@
|
|||||||
#include <bits/unique_ptr.h>
|
#include <bits/unique_ptr.h>
|
||||||
#include <bits/shared_ptr.h>
|
#include <bits/shared_ptr.h>
|
||||||
#include <calico/types.h>
|
#include <calico/types.h>
|
||||||
|
#include <tiny_obj_loader.h>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
// MEMORY
|
// MEMORY
|
||||||
@ -71,6 +73,17 @@ template <typename T> using TVector = std::vector<T>;
|
|||||||
* @tparam S The size of the array.
|
* @tparam S The size of the array.
|
||||||
*/
|
*/
|
||||||
template <typename T, size_t S> using TArray = std::array<T, S>;
|
template <typename T, size_t S> using TArray = std::array<T, S>;
|
||||||
|
/**
|
||||||
|
* @brief Alias template for creating a std::tuple with a variadic list of
|
||||||
|
* types.
|
||||||
|
*
|
||||||
|
* This alias simplifies the usage of std::tuple by allowing the user to write
|
||||||
|
* TTuple<T...> instead of std::tuple<T...>.
|
||||||
|
*
|
||||||
|
* @tparam T... Variadic template parameter pack representing the types to be
|
||||||
|
* included in the tuple.
|
||||||
|
*/
|
||||||
|
template <typename... T> using TTuple = std::tuple<T...>;
|
||||||
|
|
||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
// BASIC TYPES
|
// BASIC TYPES
|
||||||
@ -141,4 +154,10 @@ using FVector3 = glm::vec3;
|
|||||||
*/
|
*/
|
||||||
using FVector3Int = glm::ivec3;
|
using FVector3Int = glm::ivec3;
|
||||||
|
|
||||||
|
/////////////////////////////////////
|
||||||
|
// SHAPES
|
||||||
|
/////////////////////////////////////
|
||||||
|
|
||||||
|
using FMaterial = tinyobj::material_t;
|
||||||
|
|
||||||
#endif // XRBDS_CORE_TYPES_H
|
#endif // XRBDS_CORE_TYPES_H
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* This header defines the Input class, which provides static methods to query
|
* This header defines the Input class, which provides static methods to query
|
||||||
* the state of keys (held, pressed, or released) on the system. It also defines
|
* the state of keys (held, pressed, or released) on the system. It also defines
|
||||||
* the EKey enumeration for representing individual keys.
|
* the EButton enumeration for representing individual keys.
|
||||||
*
|
*
|
||||||
* The Input class is designed as a utility class and cannot be instantiated.
|
* The Input class is designed as a utility class and cannot be instantiated.
|
||||||
* It maintains internal states for keys and provides methods to update and
|
* It maintains internal states for keys and provides methods to update and
|
||||||
@ -14,8 +14,8 @@
|
|||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* - Call Input::Update() periodically to refresh the key states.
|
* - Call Input::Update() periodically to refresh the key states.
|
||||||
* - Use Input::IsKeyHeld(), Input::IsKeyDown(), or Input::IsKeyUp() to query
|
* - Use Input::IsButtonHeld(), Input::IsButtonDown(), or Input::IsButtonUp() to
|
||||||
* the state of specific keys.
|
* query the state of specific keys.
|
||||||
*
|
*
|
||||||
* @author Daniel Ramirez Morilla
|
* @author Daniel Ramirez Morilla
|
||||||
* @date 2025-04-19
|
* @date 2025-04-19
|
||||||
@ -33,7 +33,7 @@
|
|||||||
#include <nds/input.h>
|
#include <nds/input.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @enum EKey
|
* @enum EButton
|
||||||
* @brief Represents the keys available on the NDS platform.
|
* @brief Represents the keys available on the NDS platform.
|
||||||
*
|
*
|
||||||
* This enumeration defines constants for each key on the NDS system, mapping
|
* This enumeration defines constants for each key on the NDS system, mapping
|
||||||
@ -44,7 +44,7 @@
|
|||||||
*
|
*
|
||||||
* Example usage:
|
* Example usage:
|
||||||
* @code
|
* @code
|
||||||
* if (Input::IsKeyDown(EKey::A)) {
|
* if (Input::IsButtonDown(EButton::A)) {
|
||||||
* // Handle A button press
|
* // Handle A button press
|
||||||
* }
|
* }
|
||||||
* @endcode
|
* @endcode
|
||||||
@ -52,7 +52,7 @@
|
|||||||
* @note These key codes are specific to the NDS platform and rely on the
|
* @note These key codes are specific to the NDS platform and rely on the
|
||||||
* platform's key definitions.
|
* platform's key definitions.
|
||||||
*/
|
*/
|
||||||
enum EKey : u16 {
|
enum EButton : u16 {
|
||||||
A = KEY_A,
|
A = KEY_A,
|
||||||
B = KEY_B,
|
B = KEY_B,
|
||||||
X = KEY_X,
|
X = KEY_X,
|
||||||
@ -70,9 +70,9 @@ enum EKey : u16 {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @class Input
|
* @class Input
|
||||||
* @brief Provides static methods to handle input states for keys.
|
* @brief Provides static methods to handle input states for buttons.
|
||||||
*
|
*
|
||||||
* The Input class is a utility class that allows querying the state of keys
|
* The Input class is a utility class that allows querying the state of buttons
|
||||||
* (held, pressed, or released) using static methods. It is not meant to be
|
* (held, pressed, or released) using static methods. It is not meant to be
|
||||||
* instantiated.
|
* instantiated.
|
||||||
*/
|
*/
|
||||||
@ -81,46 +81,47 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Updates the internal state of the input system.
|
* @brief Updates the internal state of the input system.
|
||||||
*
|
*
|
||||||
* This method should be called periodically to refresh the key states.
|
* This method should be called periodically to refresh the button states.
|
||||||
*/
|
*/
|
||||||
static void Update();
|
static void Update();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Checks if a specific key is currently being held down.
|
* @brief Checks if a specific button is currently being held down.
|
||||||
* @param key The key to check.
|
* @param button The button to check.
|
||||||
* @return True if the key is held down, false otherwise.
|
* @return True if the button is held down, false otherwise.
|
||||||
*/
|
*/
|
||||||
static bool IsKeyHeld(EKey key);
|
static bool IsButtonHeld(EButton button);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Checks if a specific key was pressed in the current update cycle.
|
* @brief Checks if a specific button was pressed in the current update cycle.
|
||||||
* @param key The key to check.
|
* @param button The button to check.
|
||||||
* @return True if the key was pressed, false otherwise.
|
* @return True if the button was pressed, false otherwise.
|
||||||
*/
|
*/
|
||||||
static bool IsKeyDown(EKey key);
|
static bool IsButtonDown(EButton button);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Checks if a specific key was released in the current update cycle.
|
* @brief Checks if a specific button was released in the current update
|
||||||
* @param key The key to check.
|
* cycle.
|
||||||
* @return True if the key was released, false otherwise.
|
* @param button The button to check.
|
||||||
|
* @return True if the button was released, false otherwise.
|
||||||
*/
|
*/
|
||||||
static bool IsKeyUp(EKey key);
|
static bool IsButtonUp(EButton button);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* @brief Stores the state of keys currently being held down.
|
* @brief Stores the state of buttons currently being held down.
|
||||||
*/
|
*/
|
||||||
static u32 KeysHeldState;
|
static u32 ButtonsHeldState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stores the state of keys pressed in the current update cycle.
|
* @brief Stores the state of buttons pressed in the current update cycle.
|
||||||
*/
|
*/
|
||||||
static u32 KeysDownState;
|
static u32 ButtonsDownState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stores the state of keys released in the current update cycle.
|
* @brief Stores the state of buttons released in the current update cycle.
|
||||||
*/
|
*/
|
||||||
static u32 KeysUpState;
|
static u32 ButtonsUpState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Deleted constructor to prevent instantiation of the Input class.
|
* @brief Deleted constructor to prevent instantiation of the Input class.
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "core/types.h"
|
#include "core/types.h"
|
||||||
|
#include "resources/texture.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -15,19 +16,30 @@ struct FVertex {
|
|||||||
: position(pos), normal(norm), texCoords(tex) {}
|
: position(pos), normal(norm), texCoords(tex) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FShape {
|
||||||
|
TVector<FVertex> vertices;
|
||||||
|
};
|
||||||
|
|
||||||
class Mesh : public Resource {
|
class Mesh : public Resource {
|
||||||
using Super = Resource;
|
using Super = Resource;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Mesh Load(const TVector<TVector<FVertex>> &vertices);
|
static Mesh Load(const TVector<FShape> &shapes,
|
||||||
|
const TVector<FMaterial> &materials,
|
||||||
|
const TVector<PtrShr<Texture>> &textures);
|
||||||
|
|
||||||
TVector<TVector<FVertex>> getVertices() const { return vertices; }
|
const TVector<FShape> &getShapes() const { return shapes; }
|
||||||
|
const TVector<FMaterial> &getMaterials() const { return materials; }
|
||||||
|
const TVector<PtrShr<Texture>> &getTextures() const { return textures; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TVector<TVector<FVertex>> vertices;
|
TVector<FShape> shapes;
|
||||||
|
TVector<FMaterial> materials;
|
||||||
|
TVector<PtrShr<Texture>> textures;
|
||||||
|
|
||||||
Mesh() = default;
|
Mesh() = default;
|
||||||
Mesh(const TVector<TVector<FVertex>> &vertices);
|
Mesh(const TVector<FShape> &shapes, const TVector<FMaterial> &materials,
|
||||||
|
const TVector<PtrShr<Texture>> &textures);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // XRBDS_RESOURCES_MESH_H
|
#endif // XRBDS_RESOURCES_MESH_H
|
46
include/xrbds/resources/texture.h
Normal file
46
include/xrbds/resources/texture.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#ifndef XRBDS_RESOURCES_TEXTURE_H
|
||||||
|
#define XRBDS_RESOURCES_TEXTURE_H
|
||||||
|
|
||||||
|
#include "resource.h"
|
||||||
|
#include "core/types.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Texture
|
||||||
|
* @brief Represents a texture resource that includes pixel data and a color
|
||||||
|
* palette.
|
||||||
|
*
|
||||||
|
* The Texture class is derived from the Resource class and provides
|
||||||
|
* functionality to load and manage texture data and its associated palette. It
|
||||||
|
* also provides access to the texture's unique identifier.
|
||||||
|
*/
|
||||||
|
class Texture : public Resource {
|
||||||
|
using Super = Resource;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~Texture();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Loads a texture from the given pixel data and palette.
|
||||||
|
*
|
||||||
|
* @param data A reference to a vector containing the texture's pixel data.
|
||||||
|
* @param palette A reference to a vector containing the texture's color
|
||||||
|
* palette.
|
||||||
|
* @return A Texture object initialized with the provided data and palette.
|
||||||
|
*/
|
||||||
|
static Texture Load(TVector<unsigned int> &data,
|
||||||
|
TVector<unsigned short> &palette);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves the unique identifier of the texture.
|
||||||
|
*
|
||||||
|
* @return The unique identifier of the texture as an unsigned 8-bit integer.
|
||||||
|
*/
|
||||||
|
const u8 getId() { return id; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Texture(TVector<unsigned int> &data, TVector<unsigned short> &palette);
|
||||||
|
|
||||||
|
int id;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // XRBDS_RESOURCES_TEXTURE_H
|
@ -4,8 +4,14 @@
|
|||||||
#include "core/types.h"
|
#include "core/types.h"
|
||||||
#include "resources/mesh.h"
|
#include "resources/mesh.h"
|
||||||
|
|
||||||
|
struct FObjData {
|
||||||
|
TVector<TVector<FVertex>> vertices;
|
||||||
|
};
|
||||||
|
|
||||||
namespace Utils::File {
|
namespace Utils::File {
|
||||||
|
|
||||||
|
FString AssetPath(const FString &path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reads the contents of a text file and returns it as a string.
|
* @brief Reads the contents of a text file and returns it as a string.
|
||||||
*
|
*
|
||||||
@ -20,13 +26,38 @@ FString ReadTextFile(const FString &path);
|
|||||||
* vector of vertices.
|
* vector of vertices.
|
||||||
*
|
*
|
||||||
* @param path The file path to the OBJ file as an FString.
|
* @param path The file path to the OBJ file as an FString.
|
||||||
* @return A TVector of TVector of FVertex, where each inner vector represents a
|
* @return A TVector of TVector of FVertex, where each inner vector represents
|
||||||
* group of vertices.
|
* a group of vertices.
|
||||||
*
|
*
|
||||||
* @note Ensure the file at the specified path exists and is in a valid OBJ
|
* @note Ensure the file at the specified path exists and is in a valid OBJ
|
||||||
* format.
|
* format.
|
||||||
*/
|
*/
|
||||||
TVector<TVector<FVertex>> ReadObjFile(const FString &path);
|
TTuple<TVector<FShape>, TVector<FMaterial>> ReadObjFile(const FString &path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a binary file and returns its contents as a TVector of type T.
|
||||||
|
*
|
||||||
|
* @tparam T The type of data to read from the binary file.
|
||||||
|
* @param path The file path to the binary file to be read.
|
||||||
|
* @return TVector<T> A vector containing the contents of the binary file.
|
||||||
|
*/
|
||||||
|
template <typename T> TVector<T> ReadBinaryFile(const FString &path) {
|
||||||
|
FILE *file = fopen(AssetPath(path).c_str(), "rb");
|
||||||
|
if (!file) {
|
||||||
|
// TODO: iprintf("Error abriendo: %s\n", path.c_str());
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
size_t size = ftell(file);
|
||||||
|
rewind(file);
|
||||||
|
|
||||||
|
TVector<T> buffer(size);
|
||||||
|
fread(buffer.data(), 1, size, file);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Utils::File
|
} // namespace Utils::File
|
||||||
|
|
||||||
|
98
samples/hello_world/assets/meshes/cube/cube-tex.obj
Normal file
98
samples/hello_world/assets/meshes/cube/cube-tex.obj
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
# cube-tex.obj
|
||||||
|
# Import into Blender with Y-forward, Z-up
|
||||||
|
#
|
||||||
|
# Vertices: Faces:
|
||||||
|
# f-------g +-------+
|
||||||
|
# /. /| /. 5 /| 3 back
|
||||||
|
# / . / | / . / |
|
||||||
|
# e-------h | 2 +-------+ 1|
|
||||||
|
# | b . .|. c z right | . . .|. +
|
||||||
|
# | . | / | /y | . 4 | /
|
||||||
|
# |. |/ |/ |. |/
|
||||||
|
# a-------d +---- x +-------+
|
||||||
|
# 6
|
||||||
|
# bottom
|
||||||
|
|
||||||
|
# Material defined in separate file.
|
||||||
|
mtllib cube.mtl
|
||||||
|
|
||||||
|
g cube
|
||||||
|
|
||||||
|
# Vertices
|
||||||
|
v 0.0 0.0 0.0 # 1 a
|
||||||
|
v 0.0 1.0 0.0 # 2 b
|
||||||
|
v 1.0 1.0 0.0 # 3 c
|
||||||
|
v 1.0 0.0 0.0 # 4 d
|
||||||
|
v 0.0 0.0 1.0 # 5 e
|
||||||
|
v 0.0 1.0 1.0 # 6 f
|
||||||
|
v 1.0 1.0 1.0 # 7 g
|
||||||
|
v 1.0 0.0 1.0 # 8 h
|
||||||
|
|
||||||
|
# Normal vectors
|
||||||
|
# One for each face. Shared by all vertices in that face.
|
||||||
|
vn 1.0 0.0 0.0 # 1 cghd
|
||||||
|
vn -1.0 0.0 0.0 # 2 aefb
|
||||||
|
vn 0.0 1.0 0.0 # 3 gcbf
|
||||||
|
vn 0.0 -1.0 0.0 # 4 dhea
|
||||||
|
vn 0.0 0.0 1.0 # 5 hgfe
|
||||||
|
vn 0.0 0.0 -1.0 # 6 cdab
|
||||||
|
|
||||||
|
# Texture
|
||||||
|
# (u,v) coordinate into texture map image, ranging from 0.0 - 1.0.
|
||||||
|
# +---f---g---+---+
|
||||||
|
# | | 5 | | |
|
||||||
|
# f---e---h---g---+
|
||||||
|
# | 2 | 4 | 1 | | v
|
||||||
|
# b---a---d---c---+ |
|
||||||
|
# | | 6 | | | |
|
||||||
|
# +---b---c---+---+ +---- u
|
||||||
|
# | | 3 | | |
|
||||||
|
# +---f---g---+---+
|
||||||
|
vt 0.25 1.00 # 1 f(5) = f for face 5
|
||||||
|
vt 0.50 1.00 # 2 g(5)
|
||||||
|
vt 0 0.75 # 3 f(2)
|
||||||
|
vt 0.25 0.75 # 4 e(2,4,5)
|
||||||
|
vt 0.50 0.75 # 5 h(1,4,5)
|
||||||
|
vt 0.75 0.75 # 6 g(1)
|
||||||
|
vt 0 0.50 # 7 b(2)
|
||||||
|
vt 0.25 0.50 # 8 a(2,4,6)
|
||||||
|
vt 0.50 0.50 # 9 d(1,4,6)
|
||||||
|
vt 0.75 0.50 # 10 c(1)
|
||||||
|
vt 0.25 0.25 # 11 b(3,6)
|
||||||
|
vt 0.50 0.25 # 12 c(3,6)
|
||||||
|
vt 0.25 0 # 13 f(3)
|
||||||
|
vt 0.50 0 # 14 g(3)
|
||||||
|
|
||||||
|
# Define material for the following faces
|
||||||
|
usemtl texture
|
||||||
|
|
||||||
|
# Faces v/vt/vn
|
||||||
|
# 3-------2
|
||||||
|
# | - |
|
||||||
|
# | # | Each face = 2 triangles (ccw)
|
||||||
|
# | - | = 1-2-3 + 1-3-4
|
||||||
|
# 4-------1
|
||||||
|
|
||||||
|
# Face 1: cghd = cgh + chd
|
||||||
|
f 3/10/1 7/6/1 8/5/1
|
||||||
|
f 3/10/1 8/5/1 4/9/1
|
||||||
|
|
||||||
|
# Face 2: aefb = aef + afb
|
||||||
|
f 1/8/2 5/4/2 6/3/2
|
||||||
|
f 1/8/2 6/3/2 2/7/2
|
||||||
|
|
||||||
|
# Face 3: gcbf = gcb + gbf
|
||||||
|
f 7/14/3 3/12/3 2/11/3
|
||||||
|
f 7/14/3 2/11/3 6/13/3
|
||||||
|
|
||||||
|
# Face 4: dhea = dhe + dea
|
||||||
|
f 4/9/4 8/5/4 5/4/4
|
||||||
|
f 4/9/4 5/4/4 1/8/4
|
||||||
|
|
||||||
|
# Face 5: hgfe = hgf + hfe
|
||||||
|
f 8/5/5 7/2/5 6/1/5
|
||||||
|
f 8/5/5 6/1/5 5/4/5
|
||||||
|
|
||||||
|
# Face 6: cdab = cda + cab
|
||||||
|
f 3/12/6 4/9/6 1/8/6
|
||||||
|
f 3/12/6 1/8/6 2/11/6
|
7
samples/hello_world/assets/meshes/cube/cube.mtl
Normal file
7
samples/hello_world/assets/meshes/cube/cube.mtl
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
newmtl texture
|
||||||
|
Ka 0.0 0.0 0.0
|
||||||
|
Kd 0.5 0.5 0.5
|
||||||
|
Ks 0.0 0.0 0.0
|
||||||
|
Ns 10.0
|
||||||
|
illum 2
|
||||||
|
map_Kd texture.png
|
1
samples/hello_world/assets/meshes/cube/texture.img.bin
Normal file
1
samples/hello_world/assets/meshes/cube/texture.img.bin
Normal file
File diff suppressed because one or more lines are too long
BIN
samples/hello_world/assets/meshes/cube/texture.png
Normal file
BIN
samples/hello_world/assets/meshes/cube/texture.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
6
samples/hello_world/assets/meshes/mococo/ATTRIBUTION.txt
Normal file
6
samples/hello_world/assets/meshes/mococo/ATTRIBUTION.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
Model: mococo.obj
|
||||||
|
Author: pyr0xene
|
||||||
|
License: CC BY-NC 4.0 (https://creativecommons.org/licenses/by-nc/4.0/)
|
||||||
|
Source: https://sketchfab.com/3d-models/mococo-2c53699f4fe647beb52a7926821f5d9c
|
||||||
|
|
||||||
|
This model is used under the terms of the Creative Commons Attribution-NonCommercial license.
|
@ -1,46 +0,0 @@
|
|||||||
# Blender v2.76 (sub 0) OBJ File: ''
|
|
||||||
# www.blender.org
|
|
||||||
mtllib cube.mtl
|
|
||||||
o Cube
|
|
||||||
v 1.000000 -1.000000 -1.000000
|
|
||||||
v 1.000000 -1.000000 1.000000
|
|
||||||
v -1.000000 -1.000000 1.000000
|
|
||||||
v -1.000000 -1.000000 -1.000000
|
|
||||||
v 1.000000 1.000000 -0.999999
|
|
||||||
v 0.999999 1.000000 1.000001
|
|
||||||
v -1.000000 1.000000 1.000000
|
|
||||||
v -1.000000 1.000000 -1.000000
|
|
||||||
vt 1.000000 0.333333
|
|
||||||
vt 1.000000 0.666667
|
|
||||||
vt 0.666667 0.666667
|
|
||||||
vt 0.666667 0.333333
|
|
||||||
vt 0.666667 0.000000
|
|
||||||
vt 0.000000 0.333333
|
|
||||||
vt 0.000000 0.000000
|
|
||||||
vt 0.333333 0.000000
|
|
||||||
vt 0.333333 1.000000
|
|
||||||
vt 0.000000 1.000000
|
|
||||||
vt 0.000000 0.666667
|
|
||||||
vt 0.333333 0.333333
|
|
||||||
vt 0.333333 0.666667
|
|
||||||
vt 1.000000 0.000000
|
|
||||||
vn 0.000000 -1.000000 0.000000
|
|
||||||
vn 0.000000 1.000000 0.000000
|
|
||||||
vn 1.000000 0.000000 0.000000
|
|
||||||
vn -0.000000 0.000000 1.000000
|
|
||||||
vn -1.000000 -0.000000 -0.000000
|
|
||||||
vn 0.000000 0.000000 -1.000000
|
|
||||||
usemtl Material
|
|
||||||
s off
|
|
||||||
f 2/1/1 3/2/1 4/3/1
|
|
||||||
f 8/1/2 7/4/2 6/5/2
|
|
||||||
f 5/6/3 6/7/3 2/8/3
|
|
||||||
f 6/8/4 7/5/4 3/4/4
|
|
||||||
f 3/9/5 7/10/5 8/11/5
|
|
||||||
f 1/12/6 4/13/6 8/11/6
|
|
||||||
f 1/4/1 2/1/1 4/3/1
|
|
||||||
f 5/14/2 8/1/2 6/5/2
|
|
||||||
f 1/12/3 5/6/3 2/8/3
|
|
||||||
f 2/12/4 6/8/4 3/4/4
|
|
||||||
f 4/13/5 3/9/5 8/11/5
|
|
||||||
f 5/6/6 1/12/6 8/11/6
|
|
File diff suppressed because one or more lines are too long
BIN
samples/hello_world/assets/meshes/mococo/mococotexture_face1.png
Normal file
BIN
samples/hello_world/assets/meshes/mococo/mococotexture_face1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
Binary file not shown.
Before Width: | Height: | Size: 34 KiB |
7
samples/hello_world/assets/meshes/quad/quad.mtl
Normal file
7
samples/hello_world/assets/meshes/quad/quad.mtl
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
newmtl texture
|
||||||
|
Ka 0.0 0.0 0.0
|
||||||
|
Kd 0.5 0.5 0.5
|
||||||
|
Ks 0.0 0.0 0.0
|
||||||
|
Ns 10.0
|
||||||
|
illum 2
|
||||||
|
map_Kd texture.png
|
15
samples/hello_world/assets/meshes/quad/quad.obj
Normal file
15
samples/hello_world/assets/meshes/quad/quad.obj
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Blender v2.57 (sub 0) OBJ File: ''
|
||||||
|
# www.blender.org
|
||||||
|
mtllib quad.mtl
|
||||||
|
o Cube_Cube.001
|
||||||
|
v -1.000000 1.000000 0.000000
|
||||||
|
v 1.000000 1.000000 0.000000
|
||||||
|
v -1.000000 -1.000000 0.000000
|
||||||
|
v 1.000000 -1.000000 0.000000
|
||||||
|
vt 1.000000 1.000000
|
||||||
|
vt 0.000000 1.000000
|
||||||
|
vt 0.000000 0.000000
|
||||||
|
vt 1.000000 0.000000
|
||||||
|
s off
|
||||||
|
f 4/4 3/3 1/2
|
||||||
|
f 2/1 4/4 1/2
|
BIN
samples/hello_world/assets/meshes/quad/texture.img.bin
Normal file
BIN
samples/hello_world/assets/meshes/quad/texture.img.bin
Normal file
Binary file not shown.
BIN
samples/hello_world/assets/meshes/quad/texture.png
Normal file
BIN
samples/hello_world/assets/meshes/quad/texture.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
Loading…
Reference in New Issue
Block a user