From cc7fb98cf45ed697589c06e7e1d12b338ca53e98 Mon Sep 17 00:00:00 2001 From: Sam Haves Date: Fri, 14 Aug 2026 14:10:32 -0700 Subject: [PATCH] Add texture coordinates to primitive shape types. PiperOrigin-RevId: 964882123 Change-Id: I17723d21f29b3fe28e171de5c3d2bea1f55a94c2 --- doc/changelog.rst | 15 + doc/images/changelog/plane_uv_tiling.png | Bin 0 -> 167042 bytes .../filament/compat/scene_geom_util.cc | 59 ++-- src/render/classic/render_context.c | 301 +++++++++++------- src/render/classic/render_gl3.c | 46 ++- src/render/filament/assets/pbr.mat | 6 +- src/render/filament/assets/pbr_packed.mat | 6 +- src/render/filament/assets/phong_2d.mat | 6 +- src/render/filament/assets/phong_2d_fade.mat | 6 +- .../filament/assets/phong_2d_reflect.mat | 6 +- src/render/filament/assets/phong_2d_uv.mat | 6 +- .../filament/assets/phong_2d_uv_fade.mat | 6 +- .../filament/assets/phong_2d_uv_reflect.mat | 6 +- src/render/filament/core/builtins.cc | 260 +++++++++------ src/render/filament/core/builtins.h | 6 +- src/render/filament/core/renderable.cc | 46 +-- src/render/filament/support/model_objects.cc | 60 +++- .../filament/support/model_renderables.cc | 79 ++--- 18 files changed, 552 insertions(+), 368 deletions(-) create mode 100644 doc/images/changelog/plane_uv_tiling.png diff --git a/doc/changelog.rst b/doc/changelog.rst index 94e6e7f6..f41df670 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -85,6 +85,21 @@ Rendering .. admonition:: Breaking API changes :class: attention + .. image:: https://www.gstatic.com/mujoco/doc/images/changelog/primitives_textured.gif + :align: right + :width: 40% + + - Added explicit texture coordinates to built-in geometries (Plane, Box, Sphere, Ellipsoid, Capsule, + Cylinder) in both the Classic renderer and Filament. 2D textures applied to primitive shapes will look different + as textures are mapped using canonical UV parameterizations rather than projecting onto the :math:`x,y` plane. + + For finite planes, textures are now anchored to the bottom-left corner instead of the center. This will cause the + most common visual breakage, as common procedural checker textures will be phase shifted. Infinite planes continue + to be anchored at the origin with no visual changes. + + .. image:: images/changelog/plane_uv_tiling.png + :align: center + :width: 70% - Added :ref:`light/softness`: edge softness for spotlights under physically-based lighting models, given as the fraction of the cone over which intensity falls to zero. The default of 0.2 is a semi-soft cone which delivers the full :ref:`intensity` everywhere inside it, so that illuminance diff --git a/doc/images/changelog/plane_uv_tiling.png b/doc/images/changelog/plane_uv_tiling.png new file mode 100644 index 0000000000000000000000000000000000000000..0e0cc6e21e55783a512d6b6acea358deacc4b760 GIT binary patch literal 167042 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

