Convert internal representation of vertices to double. Also replace remove duplicate vertices with fast hash implementation.

PiperOrigin-RevId: 734516595
Change-Id: Ic78556688d5f2b75d69cd286b8d060e2cdeb7c48
This commit is contained in:
Kyle Bayes
2025-03-07 05:16:54 -08:00
committed by Copybara-Service
parent e4ee00e695
commit 4d024f9421
9 changed files with 435 additions and 363 deletions
+12 -37
View File
@@ -989,14 +989,6 @@ bool mjCFlexcomp::MakeMesh(mjCModel* model, char* error, int error_sz) {
return comperr(error, "File is required", error_sz);
}
// get extension and check; must be STL, OBJ or MSH
std::string ext = mjuu_getext(file);
if (strcasecmp(ext.c_str(), ".stl") &&
strcasecmp(ext.c_str(), ".obj") &&
strcasecmp(ext.c_str(), ".msh")) {
return comperr(error, "Mesh file extension must be stl, obj or msh", error_sz);
}
// check dim
if (def.spec.flex->dim < 2) {
return comperr(error, "Flex dim must be at least 2 for mesh", error_sz);
@@ -1006,6 +998,11 @@ bool mjCFlexcomp::MakeMesh(mjCModel* model, char* error, int error_sz) {
std::string filename = mjuu_combinePaths(mjs_getString(model->spec.meshdir), file);
mjResource* resource = nullptr;
if (mjCMesh::IsMSH(filename)) {
return comperr(error, "legacy MSH files are not supported in flexcomp", error_sz);
}
try {
resource = mjCBase::LoadResource(mjs_getString(model->spec.modelfiledir),
filename, 0);
@@ -1013,46 +1010,24 @@ bool mjCFlexcomp::MakeMesh(mjCModel* model, char* error, int error_sz) {
return comperr(error, err.message, error_sz);
}
// load mesh
mjCMesh mesh;
bool isobj = false;
try {
if (!strcasecmp(ext.c_str(), ".stl")) {
mesh.LoadSTL(resource);
} else if (!strcasecmp(ext.c_str(), ".obj")) {
isobj = true;
mesh.LoadOBJ(resource);
} else {
mesh.LoadMSH(resource);
}
mesh.LoadFromResource(resource, true);
mju_closeResource(resource);
} catch (mjCError err) {
mju_closeResource(resource);
return comperr(error, err.message, error_sz);
}
// LoadOBJ uses userXXX, extra processing needed
if (isobj) {
// check sizes
if (mesh.Vert().empty() || mesh.Face().empty()) {
return comperr(error, "Vertex and face data required", error_sz);
}
if (mesh.Vert().size()%3) {
return comperr(error, "Vertex data must be multiple of 3", error_sz);
}
if (mesh.Face().size()%3) {
return comperr(error, "Face data must be multiple of 3", error_sz);
}
// remove repeated vertices (not called in LoadOBJ)
mesh.RemoveRepeated();
// check sizes
if (mesh.Vert().empty() || mesh.Face().empty()) {
return comperr(error, "Vertex and face data required", error_sz);
}
// copy vertices, convert from float to double
point = vector<double> (mesh.nvert()*3);
for (int i=0; i < mesh.nvert()*3; i++) {
point[i] = (double) mesh.Vert(i);
}
// copy vertices
point = mesh.Vert();
if (mesh.HasTexcoord()) {
texcoord = mesh.Texcoord();
+329 -292
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -734,7 +734,7 @@ std::string mjCBase::GetAssetContentType(std::string_view resource_name,
auto type = mjuu_parseContentTypeAttrType(raw_text);
auto subtype = mjuu_parseContentTypeAttrSubtype(raw_text);
if (!type.has_value() || !subtype.has_value()) {
throw mjCError(this, "invalid format for content_type");
return "";
}
return std::string(*type) + "/" + std::string(*subtype);
} else {
+29 -12
View File
@@ -15,6 +15,7 @@
#ifndef MUJOCO_SRC_USER_USER_OBJECTS_H_
#define MUJOCO_SRC_USER_USER_OBJECTS_H_
#include <stdbool.h>
#include <cstddef>
#include <array>
#include <cstdlib>
@@ -195,7 +196,7 @@ class mjCBase : public mjCBase_ {
// Get and sanitize content type from raw_text if not empty, otherwise parse
// content type from resource_name; throw on failure
std::string GetAssetContentType(std::string_view resource_name, std::string_view raw_text);
static std::string GetAssetContentType(std::string_view resource_name, std::string_view raw_text);
// Add frame transformation
void SetFrame(mjCFrame* _frame);
@@ -842,9 +843,10 @@ class mjCMesh_ : public mjCBase {
std::string plugin_name;
std::string plugin_instance_name;
std::string content_type_; // content type of file
std::string content_type_ = ""; // content type of file
std::string file_; // mesh file
std::vector<float> vert_; // vertex data
mjResource* resource_ = nullptr; // resource for mesh file
std::vector<double> vert_; // vertex data
std::vector<float> normal_; // normal data
std::vector<float> texcoord_; // texcoord data
std::vector<int> face_; // vertex indices
@@ -886,7 +888,7 @@ class mjCMesh_ : public mjCBase {
double surface_; // surface of the mesh
// size of mesh data to be copied into mjModel
int szgraph_; // size of graph data in ints
int szgraph_ = 0; // size of graph data in ints
bool needhull_; // needs convex hull for collisions
int maxhullvert_; // max vertex count of convex hull
@@ -923,8 +925,8 @@ class mjCMesh: public mjCMesh_, private mjsMesh {
const double* Refquat() const { return refquat; }
const double* Scale() const { return scale; }
bool SmoothNormal() const { return smoothnormal; }
const std::vector<float>& Vert() const { return vert_; }
float Vert(int i) const { return vert_[i]; }
const std::vector<double>& Vert() const { return vert_; }
double Vert(int i) const { return vert_[i]; }
const std::vector<float>& UserVert() const { return spec_vert_; }
const std::vector<float>& UserNormal() const { return spec_normal_; }
const std::vector<float>& Texcoord() const { return texcoord_; }
@@ -997,18 +999,33 @@ class mjCMesh: public mjCMesh_, private mjsMesh {
// sets properties of a bounding volume given a face id
void SetBoundingVolume(int faceid);
void LoadOBJ(mjResource* resource); // load mesh in wavefront OBJ format
void LoadSTL(mjResource* resource); // load mesh in STL BIN format
void LoadMSH(mjResource* resource); // load mesh in MSH BIN format
// load from OBJ, STL, or MSH file; throws mjCError on failure
void LoadFromResource(mjResource* resource, bool remove_repeated = false);
void RemoveRepeated(); // remove repeated vertices
static bool IsObj(std::string_view filename, std::string_view ct = "");
static bool IsSTL(std::string_view filename, std::string_view ct = "");
static bool IsMSH(std::string_view filename, std::string_view ct = "");
bool IsObj() const;
bool IsSTL() const;
bool IsMSH() const;
private:
void TryCompile(const mjVFS* vfs);
// load mesh from cache asset, return true on success (OBJ files are only supported)
bool LoadCachedMesh(mjCCache *cache, const mjResource* resource);
// store mesh into asset cache (OBJ files are only supported)
void CacheMesh(mjCCache *cache, const mjResource* resource,
std::string_view asset_type);
void CacheMesh(mjCCache *cache, const mjResource* resource);
// convert vertices to double precision and remove repeated vertices if requested
void ProcessVertices(const std::vector<float>& vert, bool remove_repeated = false);
void LoadOBJ(mjResource* resource, bool remove_repeated); // load mesh in wavefront OBJ format
void LoadSTL(mjResource* resource); // load mesh in STL BIN format
void LoadMSH(mjResource* resource, bool remove_repeated); // load mesh in MSH BIN format
void LoadSDF(); // generate mesh using marching cubes
void MakeGraph(); // make graph of convex hull
+6 -1
View File
@@ -359,7 +359,8 @@ void mjuu_crossvec(double* a, const double* b, const double* c) {
// compute normal vector to given triangle, return length
double mjuu_makenormal(double* normal, const float* a, const float* b, const float* c) {
template<typename T> double mjuu_makenormal(double* normal, const T a[3],
const T b[3], const T c[3]) {
double v1[3] = {a[0], a[1], a[2]};
double v2[3] = {b[0], b[1], b[2]};
double v3[3] = {c[0], c[1], c[2]};
@@ -379,6 +380,10 @@ double mjuu_makenormal(double* normal, const float* a, const float* b, const flo
return nrm;
}
template double mjuu_makenormal(double* normal, const double a[3],
const double b[3], const double c[3]);
template double mjuu_makenormal(double* normal, const float a[3],
const float b[3], const float c[3]);
// compute quaternion as minimal rotation from [0;0;1] to vec
void mjuu_z2quat(double* quat, const double* vec) {
+3 -2
View File
@@ -107,8 +107,9 @@ void mjuu_localquat(double* local, const double* child, const double* parent);
// compute vector cross-product a = b x c
void mjuu_crossvec(double* a, const double* b, const double* c);
// compute normal vector to given triangle (uses float for OpenGL)
double mjuu_makenormal(double* normal, const float* a, const float* b, const float* c);
// compute normal vector to given triangle
template<typename T> double mjuu_makenormal(double* normal, const T a[3],
const T b[3], const T c[3]);
// compute quaternion corresponding to minimal rotation from [0;0;1] to vec
void mjuu_z2quat(double* quat, const double* vec);