1
0

finish obj loader

This commit is contained in:
2026-01-09 22:50:24 +08:00
parent 07bd22d2ee
commit 31dc82fc2c
9 changed files with 137 additions and 13 deletions

View File

@@ -41,12 +41,16 @@ set(CMAKE_MODULE_PATH
"${CMAKE_CURRENT_LIST_DIR}/CMake" "${CMAKE_CURRENT_LIST_DIR}/CMake"
) )
# Find required packages based on options # Find required packages based on options
find_package(spdlog REQUIRED)
if (BASALT_CUDA_DELIVER) if (BASALT_CUDA_DELIVER)
find_package(CUDA REQUIRED) find_package(CUDA REQUIRED)
endif () endif ()
if (BASALT_DIRECTX11_ENGINE) if (BASALT_DIRECTX11_ENGINE)
find_package(DirectX11 REQUIRED) find_package(DirectX11 REQUIRED)
endif () endif ()
if (BASALT_OBJ_OBJECT_LOADER)
find_package(tinyobjloader REQUIRED)
endif ()
# Include projects # Include projects

View File

@@ -14,6 +14,7 @@ PRIVATE
target_link_libraries(BasaltObjObjectLoader target_link_libraries(BasaltObjObjectLoader
PRIVATE PRIVATE
BasaltShared BasaltShared
tinyobjloader
) )
# Enable export macro # Enable export macro
target_compile_definitions(BasaltObjObjectLoader target_compile_definitions(BasaltObjObjectLoader

View File

@@ -1,9 +1,95 @@
#include <basalt/export_macro.hpp> #include <basalt/export_macro.hpp>
#include <basalt/object_loader.hpp>
#include <tiny_obj_loader.h>
#include <vector>
#include <string>
namespace object_loader = ::basalt::shared::object_loader;
using object_loader::IObjectLoader;
using object_loader::Object;
using object_loader::ObjectLoaderConfig;
namespace math = ::basalt::shared::math;
using math::FloatPoint;
using math::Index;
using math::Triangle;
using math::Vector3;
class ObjObjectLoader : public IObjectLoader {
public:
ObjObjectLoader() {}
virtual ~ObjObjectLoader() {}
public:
virtual void load(ObjectLoaderConfig&& config) override {
IObjectLoader::load(std::move(config));
// Load the OBJ file using tinyobjloader
tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes;
std::vector<tinyobj::material_t> materials;
std::string err;
// Load the OBJ file
if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &err, this->config.filename.c_str())) {
throw std::runtime_error("fail to load obj file");
}
// Create one object from all shapes in the OBJ file
std::vector<Vector3> vertices;
std::vector<Triangle> triangles;
// Extract all vertices from the OBJ file
// In tinyobjloader, vertices are stored in a flat array [x,y,z,x,y,z,...]
size_t num_vertices = attrib.vertices.size() / 3;
vertices.reserve(num_vertices);
for (size_t i = 0; i < attrib.vertices.size(); i += 3) {
Vector3 vertex;
vertex.x = attrib.vertices[i + 0]; // x coordinate
vertex.y = attrib.vertices[i + 1]; // y coordinate
vertex.z = attrib.vertices[i + 2]; // z coordinate
vertices.emplace_back(vertex);
}
// Process each shape and add its triangles
for (const auto& shape : shapes) {
// Add triangles from this shape to our collection
// Each face in the shape has been triangulated by tinyobjloader
for (size_t i = 0; i < shape.mesh.indices.size(); i += 3) {
if (i + 2 < shape.mesh.indices.size()) {
Triangle triangle;
// Get the three indices that form the triangle
// vertex_index is the index into the attrib.vertices array
int idx0 = shape.mesh.indices[i + 0].vertex_index;
int idx1 = shape.mesh.indices[i + 1].vertex_index;
int idx2 = shape.mesh.indices[i + 2].vertex_index;
// Make sure indices are valid
if (idx0 >= 0 && idx1 >= 0 && idx2 >= 0) {
triangle.i = static_cast<Index>(idx0);
triangle.j = static_cast<Index>(idx1);
triangle.k = static_cast<Index>(idx2);
triangles.emplace_back(triangle);
}
}
}
}
// Create an Object and add it to our objects vector
if (vertices.empty() || triangles.empty()) {
throw std::runtime_error("empty scene is not allowed");
} else {
this->objects.emplace_back(std::move(vertices), std::move(triangles));
}
}
};
BS_EXPORT void* BSCreateInstance() { BS_EXPORT void* BSCreateInstance() {
return nullptr; return static_cast<IObjectLoader*>(new ObjObjectLoader());
} }
BS_EXPORT void BSDestroyInstance(void* instance) { BS_EXPORT void BSDestroyInstance(void* instance) {
return; delete dynamic_cast<ObjObjectLoader*>(static_cast<IObjectLoader*>(instance));
} }

