Use tinyobjloader instead of custom obj reader

pull/170/head
James Ball 2023-01-19 23:02:52 +00:00
rodzic ece67ce7ee
commit 56efe597cb
7 zmienionych plików z 3523 dodań i 155 usunięć

Wyświetl plik

@ -41,10 +41,10 @@ std::vector<Vector2> Camera::sampleVerticesInRender(WorldObject& object) {
double oldRotateZ = object.rotateZ;
for (int i = 0; i < SAMPLE_RENDER_SAMPLES - 1; i++) {
for (size_t j = 0; j < std::min(VERTEX_SAMPLES, object.vertices.size()); j++) {
double x = object.vertices[j].v[0];
double y = object.vertices[j].v[1];
double z = object.vertices[j].v[2];
for (size_t j = 0; j < std::min(VERTEX_SAMPLES, object.numVertices); j++) {
double x = object.vs[j * 3];
double y = object.vs[j * 3 + 1];
double z = object.vs[j * 3 + 2];
vertices.push_back(project(object.rotateX, object.rotateY, object.rotateZ, x, y, z));
}
object.rotateY += rotation;

Wyświetl plik

@ -15,7 +15,7 @@ private:
const double VERTEX_VALUE_THRESHOLD = 1.0;
const double CAMERA_MOVE_INCREMENT = -0.1;
const int SAMPLE_RENDER_SAMPLES = 50;
const size_t VERTEX_SAMPLES = 1000;
const int VERTEX_SAMPLES = 1000;
const int MAX_NUM_STEPS = 1000;
double focalLength;

Wyświetl plik

@ -1,5 +1,6 @@
#include "WorldObject.h"
#include "../chinese_postman/ChinesePostman.h"
#include "tiny_obj_loader.h"
struct pair_hash {
inline std::size_t operator()(const std::pair<int, int>& v) const {
@ -8,87 +9,32 @@ struct pair_hash {
};
WorldObject::WorldObject(juce::InputStream& stream) {
std::string key;
while (!stream.isExhausted()) {
auto line = stream.readNextLine();
key = "";
std::stringstream stringstream(line.toStdString());
stringstream >> key >> std::ws;
tinyobj::ObjReaderConfig reader_config;
tinyobj::ObjReader reader;
if (key == "v") { // vertex
vertex v; float x;
while (!stringstream.eof()) {
stringstream >> x >> std::ws;
v.v.push_back(x);
}
vertices.push_back(v);
}
else if (key == "vp") { // parameter
/*vertex v; float x;
while (!stringstream.eof()) {
stringstream >> x >> std::ws;
v.v.push_back(x);
}
parameters.push_back(v);*/
}
else if (key == "vt") { // texture coordinate
/*vertex v; float x;
while (!stringstream.eof()) {
stringstream >> x >> std::ws;
v.v.push_back(x);
}
texcoords.push_back(v);*/
}
else if (key == "vn") { // normal
/*vertex v; float x;
while (!stringstream.eof()) {
stringstream >> x >> std::ws;
v.v.push_back(x);
}
v.normalize();
normals.push_back(v);*/
}
else if (key == "f") { // face
face f; int v, t, n;
while (!stringstream.eof()) {
stringstream >> v >> std::ws;
f.vertex.push_back(v - 1);
if (stringstream.peek() == '/') {
stringstream.get();
if (stringstream.peek() == '/') {
stringstream.get();
stringstream >> n >> std::ws;
f.normal.push_back(n - 1);
}
else {
stringstream >> t >> std::ws;
f.texture.push_back(t - 1);
if (stringstream.peek() == '/') {
stringstream.get();
stringstream >> n >> std::ws;
f.normal.push_back(n - 1);
}
}
}
}
faces.push_back(f);
}
}
reader.ParseFromString(stream.readEntireStreamAsString().toStdString(), "", reader_config);
vs = reader.GetAttrib().vertices;
numVertices = vs.size() / 3;
std::vector<tinyobj::shape_t> shapes = reader.GetShapes();
std::unordered_set<std::pair<int, int>, pair_hash> edge_set;
for (auto& f : faces) {
int num_vertices = f.vertex.size();
for (int i = 0; i < num_vertices; i++) {
int start = f.vertex[i];
int end = f.vertex[(i + 1) % num_vertices];
int first = start < end ? start : end;
int second = start < end ? end : start;
edge_set.insert(std::make_pair(first, second));
for (auto& shape : shapes) {
int i = 0;
int face = 0;
while (i < shape.mesh.indices.size()) {
int prevVertex = -1;
for (int j = 0; j < shape.mesh.num_face_vertices[face]; j++) {
int vertex = shape.mesh.indices[i].vertex_index;
if (prevVertex != -1) {
edge_set.insert(std::make_pair(prevVertex, vertex));
}
prevVertex = vertex;
i++;
}
face++;
}
}
}
std::list<std::pair<int, int>> edge_list;
@ -96,39 +42,46 @@ WorldObject::WorldObject(juce::InputStream& stream) {
edge_list.push_back(edge);
}
Graph graph(vertices.size(), edge_list);
Graph graph(numVertices, edge_list);
pair<list<int>, double> solution = ChinesePostman(graph);
list<int>& path = solution.first;
double x = 0.0, y = 0.0, z = 0.0;
double max = 0.0;
for (auto& v : vertices) {
x += v.v[0];
y += v.v[1];
z += v.v[2];
if (std::abs(v.v[0]) > max) max = std::abs(v.v[0]);
if (std::abs(v.v[1]) > max) max = std::abs(v.v[1]);
if (std::abs(v.v[2]) > max) max = std::abs(v.v[2]);
}
x /= vertices.size();
y /= vertices.size();
z /= vertices.size();
for (auto& v : vertices) {
v.v[0] = (v.v[0] - x) / max;
v.v[1] = (v.v[1] - y) / max;
v.v[2] = (v.v[2] - z) / max;
for (int i = 0; i < numVertices; i++) {
x += vs[i * 3];
y += vs[i * 3 + 1];
z += vs[i * 3 + 2];
if (std::abs(vs[i * 3]) > max) {
max = std::abs(vs[i * 3]);
}
if (std::abs(vs[i * 3 + 1]) > max) {
max = std::abs(vs[i * 3 + 1]);
}
if (std::abs(vs[i * 3 + 2]) > max) {
max = std::abs(vs[i * 3 + 2]);
}
}
x /= numVertices;
y /= numVertices;
z /= numVertices;
for (int i = 0; i < numVertices; i++) {
vs[i * 3] = (vs[i * 3] - x) / max;
vs[i * 3 + 1] = (vs[i * 3 + 1] - y) / max;
vs[i * 3 + 2] = (vs[i * 3 + 2] - z) / max;
}
int prevVertex = -1;
for (auto& vertex : path) {
if (prevVertex != -1) {
double x1 = vertices[prevVertex].v[0];
double y1 = vertices[prevVertex].v[1];
double z1 = vertices[prevVertex].v[2];
double x2 = vertices[vertex].v[0];
double y2 = vertices[vertex].v[1];
double z2 = vertices[vertex].v[2];
double x1 = vs[prevVertex * 3];
double y1 = vs[prevVertex * 3 + 1];
double z1 = vs[prevVertex * 3 + 2];
double x2 = vs[vertex * 3];
double y2 = vs[vertex * 3 + 1];
double z2 = vs[vertex * 3 + 2];
edges.push_back(Line3D(x1, y1, z1, x2, y2, z2));
}

Wyświetl plik

@ -3,52 +3,6 @@
#include <JuceHeader.h>
#include "Line3D.h"
// from https://www.keithlantz.net/2011/10/a-preliminary-wavefront-obj-loader-in-c/
struct vertex {
std::vector<float> v;
void normalize() {
float magnitude = 0.0f;
for (int i = 0; i < v.size(); i++)
magnitude += pow(v[i], 2.0f);
magnitude = sqrt(magnitude);
for (int i = 0; i < v.size(); i++)
v[i] /= magnitude;
}
vertex operator-(vertex v2) {
vertex v3;
if (v.size() != v2.v.size()) {
v3.v.push_back(0.0f);
v3.v.push_back(0.0f);
v3.v.push_back(0.0f);
}
else {
for (int i = 0; i < v.size(); i++)
v3.v.push_back(v[i] - v2.v[i]);
}
return v3;
}
vertex cross(vertex v2) {
vertex v3;
if (v.size() != 3 || v2.v.size() != 3) {
v3.v.push_back(0.0f);
v3.v.push_back(0.0f);
v3.v.push_back(0.0f);
}
else {
v3.v.push_back(v[1] * v2.v[2] - v[2] * v2.v[1]);
v3.v.push_back(v[2] * v2.v[0] - v[0] * v2.v[2]);
v3.v.push_back(v[0] * v2.v[1] - v[1] * v2.v[0]);
}
return v3;
}
};
struct face {
std::vector<int> vertex;
std::vector<int> texture;
std::vector<int> normal;
};
class WorldObject {
public:
WorldObject(juce::InputStream&);
@ -56,10 +10,7 @@ public:
double rotateX = 0.0, rotateY = 0.0, rotateZ = 0.0;
std::vector<Line3D> edges;
std::vector<vertex> vertices;
std::vector<float> vs;
int numVertices;
private:
std::vector<vertex> texcoords;
std::vector<vertex> normals;
std::vector<vertex> parameters;
std::vector<face> faces;
};

Wyświetl plik

@ -0,0 +1,2 @@
#define TINYOBJLOADER_IMPLEMENTATION
#include "tiny_obj_loader.h"

Plik diff jest za duży Load Diff

Wyświetl plik

@ -51,6 +51,10 @@
<FILE id="ix12FT" name="Camera.h" compile="0" resource="0" file="Source/obj/Camera.h"/>
<FILE id="JJTNO9" name="Line3D.cpp" compile="1" resource="0" file="Source/obj/Line3D.cpp"/>
<FILE id="TMrur0" name="Line3D.h" compile="0" resource="0" file="Source/obj/Line3D.h"/>
<FILE id="a4ILpa" name="tiny_obj_loader.cpp" compile="1" resource="0"
file="Source/obj/tiny_obj_loader.cpp"/>
<FILE id="YdfYbM" name="tiny_obj_loader.h" compile="0" resource="0"
file="Source/obj/tiny_obj_loader.h"/>
<FILE id="YNsbe9" name="WorldObject.cpp" compile="1" resource="0" file="Source/obj/WorldObject.cpp"/>
<FILE id="SZBVI9" name="WorldObject.h" compile="0" resource="0" file="Source/obj/WorldObject.h"/>
</GROUP>