Skip to content

Commit

Permalink
[processes] Add array to mesh process
Browse files Browse the repository at this point in the history
  • Loading branch information
jcelerier committed Nov 19, 2024
1 parent 986fd9f commit 405ae1d
Show file tree
Hide file tree
Showing 8 changed files with 282 additions and 78 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ add_library(
Threedim/Ply.hpp
Threedim/Ply.cpp

Threedim/ArrayToGeometry.hpp
Threedim/ArrayToGeometry.cpp

Threedim/StructureSynth.hpp
Threedim/StructureSynth.cpp

Expand Down
150 changes: 150 additions & 0 deletions Threedim/ArrayToGeometry.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
#include "ArrayToGeometry.hpp"

#include <Threedim/MeshHelpers.hpp>
#include <Threedim/TinyObj.hpp>
#include <vcg/complex/algorithms/create/ball_pivoting.h>
#include <vcg/complex/complex.h>

#include <QDebug>
#include <QString>

namespace Threedim
{
static thread_local TMesh array_to_mesh;

void loadPoints(TMesh& mesh, std::vector<float>& complete, PrimitiveOutputs& outputs)
{
vcg::tri::Clean<TMesh>::RemoveZeroAreaFace(mesh);
vcg::tri::UpdateTopology<TMesh>::FaceFace(mesh);
vcg::tri::Clean<TMesh>::RemoveNonManifoldFace(mesh);
vcg::tri::UpdateTopology<TMesh>::FaceFace(mesh);
vcg::tri::UpdateNormal<TMesh>::PerVertexNormalized(mesh);
vcg::tri::UpdateTexture<TMesh>::WedgeTexFromPlane(
mesh, vcg::Point3f{0., 0., 0.}, vcg::Point3f{1., 1., 1.}, 1.);

vcg::tri::RequirePerVertexNormal(mesh);
vcg::tri::RequirePerVertexTexCoord(mesh);

complete.clear();
const auto vertices = mesh.vert.size();
const auto floats
= vertices * (3 + 3 + 2); // 3 float for pos, 3 float for normal, 2 float for UV
complete.resize(floats);
float* pos_start = complete.data();
float* norm_start = complete.data() + vertices * 3;
float* uv_start = complete.data() + vertices * 3 + vertices * 3;

for (auto& fi : mesh.face)
{ // iterate each faces

auto v0 = fi.V(0);
auto v1 = fi.V(1);
auto v2 = fi.V(2);

auto p0 = v0->P();
(*pos_start++) = p0.X();
(*pos_start++) = p0.Y();
(*pos_start++) = p0.Z();

auto p1 = v1->P();
(*pos_start++) = p1.X();
(*pos_start++) = p1.Y();
(*pos_start++) = p1.Z();

auto p2 = v2->P();
(*pos_start++) = p2.X();
(*pos_start++) = p2.Y();
(*pos_start++) = p2.Z();

auto n0 = v0->N();
(*norm_start++) = n0.X();
(*norm_start++) = n0.Y();
(*norm_start++) = n0.Z();

auto n1 = v1->N();
(*norm_start++) = n1.X();
(*norm_start++) = n1.Y();
(*norm_start++) = n1.Z();

auto n2 = v2->N();
(*norm_start++) = n2.X();
(*norm_start++) = n2.Y();
(*norm_start++) = n2.Z();

#if 0
auto uv0 = fi.WT(0);
(*uv_start++) = uv0.U();
(*uv_start++) = uv0.V();

auto uv1 = fi.WT(1);
(*uv_start++) = uv1.U();
(*uv_start++) = uv1.V();

auto uv2 = fi.WT(2);
(*uv_start++) = uv2.U();
(*uv_start++) = uv2.V();
#endif
(*uv_start++) = p0.X();
(*uv_start++) = p0.Y();

(*uv_start++) = p1.X();
(*uv_start++) = p1.Y();

(*uv_start++) = p2.X();
(*uv_start++) = p2.Y();
}
outputs.geometry.mesh.buffers.main_buffer.data = complete.data();
outputs.geometry.mesh.buffers.main_buffer.size = complete.size();
outputs.geometry.mesh.buffers.main_buffer.dirty = true;

outputs.geometry.mesh.input.input0.offset = 0;
outputs.geometry.mesh.input.input1.offset = sizeof(float) * vertices * 3;
outputs.geometry.mesh.input.input2.offset = sizeof(float) * vertices * (3 + 3);
outputs.geometry.mesh.vertices = vertices;
outputs.geometry.dirty_mesh = true;
}
void ArrayToMesh::create_mesh(std::span<float> v)
{
if (v.size() < 3)
return;

if (inputs.triangulate)
{
auto& m = array_to_mesh;
m.Clear();
vcg::tri::Allocator<TMesh>::AddVertices(m, v.size() / 3);

for (std::size_t i = 0; i < v.size(); i += 3)
{
auto& vtx = m.vert[i / 3].P();
vtx.X() = v[i + 0];
vtx.Y() = v[i + 1];
vtx.Z() = v[i + 2];
}
vcg::tri::UpdateBounding<TMesh>::Box(m);
vcg::tri::UpdateNormal<TMesh>::PerFace(m);

vcg::tri::BallPivoting<TMesh> pivot(m, 0.01, 0.05);
pivot.BuildMesh();
loadTriMesh(m, complete, outputs);
}
else
{
std::size_t vertices = v.size() / 3;

this->complete.clear();
this->complete.resize(std::ceil((v.size() / 3.) * (3 + 3 + 2)));
std::copy_n(v.begin(), v.size(), complete.begin());

outputs.geometry.mesh.buffers.main_buffer.data = complete.data();
outputs.geometry.mesh.buffers.main_buffer.size = complete.size();
outputs.geometry.mesh.buffers.main_buffer.dirty = true;

outputs.geometry.mesh.input.input0.offset = 0;
outputs.geometry.mesh.input.input1.offset = sizeof(float) * vertices * 3;
outputs.geometry.mesh.input.input2.offset = sizeof(float) * vertices * (3 + 3);
outputs.geometry.mesh.vertices = vertices;
outputs.geometry.dirty_mesh = true;
}
}
}
41 changes: 41 additions & 0 deletions Threedim/ArrayToGeometry.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#pragma once

#include <Threedim/TinyObj.hpp>
#include <boost/container/vector.hpp>
#include <halp/controls.hpp>
#include <halp/geometry.hpp>
#include <halp/meta.hpp>
#include <ossia/detail/pod_vector.hpp>

namespace Threedim
{

class ArrayToMesh
{
public:
halp_meta(name, "Array to mesh")
halp_meta(category, "Visuals/3D")
halp_meta(c_name, "array_to_mesh")
halp_meta(manual_url, "https://ossia.io/score-docs/processes/array-to-mesh.html")
halp_meta(uuid, "dfc5bae9-c75c-4180-b4e8-be3063c8d8f2")

struct ins
{
struct : halp::val_port<"Input", std::vector<float>>
{
void update(ArrayToMesh& self) { self.create_mesh(value); }
} in;
PositionControl position;
RotationControl rotation;
ScaleControl scale;

halp::toggle<"Triangulate"> triangulate;
} inputs;

PrimitiveOutputs outputs;
void create_mesh(std::span<float> v);

std::vector<float> complete;
};

}
46 changes: 46 additions & 0 deletions Threedim/MeshHelpers.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#pragma once
#include <Threedim/TinyObj.hpp>
#include <vcg/complex/algorithms/clean.h>
#include <vcg/complex/algorithms/create/platonic.h>
#include <vcg/complex/algorithms/update/normal.h>
#include <vcg/complex/algorithms/update/texture.h>

namespace Threedim
{
using namespace vcg;
class TFace;
class TVertex;

struct TUsedTypes
: public vcg::UsedTypes<vcg::Use<TVertex>::AsVertexType, vcg::Use<TFace>::AsFaceType>
{
};

class TVertex
: public Vertex<
TUsedTypes,
vertex::BitFlags,
vertex::Coord3f,
vertex::Normal3f,
vertex::TexCoord2f,
vertex::Mark>
{
};

class TFace
: public Face<
TUsedTypes,
face::VertexRef,
face::Normal3f,
face::WedgeTexCoord2f,
face::BitFlags,
face::FFAdj>
{
};

class TMesh : public vcg::tri::TriMesh<std::vector<TVertex>, std::vector<TFace>>
{
};

void loadTriMesh(TMesh& mesh, std::vector<float>& complete, PrimitiveOutputs& outputs);
}
73 changes: 16 additions & 57 deletions Threedim/Primitive.cpp
Original file line number Diff line number Diff line change
@@ -1,74 +1,32 @@
#include "Primitive.hpp"

#include <vcg/complex/algorithms/clean.h>
#include <vcg/complex/algorithms/create/platonic.h>
#include <vcg/complex/algorithms/update/texture.h>
#include <Threedim/MeshHelpers.hpp>
#include <Threedim/TinyObj.hpp>

#include <QDebug>
#include <QString>

#include <iostream>

namespace
{
using namespace vcg;
class TFace;
class TVertex;

struct TUsedTypes
: public vcg::UsedTypes<vcg::Use<TVertex>::AsVertexType, vcg::Use<TFace>::AsFaceType>
{
};

class TVertex
: public Vertex<
TUsedTypes,
vertex::BitFlags,
vertex::Coord3f,
vertex::Normal3f,
vertex::TexCoord2f,
vertex::Mark>
{
};

class TFace
: public Face<
TUsedTypes,
face::VertexRef,
face::Normal3f,
face::WedgeTexCoord2f,
face::BitFlags,
face::FFAdj>
{
};

class TMesh : public vcg::tri::TriMesh<std::vector<TVertex>, std::vector<TFace>>
{
};
}

namespace Threedim
{

static thread_local TMesh mesh;

static void
loadTriMesh(TMesh& mesh, std::vector<float>& complete, PrimitiveOutputs& outputs)
void loadTriMesh(TMesh& mesh, std::vector<float>& complete, PrimitiveOutputs& outputs)
{
vcg::tri::Clean<TMesh>::RemoveUnreferencedVertex(mesh);
vcg::tri::Clean<TMesh>::RemoveZeroAreaFace(mesh);
vcg::tri::UpdateTopology<TMesh>::FaceFace(mesh);
vcg::tri::Clean<TMesh>::RemoveNonManifoldFace(mesh);
vcg::tri::UpdateTopology<TMesh>::FaceFace(mesh);
vcg::tri::UpdateNormal<TMesh>::PerVertexNormalized(mesh);
vcg::tri::UpdateTexture<TMesh>::WedgeTexFromPlane(mesh,vcg::Point3f{0.,0.,0.},vcg::Point3f{1.,1.,1.},1.);
vcg::tri::UpdateTexture<TMesh>::WedgeTexFromPlane(
mesh, vcg::Point3f{0., 0., 0.}, vcg::Point3f{1., 1., 1.}, 1.);

vcg::tri::RequirePerVertexNormal(mesh);
vcg::tri::RequirePerVertexTexCoord(mesh);

complete.clear();
const auto vertices = mesh.face.size() * 3;
const auto floats = vertices * (3 + 3 + 2); // 3 float for pos, 3 float for normal, 2 float for UV
const auto vertices = mesh.vert.size();
const auto floats
= vertices * (3 + 3 + 2); // 3 float for pos, 3 float for normal, 2 float for UV
complete.resize(floats);
float* pos_start = complete.data();
float* norm_start = complete.data() + vertices * 3;
Expand Down Expand Up @@ -124,26 +82,27 @@ loadTriMesh(TMesh& mesh, std::vector<float>& complete, PrimitiveOutputs& outputs
(*uv_start++) = uv2.U();
(*uv_start++) = uv2.V();
#endif
(*uv_start++) =p0.X();
(*uv_start++) =p0.Y();
(*uv_start++) = p0.X();
(*uv_start++) = p0.Y();

(*uv_start++) =p1.X();
(*uv_start++) =p1.Y();
(*uv_start++) = p1.X();
(*uv_start++) = p1.Y();

(*uv_start++) =p2.X();
(*uv_start++) =p2.Y();
(*uv_start++) = p2.X();
(*uv_start++) = p2.Y();
}
outputs.geometry.mesh.buffers.main_buffer.data = complete.data();
outputs.geometry.mesh.buffers.main_buffer.size = complete.size();
outputs.geometry.mesh.buffers.main_buffer.dirty = true;

outputs.geometry.mesh.input.input0.offset = 0;
outputs.geometry.mesh.input.input1.offset = sizeof(float) * vertices * 3;
outputs.geometry.mesh.input.input2.offset = sizeof(float) * vertices * (3+3);
outputs.geometry.mesh.input.input2.offset = sizeof(float) * vertices * (3 + 3);
outputs.geometry.mesh.vertices = vertices;
outputs.geometry.dirty_mesh = true;
}

static thread_local TMesh mesh;
void Plane::update()
{
/*
Expand Down
17 changes: 0 additions & 17 deletions Threedim/Primitive.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,6 @@

namespace Threedim
{
struct Update
{
void update(auto& obj) { obj.update(); }
};

struct PrimitiveOutputs
{
struct
{
halp_meta(name, "Geometry");
halp::position_normals_texcoords_geometry mesh;
float transform[16]{};
bool dirty_mesh = false;
bool dirty_transform = false;
} geometry;
};

struct Primitive
{
halp_meta(category, "Visuals/3D/Primitives")
Expand Down
Loading

0 comments on commit 405ae1d

Please sign in to comment.