Add mjmSkin to C API.
PiperOrigin-RevId: 607295996 Change-Id: I63bf7213d41acbfb98770c097979ce9b889f21ca
This commit is contained in:
committed by
Copybara-Service
parent
bafe490ea8
commit
6f958bc404
+33
-4
@@ -156,6 +156,15 @@ mjmHField* mjm_addHField(void* model) {
|
||||
|
||||
|
||||
|
||||
// add skin to model
|
||||
mjmSkin* mjm_addSkin(void* model) {
|
||||
mjCModel* modelC = static_cast<mjCModel*>(model);
|
||||
mjCSkin* skin = modelC->AddSkin();
|
||||
return &skin->spec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// add texture to model
|
||||
mjmTexture* mjm_addTexture(void* model) {
|
||||
mjCModel* modelC = static_cast<mjCModel*>(model);
|
||||
@@ -370,6 +379,7 @@ int mjm_getId(mjElement element) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// set default
|
||||
void mjm_setDefault(mjElement element, void* defspec) {
|
||||
mjCBase* baseC = reinterpret_cast<mjCBase*>(element);
|
||||
@@ -377,6 +387,7 @@ void mjm_setDefault(mjElement element, void* defspec) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// set string
|
||||
void mjm_setString(mjString dest, const char* text) {
|
||||
std::string* str = reinterpret_cast<std::string*>(dest);
|
||||
@@ -405,14 +416,15 @@ void mjm_setStringVec(mjStringVec dest, const char* text) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// add text entry to destination string vector
|
||||
void mjm_addToStringVec(mjStringVec dest, const char* text) {
|
||||
void mjm_appendString(mjStringVec dest, const char* text) {
|
||||
std::vector<std::string>* v = reinterpret_cast<std::vector<std::string>*>(dest);
|
||||
v->push_back(std::string(text));
|
||||
}
|
||||
|
||||
|
||||
// set int array
|
||||
// copy int array to vector
|
||||
void mjm_setInt(mjIntVec dest, const int* array, int size) {
|
||||
std::vector<int>* v = reinterpret_cast<std::vector<int>*>(dest);
|
||||
v->assign(size, 0.0);
|
||||
@@ -423,7 +435,15 @@ void mjm_setInt(mjIntVec dest, const int* array, int size) {
|
||||
|
||||
|
||||
|
||||
// set float array
|
||||
// append int array to vector of arrays
|
||||
void mjm_appendIntVec(mjIntVecVec dest, const int* array, int size) {
|
||||
std::vector<std::vector<int>>* v = reinterpret_cast<std::vector<std::vector<int>>*>(dest);
|
||||
v->push_back(std::vector<int>(array, array + size));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// copy float array to vector
|
||||
void mjm_setFloat(mjFloatVec dest, const float* array, int size) {
|
||||
std::vector<float>* v = reinterpret_cast<std::vector<float>*>(dest);
|
||||
v->assign(size, 0.0);
|
||||
@@ -434,7 +454,16 @@ void mjm_setFloat(mjFloatVec dest, const float* array, int size) {
|
||||
|
||||
|
||||
|
||||
// set double array
|
||||
|
||||
// append float array to vector of arrays
|
||||
void mjm_appendFloatVec(mjFloatVecVec dest, const float* array, int size) {
|
||||
std::vector<std::vector<float>>* v = reinterpret_cast<std::vector<std::vector<float>>*>(dest);
|
||||
v->push_back(std::vector<float>(array, array + size));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// copy double array to vector
|
||||
void mjm_setDouble(mjDoubleVec dest, const double* array, int size) {
|
||||
std::vector<double>* v = reinterpret_cast<std::vector<double>*>(dest);
|
||||
v->assign(size, 0.0);
|
||||
|
||||
+51
-9
@@ -32,8 +32,10 @@ typedef struct _mjElement* mjElement;
|
||||
typedef struct _mjString* mjString;
|
||||
typedef struct _mjStringVec* mjStringVec;
|
||||
typedef struct _mjIntVec* mjIntVec;
|
||||
typedef struct _mjDoubleVec* mjDoubleVec;
|
||||
typedef struct _mjIntVecVec* mjIntVecVec;
|
||||
typedef struct _mjFloatVec* mjFloatVec;
|
||||
typedef struct _mjFloatVecVec* mjFloatVecVec;
|
||||
typedef struct _mjDoubleVec* mjDoubleVec;
|
||||
|
||||
|
||||
//---------------------------------- enum types (mjt) ----------------------------------------------
|
||||
@@ -366,6 +368,34 @@ typedef struct _mjmHField { // height field specification
|
||||
} mjmHField;
|
||||
|
||||
|
||||
|
||||
typedef struct _mjmSkin { // skin specification
|
||||
mjElement element; // internal, do not modify
|
||||
mjString name; // name
|
||||
mjString classname; // class name
|
||||
mjString file; // skin file
|
||||
mjString material; // name of material used for rendering
|
||||
float rgba[4]; // rgba when material is omitted
|
||||
float inflate; // inflate in normal direction
|
||||
int group; // group for visualization
|
||||
|
||||
// mesh
|
||||
mjFloatVec vert; // vertex positions
|
||||
mjFloatVec texcoord; // texture coordinates
|
||||
mjIntVec face; // faces
|
||||
|
||||
// skin
|
||||
mjStringVec bodyname; // body names
|
||||
mjFloatVec bindpos; // bind pos
|
||||
mjFloatVec bindquat; // bind quat
|
||||
mjIntVecVec vertid; // vertex ids
|
||||
mjFloatVecVec vertweight; // vertex weights
|
||||
|
||||
// other
|
||||
mjString info; // message appended to compiler errors
|
||||
} mjmSkin;
|
||||
|
||||
|
||||
typedef struct _mjmTexture { // texture specification
|
||||
mjElement element; // internal, do not modify
|
||||
mjString name; // name
|
||||
@@ -655,6 +685,9 @@ MJAPI mjmMesh* mjm_addMesh(void* model, void* defspec);
|
||||
// Add height field to model.
|
||||
MJAPI mjmHField* mjm_addHField(void* model);
|
||||
|
||||
// Add skin to model.
|
||||
MJAPI mjmSkin* mjm_addSkin(void* model);
|
||||
|
||||
// Add texture to model.
|
||||
MJAPI mjmTexture* mjm_addTexture(void* model);
|
||||
|
||||
@@ -721,25 +754,31 @@ MJAPI mjmBody* mjm_findChild(mjmBody* body, const char* name);
|
||||
// Get element id.
|
||||
MJAPI int mjm_getId(mjElement element);
|
||||
|
||||
// Copy text to destination string.
|
||||
// Copy text to string.
|
||||
MJAPI void mjm_setString(mjString dest, const char* text);
|
||||
|
||||
// Split text to entries and copy to destination string vector.
|
||||
// Split text to entries and copy to string vector.
|
||||
MJAPI void mjm_setStringVec(mjStringVec dest, const char* text);
|
||||
|
||||
// Set specific entry in destination string vector.
|
||||
// Set entry in string vector.
|
||||
MJAPI mjtByte mjm_setInStringVec(mjStringVec dest, int i, const char* text);
|
||||
|
||||
// Add text entry to destination string vector.
|
||||
MJAPI void mjm_addToStringVec(mjStringVec dest, const char* text);
|
||||
// Append text entry to string vector.
|
||||
MJAPI void mjm_appendString(mjStringVec dest, const char* text);
|
||||
|
||||
// Copy int array to destination vector.
|
||||
// Copy int array to vector.
|
||||
MJAPI void mjm_setInt(mjIntVec dest, const int* array, int size);
|
||||
|
||||
// Copy float array to destination vector.
|
||||
// Append int array to vector of arrays.
|
||||
MJAPI void mjm_appendIntVec(mjIntVecVec dest, const int* array, int size);
|
||||
|
||||
// Copy float array to vector.
|
||||
MJAPI void mjm_setFloat(mjFloatVec dest, const float* array, int size);
|
||||
|
||||
// Copy double array to destination vector.
|
||||
// Append float array to vector of arrays.
|
||||
MJAPI void mjm_appendFloatVec(mjFloatVecVec dest, const float* array, int size);
|
||||
|
||||
// Copy double array to vector.
|
||||
MJAPI void mjm_setDouble(mjDoubleVec dest, const double* array, int size);
|
||||
|
||||
// Get string contents.
|
||||
@@ -790,6 +829,9 @@ MJAPI void mjm_defaultMesh(mjmMesh& mesh);
|
||||
// Default height field attributes.
|
||||
MJAPI void mjm_defaultHField(mjmHField& hfield);
|
||||
|
||||
// Default skin attributes.
|
||||
MJAPI void mjm_defaultSkin(mjmSkin& skin);
|
||||
|
||||
// Default texture attributes.
|
||||
MJAPI void mjm_defaultTexture(mjmTexture& texture);
|
||||
|
||||
|
||||
+253
-231
@@ -279,6 +279,15 @@ bool mjCComposite::Make(mjCModel* model, mjmBody* body, char* error, int error_s
|
||||
}
|
||||
}
|
||||
|
||||
// clear skin vectors
|
||||
face.clear();
|
||||
vert.clear();
|
||||
bindpos.clear();
|
||||
bindquat.clear();
|
||||
texcoord.clear();
|
||||
vertid.clear();
|
||||
vertweight.clear();
|
||||
|
||||
// require 3x3 for subgrid
|
||||
if (skin && skinsubgrid>0 && type!=mjCOMPTYPE_CABLE) {
|
||||
if (count[0]<3 || count[1]<3) {
|
||||
@@ -1238,57 +1247,80 @@ void mjCComposite::MakeShear(mjCModel* model) {
|
||||
|
||||
|
||||
|
||||
// copy local vectors to skin
|
||||
void mjCComposite::CopyIntoSkin(mjmSkin* skin) {
|
||||
mjm_setInt(skin->face, face.data(), face.size());
|
||||
mjm_setFloat(skin->vert, vert.data(), vert.size());
|
||||
mjm_setFloat(skin->bindpos, bindpos.data(), bindpos.size());
|
||||
mjm_setFloat(skin->bindquat, bindquat.data(), bindquat.size());
|
||||
mjm_setFloat(skin->texcoord, texcoord.data(), texcoord.size());
|
||||
|
||||
for (int i=0; i<vertid.size(); i++) {
|
||||
mjm_appendIntVec(skin->vertid, vertid[i].data(), vertid[i].size());
|
||||
}
|
||||
for (int i=0; i< vertweight.size(); i++) {
|
||||
mjm_appendFloatVec(skin->vertweight, vertweight[i].data(), vertweight[i].size());
|
||||
}
|
||||
|
||||
face.clear();
|
||||
vert.clear();
|
||||
bindpos.clear();
|
||||
bindquat.clear();
|
||||
texcoord.clear();
|
||||
vertid.clear();
|
||||
vertweight.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// add skin to 2D
|
||||
void mjCComposite::MakeSkin2(mjCModel* model, mjtNum inflate) {
|
||||
char txt[100];
|
||||
int N = count[0]*count[1];
|
||||
|
||||
// add skin, set name and material
|
||||
mjCSkin* skin = model->AddSkin();
|
||||
mjmSkin* skin = mjm_addSkin(model);
|
||||
mju::sprintf_arr(txt, "%sSkin", prefix.c_str());
|
||||
skin->name = txt;
|
||||
skin->set_material(skinmaterial);
|
||||
mjm_setString(skin->name, txt);
|
||||
mjm_setString(skin->material, skinmaterial.c_str());
|
||||
mjuu_copyvec(skin->rgba, skinrgba, 4);
|
||||
skin->inflate = inflate;
|
||||
skin->group = skingroup;
|
||||
|
||||
// copy skin from existing mesh
|
||||
if (type==mjCOMPTYPE_PARTICLE && username.empty()) {
|
||||
std::vector<int> face;
|
||||
mjXUtil::String2Vector(userface, face);
|
||||
std::vector<int> skinface;
|
||||
mjXUtil::String2Vector(userface, skinface);
|
||||
int nvert = uservert.size()/3;
|
||||
|
||||
for (int j=0; j<2; j++) {
|
||||
for (int i=0; i<nvert; i++) {
|
||||
skin->vert.push_back(0);
|
||||
skin->vert.push_back(0);
|
||||
skin->vert.push_back(0);
|
||||
vert.push_back(0);
|
||||
vert.push_back(0);
|
||||
vert.push_back(0);
|
||||
|
||||
mju::sprintf_arr(txt, "%sB%d", prefix.c_str(), i);
|
||||
skin->bodyname.push_back(txt);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindquat.push_back(1);
|
||||
skin->bindquat.push_back(0);
|
||||
skin->bindquat.push_back(0);
|
||||
skin->bindquat.push_back(0);
|
||||
mjm_appendString(skin->bodyname, txt);
|
||||
bindpos.push_back(0);
|
||||
bindpos.push_back(0);
|
||||
bindpos.push_back(0);
|
||||
bindquat.push_back(1);
|
||||
bindquat.push_back(0);
|
||||
bindquat.push_back(0);
|
||||
bindquat.push_back(0);
|
||||
|
||||
vector<int> vertid;
|
||||
vector<float> vertweight;
|
||||
vertid.push_back(j*nvert+i);
|
||||
vertweight.push_back(1);
|
||||
skin->vertid.push_back(vertid);
|
||||
skin->vertweight.push_back(vertweight);
|
||||
vertid.push_back({j*nvert+i});
|
||||
vertweight.push_back({1});
|
||||
}
|
||||
|
||||
for (int i=0; i<face.size()/3; i++) {
|
||||
skin->face.push_back(j*nvert+face[3*i]);
|
||||
skin->face.push_back(j*nvert+face[3*i+(j==0 ? 1 : 2)]);
|
||||
skin->face.push_back(j*nvert+face[3*i+(j==0 ? 2 : 1)]);
|
||||
for (int i=0; i<skinface.size()/3; i++) {
|
||||
face.push_back(j*nvert+skinface[3*i]);
|
||||
face.push_back(j*nvert+skinface[3*i+(j==0 ? 1 : 2)]);
|
||||
face.push_back(j*nvert+skinface[3*i+(j==0 ? 2 : 1)]);
|
||||
}
|
||||
}
|
||||
|
||||
CopyIntoSkin(skin);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1297,25 +1329,25 @@ void mjCComposite::MakeSkin2(mjCModel* model, mjtNum inflate) {
|
||||
for (int ix=0; ix<count[0]; ix++) {
|
||||
for (int iy=0; iy<count[1]; iy++) {
|
||||
// vertex
|
||||
skin->vert.push_back(0);
|
||||
skin->vert.push_back(0);
|
||||
skin->vert.push_back(0);
|
||||
vert.push_back(0);
|
||||
vert.push_back(0);
|
||||
vert.push_back(0);
|
||||
|
||||
// texture coordinate
|
||||
if (skintexcoord) {
|
||||
skin->texcoord.push_back(ix/(float)(count[0]-1));
|
||||
skin->texcoord.push_back(iy/(float)(count[1]-1));
|
||||
texcoord.push_back(ix/(float)(count[0]-1));
|
||||
texcoord.push_back(iy/(float)(count[1]-1));
|
||||
}
|
||||
|
||||
// face
|
||||
if (ix<count[0]-1 && iy<count[1]-1) {
|
||||
skin->face.push_back(i*N + ix*count[1]+iy);
|
||||
skin->face.push_back(i*N + (ix+1)*count[1]+iy+(i==1));
|
||||
skin->face.push_back(i*N + (ix+1)*count[1]+iy+(i==0));
|
||||
face.push_back(i*N + ix*count[1]+iy);
|
||||
face.push_back(i*N + (ix+1)*count[1]+iy+(i==1));
|
||||
face.push_back(i*N + (ix+1)*count[1]+iy+(i==0));
|
||||
|
||||
skin->face.push_back(i*N + ix*count[1]+iy);
|
||||
skin->face.push_back(i*N + (ix+(i==0))*count[1]+iy+1);
|
||||
skin->face.push_back(i*N + (ix+(i==1))*count[1]+iy+1);
|
||||
face.push_back(i*N + ix*count[1]+iy);
|
||||
face.push_back(i*N + (ix+(i==0))*count[1]+iy+1);
|
||||
face.push_back(i*N + (ix+(i==1))*count[1]+iy+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1323,46 +1355,46 @@ void mjCComposite::MakeSkin2(mjCModel* model, mjtNum inflate) {
|
||||
|
||||
// add thin triangles: X direction, iy = 0
|
||||
for (int ix=0; ix<count[0]-1; ix++) {
|
||||
skin->face.push_back(ix*count[1]);
|
||||
skin->face.push_back(N + (ix+1)*count[1]);
|
||||
skin->face.push_back((ix+1)*count[1]);
|
||||
face.push_back(ix*count[1]);
|
||||
face.push_back(N + (ix+1)*count[1]);
|
||||
face.push_back((ix+1)*count[1]);
|
||||
|
||||
skin->face.push_back(ix*count[1]);
|
||||
skin->face.push_back(N + ix*count[1]);
|
||||
skin->face.push_back(N + (ix+1)*count[1]);
|
||||
face.push_back(ix*count[1]);
|
||||
face.push_back(N + ix*count[1]);
|
||||
face.push_back(N + (ix+1)*count[1]);
|
||||
}
|
||||
|
||||
// add thin triangles: X direction, iy = count[1]-1
|
||||
for (int ix=0; ix<count[0]-1; ix++) {
|
||||
skin->face.push_back(ix*count[1] + count[1]-1);
|
||||
skin->face.push_back((ix+1)*count[1] + count[1]-1);
|
||||
skin->face.push_back(N + (ix+1)*count[1] + count[1]-1);
|
||||
face.push_back(ix*count[1] + count[1]-1);
|
||||
face.push_back((ix+1)*count[1] + count[1]-1);
|
||||
face.push_back(N + (ix+1)*count[1] + count[1]-1);
|
||||
|
||||
skin->face.push_back(ix*count[1] + count[1]-1);
|
||||
skin->face.push_back(N + (ix+1)*count[1] + count[1]-1);
|
||||
skin->face.push_back(N + ix*count[1] + count[1]-1);
|
||||
face.push_back(ix*count[1] + count[1]-1);
|
||||
face.push_back(N + (ix+1)*count[1] + count[1]-1);
|
||||
face.push_back(N + ix*count[1] + count[1]-1);
|
||||
}
|
||||
|
||||
// add thin triangles: Y direction, ix = 0
|
||||
for (int iy=0; iy<count[1]-1; iy++) {
|
||||
skin->face.push_back(iy);
|
||||
skin->face.push_back(iy+1);
|
||||
skin->face.push_back(N + iy+1);
|
||||
face.push_back(iy);
|
||||
face.push_back(iy+1);
|
||||
face.push_back(N + iy+1);
|
||||
|
||||
skin->face.push_back(iy);
|
||||
skin->face.push_back(N + iy+1);
|
||||
skin->face.push_back(N + iy);
|
||||
face.push_back(iy);
|
||||
face.push_back(N + iy+1);
|
||||
face.push_back(N + iy);
|
||||
}
|
||||
|
||||
// add thin triangles: Y direction, ix = count[0]-1
|
||||
for (int iy=0; iy<count[1]-1; iy++) {
|
||||
skin->face.push_back(iy + (count[0]-1)*count[1]);
|
||||
skin->face.push_back(N + iy+1 + (count[0]-1)*count[1]);
|
||||
skin->face.push_back(iy+1 + (count[0]-1)*count[1]);
|
||||
face.push_back(iy + (count[0]-1)*count[1]);
|
||||
face.push_back(N + iy+1 + (count[0]-1)*count[1]);
|
||||
face.push_back(iy+1 + (count[0]-1)*count[1]);
|
||||
|
||||
skin->face.push_back(iy + (count[0]-1)*count[1]);
|
||||
skin->face.push_back(N + iy + (count[0]-1)*count[1]);
|
||||
skin->face.push_back(N + iy+1 + (count[0]-1)*count[1]);
|
||||
face.push_back(iy + (count[0]-1)*count[1]);
|
||||
face.push_back(N + iy + (count[0]-1)*count[1]);
|
||||
face.push_back(N + iy+1 + (count[0]-1)*count[1]);
|
||||
}
|
||||
|
||||
// couple with bones
|
||||
@@ -1371,12 +1403,14 @@ void mjCComposite::MakeSkin2(mjCModel* model, mjtNum inflate) {
|
||||
} else if (type==mjCOMPTYPE_CABLE) {
|
||||
MakeCableBones(model, skin);
|
||||
}
|
||||
|
||||
CopyIntoSkin(skin);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// add bones in 2D
|
||||
void mjCComposite::MakeClothBones(mjCModel* model, mjCSkin* skin) {
|
||||
void mjCComposite::MakeClothBones(mjCModel* model, mjmSkin* skin) {
|
||||
char txt[100];
|
||||
int N = count[0]*count[1];
|
||||
|
||||
@@ -1391,31 +1425,25 @@ void mjCComposite::MakeClothBones(mjCModel* model, mjCSkin* skin) {
|
||||
}
|
||||
|
||||
// bind pose
|
||||
skin->bodyname.push_back(txt);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindquat.push_back(1);
|
||||
skin->bindquat.push_back(0);
|
||||
skin->bindquat.push_back(0);
|
||||
skin->bindquat.push_back(0);
|
||||
mjm_appendString(skin->bodyname, txt);
|
||||
bindpos.push_back(0);
|
||||
bindpos.push_back(0);
|
||||
bindpos.push_back(0);
|
||||
bindquat.push_back(1);
|
||||
bindquat.push_back(0);
|
||||
bindquat.push_back(0);
|
||||
bindquat.push_back(0);
|
||||
|
||||
// create vertid and vertweight
|
||||
vector<int> vertid;
|
||||
vector<float> vertweight;
|
||||
vertid.push_back(ix*count[1]+iy);
|
||||
vertid.push_back(N + ix*count[1]+iy);
|
||||
vertweight.push_back(1);
|
||||
vertweight.push_back(1);
|
||||
skin->vertid.push_back(vertid);
|
||||
skin->vertweight.push_back(vertweight);
|
||||
vertid.push_back({ix*count[1]+iy, N + ix*count[1]+iy});
|
||||
vertweight.push_back({1, 1});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void mjCComposite::MakeClothBonesSubgrid(mjCModel* model, mjCSkin* skin) {
|
||||
void mjCComposite::MakeClothBonesSubgrid(mjCModel* model, mjmSkin* skin) {
|
||||
char txt[100];
|
||||
|
||||
// populate bones
|
||||
@@ -1429,20 +1457,18 @@ void mjCComposite::MakeClothBonesSubgrid(mjCModel* model, mjCSkin* skin) {
|
||||
}
|
||||
|
||||
// bind pose
|
||||
skin->bodyname.push_back(txt);
|
||||
skin->bindpos.push_back(ix*spacing);
|
||||
skin->bindpos.push_back(iy*spacing);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindquat.push_back(1);
|
||||
skin->bindquat.push_back(0);
|
||||
skin->bindquat.push_back(0);
|
||||
skin->bindquat.push_back(0);
|
||||
mjm_appendString(skin->bodyname, txt);
|
||||
bindpos.push_back(ix*spacing);
|
||||
bindpos.push_back(iy*spacing);
|
||||
bindpos.push_back(0);
|
||||
bindquat.push_back(1);
|
||||
bindquat.push_back(0);
|
||||
bindquat.push_back(0);
|
||||
bindquat.push_back(0);
|
||||
|
||||
// empty vertid and vertweight
|
||||
vector<int> vertid;
|
||||
vector<float> vertweight;
|
||||
skin->vertid.push_back(vertid);
|
||||
skin->vertweight.push_back(vertweight);
|
||||
vertid.push_back({});
|
||||
vertweight.push_back({});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1450,7 +1476,7 @@ void mjCComposite::MakeClothBonesSubgrid(mjCModel* model, mjCSkin* skin) {
|
||||
|
||||
|
||||
// add bones to 1D
|
||||
void mjCComposite::MakeCableBones(mjCModel* model, mjCSkin* skin) {
|
||||
void mjCComposite::MakeCableBones(mjCModel* model, mjmSkin* skin) {
|
||||
char this_body[100];
|
||||
int N = count[0]*count[1];
|
||||
|
||||
@@ -1468,31 +1494,31 @@ void mjCComposite::MakeCableBones(mjCModel* model, mjCSkin* skin) {
|
||||
|
||||
// bind pose
|
||||
if (iy==0) {
|
||||
skin->bodyname.push_back(this_body);
|
||||
skin->bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.spec.size[0] : 0);
|
||||
skin->bindpos.push_back(-def[0].geom.spec.size[1]);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindquat.push_back(1); skin->bindquat.push_back(0);
|
||||
skin->bindquat.push_back(0); skin->bindquat.push_back(0);
|
||||
mjm_appendString(skin->bodyname, this_body);
|
||||
bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.spec.size[0] : 0);
|
||||
bindpos.push_back(-def[0].geom.spec.size[1]);
|
||||
bindpos.push_back(0);
|
||||
bindquat.push_back(1); bindquat.push_back(0);
|
||||
bindquat.push_back(0); bindquat.push_back(0);
|
||||
} else {
|
||||
skin->bodyname.push_back(this_body);
|
||||
skin->bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.spec.size[0] : 0);
|
||||
skin->bindpos.push_back(def[0].geom.spec.size[1]);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindquat.push_back(1); skin->bindquat.push_back(0);
|
||||
skin->bindquat.push_back(0); skin->bindquat.push_back(0);
|
||||
mjm_appendString(skin->bodyname, this_body);
|
||||
bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.spec.size[0] : 0);
|
||||
bindpos.push_back(def[0].geom.spec.size[1]);
|
||||
bindpos.push_back(0);
|
||||
bindquat.push_back(1); bindquat.push_back(0);
|
||||
bindquat.push_back(0); bindquat.push_back(0);
|
||||
}
|
||||
|
||||
// create vertid and vertweight
|
||||
skin->vertid.push_back({ix*count[1]+iy, N + ix*count[1]+iy});
|
||||
skin->vertweight.push_back({1, 1});
|
||||
vertid.push_back({ix*count[1]+iy, N + ix*count[1]+iy});
|
||||
vertweight.push_back({1, 1});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void mjCComposite::MakeCableBonesSubgrid(mjCModel* model, mjCSkin* skin) {
|
||||
void mjCComposite::MakeCableBonesSubgrid(mjCModel* model, mjmSkin* skin) {
|
||||
// populate bones
|
||||
for (int ix=0; ix<count[0]; ix++) {
|
||||
for (int iy=0; iy<count[1]; iy++) {
|
||||
@@ -1509,27 +1535,27 @@ void mjCComposite::MakeCableBonesSubgrid(mjCModel* model, mjCSkin* skin) {
|
||||
|
||||
// bind pose
|
||||
if (iy==0) {
|
||||
skin->bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.spec.size[0] : 0);
|
||||
skin->bindpos.push_back(-def[0].geom.spec.size[1]);
|
||||
skin->bindpos.push_back(0);
|
||||
bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.spec.size[0] : 0);
|
||||
bindpos.push_back(-def[0].geom.spec.size[1]);
|
||||
bindpos.push_back(0);
|
||||
} else if (iy==2) {
|
||||
skin->bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.spec.size[0] : 0);
|
||||
skin->bindpos.push_back(def[0].geom.spec.size[1]);
|
||||
skin->bindpos.push_back(0);
|
||||
bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.spec.size[0] : 0);
|
||||
bindpos.push_back(def[0].geom.spec.size[1]);
|
||||
bindpos.push_back(0);
|
||||
} else {
|
||||
skin->bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.spec.size[0] : 0);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindpos.push_back(0);
|
||||
bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.spec.size[0] : 0);
|
||||
bindpos.push_back(0);
|
||||
bindpos.push_back(0);
|
||||
}
|
||||
skin->bodyname.push_back(txt);
|
||||
skin->bindquat.push_back(1);
|
||||
skin->bindquat.push_back(0);
|
||||
skin->bindquat.push_back(0);
|
||||
skin->bindquat.push_back(0);
|
||||
mjm_appendString(skin->bodyname, txt);
|
||||
bindquat.push_back(1);
|
||||
bindquat.push_back(0);
|
||||
bindquat.push_back(0);
|
||||
bindquat.push_back(0);
|
||||
|
||||
// empty vertid and vertweight
|
||||
skin->vertid.push_back({});
|
||||
skin->vertweight.push_back({});
|
||||
vertid.push_back({});
|
||||
vertweight.push_back({});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1846,10 +1872,10 @@ void mjCComposite::MakeSkin2Subgrid(mjCModel* model, mjtNum inflate) {
|
||||
|
||||
// add skin, set name and material
|
||||
char txt[100];
|
||||
mjCSkin* skin = model->AddSkin();
|
||||
mjmSkin* skin = mjm_addSkin(model);
|
||||
mju::sprintf_arr(txt, "%sSkin", prefix.c_str());
|
||||
skin->name = txt;
|
||||
skin->set_material(skinmaterial);
|
||||
mjm_setString(skin->name, txt);
|
||||
mjm_setString(skin->material, skinmaterial.c_str());
|
||||
mjuu_copyvec(skin->rgba, skinrgba, 4);
|
||||
skin->inflate = inflate;
|
||||
skin->group = skingroup;
|
||||
@@ -1863,25 +1889,25 @@ void mjCComposite::MakeSkin2Subgrid(mjCModel* model, mjtNum inflate) {
|
||||
for (int ix=0; ix<C0; ix++) {
|
||||
for (int iy=0; iy<C1; iy++) {
|
||||
// vertex
|
||||
skin->vert.push_back(ix*S);
|
||||
skin->vert.push_back(iy*S);
|
||||
skin->vert.push_back(0);
|
||||
vert.push_back(ix*S);
|
||||
vert.push_back(iy*S);
|
||||
vert.push_back(0);
|
||||
|
||||
// texture coordinate
|
||||
if (skintexcoord) {
|
||||
skin->texcoord.push_back(ix/(float)(C0-1));
|
||||
skin->texcoord.push_back(iy/(float)(C1-1));
|
||||
texcoord.push_back(ix/(float)(C0-1));
|
||||
texcoord.push_back(iy/(float)(C1-1));
|
||||
}
|
||||
|
||||
// face
|
||||
if (ix<C0-1 && iy<C1-1) {
|
||||
skin->face.push_back(i*NN + ix*C1+iy);
|
||||
skin->face.push_back(i*NN + (ix+1)*C1+iy+(i==1));
|
||||
skin->face.push_back(i*NN + (ix+1)*C1+iy+(i==0));
|
||||
face.push_back(i*NN + ix*C1+iy);
|
||||
face.push_back(i*NN + (ix+1)*C1+iy+(i==1));
|
||||
face.push_back(i*NN + (ix+1)*C1+iy+(i==0));
|
||||
|
||||
skin->face.push_back(i*NN + ix*C1+iy);
|
||||
skin->face.push_back(i*NN + (ix+(i==0))*C1+iy+1);
|
||||
skin->face.push_back(i*NN + (ix+(i==1))*C1+iy+1);
|
||||
face.push_back(i*NN + ix*C1+iy);
|
||||
face.push_back(i*NN + (ix+(i==0))*C1+iy+1);
|
||||
face.push_back(i*NN + (ix+(i==1))*C1+iy+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1889,46 +1915,46 @@ void mjCComposite::MakeSkin2Subgrid(mjCModel* model, mjtNum inflate) {
|
||||
|
||||
// add thin triangles: X direction, iy = 0
|
||||
for (int ix=0; ix<C0-1; ix++) {
|
||||
skin->face.push_back(ix*C1);
|
||||
skin->face.push_back(NN + (ix+1)*C1);
|
||||
skin->face.push_back((ix+1)*C1);
|
||||
face.push_back(ix*C1);
|
||||
face.push_back(NN + (ix+1)*C1);
|
||||
face.push_back((ix+1)*C1);
|
||||
|
||||
skin->face.push_back(ix*C1);
|
||||
skin->face.push_back(NN + ix*C1);
|
||||
skin->face.push_back(NN + (ix+1)*C1);
|
||||
face.push_back(ix*C1);
|
||||
face.push_back(NN + ix*C1);
|
||||
face.push_back(NN + (ix+1)*C1);
|
||||
}
|
||||
|
||||
// add thin triangles: X direction, iy = C1-1
|
||||
for (int ix=0; ix<C0-1; ix++) {
|
||||
skin->face.push_back(ix*C1 + C1-1);
|
||||
skin->face.push_back((ix+1)*C1 + C1-1);
|
||||
skin->face.push_back(NN + (ix+1)*C1 + C1-1);
|
||||
face.push_back(ix*C1 + C1-1);
|
||||
face.push_back((ix+1)*C1 + C1-1);
|
||||
face.push_back(NN + (ix+1)*C1 + C1-1);
|
||||
|
||||
skin->face.push_back(ix*C1 + C1-1);
|
||||
skin->face.push_back(NN + (ix+1)*C1 + C1-1);
|
||||
skin->face.push_back(NN + ix*C1 + C1-1);
|
||||
face.push_back(ix*C1 + C1-1);
|
||||
face.push_back(NN + (ix+1)*C1 + C1-1);
|
||||
face.push_back(NN + ix*C1 + C1-1);
|
||||
}
|
||||
|
||||
// add thin triangles: Y direction, ix = 0
|
||||
for (int iy=0; iy<C1-1; iy++) {
|
||||
skin->face.push_back(iy);
|
||||
skin->face.push_back(iy+1);
|
||||
skin->face.push_back(NN + iy+1);
|
||||
face.push_back(iy);
|
||||
face.push_back(iy+1);
|
||||
face.push_back(NN + iy+1);
|
||||
|
||||
skin->face.push_back(iy);
|
||||
skin->face.push_back(NN + iy+1);
|
||||
skin->face.push_back(NN + iy);
|
||||
face.push_back(iy);
|
||||
face.push_back(NN + iy+1);
|
||||
face.push_back(NN + iy);
|
||||
}
|
||||
|
||||
// add thin triangles: Y direction, ix = C0-1
|
||||
for (int iy=0; iy<C1-1; iy++) {
|
||||
skin->face.push_back(iy + (C0-1)*C1);
|
||||
skin->face.push_back(NN + iy+1 + (C0-1)*C1);
|
||||
skin->face.push_back(iy+1 + (C0-1)*C1);
|
||||
face.push_back(iy + (C0-1)*C1);
|
||||
face.push_back(NN + iy+1 + (C0-1)*C1);
|
||||
face.push_back(iy+1 + (C0-1)*C1);
|
||||
|
||||
skin->face.push_back(iy + (C0-1)*C1);
|
||||
skin->face.push_back(NN + iy + (C0-1)*C1);
|
||||
skin->face.push_back(NN + iy+1 + (C0-1)*C1);
|
||||
face.push_back(iy + (C0-1)*C1);
|
||||
face.push_back(NN + iy + (C0-1)*C1);
|
||||
face.push_back(NN + iy+1 + (C0-1)*C1);
|
||||
}
|
||||
|
||||
if (type==mjCOMPTYPE_PARTICLE || type==mjCOMPTYPE_GRID) {
|
||||
@@ -1966,10 +1992,10 @@ void mjCComposite::MakeSkin2Subgrid(mjCModel* model, mjtNum inflate) {
|
||||
for (int bi=0; bi<16; bi++) {
|
||||
mjtNum w = Weight[d*N*16 + n*16 + bi];
|
||||
if (w) {
|
||||
skin->vertid[boneid[bi]].push_back(vid);
|
||||
skin->vertid[boneid[bi]].push_back(vid+NN);
|
||||
skin->vertweight[boneid[bi]].push_back((float)w);
|
||||
skin->vertweight[boneid[bi]].push_back((float)w);
|
||||
vertid[boneid[bi]].push_back(vid);
|
||||
vertid[boneid[bi]].push_back(vid+NN);
|
||||
vertweight[boneid[bi]].push_back((float)w);
|
||||
vertweight[boneid[bi]].push_back((float)w);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1977,6 +2003,8 @@ void mjCComposite::MakeSkin2Subgrid(mjCModel* model, mjtNum inflate) {
|
||||
}
|
||||
}
|
||||
|
||||
CopyIntoSkin(skin);
|
||||
|
||||
// free allocations
|
||||
mju_free(XY);
|
||||
mju_free(XY_W);
|
||||
@@ -1999,10 +2027,10 @@ void mjCComposite::MakeSkin3(mjCModel* model) {
|
||||
mju::sprintf_arr(cnt2, "%d", count[2]-1);
|
||||
|
||||
// add skin, set name and material
|
||||
mjCSkin* skin = model->AddSkin();
|
||||
mjmSkin* skin = mjm_addSkin(model);
|
||||
mju::sprintf_arr(txt, "%sSkin", prefix.c_str());
|
||||
skin->name = txt;
|
||||
skin->set_material(skinmaterial);
|
||||
mjm_setString(skin->name, txt);
|
||||
mjm_setString(skin->material, skinmaterial.c_str());
|
||||
mjuu_copyvec(skin->rgba, skinrgba, 4);
|
||||
skin->inflate = skininflate;
|
||||
skin->group = skingroup;
|
||||
@@ -2038,9 +2066,9 @@ void mjCComposite::MakeSkin3(mjCModel* model) {
|
||||
mju::sprintf_arr(txt, "%sB%d_%d_%d", prefix.c_str(), ix, iy, iz);
|
||||
|
||||
// add vertex
|
||||
skin->vert.push_back(0);
|
||||
skin->vert.push_back(0);
|
||||
skin->vert.push_back(0);
|
||||
vert.push_back(0);
|
||||
vert.push_back(0);
|
||||
vert.push_back(0);
|
||||
|
||||
// texture coordinate
|
||||
if (skintexcoord) {
|
||||
@@ -2053,8 +2081,8 @@ void mjCComposite::MakeSkin3(mjCModel* model) {
|
||||
Y = iz/(float)(count[2]-1);
|
||||
}
|
||||
|
||||
skin->texcoord.push_back(X);
|
||||
skin->texcoord.push_back(Y);
|
||||
texcoord.push_back(X);
|
||||
texcoord.push_back(Y);
|
||||
}
|
||||
|
||||
// save vertex id in map
|
||||
@@ -2095,9 +2123,9 @@ void mjCComposite::MakeSkin3(mjCModel* model) {
|
||||
mju::sprintf_arr(txt, "%sB%d_%d_%d", prefix.c_str(), ix, iy, iz);
|
||||
|
||||
// add vertex
|
||||
skin->vert.push_back(0);
|
||||
skin->vert.push_back(0);
|
||||
skin->vert.push_back(0);
|
||||
vert.push_back(0);
|
||||
vert.push_back(0);
|
||||
vert.push_back(0);
|
||||
|
||||
// texture coordinate
|
||||
if (skintexcoord) {
|
||||
@@ -2113,8 +2141,8 @@ void mjCComposite::MakeSkin3(mjCModel* model) {
|
||||
Y = iy/(float)(count[1]-1);
|
||||
}
|
||||
|
||||
skin->texcoord.push_back(X);
|
||||
skin->texcoord.push_back(Y);
|
||||
texcoord.push_back(X);
|
||||
texcoord.push_back(Y);
|
||||
}
|
||||
|
||||
// save vertex id in map
|
||||
@@ -2140,12 +2168,14 @@ void mjCComposite::MakeSkin3(mjCModel* model) {
|
||||
fmt = "%sB" + string(cnt0) + "_%d_%d";
|
||||
MakeSkin3Smooth(skin, count[1], count[2], 0, vmap, fmt.c_str());
|
||||
}
|
||||
|
||||
CopyIntoSkin(skin);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// make one face of 3D skin, box
|
||||
void mjCComposite::MakeSkin3Box(mjCSkin* skin, int c0, int c1, int side,
|
||||
void mjCComposite::MakeSkin3Box(mjmSkin* skin, int c0, int c1, int side,
|
||||
int& vcnt, const char* format) {
|
||||
char txt[100];
|
||||
|
||||
@@ -2153,47 +2183,43 @@ void mjCComposite::MakeSkin3Box(mjCSkin* skin, int c0, int c1, int side,
|
||||
for (int i0=0; i0<c0; i0++) {
|
||||
for (int i1=0; i1<c1; i1++) {
|
||||
// vertex
|
||||
skin->vert.push_back(0);
|
||||
skin->vert.push_back(0);
|
||||
skin->vert.push_back(0);
|
||||
vert.push_back(0);
|
||||
vert.push_back(0);
|
||||
vert.push_back(0);
|
||||
|
||||
// texture coordinate
|
||||
if (skintexcoord) {
|
||||
skin->texcoord.push_back(i0/(float)(c0-1));
|
||||
skin->texcoord.push_back(i1/(float)(c1-1));
|
||||
texcoord.push_back(i0/(float)(c0-1));
|
||||
texcoord.push_back(i1/(float)(c1-1));
|
||||
}
|
||||
|
||||
// face
|
||||
if (i0<c0-1 && i1<c1-1) {
|
||||
skin->face.push_back(vcnt + i0*c1+i1);
|
||||
skin->face.push_back(vcnt + (i0+1)*c1+i1+(side==1));
|
||||
skin->face.push_back(vcnt + (i0+1)*c1+i1+(side==0));
|
||||
face.push_back(vcnt + i0*c1+i1);
|
||||
face.push_back(vcnt + (i0+1)*c1+i1+(side==1));
|
||||
face.push_back(vcnt + (i0+1)*c1+i1+(side==0));
|
||||
|
||||
skin->face.push_back(vcnt + i0*c1+i1);
|
||||
skin->face.push_back(vcnt + (i0+(side==0))*c1+i1+1);
|
||||
skin->face.push_back(vcnt + (i0+(side==1))*c1+i1+1);
|
||||
face.push_back(vcnt + i0*c1+i1);
|
||||
face.push_back(vcnt + (i0+(side==0))*c1+i1+1);
|
||||
face.push_back(vcnt + (i0+(side==1))*c1+i1+1);
|
||||
}
|
||||
|
||||
// body name
|
||||
mju::sprintf_arr(txt, format, prefix.c_str(), i0, i1);
|
||||
|
||||
// bind pose: origin
|
||||
skin->bodyname.push_back(txt);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindquat.push_back(1);
|
||||
skin->bindquat.push_back(0);
|
||||
skin->bindquat.push_back(0);
|
||||
skin->bindquat.push_back(0);
|
||||
mjm_appendString(skin->bodyname, txt);
|
||||
bindpos.push_back(0);
|
||||
bindpos.push_back(0);
|
||||
bindpos.push_back(0);
|
||||
bindquat.push_back(1);
|
||||
bindquat.push_back(0);
|
||||
bindquat.push_back(0);
|
||||
bindquat.push_back(0);
|
||||
|
||||
// vertid and vertweight
|
||||
vector<int> vertid;
|
||||
vector<float> vertweight;
|
||||
vertid.push_back(vcnt + i0*c1+i1);
|
||||
vertweight.push_back(1);
|
||||
skin->vertid.push_back(vertid);
|
||||
skin->vertweight.push_back(vertweight);
|
||||
vertid.push_back({vcnt + i0*c1+i1});
|
||||
vertweight.push_back({1});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2204,7 +2230,7 @@ void mjCComposite::MakeSkin3Box(mjCSkin* skin, int c0, int c1, int side,
|
||||
|
||||
|
||||
// make one face of 3D skin, smooth
|
||||
void mjCComposite::MakeSkin3Smooth(mjCSkin* skin, int c0, int c1, int side,
|
||||
void mjCComposite::MakeSkin3Smooth(mjmSkin* skin, int c0, int c1, int side,
|
||||
const std::map<string, int>& vmap, const char* format) {
|
||||
char txt00[100], txt01[100], txt10[100], txt11[100];
|
||||
|
||||
@@ -2220,41 +2246,37 @@ void mjCComposite::MakeSkin3Smooth(mjCSkin* skin, int c0, int c1, int side,
|
||||
// face
|
||||
if (i0<c0-1 && i1<c1-1) {
|
||||
if (side==0) {
|
||||
skin->face.push_back(vmap.find(txt00)->second);
|
||||
skin->face.push_back(vmap.find(txt10)->second);
|
||||
skin->face.push_back(vmap.find(txt11)->second);
|
||||
face.push_back(vmap.find(txt00)->second);
|
||||
face.push_back(vmap.find(txt10)->second);
|
||||
face.push_back(vmap.find(txt11)->second);
|
||||
|
||||
skin->face.push_back(vmap.find(txt00)->second);
|
||||
skin->face.push_back(vmap.find(txt11)->second);
|
||||
skin->face.push_back(vmap.find(txt01)->second);
|
||||
face.push_back(vmap.find(txt00)->second);
|
||||
face.push_back(vmap.find(txt11)->second);
|
||||
face.push_back(vmap.find(txt01)->second);
|
||||
} else {
|
||||
skin->face.push_back(vmap.find(txt00)->second);
|
||||
skin->face.push_back(vmap.find(txt01)->second);
|
||||
skin->face.push_back(vmap.find(txt11)->second);
|
||||
face.push_back(vmap.find(txt00)->second);
|
||||
face.push_back(vmap.find(txt01)->second);
|
||||
face.push_back(vmap.find(txt11)->second);
|
||||
|
||||
skin->face.push_back(vmap.find(txt00)->second);
|
||||
skin->face.push_back(vmap.find(txt11)->second);
|
||||
skin->face.push_back(vmap.find(txt10)->second);
|
||||
face.push_back(vmap.find(txt00)->second);
|
||||
face.push_back(vmap.find(txt11)->second);
|
||||
face.push_back(vmap.find(txt10)->second);
|
||||
}
|
||||
}
|
||||
|
||||
// bind pose: origin
|
||||
skin->bodyname.push_back(txt00);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindquat.push_back(1);
|
||||
skin->bindquat.push_back(0);
|
||||
skin->bindquat.push_back(0);
|
||||
skin->bindquat.push_back(0);
|
||||
mjm_appendString(skin->bodyname, txt00);
|
||||
bindpos.push_back(0);
|
||||
bindpos.push_back(0);
|
||||
bindpos.push_back(0);
|
||||
bindquat.push_back(1);
|
||||
bindquat.push_back(0);
|
||||
bindquat.push_back(0);
|
||||
bindquat.push_back(0);
|
||||
|
||||
// vertid and vertweight
|
||||
vector<int> vertid;
|
||||
vector<float> vertweight;
|
||||
vertid.push_back(vmap.find(txt00)->second);
|
||||
vertweight.push_back(1);
|
||||
skin->vertid.push_back(vertid);
|
||||
skin->vertweight.push_back(vertweight);
|
||||
vertid.push_back({vmap.find(txt00)->second});
|
||||
vertweight.push_back({1});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include <mujoco/mjmodel.h>
|
||||
#include "user/user_api.h"
|
||||
#include "user/user_model.h"
|
||||
#include "user/user_objects.h"
|
||||
|
||||
@@ -79,14 +80,14 @@ class mjCComposite {
|
||||
|
||||
void MakeSkin2(mjCModel* model, mjtNum inflate);
|
||||
void MakeSkin2Subgrid(mjCModel* model, mjtNum inflate);
|
||||
void MakeClothBones(mjCModel* model, mjCSkin* skin);
|
||||
void MakeClothBonesSubgrid(mjCModel* model, mjCSkin* skin);
|
||||
void MakeCableBones(mjCModel* model, mjCSkin* skin);
|
||||
void MakeCableBonesSubgrid(mjCModel* model, mjCSkin* skin);
|
||||
void MakeClothBones(mjCModel* model, mjmSkin* skin);
|
||||
void MakeClothBonesSubgrid(mjCModel* model, mjmSkin* skin);
|
||||
void MakeCableBones(mjCModel* model, mjmSkin* skin);
|
||||
void MakeCableBonesSubgrid(mjCModel* model, mjmSkin* skin);
|
||||
|
||||
void MakeSkin3(mjCModel* model);
|
||||
void MakeSkin3Box(mjCSkin* skin, int c0, int c1, int side, int& vcnt, const char* format);
|
||||
void MakeSkin3Smooth(mjCSkin* skin, int c0, int c1, int side,
|
||||
void MakeSkin3Box(mjmSkin* skin, int c0, int c1, int side, int& vcnt, const char* format);
|
||||
void MakeSkin3Smooth(mjmSkin* skin, int c0, int c1, int side,
|
||||
const std::map<std::string, int>& vmap, const char* format);
|
||||
|
||||
void BoxProject(double* pos);
|
||||
@@ -138,6 +139,16 @@ class mjCComposite {
|
||||
private:
|
||||
mjmBody* AddRopeBody(mjCModel* model, mjmBody* body, int ix, int ix1);
|
||||
mjmBody* AddCableBody(mjCModel* model, mjmBody* body, int ix, mjtNum normal[3], mjtNum prev_quat[4]);
|
||||
|
||||
// temporary skin vectors
|
||||
void CopyIntoSkin(mjmSkin* skin);
|
||||
std::vector<int> face;
|
||||
std::vector<float> vert;
|
||||
std::vector<float> bindpos;
|
||||
std::vector<float> bindquat;
|
||||
std::vector<float> texcoord;
|
||||
std::vector<std::vector<int>> vertid;
|
||||
std::vector<std::vector<float>> vertweight;
|
||||
};
|
||||
|
||||
#endif // MUJOCO_SRC_USER_USER_COMPOSITE_H_
|
||||
|
||||
@@ -385,7 +385,7 @@ bool mjCFlexcomp::Make(mjCModel* model, mjmBody* body, char* error, int error_sz
|
||||
|
||||
// rigid: set parent name, nothing else to do
|
||||
if (rigid) {
|
||||
mjm_addToStringVec(pf->vertbody, mjm_getString(body->name));
|
||||
mjm_appendString(pf->vertbody, mjm_getString(body->name));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -402,7 +402,7 @@ bool mjCFlexcomp::Make(mjCModel* model, mjmBody* body, char* error, int error_sz
|
||||
|
||||
// pinned: parent body
|
||||
if (pinned[i]) {
|
||||
mjm_addToStringVec(pf->vertbody, mjm_getString(body->name));
|
||||
mjm_appendString(pf->vertbody, mjm_getString(body->name));
|
||||
|
||||
// add plugin
|
||||
if (plugin_instance) {
|
||||
@@ -459,7 +459,7 @@ bool mjCFlexcomp::Make(mjCModel* model, mjmBody* body, char* error, int error_sz
|
||||
char txt[100];
|
||||
mju::sprintf_arr(txt, "%s_%d", name.c_str(), i);
|
||||
mjm_setString(pb->name, txt);
|
||||
mjm_addToStringVec(pf->vertbody, mjm_getString(pb->name));
|
||||
mjm_appendString(pf->vertbody, mjm_getString(pb->name));
|
||||
|
||||
// clear flex vertex coordinates if allocated
|
||||
if (!centered) {
|
||||
|
||||
@@ -210,6 +210,17 @@ void mjm_defaultHField(mjmHField& hfield) {
|
||||
|
||||
|
||||
|
||||
// default skin attributes
|
||||
void mjm_defaultSkin(mjmSkin& skin) {
|
||||
memset(&skin, 0, sizeof(mjmSkin));
|
||||
skin.rgba[0] = skin.rgba[1] = skin.rgba[2] = 0.5f;
|
||||
skin.rgba[3] = 1.0f;
|
||||
skin.inflate = 0;
|
||||
skin.group = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// default texture attributes
|
||||
void mjm_defaultTexture(mjmTexture& texture) {
|
||||
memset(&texture, 0, sizeof(mjmTexture));
|
||||
|
||||
+139
-90
@@ -1829,45 +1829,92 @@ void mjCMesh::MakeCenter(void) {
|
||||
|
||||
// constructor
|
||||
mjCSkin::mjCSkin(mjCModel* _model) {
|
||||
mjm_defaultSkin(spec);
|
||||
|
||||
// set model pointer
|
||||
model = _model;
|
||||
|
||||
// clear data
|
||||
file.clear();
|
||||
material_.clear();
|
||||
rgba[0] = rgba[1] = rgba[2] = 0.5f;
|
||||
rgba[3] = 1.0f;
|
||||
inflate = 0;
|
||||
group = 0;
|
||||
spec_file_.clear();
|
||||
spec_material_.clear();
|
||||
spec_vert_.clear();
|
||||
spec_texcoord_.clear();
|
||||
spec_face_.clear();
|
||||
spec_bodyname_.clear();
|
||||
spec_bindpos_.clear();
|
||||
spec_bindquat_.clear();
|
||||
spec_vertid_.clear();
|
||||
spec_vertweight_.clear();
|
||||
|
||||
vert.clear();
|
||||
texcoord.clear();
|
||||
face.clear();
|
||||
|
||||
bodyname.clear();
|
||||
bindpos.clear();
|
||||
bindquat.clear();
|
||||
vertid.clear();
|
||||
vertweight.clear();
|
||||
bodyid.clear();
|
||||
|
||||
matid = -1;
|
||||
|
||||
// point to local (needs to be after defaults)
|
||||
PointToLocal();
|
||||
|
||||
// in case this camera is not compiled
|
||||
CopyFromSpec();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void mjCSkin::PointToLocal() {
|
||||
spec.element = (mjElement)this;
|
||||
spec.name = (mjString)&name;
|
||||
spec.classname = (mjString)&classname;
|
||||
spec.file = (mjString)&spec_file_;
|
||||
spec.material = (mjString)&spec_material_;
|
||||
spec.vert = (mjFloatVec)&spec_vert_;
|
||||
spec.texcoord = (mjFloatVec)&spec_texcoord_;
|
||||
spec.face = (mjIntVec)&spec_face_;
|
||||
spec.bodyname = (mjStringVec)&spec_bodyname_;
|
||||
spec.bindpos = (mjFloatVec)&spec_bindpos_;
|
||||
spec.bindquat = (mjFloatVec)&spec_bindquat_;
|
||||
spec.vertid = (mjIntVecVec)&spec_vertid_;
|
||||
spec.vertweight = (mjFloatVecVec)&spec_vertweight_;
|
||||
spec.info = (mjString)&info;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void mjCSkin::CopyFromSpec() {
|
||||
*static_cast<mjmSkin*>(this) = spec;
|
||||
file_ = spec_file_;
|
||||
material_ = spec_material_;
|
||||
vert_ = spec_vert_;
|
||||
texcoord_ = spec_texcoord_;
|
||||
face_ = spec_face_;
|
||||
bodyname_ = spec_bodyname_;
|
||||
bindpos_ = spec_bindpos_;
|
||||
bindquat_ = spec_bindquat_;
|
||||
vertid_ = spec_vertid_;
|
||||
vertweight_ = spec_vertweight_;
|
||||
file = (mjString)&spec_file_;
|
||||
material = (mjString)&spec_material_;
|
||||
vert = (mjFloatVec)&spec_vert_;
|
||||
texcoord = (mjFloatVec)&spec_texcoord_;
|
||||
face = (mjIntVec)&spec_face_;
|
||||
bodyname = (mjStringVec)&spec_bodyname_;
|
||||
bindpos = (mjFloatVec)&spec_bindpos_;
|
||||
bindquat = (mjFloatVec)&spec_bindquat_;
|
||||
vertid = (mjIntVecVec)&spec_vertid_;
|
||||
vertweight = (mjFloatVecVec)&spec_vertweight_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// destructor
|
||||
mjCSkin::~mjCSkin() {
|
||||
file.clear();
|
||||
material_.clear();
|
||||
vert.clear();
|
||||
texcoord.clear();
|
||||
face.clear();
|
||||
bodyname.clear();
|
||||
bindpos.clear();
|
||||
bindquat.clear();
|
||||
vertid.clear();
|
||||
vertweight.clear();
|
||||
spec_file_.clear();
|
||||
spec_material_.clear();
|
||||
spec_vert_.clear();
|
||||
spec_texcoord_.clear();
|
||||
spec_face_.clear();
|
||||
spec_bodyname_.clear();
|
||||
spec_bindpos_.clear();
|
||||
spec_bindquat_.clear();
|
||||
spec_vertid_.clear();
|
||||
spec_vertweight_.clear();
|
||||
bodyid.clear();
|
||||
}
|
||||
|
||||
@@ -1875,33 +1922,35 @@ mjCSkin::~mjCSkin() {
|
||||
|
||||
// compiler
|
||||
void mjCSkin::Compile(const mjVFS* vfs) {
|
||||
CopyFromSpec();
|
||||
|
||||
// load file
|
||||
if (!file.empty()) {
|
||||
if (!file_.empty()) {
|
||||
// make sure data is not present
|
||||
if (!vert.empty() ||
|
||||
!texcoord.empty() ||
|
||||
!face.empty() ||
|
||||
!bodyname.empty() ||
|
||||
!bindpos.empty() ||
|
||||
!bindquat.empty() ||
|
||||
!vertid.empty() ||
|
||||
!vertweight.empty() ||
|
||||
if (!vert_.empty() ||
|
||||
!texcoord_.empty() ||
|
||||
!face_.empty() ||
|
||||
!bodyname_.empty() ||
|
||||
!bindpos_.empty() ||
|
||||
!bindquat_.empty() ||
|
||||
!vertid_.empty() ||
|
||||
!vertweight_.empty() ||
|
||||
!bodyid.empty()) {
|
||||
throw mjCError(this, "Data already exists, trying to load from skin file: %s", file.c_str());
|
||||
throw mjCError(this, "Data already exists, trying to load from skin file: %s", file_.c_str());
|
||||
}
|
||||
|
||||
// remove path from file if necessary
|
||||
if (model->strippath) {
|
||||
file = mjuu_strippath(file);
|
||||
file_ = mjuu_strippath(file_);
|
||||
}
|
||||
|
||||
// load SKN
|
||||
string ext = mjuu_getext(file);
|
||||
string ext = mjuu_getext(file_);
|
||||
if (strcasecmp(ext.c_str(), ".skn")) {
|
||||
throw mjCError(this, "Unknown skin file type: %s", file.c_str());
|
||||
throw mjCError(this, "Unknown skin file type: %s", file_.c_str());
|
||||
}
|
||||
|
||||
string filename = mjuu_makefullname(model->modelfiledir, model->meshdir, file);
|
||||
string filename = mjuu_makefullname(model->modelfiledir, model->meshdir, file_);
|
||||
mjResource* resource = LoadResource(filename, vfs);
|
||||
|
||||
try {
|
||||
@@ -1914,48 +1963,48 @@ void mjCSkin::Compile(const mjVFS* vfs) {
|
||||
}
|
||||
|
||||
// make sure all data is present
|
||||
if (vert.empty() ||
|
||||
face.empty() ||
|
||||
bodyname.empty() ||
|
||||
bindpos.empty() ||
|
||||
bindquat.empty() ||
|
||||
vertid.empty() ||
|
||||
vertweight.empty()) {
|
||||
if (vert_.empty() ||
|
||||
face_.empty() ||
|
||||
bodyname_.empty() ||
|
||||
bindpos_.empty() ||
|
||||
bindquat_.empty() ||
|
||||
vertid_.empty() ||
|
||||
vertweight_.empty()) {
|
||||
throw mjCError(this, "Missing data in skin");
|
||||
}
|
||||
|
||||
// check mesh sizes
|
||||
if (vert.size()%3) {
|
||||
if (vert_.size()%3) {
|
||||
throw mjCError(this, "Vertex data must be multiple of 3");
|
||||
}
|
||||
if (!texcoord.empty() && texcoord.size()!=2*vert.size()/3) {
|
||||
if (!texcoord_.empty() && texcoord_.size()!=2*vert_.size()/3) {
|
||||
throw mjCError(this, "Vertex and texcoord data incompatible size");
|
||||
}
|
||||
if (face.size()%3) {
|
||||
if (face_.size()%3) {
|
||||
throw mjCError(this, "Face data must be multiple of 3");
|
||||
}
|
||||
|
||||
// check bone sizes
|
||||
size_t nbone = bodyname.size();
|
||||
if (bindpos.size()!=3*nbone) {
|
||||
size_t nbone = bodyname_.size();
|
||||
if (bindpos_.size()!=3*nbone) {
|
||||
throw mjCError(this, "Unexpected bindpos size in skin");
|
||||
}
|
||||
if (bindquat.size()!=4*nbone) {
|
||||
if (bindquat_.size()!=4*nbone) {
|
||||
throw mjCError(this, "Unexpected bindquat size in skin");
|
||||
}
|
||||
if (vertid.size()!=nbone) {
|
||||
if (vertid_.size()!=nbone) {
|
||||
throw mjCError(this, "Unexpected vertid size in skin");
|
||||
}
|
||||
if (vertweight.size()!=nbone) {
|
||||
if (vertweight_.size()!=nbone) {
|
||||
throw mjCError(this, "Unexpected vertweight size in skin");
|
||||
}
|
||||
|
||||
// resolve body names
|
||||
bodyid.resize(nbone);
|
||||
for (int i=0; i<nbone; i++) {
|
||||
mjCBase* pbody = model->FindObject(mjOBJ_BODY, bodyname[i]);
|
||||
mjCBase* pbody = model->FindObject(mjOBJ_BODY, bodyname_[i]);
|
||||
if (!pbody) {
|
||||
throw mjCError(this, "unknown body '%s' in skin", bodyname[i].c_str());
|
||||
throw mjCError(this, "unknown body '%s' in skin", bodyname_[i].c_str());
|
||||
}
|
||||
bodyid[i] = pbody->id;
|
||||
}
|
||||
@@ -1970,28 +2019,28 @@ void mjCSkin::Compile(const mjVFS* vfs) {
|
||||
|
||||
// set total vertex weights to 0
|
||||
vector<float> vw;
|
||||
size_t nvert = vert.size()/3;
|
||||
size_t nvert = vert_.size()/3;
|
||||
vw.resize(nvert);
|
||||
fill(vw.begin(), vw.end(), 0.0f);
|
||||
|
||||
// accumulate vertex weights from all bones
|
||||
for (int i=0; i<nbone; i++) {
|
||||
// make sure bone has vertices and sizes match
|
||||
size_t nbv = vertid[i].size();
|
||||
if (vertweight[i].size()!=nbv || nbv==0) {
|
||||
size_t nbv = vertid_[i].size();
|
||||
if (vertweight_[i].size()!=nbv || nbv==0) {
|
||||
throw mjCError(this, "vertid and vertweight must have same non-zero size in skin");
|
||||
}
|
||||
|
||||
// accumulate weights in global array
|
||||
for (int j=0; j<nbv; j++) {
|
||||
// get index and check range
|
||||
int jj = vertid[i][j];
|
||||
int jj = vertid_[i][j];
|
||||
if (jj<0 || jj>=nvert) {
|
||||
throw mjCError(this, "vertid %d out of range in skin", NULL, jj);
|
||||
}
|
||||
|
||||
// accumulate
|
||||
vw[jj] += vertweight[i][j];
|
||||
vw[jj] += vertweight_[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2004,25 +2053,25 @@ void mjCSkin::Compile(const mjVFS* vfs) {
|
||||
|
||||
// normalize vertex weights
|
||||
for (int i=0; i<nbone; i++) {
|
||||
for (int j=0; j<vertid[i].size(); j++) {
|
||||
vertweight[i][j] /= vw[vertid[i][j]];
|
||||
for (int j=0; j<vertid_[i].size(); j++) {
|
||||
vertweight_[i][j] /= vw[vertid_[i][j]];
|
||||
}
|
||||
}
|
||||
|
||||
// normalize bindquat
|
||||
for (int i=0; i<nbone; i++) {
|
||||
mjtNum quat[4] = {
|
||||
(mjtNum)bindquat[4*i],
|
||||
(mjtNum)bindquat[4*i+1],
|
||||
(mjtNum)bindquat[4*i+2],
|
||||
(mjtNum)bindquat[4*i+3]
|
||||
(mjtNum)bindquat_[4*i],
|
||||
(mjtNum)bindquat_[4*i+1],
|
||||
(mjtNum)bindquat_[4*i+2],
|
||||
(mjtNum)bindquat_[4*i+3]
|
||||
};
|
||||
mju_normalize4(quat);
|
||||
|
||||
bindquat[4*i] = (float) quat[0];
|
||||
bindquat[4*i+1] = (float) quat[1];
|
||||
bindquat[4*i+2] = (float) quat[2];
|
||||
bindquat[4*i+3] = (float) quat[3];
|
||||
bindquat_[4*i] = (float) quat[0];
|
||||
bindquat_[4*i+1] = (float) quat[1];
|
||||
bindquat_[4*i+2] = (float) quat[2];
|
||||
bindquat_[4*i+3] = (float) quat[3];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2066,31 +2115,31 @@ void mjCSkin::LoadSKN(mjResource* resource) {
|
||||
|
||||
// copy vert
|
||||
if (nvert) {
|
||||
vert.resize(3*nvert);
|
||||
memcpy(vert.data(), pdata+cnt, 3*nvert*sizeof(float));
|
||||
vert_.resize(3*nvert);
|
||||
memcpy(vert_.data(), pdata+cnt, 3*nvert*sizeof(float));
|
||||
cnt += 3*nvert;
|
||||
}
|
||||
|
||||
// copy texcoord
|
||||
if (ntexcoord) {
|
||||
texcoord.resize(2*ntexcoord);
|
||||
memcpy(texcoord.data(), pdata+cnt, 2*ntexcoord*sizeof(float));
|
||||
texcoord_.resize(2*ntexcoord);
|
||||
memcpy(texcoord_.data(), pdata+cnt, 2*ntexcoord*sizeof(float));
|
||||
cnt += 2*ntexcoord;
|
||||
}
|
||||
|
||||
// copy face
|
||||
if (nface) {
|
||||
face.resize(3*nface);
|
||||
memcpy(face.data(), pdata+cnt, 3*nface*sizeof(int));
|
||||
face_.resize(3*nface);
|
||||
memcpy(face_.data(), pdata+cnt, 3*nface*sizeof(int));
|
||||
cnt += 3*nface;
|
||||
}
|
||||
|
||||
// allocate bone arrays
|
||||
bodyname.clear();
|
||||
bindpos.resize(3*nbone);
|
||||
bindquat.resize(4*nbone);
|
||||
vertid.resize(nbone);
|
||||
vertweight.resize(nbone);
|
||||
bodyname_.clear();
|
||||
bindpos_.resize(3*nbone);
|
||||
bindquat_.resize(4*nbone);
|
||||
vertid_.resize(nbone);
|
||||
vertweight_.resize(nbone);
|
||||
|
||||
// read bones
|
||||
for (int i=0; i<nbone; i++) {
|
||||
@@ -2104,14 +2153,14 @@ void mjCSkin::LoadSKN(mjResource* resource) {
|
||||
strncpy(txt, (char*)(pdata+cnt), 39);
|
||||
txt[39] = '\0';
|
||||
cnt += 10;
|
||||
bodyname.push_back(txt);
|
||||
bodyname_.push_back(txt);
|
||||
|
||||
// read bindpos
|
||||
memcpy(bindpos.data()+3*i, pdata+cnt, 3*sizeof(float));
|
||||
memcpy(bindpos_.data()+3*i, pdata+cnt, 3*sizeof(float));
|
||||
cnt += 3;
|
||||
|
||||
// read bind quat
|
||||
memcpy(bindquat.data()+4*i, pdata+cnt, 4*sizeof(float));
|
||||
memcpy(bindquat_.data()+4*i, pdata+cnt, 4*sizeof(float));
|
||||
cnt += 4;
|
||||
|
||||
// read vertex count
|
||||
@@ -2131,13 +2180,13 @@ void mjCSkin::LoadSKN(mjResource* resource) {
|
||||
}
|
||||
|
||||
// read vertid
|
||||
vertid[i].resize(vcount);
|
||||
memcpy(vertid[i].data(), (int*)(pdata+cnt), vcount*sizeof(int));
|
||||
vertid_[i].resize(vcount);
|
||||
memcpy(vertid_[i].data(), (int*)(pdata+cnt), vcount*sizeof(int));
|
||||
cnt += vcount;
|
||||
|
||||
// read vertweight
|
||||
vertweight[i].resize(vcount);
|
||||
memcpy(vertweight[i].data(), (int*)(pdata+cnt), vcount*sizeof(int));
|
||||
vertweight_[i].resize(vcount);
|
||||
memcpy(vertweight_[i].data(), (int*)(pdata+cnt), vcount*sizeof(int));
|
||||
cnt += vcount;
|
||||
}
|
||||
|
||||
|
||||
+22
-22
@@ -1044,12 +1044,12 @@ void mjCModel::SetSizes(void) {
|
||||
|
||||
// skin counts
|
||||
for (int i=0; i<nskin; i++) {
|
||||
nskinvert += skins[i]->vert.size()/3;
|
||||
nskintexvert += skins[i]->texcoord.size()/2;
|
||||
nskinface += skins[i]->face.size()/3;
|
||||
nskinvert += skins[i]->get_vert().size()/3;
|
||||
nskintexvert += skins[i]->get_texcoord().size()/2;
|
||||
nskinface += skins[i]->get_face().size()/3;
|
||||
nskinbone += skins[i]->bodyid.size();
|
||||
for (int j=0; j<skins[i]->bodyid.size(); j++) {
|
||||
nskinbonevert += skins[i]->vertid[j].size();
|
||||
nskinbonevert += skins[i]->get_vertid()[j].size();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2094,25 +2094,25 @@ void mjCModel::CopyObjects(mjModel* m) {
|
||||
copyvec(m->skin_rgba+4*i, psk->rgba, 4);
|
||||
m->skin_inflate[i] = psk->inflate;
|
||||
m->skin_vertadr[i] = vert_adr;
|
||||
m->skin_vertnum[i] = psk->vert.size()/3;
|
||||
m->skin_texcoordadr[i] = (!psk->texcoord.empty() ? texcoord_adr : -1);
|
||||
m->skin_vertnum[i] = psk->get_vert().size()/3;
|
||||
m->skin_texcoordadr[i] = (!psk->get_texcoord().empty() ? texcoord_adr : -1);
|
||||
m->skin_faceadr[i] = face_adr;
|
||||
m->skin_facenum[i] = psk->face.size()/3;
|
||||
m->skin_facenum[i] = psk->get_face().size()/3;
|
||||
m->skin_boneadr[i] = bone_adr;
|
||||
m->skin_bonenum[i] = psk->bodyid.size();
|
||||
|
||||
// copy mesh data
|
||||
memcpy(m->skin_vert + 3*vert_adr, psk->vert.data(), psk->vert.size()*sizeof(float));
|
||||
if (!psk->texcoord.empty())
|
||||
memcpy(m->skin_texcoord + 2*texcoord_adr, psk->texcoord.data(),
|
||||
psk->texcoord.size()*sizeof(float));
|
||||
memcpy(m->skin_face + 3*face_adr, psk->face.data(), psk->face.size()*sizeof(int));
|
||||
memcpy(m->skin_vert + 3*vert_adr, psk->get_vert().data(), psk->get_vert().size()*sizeof(float));
|
||||
if (!psk->get_texcoord().empty())
|
||||
memcpy(m->skin_texcoord + 2*texcoord_adr, psk->get_texcoord().data(),
|
||||
psk->get_texcoord().size()*sizeof(float));
|
||||
memcpy(m->skin_face + 3*face_adr, psk->get_face().data(), psk->get_face().size()*sizeof(int));
|
||||
|
||||
// copy bind poses and body ids
|
||||
memcpy(m->skin_bonebindpos+3*bone_adr, psk->bindpos.data(),
|
||||
psk->bindpos.size()*sizeof(float));
|
||||
memcpy(m->skin_bonebindquat+4*bone_adr, psk->bindquat.data(),
|
||||
psk->bindquat.size()*sizeof(float));
|
||||
memcpy(m->skin_bonebindpos+3*bone_adr, psk->get_bindpos().data(),
|
||||
psk->get_bindpos().size()*sizeof(float));
|
||||
memcpy(m->skin_bonebindquat+4*bone_adr, psk->get_bindquat().data(),
|
||||
psk->get_bindquat().size()*sizeof(float));
|
||||
memcpy(m->skin_bonebodyid+bone_adr, psk->bodyid.data(),
|
||||
psk->bodyid.size()*sizeof(int));
|
||||
|
||||
@@ -2120,13 +2120,13 @@ void mjCModel::CopyObjects(mjModel* m) {
|
||||
for (int j=0; j<m->skin_bonenum[i]; j++) {
|
||||
// set fields
|
||||
m->skin_bonevertadr[bone_adr+j] = bonevert_adr;
|
||||
m->skin_bonevertnum[bone_adr+j] = (int)psk->vertid[j].size();
|
||||
m->skin_bonevertnum[bone_adr+j] = (int)psk->get_vertid()[j].size();
|
||||
|
||||
// copy data
|
||||
memcpy(m->skin_bonevertid+bonevert_adr, psk->vertid[j].data(),
|
||||
psk->vertid[j].size()*sizeof(int));
|
||||
memcpy(m->skin_bonevertweight+bonevert_adr, psk->vertweight[j].data(),
|
||||
psk->vertid[j].size()*sizeof(float));
|
||||
memcpy(m->skin_bonevertid+bonevert_adr, psk->get_vertid()[j].data(),
|
||||
psk->get_vertid()[j].size()*sizeof(int));
|
||||
memcpy(m->skin_bonevertweight+bonevert_adr, psk->get_vertweight()[j].data(),
|
||||
psk->get_vertid()[j].size()*sizeof(float));
|
||||
|
||||
// advance counter
|
||||
bonevert_adr += m->skin_bonevertnum[bone_adr+j];
|
||||
@@ -2134,7 +2134,7 @@ void mjCModel::CopyObjects(mjModel* m) {
|
||||
|
||||
// advance mesh and bone counters
|
||||
vert_adr += m->skin_vertnum[i];
|
||||
texcoord_adr += psk->texcoord.size()/2;
|
||||
texcoord_adr += psk->get_texcoord().size()/2;
|
||||
face_adr += m->skin_facenum[i];
|
||||
bone_adr += m->skin_bonenum[i];
|
||||
}
|
||||
|
||||
@@ -3677,7 +3677,6 @@ mjCEquality::mjCEquality(mjCModel* _model, mjCDef* _def) {
|
||||
model = _model;
|
||||
def = (_def ? _def : (_model ? _model->defaults[0] : 0));
|
||||
|
||||
|
||||
// point to local (needs to be after defaults)
|
||||
PointToLocal();
|
||||
|
||||
|
||||
+40
-20
@@ -771,32 +771,30 @@ class mjCMesh: public mjCBase, private mjmMesh {
|
||||
//------------------------- class mjCSkin ----------------------------------------------------------
|
||||
// Describes a skin
|
||||
|
||||
class mjCSkin: public mjCBase {
|
||||
class mjCSkin: public mjCBase, private mjmSkin {
|
||||
friend class mjCModel;
|
||||
friend class mjXWriter;
|
||||
|
||||
public:
|
||||
std::string get_file() const { return file; }
|
||||
void set_material(std::string _material) { material_ = _material; }
|
||||
mjmSkin spec;
|
||||
using mjCBase::name;
|
||||
using mjCBase::classname;
|
||||
using mjCBase::info;
|
||||
|
||||
std::string get_file() const { return file_; }
|
||||
std::string& get_material() { return material_; }
|
||||
std::vector<float>& get_vert() { return vert_; }
|
||||
std::vector<float>& get_texcoord() { return texcoord_; }
|
||||
std::vector<int>& get_face() { return face_; }
|
||||
std::vector<std::string>& get_bodyname() { return bodyname_; }
|
||||
std::vector<float>& get_bindpos() { return bindpos_; }
|
||||
std::vector<float>& get_bindquat() { return bindquat_; }
|
||||
std::vector<std::vector<int>>& get_vertid() { return vertid_; }
|
||||
std::vector<std::vector<float>>& get_vertweight() { return vertweight_; }
|
||||
void del_material() { material_.clear(); }
|
||||
|
||||
std::string file; // skin file
|
||||
float rgba[4]; // rgba when material is omitted
|
||||
float inflate; // inflate in normal direction
|
||||
int group; // group for visualization
|
||||
|
||||
// mesh
|
||||
std::vector<float> vert; // vertex positions
|
||||
std::vector<float> texcoord; // texture coordinates
|
||||
std::vector<int> face; // faces
|
||||
|
||||
// skin
|
||||
std::vector<std::string> bodyname; // body names
|
||||
std::vector<float> bindpos; // bind pos
|
||||
std::vector<float> bindquat; // bind quat
|
||||
std::vector<std::vector<int>> vertid; // vertex ids
|
||||
std::vector<std::vector<float>> vertweight; // vertex weights
|
||||
void CopyFromSpec();
|
||||
void PointToLocal();
|
||||
|
||||
private:
|
||||
mjCSkin(mjCModel* = 0); // constructor
|
||||
@@ -804,7 +802,29 @@ class mjCSkin: public mjCBase {
|
||||
void Compile(const mjVFS* vfs); // compiler
|
||||
void LoadSKN(mjResource* resource); // load skin in SKN BIN format
|
||||
|
||||
std::string material_; // name of material used for rendering
|
||||
// variable size attributes
|
||||
std::string file_;
|
||||
std::string material_;
|
||||
std::vector<float> vert_;
|
||||
std::vector<float> texcoord_;
|
||||
std::vector<int> face_;
|
||||
std::vector<std::string> bodyname_;
|
||||
std::vector<float> bindpos_;
|
||||
std::vector<float> bindquat_;
|
||||
std::vector<std::vector<int>> vertid_;
|
||||
std::vector<std::vector<float>> vertweight_;
|
||||
|
||||
std::string spec_file_;
|
||||
std::string spec_material_;
|
||||
std::vector<float> spec_vert_;
|
||||
std::vector<float> spec_texcoord_;
|
||||
std::vector<int> spec_face_;
|
||||
std::vector<std::string> spec_bodyname_;
|
||||
std::vector<float> spec_bindpos_;
|
||||
std::vector<float> spec_bindquat_;
|
||||
std::vector<std::vector<int>> spec_vertid_;
|
||||
std::vector<std::vector<float>> spec_vertweight_;
|
||||
|
||||
int matid; // material id
|
||||
std::vector<int> bodyid; // body ids
|
||||
};
|
||||
|
||||
@@ -1416,14 +1416,20 @@ void mjXReader::OneMesh(XMLElement* elem, mjmMesh* pmesh) {
|
||||
|
||||
|
||||
// skin element parser
|
||||
void mjXReader::OneSkin(XMLElement* elem, mjCSkin* pskin) {
|
||||
string text;
|
||||
void mjXReader::OneSkin(XMLElement* elem, mjmSkin* pskin) {
|
||||
string text, name, file, material;
|
||||
float data[4];
|
||||
|
||||
// read attributes
|
||||
ReadAttrTxt(elem, "name", pskin->name);
|
||||
ReadAttrTxt(elem, "file", pskin->file);
|
||||
ReadAttrTxt(elem, "material", pskin->get_material());
|
||||
if (ReadAttrTxt(elem, "name", name)) {
|
||||
mjm_setString(pskin->name, name.c_str());
|
||||
}
|
||||
if (ReadAttrTxt(elem, "file", file)) {
|
||||
mjm_setString(pskin->file, file.c_str());
|
||||
}
|
||||
if (ReadAttrTxt(elem, "material", material)) {
|
||||
mjm_setString(pskin->material, material.c_str());
|
||||
}
|
||||
ReadAttrInt(elem, "group", &pskin->group);
|
||||
if (pskin->group<0 || pskin->group>=mjNGROUP) {
|
||||
throw mjXError(elem, "skin group must be between 0 and 5");
|
||||
@@ -1432,51 +1438,72 @@ void mjXReader::OneSkin(XMLElement* elem, mjCSkin* pskin) {
|
||||
ReadAttr(elem, "inflate", 1, &pskin->inflate, text);
|
||||
|
||||
// read vertex data
|
||||
if (ReadAttrTxt(elem, "vertex", text)) String2Vector(text, pskin->vert);
|
||||
if (ReadAttrTxt(elem, "vertex", text)) {
|
||||
std::vector<float> vert;
|
||||
String2Vector(text, vert);
|
||||
mjm_setFloat(pskin->vert, vert.data(), vert.size());
|
||||
}
|
||||
|
||||
// read texcoord data
|
||||
if (ReadAttrTxt(elem, "texcoord", text)) String2Vector(text, pskin->texcoord);
|
||||
if (ReadAttrTxt(elem, "texcoord", text)) {
|
||||
std::vector<float> texcoord;
|
||||
String2Vector(text, texcoord);
|
||||
mjm_setFloat(pskin->texcoord, texcoord.data(), texcoord.size());
|
||||
}
|
||||
|
||||
// read user face data
|
||||
if (ReadAttrTxt(elem, "face", text)) String2Vector(text, pskin->face);
|
||||
if (ReadAttrTxt(elem, "face", text)) {
|
||||
std::vector<int> face;
|
||||
String2Vector(text, face);
|
||||
mjm_setInt(pskin->face, face.data(), face.size());
|
||||
}
|
||||
|
||||
// read bones
|
||||
XMLElement* bone = FirstChildElement(elem, "bone");
|
||||
std::vector<float> bindpos;
|
||||
std::vector<float> bindquat;
|
||||
|
||||
while (bone) {
|
||||
// read body
|
||||
ReadAttrTxt(bone, "body", text, true);
|
||||
pskin->bodyname.push_back(text);
|
||||
mjm_appendString(pskin->bodyname, text.c_str());
|
||||
|
||||
// read bindpos
|
||||
ReadAttr(bone, "bindpos", 3, data, text, true);
|
||||
pskin->bindpos.push_back(data[0]);
|
||||
pskin->bindpos.push_back(data[1]);
|
||||
pskin->bindpos.push_back(data[2]);
|
||||
bindpos.push_back(data[0]);
|
||||
bindpos.push_back(data[1]);
|
||||
bindpos.push_back(data[2]);
|
||||
|
||||
// read bindquat
|
||||
ReadAttr(bone, "bindquat", 4, data, text, true);
|
||||
pskin->bindquat.push_back(data[0]);
|
||||
pskin->bindquat.push_back(data[1]);
|
||||
pskin->bindquat.push_back(data[2]);
|
||||
pskin->bindquat.push_back(data[3]);
|
||||
bindquat.push_back(data[0]);
|
||||
bindquat.push_back(data[1]);
|
||||
bindquat.push_back(data[2]);
|
||||
bindquat.push_back(data[3]);
|
||||
|
||||
// read vertid
|
||||
vector<int> tempid;
|
||||
ReadAttrTxt(bone, "vertid", text, true);
|
||||
String2Vector(text, tempid);
|
||||
pskin->vertid.push_back(tempid);
|
||||
mjm_appendIntVec(pskin->vertid, tempid.data(), tempid.size());
|
||||
|
||||
// read vertweight
|
||||
vector<float> tempweight;
|
||||
ReadAttrTxt(bone, "vertweight", text, true);
|
||||
String2Vector(text, tempweight);
|
||||
pskin->vertweight.push_back(tempweight);
|
||||
mjm_appendFloatVec(pskin->vertweight, tempweight.data(), tempweight.size());
|
||||
|
||||
// advance to next bone
|
||||
bone = NextSiblingElement(bone, "bone");
|
||||
}
|
||||
|
||||
GetXMLPos(elem, pskin);
|
||||
// set bind vectors
|
||||
mjm_setFloat(pskin->bindpos, bindpos.data(), bindpos.size());
|
||||
mjm_setFloat(pskin->bindquat, bindquat.data(), bindquat.size());
|
||||
|
||||
// write error info
|
||||
mjm_setString(pskin->info,
|
||||
std::string("line = " + std::to_string(elem->GetLineNum()) + ", column = -1").c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -3129,7 +3156,7 @@ void mjXReader::Asset(XMLElement* section) {
|
||||
// skin sub-element... deprecate ???
|
||||
else if (name=="skin") {
|
||||
// create skin and parse
|
||||
mjCSkin* pskin = model->AddSkin();
|
||||
mjmSkin* pskin = mjm_addSkin(model);
|
||||
OneSkin(elem, pskin);
|
||||
}
|
||||
|
||||
@@ -3498,7 +3525,7 @@ void mjXReader::Deformable(XMLElement* section) {
|
||||
// skin sub-element
|
||||
else if (name=="skin") {
|
||||
// create skin and parse
|
||||
mjCSkin* pskin = model->AddSkin();
|
||||
mjmSkin* pskin = mjm_addSkin(model);
|
||||
OneSkin(elem, pskin);
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ class mjXReader : public mjXBase {
|
||||
// single element parsers, used in defaults and main body
|
||||
void OneFlex(tinyxml2::XMLElement* elem, mjmFlex* pflex);
|
||||
void OneMesh(tinyxml2::XMLElement* elem, mjmMesh* pmesh);
|
||||
void OneSkin(tinyxml2::XMLElement* elem, mjCSkin* pskin);
|
||||
void OneSkin(tinyxml2::XMLElement* elem, mjmSkin* pskin);
|
||||
void OneMaterial(tinyxml2::XMLElement* elem, mjmMaterial* pmaterial);
|
||||
void OneJoint(tinyxml2::XMLElement* elem, mjmJoint* pjoint);
|
||||
void OneGeom(tinyxml2::XMLElement* elem, mjmGeom* pgeom);
|
||||
|
||||
@@ -205,44 +205,44 @@ void mjXWriter::OneSkin(XMLElement* elem, mjCSkin* pskin) {
|
||||
|
||||
// write attributes
|
||||
WriteAttrTxt(elem, "name", pskin->name);
|
||||
WriteAttrTxt(elem, "file", pskin->file);
|
||||
WriteAttrTxt(elem, "file", pskin->get_file());
|
||||
WriteAttrTxt(elem, "material", pskin->get_material());
|
||||
WriteAttrInt(elem, "group", pskin->group, 0);
|
||||
WriteAttr(elem, "rgba", 4, pskin->rgba, mydef.geom.rgba);
|
||||
WriteAttr(elem, "inflate", 1, &pskin->inflate, &zero);
|
||||
|
||||
// write data if no file
|
||||
if (pskin->file.empty()) {
|
||||
if (pskin->get_file().empty()) {
|
||||
// mesh vert
|
||||
Vector2String(text, pskin->vert);
|
||||
Vector2String(text, pskin->get_vert());
|
||||
WriteAttrTxt(elem, "vertex", text);
|
||||
|
||||
// mesh texcoord
|
||||
if (!pskin->texcoord.empty()) {
|
||||
Vector2String(text, pskin->texcoord);
|
||||
if (!pskin->get_texcoord().empty()) {
|
||||
Vector2String(text, pskin->get_texcoord());
|
||||
WriteAttrTxt(elem, "texcoord", text);
|
||||
}
|
||||
|
||||
// mesh face
|
||||
Vector2String(text, pskin->face);
|
||||
Vector2String(text, pskin->get_face());
|
||||
WriteAttrTxt(elem, "face", text);
|
||||
|
||||
// bones
|
||||
for (size_t i=0; i<pskin->bodyname.size(); i++) {
|
||||
for (size_t i=0; i<pskin->get_bodyname().size(); i++) {
|
||||
// make bone
|
||||
XMLElement* bone = InsertEnd(elem, "bone");
|
||||
|
||||
// write attributes
|
||||
WriteAttrTxt(bone, "body", pskin->bodyname[i]);
|
||||
WriteAttr(bone, "bindpos", 3, pskin->bindpos.data()+3*i);
|
||||
WriteAttr(bone, "bindquat", 4, pskin->bindquat.data()+4*i);
|
||||
WriteAttrTxt(bone, "body", pskin->get_bodyname()[i]);
|
||||
WriteAttr(bone, "bindpos", 3, pskin->get_bindpos().data()+3*i);
|
||||
WriteAttr(bone, "bindquat", 4, pskin->get_bindquat().data()+4*i);
|
||||
|
||||
// write vertid
|
||||
Vector2String(text, pskin->vertid[i]);
|
||||
Vector2String(text, pskin->get_vertid()[i]);
|
||||
WriteAttrTxt(bone, "vertid", text);
|
||||
|
||||
// write vertweight
|
||||
Vector2String(text, pskin->vertweight[i]);
|
||||
Vector2String(text, pskin->get_vertweight()[i]);
|
||||
WriteAttrTxt(bone, "vertweight", text);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user