View File

@@ -4,6 +4,7 @@
#include <basalt/char_types.hpp> #include <basalt/char_types.hpp>
#include <basalt/engine.hpp> #include <basalt/engine.hpp>
#include <basalt/deliver.hpp> #include <basalt/deliver.hpp>
#include <spdlog/spdlog.h>
namespace engine = ::basalt::shared::engine; namespace engine = ::basalt::shared::engine;
using engine::EngineConfig; using engine::EngineConfig;
@@ -20,18 +21,22 @@ using ::basalt::presenter::cmd_client::CmdClient;
using ::basalt::presenter::stopwatch::Stopwatch; using ::basalt::presenter::stopwatch::Stopwatch;
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
spdlog::info("Finding plugins...");
auto engine_dll = DllLoader(DllKind::Engine, BSTEXT("BasaltDirectX11Engine")); auto engine_dll = DllLoader(DllKind::Engine, BSTEXT("BasaltDirectX11Engine"));
auto deliver_dll = DllLoader(DllKind::Deliver, BSTEXT("BasaltPipeDeliver")); auto deliver_dll = DllLoader(DllKind::Deliver, BSTEXT("BasaltPipeDeliver"));
auto client = CmdClient(); auto client = CmdClient();
spdlog::info("Waiting BasaltTrainer...");
auto payload = client.wait_handshake(); auto payload = client.wait_handshake();
spdlog::info("Allocating resources...");
auto* engine = engine_dll.create_instance<IEngine>(); auto* engine = engine_dll.create_instance<IEngine>();
//auto* deliver = deliver_dll.create_instance<IDeliver>(); //auto* deliver = deliver_dll.create_instance<IDeliver>();
EngineConfig engine_config{.headless = false, .width = payload.width, .height = payload.height}; EngineConfig engine_config{.headless = false, .width = payload.width, .height = payload.height};
engine->startup(std::move(engine_config)); engine->startup(std::move(engine_config));
spdlog::info("Start to running.");
Stopwatch stopwatch(120); Stopwatch stopwatch(120);
while (true) { while (true) {
auto req_stop = engine->tick(); auto req_stop = engine->tick();
@@ -40,6 +45,9 @@ int main(int argc, char* argv[]) {
if (can_stop) break; if (can_stop) break;
} }
spdlog::info("Destroying resources...");
engine->shutdown(); engine->shutdown();
engine_dll.destroy_instance(engine); engine_dll.destroy_instance(engine);
spdlog::info("Program stop.");
} }

View File