LST7_U 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 z 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 yo*$0aFdE>-Tk}5!i^K7>-~YeR|NRx3JAjSO= 0 && texrepeat > 0) { - return 2.0f / texrepeat; - } else { - const float zfar = model->vis.map.zfar * model->stat.extent; - return 2.1f * zfar / (mjMAXPLANEGRID - 2); - } -} - static void PrepareGeomMeshes(mjrfRenderable* renderable, const mjvGeom& geom, ModelObjects* model_objs, SceneObjects* scene_objs) { @@ -230,37 +217,31 @@ static void UpdateGeomMaterial(mjrfRenderable* renderable, const mjvGeom& geom, } } - if (tex_uniform) { - if (geom.size[0] > 0) { - material.uv_scale[0] *= geom.size[0]; - } - if (geom.size[1] > 0) { - material.uv_scale[1] *= geom.size[1]; - } - } const bool is_infinite_plane = geom.type == mjGEOM_PLANE && (geom.size[0] <= 0 || geom.size[1] <= 0); if (is_infinite_plane) { - // Infinite planes are scaled to match the tile size used by - // re-centering in engine_vis_visualize.c. const float plane_scale = static_cast(mjMAXPLANEGRID) / 2.0f; - const float tile_size_x = - GetPlaneTileSize(model, geom.matid, tex_repeat[0]); - const float tile_size_y = - GetPlaneTileSize(model, geom.matid, tex_repeat[1]); - material.uv_scale[0] = 2.0f * plane_scale / tile_size_x; - material.uv_scale[1] = 2.0f * plane_scale / tile_size_y; - } - // We want to do the equivalent of: - // mjr_setf4(splane, 0.5 * scl.x, 0, 0, -0.5); - // mjr_setf4(tplane, 0, -0.5 * scl.y, 0, -0.5); - // glTexGenfv(GL_S, GL_OBJECT_PLANE, splane); - // glTexGenfv(GL_T, GL_OBJECT_PLANE, tplane); - material.uv_scale[0] = 0.5f * material.uv_scale[0]; - material.uv_scale[1] = -0.5f * material.uv_scale[1]; - material.uv_offset[0] = -0.5f; - material.uv_offset[1] = -0.5f; + const float dot_pos_axis_x = geom.pos[0] * geom.mat[0] + + geom.pos[1] * geom.mat[3] + + geom.pos[2] * geom.mat[6]; + const float dot_pos_axis_y = geom.pos[0] * geom.mat[1] + + geom.pos[1] * geom.mat[4] + + geom.pos[2] * geom.mat[7]; + + material.uv_scale[0] *= plane_scale; + material.uv_scale[1] *= plane_scale; + // The vertex UVs in PlaneBuilder are u0 = 0.5*x + 0.5, v0 = -0.5*y + 0.5. + // To keep the world-space texture coordinate u = 0.5*worldX*texrepeat - 0.5 + // independent of the snapped geomPos, uv_offset must compensate by 0.5*dot_pos. + material.uv_offset[0] = + (0.5f * dot_pos_axis_x - 0.5f * plane_scale) * tex_repeat[0] - 0.5f; + material.uv_offset[1] = + (-0.5f * dot_pos_axis_y - 0.5f * plane_scale) * tex_repeat[1] - 0.5f; + } else if (tex_uniform) { + material.uv_scale[0] *= (geom.size[0] ? geom.size[0] : 1.0f); + material.uv_scale[1] *= (geom.size[1] ? geom.size[1] : 1.0f); + } } else { // For cube maps, if `tex_uniform` is true, then scale the texture so that // it covers a 1x1 area of world space rather than the area of the object. diff --git a/src/render/classic/render_context.c b/src/render/classic/render_context.c index ec21204d..985d31d8 100644 --- a/src/render/classic/render_context.c +++ b/src/render/classic/render_context.c @@ -117,11 +117,19 @@ static void makePlane(const mjModel* m, mjrContext* con) { glBegin(GL_QUADS); glNormal3d(0, 0, 1); double d = 2.0/m->vis.quality.numquads; + double nq = (double)m->vis.quality.numquads; for (int x=0; x < m->vis.quality.numquads; x++) { for (int y=0; y < m->vis.quality.numquads; y++) { + glTexCoord2d((double)x/nq, 1.0 - (double)y/nq); glVertex3d(d*(x+0)-1, d*(y+0)-1, 0); + + glTexCoord2d((double)(x+1)/nq, 1.0 - (double)y/nq); glVertex3d(d*(x+1)-1, d*(y+0)-1, 0); + + glTexCoord2d((double)(x+1)/nq, 1.0 - (double)(y+1)/nq); glVertex3d(d*(x+1)-1, d*(y+1)-1, 0); + + glTexCoord2d((double)x/nq, 1.0 - (double)(y+1)/nq); glVertex3d(d*(x+0)-1, d*(y+1)-1, 0); } } @@ -198,10 +206,27 @@ static void makePlane(const mjModel* m, mjrContext* con) { // make grid for (int x=0; x < nn[0]; x++) { for (int y=0; y < nn[1]; y++) { - glVertex3d(grid[0][x+0], grid[1][y+0], 0); - glVertex3d(grid[0][x+1], grid[1][y+0], 0); - glVertex3d(grid[0][x+1], grid[1][y+1], 0); - glVertex3d(grid[0][x+0], grid[1][y+1], 0); + double u0, u1, v0, v1; + if (sz[0] > 0) { + u0 = (grid[0][x+0] + sz[0]) / (2.0 * sz[0]); + u1 = (grid[0][x+1] + sz[0]) / (2.0 * sz[0]); + } else { + u0 = 0.5 * grid[0][x+0]; + u1 = 0.5 * grid[0][x+1]; + } + + if (sz[1] > 0) { + v0 = 1.0 - (grid[1][y+0] + sz[1]) / (2.0 * sz[1]); + v1 = 1.0 - (grid[1][y+1] + sz[1]) / (2.0 * sz[1]); + } else { + v0 = -0.5 * grid[1][y+0]; + v1 = -0.5 * grid[1][y+1]; + } + + glTexCoord2d(u0, v0); glVertex3d(grid[0][x+0], grid[1][y+0], 0); + glTexCoord2d(u1, v0); glVertex3d(grid[0][x+1], grid[1][y+0], 0); + glTexCoord2d(u1, v1); glVertex3d(grid[0][x+1], grid[1][y+1], 0); + glTexCoord2d(u0, v1); glVertex3d(grid[0][x+0], grid[1][y+1], 0); } } @@ -552,21 +577,26 @@ static void halfSphere(int sign, int nSlice, int nStack) { n3[0] = n3[1] = 0; n3[2] = sign; + float u1 = az1 / (2.0f*mjPI); + float v_el1 = (float)(nStack-1) / (float)nStack; + float u2 = az2 / (2.0f*mjPI); + float u3 = (az1 + az2) / 2.0f / (2.0f*mjPI); + float v3_uv = 1.0f; + + if (sign > 0) { + v_el1 = 1.0f - v_el1; + v3_uv = 1.0f - v3_uv; + } + // make triangle if (sign > 0) { - glNormal3fv(n1); - glVertex3fv(v1); - glNormal3fv(n2); - glVertex3fv(v2); - glNormal3fv(n3); - glVertex3fv(v3); + glTexCoord2f(u1, v_el1); glNormal3fv(n1); glVertex3fv(v1); + glTexCoord2f(u2, v_el1); glNormal3fv(n2); glVertex3fv(v2); + glTexCoord2f(u3, v3_uv); glNormal3fv(n3); glVertex3fv(v3); } else { - glNormal3fv(n3); - glVertex3fv(v3); - glNormal3fv(n2); - glVertex3fv(v2); - glNormal3fv(n1); - glVertex3fv(v1); + glTexCoord2f(u3, v3_uv); glNormal3fv(n3); glVertex3fv(v3); + glTexCoord2f(u2, v_el1); glNormal3fv(n2); glVertex3fv(v2); + glTexCoord2f(u1, v_el1); glNormal3fv(n1); glVertex3fv(v1); } } glEnd(); @@ -577,6 +607,14 @@ static void halfSphere(int sign, int nSlice, int nStack) { el1 = (mjPI/2.0f * sign * (i+0)) / (float)nStack; el2 = (mjPI/2.0f * sign * (i+1)) / (float)nStack; + float v_el1 = (float)(i+0) / (float)nStack; + float v_el2 = (float)(i+1) / (float)nStack; + + if (sign > 0) { + v_el1 = 1.0f - v_el1; + v_el2 = 1.0f - v_el2; + } + for (int j=0; j < nSlice; j++) { az1 = (2.0f*mjPI * (j+0)) / (float)nSlice; az2 = (2.0f*mjPI * (j+1)) / (float)nSlice; @@ -587,25 +625,20 @@ static void halfSphere(int sign, int nSlice, int nStack) { setVertexSphere(v3, n3, az2, el2, sign); setVertexSphere(v4, n4, az1, el2, sign); + float u1 = az1 / (2.0f*mjPI); + float u2 = az2 / (2.0f*mjPI); + // make quad if (sign > 0) { - glNormal3fv(n1); - glVertex3fv(v1); - glNormal3fv(n2); - glVertex3fv(v2); - glNormal3fv(n3); - glVertex3fv(v3); - glNormal3fv(n4); - glVertex3fv(v4); + glTexCoord2f(u1, v_el1); glNormal3fv(n1); glVertex3fv(v1); + glTexCoord2f(u2, v_el1); glNormal3fv(n2); glVertex3fv(v2); + glTexCoord2f(u2, v_el2); glNormal3fv(n3); glVertex3fv(v3); + glTexCoord2f(u1, v_el2); glNormal3fv(n4); glVertex3fv(v4); } else { - glNormal3fv(n4); - glVertex3fv(v4); - glNormal3fv(n3); - glVertex3fv(v3); - glNormal3fv(n2); - glVertex3fv(v2); - glNormal3fv(n1); - glVertex3fv(v1); + glTexCoord2f(u1, v_el2); glNormal3fv(n4); glVertex3fv(v4); + glTexCoord2f(u2, v_el2); glNormal3fv(n3); glVertex3fv(v3); + glTexCoord2f(u2, v_el1); glNormal3fv(n2); glVertex3fv(v2); + glTexCoord2f(u1, v_el1); glNormal3fv(n1); glVertex3fv(v1); } } } @@ -624,6 +657,9 @@ static void sphere(int nSlice, int nStack) { glBegin(GL_TRIANGLES); for (int sign=-1; sign <= 1; sign+=2) { el1 = (0.5*mjPI * sign * (nStack/2-1)) / (float)(nStack/2); + float v_el1 = 0.5f - sign * (float)(nStack/2-1) / (float)nStack; + float v3_uv = sign > 0 ? 0.0f : 1.0f; + for (int j=0; j < nSlice; j++) { az1 = (2.0f*mjPI * (j+0.0f)) / (float)nSlice; az2 = (2.0f*mjPI * (j+1.0f)) / (float)nSlice; @@ -636,21 +672,19 @@ static void sphere(int nSlice, int nStack) { n3[0] = n3[1] = 0; n3[2] = sign; + float u1 = az1 / (2.0f*mjPI); + float u2 = az2 / (2.0f*mjPI); + float u3 = (az1 + az2) / 2.0f / (2.0f*mjPI); + // make triangle if (sign > 0) { - glNormal3fv(n1); - glVertex3fv(v1); - glNormal3fv(n2); - glVertex3fv(v2); - glNormal3fv(n3); - glVertex3fv(v3); + glTexCoord2f(u1, v_el1); glNormal3fv(n1); glVertex3fv(v1); + glTexCoord2f(u2, v_el1); glNormal3fv(n2); glVertex3fv(v2); + glTexCoord2f(u3, v3_uv); glNormal3fv(n3); glVertex3fv(v3); } else { - glNormal3fv(n3); - glVertex3fv(v3); - glNormal3fv(n2); - glVertex3fv(v2); - glNormal3fv(n1); - glVertex3fv(v1); + glTexCoord2f(u3, v3_uv); glNormal3fv(n3); glVertex3fv(v3); + glTexCoord2f(u2, v_el1); glNormal3fv(n2); glVertex3fv(v2); + glTexCoord2f(u1, v_el1); glNormal3fv(n1); glVertex3fv(v1); } } } @@ -663,6 +697,9 @@ static void sphere(int nSlice, int nStack) { el1 = (0.5*mjPI * sign * (i+0)) / (float)(nStack/2); el2 = (0.5*mjPI * sign * (i+1)) / (float)(nStack/2); + float v_el1 = 0.5f - sign * (float)(i+0) / (float)nStack; + float v_el2 = 0.5f - sign * (float)(i+1) / (float)nStack; + for (int j=0; j < nSlice; j++) { az1 = (2.0f*mjPI * (j+0)) / (float)nSlice; az2 = (2.0f*mjPI * (j+1)) / (float)nSlice; @@ -673,25 +710,20 @@ static void sphere(int nSlice, int nStack) { setVertexSphere(v3, n3, az2, el2, 0); setVertexSphere(v4, n4, az1, el2, 0); + float u1 = az1 / (2.0f*mjPI); + float u2 = az2 / (2.0f*mjPI); + // make quad if (sign > 0) { - glNormal3fv(n1); - glVertex3fv(v1); - glNormal3fv(n2); - glVertex3fv(v2); - glNormal3fv(n3); - glVertex3fv(v3); - glNormal3fv(n4); - glVertex3fv(v4); + glTexCoord2f(u1, v_el1); glNormal3fv(n1); glVertex3fv(v1); + glTexCoord2f(u2, v_el1); glNormal3fv(n2); glVertex3fv(v2); + glTexCoord2f(u2, v_el2); glNormal3fv(n3); glVertex3fv(v3); + glTexCoord2f(u1, v_el2); glNormal3fv(n4); glVertex3fv(v4); } else { - glNormal3fv(n4); - glVertex3fv(v4); - glNormal3fv(n3); - glVertex3fv(v3); - glNormal3fv(n2); - glVertex3fv(v2); - glNormal3fv(n1); - glVertex3fv(v1); + glTexCoord2f(u1, v_el2); glNormal3fv(n4); glVertex3fv(v4); + glTexCoord2f(u2, v_el2); glNormal3fv(n3); glVertex3fv(v3); + glTexCoord2f(u2, v_el1); glNormal3fv(n2); glVertex3fv(v2); + glTexCoord2f(u1, v_el1); glNormal3fv(n1); glVertex3fv(v1); } } } @@ -729,15 +761,22 @@ static void disk(int sign, int nSlice, int nStack) { v3[0] = v3[1] = 0; v3[2] = sign; + float u1 = 0.5f + 0.5f * v1[0]; + float v1_uv = 0.5f + 0.5f * v1[1]; + float u2 = 0.5f + 0.5f * v2[0]; + float v2_uv = 0.5f + 0.5f * v2[1]; + float u3 = 0.5f; + float v3_uv = 0.5f; + // make triangle if (sign > 0) { - glVertex3fv(v1); - glVertex3fv(v2); - glVertex3fv(v3); + glTexCoord2f(u1, v1_uv); glVertex3fv(v1); + glTexCoord2f(u2, v2_uv); glVertex3fv(v2); + glTexCoord2f(u3, v3_uv); glVertex3fv(v3); } else { - glVertex3fv(v3); - glVertex3fv(v2); - glVertex3fv(v1); + glTexCoord2f(u3, v3_uv); glVertex3fv(v3); + glTexCoord2f(u2, v2_uv); glVertex3fv(v2); + glTexCoord2f(u1, v1_uv); glVertex3fv(v1); } } glEnd(); @@ -759,17 +798,26 @@ static void disk(int sign, int nSlice, int nStack) { setVertexDisk(v3, az2, r1, sign); setVertexDisk(v4, az1, r1, sign); + float u1 = 0.5f + 0.5f * v1[0]; + float v1_uv = 0.5f + 0.5f * v1[1]; + float u2 = 0.5f + 0.5f * v2[0]; + float v2_uv = 0.5f + 0.5f * v2[1]; + float u3 = 0.5f + 0.5f * v3[0]; + float v3_uv = 0.5f + 0.5f * v3[1]; + float u4 = 0.5f + 0.5f * v4[0]; + float v4_uv = 0.5f + 0.5f * v4[1]; + // make quad if (sign > 0) { - glVertex3fv(v1); - glVertex3fv(v2); - glVertex3fv(v3); - glVertex3fv(v4); + glTexCoord2f(u1, v1_uv); glVertex3fv(v1); + glTexCoord2f(u2, v2_uv); glVertex3fv(v2); + glTexCoord2f(u3, v3_uv); glVertex3fv(v3); + glTexCoord2f(u4, v4_uv); glVertex3fv(v4); } else { - glVertex3fv(v4); - glVertex3fv(v3); - glVertex3fv(v2); - glVertex3fv(v1); + glTexCoord2f(u4, v4_uv); glVertex3fv(v4); + glTexCoord2f(u3, v3_uv); glVertex3fv(v3); + glTexCoord2f(u2, v2_uv); glVertex3fv(v2); + glTexCoord2f(u1, v1_uv); glVertex3fv(v1); } } } @@ -817,13 +865,14 @@ static void cone(int nSlice, int nStack) { n3[2] = n1[2]+n2[2]; mjr_normalizeVec(n3); + float u1 = (float)j / (float)nSlice; + float u2 = (float)(j+1) / (float)nSlice; + float u3 = (u1 + u2) / 2.0f; + // make triangle - glNormal3fv(n1); - glVertex3fv(v1); - glNormal3fv(n2); - glVertex3fv(v2); - glNormal3fv(n3); - glVertex3fv(v3); + glTexCoord2f(u1, r1); glNormal3fv(n1); glVertex3fv(v1); + glTexCoord2f(u2, r1); glNormal3fv(n2); glVertex3fv(v2); + glTexCoord2f(u3, 0.0f); glNormal3fv(n3); glVertex3fv(v3); } glEnd(); @@ -843,15 +892,14 @@ static void cone(int nSlice, int nStack) { setVertexCone(v3, n3, az2, r1); setVertexCone(v4, n4, az1, r1); + float u1 = (float)j / (float)nSlice; + float u2 = (float)(j+1) / (float)nSlice; + // make quad - glNormal3fv(n1); - glVertex3fv(v1); - glNormal3fv(n2); - glVertex3fv(v2); - glNormal3fv(n3); - glVertex3fv(v3); - glNormal3fv(n4); - glVertex3fv(v4); + glTexCoord2f(u1, r2); glNormal3fv(n1); glVertex3fv(v1); + glTexCoord2f(u2, r2); glNormal3fv(n2); glVertex3fv(v2); + glTexCoord2f(u2, r1); glNormal3fv(n3); glVertex3fv(v3); + glTexCoord2f(u1, r1); glNormal3fv(n4); glVertex3fv(v4); } } glEnd(); @@ -883,6 +931,9 @@ static void cylinder(int nSlice, int nStack) { h1 = 2*(i+0)/(float)nStack - 1; h2 = 2*(i+1)/(float)nStack - 1; + float v_el1 = (1.0f - h1) / 2.0f; + float v_el2 = (1.0f - h2) / 2.0f; + for (int j=0; j < nSlice; j++) { az1 = (2.0f*mjPI * (j+0)) / (float)nSlice; az2 = (2.0f*mjPI * (j+1)) / (float)nSlice; @@ -893,15 +944,14 @@ static void cylinder(int nSlice, int nStack) { setVertexCylinder(v3, n3, az2, h2); setVertexCylinder(v4, n4, az1, h2); + float u1 = (float)j / (float)nSlice; + float u2 = (float)(j+1) / (float)nSlice; + // make quad - glNormal3fv(n1); - glVertex3fv(v1); - glNormal3fv(n2); - glVertex3fv(v2); - glNormal3fv(n3); - glVertex3fv(v3); - glNormal3fv(n4); - glVertex3fv(v4); + glTexCoord2f(u1, v_el1); glNormal3fv(n1); glVertex3fv(v1); + glTexCoord2f(u2, v_el1); glNormal3fv(n2); glVertex3fv(v2); + glTexCoord2f(u2, v_el2); glNormal3fv(n3); glVertex3fv(v3); + glTexCoord2f(u1, v_el2); glNormal3fv(n4); glVertex3fv(v4); } } glEnd(); @@ -1009,43 +1059,54 @@ static void makeBuiltin(const mjModel* m, mjrContext* con) { // box glNewList(con->baseBuiltin + mjrBOX, GL_COMPILE); glBegin(GL_QUADS); + double nq = (double)numquads; for (int x=0; x < numquads; x++) { for (int y=0; y < numquads; y++) { + double u0_t = (double)x / nq; + double u1_t = (double)(x+1) / nq; + double v0_t = 1.0 - (double)y / nq; + double v1_t = 1.0 - (double)(y+1) / nq; + + double u0_b = (double)x / nq; + double u1_b = (double)(x+1) / nq; + double v0_b = 1.0 - (double)(y+1) / nq; + double v1_b = 1.0 - (double)y / nq; + glNormal3f(0, 0, 1); // top - glVertex3f(d*(x+0)-1, d*(y+0)-1, 1); - glVertex3f(d*(x+1)-1, d*(y+0)-1, 1); - glVertex3f(d*(x+1)-1, d*(y+1)-1, 1); - glVertex3f(d*(x+0)-1, d*(y+1)-1, 1); + glTexCoord2d(u0_t, v0_t); glVertex3f(d*(x+0)-1, d*(y+0)-1, 1); + glTexCoord2d(u1_t, v0_t); glVertex3f(d*(x+1)-1, d*(y+0)-1, 1); + glTexCoord2d(u1_t, v1_t); glVertex3f(d*(x+1)-1, d*(y+1)-1, 1); + glTexCoord2d(u0_t, v1_t); glVertex3f(d*(x+0)-1, d*(y+1)-1, 1); glNormal3f(0, 0, -1); // bottom - glVertex3f(d*(x+0)-1, d*(y+1)-1, -1); - glVertex3f(d*(x+1)-1, d*(y+1)-1, -1); - glVertex3f(d*(x+1)-1, d*(y+0)-1, -1); - glVertex3f(d*(x+0)-1, d*(y+0)-1, -1); + glTexCoord2d(u0_b, v0_b); glVertex3f(d*(x+0)-1, d*(y+1)-1, -1); + glTexCoord2d(u1_b, v0_b); glVertex3f(d*(x+1)-1, d*(y+1)-1, -1); + glTexCoord2d(u1_b, v1_b); glVertex3f(d*(x+1)-1, d*(y+0)-1, -1); + glTexCoord2d(u0_b, v1_b); glVertex3f(d*(x+0)-1, d*(y+0)-1, -1); glNormal3f(1, 0, 0); // right - glVertex3f(1, d*(x+0)-1, d*(y+0)-1); - glVertex3f(1, d*(x+1)-1, d*(y+0)-1); - glVertex3f(1, d*(x+1)-1, d*(y+1)-1); - glVertex3f(1, d*(x+0)-1, d*(y+1)-1); + glTexCoord2d(u0_t, v0_t); glVertex3f(1, d*(x+0)-1, d*(y+0)-1); + glTexCoord2d(u1_t, v0_t); glVertex3f(1, d*(x+1)-1, d*(y+0)-1); + glTexCoord2d(u1_t, v1_t); glVertex3f(1, d*(x+1)-1, d*(y+1)-1); + glTexCoord2d(u0_t, v1_t); glVertex3f(1, d*(x+0)-1, d*(y+1)-1); glNormal3f(-1, 0, 0); // left - glVertex3f(-1, d*(x+0)-1, d*(y+1)-1); - glVertex3f(-1, d*(x+1)-1, d*(y+1)-1); - glVertex3f(-1, d*(x+1)-1, d*(y+0)-1); - glVertex3f(-1, d*(x+0)-1, d*(y+0)-1); + glTexCoord2d(u0_b, v0_b); glVertex3f(-1, d*(x+0)-1, d*(y+1)-1); + glTexCoord2d(u1_b, v0_b); glVertex3f(-1, d*(x+1)-1, d*(y+1)-1); + glTexCoord2d(u1_b, v1_b); glVertex3f(-1, d*(x+1)-1, d*(y+0)-1); + glTexCoord2d(u0_b, v1_b); glVertex3f(-1, d*(x+0)-1, d*(y+0)-1); glNormal3f(0, -1, 0); // front - glVertex3f(d*(x+0)-1, -1, d*(y+0)-1); - glVertex3f(d*(x+1)-1, -1, d*(y+0)-1); - glVertex3f(d*(x+1)-1, -1, d*(y+1)-1); - glVertex3f(d*(x+0)-1, -1, d*(y+1)-1); + glTexCoord2d(u0_t, v0_t); glVertex3f(d*(x+0)-1, -1, d*(y+0)-1); + glTexCoord2d(u1_t, v0_t); glVertex3f(d*(x+1)-1, -1, d*(y+0)-1); + glTexCoord2d(u1_t, v1_t); glVertex3f(d*(x+1)-1, -1, d*(y+1)-1); + glTexCoord2d(u0_t, v1_t); glVertex3f(d*(x+0)-1, -1, d*(y+1)-1); glNormal3f(0, 1, 0); // back - glVertex3f(d*(x+0)-1, 1, d*(y+1)-1); - glVertex3f(d*(x+1)-1, 1, d*(y+1)-1); - glVertex3f(d*(x+1)-1, 1, d*(y+0)-1); - glVertex3f(d*(x+0)-1, 1, d*(y+0)-1); + glTexCoord2d(u0_b, v0_b); glVertex3f(d*(x+0)-1, 1, d*(y+1)-1); + glTexCoord2d(u1_b, v0_b); glVertex3f(d*(x+1)-1, 1, d*(y+1)-1); + glTexCoord2d(u1_b, v1_b); glVertex3f(d*(x+1)-1, 1, d*(y+0)-1); + glTexCoord2d(u0_b, v1_b); glVertex3f(d*(x+0)-1, 1, d*(y+0)-1); } } glEnd(); diff --git a/src/render/classic/render_gl3.c b/src/render/classic/render_gl3.c index b5ee76c3..4e1036e4 100644 --- a/src/render/classic/render_gl3.c +++ b/src/render/classic/render_gl3.c @@ -58,6 +58,21 @@ enum { }; +// check if geom type is a builtin shape with explicit UVs +static int isBuiltinWithUV(int type) { + return (type == mjGEOM_PLANE || + type == mjGEOM_SPHERE || + type == mjGEOM_ELLIPSOID || + type == mjGEOM_BOX || + type == mjGEOM_CYLINDER || + type == mjGEOM_CAPSULE || + type == mjGEOM_ARROW || + type == mjGEOM_ARROW1 || + type == mjGEOM_ARROW2 || + type == mjGEOM_TRIANGLE); +} + + // enable/disable texture mapping static void settexture(int type, int state, const mjrContext* con, const mjvGeom* geom) { float plane[4], scl[2]; @@ -102,18 +117,44 @@ static void settexture(int type, int state, const mjrContext* con, const mjvGeom } // explicit texture coordinates - else if (type == mjtexREGULAR && geom->texcoord) { + else if (type == mjtexREGULAR && geom && + (geom->texcoord || (texid >= 0 && con->textureType[texid] == mjTEXTURE_2D && isBuiltinWithUV(geom->type)))) { // enable if (state && texid >= 0) { glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, con->texture[texid]); + + // determine scaling + scl[0] = texrepeat[0] > 0 ? texrepeat[0] : 1.0f; + scl[1] = texrepeat[1] > 0 ? texrepeat[1] : 1.0f; + + // uniform: repeat relative to spatial units rather than object + if (texuniform) { + if (geom->size[0] > 0) { + scl[0] = scl[0] * geom->size[0]; + } + if (geom->size[1] > 0) { + scl[1] = scl[1] * geom->size[1]; + } + } + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + if (geom->type == mjGEOM_PLANE && (geom->size[0] <= 0 || geom->size[1] <= 0)) { + glTranslatef(-0.5f, -0.5f, 0.0f); + } + glScalef(scl[0], scl[1], 1.0f); + glMatrixMode(GL_MODELVIEW); } // disable else { glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); } } @@ -458,8 +499,11 @@ static void renderGeom(const mjvGeom* geom, int mode, const float* headpos, glDisable(GL_CULL_FACE); glBegin(GL_TRIANGLES); glNormal3f(0, 0, 1); + glTexCoord2f(0, 1); glVertex3f(0, 0, 0); + glTexCoord2f(1, 1); glVertex3f(size[0], 0, 0); + glTexCoord2f(0, 0); glVertex3f(0, size[1], 0); glEnd(); if (scn->flags[mjRND_CULL_FACE]) { diff --git a/src/render/filament/assets/pbr.mat b/src/render/filament/assets/pbr.mat index 5da47efc..631da851 100644 --- a/src/render/filament/assets/pbr.mat +++ b/src/render/filament/assets/pbr.mat @@ -26,7 +26,9 @@ material { { type : float4, name : BaseColorFactor }, { type : float, name : MetallicFactor }, { type : float, name : RoughnessFactor }, - { type : float, name : EmissiveFactor } + { type : float, name : EmissiveFactor }, + { type : float3, name : UvScale }, + { type : float3, name : UvOffset } ], requires : [ @@ -36,7 +38,7 @@ material { fragment { void material(inout MaterialInputs material) { - vec2 uv = getUV0(); + vec2 uv = getUV0() * materialParams.UvScale.xy + materialParams.UvOffset.xy; material.normal = texture(materialParams_Normal, uv).xyz * 2.0 - 1.0; prepareMaterial(material); diff --git a/src/render/filament/assets/pbr_packed.mat b/src/render/filament/assets/pbr_packed.mat index ecd7bfa0..4a192b83 100644 --- a/src/render/filament/assets/pbr_packed.mat +++ b/src/render/filament/assets/pbr_packed.mat @@ -24,7 +24,9 @@ material { { type : float4, name : BaseColorFactor }, { type : float, name : MetallicFactor }, { type : float, name : RoughnessFactor }, - { type : float, name : EmissiveFactor } + { type : float, name : EmissiveFactor }, + { type : float3, name : UvScale }, + { type : float3, name : UvOffset } ], requires : [ uv0 @@ -33,7 +35,7 @@ material { fragment { void material(inout MaterialInputs material) { - vec2 uv = getUV0(); + vec2 uv = getUV0() * materialParams.UvScale.xy + materialParams.UvOffset.xy; material.normal = texture(materialParams_Normal, uv).xyz * 2.0 - 1.0; prepareMaterial(material); diff --git a/src/render/filament/assets/phong_2d.mat b/src/render/filament/assets/phong_2d.mat index 06c873eb..ee6e136f 100644 --- a/src/render/filament/assets/phong_2d.mat +++ b/src/render/filament/assets/phong_2d.mat @@ -38,7 +38,11 @@ vertex { fragment { void material(inout MaterialInputs material) { - vec2 uv = variable_vertex_pos.xy * materialParams.UvScale.xy + materialParams.UvOffset.xy; + // Convert centered object-space positions [-1, 1] to standard [0, 1] UVs: + // * 0.5 scales [-1, 1] to [-0.5, 0.5] + // * -0.5 on Y flips the vertical axis (top of geom = V=0) + // * - vec2(0.5, 0.5) offsets origin to match OpenGL glTexGen conventions + vec2 uv = variable_vertex_pos.xy * vec2(0.5, -0.5) * materialParams.UvScale.xy - vec2(0.5, 0.5) + materialParams.UvOffset.xy; prepareMaterial(material); material.baseColor = materialParams.BaseColorFactor; diff --git a/src/render/filament/assets/phong_2d_fade.mat b/src/render/filament/assets/phong_2d_fade.mat index 15f690e3..d63c226e 100644 --- a/src/render/filament/assets/phong_2d_fade.mat +++ b/src/render/filament/assets/phong_2d_fade.mat @@ -39,7 +39,11 @@ vertex { fragment { void material(inout MaterialInputs material) { - vec2 uv = variable_vertex_pos.xy * materialParams.UvScale.xy + materialParams.UvOffset.xy; + // Convert centered object-space positions [-1, 1] to standard [0, 1] UVs: + // * 0.5 scales [-1, 1] to [-0.5, 0.5] + // * -0.5 on Y flips the vertical axis (top of geom = V=0) + // * - vec2(0.5, 0.5) offsets origin to match OpenGL glTexGen conventions + vec2 uv = variable_vertex_pos.xy * vec2(0.5, -0.5) * materialParams.UvScale.xy - vec2(0.5, 0.5) + materialParams.UvOffset.xy; prepareMaterial(material); material.baseColor = materialParams.BaseColorFactor; diff --git a/src/render/filament/assets/phong_2d_reflect.mat b/src/render/filament/assets/phong_2d_reflect.mat index bbf7ba46..f37e8966 100644 --- a/src/render/filament/assets/phong_2d_reflect.mat +++ b/src/render/filament/assets/phong_2d_reflect.mat @@ -40,7 +40,11 @@ vertex { fragment { void material(inout MaterialInputs material) { - vec2 uv = variable_vertex_pos.xy * materialParams.UvScale.xy + materialParams.UvOffset.xy; + // Convert centered object-space positions [-1, 1] to standard [0, 1] UVs: + // * 0.5 scales [-1, 1] to [-0.5, 0.5] + // * -0.5 on Y flips the vertical axis (top of geom = V=0) + // * - vec2(0.5, 0.5) offsets origin to match OpenGL glTexGen conventions + vec2 uv = variable_vertex_pos.xy * vec2(0.5, -0.5) * materialParams.UvScale.xy - vec2(0.5, 0.5) + materialParams.UvOffset.xy; vec2 screen_uv = gl_FragCoord.xy * getResolution().zw; prepareMaterial(material); diff --git a/src/render/filament/assets/phong_2d_uv.mat b/src/render/filament/assets/phong_2d_uv.mat index 726e9308..491a48fa 100644 --- a/src/render/filament/assets/phong_2d_uv.mat +++ b/src/render/filament/assets/phong_2d_uv.mat @@ -21,7 +21,9 @@ material { { type : float, name : SpecularFactor }, { type : float, name : GlossinessFactor }, { type : float, name : EmissiveFactor }, - { type : sampler2d, name : BaseColor } + { type : sampler2d, name : BaseColor }, + { type : float3, name : UvScale }, + { type : float3, name : UvOffset } ], requires : [ uv0 @@ -30,7 +32,7 @@ material { fragment { void material(inout MaterialInputs material) { - vec2 uv = getUV0(); + vec2 uv = getUV0() * materialParams.UvScale.xy + materialParams.UvOffset.xy; prepareMaterial(material); material.baseColor = materialParams.BaseColorFactor; diff --git a/src/render/filament/assets/phong_2d_uv_fade.mat b/src/render/filament/assets/phong_2d_uv_fade.mat index bdd6f74e..4419d1c0 100644 --- a/src/render/filament/assets/phong_2d_uv_fade.mat +++ b/src/render/filament/assets/phong_2d_uv_fade.mat @@ -22,7 +22,9 @@ material { { type : float, name : SpecularFactor }, { type : float, name : GlossinessFactor }, { type : float, name : EmissiveFactor }, - { type : sampler2d, name : BaseColor } + { type : sampler2d, name : BaseColor }, + { type : float3, name : UvScale }, + { type : float3, name : UvOffset } ], requires : [ uv0 @@ -31,7 +33,7 @@ material { fragment { void material(inout MaterialInputs material) { - vec2 uv = getUV0(); + vec2 uv = getUV0() * materialParams.UvScale.xy + materialParams.UvOffset.xy; prepareMaterial(material); material.baseColor = materialParams.BaseColorFactor; diff --git a/src/render/filament/assets/phong_2d_uv_reflect.mat b/src/render/filament/assets/phong_2d_uv_reflect.mat index 4160167d..3d795f8d 100644 --- a/src/render/filament/assets/phong_2d_uv_reflect.mat +++ b/src/render/filament/assets/phong_2d_uv_reflect.mat @@ -23,7 +23,9 @@ material { { type : float, name : EmissiveFactor }, { type : float, name : Reflectance }, { type : sampler2d, name : BaseColor }, - { type : sampler2d, name : Reflection } + { type : sampler2d, name : Reflection }, + { type : float3, name : UvScale }, + { type : float3, name : UvOffset } ], requires : [ uv0 @@ -32,7 +34,7 @@ material { fragment { void material(inout MaterialInputs material) { - vec2 uv = getUV0(); + vec2 uv = getUV0() * materialParams.UvScale.xy + materialParams.UvOffset.xy; vec2 screen_uv = gl_FragCoord.xy * getResolution().zw; prepareMaterial(material); diff --git a/src/render/filament/core/builtins.cc b/src/render/filament/core/builtins.cc index 9e40f99a..753dba39 100644 --- a/src/render/filament/core/builtins.cc +++ b/src/render/filament/core/builtins.cc @@ -76,17 +76,24 @@ class BuiltinBuilder { config.max_indices = builder->indices_.size(); config.index_type = mjINDEX_TYPE_U16; config.primitive_type = builder->primitive_type_; - config.num_attributes = 2; + config.num_attributes = builder->texcoords_.empty() ? 2 : 3; config.attributes[0].usage = mjVERTEX_ATTRIBUTE_USAGE_POSITION; config.attributes[0].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT3; config.attributes[1].usage = mjVERTEX_ATTRIBUTE_USAGE_TANGENTS; config.attributes[1].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT4; + if (!builder->texcoords_.empty()) { + config.attributes[2].usage = mjVERTEX_ATTRIBUTE_USAGE_UV; + config.attributes[2].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT2; + } mjrfMeshData data; mjrf_defaultMeshData(&data); data.num_vertices = builder->positions_.size(); data.vertices[0] = builder->positions_.data(); data.vertices[1] = builder->orientations_.data(); + if (!builder->texcoords_.empty()) { + data.vertices[2] = builder->texcoords_.data(); + } data.num_indices = builder->indices_.size(); data.indices = builder->indices_.data(); data.bounds_min[0] = builder->bounds_min_.x; @@ -114,6 +121,7 @@ class BuiltinBuilder { int primitive_type_ = mjMESH_PRIMITIVE_TYPE_TRIANGLES; std::vector positions_; std::vector orientations_; + std::vector texcoords_; std::vector indices_; float3 bounds_min_ = {0, 0, 0}; float3 bounds_max_ = {0, 0, 0}; @@ -143,6 +151,7 @@ class PlaneBuilder : public BuiltinBuilder { explicit PlaneBuilder(int num_quads_per_axis) { const int num_vertices = NumVerticesPerSide(num_quads_per_axis); positions_.reserve(num_vertices); + texcoords_.reserve(num_vertices); const float delta = 2.0f / num_quads_per_axis; for (int x = 0; x <= num_quads_per_axis; ++x) { @@ -150,6 +159,7 @@ class PlaneBuilder : public BuiltinBuilder { const float dx = delta * static_cast(x); const float dy = delta * static_cast(y); positions_.emplace_back(dx - 1.0f, dy - 1.0f, 0); + texcoords_.emplace_back(0.5f * dx, 1.0f - (0.5f * dy)); } } @@ -180,6 +190,11 @@ class TriangleBuilder : public BuiltinBuilder { positions_.emplace_back(1, 0, 0); positions_.emplace_back(0, 1, 0); + texcoords_.reserve(3); + texcoords_.emplace_back(0, 1); + texcoords_.emplace_back(1, 1); + texcoords_.emplace_back(0, 0); + orientations_.resize(positions_.size(), CalculateOrientation({0, 0, 1})); indices_.reserve(3); @@ -187,7 +202,7 @@ class TriangleBuilder : public BuiltinBuilder { indices_.emplace_back(1); indices_.emplace_back(2); - SetBounds({-1, -1, -0.001}, {1, 1, 0.001}); + SetBounds({0, 0, -0.001}, {1, 1, 0.001}); } }; @@ -255,6 +270,7 @@ class BoxBuilder : public BuiltinBuilder { positions_.reserve(num_vertices); orientations_.reserve(num_vertices); + texcoords_.reserve(num_vertices); indices_.reserve(num_indices); GenerateVerticesForSide({0, 1, 0}, @@ -302,6 +318,9 @@ class BoxBuilder : public BuiltinBuilder { const float3 position = pt_gen({dx, dy}); positions_.push_back(position); orientations_.push_back(orientation); + const float u = static_cast(x) / num_quads_per_axis_; + const float v = 1.0f - (static_cast(y) / num_quads_per_axis_); + texcoords_.emplace_back(u, v); } } } @@ -313,20 +332,26 @@ class BoxBuilder : public BuiltinBuilder { class TubeBuilder : public BuiltinBuilder { public: TubeBuilder(int num_stacks, int num_slices) { - const int num_vertices = num_slices * (num_stacks + 1); + const int verts_per_ring = num_slices + 1; + const int num_vertices = verts_per_ring * (num_stacks + 1); positions_.reserve(num_vertices); orientations_.reserve(num_vertices); + texcoords_.reserve(num_vertices); const float delta_angle = 2.f * std::numbers::pi / (float)num_slices; const float delta_stack = 2.f / static_cast(num_stacks); - for (int i = 0; i < num_slices; ++i) { - const float angle = static_cast(i) * delta_angle; + for (int i = 0; i <= num_slices; ++i) { + const int geo_i = i % num_slices; + const float angle = static_cast(geo_i) * delta_angle; const float2 pt{std::cos(angle), std::sin(angle)}; const float4 orientation = CalculateOrientation({pt.x, pt.y, 0}); + const float u = static_cast(i) / num_slices; for (int j = 0; j <= num_stacks; ++j) { const float z = -1.0f + (static_cast(j) * delta_stack); positions_.emplace_back(pt.x, pt.y, z); orientations_.push_back(orientation); + const float v = 1.0f - ((static_cast(j) * delta_stack) / 2.0f); + texcoords_.emplace_back(u, v); } } @@ -337,10 +362,11 @@ class TubeBuilder : public BuiltinBuilder { for (int i = 0; i < num_slices; ++i) { for (int j = 0; j < num_stacks; ++j) { const int base_idx = (i * num_vertices_in_spine) + j; + const int next_base_idx = ((i + 1) * num_vertices_in_spine) + j; const int i0 = base_idx + 0; const int i1 = base_idx + 1; - const int i2 = (base_idx + num_stacks + 2) % num_vertices; - const int i3 = (base_idx + num_stacks + 1) % num_vertices; + const int i2 = next_base_idx + 1; + const int i3 = next_base_idx + 0; AppendQuadIndices(indices_, i0, i3, i2, i1); } } @@ -357,8 +383,9 @@ class ConeBuilder : public BuiltinBuilder { ((num_stacks - 1) * num_slices * kNumVerticesPerQuad); positions_.reserve(num_vertices); orientations_.reserve(num_vertices); + texcoords_.reserve(num_vertices); - // pole: use triangles + // Pole: use triangles const float delta_angle = 2.0 * std::numbers::pi / static_cast(num_slices); const float delta_radius = 1.0f / static_cast(num_stacks); @@ -367,14 +394,20 @@ class ConeBuilder : public BuiltinBuilder { const float angle1 = (j + 0) * delta_angle; const float angle2 = (j + 1) * delta_angle; - AppendVert(angle1, delta_radius); - AppendVert(angle2, delta_radius); + const float u1 = static_cast(j) / num_slices; + const float u2 = static_cast(j + 1) / num_slices; + const float v1 = delta_radius; + const float u_mid = (u1 + u2) / 2.f; + + AppendVert(angle1, delta_radius, u1, v1); + AppendVert(angle2, delta_radius, u2, v1); positions_.emplace_back(0, 0, 1); orientations_.emplace_back(CalculateOrientation({0, 0, 1})); + texcoords_.emplace_back(u_mid, 0.f); } - // the rest: use quads + // The rest: use quads for (int i = 1; i < num_stacks; ++i) { const float radius1 = delta_radius * (i + 0); const float radius2 = delta_radius * (i + 1); @@ -382,10 +415,14 @@ class ConeBuilder : public BuiltinBuilder { for (int j = 0; j < num_slices; ++j) { const float angle1 = (j + 0) * delta_angle; const float angle2 = (j + 1) * delta_angle; - AppendVert(angle1, radius2); - AppendVert(angle2, radius2); - AppendVert(angle2, radius1); - AppendVert(angle1, radius1); + const float u1 = static_cast(j) / num_slices; + const float u2 = static_cast(j + 1) / num_slices; + const float v1 = radius1; + const float v2 = radius2; + AppendVert(angle1, radius2, u1, v2); + AppendVert(angle2, radius2, u2, v2); + AppendVert(angle2, radius1, u2, v1); + AppendVert(angle1, radius1, u1, v1); } } @@ -413,7 +450,7 @@ class ConeBuilder : public BuiltinBuilder { } private: - void AppendVert(float theta, float radius) { + void AppendVert(float theta, float radius, float u, float v) { static constexpr float kNormalScale = 0.70710678118f; const float cz = std::cos(theta); const float sz = std::sin(theta); @@ -421,6 +458,7 @@ class ConeBuilder : public BuiltinBuilder { const float3 n{cz * kNormalScale, sz * kNormalScale, kNormalScale}; positions_.push_back(pt); orientations_.push_back(CalculateOrientation(n)); + texcoords_.emplace_back(u, v); } }; @@ -429,15 +467,18 @@ class DiskBuilder : public BuiltinBuilder { explicit DiskBuilder(int num_slices) { const int num_vertices = num_slices + 1; positions_.reserve(num_vertices); + texcoords_.reserve(num_vertices); const float delta_angle = 2.0 * std::numbers::pi / static_cast(num_slices); positions_.push_back({0, 0, 0}); + texcoords_.emplace_back(0.5f, 0.5f); for (int i = 0; i < num_slices; ++i) { const float angle = static_cast(i) * delta_angle; const float x = std::cos(angle); const float y = std::sin(angle); positions_.push_back({x, y, 0}); + texcoords_.emplace_back(0.5f + 0.5f * x, 0.5f + 0.5f * y); } orientations_.resize(positions_.size(), CalculateOrientation({0, 0, 1})); @@ -458,178 +499,195 @@ class DiskBuilder : public BuiltinBuilder { class SphereBuilder : public BuiltinBuilder { public: SphereBuilder(int num_stacks, int num_slices) { - static constexpr uint16_t kNorthPoleIndex = 0; - static constexpr uint16_t kSouthPoleIndex = 1; + // To avoid a UV seam artifact, each latitude ring has num_slices+1 + // vertices: the last vertex is a geometric duplicate of the first but + // with u=1.0 instead of u=0.0. This prevents the GPU from interpolating + // backwards from uā‰ˆ0.97 to u=0.0 across the last quad. + // + // Each polar triangle also gets its own pole vertex with u set to the + // midpoint of the two ring vertices, avoiding the degenerate atan2 at + // the pole. - const int num_vertices = (num_stacks * num_slices) + 2; // +2 for poles + const int verts_per_ring = num_slices + 1; // extra vertex for u=1 seam + const int ring_verts = num_stacks * verts_per_ring; + const int pole_verts = 2 * num_slices; // one pole vert per polar triangle + const int num_vertices = ring_verts + pole_verts; positions_.reserve(num_vertices); orientations_.reserve(num_vertices); + texcoords_.reserve(num_vertices); const float lat_angle_delta = std::numbers::pi / static_cast(num_stacks + 1); const float lon_angle_delta = 2.0 * std::numbers::pi / static_cast(num_slices); - // Add the north and south poles. - AppendVert(0, 0, 1); - AppendVert(0, 0, -1); - - // Vertices by latitude. + // Latitude ring vertices (with seam column). for (int lat = 0; lat < num_stacks; ++lat) { - // +1 because we handle the north pole (which would be at a lat angle of - // 0-degrees) explicitly. const float lat_angle = static_cast(lat + 1) * lat_angle_delta; const float cos_lat_angle = std::cos(lat_angle); const float sin_lat_angle = std::sin(lat_angle); const float z = cos_lat_angle; + const float v = lat_angle / std::numbers::pi_v; - for (int lon = 0; lon < num_slices; ++lon) { - const float lon_angle = static_cast(lon) * lon_angle_delta; + for (int lon = 0; lon <= num_slices; ++lon) { + const float u = static_cast(lon) / num_slices; + // Wrap the geometry back to lon=0 for the seam column. + const int geo_lon = lon % num_slices; + const float lon_angle = static_cast(geo_lon) * lon_angle_delta; - const float cos_lon_angle = std::cos(lon_angle); - const float sin_lon_angle = std::sin(lon_angle); - - const float x = sin_lat_angle * cos_lon_angle; - const float y = sin_lat_angle * sin_lon_angle; - AppendVert(x, y, z); + const float x = sin_lat_angle * std::cos(lon_angle); + const float y = sin_lat_angle * std::sin(lon_angle); + AppendVert(x, y, z, u, v); } } + // Per-face pole vertices. Each polar triangle gets a unique pole vertex + // with u set to the midpoint of the two adjacent ring vertices. + const int north_pole_start = ring_verts; + for (int lon = 0; lon < num_slices; ++lon) { + const float u = (static_cast(lon) + 0.5f) / num_slices; + AppendVert(0, 0, 1, u, 0.0f); + } + const int south_pole_start = north_pole_start + num_slices; + for (int lon = 0; lon < num_slices; ++lon) { + const float u = (static_cast(lon) + 0.5f) / num_slices; + AppendVert(0, 0, -1, u, 1.0f); + } + + // Indices. const size_t num_tris_polar_cap = num_slices; const size_t num_quads_body = num_slices * (num_stacks - 1); const int num_indices = (2 * num_tris_polar_cap * kNumIndicesPerTriangle) + (num_quads_body * kNumIndicesPerQuad); indices_.reserve(num_indices); - // The first two vertices are the poles, so the first vertex in the first - // row starts at index 2. - uint16_t row_start = kSouthPoleIndex + 1; - - // North polar cap. + // North polar cap — each triangle uses its own pole vertex. + const uint16_t first_ring_start = 0; for (int lon = 0; lon < num_slices; ++lon) { - const int next = lon < (num_slices - 1) ? lon + 1 : 0; - indices_.push_back(kNorthPoleIndex); - indices_.push_back(row_start + lon); - indices_.push_back(row_start + next); + indices_.push_back(north_pole_start + lon); + indices_.push_back(first_ring_start + lon); + indices_.push_back(first_ring_start + lon + 1); } - // Latitudinal triangle strips. + // Latitudinal quad strips — no index wrapping needed thanks to seam column. for (int lat = 0; lat < num_stacks - 1; lat++) { - const uint16_t north_start = row_start; - const uint16_t south_start = row_start + num_slices; + const uint16_t north_start = lat * verts_per_ring; + const uint16_t south_start = (lat + 1) * verts_per_ring; for (int lon = 0; lon < num_slices; ++lon) { - // The offset to the index that is adjacent to the current index. - const int adjacent = lon < (num_slices - 1) ? lon + 1 : 0; - - const int i0 = (north_start + lon); - const int i1 = (south_start + lon); - const int i2 = (south_start + adjacent); - const int i3 = (north_start + adjacent); + const int i0 = north_start + lon; + const int i1 = south_start + lon; + const int i2 = south_start + lon + 1; + const int i3 = north_start + lon + 1; AppendQuadIndices(indices_, i0, i1, i2, i3); } - row_start += num_slices; } // South polar cap. + const uint16_t last_ring_start = (num_stacks - 1) * verts_per_ring; for (int lon = 0; lon < num_slices; ++lon) { - const int adjacent = lon < (num_slices - 1) ? lon + 1 : 0; - indices_.push_back(kSouthPoleIndex); - indices_.push_back(row_start + adjacent); - indices_.push_back(row_start + lon); + indices_.push_back(south_pole_start + lon); + indices_.push_back(last_ring_start + lon + 1); + indices_.push_back(last_ring_start + lon); } SetBounds({-1, -1, -1}, {1, 1, 1}); } private: - void AppendVert(float x, float y, float z) { + void AppendVert(float x, float y, float z, float u, float v) { const float3 pt{x, y, z}; positions_.push_back(pt); orientations_.push_back(CalculateOrientation(pt)); + texcoords_.emplace_back(u, v); } }; class DomeBuilder : public BuiltinBuilder { public: - DomeBuilder(int num_stacks, int num_slices) { - static constexpr uint16_t kPoleIndex = 0; + DomeBuilder(int num_stacks, int num_slices, bool flip_u = false, + bool flip_v = false) { + // Same seam-fix strategy as SphereBuilder: extra vertex per ring at u=1.0 + // and per-face pole vertices. - const int num_vertices = (num_stacks * num_slices) + 1; // +1 for poles + const int verts_per_ring = num_slices + 1; + const int ring_verts = num_stacks * verts_per_ring; + const int pole_verts = num_slices; // one pole vert per polar triangle + const int num_vertices = ring_verts + pole_verts; positions_.reserve(num_vertices); orientations_.reserve(num_vertices); + texcoords_.reserve(num_vertices); const float lat_angle_delta = 0.5 * std::numbers::pi / static_cast(num_stacks); const float lon_angle_delta = 2.0 * std::numbers::pi / static_cast(num_slices); - // Add the pole. - AppendVert(0, 0, 1); - - // Vertices by latitude. + // Latitude ring vertices (with seam column). for (int lat = 0; lat < num_stacks; ++lat) { - // +1 because we handle the north pole (which would be at a lat angle of - // 0-degrees) explicitly. const float lat_angle = static_cast(lat + 1) * lat_angle_delta; const float cos_lat_angle = std::cos(lat_angle); const float sin_lat_angle = std::sin(lat_angle); const float z = cos_lat_angle; + const float v_val = 1.0f - (2.0f * lat_angle / std::numbers::pi_v); + const float v = flip_v ? 1.0f - v_val : v_val; - for (int lon = 0; lon < num_slices; ++lon) { - const float lon_angle = static_cast(lon) * lon_angle_delta; - const float cos_lon_angle = std::cos(lon_angle); - const float sin_lon_angle = std::sin(lon_angle); + for (int lon = 0; lon <= num_slices; ++lon) { + const float u_val = static_cast(lon) / num_slices; + const float u = flip_u ? 1.0f - u_val : u_val; + const int geo_lon = lon % num_slices; + const float lon_angle = static_cast(geo_lon) * lon_angle_delta; - const float x = sin_lat_angle * cos_lon_angle; - const float y = sin_lat_angle * sin_lon_angle; - AppendVert(x, y, z); + const float x = sin_lat_angle * std::cos(lon_angle); + const float y = sin_lat_angle * std::sin(lon_angle); + AppendVert(x, y, z, u, v); } } + // Per-face pole vertices. + const int pole_start = ring_verts; + for (int lon = 0; lon < num_slices; ++lon) { + const float u_val = (static_cast(lon) + 0.5f) / num_slices; + const float u = flip_u ? 1.0f - u_val : u_val; + AppendVert(0, 0, 1, u, flip_v ? 0.0f : 1.0f); + } + + // Indices. const size_t num_tris_polar_cap = num_slices; const size_t num_quads_body = num_slices * (num_stacks - 1); const int num_indices = (num_tris_polar_cap * kNumIndicesPerTriangle) + (num_quads_body * kNumIndicesPerQuad); indices_.reserve(num_indices); - // The first vertex is the poles, so the first vertex in the first row - // starts at index 1. - uint16_t row_start = kPoleIndex + 1; - - // North polar cap. + // Polar cap — each triangle uses its own pole vertex. + const uint16_t first_ring_start = 0; for (int lon = 0; lon < num_slices; ++lon) { - const int next = lon < (num_slices - 1) ? lon + 1 : 0; - indices_.push_back(kPoleIndex); - indices_.push_back(row_start + lon); - indices_.push_back(row_start + next); + indices_.push_back(pole_start + lon); + indices_.push_back(first_ring_start + lon); + indices_.push_back(first_ring_start + lon + 1); } - // Latitudinal quad strips. The first "stack" was handled above, so we - // only need to iterate over N-1 stacks. + // Latitudinal quad strips. for (int lat = 0; lat < num_stacks - 1; lat++) { - const int north_start = row_start; - const int south_start = row_start + num_slices; + const uint16_t north_start = lat * verts_per_ring; + const uint16_t south_start = (lat + 1) * verts_per_ring; for (int lon = 0; lon < num_slices; ++lon) { - // The offset to the index that is adjacent to the current index. - const int adjacent = lon < (num_slices - 1) ? lon + 1 : 0; - - const int i0 = (north_start + lon); - const int i1 = (south_start + lon); - const int i2 = (south_start + adjacent); - const int i3 = (north_start + adjacent); + const int i0 = north_start + lon; + const int i1 = south_start + lon; + const int i2 = south_start + lon + 1; + const int i3 = north_start + lon + 1; AppendQuadIndices(indices_, i0, i1, i2, i3); } - row_start += num_slices; } SetBounds({-1, -1, 0}, {1, 1, 1}); } private: - void AppendVert(float x, float y, float z) { + void AppendVert(float x, float y, float z, float u, float v) { const float3 pt{x, y, z}; positions_.push_back(pt); orientations_.push_back(CalculateOrientation(pt)); + texcoords_.emplace_back(u, v); } }; @@ -643,7 +701,10 @@ Builtins::Builtins(filament::Engine* engine, int nstack, int nslice, sphere_ = BuiltinBuilder::Create(engine, nstack, nslice); tube_ = BuiltinBuilder::Create(engine, nstack, nslice); disk_ = BuiltinBuilder::Create(engine, nslice); - dome_ = BuiltinBuilder::Create(engine, nstack, nslice); + dome_top_ = + BuiltinBuilder::Create(engine, nstack, nslice, false, true); + dome_bottom_ = + BuiltinBuilder::Create(engine, nstack, nslice, true, false); cone_ = BuiltinBuilder::Create(engine, nstack, nslice); } @@ -655,7 +716,8 @@ const Mesh* Builtins::Box() { return box_.get(); } const Mesh* Builtins::Sphere() { return sphere_.get(); } const Mesh* Builtins::Cone() { return cone_.get(); } const Mesh* Builtins::Disk() { return disk_.get(); } -const Mesh* Builtins::Dome() { return dome_.get(); } +const Mesh* Builtins::DomeTop() { return dome_top_.get(); } +const Mesh* Builtins::DomeBottom() { return dome_bottom_.get(); } const Mesh* Builtins::Tube() { return tube_.get(); } } // namespace mujoco diff --git a/src/render/filament/core/builtins.h b/src/render/filament/core/builtins.h index 3024dd1f..4dbbdef6 100644 --- a/src/render/filament/core/builtins.h +++ b/src/render/filament/core/builtins.h @@ -36,7 +36,8 @@ class Builtins { const Mesh* Sphere(); const Mesh* Cone(); const Mesh* Disk(); - const Mesh* Dome(); + const Mesh* DomeTop(); + const Mesh* DomeBottom(); const Mesh* Tube(); private: @@ -48,7 +49,8 @@ class Builtins { std::unique_ptr sphere_; std::unique_ptr cone_; std::unique_ptr disk_; - std::unique_ptr dome_; + std::unique_ptr dome_top_; + std::unique_ptr dome_bottom_; std::unique_ptr tube_; }; diff --git a/src/render/filament/core/renderable.cc b/src/render/filament/core/renderable.cc index 96dda1be..25cd7fca 100644 --- a/src/render/filament/core/renderable.cc +++ b/src/render/filament/core/renderable.cc @@ -170,8 +170,11 @@ void Renderable::UpdateTransform() { filament::TransformManager& tm = GetEngine()->getTransformManager(); if (geom_type_ == mjGEOM_PLANE && (trs_.size[0] <= 0 || trs_.size[1] <= 0)) { infinite_plane_ = true; + static constexpr float kInfiniteScale = 0.5f * mjMAXPLANEGRID; + const mat4f scaling = + mat4f::scaling(float3{kInfiniteScale, kInfiniteScale, 1.0f}); const mat4f transform = - filament::math::mat4f(trs_.rotation, trs_.translation); + filament::math::mat4f(trs_.rotation, trs_.translation) * scaling; for (Part& part : parts_) { tm.setTransform(tm.getInstance(part.entity), transform); } @@ -340,43 +343,6 @@ void Renderable::BindMaterialInstance(const mjrfRenderRequest& request) { mju_error("No material instances to bind."); } - if (geom_type_ == mjGEOM_PLANE && infinite_plane_) { - // Emulate an infinite plane by recentering a large quad in world space - // relative to the camera. We use the shared mjMAXPLANEGRID value as the - // size of the quad to ensure the texture scaling matches. - static constexpr float kInfiniteScale = 0.5f * mjMAXPLANEGRID; - const mat4f scaling = - mat4f::scaling(float3{kInfiniteScale, kInfiniteScale, 1.0f}); - - const float3 camera_pos = ReadFloat3(request.camera.pos); - const float3 plane_origin = transform_[3].xyz; - const mat3f plane_rotation = transform_.upperLeft(); - - const float3 vec = camera_pos - plane_origin; - const float3 plane_x = normalize(plane_rotation[0]); - const float3 plane_y = normalize(plane_rotation[1]); - - // Project camera position onto the plane's local XY axes. - float dx = dot(vec, plane_x); - float dy = dot(vec, plane_y); - - // Quantize based on uv_scale. - const float tile_size[] = {kInfiniteScale / material_.uv_scale[0], - kInfiniteScale / material_.uv_scale[1]}; - dx = tile_size[0] * mju_round(dx / tile_size[0]); - dy = tile_size[1] * mju_round(dy / tile_size[1]); - - // Calculate the new center quad as a displacement from the plane origin. - const float3 displacement = dx * plane_x + dy * plane_y; - const float3 center = plane_origin + displacement; - - const mat4f transform = mat4f(plane_rotation, center) * scaling; - filament::TransformManager& tm = GetEngine()->getTransformManager(); - for (Part& part : parts_) { - tm.setTransform(tm.getInstance(part.entity), transform); - } - } - const DrawState& state = draw_queue_.front(); SetCastShadows(state.cast_shadows); SetReceiveShadows(state.receive_shadows); @@ -502,8 +468,8 @@ void Renderable::SetGeomMesh(mjtGeom type, int nstack, int nslice, int nquad) { case mjGEOM_CAPSULE: // Capsules are a tube with two domes at the ends. AppendMesh(builtins->Tube()); - AppendMesh(builtins->Dome()); - AppendMesh(builtins->Dome()); + AppendMesh(builtins->DomeTop()); + AppendMesh(builtins->DomeBottom()); get_transform_fn_ = [](int index, const Trs& trs) { // We apply an inverse scale to the domes to counteract the capsule's diff --git a/src/render/filament/support/model_objects.cc b/src/render/filament/support/model_objects.cc index 3e342c2b..32511ddc 100644 --- a/src/render/filament/support/model_objects.cc +++ b/src/render/filament/support/model_objects.cc @@ -157,15 +157,17 @@ static void FillMeshBuffer(MeshBuilder& builder, const mjModel* model, int meshi static void FillHeightFieldBuffer(MeshBuilder& builder, const mjModel* model, int hfieldid) { - auto append_tri = [&](float3 a, float3 b, float3 c) { + auto append_tri = [&](float3 a, float3 b, float3 c, float2 uv_a, float2 uv_b, + float2 uv_c) { float4 orientation = CalculateOrientation(a, b, c); - builder.Append(a, orientation, float2(0, 0)); - builder.Append(b, orientation, float2(0, 0)); - builder.Append(c, orientation, float2(0, 0)); + builder.Append(a, orientation, uv_a); + builder.Append(b, orientation, uv_b); + builder.Append(c, orientation, uv_c); }; - auto append_quad = [&](float3 a, float3 b, float3 c, float3 d) { - append_tri(a, b, d); - append_tri(d, b, c); + auto append_quad = [&](float3 a, float3 b, float3 c, float3 d, float2 uv_a, + float2 uv_b, float2 uv_c, float2 uv_d) { + append_tri(a, b, d, uv_a, uv_b, uv_d); + append_tri(d, b, c, uv_d, uv_b, uv_c); }; const float* data = model->hfield_data + model->hfield_adr[hfieldid]; @@ -227,10 +229,21 @@ static void FillHeightFieldBuffer(MeshBuilder& builder, const mjModel* model, } const float3 mid = {mid_x, mid_y, mid_z}; - append_tri(a, b, mid); - append_tri(b, c, mid); - append_tri(c, d, mid); - append_tri(d, a, mid); + const float2 uv_a = {(float)col / (ncol - 1), + 1.f - (float)row / (nrow - 1)}; + const float2 uv_b = {(float)(col + 1) / (ncol - 1), + 1.f - (float)row / (nrow - 1)}; + const float2 uv_c = {(float)(col + 1) / (ncol - 1), + 1.f - (float)(row + 1) / (nrow - 1)}; + const float2 uv_d = {(float)col / (ncol - 1), + 1.f - (float)(row + 1) / (nrow - 1)}; + const float2 uv_mid = {(float)(col + 0.5f) / (ncol - 1), + 1.f - (float)(row + 0.5f) / (nrow - 1)}; + + append_tri(a, b, mid, uv_a, uv_b, uv_mid); + append_tri(b, c, mid, uv_b, uv_c, uv_mid); + append_tri(c, d, mid, uv_c, uv_d, uv_mid); + append_tri(d, a, mid, uv_d, uv_a, uv_mid); } } // Build the left edge. @@ -239,7 +252,9 @@ static void FillHeightFieldBuffer(MeshBuilder& builder, const mjModel* model, const float3 b = get_pos(row + 1, 0); const float3 c = {b.x, b.y, -sz[3]}; const float3 d = {a.x, a.y, -sz[3]}; - append_quad(a, b, c, d); + const float2 uv_a = {0.f, 1.f - (float)row / (nrow - 1)}; + const float2 uv_b = {0.f, 1.f - (float)(row + 1) / (nrow - 1)}; + append_quad(a, b, c, d, uv_a, uv_b, uv_b, uv_a); } // Build the right edge. for (int row = 0; row < nrow - 1; ++row) { @@ -247,7 +262,9 @@ static void FillHeightFieldBuffer(MeshBuilder& builder, const mjModel* model, const float3 b = get_pos(row, ncol - 1); const float3 c = {b.x, b.y, -sz[3]}; const float3 d = {a.x, a.y, -sz[3]}; - append_quad(a, b, c, d); + const float2 uv_a = {1.f, 1.f - (float)(row + 1) / (nrow - 1)}; + const float2 uv_b = {1.f, 1.f - (float)row / (nrow - 1)}; + append_quad(a, b, c, d, uv_a, uv_b, uv_b, uv_a); } // Build the front edge. for (int col = 0; col < ncol - 1; ++col) { @@ -255,7 +272,9 @@ static void FillHeightFieldBuffer(MeshBuilder& builder, const mjModel* model, const float3 b = {a.x, a.y, -sz[3]}; const float3 d = get_pos(0, col + 1); const float3 c = {d.x, d.y, -sz[3]}; - append_quad(a, b, c, d); + const float2 uv_a = {(float)col / (ncol - 1), 1.f}; + const float2 uv_d = {(float)(col + 1) / (ncol - 1), 1.f}; + append_quad(a, b, c, d, uv_a, uv_a, uv_d, uv_d); } // Build the back edge. for (int col = 0; col < ncol - 1; ++col) { @@ -263,7 +282,9 @@ static void FillHeightFieldBuffer(MeshBuilder& builder, const mjModel* model, const float3 b = {a.x, a.y, -sz[3]}; const float3 d = get_pos(nrow - 1, col); const float3 c = {d.x, d.y, -sz[3]}; - append_quad(a, b, c, d); + const float2 uv_a = {(float)(col + 1) / (ncol - 1), 0.f}; + const float2 uv_d = {(float)col / (ncol - 1), 0.f}; + append_quad(a, b, c, d, uv_a, uv_a, uv_d, uv_d); } // Build the base. We use the visualization quality as the size rather than // the height field dimensions. @@ -275,8 +296,13 @@ static void FillHeightFieldBuffer(MeshBuilder& builder, const mjModel* model, const float x1 = sz[0] * ((col + 1) / base_width - 1.0f); const float y0 = sz[1] * ((row + 0) / base_height - 1.0f); const float y1 = sz[1] * ((row + 1) / base_height - 1.0f); + const float2 uv0 = {(col + 0) / (2.f * base_width), + 1.f - (row + 0) / (2.f * base_height)}; + const float2 uv1 = {(col + 1) / (2.f * base_width), + 1.f - (row + 1) / (2.f * base_height)}; append_quad({x0, y0, -sz[3]}, {x0, y1, -sz[3]}, {x1, y1, -sz[3]}, - {x1, y0, -sz[3]}); + {x1, y0, -sz[3]}, {uv0.x, uv0.y}, {uv0.x, uv1.y}, + {uv1.x, uv1.y}, {uv1.x, uv0.y}); } } } @@ -303,7 +329,7 @@ static int CalculateHeightFieldVertexCount(const mjModel* model, int hfieldid) { } static bool HasUvs(const mjModel* model, int id, MeshType mesh_type) { - return mesh_type != MeshType::kHeightField && + return mesh_type == MeshType::kHeightField || model->mesh_texcoordadr[id] >= 0; } diff --git a/src/render/filament/support/model_renderables.cc b/src/render/filament/support/model_renderables.cc index 948f1a10..764ab421 100644 --- a/src/render/filament/support/model_renderables.cc +++ b/src/render/filament/support/model_renderables.cc @@ -50,19 +50,6 @@ void xtof(float* dst, const T* src, int n) { } } -// Returns the tile size for infinite plane texture alignment. -// This is duplicated from engine_vis_visualize.c (re-center infinite plane) -// to ensure UV scaling matches the re-centering increments. -static float GetPlaneTileSize(const mjModel* model, int matid, - float texrepeat) { - if (matid >= 0 && texrepeat > 0) { - return 2.0f / texrepeat; - } else { - const float zfar = model->vis.map.zfar * model->stat.extent; - return 2.1f * zfar / (mjMAXPLANEGRID - 2); - } -} - static mjtCatBit GetBodyCategory(const mjModel* m, int bodyid) { // mocap subtrees are their own weld, hence not static if (m->body_weldid[bodyid] == 0) { @@ -745,12 +732,16 @@ mjrfMaterial ModelRenderables::GetDefaultMaterial(mjtObj obj_type, mjtGeom geom_type = mjGEOM_NONE; const float* rgba = nullptr; const mjtNum* size = nullptr; + const mjtNum* pos = nullptr; + const mjtNum* quat = nullptr; switch (obj_type) { case mjOBJ_GEOM: geom_type = (mjtGeom)model->geom_type[obj_index]; rgba = model->geom_rgba + (4 * obj_index); size = model->geom_size + (3 * obj_index); + pos = model->geom_pos + (3 * obj_index); + quat = model->geom_quat + (4 * obj_index); matid = model->geom_matid[obj_index]; break; case mjOBJ_SITE: @@ -873,35 +864,49 @@ mjrfMaterial ModelRenderables::GetDefaultMaterial(mjtObj obj_type, } } - if (tex_uniform) { - if (fsize[0] > 0) { - material.uv_scale[0] *= fsize[0]; - } - if (fsize[1] > 0) { - material.uv_scale[1] *= fsize[1]; - } - } const bool is_infinite_plane = geom_type == mjGEOM_PLANE && (fsize[0] <= 0 || fsize[1] <= 0); if (is_infinite_plane) { - // Infinite planes are scaled to match the tile size used by - // re-centering in engine_vis_visualize.c. + // With infinite planes, we want to use the UvOffset to account for + // the plane's position in world space due to re-centering. + // + // Infinite planes will use world-space UVs, with a tile size of 1x1 + // world units by default (texrepeat=(1, 1)). + // + // The shader computes: uv = uv0 * UvScale + UvOffset + // We want: uv = dot(worldPos, planeAxis) * texFrequency + // + // Since worldPos = rotation * (objectPos * planeScale) + geomPos: + // + // dot(worldPos, axisK) = objectPos.k * planeScale + dot(geomPos, axisK) + // + // Meaning: + // UvScale = planeScale * texrepeat + // UvOffset = dot(geomPos, planeAxis) * texrepeat const float plane_scale = static_cast(mjMAXPLANEGRID) / 2.0f; - const float tile_size_x = GetPlaneTileSize(model, matid, tex_repeat[0]); - const float tile_size_y = GetPlaneTileSize(model, matid, tex_repeat[1]); - material.uv_scale[0] = 2.0f * plane_scale / tile_size_x; - material.uv_scale[1] = 2.0f * plane_scale / tile_size_y; - } - // We want to do the equivalent of: - // mjr_setf4(splane, 0.5 * scl.x, 0, 0, -0.5); - // mjr_setf4(tplane, 0, -0.5 * scl.y, 0, -0.5); - // glTexGenfv(GL_S, GL_OBJECT_PLANE, splane); - // glTexGenfv(GL_T, GL_OBJECT_PLANE, tplane); - material.uv_scale[0] = 0.5f * material.uv_scale[0]; - material.uv_scale[1] = -0.5f * material.uv_scale[1]; - material.uv_offset[0] = -0.5f; - material.uv_offset[1] = -0.5f; + float dot_pos_axis_x = 0.0f; + float dot_pos_axis_y = 0.0f; + if (pos && quat) { + mjtNum mat[9]; + mju_quat2Mat(mat, quat); + dot_pos_axis_x = pos[0] * mat[0] + pos[1] * mat[3] + pos[2] * mat[6]; + dot_pos_axis_y = pos[0] * mat[1] + pos[1] * mat[4] + pos[2] * mat[7]; + } + + material.uv_scale[0] *= plane_scale; + material.uv_scale[1] *= plane_scale; + // The vertex UVs in PlaneBuilder are u0 = 0.5*x + 0.5, v0 = -0.5*y + 0.5. + // To keep the world-space texture coordinate u = 0.5*worldX*texrepeat - 0.5 + // independent of the snapped geomPos, uv_offset must compensate by 0.5*dot_pos. + material.uv_offset[0] = + (0.5f * dot_pos_axis_x - 0.5f * plane_scale) * tex_repeat[0] - 0.5f; + material.uv_offset[1] = + (-0.5f * dot_pos_axis_y - 0.5f * plane_scale) * tex_repeat[1] - 0.5f; + } else if (tex_uniform) { + material.uv_scale[0] *= (fsize[0] ? fsize[0] : 1.0f); + material.uv_scale[1] *= (fsize[1] ? fsize[1] : 1.0f); + } } else { // For cube maps, if `tex_uniform` is true, then scale the texture so that // it covers a 1x1 area of world space rather than the area of the object.