VR開發(fā)--八象限法根據(jù)全景二維坐標(biāo)換算出三維球面坐標(biāo)

背景: 在three中使用2:1的全景圖可以迅速成型VR項(xiàng)目上線, 但如果場景中需要標(biāo)注或者定位時(shí),由于沒有建模,很難迅速的找到三維坐標(biāo).尤其是當(dāng)需要定位的點(diǎn)很多時(shí),手工定位是一項(xiàng)十分痛苦的事情.

這個(gè)問題想了一周時(shí)間,極坐標(biāo)變換,高斯投影,geo定位等方法都試過,但是由于低維轉(zhuǎn)高維,缺少信息,均宣告失敗.周一例會(huì)的時(shí)候和三維圖形算法大神聊天,大神說可以嘗試著用數(shù)據(jù)擬合的方式來找找聯(lián)系,死馬當(dāng)活馬醫(yī),結(jié)果擬合分析后居然真找出了聯(lián)系,然后還意外發(fā)現(xiàn)了three是怎么拼接全景圖的(見附圖,坐標(biāo)點(diǎn)一致的地方three會(huì)進(jìn)行拼接,各象限的極限點(diǎn)已經(jīng)標(biāo)出,很容易寫出轉(zhuǎn)換函數(shù)),


擬合結(jié)果.png

今天花了一下午寫完轉(zhuǎn)換函數(shù),這樣就可以實(shí)現(xiàn)自動(dòng)標(biāo)記定位了,整體思路就是把全景圖按4:2:2的比例,切成8個(gè)象限,將uv與xy關(guān)聯(lián),再將z與uv的權(quán)重關(guān)系算出來,這樣就可以根據(jù)uv逆推出z,由于全景圖邊緣部分會(huì)存在畸變,所以要根據(jù)比例算出修正系數(shù),我司的系數(shù)大概是1.25,這個(gè)和相機(jī)有關(guān),完整代碼如下:

/**
 * 八象限法---根據(jù)全景二維坐標(biāo)換算球面坐標(biāo)
 * @param
 * panoramaX: 二維全景x
 * panoramaY: 二維全景y
 * panoramaW: 全景圖寬度w
 * panoramaH: 全景圖高度h
 * R: 球體半徑
 */
