Allow multiple textures per material in MJCF.
PiperOrigin-RevId: 654795013 Change-Id: I418b72533484d00accaf801a342aa183e602a2d0
This commit is contained in:
committed by
Copybara-Service
parent
e79efa60d6
commit
33e5960653
+86
-64
@@ -3217,7 +3217,7 @@ mjCTexture::mjCTexture(mjCModel* _model) {
|
||||
spec_cubefiles_.assign(6, "");
|
||||
|
||||
// clear internal variables
|
||||
rgb.clear();
|
||||
data.clear();
|
||||
|
||||
// point to local
|
||||
PointToLocal();
|
||||
@@ -3266,14 +3266,14 @@ void mjCTexture::CopyFromSpec() {
|
||||
cubefiles_ = spec_cubefiles_;
|
||||
|
||||
// clear precompiled asset. TODO: use asset cache
|
||||
rgb.clear();
|
||||
data.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// free data storage allocated by lodepng
|
||||
mjCTexture::~mjCTexture() {
|
||||
rgb.clear();
|
||||
data.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -3366,21 +3366,21 @@ void mjCTexture::Builtin2D(void) {
|
||||
double pos = 2*sqrt(x*x+y*y) - 1;
|
||||
|
||||
// interpolate through sigmoid
|
||||
interp(rgb.data() + 3*(r*width+c), rgb2, rgb1, pos);
|
||||
interp(data.data() + 3*(r*width+c), rgb2, rgb1, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checker
|
||||
else if (builtin==mjBUILTIN_CHECKER) {
|
||||
checker(rgb.data(), RGB1, RGB2, width, height);
|
||||
checker(data.data(), RGB1, RGB2, width, height);
|
||||
}
|
||||
|
||||
// flat
|
||||
else if (builtin==mjBUILTIN_FLAT) {
|
||||
for (int r=0; r<height; r++) {
|
||||
for (int c=0; c<width; c++) {
|
||||
memcpy(rgb.data()+3*(r*width+c), RGB1, 3);
|
||||
memcpy(data.data()+3*(r*width+c), RGB1, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3390,28 +3390,28 @@ void mjCTexture::Builtin2D(void) {
|
||||
// edge
|
||||
if (mark==mjMARK_EDGE) {
|
||||
for (int r=0; r<height; r++) {
|
||||
memcpy(rgb.data()+3*(r*width+0), RGBm, 3);
|
||||
memcpy(rgb.data()+3*(r*width+width-1), RGBm, 3);
|
||||
memcpy(data.data()+3*(r*width+0), RGBm, 3);
|
||||
memcpy(data.data()+3*(r*width+width-1), RGBm, 3);
|
||||
}
|
||||
for (int c=0; c<width; c++) {
|
||||
memcpy(rgb.data()+3*(0*width+c), RGBm, 3);
|
||||
memcpy(rgb.data()+3*((height-1)*width+c), RGBm, 3);
|
||||
memcpy(data.data()+3*(0*width+c), RGBm, 3);
|
||||
memcpy(data.data()+3*((height-1)*width+c), RGBm, 3);
|
||||
}
|
||||
}
|
||||
|
||||
// cross
|
||||
else if (mark==mjMARK_CROSS) {
|
||||
for (int r=0; r<height; r++) {
|
||||
memcpy(rgb.data()+3*(r*width+width/2), RGBm, 3);
|
||||
memcpy(data.data()+3*(r*width+width/2), RGBm, 3);
|
||||
}
|
||||
for (int c=0; c<width; c++) {
|
||||
memcpy(rgb.data()+3*(height/2*width+c), RGBm, 3);
|
||||
memcpy(data.data()+3*(height/2*width+c), RGBm, 3);
|
||||
}
|
||||
}
|
||||
|
||||
// random dots
|
||||
else if (mark==mjMARK_RANDOM && random>0) {
|
||||
randomdot(rgb.data(), markrgb, width, height, random);
|
||||
randomdot(data.data(), markrgb, width, height, random);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3446,26 +3446,26 @@ void mjCTexture::BuiltinCube(void) {
|
||||
|
||||
// set sides
|
||||
interp(RGBi, rgb1, rgb2, elside);
|
||||
memcpy(rgb.data() + 0 * 3 * ww + 3 * (r * w + c), RGBi, 3); // 0: right
|
||||
memcpy(rgb.data() + 1 * 3 * ww + 3 * (r * w + c), RGBi, 3); // 1: left
|
||||
memcpy(rgb.data() + 4 * 3 * ww + 3 * (r * w + c), RGBi, 3); // 4: front
|
||||
memcpy(rgb.data() + 5 * 3 * ww + 3 * (r * w + c), RGBi, 3); // 5: back
|
||||
memcpy(data.data() + 0 * 3 * ww + 3 * (r * w + c), RGBi, 3); // 0: right
|
||||
memcpy(data.data() + 1 * 3 * ww + 3 * (r * w + c), RGBi, 3); // 1: left
|
||||
memcpy(data.data() + 4 * 3 * ww + 3 * (r * w + c), RGBi, 3); // 4: front
|
||||
memcpy(data.data() + 5 * 3 * ww + 3 * (r * w + c), RGBi, 3); // 5: back
|
||||
|
||||
// set up and down
|
||||
interp(rgb.data() + 2 * 3 * ww + 3 * (r * w + c), rgb1, rgb2, elup); // 2: up
|
||||
interp(rgb.data() + 3 * 3 * ww + 3 * (r * w + c), rgb1, rgb2, -elup); // 3: down
|
||||
interp(data.data() + 2 * 3 * ww + 3 * (r * w + c), rgb1, rgb2, elup); // 2: up
|
||||
interp(data.data() + 3 * 3 * ww + 3 * (r * w + c), rgb1, rgb2, -elup); // 3: down
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checker
|
||||
else if (builtin == mjBUILTIN_CHECKER) {
|
||||
checker(rgb.data() + 0 * 3 * ww, RGB1, RGB2, w, w);
|
||||
checker(rgb.data() + 1 * 3 * ww, RGB1, RGB2, w, w);
|
||||
checker(rgb.data() + 2 * 3 * ww, RGB1, RGB2, w, w);
|
||||
checker(rgb.data() + 3 * 3 * ww, RGB1, RGB2, w, w);
|
||||
checker(rgb.data() + 4 * 3 * ww, RGB2, RGB1, w, w);
|
||||
checker(rgb.data() + 5 * 3 * ww, RGB2, RGB1, w, w);
|
||||
checker(data.data() + 0 * 3 * ww, RGB1, RGB2, w, w);
|
||||
checker(data.data() + 1 * 3 * ww, RGB1, RGB2, w, w);
|
||||
checker(data.data() + 2 * 3 * ww, RGB1, RGB2, w, w);
|
||||
checker(data.data() + 3 * 3 * ww, RGB1, RGB2, w, w);
|
||||
checker(data.data() + 4 * 3 * ww, RGB2, RGB1, w, w);
|
||||
checker(data.data() + 5 * 3 * ww, RGB2, RGB1, w, w);
|
||||
}
|
||||
|
||||
// flat
|
||||
@@ -3473,14 +3473,14 @@ void mjCTexture::BuiltinCube(void) {
|
||||
for (int r = 0; r < w; r++) {
|
||||
for (int c = 0; c < w; c++) {
|
||||
// set sides and up
|
||||
memcpy(rgb.data() + 0 * 3 * ww + 3 * (r * w + c), RGB1, 3);
|
||||
memcpy(rgb.data() + 1 * 3 * ww + 3 * (r * w + c), RGB1, 3);
|
||||
memcpy(rgb.data() + 2 * 3 * ww + 3 * (r * w + c), RGB1, 3);
|
||||
memcpy(rgb.data() + 4 * 3 * ww + 3 * (r * w + c), RGB1, 3);
|
||||
memcpy(rgb.data() + 5 * 3 * ww + 3 * (r * w + c), RGB1, 3);
|
||||
memcpy(data.data() + 0 * 3 * ww + 3 * (r * w + c), RGB1, 3);
|
||||
memcpy(data.data() + 1 * 3 * ww + 3 * (r * w + c), RGB1, 3);
|
||||
memcpy(data.data() + 2 * 3 * ww + 3 * (r * w + c), RGB1, 3);
|
||||
memcpy(data.data() + 4 * 3 * ww + 3 * (r * w + c), RGB1, 3);
|
||||
memcpy(data.data() + 5 * 3 * ww + 3 * (r * w + c), RGB1, 3);
|
||||
|
||||
// set down
|
||||
memcpy(rgb.data() + 3 * 3 * ww + 3 * (r * w + c), RGB2, 3);
|
||||
memcpy(data.data() + 3 * 3 * ww + 3 * (r * w + c), RGB2, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3491,12 +3491,12 @@ void mjCTexture::BuiltinCube(void) {
|
||||
if (mark == mjMARK_EDGE) {
|
||||
for (int j = 0; j < 6; j++) {
|
||||
for (int r = 0; r < w; r++) {
|
||||
memcpy(rgb.data() + j * 3 * ww + 3 * (r * w + 0), RGBm, 3);
|
||||
memcpy(rgb.data() + j * 3 * ww + 3 * (r * w + w - 1), RGBm, 3);
|
||||
memcpy(data.data() + j * 3 * ww + 3 * (r * w + 0), RGBm, 3);
|
||||
memcpy(data.data() + j * 3 * ww + 3 * (r * w + w - 1), RGBm, 3);
|
||||
}
|
||||
for (int c = 0; c < w; c++) {
|
||||
memcpy(rgb.data() + j * 3 * ww + 3 * (0 * w + c), RGBm, 3);
|
||||
memcpy(rgb.data() + j * 3 * ww + 3 * ((w - 1) * w + c), RGBm, 3);
|
||||
memcpy(data.data() + j * 3 * ww + 3 * (0 * w + c), RGBm, 3);
|
||||
memcpy(data.data() + j * 3 * ww + 3 * ((w - 1) * w + c), RGBm, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3505,17 +3505,17 @@ void mjCTexture::BuiltinCube(void) {
|
||||
else if (mark == mjMARK_CROSS) {
|
||||
for (int j = 0; j < 6; j++) {
|
||||
for (int r = 0; r < w; r++) {
|
||||
memcpy(rgb.data() + j * 3 * ww + 3 * (r * w + w / 2), RGBm, 3);
|
||||
memcpy(data.data() + j * 3 * ww + 3 * (r * w + w / 2), RGBm, 3);
|
||||
}
|
||||
for (int c = 0; c < w; c++) {
|
||||
memcpy(rgb.data() + j * 3 * ww + 3 * (w / 2 * w + c), RGBm, 3);
|
||||
memcpy(data.data() + j * 3 * ww + 3 * (w / 2 * w + c), RGBm, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// random dots
|
||||
else if (mark == mjMARK_RANDOM && random > 0) {
|
||||
randomdot(rgb.data(), markrgb, w, height, random);
|
||||
randomdot(data.data(), markrgb, w, height, random);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3523,14 +3523,23 @@ void mjCTexture::BuiltinCube(void) {
|
||||
void mjCTexture::LoadPNG(mjResource* resource,
|
||||
std::vector<unsigned char>& image,
|
||||
unsigned int& w, unsigned int& h) {
|
||||
PNGImage png_image = PNGImage::Load(this, resource, LCT_RGB);
|
||||
LodePNGColorType color_type;
|
||||
if (nchannel == 4) {
|
||||
color_type = LCT_RGBA;
|
||||
} else if (nchannel == 3) {
|
||||
color_type = LCT_RGB;
|
||||
} else if (nchannel == 1) {
|
||||
color_type = LCT_GREY;
|
||||
} else {
|
||||
throw mjCError(this, "Unsupported number of channels: %s",
|
||||
std::to_string(nchannel).c_str());
|
||||
}
|
||||
PNGImage png_image = PNGImage::Load(this, resource, color_type);
|
||||
w = png_image.Width();
|
||||
h = png_image.Height();
|
||||
image = png_image.MoveData();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// load custom file
|
||||
void mjCTexture::LoadCustom(mjResource* resource,
|
||||
std::vector<unsigned char>& image,
|
||||
@@ -3601,6 +3610,10 @@ void mjCTexture::LoadFlip(std::string filename, const mjVFS* vfs,
|
||||
|
||||
// horizontal flip
|
||||
if (hflip) {
|
||||
if (nchannel != 3) {
|
||||
throw mjCError(
|
||||
this, "currently only 3-channel textures support horizontal flip");
|
||||
}
|
||||
for (int r=0; r<h; r++) {
|
||||
for (int c=0; c<w/2; c++) {
|
||||
int c1 = w-1-c;
|
||||
@@ -3623,6 +3636,10 @@ void mjCTexture::LoadFlip(std::string filename, const mjVFS* vfs,
|
||||
|
||||
// vertical flip
|
||||
if (vflip) {
|
||||
if (nchannel != 3) {
|
||||
throw mjCError(
|
||||
this, "currently only 3-channel textures support vertical flip");
|
||||
}
|
||||
for (int r=0; r<h/2; r++) {
|
||||
for (int c=0; c<w; c++) {
|
||||
int r1 = h-1-r;
|
||||
@@ -3658,12 +3675,12 @@ void mjCTexture::Load2D(std::string filename, const mjVFS* vfs) {
|
||||
height = h;
|
||||
|
||||
// allocate and copy data
|
||||
rgb.assign(3*width*height, 0);
|
||||
if (rgb.empty()) {
|
||||
data.assign(nchannel*width*height, 0);
|
||||
if (data.empty()) {
|
||||
throw mjCError(this, "Could not allocate memory for texture '%s' (id %d)",
|
||||
(const char*)file_.c_str(), id);
|
||||
}
|
||||
memcpy(rgb.data(), image.data(), 3*width*height);
|
||||
memcpy(data.data(), image.data(), nchannel*width*height);
|
||||
image.clear();
|
||||
}
|
||||
|
||||
@@ -3697,8 +3714,8 @@ void mjCTexture::LoadCubeSingle(std::string filename, const mjVFS* vfs) {
|
||||
}
|
||||
|
||||
// allocate data
|
||||
rgb.assign(3*width*height, 0);
|
||||
if (rgb.empty()) {
|
||||
data.assign(3*width*height, 0);
|
||||
if (data.empty()) {
|
||||
throw mjCError(this,
|
||||
"Could not allocate memory for texture '%s' (id %d)",
|
||||
(const char*)file_.c_str(), id);
|
||||
@@ -3706,7 +3723,7 @@ void mjCTexture::LoadCubeSingle(std::string filename, const mjVFS* vfs) {
|
||||
|
||||
// copy: repeated
|
||||
if (gridsize[0]==1 && gridsize[1]==1) {
|
||||
memcpy(rgb.data(), image.data(), 3*width*width);
|
||||
memcpy(data.data(), image.data(), 3*width*width);
|
||||
}
|
||||
|
||||
// copy: grid
|
||||
@@ -3739,7 +3756,7 @@ void mjCTexture::LoadCubeSingle(std::string filename, const mjVFS* vfs) {
|
||||
int rstart = width*(k/gridsize[1]);
|
||||
int cstart = width*(k%gridsize[1]);
|
||||
for (int j=0; j<width; j++) {
|
||||
memcpy(rgb.data()+i*3*width*width+j*3*width, image.data()+(j+rstart)*3*w+3*cstart, 3*width);
|
||||
memcpy(data.data()+i*3*width*width+j*3*width, image.data()+(j+rstart)*3*w+3*cstart, 3*width);
|
||||
}
|
||||
|
||||
// mark as defined
|
||||
@@ -3753,7 +3770,7 @@ void mjCTexture::LoadCubeSingle(std::string filename, const mjVFS* vfs) {
|
||||
for (int k=0; k<width; k++) {
|
||||
for (int s=0; s<width; s++) {
|
||||
for (int j=0; j<3; j++) {
|
||||
rgb[i*3*width*width + 3*(k*width+s) + j] = (mjtByte)(255*rgb1[j]);
|
||||
data[i*3*width*width + 3*(k*width+s) + j] = (mjtByte)(255*rgb1[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3795,11 +3812,11 @@ void mjCTexture::LoadCubeSeparate(const mjVFS* vfs) {
|
||||
}
|
||||
|
||||
// first file: set size and allocate data
|
||||
if (rgb.empty()) {
|
||||
if (data.empty()) {
|
||||
width = w;
|
||||
height = 6*width;
|
||||
rgb.assign(3*width*height, 0);
|
||||
if (rgb.empty()) {
|
||||
data.assign(3*width*height, 0);
|
||||
if (data.empty()) {
|
||||
throw mjCError(this, "Could not allocate memory for texture");
|
||||
}
|
||||
}
|
||||
@@ -3812,7 +3829,7 @@ void mjCTexture::LoadCubeSeparate(const mjVFS* vfs) {
|
||||
}
|
||||
|
||||
// copy data
|
||||
memcpy(rgb.data()+i*3*width*width, image.data(), 3*width*width);
|
||||
memcpy(data.data()+i*3*width*width, image.data(), 3*width*width);
|
||||
image.clear();
|
||||
|
||||
// mark as defined
|
||||
@@ -3826,7 +3843,7 @@ void mjCTexture::LoadCubeSeparate(const mjVFS* vfs) {
|
||||
for (int k=0; k<width; k++) {
|
||||
for (int s=0; s<width; s++) {
|
||||
for (int j=0; j<3; j++) {
|
||||
rgb[i*3*width*width + 3*(k*width+s) + j] = (mjtByte)(255*rgb1[j]);
|
||||
data[i*3*width*width + 3*(k*width+s) + j] = (mjtByte)(255*rgb1[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3857,8 +3874,8 @@ void mjCTexture::Compile(const mjVFS* vfs) {
|
||||
}
|
||||
|
||||
// allocate data
|
||||
rgb.assign(3*width*height, 0);
|
||||
if (rgb.empty()) {
|
||||
data.assign(nchannel*width*height, 0);
|
||||
if (data.empty()) {
|
||||
throw mjCError(this, "Could not allocate memory for texture");
|
||||
}
|
||||
|
||||
@@ -3914,7 +3931,7 @@ void mjCTexture::Compile(const mjVFS* vfs) {
|
||||
}
|
||||
|
||||
// make sure someone allocated data; SHOULD NOT OCCUR
|
||||
if (rgb.empty()) {
|
||||
if (data.empty()) {
|
||||
throw mjCError(this, "texture '%s' (id %d) was not specified", name.c_str(), id);
|
||||
}
|
||||
}
|
||||
@@ -3927,10 +3944,13 @@ void mjCTexture::Compile(const mjVFS* vfs) {
|
||||
mjCMaterial::mjCMaterial(mjCModel* _model, mjCDef* _def) {
|
||||
mjs_defaultMaterial(&spec);
|
||||
elemtype = mjOBJ_MATERIAL;
|
||||
textures_.assign(mjNTEXROLE, "");
|
||||
spec_textures_.assign(mjNTEXROLE, "");
|
||||
|
||||
// clear internal
|
||||
spec_texture_.clear();
|
||||
texid = -1;
|
||||
for (int i=0; i<mjNTEXROLE; i++) {
|
||||
texid[i] = -1;
|
||||
}
|
||||
|
||||
// reset to default if given
|
||||
if (_def) {
|
||||
@@ -3969,16 +3989,16 @@ mjCMaterial& mjCMaterial::operator=(const mjCMaterial& other) {
|
||||
void mjCMaterial::PointToLocal() {
|
||||
spec.element = static_cast<mjsElement*>(this);
|
||||
spec.name = &name;
|
||||
spec.texture = &spec_texture_;
|
||||
spec.textures = &spec_textures_;
|
||||
spec.info = &info;
|
||||
texture = nullptr;
|
||||
textures = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void mjCMaterial::CopyFromSpec() {
|
||||
*static_cast<mjsMaterial*>(this) = spec;
|
||||
texture_ = spec_texture_;
|
||||
textures_ = spec_textures_;
|
||||
}
|
||||
|
||||
|
||||
@@ -3987,8 +4007,10 @@ void mjCMaterial::NameSpace(const mjCModel* m) {
|
||||
if (!name.empty()) {
|
||||
name = m->prefix + name + m->suffix;
|
||||
}
|
||||
if (!spec_texture_.empty() && model != m) {
|
||||
spec_texture_ = m->prefix + spec_texture_ + m->suffix;
|
||||
for (int i=0; i<mjNTEXROLE; i++) {
|
||||
if (!spec_textures_[i].empty() && model != m) {
|
||||
spec_textures_[i] = m->prefix + spec_textures_[i] + m->suffix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user