@@ -1,5 +1,5 @@
#include "stopwatch.hpp" #include "stopwatch.hpp"
#include <print> #include <spdlog/spdlog.h>
namespace basalt::presenter::stopwatch { namespace basalt::presenter::stopwatch {
@@ -20,7 +20,7 @@ namespace basalt::presenter::stopwatch {
auto frame_time = static_cast<double>(time_diff.count()) / this->interval; auto frame_time = static_cast<double>(time_diff.count()) / this->interval;
auto fps = 1000.0 / frame_time; auto fps = 1000.0 / frame_time;
// 输出给用户 // 输出给用户
std::print("FPS: {:.2f} Frame Time: {:.4f} ms\n", fps, frame_time); spdlog::info("FPS: {:.2f} Frame Time: {:.4f} ms", fps, frame_time);
// 把结束时间设置为开始时间继续下一轮循环 // 把结束时间设置为开始时间继续下一轮循环
this->start_point = stop_point; this->start_point = stop_point;

View File

@@ -10,6 +10,8 @@ We assume that you executing following commands in the root directory of `Basalt
### spdlog ### spdlog
##### Build
```sh ```sh
cd external cd external
git clone -b 1.17.0 https://github.com/gabime/spdlog.git git clone -b 1.17.0 https://github.com/gabime/spdlog.git
@@ -19,53 +21,65 @@ mkdir out
cd out cd out
mkdir build mkdir build
mkdir install mkdir install
cd build
``` ```
In Windows: In Windows:
```bat ```bat
cmake -A x64 ../.. cmake -A x64 -DCMAKE_CXX_STANDARD=23 -DSPDLOG_WCHAR_SUPPORT=ON -DSPDLOG_WCHAR_FILENAMES=ON -DSPDLOG_WCHAR_CONSOLE=ON -DSPDLOG_BUILD_EXAMPLE=OFF ../..
cmake --build . --config Release cmake --build . --config Release
cmake --install . --prefix=../install cmake --install . --config Release --prefix=../install
``` ```
Or in POSIX: Or in POSIX:
```sh ```sh
cmake -DCMAKE_BUILD_TYPE=Release ../.. cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=23 -DSPDLOG_BUILD_EXAMPLE=OFF ../..
cmake --build . cmake --build .
cmake --install . --prefix=../install cmake --install . --prefix=../install
``` ```
##### Usage
Use `-Dspdlog_ROOT=<path to spdlog install directory>` in cmake when you configure this project.
#### tinyobjloader #### tinyobjloader
##### Build
```sh ```sh
cd external cd external
git clone -b v2.0.0 https://github.com/tinyobjloader/tinyobjloader.git git clone -b v1.0.6 https://github.com/tinyobjloader/tinyobjloader.git
cd tinyobjloader cd tinyobjloader
mkdir out mkdir out
cd out cd out
mkdir build mkdir build
mkdir install mkdir install
cd build
``` ```
In Windows: In Windows:
```bat ```bat
cmake -A x64 ../.. cmake -A x64 -DCMAKE_CXX_STANDARD=23 ../..
cmake --build . --config Release cmake --build . --config Release
cmake --install . --prefix=../install cmake --install . --config Release --prefix=../install
``` ```
Or in POSIX: Or in POSIX:
```sh ```sh
cmake -DCMAKE_BUILD_TYPE=Release ../.. cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=23 ../..
cmake --build . cmake --build .
cmake --install . --prefix=../install cmake --install . --prefix=../install
``` ```
##### Usage
Use `-Dtinyobjloader_ROOT=<path to tinyobjloader install directory>` in cmake when you configure this project.
## Warning ## Warning
This project was not written robustly. This project was not written robustly.

View File

@@ -30,6 +30,10 @@ PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>" "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>" "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
) )
target_link_libraries(BasaltShared
PUBLIC
spdlog::spdlog
)
target_compile_definitions(BasaltShared target_compile_definitions(BasaltShared
PUBLIC PUBLIC
$<$<PLATFORM_ID:Windows>:BASALT_OS_WINDOWS> $<$<PLATFORM_ID:Windows>:BASALT_OS_WINDOWS>

View File

@@ -37,8 +37,9 @@ namespace basalt::shared::object_loader {
IObjectLoader::~IObjectLoader() {} IObjectLoader::~IObjectLoader() {}
void IObjectLoader::load() { void IObjectLoader::load(ObjectLoaderConfig&& config) {
if (this->status != ObjectLoaderStatus::Ready) throw std::runtime_error("unexpected object loader status"); if (this->status != ObjectLoaderStatus::Ready) throw std::runtime_error("unexpected object loader status");
this->config = std::move(config);
this->status = ObjectLoaderStatus::Loaded; this->status = ObjectLoaderStatus::Loaded;
} }

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "math.hpp" #include "math.hpp"
#include <vector> #include <vector>
#include <string>
namespace basalt::shared::object_loader { namespace basalt::shared::object_loader {
@@ -20,6 +21,10 @@ namespace basalt::shared::object_loader {
std::vector<math::Triangle> triangles; std::vector<math::Triangle> triangles;
}; };
struct ObjectLoaderConfig {
std::string filename;
};
enum class ObjectLoaderStatus { enum class ObjectLoaderStatus {
Ready, Ready,
Loaded, Loaded,
@@ -37,12 +42,13 @@ namespace basalt::shared::object_loader {
virtual ~IObjectLoader(); virtual ~IObjectLoader();
public: public:
virtual void load(); virtual void load(ObjectLoaderConfig&& config);
const Object& get_object(size_t index) const; const Object& get_object(size_t index) const;
size_t get_object_count() const; size_t get_object_count() const;
protected: protected:
ObjectLoaderStatus status; ObjectLoaderStatus status;
ObjectLoaderConfig config;
std::vector<Object> objects; std::vector<Object> objects;
}; };