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:
committed by
Copybara-Service
parent
e4ee00e695
commit
4d024f9421
+12
-37
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user