Modify mjCMesh vert_ field to be vector<float> instead of vector<double>.
PiperOrigin-RevId: 882162404 Change-Id: Ia97439420f284d594f5cb1a91cd0fb640ac8dff0
This commit is contained in:
committed by
Copybara-Service
parent
de3b9d3426
commit
3601b063dc
@@ -1185,7 +1185,7 @@ bool mjCFlexcomp::MakeMesh(mjCModel* model, mjsCompiler* compiler, char* error,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// copy vertices
|
// copy vertices
|
||||||
point = mesh.Vert();
|
point.assign(mesh.Vert().begin(), mesh.Vert().end());
|
||||||
|
|
||||||
if (mesh.HasTexcoord()) {
|
if (mesh.HasTexcoord()) {
|
||||||
texcoord = mesh.Texcoord();
|
texcoord = mesh.Texcoord();
|
||||||
|
|||||||
+108
-102
@@ -492,7 +492,7 @@ void mjCMesh::CacheMesh(mjCCache* cache, const mjResource* resource) {
|
|||||||
|
|
||||||
// calculate estimated size of mesh
|
// calculate estimated size of mesh
|
||||||
std::size_t size = sizeof(mjCMesh)
|
std::size_t size = sizeof(mjCMesh)
|
||||||
+ (sizeof(double) * vert_.size())
|
+ (sizeof(float) * vert_.size())
|
||||||
+ (sizeof(float) * normal_.size())
|
+ (sizeof(float) * normal_.size())
|
||||||
+ (sizeof(float) * texcoord_.size())
|
+ (sizeof(float) * texcoord_.size())
|
||||||
+ (sizeof(int) * face_.size())
|
+ (sizeof(int) * face_.size())
|
||||||
@@ -538,7 +538,7 @@ struct VertexKey {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// convert vertices to double precision and remove repeated vertices if requested
|
// process and remove repeated vertices if requested
|
||||||
void mjCMesh::ProcessVertices(const std::vector<float>& vert, bool remove_repeated) {
|
void mjCMesh::ProcessVertices(const std::vector<float>& vert, bool remove_repeated) {
|
||||||
vert_.clear();
|
vert_.clear();
|
||||||
int nvert = vert.size();
|
int nvert = vert.size();
|
||||||
@@ -775,24 +775,24 @@ void mjCMesh::TryCompile(const mjVFS* vfs) {
|
|||||||
// compute mesh properties
|
// compute mesh properties
|
||||||
if (!fromCache) {
|
if (!fromCache) {
|
||||||
Process();
|
Process();
|
||||||
}
|
|
||||||
|
|
||||||
// make octree
|
if (!file_.empty()) {
|
||||||
if (!needsdf) {
|
CacheMesh(cache, resource_);
|
||||||
octree_.Clear(); // this occurs when a non-SDF mesh is loaded from a cached SDF mesh
|
}
|
||||||
} else if (octree_.NumNodes() == 0) {
|
} else {
|
||||||
octree_.SetFace(vert_, face_);
|
// When a mesh is loaded from the cache, has no octree but needs one,
|
||||||
octree_.CreateOctree(aamm_);
|
// we need to compute it here. If inversely it has an octree but we *do not*
|
||||||
|
// need one, we clear it.
|
||||||
// compute sdf coefficients
|
if (!needsdf) {
|
||||||
if (!plugin.active) {
|
octree_.Clear();
|
||||||
octree_.ComputeSdfCoeffs(vert_.data(), nvert(), face_.data(), nface(), tree_);
|
} else if (octree_.NumNodes() == 0) {
|
||||||
|
std::vector<double> dvert(vert_.begin(), vert_.end());
|
||||||
|
octree_.SetFace(dvert, face_);
|
||||||
|
octree_.CreateOctree(aamm_);
|
||||||
|
if (!plugin.active) {
|
||||||
|
octree_.ComputeSdfCoeffs(dvert.data(), nvert(), face_.data(), nface(), tree_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// cache mesh
|
|
||||||
if (!fromCache && !file_.empty()) {
|
|
||||||
CacheMesh(cache, resource_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// close resource
|
// close resource
|
||||||
@@ -805,18 +805,18 @@ void mjCMesh::TryCompile(const mjVFS* vfs) {
|
|||||||
|
|
||||||
|
|
||||||
// get bounding volume
|
// get bounding volume
|
||||||
void mjCMesh::SetBoundingVolume(int faceid) {
|
void mjCMesh::SetBoundingVolume(int faceid, const double* dvert) {
|
||||||
constexpr double kMaxVal = std::numeric_limits<double>::max();
|
constexpr double kMaxVal = std::numeric_limits<double>::max();
|
||||||
double face_aamm[6] = {kMaxVal, kMaxVal, kMaxVal, -kMaxVal, -kMaxVal, -kMaxVal};
|
double face_aamm[6] = {kMaxVal, kMaxVal, kMaxVal, -kMaxVal, -kMaxVal, -kMaxVal};
|
||||||
|
|
||||||
for (int j = 0; j < 3; j++) {
|
for (int j = 0; j < 3; j++) {
|
||||||
int vertid = face_[3*faceid + j];
|
int vertid = face_[3*faceid + j];
|
||||||
face_aamm[0] = std::min(face_aamm[0], vert_[3*vertid + 0]);
|
face_aamm[0] = std::min(face_aamm[0], dvert[3*vertid + 0]);
|
||||||
face_aamm[1] = std::min(face_aamm[1], vert_[3*vertid + 1]);
|
face_aamm[1] = std::min(face_aamm[1], dvert[3*vertid + 1]);
|
||||||
face_aamm[2] = std::min(face_aamm[2], vert_[3*vertid + 2]);
|
face_aamm[2] = std::min(face_aamm[2], dvert[3*vertid + 2]);
|
||||||
face_aamm[3] = std::max(face_aamm[3], vert_[3*vertid + 0]);
|
face_aamm[3] = std::max(face_aamm[3], dvert[3*vertid + 0]);
|
||||||
face_aamm[4] = std::max(face_aamm[4], vert_[3*vertid + 1]);
|
face_aamm[4] = std::max(face_aamm[4], dvert[3*vertid + 1]);
|
||||||
face_aamm[5] = std::max(face_aamm[5], vert_[3*vertid + 2]);
|
face_aamm[5] = std::max(face_aamm[5], dvert[3*vertid + 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
face_aabb_.push_back(.5 * (face_aamm[0] + face_aamm[3]));
|
face_aabb_.push_back(.5 * (face_aamm[0] + face_aamm[3]));
|
||||||
@@ -851,9 +851,7 @@ bool mjCMesh::HasTexcoord() const {
|
|||||||
|
|
||||||
|
|
||||||
void mjCMesh::CopyVert(float* arr) const {
|
void mjCMesh::CopyVert(float* arr) const {
|
||||||
for (int i = 0; i < vert_.size(); ++i) {
|
std::copy(vert_.begin(), vert_.end(), arr);
|
||||||
arr[i] = (float)vert_[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1187,16 +1185,15 @@ void mjCMesh::LoadMSH(mjResource* resource, bool remove_repeated) {
|
|||||||
|
|
||||||
|
|
||||||
// compute the volume and center-of-mass of the mesh given the face centroid
|
// compute the volume and center-of-mass of the mesh given the face centroid
|
||||||
double mjCMesh::ComputeVolume(double CoM[3], const double facecen[3]) const {
|
double mjCMesh::ComputeVolume(double CoM[3], const double facecen[3], const double* dvert) const {
|
||||||
double normal[3], center[3], total_volume = 0;
|
double normal[3], center[3], total_volume = 0;
|
||||||
CoM[0] = CoM[1] = CoM[2] = 0;
|
CoM[0] = CoM[1] = CoM[2] = 0;
|
||||||
int nf = (inertia == mjMESH_INERTIA_CONVEX) ? graph_[1] : nface();
|
int nf = (inertia == mjMESH_INERTIA_CONVEX) ? graph_[1] : nface();
|
||||||
const int* f = (inertia == mjMESH_INERTIA_CONVEX) ? GraphFaces() : face_.data();
|
const int* f = (inertia == mjMESH_INERTIA_CONVEX) ? GraphFaces() : face_.data();
|
||||||
|
|
||||||
for (int i = 0; i < nf; i++) {
|
for (int i = 0; i < nf; i++) {
|
||||||
// get area, normal and center
|
double area = triangle(normal, center, &dvert[3*f[3*i]], &dvert[3*f[3*i + 1]],
|
||||||
double area = triangle(normal, center, &vert_[3*f[3*i]], &vert_[3*f[3*i + 1]],
|
&dvert[3*f[3*i + 2]]);
|
||||||
&vert_[3*f[3*i + 2]]);
|
|
||||||
|
|
||||||
// compute and add volume
|
// compute and add volume
|
||||||
double vec[3] = {center[0] - facecen[0], center[1] - facecen[1], center[2] - facecen[2]};
|
double vec[3] = {center[0] - facecen[0], center[1] - facecen[1], center[2] - facecen[2]};
|
||||||
@@ -1226,14 +1223,13 @@ double mjCMesh::ComputeVolume(double CoM[3], const double facecen[3]) const {
|
|||||||
|
|
||||||
|
|
||||||
// compute the surface area and center-of-mass of the mesh given the face centroid
|
// compute the surface area and center-of-mass of the mesh given the face centroid
|
||||||
double mjCMesh::ComputeSurfaceArea(double CoM[3], const double facecen[3]) const {
|
double mjCMesh::ComputeSurfaceArea(double CoM[3], const double facecen[3], const double* dvert) const {
|
||||||
double surface = 0;
|
double surface = 0;
|
||||||
CoM[0] = CoM[1] = CoM[2] = 0;
|
CoM[0] = CoM[1] = CoM[2] = 0;
|
||||||
for (int i = 0; i < nface(); i++) {
|
for (int i = 0; i < nface(); i++) {
|
||||||
// get area and center
|
|
||||||
double area, center[3];
|
double area, center[3];
|
||||||
area = triangle(nullptr, center, &vert_[3*face_[3*i]],
|
area = triangle(nullptr, center, &dvert[3*face_[3*i]],
|
||||||
&vert_[3*face_[3*i + 1]], &vert_[3*face_[3*i + 2]]);
|
&dvert[3*face_[3*i + 1]], &dvert[3*face_[3*i + 2]]);
|
||||||
|
|
||||||
// add pyramid com
|
// add pyramid com
|
||||||
surface += area;
|
surface += area;
|
||||||
@@ -1254,28 +1250,24 @@ double mjCMesh::ComputeSurfaceArea(double CoM[3], const double facecen[3]) const
|
|||||||
|
|
||||||
|
|
||||||
// apply transformations
|
// apply transformations
|
||||||
void mjCMesh::ApplyTransformations() {
|
void mjCMesh::ApplyTransformations(double* dvert) {
|
||||||
// translate
|
|
||||||
if (refpos[0] != 0 || refpos[1] != 0 || refpos[2] != 0) {
|
if (refpos[0] != 0 || refpos[1] != 0 || refpos[2] != 0) {
|
||||||
int nv = nvert();
|
int nv = nvert();
|
||||||
for (int i = 0; i < nv; i++) {
|
for (int i = 0; i < nv; i++) {
|
||||||
vert_[3*i + 0] -= refpos[0];
|
dvert[3*i + 0] -= refpos[0];
|
||||||
vert_[3*i + 1] -= refpos[1];
|
dvert[3*i + 1] -= refpos[1];
|
||||||
vert_[3*i + 2] -= refpos[2];
|
dvert[3*i + 2] -= refpos[2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rotate
|
|
||||||
if (refquat[0] != 1 || refquat[1] != 0 || refquat[2] != 0 || refquat[3] != 0) {
|
if (refquat[0] != 1 || refquat[1] != 0 || refquat[2] != 0 || refquat[3] != 0) {
|
||||||
// prepare rotation
|
|
||||||
double quat[4] = {refquat[0], refquat[1], refquat[2], refquat[3]};
|
double quat[4] = {refquat[0], refquat[1], refquat[2], refquat[3]};
|
||||||
double mat[9];
|
double mat[9];
|
||||||
mjuu_normvec(quat, 4);
|
mjuu_normvec(quat, 4);
|
||||||
mjuu_quat2mat(mat, quat);
|
mjuu_quat2mat(mat, quat);
|
||||||
|
|
||||||
// process vertices
|
|
||||||
for (int i = 0; i < nvert(); i++) {
|
for (int i = 0; i < nvert(); i++) {
|
||||||
mjuu_mulvecmatT(&vert_[3*i], &vert_[3*i], mat);
|
mjuu_mulvecmatT(&dvert[3*i], &dvert[3*i], mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// process normals
|
// process normals
|
||||||
@@ -1291,9 +1283,9 @@ void mjCMesh::ApplyTransformations() {
|
|||||||
// scale
|
// scale
|
||||||
if (scale[0] != 1 || scale[1] != 1 || scale[2] != 1) {
|
if (scale[0] != 1 || scale[1] != 1 || scale[2] != 1) {
|
||||||
for (int i = 0; i < nvert(); i++) {
|
for (int i = 0; i < nvert(); i++) {
|
||||||
vert_[3*i + 0] *= scale[0];
|
dvert[3*i + 0] *= scale[0];
|
||||||
vert_[3*i + 1] *= scale[1];
|
dvert[3*i + 1] *= scale[1];
|
||||||
vert_[3*i + 2] *= scale[2];
|
dvert[3*i + 2] *= scale[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < nnormal(); i++) {
|
for (int i = 0; i < nnormal(); i++) {
|
||||||
@@ -1325,14 +1317,13 @@ void mjCMesh::ApplyTransformations() {
|
|||||||
|
|
||||||
|
|
||||||
// find centroid of faces, return total area
|
// find centroid of faces, return total area
|
||||||
double mjCMesh::ComputeFaceCentroid(double facecen[3]) const {
|
double mjCMesh::ComputeFaceCentroid(double facecen[3], const double* dvert) const {
|
||||||
double total_area = 0;
|
double total_area = 0;
|
||||||
|
|
||||||
for (int i = 0; i < nface(); i++) {
|
for (int i = 0; i < nface(); i++) {
|
||||||
// get area and center
|
|
||||||
double area, center[3];
|
double area, center[3];
|
||||||
area = triangle(nullptr, center, &vert_[3*face_[3*i]],
|
area = triangle(nullptr, center, &dvert[3*face_[3*i]],
|
||||||
&vert_[3*face_[3*i + 1]], &vert_[3*face_[3*i + 2]]);
|
&dvert[3*face_[3*i + 1]], &dvert[3*face_[3*i + 2]]);
|
||||||
|
|
||||||
// accumulate
|
// accumulate
|
||||||
facecen[0] += area * center[0];
|
facecen[0] += area * center[0];
|
||||||
@@ -1353,13 +1344,15 @@ double mjCMesh::ComputeFaceCentroid(double facecen[3]) const {
|
|||||||
|
|
||||||
|
|
||||||
void mjCMesh::Process() {
|
void mjCMesh::Process() {
|
||||||
|
std::vector<double> dvert(vert_.begin(), vert_.end());
|
||||||
|
|
||||||
// create half-edge structure (if mesh was in XML)
|
// create half-edge structure (if mesh was in XML)
|
||||||
if (halfedge_.empty()) {
|
if (halfedge_.empty()) {
|
||||||
for (int i = 0; i < nface(); i++) {
|
for (int i = 0; i < nface(); i++) {
|
||||||
int v0 = face_[3*i + 0];
|
int v0 = face_[3*i + 0];
|
||||||
int v1 = face_[3*i + 1];
|
int v1 = face_[3*i + 1];
|
||||||
int v2 = face_[3*i + 2];
|
int v2 = face_[3*i + 2];
|
||||||
if (triangle(nullptr, nullptr, &vert_[3*v0], &vert_[3*v1], &vert_[3*v2]) > sqrt(mjMINVAL)) {
|
if (triangle(nullptr, nullptr, &dvert[3*v0], &dvert[3*v1], &dvert[3*v2]) > sqrt(mjMINVAL)) {
|
||||||
halfedge_.push_back({v0, v1});
|
halfedge_.push_back({v0, v1});
|
||||||
halfedge_.push_back({v1, v2});
|
halfedge_.push_back({v1, v2});
|
||||||
halfedge_.push_back({v2, v0});
|
halfedge_.push_back({v2, v0});
|
||||||
@@ -1383,7 +1376,7 @@ void mjCMesh::Process() {
|
|||||||
|
|
||||||
// make graph describing convex hull
|
// make graph describing convex hull
|
||||||
if (needhull_ || face_.empty()) {
|
if (needhull_ || face_.empty()) {
|
||||||
MakeGraph();
|
MakeGraph(dvert.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
// no faces: copy from convex hull
|
// no faces: copy from convex hull
|
||||||
@@ -1393,7 +1386,7 @@ void mjCMesh::Process() {
|
|||||||
|
|
||||||
// no normals: make
|
// no normals: make
|
||||||
if (normal_.empty()) {
|
if (normal_.empty()) {
|
||||||
MakeNormal();
|
MakeNormal(dvert.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
// check facenormal size
|
// check facenormal size
|
||||||
@@ -1416,7 +1409,7 @@ void mjCMesh::Process() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (szgraph_) {
|
if (szgraph_) {
|
||||||
MakePolygons();
|
MakePolygons(dvert.data());
|
||||||
} else {
|
} else {
|
||||||
polygon_map_.resize(nvert());
|
polygon_map_.resize(nvert());
|
||||||
}
|
}
|
||||||
@@ -1436,11 +1429,11 @@ void mjCMesh::Process() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// user offset, rotation, scaling
|
// user offset, rotation, scaling
|
||||||
ApplyTransformations();
|
ApplyTransformations(dvert.data());
|
||||||
|
|
||||||
// find centroid of faces
|
// find centroid of faces
|
||||||
double facecen[3] = {0, 0, 0};
|
double facecen[3] = {0, 0, 0};
|
||||||
if (ComputeFaceCentroid(facecen) < mjMINVAL) {
|
if (ComputeFaceCentroid(facecen, dvert.data()) < mjMINVAL) {
|
||||||
throw mjCError(this, "mesh surface area is too small: %s", name.c_str());
|
throw mjCError(this, "mesh surface area is too small: %s", name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1451,12 +1444,12 @@ void mjCMesh::Process() {
|
|||||||
|
|
||||||
// compute CoM and volume/area
|
// compute CoM and volume/area
|
||||||
if (inertia == mjMESH_INERTIA_SHELL) {
|
if (inertia == mjMESH_INERTIA_SHELL) {
|
||||||
surface_ = ComputeSurfaceArea(CoM, facecen);
|
surface_ = ComputeSurfaceArea(CoM, facecen, dvert.data());
|
||||||
if (surface_ < mjMINVAL) {
|
if (surface_ < mjMINVAL) {
|
||||||
throw mjCError(this, "mesh surface area is too small: %s", name.c_str());
|
throw mjCError(this, "mesh surface area is too small: %s", name.c_str());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((volume_ = ComputeVolume(CoM, facecen)) < mjMINVAL) {
|
if ((volume_ = ComputeVolume(CoM, facecen, dvert.data())) < mjMINVAL) {
|
||||||
if (volume_ < 0) {
|
if (volume_ < 0) {
|
||||||
throw mjCError(this, "mesh volume is negative (misoriented triangles): %s", name.c_str());
|
throw mjCError(this, "mesh volume is negative (misoriented triangles): %s", name.c_str());
|
||||||
} else {
|
} else {
|
||||||
@@ -1467,7 +1460,7 @@ void mjCMesh::Process() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute inertia
|
// compute inertia
|
||||||
double total_volume = ComputeInertia(inert, CoM);
|
double total_volume = ComputeInertia(inert, CoM, dvert.data());
|
||||||
if (inertia == mjMESH_INERTIA_SHELL) {
|
if (inertia == mjMESH_INERTIA_SHELL) {
|
||||||
surface_ = total_volume;
|
surface_ = total_volume;
|
||||||
} else {
|
} else {
|
||||||
@@ -1511,11 +1504,11 @@ void mjCMesh::Process() {
|
|||||||
|
|
||||||
// transform CoM to origin
|
// transform CoM to origin
|
||||||
for (int i=0; i < nvert(); i++) {
|
for (int i=0; i < nvert(); i++) {
|
||||||
vert_[3*i + 0] -= CoM[0];
|
dvert[3*i + 0] -= CoM[0];
|
||||||
vert_[3*i + 1] -= CoM[1];
|
dvert[3*i + 1] -= CoM[1];
|
||||||
vert_[3*i + 2] -= CoM[2];
|
dvert[3*i + 2] -= CoM[2];
|
||||||
}
|
}
|
||||||
Rotate(quattmp);
|
Rotate(quattmp, dvert.data());
|
||||||
|
|
||||||
// save the pos and quat that was used to transform the mesh
|
// save the pos and quat that was used to transform the mesh
|
||||||
mjuu_copyvec(pos_, CoM, 3);
|
mjuu_copyvec(pos_, CoM, 3);
|
||||||
@@ -1525,11 +1518,11 @@ void mjCMesh::Process() {
|
|||||||
|
|
||||||
// no radii: make
|
// no radii: make
|
||||||
if (!center_) {
|
if (!center_) {
|
||||||
MakeCenter();
|
MakeCenter(dvert.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
// recompute polygon normals
|
// recompute polygon normals
|
||||||
MakePolygonNormals();
|
MakePolygonNormals(dvert.data());
|
||||||
|
|
||||||
// make bounding volume hierarchy
|
// make bounding volume hierarchy
|
||||||
if (tree_.Bvh().empty()) {
|
if (tree_.Bvh().empty()) {
|
||||||
@@ -1537,16 +1530,31 @@ void mjCMesh::Process() {
|
|||||||
face_aabb_.reserve(3*face_.size());
|
face_aabb_.reserve(3*face_.size());
|
||||||
tree_.AllocateBoundingVolumes(nface());
|
tree_.AllocateBoundingVolumes(nface());
|
||||||
for (int i = 0; i < nface(); i++) {
|
for (int i = 0; i < nface(); i++) {
|
||||||
SetBoundingVolume(i);
|
SetBoundingVolume(i, dvert.data());
|
||||||
}
|
}
|
||||||
tree_.CreateBVH();
|
tree_.CreateBVH();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// make octree
|
||||||
|
if (needsdf) {
|
||||||
|
octree_.SetFace(dvert, face_);
|
||||||
|
octree_.CreateOctree(aamm_);
|
||||||
|
|
||||||
|
if (!plugin.active) {
|
||||||
|
octree_.ComputeSdfCoeffs(dvert.data(), nvert(), face_.data(), nface(), tree_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// narrow back to float
|
||||||
|
for (int i = 0; i < (int)dvert.size(); i++) {
|
||||||
|
vert_[i] = (float)dvert[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// compute abstract (unitless) inertia, recompute area / volume
|
// compute abstract (unitless) inertia, recompute area / volume
|
||||||
double mjCMesh::ComputeInertia(double inert[6], const double CoM[3]) const {
|
double mjCMesh::ComputeInertia(double inert[6], const double CoM[3], const double* dvert) const {
|
||||||
double total_volume = 0;
|
double total_volume = 0;
|
||||||
|
|
||||||
// copy vertices to avoid modifying the original mesh
|
// copy vertices to avoid modifying the original mesh
|
||||||
@@ -1555,9 +1563,9 @@ double mjCMesh::ComputeInertia(double inert[6], const double CoM[3]) const {
|
|||||||
|
|
||||||
// translate vertices to origin in order to compute inertia
|
// translate vertices to origin in order to compute inertia
|
||||||
for (int i = 0; i < nvert(); i++) {
|
for (int i = 0; i < nvert(); i++) {
|
||||||
vert_centered.push_back(vert_[3*i + 0] - CoM[0]);
|
vert_centered.push_back(dvert[3*i + 0] - CoM[0]);
|
||||||
vert_centered.push_back(vert_[3*i + 1] - CoM[1]);
|
vert_centered.push_back(dvert[3*i + 1] - CoM[1]);
|
||||||
vert_centered.push_back(vert_[3*i + 2] - CoM[2]);
|
vert_centered.push_back(dvert[3*i + 2] - CoM[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// accumulate products of inertia, recompute volume
|
// accumulate products of inertia, recompute volume
|
||||||
@@ -1612,22 +1620,20 @@ double mjCMesh::ComputeInertia(double inert[6], const double CoM[3]) const {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void mjCMesh::Rotate(double quat[4]) {
|
void mjCMesh::Rotate(double quat[4], double* dvert) {
|
||||||
// rotate vertices and normals of mesh by quaternion
|
|
||||||
double neg[4] = {quat[0], -quat[1], -quat[2], -quat[3]};
|
double neg[4] = {quat[0], -quat[1], -quat[2], -quat[3]};
|
||||||
double mat[9];
|
double mat[9];
|
||||||
mjuu_quat2mat(mat, neg);
|
mjuu_quat2mat(mat, neg);
|
||||||
int nv = nvert();
|
int nv = nvert();
|
||||||
for (int i = 0; i < nv; i++) {
|
for (int i = 0; i < nv; i++) {
|
||||||
mjuu_mulvecmat(&vert_[3*i], &vert_[3*i], mat);
|
mjuu_mulvecmat(&dvert[3*i], &dvert[3*i], mat);
|
||||||
|
|
||||||
// axis-aligned bounding box
|
aamm_[0] = std::min(aamm_[0], dvert[3*i + 0]);
|
||||||
aamm_[0] = std::min(aamm_[0], vert_[3*i + 0]);
|
aamm_[3] = std::max(aamm_[3], dvert[3*i + 0]);
|
||||||
aamm_[3] = std::max(aamm_[3], vert_[3*i + 0]);
|
aamm_[1] = std::min(aamm_[1], dvert[3*i + 1]);
|
||||||
aamm_[1] = std::min(aamm_[1], vert_[3*i + 1]);
|
aamm_[4] = std::max(aamm_[4], dvert[3*i + 1]);
|
||||||
aamm_[4] = std::max(aamm_[4], vert_[3*i + 1]);
|
aamm_[2] = std::min(aamm_[2], dvert[3*i + 2]);
|
||||||
aamm_[2] = std::min(aamm_[2], vert_[3*i + 2]);
|
aamm_[5] = std::max(aamm_[5], dvert[3*i + 2]);
|
||||||
aamm_[5] = std::max(aamm_[5], vert_[3*i + 2]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i < nnormal(); i++) {
|
for (int i=0; i < nnormal(); i++) {
|
||||||
@@ -1699,7 +1705,7 @@ double mjCMesh::GetVolumeRef() const {
|
|||||||
|
|
||||||
|
|
||||||
// make graph describing convex hull
|
// make graph describing convex hull
|
||||||
void mjCMesh::MakeGraph() {
|
void mjCMesh::MakeGraph(const double* dvert) {
|
||||||
int adr, ok, curlong, totlong, exitcode;
|
int adr, ok, curlong, totlong, exitcode;
|
||||||
facetT* facet, **facetp;
|
facetT* facet, **facetp;
|
||||||
vertexT* vertex, *vertex1, **vertex1p;
|
vertexT* vertex, *vertex1, **vertex1p;
|
||||||
@@ -1728,7 +1734,7 @@ void mjCMesh::MakeGraph() {
|
|||||||
if (!exitcode) {
|
if (!exitcode) {
|
||||||
// actual init
|
// actual init
|
||||||
qh_initflags(qh, const_cast<char*>(qhopt.c_str()));
|
qh_initflags(qh, const_cast<char*>(qhopt.c_str()));
|
||||||
qh_init_B(qh, vert_.data(), nvert(), 3, qh_False);
|
qh_init_B(qh, const_cast<double*>(dvert), nvert(), 3, qh_False);
|
||||||
|
|
||||||
// construct convex hull
|
// construct convex hull
|
||||||
qh_qhull(qh);
|
qh_qhull(qh);
|
||||||
@@ -2403,7 +2409,7 @@ void mjCMesh::MakeCone(int nedge, double radius) {
|
|||||||
|
|
||||||
|
|
||||||
// compute vertex normals
|
// compute vertex normals
|
||||||
void mjCMesh::MakeNormal() {
|
void mjCMesh::MakeNormal(const double* dvert) {
|
||||||
// only if normal data is missing
|
// only if normal data is missing
|
||||||
if (!normal_.empty()) {
|
if (!normal_.empty()) {
|
||||||
return;
|
return;
|
||||||
@@ -2427,8 +2433,8 @@ void mjCMesh::MakeNormal() {
|
|||||||
// get triangle edges
|
// get triangle edges
|
||||||
double vec01[3], vec02[3];
|
double vec01[3], vec02[3];
|
||||||
for (int j=0; j < 3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
vec01[j] = vert_[3*vertid[1]+j] - vert_[3*vertid[0]+j];
|
vec01[j] = dvert[3*vertid[1]+j] - dvert[3*vertid[0]+j];
|
||||||
vec02[j] = vert_[3*vertid[2]+j] - vert_[3*vertid[0]+j];
|
vec02[j] = dvert[3*vertid[2]+j] - dvert[3*vertid[0]+j];
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute face normal
|
// compute face normal
|
||||||
@@ -2462,8 +2468,8 @@ void mjCMesh::MakeNormal() {
|
|||||||
// get triangle edges
|
// get triangle edges
|
||||||
double vec01[3], vec02[3];
|
double vec01[3], vec02[3];
|
||||||
for (int j=0; j < 3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
vec01[j] = vert_[3*vertid[1]+j] - vert_[3*vertid[0]+j];
|
vec01[j] = dvert[3*vertid[1]+j] - dvert[3*vertid[0]+j];
|
||||||
vec02[j] = vert_[3*vertid[2]+j] - vert_[3*vertid[0]+j];
|
vec02[j] = dvert[3*vertid[2]+j] - dvert[3*vertid[0]+j];
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute face normal
|
// compute face normal
|
||||||
@@ -2515,7 +2521,7 @@ void mjCMesh::MakeNormal() {
|
|||||||
|
|
||||||
|
|
||||||
// compute face circumradii
|
// compute face circumradii
|
||||||
void mjCMesh::MakeCenter() {
|
void mjCMesh::MakeCenter(const double* dvert) {
|
||||||
if (center_) {
|
if (center_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2531,8 +2537,8 @@ void mjCMesh::MakeCenter() {
|
|||||||
// get triangle edges
|
// get triangle edges
|
||||||
double a[3], b[3];
|
double a[3], b[3];
|
||||||
for (int j=0; j < 3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
a[j] = vert_[3*vertid[0]+j] - vert_[3*vertid[2]+j];
|
a[j] = dvert[3*vertid[0]+j] - dvert[3*vertid[2]+j];
|
||||||
b[j] = vert_[3*vertid[1]+j] - vert_[3*vertid[2]+j];
|
b[j] = dvert[3*vertid[1]+j] - dvert[3*vertid[2]+j];
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute face normal
|
// compute face normal
|
||||||
@@ -2551,20 +2557,20 @@ void mjCMesh::MakeCenter() {
|
|||||||
norm_a_2 * b[2] - norm_b_2 * a[2]
|
norm_a_2 * b[2] - norm_b_2 * a[2]
|
||||||
};
|
};
|
||||||
mjuu_crossvec(res, vec, nrm);
|
mjuu_crossvec(res, vec, nrm);
|
||||||
center_[3*i+0] = res[0]/(2*area*area) + vert_[3*vertid[2]+0];
|
center_[3*i+0] = res[0]/(2*area*area) + dvert[3*vertid[2]+0];
|
||||||
center_[3*i+1] = res[1]/(2*area*area) + vert_[3*vertid[2]+1];
|
center_[3*i+1] = res[1]/(2*area*area) + dvert[3*vertid[2]+1];
|
||||||
center_[3*i+2] = res[2]/(2*area*area) + vert_[3*vertid[2]+2];
|
center_[3*i+2] = res[2]/(2*area*area) + dvert[3*vertid[2]+2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// compute the normals of the polygons
|
// compute the normals of the polygons
|
||||||
void mjCMesh::MakePolygonNormals() {
|
void mjCMesh::MakePolygonNormals(const double* dvert) {
|
||||||
for (int i = 0; i < polygons_.size(); ++i) {
|
for (int i = 0; i < polygons_.size(); ++i) {
|
||||||
double n[3];
|
double n[3];
|
||||||
mjuu_makenormal(n, &vert_[3*polygons_[i][0]], &vert_[3*polygons_[i][1]],
|
mjuu_makenormal(n, &dvert[3*polygons_[i][0]], &dvert[3*polygons_[i][1]],
|
||||||
&vert_[3*polygons_[i][2]]);
|
&dvert[3*polygons_[i][2]]);
|
||||||
polygon_normals_[3*i + 0] = n[0];
|
polygon_normals_[3*i + 0] = n[0];
|
||||||
polygon_normals_[3*i + 1] = n[1];
|
polygon_normals_[3*i + 1] = n[1];
|
||||||
polygon_normals_[3*i + 2] = n[2];
|
polygon_normals_[3*i + 2] = n[2];
|
||||||
@@ -2803,7 +2809,7 @@ struct PairHash {
|
|||||||
|
|
||||||
|
|
||||||
// merge coplanar mesh triangular faces into polygonal sides to represent the geometry of the mesh
|
// merge coplanar mesh triangular faces into polygonal sides to represent the geometry of the mesh
|
||||||
void mjCMesh::MakePolygons() {
|
void mjCMesh::MakePolygons(const double* dvert) {
|
||||||
constexpr double kAngleTol = 0.01;
|
constexpr double kAngleTol = 0.01;
|
||||||
std::unordered_map<std::pair<double, double>, MeshPolygon, PairHash> mesh_polygons;
|
std::unordered_map<std::pair<double, double>, MeshPolygon, PairHash> mesh_polygons;
|
||||||
polygons_.clear();
|
polygons_.clear();
|
||||||
@@ -2820,9 +2826,9 @@ void mjCMesh::MakePolygons() {
|
|||||||
int vi1 = faces[3*i + 0];
|
int vi1 = faces[3*i + 0];
|
||||||
int vi2 = faces[3*i + 1];
|
int vi2 = faces[3*i + 1];
|
||||||
int vi3 = faces[3*i + 2];
|
int vi3 = faces[3*i + 2];
|
||||||
double* v1 = &vert_[3*vi1];
|
const double* v1 = &dvert[3*vi1];
|
||||||
double* v2 = &vert_[3*vi2];
|
const double* v2 = &dvert[3*vi2];
|
||||||
double* v3 = &vert_[3*vi3];
|
const double* v3 = &dvert[3*vi3];
|
||||||
|
|
||||||
std::pair<double, double> key;
|
std::pair<double, double> key;
|
||||||
if (!MeshPolygonKey(key, v1, v2, v3, kAngleTol)) {
|
if (!MeshPolygonKey(key, v1, v2, v3, kAngleTol)) {
|
||||||
|
|||||||
@@ -587,6 +587,7 @@ void mjCOctree::CopyCoeff(mjtNum* coeff) const {
|
|||||||
|
|
||||||
|
|
||||||
void mjCOctree::SetFace(const std::vector<double>& vert, const std::vector<int>& face) {
|
void mjCOctree::SetFace(const std::vector<double>& vert, const std::vector<int>& face) {
|
||||||
|
face_.reserve(face.size()/3);
|
||||||
for (int i = 0; i < face.size(); i += 3) {
|
for (int i = 0; i < face.size(); i += 3) {
|
||||||
std::array<double, 3> v0 = {vert[3*face[i+0]], vert[3*face[i+0]+1], vert[3*face[i+0]+2]};
|
std::array<double, 3> v0 = {vert[3*face[i+0]], vert[3*face[i+0]+1], vert[3*face[i+0]+2]};
|
||||||
std::array<double, 3> v1 = {vert[3*face[i+1]], vert[3*face[i+1]+1], vert[3*face[i+1]+2]};
|
std::array<double, 3> v1 = {vert[3*face[i+1]], vert[3*face[i+1]+1], vert[3*face[i+1]+2]};
|
||||||
@@ -613,6 +614,8 @@ void mjCOctree::Make(std::vector<Triangle>& elements) {
|
|||||||
|
|
||||||
|
|
||||||
void mjCOctree::CreateOctree(const double aamm[6]) {
|
void mjCOctree::CreateOctree(const double aamm[6]) {
|
||||||
|
Clear();
|
||||||
|
|
||||||
double aabb[6] = {(aamm[0] + aamm[3]) / 2, (aamm[1] + aamm[4]) / 2, (aamm[2] + aamm[5]) / 2,
|
double aabb[6] = {(aamm[0] + aamm[3]) / 2, (aamm[1] + aamm[4]) / 2, (aamm[2] + aamm[5]) / 2,
|
||||||
(aamm[3] - aamm[0]) / 2, (aamm[4] - aamm[1]) / 2, (aamm[5] - aamm[2]) / 2};
|
(aamm[3] - aamm[0]) / 2, (aamm[4] - aamm[1]) / 2, (aamm[5] - aamm[2]) / 2};
|
||||||
double box[6] = {aabb[0] - 1.1 * aabb[3], aabb[1] - 1.1 * aabb[4], aabb[2] - 1.1 * aabb[5],
|
double box[6] = {aabb[0] - 1.1 * aabb[3], aabb[1] - 1.1 * aabb[4], aabb[2] - 1.1 * aabb[5],
|
||||||
|
|||||||
+19
-17
@@ -299,8 +299,11 @@ class mjCOctree : public mjCOctree_ {
|
|||||||
sizeof(Point) * vert_.size();
|
sizeof(Point) * vert_.size();
|
||||||
}
|
}
|
||||||
void Clear() {
|
void Clear() {
|
||||||
|
nnode_ = 0;
|
||||||
|
nvert_ = 0;
|
||||||
node_.clear();
|
node_.clear();
|
||||||
face_.clear();
|
vert_.clear();
|
||||||
|
hang_.clear();
|
||||||
}
|
}
|
||||||
void AddCoeff(int n, int v, double coeff) { node_[n].coeff[v] = coeff; }
|
void AddCoeff(int n, int v, double coeff) { node_[n].coeff[v] = coeff; }
|
||||||
double Coeff(int n, int v) const { return node_[n].coeff[v]; }
|
double Coeff(int n, int v) const { return node_[n].coeff[v]; }
|
||||||
@@ -1071,7 +1074,7 @@ class mjCMesh_ : public mjCBase {
|
|||||||
std::string content_type_ = ""; // content type of file
|
std::string content_type_ = ""; // content type of file
|
||||||
std::string file_; // mesh file
|
std::string file_; // mesh file
|
||||||
mjResource* resource_ = nullptr; // resource for mesh file
|
mjResource* resource_ = nullptr; // resource for mesh file
|
||||||
std::vector<double> vert_; // vertex data
|
std::vector<float> vert_; // vertex data
|
||||||
std::vector<float> normal_; // normal data
|
std::vector<float> normal_; // normal data
|
||||||
std::vector<float> texcoord_; // texcoord data
|
std::vector<float> texcoord_; // texcoord data
|
||||||
std::vector<int> face_; // vertex indices
|
std::vector<int> face_; // vertex indices
|
||||||
@@ -1156,8 +1159,8 @@ class mjCMesh: public mjCMesh_, private mjsMesh {
|
|||||||
const double* Refquat() const { return refquat; }
|
const double* Refquat() const { return refquat; }
|
||||||
const double* Scale() const { return scale; }
|
const double* Scale() const { return scale; }
|
||||||
bool SmoothNormal() const { return smoothnormal; }
|
bool SmoothNormal() const { return smoothnormal; }
|
||||||
const std::vector<double>& Vert() const { return vert_; }
|
const std::vector<float>& Vert() const { return vert_; }
|
||||||
double Vert(int i) const { return vert_[i]; }
|
float Vert(int i) const { return vert_[i]; }
|
||||||
const std::vector<float>& UserVert() const { return spec_vert_; }
|
const std::vector<float>& UserVert() const { return spec_vert_; }
|
||||||
const std::vector<float>& UserNormal() const { return spec_normal_; }
|
const std::vector<float>& UserNormal() const { return spec_normal_; }
|
||||||
const std::vector<float>& Texcoord() const { return texcoord_; }
|
const std::vector<float>& Texcoord() const { return texcoord_; }
|
||||||
@@ -1233,7 +1236,7 @@ class mjCMesh: public mjCMesh_, private mjsMesh {
|
|||||||
void CopyPolygonNormals(mjtNum* arr);
|
void CopyPolygonNormals(mjtNum* arr);
|
||||||
|
|
||||||
// sets properties of a bounding volume given a face id
|
// sets properties of a bounding volume given a face id
|
||||||
void SetBoundingVolume(int faceid);
|
void SetBoundingVolume(int faceid, const double* dvert);
|
||||||
|
|
||||||
// load from OBJ, STL, or MSH file; throws mjCError on failure
|
// load from OBJ, STL, or MSH file; throws mjCError on failure
|
||||||
void LoadFromResource(mjResource* resource, bool remove_repeated = false);
|
void LoadFromResource(mjResource* resource, bool remove_repeated = false);
|
||||||
@@ -1264,22 +1267,22 @@ class mjCMesh: public mjCMesh_, private mjsMesh {
|
|||||||
void LoadMSH(mjResource* resource, bool remove_repeated); // load mesh in MSH BIN format
|
void LoadMSH(mjResource* resource, bool remove_repeated); // load mesh in MSH BIN format
|
||||||
|
|
||||||
void LoadSDF(); // generate mesh using marching cubes
|
void LoadSDF(); // generate mesh using marching cubes
|
||||||
void MakeGraph(); // make graph of convex hull
|
void MakeGraph(const double* dvert); // make graph of convex hull
|
||||||
void CopyGraph(); // copy graph into face data
|
void CopyGraph(); // copy graph into face data
|
||||||
void MakeNormal(); // compute vertex normals
|
void MakeNormal(const double* dvert); // compute vertex normals
|
||||||
void MakeCenter(); // compute face circumcircle data
|
void MakeCenter(const double* dvert); // compute face circumcircle data
|
||||||
void Process(); // compute inertial properties
|
void Process(); // compute inertial properties
|
||||||
void ApplyTransformations(); // apply user transformations
|
void ApplyTransformations(double* dvert); // apply user transformations
|
||||||
double ComputeFaceCentroid(double[3]) const; // compute centroid of all faces
|
double ComputeFaceCentroid(double[3], const double* dvert) const;
|
||||||
void CheckInitialMesh() const; // check if initial mesh is valid
|
void CheckInitialMesh() const; // check if initial mesh is valid
|
||||||
void CopyPlugin();
|
void CopyPlugin();
|
||||||
void Rotate(double quat[4]); // rotate mesh by quaternion
|
void Rotate(double quat[4], double* dvert); // rotate mesh by quaternion
|
||||||
void Transform(double pos[3], double quat[4]); // transform mesh by position and quaternion
|
void Transform(double pos[3], double quat[4]); // transform mesh by position and quaternion
|
||||||
void MakePolygons(); // compute the polygon sides of the mesh
|
void MakePolygons(const double* dvert); // compute the polygon sides of the mesh
|
||||||
void MakePolygonNormals(); // compute the normals of the polygons
|
void MakePolygonNormals(const double* dvert); // compute the normals of the polygons
|
||||||
|
|
||||||
// computes the inertia matrix of the mesh given the type of inertia
|
// computes the inertia matrix of the mesh given the type of inertia
|
||||||
double ComputeInertia(double inert[6], const double CoM[3]) const;
|
double ComputeInertia(double inert[6], const double CoM[3], const double* dvert) const;
|
||||||
|
|
||||||
int* GraphFaces() const {
|
int* GraphFaces() const {
|
||||||
return graph_ + 2 + 3*(graph_[0] + graph_[1]);
|
return graph_ + 2 + 3*(graph_[0] + graph_[1]);
|
||||||
@@ -1295,9 +1298,8 @@ class mjCMesh: public mjCMesh_, private mjsMesh {
|
|||||||
std::vector<std::vector<int>> polygon_map_; // map from vertex to polygon
|
std::vector<std::vector<int>> polygon_map_; // map from vertex to polygon
|
||||||
|
|
||||||
// compute the volume and center-of-mass of the mesh given the face centroid
|
// compute the volume and center-of-mass of the mesh given the face centroid
|
||||||
double ComputeVolume(double CoM[3], const double facecen[3]) const;
|
double ComputeVolume(double CoM[3], const double facecen[3], const double* dvert) const;
|
||||||
// compute the surface area and center-of-mass of the mesh given the face centroid
|
double ComputeSurfaceArea(double CoM[3], const double facecen[3], const double* dvert) const;
|
||||||
double ComputeSurfaceArea(double CoM[3], const double facecen[3]) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user