Skip to content

Commit

Permalink
Make seed fixed for random number generator when using `<texture mark…
Browse files Browse the repository at this point in the history
…="random"/>`

Also improve documentation regarding texture height and width attributes.

PiperOrigin-RevId: 648427167
Change-Id: I59a0fe75d3526f8563a5252584ed60ef7fb8fd70
  • Loading branch information
yuvaltassa authored and Copybara-Service committed Jul 1, 2024
1 parent c1ade85 commit f2c3be4
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 20 deletions.
36 changes: 21 additions & 15 deletions doc/XMLreference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1564,17 +1564,21 @@ still be specified here but this functionality is now deprecated and will be rem
This and the remaining attributes control the generation of procedural textures. If the value of this attribute is
different from "none", the texture is treated as procedural and any file names are ignored. The keywords have the
following meaning:
The **gradient** type generates a color gradient from rgb1 to rgb2. The interpolation in color space is done through
a sigmoid function. For cube and skybox textures the gradient is along the +Y axis, i.e., from top to bottom for
skybox rendering.

The **checker** type generates a 2-by-2 checker pattern with alternating colors given by rgb1 to rgb2. This is
suitable for rendering ground planes and also for marking objects with rotational symmetries. Note that 2d textures
can be scaled so as to repeat the pattern as many times as necessary. For cube and skybox textures, the checker
pattern is painted on each side of the cube.
**gradient**
Generates a color gradient from rgb1 to rgb2. The interpolation in color space is done through
a sigmoid function. For cube and skybox textures the gradient is along the +Y axis, i.e., from top to bottom for
skybox rendering.

The **flat** type fills the entire texture with rgb1, except for the bottom face of cube and skybox textures which is
filled with rgb2.
**checker**
Generates a 2-by-2 checker pattern with alternating colors given by rgb1 and rgb2. This is suitable for rendering
ground planes and also for marking objects with rotational symmetries. Note that 2d textures can be scaled so as
to repeat the pattern as many times as necessary. For cube and skybox textures, the checker pattern is painted on
each side of the cube.

**flat**
Fills the entire texture with rgb1, except for the bottom face of cube and skybox textures which is
filled with rgb2.

.. _asset-texture-rgb1:

Expand Down Expand Up @@ -1604,21 +1608,23 @@ still be specified here but this functionality is now deprecated and will be rem

:at:`random`: :at-val:`real, "0.01"`
When the mark attribute is set to "random", this attribute determines the probability of turning on each pixel. Note
that larger textures have more pixels, and the probability here is applied independently to each pixel - thus the
that larger textures have more pixels, and the probability here is applied independently to each pixel -- thus the
texture size and probability need to be adjusted jointly. Together with a gradient skybox texture, this can create
the appearance of a night sky with stars.
the appearance of a night sky with stars. The random number generator is initialized with a fixed seed.

.. _asset-texture-width:

:at:`width`: :at-val:`int, "0"`
The width of the procedural texture, i.e., the number of columns in the image. For cube and skybox procedural
textures the width and height must be equal. Larger values usually result in higher quality images, although in some
cases (e.g. checker patterns) small values are sufficient.
The width of a procedural texture, i.e., the number of columns in the image. Larger values usually result in higher
quality images, although in some cases (e.g. checker patterns) small values are sufficient. For textures loaded from
files, this attribute is ignored.

.. _asset-texture-height:

:at:`height`: :at-val:`int, "0"`
The height of the procedural texture, i.e., the number of rows in the image.
The height of the procedural texture, i.e., the number of rows in the image. For cube and skybox textures, this
attribute is ignored and the height is set to 6 times the width. For textures loaded from files, this attribute is
ignored.

.. _asset-texture-hflip:

Expand Down
20 changes: 15 additions & 5 deletions src/user/user_objects.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
#include <cmath>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <map>
#include <optional>
#include <random>
#include <sstream>
#include <string>
#include <string_view>
Expand Down Expand Up @@ -3227,9 +3227,15 @@ mjCTexture::~mjCTexture() {
// insert random dots
static void randomdot(unsigned char* rgb, const double* markrgb,
int width, int height, double probability) {
// make distribution using fixed seed
std::mt19937_64 rng;
rng.seed(42);
std::uniform_real_distribution<double> dist(0, 1);

// sample
for (int r=0; r<height; r++) {
for (int c=0; c<width; c++) {
if (rand()<probability*RAND_MAX) {
if (dist(rng)<probability) {
for (int j=0; j<3; j++) {
rgb[3*(r*width+c)+j] = (mjtByte)(255*markrgb[j]);
}
Expand Down Expand Up @@ -3779,14 +3785,18 @@ void mjCTexture::Compile(const mjVFS* vfs) {

// builtin
if (builtin != mjBUILTIN_NONE) {
// check size
if (width<1 || height<1) {
throw mjCError(this, "Invalid width or height of builtin texture");
// check width
if (width<1) {
throw mjCError(this, "Invalid width of builtin texture");
}

// adjust height of cube texture
if (type != mjTEXTURE_2D) {
height = 6*width;
} else {
if (height<1) {
throw mjCError(this, "Invalid height of builtin texture");
}
}

// allocate data
Expand Down
20 changes: 20 additions & 0 deletions test/user/user_objects_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,26 @@ TEST_F(MjCHFieldTest, PngMap) {
mj_deleteModel(model);
}

// ------------- test textures -------------------------------------------------

using MjCTextureTest = MujocoTest;

TEST_F(MjCTextureTest, TexturesLoad) {
static constexpr char xml[] = R"(
<mujoco>
<asset>
<texture name="body" type="cube" builtin="flat" mark="cross" width="8"
rgb1="0.8 0.6 0.4" rgb2="0.8 0.6 0.4" markrgb="1 1 1"/>
</asset>
</mujoco>
)";
std::array<char, 1024> error;
mjModel* m = LoadModelFromString(xml, error.data(), error.size());
ASSERT_THAT(m, NotNull()) << error.data();

mj_deleteModel(m);
}

// ------------- test quaternion normalization----------------------------------

using QuatNorm = MujocoTest;
Expand Down

0 comments on commit f2c3be4

Please sign in to comment.