{"id":147,"date":"2025-07-29T03:29:30","date_gmt":"2025-07-29T03:29:30","guid":{"rendered":"https:\/\/summergeometry.org\/sgi2025\/?p=147"},"modified":"2025-08-01T23:54:27","modified_gmt":"2025-08-01T23:54:27","slug":"tutorial-week-day-4-texture-optimization","status":"publish","type":"post","link":"https:\/\/summergeometry.org\/sgi2025\/tutorial-week-day-4-texture-optimization\/","title":{"rendered":"Tutorial Week Day 4: Texture Optimization"},"content":{"rendered":"\n<h3 class=\"wp-block-heading\">Intro<\/h3>\n\n\n\n<p>Now that you&#8217;ve gotten the grasp of meshes, and created your very first 3D object on Polyscope, what can we do next? On Day 4 of the SGI Tutorial Week, we had speakers <a href=\"https:\/\/rgliu.com\/\">Richard Liu<\/a> and <a href=\"https:\/\/ddecatur.github.io\/\">Dale Decatur<\/a> from the <a href=\"https:\/\/3dl.cs.uchicago.edu\/\">Threedle Lab<\/a> at UChicago explaining about Texture Optimization.<\/p>\n\n\n\n<p>In animated movies and video games, we are used to observing them with realistic textures. Intuitively, we might imagine that we have this texture as a map applied as a flat &#8220;sticker&#8221; over it. However, we know from some well-known examples in cartography that it is difficult to create a 2D map of a 3D shape like the Earth without introducing distortions or cuts. <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"703\" src=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-2.png\" alt=\"\" class=\"wp-image-249\" srcset=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-2.png 1024w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-2-300x206.png 300w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-2-768x527.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><a href=\"https:\/\/www.jouav.com\/blog\/distortion-in-geography.html\">Source<\/a><\/figcaption><\/figure>\n<\/div>\n\n\n<p>Besides, ideally, we would want to be able to transition from the 2D to the 3D map <strong>interchangeably<\/strong>. Framing this 2D map as a function on \\(\\mathbb{R^2}\\), we would like it to be bijective.<\/p>\n\n\n\n<p>The process of creating a bijective map from a mesh S in \\(\\mathbb{R^3}\\) to a given domain \\(\\Omega\\), or \\(F: \\Omega \\leftrightarrow S\\), is known as mesh parametrization. <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"274\" src=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-3-1024x274.png\" alt=\"\" class=\"wp-image-250\" srcset=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-3-1024x274.png 1024w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-3-300x80.png 300w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-3-768x206.png 768w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-3-1200x322.png 1200w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-3.png 1358w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><a href=\"https:\/\/people.eecs.berkeley.edu\/~jrs\/meshpapers\/ShefferPraunRose.pdf\">Source<\/a><\/figcaption><\/figure>\n<\/div>\n\n\n<h3 class=\"wp-block-heading\">UV Unwrapping<\/h3>\n\n\n\n<p>Consider a mesh defined by the object as \\(M = {V, E, F}\\), with Vertices, Edges and Faces respectively, where:<\/p>\n\n\n\n\\begin{equation*}\n    V \\subset R^3 \n\\end{equation*}\n\n\n\n\\begin{align*}\n    E = \\{(i, j) \\quad &amp;| \\text{\\quad vertex i is connected to vertex j}\\} \\\\\n    F = \\{(i, j, k) \\quad &amp;| \\quad \\text{vertex i, j , k share a face}\\}\n\\end{align*}\n\n\n\n<p>For a mesh M, we define the parametrization as a function mapping vertices \\(V\\) to some domain \\(\\Omega\\)<\/p>\n\n\n\n\\begin{equation*}\n    U: V \\subset \\mathbb{R}^3 \\rightarrow \\Omega \\subset \\mathbb{R}^2\n\\end{equation*}\n\n\n\n<p>For every vertex \\(v_i\\) we assign a 2D coordinate \\(U(v_i) = (u_i, v_i)\\) (this is why the method is called UV unwrapping).<\/p>\n\n\n\n<p>This parametrization has a constraint, however. <strong>Only disk topology surfaces<\/strong> (those with a 1 boundary loop) surfaces admit a homeomorphism (a continuous and bijective map) to the bounded 2D plane.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"499\" src=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-4-1024x499.png\" alt=\"\" class=\"wp-image-251\" srcset=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-4-1024x499.png 1024w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-4-300x146.png 300w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-4-768x374.png 768w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-4.png 1198w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Source: Richard Liu<\/figcaption><\/figure>\n<\/div>\n\n\n<p>As a workaround, we can always introduce a <strong>cut<\/strong>. <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"459\" src=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-5-1024x459.png\" alt=\"\" class=\"wp-image-252\" srcset=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-5-1024x459.png 1024w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-5-300x134.png 300w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-5-768x344.png 768w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-5-1536x688.png 1536w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-5-1200x537.png 1200w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-5.png 1659w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Source: Richard Liu<\/figcaption><\/figure>\n<\/div>\n\n\n<p>However, these seams create discontinuities, and in turn, distortions we want to minimize. We can distinguish different kinds of distortions using the Jacobian, the matrix of all first-order partial derivatives of a vector-valued function. Specifically, we look at the <strong>singular<\/strong> values of the Jacobian (which in the UV function is defined as a 2&#215;3 matrix per triangle).<\/p>\n\n\n\n\\begin{align*}\n    J_f = U\\Sigma V^T = U \\begin{pmatrix} \n    \\sigma_1 &amp; 0 \\\\\n    0 &amp; \\sigma_2 \\\\ \n    0 &amp; 0\n    \\end{pmatrix} V^T \\\\\n    f \\text{ is equiareal or area preserving} \\Leftrightarrow \\sigma_1 \\sigma_2 &amp;= 1 \\\\\n    f \\text{ is equiareal or area preserving} \\Leftrightarrow \\sigma_1 &amp;= \\sigma_2 \\\\\n    f \\text{ is equiareal or area preserving} \\Leftrightarrow \\sigma_1 &amp;= \\sigma_2 = 1 \n\\end{align*}\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"495\" src=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-8-1024x495.png\" alt=\"\" class=\"wp-image-255\" srcset=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-8-1024x495.png 1024w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-8-300x145.png 300w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-8-768x372.png 768w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-8-1536x743.png 1536w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-8-1200x580.png 1200w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-8.png 1567w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><a href=\"https:\/\/github.com\/alecjacobson\/geometry-processing-parameterization?tab=readme-ov-file\">Source<\/a><\/figcaption><\/figure>\n<\/div>\n\n\n<p>We can find the Jacobians of the UV map assignment \\(U\\) using the mesh gradient operator \\(G \\in \\mathbb{R}^{3|F|\\times V}\\)<\/p>\n\n\n\n\\begin{align*}\n    GU = J \\in \\mathbb{R}^{3|F|\\times V}\n\\end{align*}\n\n\n\n<p>The classical approach for optimizing a mesh parametrization is viewing the mesh surface as the graph of a <strong>mass-spring system<\/strong> (least squares optimization problem). The mesh vertices are the nodes (with equal mass) with each edge acting as a spring with some stiffness constant. <\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"910\" height=\"368\" src=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-6.png\" alt=\"\" class=\"wp-image-253\" srcset=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-6.png 910w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-6-300x121.png 300w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-6-768x311.png 768w\" sizes=\"auto, (max-width: 910px) 100vw, 910px\" \/><figcaption class=\"wp-element-caption\">Source: Richard Liu<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Two key design choices in setting up this problem are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Where to put the boundary?<\/li>\n\n\n\n<li>How to set the spring weights (stiffness)?<\/li>\n<\/ul>\n\n\n\n<p>To compute the parametrization, we <strong>minimize<\/strong> the sum of spring potential energies.<\/p>\n\n\n\n\\begin{align*}\n    \\min_U \\sum_{\\{i, j\\} \\in E} w_ij || u_i &#8211; u_j||^2\n\\end{align*}\n\n\n\n<p>Where \\(u_i = (u_i, v_i)\\) is the UV coordinate to vertex i. We then aim to solve the ODE:<\/p>\n\n\n\n\\begin{align*}\n    \\frac{\\partial E}{\\partial u _i }=  \\sum_{j \\in N_i} 2 \\cdot w_{ij} (u_i &#8211; u_j) = 0\n\\end{align*}\n\n\n\n<p>Where \\(N_i\\) indexes all neighbors of vertex \\(i\\). We can now fix the boundary vertices and solve each equation for the remaining \\(u_i\\).<\/p>\n\n\n\n<p>A solution by Tutte (1963) and Floater (1997) was computed such that if the boundary is convex and the weights are positive, the solution is <strong>guaranteed to be injective<\/strong>. While an injective map has its limitations in terms of transferring the texture back into the 3D shape, it allows us to easily visualize the 2D map of this shape. <\/p>\n\n\n\n<p>Here, we would need to fix or map a boundary to a circle, where all weights are 1.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"613\" src=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-7-1024x613.png\" alt=\"\" class=\"wp-image-254\" srcset=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-7-1024x613.png 1024w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-7-300x180.png 300w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-7-768x460.png 768w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-7.png 1196w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><a href=\"https:\/\/github.com\/alecjacobson\/geometry-processing-parameterization?tab=readme-ov-file\">Source<\/a><\/figcaption><\/figure>\n<\/div>\n\n\n<p>An alternative to the classical approach is <strong>trivial parametrization<\/strong>, where we split the mesh up into its individual triangles in a triangle soup and then flatten each triangle (isometric distortion). We would then translate and scale all triangles to be packed into the unit square.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"264\" src=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-9-1024x264.png\" alt=\"\" class=\"wp-image-256\" srcset=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-9-1024x264.png 1024w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-9-300x77.png 300w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-9-768x198.png 768w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-9-1536x396.png 1536w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-9-1200x309.png 1200w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-9.png 1828w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Source: Richard Liu<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Translation and uniform scaling does not affect the angles, such that we have no angle distortion. So this tells us that this parametrization approach is <strong>conformal<\/strong>. <\/p>\n\n\n\n<p>Still, when packing triangles into the texture image, we might need to rescale them so they fit, meaning the areas are <strong>not guaranteed<\/strong> to be the same. We can verify this based on the SDF values:<\/p>\n\n\n\n\\begin{align*}\n    \\sigma_1\\sigma_2 \\neq 1\n\\end{align*}\n\n\n\n<p>This won&#8217;t be too relevant in the end though because all triangles get scaled by the same factor, so that the area of each triangle is preserved up to some global scaler. As a result, we would still get an even sampling of the surface, which is what we would care about, at least intuitively, for texture mapping. <\/p>\n\n\n\n<p>However, applying a classical algorithm to trivial parametrization is typically a <strong>bad solution because it introduces maximal cuts (discontinuities)<\/strong>. How can we overcome this issue?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Parametrization with Neural Networks<\/h3>\n\n\n\n<p>Assume we have some parametrized function and some target value. With an adaptive learning algorithm, we determine the direction in which to change our parameters so that the function moves closer to our target.<\/p>\n\n\n\n<p>We compute some loss or measure of closeness between our current function evaluation and our target value.We then compute the gradient of this loss with respect to our parameters. Take a small step in that direction. We would repeat this process until we ideally achieved the global minimum.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"395\" src=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-11-1024x395.png\" alt=\"\" class=\"wp-image-258\" srcset=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-11-1024x395.png 1024w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-11-300x116.png 300w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-11-768x296.png 768w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-11-1536x592.png 1536w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-11-1200x462.png 1200w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-11.png 1866w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\"><a href=\"https:\/\/mpopov.com\/blog\/2021\/02\/28\/animation-of-optimization-in-torch\/\" data-type=\"link\" data-id=\"https:\/\/mpopov.com\/blog\/2021\/02\/28\/animation-of-optimization-in-torch\/\">Source<\/a> (left) and <a href=\"https:\/\/mpopov.com\/blog\/2021\/02\/28\/animation-of-optimization-in-torch\/ https:\/\/www.bpesquet.fr\/mlhandbook\/fundamentals\/training_models.html\">Source<\/a> (right)<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Similarly, we can use an approach to optimize the mesh texture.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Parametric function = <\/strong>rendering function<\/li>\n\n\n\n<li><strong>Parameters =<\/strong> texture map pixel values (texel = texture pixel)<\/li>\n\n\n\n<li><strong>Target =<\/strong> existing images of the object with the desired colors<\/li>\n\n\n\n<li><strong>Loss =<\/strong> pixel differences between our rendered images and target images.<\/li>\n<\/ul>\n\n\n\n<p>What happens if we do this? We do achieve a texture map, but each pixel is mostly optimized independently. As a result, the texture ends up more grainy. <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"692\" height=\"1024\" src=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-12-692x1024.png\" alt=\"\" class=\"wp-image-259\" srcset=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-12-692x1024.png 692w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-12-203x300.png 203w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-12.png 701w\" sizes=\"auto, (max-width: 692px) 100vw, 692px\" \/><figcaption class=\"wp-element-caption\">Source: Dale Decatur<\/figcaption><\/figure>\n<\/div>\n\n\n<h4 class=\"wp-block-heading\">Improving Smoothness<\/h4>\n\n\n\n<p>What can we do to improve this? Well, we would want to make the function more smooth. For this, we can optimize a new function \\(\\phi(u, v) : \\mathbb{R}^2 \\rightarrow \\mathbb{R}^2\\) that maps the texels to RGB color values. By smoothness in \\(\\phi\\), we mean that \\(\\phi\\) is <strong>continuous<\/strong>. <\/p>\n\n\n\n<p>To get the color at any point in the 2D texture map, we just need to query \\(\\phi\\) at that UV coordinate! <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"641\" height=\"837\" src=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-16.png\" alt=\"\" class=\"wp-image-268\" srcset=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-16.png 641w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-16-230x300.png 230w\" sizes=\"auto, (max-width: 641px) 100vw, 641px\" \/><figcaption class=\"wp-element-caption\">Source: Dale Decatur<\/figcaption><\/figure>\n<\/div>\n\n\n<p>To encourage smoothness in \\(\\phi\\), we can use a 3D coordinate network.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"485\" height=\"864\" src=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-13.png\" alt=\"\" class=\"wp-image-260\" style=\"width:485px;height:auto\" srcset=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-13.png 485w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-13-168x300.png 168w\" sizes=\"auto, (max-width: 485px) 100vw, 485px\" \/><figcaption class=\"wp-element-caption\"><br>Tannic et al, CVPR 2021<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Consider a mapping from a 3D surface to a 2D texture. We can learn a 3D coordinate \\(\\phi\\): \\(\\mathbb{R}^3 \\rightarrow \\mathbb{R}^2\\) that maps 3D surface points to RGB colors. \\(\\phi(x, y, z) = (R, G, B)\\).<\/p>\n\n\n\n<p>We can then use the inverse map to go from 2D texture coordinates to 3D surface points, then query those points with the coordinate network to get colors, then map those colors back to the 2D texture for easy rendering.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"566\" src=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-14-1024x566.png\" alt=\"\" class=\"wp-image-261\" srcset=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-14-1024x566.png 1024w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-14-300x166.png 300w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-14-768x425.png 768w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-14-1200x663.png 1200w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-14.png 1532w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Source: Dale Decatur<\/figcaption><\/figure>\n<\/div>\n\n\n<h4 class=\"wp-block-heading\">How to compute an inverse map? <\/h4>\n\n\n\n<p>We aim to have a mapping from texels to surface poitns, but we already have a mapping from the vertices to the texel plane. The way we can map an arbitrary coordinate to the surface is through barycentric interpolation, a coordinate system relative to a given triangle. In this system, any points has 3 barycentric coordinates.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"659\" height=\"497\" src=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-15.png\" alt=\"\" class=\"wp-image-262\" srcset=\"https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-15.png 659w, https:\/\/summergeometry.org\/sgi2025\/wp-content\/uploads\/2025\/07\/image-15-300x226.png 300w\" sizes=\"auto, (max-width: 659px) 100vw, 659px\" \/><figcaption class=\"wp-element-caption\"><a href=\"https:\/\/en.wikipedia.org\/wiki\/Barycentric_coordinate_system\">Source<\/a><\/figcaption><\/figure>\n<\/div>\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Intro Now that you&#8217;ve gotten the grasp of meshes, and created your very first 3D object on Polyscope, what can we do next? On Day 4 of the SGI Tutorial Week, we had speakers Richard Liu and Dale Decatur from the Threedle Lab at UChicago explaining about Texture Optimization. In animated movies and video games, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":257,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[37],"tags":[],"ppma_author":[9],"class_list":["post-147","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorial-week"],"authors":[{"term_id":9,"user_id":0,"is_guest":1,"slug":"cap-marina-levay","display_name":"marina.levay","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/summergeometry.org\/sgi2025\/wp-json\/wp\/v2\/posts\/147","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/summergeometry.org\/sgi2025\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/summergeometry.org\/sgi2025\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/summergeometry.org\/sgi2025\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/summergeometry.org\/sgi2025\/wp-json\/wp\/v2\/comments?post=147"}],"version-history":[{"count":10,"href":"https:\/\/summergeometry.org\/sgi2025\/wp-json\/wp\/v2\/posts\/147\/revisions"}],"predecessor-version":[{"id":439,"href":"https:\/\/summergeometry.org\/sgi2025\/wp-json\/wp\/v2\/posts\/147\/revisions\/439"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/summergeometry.org\/sgi2025\/wp-json\/wp\/v2\/media\/257"}],"wp:attachment":[{"href":"https:\/\/summergeometry.org\/sgi2025\/wp-json\/wp\/v2\/media?parent=147"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/summergeometry.org\/sgi2025\/wp-json\/wp\/v2\/categories?post=147"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/summergeometry.org\/sgi2025\/wp-json\/wp\/v2\/tags?post=147"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/summergeometry.org\/sgi2025\/wp-json\/wp\/v2\/ppma_author?post=147"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}