Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added capsule mesh #155

Merged
merged 8 commits into from
Jan 22, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions graphics/include/ignition/common/MeshManager.hh
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,18 @@ namespace ignition
const int _rings,
const int _segments);

/// \brief Create a capsule mesh
/// \param[in] _name the name of the new mesh
/// \param[in] _radius the radius of the capsule in the x y plane
/// \param[in] _length length of the body
/// \param[in] _rings the number of circles along the height
/// \param[in] _segments the number of segment per circle
public: void CreateCapsule(const std::string &_name,
const double radius,
const double length,
const unsigned int _rings,
const unsigned int _segments);

/// \brief Create a cone mesh
/// \param[in] _name the name of the new mesh
/// \param[in] _radius the radius of the cylinder in the x y plane
Expand Down
151 changes: 151 additions & 0 deletions graphics/src/MeshManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,157 @@ void MeshManager::CreateCamera(const std::string &_name, float _scale)
mesh->RecalculateNormals();
}

void MeshManager::CreateCapsule(const std::string &_name,
const double _radius,
const double _length,
const unsigned int _rings,
const unsigned int _segments)
{
if (this->HasMesh(_name))
{
return;
ahcorde marked this conversation as resolved.
Show resolved Hide resolved
}

Mesh *mesh = new Mesh();
ahcorde marked this conversation as resolved.
Show resolved Hide resolved
mesh->SetName(_name);
this->dataPtr->meshes.insert(std::make_pair(_name, mesh));

SubMesh subMesh;

// Based on https://github.com/godotengine/godot primitive_meshes.cpp
int prevRow, thisRow, point;
double x, y, z, u, v, w;
const double oneThird = 1.0 / 3.0;
const double twoThirds = 2.0 / 3.0;

point = 0;

/* top hemisphere */
thisRow = 0;
prevRow = 0;
for (unsigned int j = 0; j <= (_rings + 1); j++) {
v = j;

v /= (_rings + 1);
w = sin(0.5 * IGN_PI * v);
y = _radius * cos(0.5 * IGN_PI * v);

for (unsigned int i = 0; i <= _segments; i++) {
u = i;
u /= _segments;

x = -sin(u * (IGN_PI * 2.0));
z = cos(u * (IGN_PI * 2.0));

ignition::math::Vector3d p(
x * _radius * w, y, -z * _radius * w);
// Compute vertex
subMesh.AddVertex(ignition::math::Vector3d(
p + ignition::math::Vector3d(0.0, 0.5 * _length, 0.0)));
subMesh.AddTexCoord({u, v * oneThird});
subMesh.AddNormal(p.Normalize());

point++;

if (i > 0 && j > 0) {
subMesh.AddIndex(thisRow + i - 1);
subMesh.AddIndex(prevRow + i);
subMesh.AddIndex(prevRow + i - 1);

subMesh.AddIndex(thisRow + i - 1);
subMesh.AddIndex(thisRow + i);
subMesh.AddIndex(prevRow + i);
}
}
prevRow = thisRow;
thisRow = point;
}

/* cylinder */
thisRow = point;
prevRow = 0;
for (unsigned int j = 0; j <= (_rings + 1); j++) {
v = j;
v /= (_rings + 1);

y = _length * v;
y = (_length * 0.5) - y;

for (unsigned int i = 0; i <= _segments; i++) {
u = i;
u /= _segments;

x = -sin(u * (IGN_PI * 2.0));
z = cos(u * (IGN_PI * 2.0));

ignition::math::Vector3d p(
x * _radius, y, -z * _radius);

// Compute vertex
subMesh.AddVertex(p);
subMesh.AddTexCoord({u, oneThird + (v * oneThird)});
subMesh.AddNormal(ignition::math::Vector3d(x, 0.0, -z));
point++;

if (i > 0 && j > 0) {
subMesh.AddIndex(thisRow + i - 1);
subMesh.AddIndex(prevRow + i);
subMesh.AddIndex(prevRow + i - 1);

subMesh.AddIndex(thisRow + i - 1);
subMesh.AddIndex(thisRow + i);
subMesh.AddIndex(prevRow + i);
}
}
prevRow = thisRow;
thisRow = point;
}

/* bottom hemisphere */
thisRow = point;
prevRow = 0;
for (unsigned int j = 0; j <= (_rings + 1); j++) {
v = j;

v /= (_rings + 1);
v += 1.0;
w = sin(0.5 * IGN_PI * v);
y = _radius * cos(0.5 * IGN_PI * v);

for (unsigned int i = 0; i <= _segments; i++) {
float u2 = i;
ahcorde marked this conversation as resolved.
Show resolved Hide resolved
u2 /= _segments;

x = -sin(u2 * (IGN_PI * 2.0));
z = cos(u2 * (IGN_PI * 2.0));

ignition::math::Vector3d p(
x * _radius * w, y, -z * _radius * w);
// Compute vertex
subMesh.AddVertex(ignition::math::Vector3d(
p + ignition::math::Vector3d(0.0, -0.5 * _length, 0.0)));
subMesh.AddTexCoord({u2, twoThirds + ((v - 1.0) * oneThird)});
subMesh.AddNormal(p.Normalize());
point++;

if (i > 0 && j > 0) {
subMesh.AddIndex(thisRow + i - 1);
subMesh.AddIndex(prevRow + i);
subMesh.AddIndex(prevRow + i - 1);

subMesh.AddIndex(thisRow + i - 1);
subMesh.AddIndex(thisRow + i);
subMesh.AddIndex(prevRow + i);
}
}

prevRow = thisRow;
thisRow = point;
}

mesh->AddSubMesh(subMesh);
}

//////////////////////////////////////////////////
void MeshManager::CreateCylinder(const std::string &name, float radius,
float height, int rings, int segments)
Expand Down
27 changes: 27 additions & 0 deletions graphics/src/SubMesh_TEST.cc
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,33 @@ TEST_F(SubMeshTest, Volume)
1e-2);
}

// Capsule mesh tests
{
common::MeshManager::Instance()->CreateCapsule("capsule",
1, 1, 10, 10);

const common::Mesh *unitCapsule =
common::MeshManager::Instance()->MeshByName("capsule");
ASSERT_TRUE(unitCapsule != nullptr);

// Checking that we can not add or modify a new mesh with the same name
common::MeshManager::Instance()->CreateCapsule("capsule",
1, 1, 100, 100);
const common::Mesh *unitCapsule2 =
common::MeshManager::Instance()->MeshByName("capsule");

// the new mesh should have more vertex, but it should be introduced in the
// meshmanager. It should be the same number becuase it was not modified.
EXPECT_EQ(unitCapsule->VertexCount(), unitCapsule2->VertexCount());

common::MeshManager::Instance()->CreateCapsule("other_capsule",
1.5, 7.5, 10, 10);

const common::Mesh *otherCapsule =
common::MeshManager::Instance()->MeshByName("other_capsule");
ASSERT_TRUE(otherCapsule != nullptr);
}

// Cylinder mesh tests
{
common::MeshManager::Instance()->CreateCylinder("unit_cylinder",
Expand Down