Add texture attribute to lights.
PiperOrigin-RevId: 763739805 Change-Id: I333ed2ac68f30f79f688ca01d7b5fd6bf2d836c9
This commit is contained in:
committed by
Copybara-Service
parent
441ca838a1
commit
568620dd2f
@@ -2961,6 +2961,11 @@ Attributes may be applied or ignored depending on the lighting model being used.
|
||||
The color of the light. For the Phong (default) lighting model, this defines the diffuse color of
|
||||
the light.
|
||||
|
||||
.. _body-light-texture:
|
||||
|
||||
:at:`texture`: :at-val:`string, optional`
|
||||
The texture to use for image-based lighting. This is unused by the default Phong lighting model.
|
||||
|
||||
.. _body-light-intensity:
|
||||
|
||||
:at:`intensity`: :at-val:`real, "1000.0"`
|
||||
|
||||
+1
-1
@@ -321,7 +321,7 @@
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
| | | | :ref:`cutoff<body-light-cutoff>` | :ref:`exponent<body-light-exponent>` | :ref:`ambient<body-light-ambient>` | :ref:`diffuse<body-light-diffuse>` | |
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
| | | | :ref:`specular<body-light-specular>` | :ref:`mode<body-light-mode>` | :ref:`target<body-light-target>` | | |
|
||||
| | | | :ref:`specular<body-light-specular>` | :ref:`mode<body-light-mode>` | :ref:`target<body-light-target>` | :ref:`texture<body-light-texture>` | |
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| |_| body |br| |_| |L| | | .. table:: |
|
||||
|
||||
@@ -1186,6 +1186,7 @@ struct mjModel_ {
|
||||
int* light_bodyid; // id of light's body (nlight x 1)
|
||||
int* light_targetbodyid; // id of targeted body; -1: none (nlight x 1)
|
||||
int* light_type; // spot, directional, etc. (mjtLightType) (nlight x 1)
|
||||
int* light_texid; // texture id for image lights (nlight x 1)
|
||||
mjtByte* light_castshadow; // does light cast shadows (nlight x 1)
|
||||
float* light_bulbradius; // light radius for soft shadows (nlight x 1)
|
||||
float* light_intensity; // intensity, in candela (nlight x 1)
|
||||
@@ -2043,6 +2044,7 @@ typedef struct mjsLight_ { // light specification
|
||||
// intrinsics
|
||||
mjtByte active; // is light active
|
||||
mjtLightType type; // type of light
|
||||
mjString* texture; // texture name for image lights
|
||||
mjtByte castshadow; // does light cast shadows
|
||||
float bulbradius; // bulb radius, for soft shadows
|
||||
float intensity; // intensity, in candelas
|
||||
@@ -2847,6 +2849,7 @@ struct mjvLight_ { // OpenGL light
|
||||
float pos[3]; // position rel. to body frame
|
||||
float dir[3]; // direction rel. to body frame
|
||||
int type; // type (mjtLightType)
|
||||
int texid; // texture id for image lights
|
||||
float attenuation[3]; // OpenGL attenuation (quadratic model)
|
||||
float cutoff; // OpenGL cutoff
|
||||
float exponent; // OpenGL exponent
|
||||
|
||||
@@ -858,6 +858,7 @@ struct mjModel_ {
|
||||
int* light_bodyid; // id of light's body (nlight x 1)
|
||||
int* light_targetbodyid; // id of targeted body; -1: none (nlight x 1)
|
||||
int* light_type; // spot, directional, etc. (mjtLightType) (nlight x 1)
|
||||
int* light_texid; // texture id for image lights (nlight x 1)
|
||||
mjtByte* light_castshadow; // does light cast shadows (nlight x 1)
|
||||
float* light_bulbradius; // light radius for soft shadows (nlight x 1)
|
||||
float* light_intensity; // intensity, in candela (nlight x 1)
|
||||
|
||||
@@ -395,6 +395,7 @@ typedef struct mjsLight_ { // light specification
|
||||
// intrinsics
|
||||
mjtByte active; // is light active
|
||||
mjtLightType type; // type of light
|
||||
mjString* texture; // texture name for image lights
|
||||
mjtByte castshadow; // does light cast shadows
|
||||
float bulbradius; // bulb radius, for soft shadows
|
||||
float intensity; // intensity, in candelas
|
||||
|
||||
@@ -262,6 +262,7 @@ struct mjvLight_ { // OpenGL light
|
||||
float pos[3]; // position rel. to body frame
|
||||
float dir[3]; // direction rel. to body frame
|
||||
int type; // type (mjtLightType)
|
||||
int texid; // texture id for image lights
|
||||
float attenuation[3]; // OpenGL attenuation (quadratic model)
|
||||
float cutoff; // OpenGL cutoff
|
||||
float exponent; // OpenGL exponent
|
||||
|
||||
@@ -300,6 +300,7 @@
|
||||
X ( int, light_bodyid, nlight, 1 ) \
|
||||
X ( int, light_targetbodyid, nlight, 1 ) \
|
||||
X ( int, light_type, nlight, 1 ) \
|
||||
X ( int, light_texid, nlight, 1 ) \
|
||||
X ( mjtByte, light_castshadow, nlight, 1 ) \
|
||||
X ( float, light_bulbradius, nlight, 1 ) \
|
||||
X ( float, light_intensity, nlight, 1 ) \
|
||||
|
||||
@@ -2227,6 +2227,14 @@ STRUCTS: Mapping[str, StructDecl] = dict([
|
||||
doc='spot, directional, etc. (mjtLightType)',
|
||||
array_extent=('nlight',),
|
||||
),
|
||||
StructFieldDecl(
|
||||
name='light_texid',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='int'),
|
||||
),
|
||||
doc='texture id for image lights',
|
||||
array_extent=('nlight',),
|
||||
),
|
||||
StructFieldDecl(
|
||||
name='light_castshadow',
|
||||
type=PointerType(
|
||||
@@ -6702,6 +6710,11 @@ STRUCTS: Mapping[str, StructDecl] = dict([
|
||||
type=ValueType(name='int'),
|
||||
doc='type (mjtLightType)',
|
||||
),
|
||||
StructFieldDecl(
|
||||
name='texid',
|
||||
type=ValueType(name='int'),
|
||||
doc='texture id for image lights',
|
||||
),
|
||||
StructFieldDecl(
|
||||
name='attenuation',
|
||||
type=ArrayType(
|
||||
@@ -8996,6 +9009,13 @@ STRUCTS: Mapping[str, StructDecl] = dict([
|
||||
type=ValueType(name='mjtLightType'),
|
||||
doc='type of light',
|
||||
),
|
||||
StructFieldDecl(
|
||||
name='texture',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjString'),
|
||||
),
|
||||
doc='texture name for image lights',
|
||||
),
|
||||
StructFieldDecl(
|
||||
name='castshadow',
|
||||
type=ValueType(name='mjtByte'),
|
||||
|
||||
@@ -1074,6 +1074,7 @@ This is useful for example when the MJB is not available as a file on disk.)"));
|
||||
X(exponent);
|
||||
X(headlight);
|
||||
X(type);
|
||||
X(texid);
|
||||
X(castshadow);
|
||||
X(bulbradius);
|
||||
X(intensity);
|
||||
|
||||
@@ -2143,8 +2143,12 @@ void mjv_makeLights(const mjModel* m, const mjData* d, mjvScene* scn) {
|
||||
// set default properties
|
||||
memset(thislight, 0, sizeof(mjvLight));
|
||||
thislight->headlight = 1;
|
||||
thislight->texid = -1;
|
||||
thislight->type = mjLIGHT_DIRECTIONAL;
|
||||
thislight->castshadow = 0;
|
||||
thislight->bulbradius = 0.02;
|
||||
thislight->intensity = 1000;
|
||||
thislight->range = 10;
|
||||
|
||||
// compute head position and gaze direction in model space
|
||||
mjtNum hpos[3], hfwd[3];
|
||||
@@ -2170,6 +2174,7 @@ void mjv_makeLights(const mjModel* m, const mjData* d, mjvScene* scn) {
|
||||
// copy properties
|
||||
memset(thislight, 0, sizeof(mjvLight));
|
||||
thislight->type = m->light_type[i];
|
||||
thislight->texid = m->light_texid[i];
|
||||
thislight->castshadow = m->light_castshadow[i];
|
||||
thislight->bulbradius = m->light_bulbradius[i];
|
||||
thislight->intensity = m->light_intensity[i];
|
||||
|
||||
@@ -2670,6 +2670,7 @@ void mjCModel::CopyTree(mjModel* m) {
|
||||
m->light_mode[lid] = (int)pl->mode;
|
||||
m->light_targetbodyid[lid] = pl->targetbodyid;
|
||||
m->light_type[lid] = pl->type;
|
||||
m->light_texid[lid] = pl->texid;
|
||||
m->light_castshadow[lid] = (mjtByte)pl->castshadow;
|
||||
m->light_active[lid] = (mjtByte)pl->active;
|
||||
mjuu_copyvec(m->light_pos+3*lid, pl->pos, 3);
|
||||
|
||||
@@ -3553,7 +3553,10 @@ mjCLight::mjCLight(mjCModel* _model, mjCDef* _def) {
|
||||
// clear private variables
|
||||
body = 0;
|
||||
targetbodyid = -1;
|
||||
texid = -1;
|
||||
spec_targetbody_.clear();
|
||||
spec_texture_.clear();
|
||||
|
||||
|
||||
// reset to default if given
|
||||
if (_def) {
|
||||
@@ -3593,6 +3596,7 @@ void mjCLight::PointToLocal() {
|
||||
spec.element = static_cast<mjsElement*>(this);
|
||||
spec.name = &name;
|
||||
spec.targetbody = &spec_targetbody_;
|
||||
spec.texture = &spec_texture_;
|
||||
spec.info = &info;
|
||||
targetbody = nullptr;
|
||||
}
|
||||
@@ -3604,6 +3608,9 @@ void mjCLight::NameSpace(const mjCModel* m) {
|
||||
if (!spec_targetbody_.empty()) {
|
||||
spec_targetbody_ = m->prefix + spec_targetbody_ + m->suffix;
|
||||
}
|
||||
if (!spec_texture_.empty()) {
|
||||
spec_texture_ = m->prefix + spec_texture_ + m->suffix;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3611,6 +3618,7 @@ void mjCLight::NameSpace(const mjCModel* m) {
|
||||
void mjCLight::CopyFromSpec() {
|
||||
*static_cast<mjsLight*>(this) = spec;
|
||||
targetbody_ = spec_targetbody_;
|
||||
texture_ = spec_texture_;
|
||||
}
|
||||
|
||||
|
||||
@@ -3643,6 +3651,16 @@ void mjCLight::Compile(void) {
|
||||
throw mjCError(this, "unknown target body in light");
|
||||
}
|
||||
}
|
||||
|
||||
// get texture
|
||||
if (!texture_.empty()) {
|
||||
mjCTexture* tex = (mjCTexture*)model->FindObject(mjOBJ_TEXTURE, texture_);
|
||||
if (tex) {
|
||||
texid = tex->id;
|
||||
} else {
|
||||
throw mjCError(this, "unknown target body in light");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -793,6 +793,9 @@ class mjCLight_ : public mjCBase {
|
||||
protected:
|
||||
mjCBody* body; // light's body
|
||||
int targetbodyid; // id of target body; -1: none
|
||||
int texid; // id of texture; -1: none
|
||||
std::string texture_;
|
||||
std::string spec_texture_;
|
||||
std::string targetbody_;
|
||||
std::string spec_targetbody_;
|
||||
};
|
||||
@@ -814,6 +817,7 @@ class mjCLight : public mjCLight_, private mjsLight {
|
||||
|
||||
// used by mjXWriter and mjCModel
|
||||
const std::string& get_targetbody() const { return targetbody_; }
|
||||
const std::string& get_texture() const { return texture_; }
|
||||
|
||||
void SetParent(mjCBody* _body) { body = _body; }
|
||||
mjCBody* GetParent() const { return body; }
|
||||
|
||||
@@ -281,9 +281,9 @@ const char* MJCF[nMJCF][mjXATTRNUM] = {
|
||||
{"camera", "*", "20", "name", "class", "orthographic", "fovy", "ipd", "resolution", "pos",
|
||||
"quat", "axisangle", "xyaxes", "zaxis", "euler", "mode", "target",
|
||||
"focal", "focalpixel", "principal", "principalpixel", "sensorsize", "user"},
|
||||
{"light", "*", "19", "name", "class", "directional", "type", "castshadow", "active",
|
||||
{"light", "*", "20", "name", "class", "directional", "type", "castshadow", "active",
|
||||
"pos", "dir", "bulbradius", "intensity", "range", "attenuation", "cutoff",
|
||||
"exponent", "ambient", "diffuse", "specular", "mode", "target"},
|
||||
"exponent", "ambient", "diffuse", "specular", "mode", "target", "texture"},
|
||||
{"plugin", "*", "2", "plugin", "instance"},
|
||||
{"<"},
|
||||
{"config", "*", "2", "key", "value"},
|
||||
@@ -1864,12 +1864,15 @@ void mjXReader::OneCamera(XMLElement* elem, mjsCamera* camera) {
|
||||
void mjXReader::OneLight(XMLElement* elem, mjsLight* light) {
|
||||
int n;
|
||||
bool has_directional = false;
|
||||
string text, name, targetbody;
|
||||
string text, name, texture, targetbody;
|
||||
|
||||
// read attributes
|
||||
if (ReadAttrTxt(elem, "name", name)) {
|
||||
mjs_setString(light->name, name.c_str());
|
||||
}
|
||||
if (ReadAttrTxt(elem, "texture", texture)) {
|
||||
mjs_setString(light->texture, texture.c_str());
|
||||
}
|
||||
if (ReadAttrTxt(elem, "target", targetbody)) {
|
||||
mjs_setString(light->targetbody, targetbody.c_str());
|
||||
}
|
||||
|
||||
@@ -608,6 +608,7 @@ void mjXWriter::OneLight(XMLElement* elem, const mjCLight* light, mjCDef* def,
|
||||
WriteAttr(elem, "intensity", 1, &light->intensity, &def->Light().intensity);
|
||||
WriteAttr(elem, "range", 1, &light->range, &def->Light().range);
|
||||
WriteAttrKey(elem, "type", lighttype_map, lighttype_sz, light->type, def->Light().type);
|
||||
WriteAttrTxt(elem, "texture", light->get_texture());
|
||||
WriteAttrKey(elem, "castshadow", bool_map, 2, light->castshadow, def->Light().castshadow);
|
||||
WriteAttrKey(elem, "active", bool_map, 2, light->active, def->Light().active);
|
||||
WriteAttr(elem, "attenuation", 3, light->attenuation, def->Light().attenuation);
|
||||
|
||||
@@ -2294,6 +2294,29 @@ TEST_F(UserObjectsTest, FrameTransformsLight) {
|
||||
mj_deleteModel(m);
|
||||
}
|
||||
|
||||
TEST_F(ContentTypeTest, ImageLightsReferenceTexture) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<asset>
|
||||
<texture name="texture" 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>
|
||||
|
||||
<worldbody>
|
||||
<light type="image" texture="texture"/>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
)";
|
||||
|
||||
std::array<char, 1024> error;
|
||||
mjModel* m = LoadModelFromString(xml, error.data(), error.size());
|
||||
EXPECT_THAT(m, NotNull());
|
||||
EXPECT_EQ(m->ntex, 1);
|
||||
EXPECT_EQ(m->nlight, 1);
|
||||
EXPECT_THAT(m->light_texid[0], 0);
|
||||
mj_deleteModel(m);
|
||||
}
|
||||
|
||||
|
||||
// ------------- test bvh ------------------------------------------------------
|
||||
TEST_F(UserObjectsTest, RobustBVH) {
|
||||
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
<mujoco>
|
||||
<asset>
|
||||
<texture name="texture1" type="2d" file="hfield.png"/>
|
||||
</asset>
|
||||
<worldbody>
|
||||
<light name="light1" type="spot" pos="1 2 3" dir="0 0 1" diffuse="0.1 0.2 0.3" ambient="0.4 0.5 0.6" specular="0.7 0.8 0.95"/>
|
||||
<light name="light2" type="spot" attenuation="0.1 0.2 0.3" cutoff="0.4" exponent="0.5"/>
|
||||
<light name="light3" type="point" range="2" intensity="300" bulbradius="0.5"/>
|
||||
<light name="light4" type="directional" dir="1 0 0" active="false" castshadow="false"/>
|
||||
<light name="light5" type="image" texture="texture1"/>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
@@ -5441,6 +5441,7 @@ public unsafe struct mjModel_ {
|
||||
public int* light_bodyid;
|
||||
public int* light_targetbodyid;
|
||||
public int* light_type;
|
||||
public int* light_texid;
|
||||
public byte* light_castshadow;
|
||||
public float* light_bulbradius;
|
||||
public float* light_intensity;
|
||||
@@ -6082,6 +6083,7 @@ public unsafe struct mjvLight_ {
|
||||
public fixed float pos[3];
|
||||
public fixed float dir[3];
|
||||
public int type;
|
||||
public int texid;
|
||||
public fixed float attenuation[3];
|
||||
public float cutoff;
|
||||
public float exponent;
|
||||
|
||||
Reference in New Issue
Block a user