Add mjmTexture to C API.
PiperOrigin-RevId: 606543622 Change-Id: I2db743c1c40116f0503329fb1d004d9b041e83e7
This commit is contained in:
committed by
Copybara-Service
parent
47bb4a828e
commit
06505f49f9
@@ -137,6 +137,15 @@ mjmFrame* mjm_addFrame(mjmBody* bodyspec, mjmFrame* parentframe) {
|
||||
|
||||
|
||||
|
||||
// add texture to model
|
||||
mjmTexture* mjm_addTexture(void* model) {
|
||||
mjCModel* modelC = static_cast<mjCModel*>(model);
|
||||
mjCTexture* texture = modelC->AddTexture();
|
||||
return &texture->spec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// add material to model
|
||||
mjmMaterial* mjm_addMaterial(void* model, void* defspec) {
|
||||
mjCModel* modelC = static_cast<mjCModel*>(model);
|
||||
@@ -312,6 +321,19 @@ void mjm_setString(mjString dest, const char* text) {
|
||||
|
||||
|
||||
|
||||
// Set specific entry in destination string vector.
|
||||
mjtByte mjm_setInStringVec(mjStringVec dest, int i, const char* text) {
|
||||
std::vector<std::string>* v = reinterpret_cast<std::vector<std::string>*>(dest);
|
||||
if (v->size() <= i) {
|
||||
mju_error("Requested index in mjm_setInStringVec is out of bounds");
|
||||
return 0;
|
||||
}
|
||||
v->at(i) = std::string(text);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// split text and copy into string array
|
||||
void mjm_setStringVec(mjStringVec dest, const char* text) {
|
||||
std::vector<std::string>* v = reinterpret_cast<std::vector<std::string>*>(dest);
|
||||
|
||||
+62
-3
@@ -38,12 +38,28 @@ typedef struct _mjFloatVec* mjFloatVec;
|
||||
|
||||
//---------------------------------- enum types (mjt) ----------------------------------------------
|
||||
|
||||
typedef enum _mjtGeomInertia { // type of inertia inference
|
||||
mjINERTIA_VOLUME, // mass distributed in the volume
|
||||
mjINERTIA_SHELL, // mass distributed on the surface
|
||||
typedef enum _mjtGeomInertia { // type of inertia inference
|
||||
mjINERTIA_VOLUME, // mass distributed in the volume
|
||||
mjINERTIA_SHELL, // mass distributed on the surface
|
||||
} mjtGeomInertia;
|
||||
|
||||
|
||||
typedef enum _mjtBuiltin { // type of built-in procedural texture
|
||||
mjBUILTIN_NONE = 0, // no built-in texture
|
||||
mjBUILTIN_GRADIENT, // gradient: rgb1->rgb2
|
||||
mjBUILTIN_CHECKER, // checker pattern: rgb1, rgb2
|
||||
mjBUILTIN_FLAT // 2d: rgb1; cube: rgb1-up, rgb2-side, rgb3-down
|
||||
} mjtBuiltin;
|
||||
|
||||
|
||||
typedef enum _mjtMark { // mark type for procedural textures
|
||||
mjMARK_NONE = 0, // no mark
|
||||
mjMARK_EDGE, // edges
|
||||
mjMARK_CROSS, // cross
|
||||
mjMARK_RANDOM // random dots
|
||||
} mjtMark;
|
||||
|
||||
|
||||
//---------------------------------- attribute structs (mjm) ---------------------------------------
|
||||
|
||||
typedef struct _mjmOrientation { // alternative orientation specifiers
|
||||
@@ -309,6 +325,40 @@ typedef struct _mjmFlex {
|
||||
} mjmFlex;
|
||||
|
||||
|
||||
typedef struct _mjmTexture { // texture specification
|
||||
mjElement element; // internal, do not modify
|
||||
mjString name; // name
|
||||
mjString classname; // class name
|
||||
mjtTexture type; // texture type
|
||||
|
||||
// method 1: builtin
|
||||
int builtin; // builtin type (mjtBuiltin)
|
||||
int mark; // mark type (mjtMark)
|
||||
double rgb1[3]; // first color for builtin
|
||||
double rgb2[3]; // second color for builtin
|
||||
double markrgb[3]; // mark color
|
||||
double random; // probability of random dots
|
||||
int height; // height in pixels (square for cube and skybox)
|
||||
int width; // width in pixels
|
||||
|
||||
// method 2: single file
|
||||
mjString content_type; // content type of file
|
||||
mjString file; // png file to load; use for all sides of cube
|
||||
int gridsize[2]; // size of grid for composite file; (1,1)-repeat
|
||||
char gridlayout[13]; // row-major: L,R,F,B,U,D for faces; . for unused
|
||||
|
||||
// method 3: separate files
|
||||
mjStringVec cubefiles; // different file for each side of the cube
|
||||
|
||||
// flip options
|
||||
mjtByte hflip; // horizontal flip
|
||||
mjtByte vflip; // vertical flip
|
||||
|
||||
// other
|
||||
mjString info; // message appended to compiler errors
|
||||
} mjmTexture;
|
||||
|
||||
|
||||
typedef struct _mjmMaterial { // material specification
|
||||
mjElement element; // internal, do not modify
|
||||
mjString name; // name
|
||||
@@ -508,6 +558,9 @@ MJAPI mjmFrame* mjm_addFrame(mjmBody* body, mjmFrame* parentframe);
|
||||
// Add flex to model.
|
||||
MJAPI mjmFlex* mjm_addFlex(void* model);
|
||||
|
||||
// Add texture to model.
|
||||
MJAPI mjmTexture* mjm_addTexture(void* model);
|
||||
|
||||
// Add material to model.
|
||||
MJAPI mjmMaterial* mjm_addMaterial(void* model, void* defspec);
|
||||
|
||||
@@ -562,6 +615,9 @@ MJAPI void mjm_setString(mjString dest, const char* text);
|
||||
// Split text to entries and copy to destination string vector.
|
||||
MJAPI void mjm_setStringVec(mjStringVec dest, const char* text);
|
||||
|
||||
// Set specific entry in destination 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);
|
||||
|
||||
@@ -616,6 +672,9 @@ MJAPI void mjm_defaultLight(mjmLight& light);
|
||||
// Default flex attributes.
|
||||
MJAPI void mjm_defaultFlex(mjmFlex& flex);
|
||||
|
||||
// Default texture attributes.
|
||||
MJAPI void mjm_defaultTexture(mjmTexture& texture);
|
||||
|
||||
// Default material attributes.
|
||||
MJAPI void mjm_defaultMaterial(mjmMaterial& material);
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <cstring>
|
||||
#include <mujoco/mjmodel.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "cc/array_safety.h"
|
||||
#include "user/user_api.h"
|
||||
#include "user/user_util.h"
|
||||
|
||||
@@ -191,6 +192,20 @@ void mjm_defaultFlex(mjmFlex& flex) {
|
||||
|
||||
|
||||
|
||||
// default texture attributes
|
||||
void mjm_defaultTexture(mjmTexture& texture) {
|
||||
memset(&texture, 0, sizeof(mjmTexture));
|
||||
texture.type = mjTEXTURE_CUBE;
|
||||
mjuu_setvec(texture.rgb1, 0.8, 0.8, 0.8);
|
||||
mjuu_setvec(texture.rgb2, 0.5, 0.5, 0.5);
|
||||
mjuu_setvec(texture.markrgb, 0, 0, 0);
|
||||
texture.random = 0.01;
|
||||
texture.gridsize[0] = texture.gridsize[1] = 1;
|
||||
mujoco::util::strcpy_arr(texture.gridlayout, "............");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// default material attributes
|
||||
void mjm_defaultMaterial(mjmMaterial& material) {
|
||||
memset(&material, 0, sizeof(mjmMaterial));
|
||||
|
||||
@@ -904,6 +904,7 @@ void mjCModel::SetDefaultNames(std::vector<T*>& assets) {
|
||||
|
||||
// use filename if name is missing
|
||||
for (int i=0; i<assets.size(); i++) {
|
||||
assets[i]->CopyFromSpec();
|
||||
if (assets[i]->name.empty()) {
|
||||
stripped = mjuu_strippath(assets[i]->get_file());
|
||||
assets[i]->name = mjuu_stripext(stripped);
|
||||
|
||||
+52
-35
@@ -2579,35 +2579,50 @@ void mjCHField::Compile(const mjVFS* vfs) {
|
||||
|
||||
// initialize defaults
|
||||
mjCTexture::mjCTexture(mjCModel* _model) {
|
||||
mjm_defaultTexture(spec);
|
||||
|
||||
// set model pointer
|
||||
model = _model;
|
||||
|
||||
// clear user settings: builtin
|
||||
type = mjTEXTURE_CUBE;
|
||||
builtin = mjBUILTIN_NONE;
|
||||
mark = mjMARK_NONE;
|
||||
mjuu_setvec(rgb1, 0.8, 0.8, 0.8);
|
||||
mjuu_setvec(rgb2, 0.5, 0.5, 0.5);
|
||||
mjuu_setvec(markrgb, 0, 0, 0);
|
||||
random = 0.01;
|
||||
height = width = 0;
|
||||
|
||||
// clear user settings: single file
|
||||
file.clear();
|
||||
gridsize[0] = gridsize[1] = 1;
|
||||
mju::strcpy_arr(gridlayout, "............");
|
||||
spec_file_.clear();
|
||||
spec_content_type_.clear();
|
||||
|
||||
// clear user settings: separate file
|
||||
for (int i=0; i<6; i++) {
|
||||
cubefiles[i].clear();
|
||||
}
|
||||
|
||||
// clear flip options
|
||||
hflip = false;
|
||||
vflip = false;
|
||||
spec_cubefiles_.assign(6, "");
|
||||
|
||||
// clear internal variables
|
||||
rgb = 0;
|
||||
|
||||
// point to local (needs to be after defaults)
|
||||
PointToLocal();
|
||||
|
||||
// in case this camera is not compiled
|
||||
CopyFromSpec();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void mjCTexture::PointToLocal() {
|
||||
spec.element = (mjElement)this;
|
||||
spec.name = (mjString)&name;
|
||||
spec.classname = (mjString)&classname;
|
||||
spec.file = (mjString)&spec_file_;
|
||||
spec.content_type = (mjString)&spec_content_type_;
|
||||
spec.cubefiles = (mjStringVec)&spec_cubefiles_;
|
||||
spec.info = (mjString)&info;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void mjCTexture::CopyFromSpec() {
|
||||
*static_cast<mjmTexture*>(this) = spec;
|
||||
file_ = spec_file_;
|
||||
content_type_ = spec_content_type_;
|
||||
cubefiles_ = spec_cubefiles_;
|
||||
file = (mjString)&file_;
|
||||
content_type = (mjString)&content_type_;
|
||||
cubefiles = (mjStringVec)&cubefiles_;
|
||||
}
|
||||
|
||||
|
||||
@@ -2930,7 +2945,7 @@ void mjCTexture::LoadCustom(mjResource* resource,
|
||||
void mjCTexture::LoadFlip(string filename, const mjVFS* vfs,
|
||||
std::vector<unsigned char>& image,
|
||||
unsigned int& w, unsigned int& h) {
|
||||
std::string asset_type = GetAssetContentType(filename, content_type);
|
||||
std::string asset_type = GetAssetContentType(filename, content_type_);
|
||||
|
||||
// fallback to custom
|
||||
if (asset_type.empty()) {
|
||||
@@ -3017,7 +3032,7 @@ void mjCTexture::Load2D(string filename, const mjVFS* vfs) {
|
||||
rgb = (mjtByte*) mju_malloc(3*width*height);
|
||||
if (!rgb) {
|
||||
throw mjCError(this, "Could not allocate memory for texture '%s' (id %d)",
|
||||
(const char*)file.c_str(), id);
|
||||
(const char*)file_.c_str(), id);
|
||||
}
|
||||
memcpy(rgb, image.data(), 3*width*height);
|
||||
image.clear();
|
||||
@@ -3043,7 +3058,7 @@ void mjCTexture::LoadCubeSingle(string filename, const mjVFS* vfs) {
|
||||
if (w/gridsize[1]!=h/gridsize[0] || (w%gridsize[1]) || (h%gridsize[0])) {
|
||||
throw mjCError(this,
|
||||
"PNG size must be integer multiple of gridsize in texture '%s' (id %d)",
|
||||
(const char*)file.c_str(), id);
|
||||
(const char*)file_.c_str(), id);
|
||||
}
|
||||
|
||||
// assign size: repeated or full
|
||||
@@ -3059,7 +3074,7 @@ void mjCTexture::LoadCubeSingle(string filename, const mjVFS* vfs) {
|
||||
if (!rgb) {
|
||||
throw mjCError(this,
|
||||
"Could not allocate memory for texture '%s' (id %d)",
|
||||
(const char*)file.c_str(), id);
|
||||
(const char*)file_.c_str(), id);
|
||||
}
|
||||
|
||||
// copy: repeated
|
||||
@@ -3090,7 +3105,7 @@ void mjCTexture::LoadCubeSingle(string filename, const mjVFS* vfs) {
|
||||
i = 5;
|
||||
} else if (gridlayout[k]!='.')
|
||||
throw mjCError(this, "gridlayout symbol is not among '.RLUDFB' in texture '%s' (id %d)",
|
||||
(const char*)file.c_str(), id);
|
||||
(const char*)file_.c_str(), id);
|
||||
|
||||
// load if specified
|
||||
if (i>=0) {
|
||||
@@ -3132,14 +3147,14 @@ void mjCTexture::LoadCubeSeparate(const mjVFS* vfs) {
|
||||
|
||||
// process nonempty files
|
||||
for (int i=0; i<6; i++) {
|
||||
if (!cubefiles[i].empty()) {
|
||||
if (!cubefiles_[i].empty()) {
|
||||
// remove path from file if necessary
|
||||
if (model->strippath) {
|
||||
cubefiles[i] = mjuu_strippath(cubefiles[i]);
|
||||
cubefiles_[i] = mjuu_strippath(cubefiles_[i]);
|
||||
}
|
||||
|
||||
// make filename
|
||||
string filename = mjuu_makefullname(model->modelfiledir, model->texturedir, cubefiles[i]);
|
||||
string filename = mjuu_makefullname(model->modelfiledir, model->texturedir, cubefiles_[i]);
|
||||
|
||||
// load PNG or custom
|
||||
unsigned int w, h;
|
||||
@@ -3150,7 +3165,7 @@ void mjCTexture::LoadCubeSeparate(const mjVFS* vfs) {
|
||||
if (w!=h) {
|
||||
throw mjCError(this,
|
||||
"Non-square PNG file '%s' in cube or skybox id %d",
|
||||
(const char*)cubefiles[i].c_str(), id);
|
||||
(const char*)cubefiles_[i].c_str(), id);
|
||||
}
|
||||
|
||||
// first file: set size and allocate data
|
||||
@@ -3169,7 +3184,7 @@ void mjCTexture::LoadCubeSeparate(const mjVFS* vfs) {
|
||||
else if (width!=w) {
|
||||
throw mjCError(this,
|
||||
"PNG file '%s' has incompatible size in texture id %d",
|
||||
(const char*)cubefiles[i].c_str(), id);
|
||||
(const char*)cubefiles_[i].c_str(), id);
|
||||
}
|
||||
|
||||
// copy data
|
||||
@@ -3199,6 +3214,8 @@ void mjCTexture::LoadCubeSeparate(const mjVFS* vfs) {
|
||||
|
||||
// compiler
|
||||
void mjCTexture::Compile(const mjVFS* vfs) {
|
||||
CopyFromSpec();
|
||||
|
||||
// builtin
|
||||
if (builtin!=mjBUILTIN_NONE) {
|
||||
// check size
|
||||
@@ -3230,14 +3247,14 @@ void mjCTexture::Compile(const mjVFS* vfs) {
|
||||
}
|
||||
|
||||
// single file
|
||||
else if (!file.empty()) {
|
||||
else if (!file_.empty()) {
|
||||
// remove path from file if necessary
|
||||
if (model->strippath) {
|
||||
file = mjuu_strippath(file);
|
||||
file_ = mjuu_strippath(file_);
|
||||
}
|
||||
|
||||
// make filename
|
||||
string filename = mjuu_makefullname(model->modelfiledir, model->texturedir, file);
|
||||
string filename = mjuu_makefullname(model->modelfiledir, model->texturedir, file_);
|
||||
|
||||
// dispatch
|
||||
if (type==mjTEXTURE_2D) {
|
||||
@@ -3259,14 +3276,14 @@ void mjCTexture::Compile(const mjVFS* vfs) {
|
||||
// at least one cubefile must be defined
|
||||
bool defined = false;
|
||||
for (int i=0; i<6; i++) {
|
||||
if (!cubefiles[i].empty()) {
|
||||
if (!cubefiles_[i].empty()) {
|
||||
defined = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!defined) {
|
||||
throw mjCError(this,
|
||||
"No cubefiles defined in cube or skybox texture '%s' (id %d)",
|
||||
"No cubefiles_ defined in cube or skybox texture '%s' (id %d)",
|
||||
(const char*)name.c_str(), id);
|
||||
}
|
||||
|
||||
|
||||
+17
-43
@@ -68,24 +68,6 @@ class mjXURDF; // defined in xml_urdf
|
||||
const int mjGEOMINFO[mjNGEOMTYPES] = {3, 0, 1, 2, 3, 2, 3, 0};
|
||||
|
||||
|
||||
// builtin type for procedural textures
|
||||
typedef enum _mjtBuiltin {
|
||||
mjBUILTIN_NONE = 0, // no builtin
|
||||
mjBUILTIN_GRADIENT, // circular gradient: rgb1->rgb2->rgb3
|
||||
mjBUILTIN_CHECKER, // checker pattern: rgb1, rgb2
|
||||
mjBUILTIN_FLAT // 2d: rgb1; cube: rgb1-up, rgb2-side, rgb3-down
|
||||
} mjtBuiltin;
|
||||
|
||||
|
||||
// mark type for procedural textures
|
||||
typedef enum _mjtMark {
|
||||
mjMARK_NONE = 0, // no mark
|
||||
mjMARK_EDGE, // paint edges
|
||||
mjMARK_CROSS, // paint cross
|
||||
mjMARK_RANDOM // paint random dots
|
||||
} mjtMark;
|
||||
|
||||
|
||||
// error information
|
||||
class [[nodiscard]] mjCError {
|
||||
public:
|
||||
@@ -871,7 +853,7 @@ class mjCHField : public mjCBase {
|
||||
//------------------------- class mjCTexture -------------------------------------------------------
|
||||
// Describes a texture
|
||||
|
||||
class mjCTexture : public mjCBase {
|
||||
class mjCTexture : public mjCBase, private mjmTexture {
|
||||
friend class mjCModel;
|
||||
friend class mjXReader;
|
||||
friend class mjXWriter;
|
||||
@@ -879,32 +861,17 @@ class mjCTexture : public mjCBase {
|
||||
public:
|
||||
~mjCTexture(); // destructor
|
||||
|
||||
std::string get_file() const { return file; }
|
||||
mjmTexture spec;
|
||||
using mjCBase::name;
|
||||
using mjCBase::classname;
|
||||
using mjCBase::info;
|
||||
|
||||
mjtTexture type; // texture type
|
||||
void CopyFromSpec(void);
|
||||
void PointToLocal(void);
|
||||
|
||||
// method 1: builtin
|
||||
mjtBuiltin builtin; // builtin type
|
||||
mjtMark mark; // mark type
|
||||
double rgb1[3]; // first color for builtin
|
||||
double rgb2[3]; // second color for builtin
|
||||
double markrgb[3]; // mark color
|
||||
double random; // probability of random dots
|
||||
int height; // height in pixels (square for cube and skybox)
|
||||
int width; // width in pixels
|
||||
|
||||
// method 2: single file
|
||||
std::string content_type; // content type of file
|
||||
std::string file; // png file to load; use for all sides of cube
|
||||
int gridsize[2]; // size of grid for composite file; (1,1)-repeat
|
||||
char gridlayout[13]; // row-major: L,R,F,B,U,D for faces; . for unused
|
||||
|
||||
// method 3: separate files
|
||||
std::string cubefiles[6]; // different file for each side of the cube
|
||||
|
||||
// flip options
|
||||
bool hflip; // horizontal flip
|
||||
bool vflip; // vertical flip
|
||||
std::string get_file() const { return file_; }
|
||||
std::string get_content_type() const { return content_type_; }
|
||||
std::vector<std::string> get_cubefiles() const { return cubefiles_; }
|
||||
|
||||
private:
|
||||
mjCTexture(mjCModel*); // constructor
|
||||
@@ -928,6 +895,13 @@ class mjCTexture : public mjCBase {
|
||||
unsigned int& w, unsigned int& h);
|
||||
|
||||
mjtByte* rgb; // rgb data
|
||||
std::string file_;
|
||||
std::string content_type_;
|
||||
std::vector<std::string> cubefiles_;
|
||||
|
||||
std::string spec_file_;
|
||||
std::string spec_content_type_;
|
||||
std::vector<std::string> spec_cubefiles_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -2980,7 +2980,7 @@ void mjXReader::Visual(XMLElement* section) {
|
||||
// asset section parser
|
||||
void mjXReader::Asset(XMLElement* section) {
|
||||
int n;
|
||||
string text, name;
|
||||
string text, name, texname, content_type, file;
|
||||
XMLElement* elem;
|
||||
|
||||
// iterate over child elements
|
||||
@@ -2998,16 +2998,25 @@ void mjXReader::Asset(XMLElement* section) {
|
||||
// texture sub-element
|
||||
if (name=="texture") {
|
||||
// create texture
|
||||
mjCTexture* ptex = model->AddTexture();
|
||||
GetXMLPos(elem, ptex);
|
||||
mjmTexture* ptex = mjm_addTexture(model);
|
||||
|
||||
// write error info
|
||||
mjm_setString(ptex->info,
|
||||
std::string("line = " + std::to_string(elem->GetLineNum()) + ", column = -1").c_str());
|
||||
|
||||
// read attributes
|
||||
if (MapValue(elem, "type", &n, texture_map, texture_sz)) {
|
||||
ptex->type = (mjtTexture)n;
|
||||
}
|
||||
ReadAttrTxt(elem, "name", ptex->name);
|
||||
ReadAttrTxt(elem, "content_type", ptex->content_type);
|
||||
ReadAttrTxt(elem, "file", ptex->file);
|
||||
if (ReadAttrTxt(elem, "name", texname)) {
|
||||
mjm_setString(ptex->name, texname.c_str());
|
||||
}
|
||||
if (ReadAttrTxt(elem, "content_type", content_type)) {
|
||||
mjm_setString(ptex->content_type, content_type.c_str());
|
||||
}
|
||||
if (ReadAttrTxt(elem, "file", file)) {
|
||||
mjm_setString(ptex->file, file.c_str());
|
||||
}
|
||||
ReadAttrInt(elem, "width", &ptex->width);
|
||||
ReadAttrInt(elem, "height", &ptex->height);
|
||||
ReadAttr(elem, "rgb1", 3, ptex->rgb1, text);
|
||||
@@ -3042,12 +3051,16 @@ void mjXReader::Asset(XMLElement* section) {
|
||||
}
|
||||
|
||||
// separate files
|
||||
ReadAttrTxt(elem, "fileright", ptex->cubefiles[0]);
|
||||
ReadAttrTxt(elem, "fileleft", ptex->cubefiles[1]);
|
||||
ReadAttrTxt(elem, "fileup", ptex->cubefiles[2]);
|
||||
ReadAttrTxt(elem, "filedown", ptex->cubefiles[3]);
|
||||
ReadAttrTxt(elem, "filefront", ptex->cubefiles[4]);
|
||||
ReadAttrTxt(elem, "fileback", ptex->cubefiles[5]);
|
||||
std::vector<string> cubefiles(6);
|
||||
ReadAttrTxt(elem, "fileright", cubefiles[0]);
|
||||
ReadAttrTxt(elem, "fileleft", cubefiles[1]);
|
||||
ReadAttrTxt(elem, "fileup", cubefiles[2]);
|
||||
ReadAttrTxt(elem, "filedown", cubefiles[3]);
|
||||
ReadAttrTxt(elem, "filefront", cubefiles[4]);
|
||||
ReadAttrTxt(elem, "fileback", cubefiles[5]);
|
||||
for (int i = 0; i < cubefiles.size(); i++) {
|
||||
mjm_setInStringVec(ptex->cubefiles, i, cubefiles[i].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// material sub-element
|
||||
|
||||
@@ -1358,16 +1358,16 @@ void mjXWriter::Asset(XMLElement* root) {
|
||||
// write textures loaded from files
|
||||
else {
|
||||
// write single file
|
||||
WriteAttrTxt(elem, "content_type", ptex->content_type);
|
||||
WriteAttrTxt(elem, "file", ptex->file);
|
||||
WriteAttrTxt(elem, "content_type", ptex->get_content_type());
|
||||
WriteAttrTxt(elem, "file", ptex->get_file());
|
||||
|
||||
// write separate files
|
||||
WriteAttrTxt(elem, "fileright", ptex->cubefiles[0]);
|
||||
WriteAttrTxt(elem, "fileleft", ptex->cubefiles[1]);
|
||||
WriteAttrTxt(elem, "fileup", ptex->cubefiles[2]);
|
||||
WriteAttrTxt(elem, "filedown", ptex->cubefiles[3]);
|
||||
WriteAttrTxt(elem, "filefront", ptex->cubefiles[4]);
|
||||
WriteAttrTxt(elem, "fileback", ptex->cubefiles[5]);
|
||||
WriteAttrTxt(elem, "fileright", ptex->get_cubefiles()[0]);
|
||||
WriteAttrTxt(elem, "fileleft", ptex->get_cubefiles()[1]);
|
||||
WriteAttrTxt(elem, "fileup", ptex->get_cubefiles()[2]);
|
||||
WriteAttrTxt(elem, "filedown", ptex->get_cubefiles()[3]);
|
||||
WriteAttrTxt(elem, "filefront", ptex->get_cubefiles()[4]);
|
||||
WriteAttrTxt(elem, "fileback", ptex->get_cubefiles()[5]);
|
||||
if (ptex->hflip) {
|
||||
WriteAttrKey(elem, "hflip", bool_map, 2, 1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user