export function coordinateTransformation(panoramaX, panoramaY, panoramaW = 7680, panoramaH = 3840, R = 7000) {
    if (!panoramaX || !panoramaY) {
        return false
    }
    // 默認(rèn)第一象限(0,0)=>(0,1,0)
    let quadrantNum = 0
    // 球坐標(biāo)法線
    let normal = { x: 1, y: 1, z: 1 }
    // 球坐標(biāo)
    let sphereCoordinate = { x: 0, y: 0, z: 0 }
    // 全景圖切分?jǐn)?shù),按4:2:2的比例,至少8個(gè)象限
    const QUARTER_W_SEGMENT = 4
    const HALF_H_SEGMENT = 2
    // 象限單位
    const QUARTER_W = Math.floor(panoramaW / QUARTER_W_SEGMENT)
    const HALF_H = Math.floor(panoramaH / HALF_H_SEGMENT)
    // 象限外偏移,用于確定坐標(biāo)象限
    const QUADRANT_X = Math.floor(panoramaX / QUARTER_W)
    const QUADRANT_Y = Math.floor(panoramaY / HALF_H)
    // 象限內(nèi)偏移,用于換算球體坐標(biāo)
    const OFFSET_X_2D = Math.floor(panoramaX % QUARTER_W)
    const OFFSET_Y_2D = Math.floor(panoramaY % HALF_H)
    // 在南半球
    if (QUADRANT_Y) {
        quadrantNum += QUARTER_W_SEGMENT
        normal.y = -1
    }
    // 確定象限
    if (QUADRANT_X) {
        quadrantNum += QUADRANT_X
    }
    // 在左半球
    if (quadrantNum % QUARTER_W_SEGMENT < 2) {
        normal.x = -1
    }
    // 在前半球
    if (quadrantNum % QUARTER_W_SEGMENT < 3 && quadrantNum % QUARTER_W_SEGMENT > 0) {
        normal.z = -1
    }
    console.log('球體法線normal', normal);

    // 對Z軸影響的權(quán)重
    let POWER_Z = ""
    // 南北半球坐標(biāo)轉(zhuǎn)換,通過normal.y消除Y軸偏移帶來的誤差
    if (normal.y > 0) {
        //北半球右旋
        sphereCoordinate.y = (HALF_H - OFFSET_Y_2D) * 1.25 / HALF_H * normal.y
        POWER_Z = OFFSET_Y_2D / OFFSET_X_2D < 1 ? "Y" : "X"
    } else {
        //南半球左旋
        sphereCoordinate.y = (OFFSET_Y_2D / HALF_H) * 1.25 * normal.y
        POWER_Z = OFFSET_Y_2D / OFFSET_X_2D > 1 ? "Y" : "X"
    }

    //沒有了Y軸,簡化為四象限
    switch (quadrantNum % QUARTER_W_SEGMENT) {
        case 0: {
            sphereCoordinate.x = OFFSET_X_2D / QUARTER_W * normal.x
            if (POWER_Z === "X") {
                sphereCoordinate.z = (QUARTER_W - OFFSET_X_2D) / QUARTER_W * normal.z
            } else if (POWER_Z === "Y") {
                if (normal.y > 0) {
                    sphereCoordinate.z = OFFSET_Y_2D / HALF_H * normal.z
                } else {
                    sphereCoordinate.z = (HALF_H - OFFSET_Y_2D) / HALF_H * normal.z
                }
            }
            break
        }
        case 1: {
            sphereCoordinate.x = (QUARTER_W - OFFSET_X_2D) / QUARTER_W * normal.x
            if (POWER_Z === "X") {
                sphereCoordinate.z = (OFFSET_X_2D) / QUARTER_W * normal.z
            } else if (POWER_Z === "Y") {
                if (normal.y > 0) {
                    sphereCoordinate.z = OFFSET_Y_2D / HALF_H * normal.z
                } else {
                    sphereCoordinate.z = (HALF_H - OFFSET_Y_2D) / HALF_H * normal.z
                }
            }
            break
        }
        case 2: {
            sphereCoordinate.x = OFFSET_X_2D / QUARTER_W * normal.x
            if (POWER_Z === "X") {
                sphereCoordinate.z = (QUARTER_W - OFFSET_X_2D) / QUARTER_W * normal.z
            } else if (POWER_Z === "Y") {
                if (normal.y > 0) {
                    sphereCoordinate.z = OFFSET_Y_2D / HALF_H * normal.z
                } else {
                    sphereCoordinate.z = (HALF_H - OFFSET_Y_2D) / HALF_H * normal.z
                }
            }
            break
        }
        case 3: {
            sphereCoordinate.x = (QUARTER_W - OFFSET_X_2D) / QUARTER_W * normal.x
            if (POWER_Z === "X") {
                sphereCoordinate.z = (OFFSET_X_2D) / QUARTER_W * normal.z
            } else if (POWER_Z === "Y") {
                if (normal.y > 0) {
                    sphereCoordinate.z = OFFSET_Y_2D / HALF_H * normal.z
                } else {
                    sphereCoordinate.z = (HALF_H - OFFSET_Y_2D) / HALF_H * normal.z
                }
            }
            break
        }
    }
    sphereCoordinate = {
        x: Math.ceil(sphereCoordinate.x * R),
        y: Math.ceil(sphereCoordinate.y * R),
        z: Math.ceil(sphereCoordinate.z * R)
    }
    console.log('球體坐標(biāo)sphereCoordinate', sphereCoordinate);
    return sphereCoordinate
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末讨盒,一起剝皮案震驚了整個(gè)濱河市墅垮,隨后出現(xiàn)的幾起案子葱椭,更是在濱河造成了極大的恐慌廓鞠,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怎囚,死亡現(xiàn)場離奇詭異卿叽,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)恳守,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門考婴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人催烘,你說我怎么就攤上這事沥阱。” “怎么了伊群?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵考杉,是天一觀的道長。 經(jīng)常有香客問我舰始,道長崇棠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任丸卷,我火速辦了婚禮枕稀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘及老。我一直安慰自己抽莱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布骄恶。 她就那樣靜靜地躺著,像睡著了一般匕垫。 火紅的嫁衣襯著肌膚如雪僧鲁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機(jī)與錄音寞秃,去河邊找鬼斟叼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛春寿,可吹牛的內(nèi)容都是我干的朗涩。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼绑改,長吁一口氣:“原來是場噩夢啊……” “哼谢床!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起厘线,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤识腿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后造壮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體渡讼,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年耳璧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了成箫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡旨枯,死狀恐怖伟众,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情召廷,我是刑警寧澤凳厢,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站竞慢,受9級(jí)特大地震影響先紫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜筹煮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一遮精、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧败潦,春花似錦本冲、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至沟饥,卻和暖如春添怔,著一層夾襖步出監(jiān)牢的瞬間湾戳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工广料, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留砾脑,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓艾杏,卻偏偏與公主長得像韧衣,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子购桑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344