聊一聊全景图

作者:李洋

前段时间学习了ThreeJS项目里边关于全景图的案例之后,自己动手练习了一下,实现了两个全景图的例子,分别如下:

WebGLRender 球型全景图

WebGLRender 立方体全景图

网络不好的情况下第一次打开可能会比较慢,因为全景图资源比较大。

实现原理比较简单,只要把摄像机放在模型中心,然后把全景图渲染到模型内表面即可;

不过还是需要注意以下两点:

其一有两种方法可以把全景图渲染到模型内表面;

1 . 一种是在创建材质时设置side参数为THREE.BackSide;

2 .另一种种则是对模型进行镜像变换;

其二球型全景图和立方体全景图使用的图片资源是有区别的;

球型全景图如下:

立方体全景图如下:

虽然球型全景图更贴近人眼的构建模式,但是从模型上来说比立方体更复杂,而且出于兼容性考虑使用CSSRender时是无法构建球模型的,因此立方体全景图具有更高的性能和更好的兼容性。

但是我在网络上并没有找到把球型全景图转换为立方体全景图的工具,相关文章也较少,稍有提及的也是一笔略过。

所幸在KM上找到了一遍andrewwen的文章虽然没有代码实现但是推导过程比较详细的文章球面全景图到立方体全景图的转换

根据自己搜到的相关知识并加以理解最终用WebGL实现了球型全景图转立方体全景图工具

点击上述链接应该会看到该程序根据一张球型全景图生成了一张正方形图片即立方体全景图的一个面;

该工具核心代码如下:

该工具每次只能得到立方体的一个面,图中y轴负平面没有被注释得到了执行,因此得到是y轴负平面也就是立方体的底面,要想得到其它平面,只需要执行相关平面代码即可。

最终得到的六个面后,对应相关命名代入立方体全景图例子中的图片数组即可得到立方体全景图了。

如果你还有兴趣了解该工具的实现,可以接着往下看;

虽然上边的核心代码很简单每个面大概三四行代码的样子,其实球型全景图到立方体全景图的转换涉及到好几个坐标系的相互映射,稍不小心就会出错,如下:

坐标系说明:

xyz坐标系是全景场景中的坐标系;st坐标系是立方体单个平面的纹理坐标系。

WebGL中的纹理坐标系统是二维的,为了将纹理坐标和广泛使用的x坐标和y坐标区分开来,使用s和t命名,称之为st坐标系统,WebGL纹理坐标系示意图以及纹理映射相关知识可以在WebGL ThreeJS学习总结一、二找到。

假设点P是从球面和Z轴的交点绕Y轴旋转theta,然后在Y轴和其本身组成的平面上绕其过原点的法向量旋转phi得到,那么点P的坐标如下:

    P(x,y,z);

    x = r*cos(phi)*sin(theta);
    y = r*sin(phi);
    z = r*cos(phi)*cos(theta);

因为立方体的六个面都和球面相切,那么假设上图中的OP直线和正方体的某个面相交于点Q,那么OQ向量肯定等于m乘以OP向量,那么点Q的坐标如下:

    OQ = m*OP;

    Q(x1,y1,z1);

    x1 = m*x = m*r*cos(phi)*sin(theta);
    y1 = m*y = m*r*sin(phi);
    z1 = m*z = m*r*cos(phi)*cos(theta);

如果点Q在立方体的Z平面上;

    z1 = r = m*r*cos(phi)*cos(theta);

    m*cos(phi)*cos(theta) = 1;
    m*sin(phi) = 1/cos(theta)*tan(phi);
    m*cos(phi)*sin(theta) = 1/tan(theta);

    x1 = r/tan(theta);
    y1 = r/cos(theta)*tan(phi);

    Q(r/tan(theta),r/cos(theta)*tan(phi),r);

此时得到了点Q在xyz坐标系中的坐标,再假设点Q在st坐标系中的坐标为(s0,t0),那么就可以求得theta和phi的值;

    //WebGL纹理坐标最大为1,因此r = 0.5
    float r = 0.5;

    //xyz坐标系和st坐标系的映射关系
    x = 0.5-s;
    y = t-0.5;

通过上边的分析就不难看懂下述代码了;

之所以求出theta和phi的值是因为可以通过这两个值把球型全景图转换为二维;示意图如下:

    float s1 = theta/PI*0.5 + 0.5;
    float t1 = phi/PI*2.0*0.5 + 0.5;

整个推导过程就可以理解为点Q(s0,t0)为立方体全景图z轴正平面的点,对应到二维球型全景图中的坐标为(s1,t1)

最后需要注意的是需要控制thetaphi的值不能让其超出范围,还有就是负平面的thetaphi可以根据正平面的theta或者phi加上一定的值得到。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏飞扬的花生

jsencrypt参数前端加密c#解密

      写程序时一般是通过form表单或者ajax方式将参数提交到服务器进行验证,如何防止提交的请求不被抓包后串改,虽然无法说绝对安全却给非法提交提高了难度...

4229
来自专栏杨龙飞前端

scrollto 到指定位置

2944
来自专栏pangguoming

Spring Boot集成JasperReports生成PDF文档

由于工作需要,要实现后端根据模板动态填充数据生成PDF文档,通过技术选型,使用Ireport5.6来设计模板,结合JasperReports5.6工具库来调用渲...

1.4K7
来自专栏菩提树下的杨过

Flash/Flex学习笔记(23):运动学原理

先写一个公用的小球类Ball: package{ import flash.display.Sprite; //小球 类 public class B...

27310
来自专栏陈仁松博客

ASP.NET Core 'Microsoft.Win32.Registry' 错误修复

今天在发布Asp.net Core应用到Azure的时候出现错误InvalidOperationException: Cannot find compilati...

5228
来自专栏张善友的专栏

Mix 10 上的asp.net mvc 2的相关Session

Beyond File | New Company: From Cheesy Sample to Social Platform Scott Hansel...

2787
来自专栏一个爱瞎折腾的程序猿

sqlserver使用存储过程跟踪SQL

USE [master] GO /****** Object: StoredProcedure [dbo].[sp_perfworkload_trace_s...

2860
来自专栏大内老A

The .NET of Tomorrow

Ed Charbeneau(http://developer.telerik.com/featured/the-net-of-tomorrow/) Exciti...

38610
来自专栏芋道源码1024

熔断器 Hystrix 源码解析 —— 断路器 HystrixCircuitBreaker

本文主要基于 Hystrix 1.5.X 版本 1. 概述 2. HystrixCircuitBreaker 3. HystrixCircuitBreaker....

5767
来自专栏我和未来有约会

Kit 3D 更新

Kit3D is a 3D graphics engine written for Microsoft Silverlight. Kit3D was inita...

2936

扫码关注云+社区