|
28 | 28 |
|
29 | 29 | namespace mujoco { |
30 | 30 |
|
31 | | -// Returns the tile size for infinite plane texture alignment. |
32 | | -// This is duplicated from engine_vis_visualize.c (re-center infinite plane) |
33 | | -// to ensure UV scaling matches the re-centering increments. |
34 | | -static float GetPlaneTileSize(const mjModel* model, int matid, |
35 | | - float texrepeat) { |
36 | | - if (matid >= 0 && texrepeat > 0) { |
37 | | - return 2.0f / texrepeat; |
38 | | - } else { |
39 | | - const float zfar = model->vis.map.zfar * model->stat.extent; |
40 | | - return 2.1f * zfar / (mjMAXPLANEGRID - 2); |
41 | | - } |
42 | | -} |
43 | | - |
44 | 31 | static void PrepareGeomMeshes(mjrfRenderable* renderable, const mjvGeom& geom, |
45 | 32 | ModelObjects* model_objs, |
46 | 33 | SceneObjects* scene_objs) { |
@@ -230,37 +217,31 @@ static void UpdateGeomMaterial(mjrfRenderable* renderable, const mjvGeom& geom, |
230 | 217 | } |
231 | 218 | } |
232 | 219 |
|
233 | | - if (tex_uniform) { |
234 | | - if (geom.size[0] > 0) { |
235 | | - material.uv_scale[0] *= geom.size[0]; |
236 | | - } |
237 | | - if (geom.size[1] > 0) { |
238 | | - material.uv_scale[1] *= geom.size[1]; |
239 | | - } |
240 | | - } |
241 | 220 | const bool is_infinite_plane = |
242 | 221 | geom.type == mjGEOM_PLANE && (geom.size[0] <= 0 || geom.size[1] <= 0); |
243 | 222 | if (is_infinite_plane) { |
244 | | - // Infinite planes are scaled to match the tile size used by |
245 | | - // re-centering in engine_vis_visualize.c. |
246 | 223 | const float plane_scale = static_cast<float>(mjMAXPLANEGRID) / 2.0f; |
247 | | - const float tile_size_x = |
248 | | - GetPlaneTileSize(model, geom.matid, tex_repeat[0]); |
249 | | - const float tile_size_y = |
250 | | - GetPlaneTileSize(model, geom.matid, tex_repeat[1]); |
251 | | - material.uv_scale[0] = 2.0f * plane_scale / tile_size_x; |
252 | | - material.uv_scale[1] = 2.0f * plane_scale / tile_size_y; |
253 | | - } |
254 | 224 |
|
255 | | - // We want to do the equivalent of: |
256 | | - // mjr_setf4(splane, 0.5 * scl.x, 0, 0, -0.5); |
257 | | - // mjr_setf4(tplane, 0, -0.5 * scl.y, 0, -0.5); |
258 | | - // glTexGenfv(GL_S, GL_OBJECT_PLANE, splane); |
259 | | - // glTexGenfv(GL_T, GL_OBJECT_PLANE, tplane); |
260 | | - material.uv_scale[0] = 0.5f * material.uv_scale[0]; |
261 | | - material.uv_scale[1] = -0.5f * material.uv_scale[1]; |
262 | | - material.uv_offset[0] = -0.5f; |
263 | | - material.uv_offset[1] = -0.5f; |
| 225 | + const float dot_pos_axis_x = geom.pos[0] * geom.mat[0] + |
| 226 | + geom.pos[1] * geom.mat[3] + |
| 227 | + geom.pos[2] * geom.mat[6]; |
| 228 | + const float dot_pos_axis_y = geom.pos[0] * geom.mat[1] + |
| 229 | + geom.pos[1] * geom.mat[4] + |
| 230 | + geom.pos[2] * geom.mat[7]; |
| 231 | + |
| 232 | + material.uv_scale[0] *= plane_scale; |
| 233 | + material.uv_scale[1] *= plane_scale; |
| 234 | + // The vertex UVs in PlaneBuilder are u0 = 0.5*x + 0.5, v0 = -0.5*y + 0.5. |
| 235 | + // To keep the world-space texture coordinate u = 0.5*worldX*texrepeat - 0.5 |
| 236 | + // independent of the snapped geomPos, uv_offset must compensate by 0.5*dot_pos. |
| 237 | + material.uv_offset[0] = |
| 238 | + (0.5f * dot_pos_axis_x - 0.5f * plane_scale) * tex_repeat[0] - 0.5f; |
| 239 | + material.uv_offset[1] = |
| 240 | + (-0.5f * dot_pos_axis_y - 0.5f * plane_scale) * tex_repeat[1] - 0.5f; |
| 241 | + } else if (tex_uniform) { |
| 242 | + material.uv_scale[0] *= (geom.size[0] ? geom.size[0] : 1.0f); |
| 243 | + material.uv_scale[1] *= (geom.size[1] ? geom.size[1] : 1.0f); |
| 244 | + } |
264 | 245 | } else { |
265 | 246 | // For cube maps, if `tex_uniform` is true, then scale the texture so that |
266 | 247 | // it covers a 1x1 area of world space rather than the area of the object. |
|
0 commit comments