欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Three.js中自定義UV坐標貼圖舉例超詳細講解

 更新時間:2025年07月22日 10:23:57   作者:Code_Geo  
UV映射是一種將二維紋理映射到三維模型表面的技術(shù),這篇文章主要介紹了Three.js中自定義UV坐標貼圖的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

一、背景

1.1 使用場景 / 什么時候需要這樣處理

1、當原始幾何體沒有 UV 信息

  • 比如從 GeoJSON 或自定義頂點數(shù)據(jù)生成的幾何體,通常不包含默認的 uv 屬性。
  • 沒有 uv 信息,紋理就無法正確貼在模型表面。

2、當默認 UV 無法滿足紋理顯示需求

  • 比如自動生成的 UV 是按照立方體或球體映射方式,但你希望紋理按照 XY 平面鋪開。
  • 或你想自定義紋理拉伸、縮放、裁剪方式。

3、貼圖范圍較大時

  • 如將紋理貼在一個很大的面(如整個省份或城市)上,需要歸一化 UV才能完整顯示整張圖,否則紋理可能看起來被擠壓或重復。

4、材質(zhì)設(shè)置使用了 map(紋理貼圖)

  • UV 坐標直接決定了紋理如何映射到頂點上,沒有正確的 UV,貼圖就是黑的或者混亂的。

1.2 這樣處理的好處

好處描述
? 自定義貼圖范圍按照 XY 平面的實際邊界(bounding box)進行歸一化貼圖,紋理完整而且可控。
? 保證不同面統(tǒng)一貼圖邏輯使所有面在同一坐標系下統(tǒng)一使用紋理坐標,適用于多個 Mesh 的統(tǒng)一貼圖。
? 更好地適應(yīng)實際地理數(shù)據(jù)尤其適合地圖類、建筑投影、城市地塊等從經(jīng)緯度生成的模型。
? 提高美觀性避免貼圖拉伸、模糊、重復等問題。讓紋理在面上看起來更自然。

1.3 舉個例子

假如你從 GeoJSON 創(chuàng)建了一個類似湖北省的面模型,你貼上一張高清地圖 top.png 作為貼圖,如果不設(shè)置 UV:

  • 紋理可能根本看不到。

  • 或者整個紋理只出現(xiàn)在幾何體的一個小角落(默認 UV 不匹配)。

  • 甚至多個面公用同一張紋理,但位置都不對。

二、紋理貼圖與 UV 的基礎(chǔ)知識

在 3D 渲染中,為了將 2D 圖片(紋理)映射到 3D 幾何體上,需要用到 UV 坐標

概念說明
紋理貼圖(Texture Mapping)是將 2D 圖像(比如一張地圖、照片等)映射到 3D 模型表面的過程。
UV 坐標是二維坐標系 [u, v],對應(yīng)圖片的水平方向(U)和垂直方向(V),取值范圍通常是 [0, 1]。
目的指定幾何體的哪個頂點對應(yīng)紋理圖的哪個像素點。沒有 UV,Three.js 無法知道貼圖怎么“貼”上去。

例子:

  • uv = [0,0] 表示貼圖左下角,[1,1] 表示右上角。
  • 如果某三角面頂點 uv 是 [0,0], [1,0], [0,1],那紋理就會映射為一個右角三角區(qū)域。

三、代碼逐步解析

  const group = topPolygonMesh.object3d;
  if (!group) return;
  group.traverse(child => {
    if (child.isMesh && child.geometry && child.geometry.attributes.position) {
      const posAttr = child.geometry.attributes.position;
      const positions = posAttr.array;
      // 1. 計算 XY 投影平面的包圍盒
      let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
      for (let i = 0; i < positions.length; i += 3) {
        const x = positions[i];
        const y = positions[i + 1];
        if (x < minX) minX = x;
        if (y < minY) minY = y;
        if (x > maxX) maxX = x;
        if (y > maxY) maxY = y;
      };
      const width = maxX - minX;
      const height = maxY - minY;
      // 2. 根據(jù) bbox 生成新的 UV(按 XY 貼圖)
      const uv = [];
      for (let i = 0; i < positions.length; i += 3) {
        const x = positions[i];
        const y = positions[i + 1];
        const u = (x - minX) / width;
        const v = (y - minY) / height;
        uv.push(u, v);
      };
      // 3. 設(shè)置新的 UV
      child.geometry.setAttribute('uv', new THREE.Float32BufferAttribute(uv, 2));
      child.geometry.attributes.uv.needsUpdate = true;
    }
  })

使用你上面的邏輯:

  • 會將湖北省這個面在 XY 平面上的投影范圍歸一化為 [0,1] × [0,1],然后貼圖正好完整覆蓋整個省份模型頂面。
  • 并且每個三角面上紋理也會均勻分布,不會拉伸、重復或扭曲。

代碼每部分解析

const group = topPolygonMesh.object3d;
if (!group) return;
group.traverse(child => {
  if (child.isMesh && child.geometry && child.geometry.attributes.position) {

?? 找到場景中的所有 Mesh,確保其包含幾何體和位置(頂點)數(shù)據(jù)。

第一步:計算 XY 平面的包圍盒

const posAttr = child.geometry.attributes.position;
const positions = posAttr.array;

let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
for (let i = 0; i < positions.length; i += 3) {
  const x = positions[i];
  const y = positions[i + 1];
  if (x < minX) minX = x;
  if (y < minY) minY = y;
  if (x > maxX) maxX = x;
  if (y > maxY) maxY = y;
}
const width = maxX - minX;
const height = maxY - minY;

?? 獲取幾何體在 XY 平面上的包圍盒

第二步:計算新的 UV 坐標

const uv = [];
for (let i = 0; i < positions.length; i += 3) {
  const x = positions[i];
  const y = positions[i + 1];
  const u = (x - minX) / width;
  const v = (y - minY) / height;
  uv.push(u, v);
}

?? 將 XY 坐標歸一化為 UV 區(qū)間

第三步:應(yīng)用 UV 到幾何體

child.geometry.setAttribute('uv', new THREE.Float32BufferAttribute(uv, 2));
child.geometry.attributes.uv.needsUpdate = true;

?? 設(shè)置 UV 屬性并通知渲染系統(tǒng)更新

四、目的總結(jié)

該段代碼的最終目標是:
? 使 XY 平面上的任意不規(guī)則幾何體,都能準確、完整地顯示一張貼圖(通常是一張地圖或圖案)

五、為什么默認 UV 不適用?

場景是否需要手動設(shè)置 UV
自定義頂點數(shù)據(jù)構(gòu)建幾何體? 是的,需要自定義 UV
從 GeoJSON/TopoJSON 轉(zhuǎn)換成幾何體? 是的,沒有默認 UV
使用 ExtrudeGeometry, ShapeGeometry? 有自動生成 UV,但經(jīng)常不滿足 XY 貼圖的需要
紋理貼圖變形嚴重或重復? 需要重設(shè) UV 保證平鋪、清晰

總結(jié)

項目內(nèi)容
?? 目的將紋理按照 XY 平面貼滿整個面
?? 原理將 XY 坐標歸一化為 [0,1] 區(qū)間作為 UV
?? 效果保證紋理不變形、無縫、完整地顯示
?? 場景地圖貼圖、建筑貼圖、非規(guī)則面紋理貼圖
?? 重點UV 反映的是“紋理坐標”,不是世界坐標

到此這篇關(guān)于Three.js中自定義UV坐標貼圖的文章就介紹到這了,更多相關(guān)Three.js自定義UV坐標貼圖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論