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