最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Three.js中自定義UV坐標(biāo)貼圖舉例超詳細(xì)講解

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

一、背景

1.1 使用場(chǎng)景 / 什么時(shí)候需要這樣處理

1、當(dāng)原始幾何體沒(méi)有 UV 信息

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

2、當(dāng)默認(rèn) UV 無(wú)法滿足紋理顯示需求

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

3、貼圖范圍較大時(shí)

  • 如將紋理貼在一個(gè)很大的面(如整個(gè)省份或城市)上,需要?dú)w一化 UV才能完整顯示整張圖,否則紋理可能看起來(lái)被擠壓或重復(fù)。

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

  • UV 坐標(biāo)直接決定了紋理如何映射到頂點(diǎn)上,沒(méi)有正確的 UV,貼圖就是黑的或者混亂的。

1.2 這樣處理的好處

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

1.3 舉個(gè)例子

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

  • 紋理可能根本看不到。

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

  • 甚至多個(gè)面公用同一張紋理,但位置都不對(duì)。

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

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

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

例子:

  • uv = [0,0] 表示貼圖左下角,[1,1] 表示右上角。
  • 如果某三角面頂點(diǎn) uv 是 [0,0], [1,0], [0,1],那紋理就會(huì)映射為一個(gè)右角三角區(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. 計(jì)算 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;
    }
  })

使用你上面的邏輯:

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

代碼每部分解析

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

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

第一步:計(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 平面上的包圍盒

第二步:計(jì)算新的 UV 坐標(biāo)

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 坐標(biāo)歸一化為 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é)

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

五、為什么默認(rèn) UV 不適用?

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

總結(jié)

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

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

相關(guān)文章

  • JS內(nèi)置對(duì)象和Math對(duì)象知識(shí)點(diǎn)詳解

    JS內(nèi)置對(duì)象和Math對(duì)象知識(shí)點(diǎn)詳解

    在本篇文章里小編給大家分享的是關(guān)于JS內(nèi)置對(duì)象和Math對(duì)象知識(shí)點(diǎn)詳解內(nèi)容,有需要的朋友們可以參考下。
    2020-04-04
  • 前端精度丟失問(wèn)題解決之后端Long類(lèi)型到前端的處理策略

    前端精度丟失問(wèn)題解決之后端Long類(lèi)型到前端的處理策略

    這篇文章主要介紹了前端精度丟失問(wèn)題解決之后端Long類(lèi)型到前端的處理策略,在Web開(kāi)發(fā)中前后端數(shù)據(jù)類(lèi)型不匹配尤其是Long類(lèi)型數(shù)據(jù)到前端可能導(dǎo)致精度丟失,文章探討了此問(wèn)題并提供三種解決方法,需要的朋友可以參考下
    2024-09-09
  • JavaScript中reduce()的用法實(shí)例

    JavaScript中reduce()的用法實(shí)例

    reduce()方法接收一個(gè)函數(shù)作為累加器(accumulator),數(shù)組中的每個(gè)值(從左到右)開(kāi)始縮減,最終為一個(gè)值,下面這篇文章主要給大家介紹了關(guān)于JavaScript中reduce()的用法實(shí)例,需要的朋友可以參考下
    2022-05-05
  • JS實(shí)現(xiàn)懸浮球只在一側(cè)滑動(dòng)并且是橫屏狀態(tài)下

    JS實(shí)現(xiàn)懸浮球只在一側(cè)滑動(dòng)并且是橫屏狀態(tài)下

    這篇文章主要介紹了JS實(shí)現(xiàn)懸浮球只在一側(cè)滑動(dòng) 并且是橫屏狀態(tài)下,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • 詳談js遍歷集合(Array,Map,Set)

    詳談js遍歷集合(Array,Map,Set)

    下面小編就為大家?guī)?lái)一篇詳談js遍歷集合(Array,Map,Set)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-04-04
  • JavaScript深入V8引擎以及編寫(xiě)優(yōu)化代碼的5個(gè)技巧

    JavaScript深入V8引擎以及編寫(xiě)優(yōu)化代碼的5個(gè)技巧

    這篇文章主要介紹了JavaScript深入V8引擎以及編寫(xiě)優(yōu)化代碼的5個(gè)技巧,JavaScript引擎是執(zhí)行 JavaScript 代碼的程序或解釋器。JavaScript引擎可以實(shí)現(xiàn)為標(biāo)準(zhǔn)解釋器,或者以某種形式將JavaScript編譯為字節(jié)碼的即時(shí)編譯器。,需要的朋友可以參考下
    2019-06-06
  • js調(diào)用AJAX時(shí)Get和post的亂碼解決方法

    js調(diào)用AJAX時(shí)Get和post的亂碼解決方法

    在使用"get"時(shí),抓取的頁(yè)面最后加上編碼類(lèi)型,在使用post時(shí)用vbscript解決了編碼問(wèn)題,具體實(shí)現(xiàn)如下,有類(lèi)似情況的朋友可以參考下哈
    2013-06-06
  • Javascript正則控制文本框只能輸入整數(shù)或浮點(diǎn)數(shù)

    Javascript正則控制文本框只能輸入整數(shù)或浮點(diǎn)數(shù)

    這篇文章主要介紹Javascript正則如何控制文本框只能輸入整數(shù)或浮點(diǎn)數(shù),需要的朋友可以參考下
    2014-09-09
  • BootStrap Fileinput的使用教程

    BootStrap Fileinput的使用教程

    bootstrap-fileinput是基于bootstrap的上傳控件。此控件在網(wǎng)上可以找到很多例子,接下來(lái)通過(guò)本文給大家分享bootstrap fileinput的使用教程,非常不錯(cuò),感興趣的朋友一起看看吧
    2016-12-12
  • JavaScript運(yùn)動(dòng)減速效果實(shí)例分析

    JavaScript運(yùn)動(dòng)減速效果實(shí)例分析

    這篇文章主要介紹了JavaScript運(yùn)動(dòng)減速效果,模擬了物體做減速運(yùn)動(dòng)的效果,以兩個(gè)實(shí)例形式分析了javascript實(shí)現(xiàn)物體做減速運(yùn)動(dòng)的實(shí)現(xiàn)技巧,涉及javascript動(dòng)態(tài)操作頁(yè)面元素樣式及數(shù)學(xué)運(yùn)算的方法,非常簡(jiǎn)潔實(shí)用,需要的朋友可以參考下
    2015-08-08

最新評(píng)論

昌都县| 曲阜市| 曲靖市| 玉田县| 辽宁省| 华宁县| 且末县| 卫辉市| 邯郸市| 昌图县| 泰顺县| 安乡县| 林甸县| 无为县| 长沙县| 湖口县| 余江县| 萝北县| 罗山县| 南江县| 普安县| 小金县| 伊宁县| 汝城县| 平昌县| 如东县| 抚宁县| 绵阳市| 尚志市| 金山区| 普陀区| 盐池县| 达孜县| 焦作市| 天祝| 宜丰县| 丰宁| 柯坪县| 东辽县| 尉犁县| 麦盖提县|