笔者注: 这篇文章是我本人在2009年发表在cppblog的一篇技术文章,由于我的技术博客迁移至博客园,所以转载到了此,非盗文。

  以下是正文:

  前段时间被项目组长委派实现基于3D地形的道路系统。实现的目标是类似于Crysis编辑器的功能:可以由编辑人员在地面上指定一系列控制点,用某种合适的曲线插值生成一条道路,指定纹理后就可以智能地将道路显示出来。

  然而要实现这些功能,必须克服以下的几个难题:
(1)用哪种曲线可以方便模拟出道路段,而且可以灵活地调节?
(2)地形通常都有Lod优化,其网格会实时变化,如何获取道路段覆盖的地形网格?如何让道路刚好“贴”在地表上而不会产生交叉,融合,断裂现象?
(3)如何生成道路顶点的纹理,才能不让纹理产生扭曲或其它不准确的现象?

  刚刚接到任务时,一头雾水,无从下手。于是急忙搬出google大哥,从gameres驰骋到gamedev,从项目组长询问到网上认识的高手,都没有找到道路实现的相关资料和有效的解决方法。

  后来研究了一下Crysis编辑器的道路系统操作和线条生成模式,并且在有着十几年游戏开发经验的Dunhill兄指点迷津下,终于找到了一些眉目,经过半个月多的摸索和调试,终于在今天比较完整地将道路系统实现了。由于网上资料少,特撰此文,如果以后有人也做到类似的专题,希望可以提供一些有用的信息。

  首先,将编辑人员指定的道路控制点用样条曲线生成一系列平滑过渡的道路段顶点。样条曲线有很多种,经过比较,我采用了B样条曲线,感觉它可以比较好地控制道路的弯曲,而且又不乏道路的平滑特性。由此解决了文章开头提出的问题(1)。效果如下图:
  

  上图有6个控制点,经过插值生成了一系列中间过渡点,从而将控制点连成了比较平滑的道路骨架。对于样条曲线插值的生成方法,网上很多资料,这里就不详细讨论了。

  接着,将生成的道路曲线分拆成一个个四边形(我们不妨称之为道路单元段),将这些四边形覆盖的地形图元提取出来。由于地形Lod是不断变化的,如果道路随着地形Lod变化就不断提取地形图元会使得效率很低下。经过一番研究,发现如果地形Lod做得足够好的话,由地形Lod变化而产生的地形Pop现象对道路影响不大,完全可以提取道路在地形最高Lod时覆盖的图元数据,由此解决了开头提出的问题(2)。注意在提取图元的时候要完全按照地形构造的规则进行提取,否则有可能出现道路和地形相交合或分离的问题。

  提取了某个道路单元段覆盖的地形图元后,将该道路单元段的四个顶点构造出四个垂直于水平面的裁剪面,将地形图元和构造的裁剪平面作为参数送入裁剪程序。裁剪程序通常是用三维齐次坐标的区位码标志裁剪方法,这个算法在《计算机图形学》一书有提及,网上也有该算法的详细描述。将裁减后的道路单元段链接起来后的效果如下图:
  

  黄色线条是地形图元,黑色的线条是道路的图元。可以看出,经过裁减后的道路增加了很多顶点和线条来链接道路和地形的相交点,这样做是为了防止道路与地形可能出现的交叉、分离和断裂现象。

  裁剪完道路单元段后,给每个道路单元段的顶点生成纹理坐标。尝试了很多方法,最后采用的纹理映射方法是如下:

  

  见上图,v0、v2、v3、v5是道路单元段的顶点,v1、v4分别是v0与v2、v3与v5的中点,v1到道路起始点的中轴线累积长度totalL,另外求出顶点到道路单元段的四个边距L1、L2、L3、L4和中轴线长L。
  纹理坐标u = L2 / (L2 + L4)
  纹理坐标v = (totalL + L * L1 / (L1 + L3) ) / tileLength (tileLength是纹理的格子长度,可由编辑人员调节)

  这种纹理映射方法在道路不是很弯的情况下,都能比较好地生产纹理图。但若道路弯曲得比较厉害,纹理也会出现扭曲。如果哪位能提出更好的纹理坐标生成方法,请告知。生成纹理坐标后,记得给道路顶点高度往上平移一点点(我取了0.01f),这样可以避免道路和地形由于Z值相同而产生闪烁现象.

  最后发一张贴上纹理的道路效果图,如有什么问题欢迎留言探讨。

  

3D地形中的道路模拟的更多相关文章

  1. 在WPF中使用PlaneProjection模拟动态3D效果

    原文:在WPF中使用PlaneProjection模拟动态3D效果 虽然在WPF中也集成了3D呈现的功能,在简单的3D应用中,有时候并不需要真实光影的3D场景.毕竟使用3D引擎会消耗很多资源,有时候使 ...

  2. ArcGIS Portal 10.4 本地坐标系的web 3d地形展示制作说明

    原文:ArcGIS Portal 10.4 本地坐标系的web 3d地形展示制作说明 ArcGIS Portal 10.4 本地坐标系的web 3d地形展示制作说明 By 李远祥 ArcGIS Por ...

  3. 【转载】3D/2D中的D3DXMatrixPerspectiveFovLH和D3DXMatrixOrthoLH投影函数详解

    原文:3D/2D中的D3DXMatrixPerspectiveFovLH和D3DXMatrixOrthoLH投影函数详解 3D中z值会影响屏幕坐标系到世界坐标系之间的转换,2D中Z值不会产生影响(而只 ...

  4. [Unity3D]Unity3D游戏开发之在3D场景中选择物体并显示轮廓效果

    大家好,我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei. 在<仙剑奇侠传>.<古剑奇谭>等游戏中,常常须要玩家在一个3D场景中 ...

  5. php中CURL技术模拟登陆抓取数据实战,抓取某校教务处学生成绩。

    这两天有基友要php中curl抓取教务处成绩的源码,用于微信公众平台的开发.下面笔者只好忍痛割爱了.php中CURL技术模拟登陆抓取数据实战,抓取沈阳工学院教务处学生成绩. 首先,教务处登录需要验证码 ...

  6. CSS3之3D效果中的transform运用

    css3中添加了很多新的标签 属性 描述 css transform 向元素应用 2D 或 3D 转换. 3 transform-origin 允许你改变被转换元素的位置. 3 transform-s ...

  7. 基于 HTML5 WebGL 的 3D 场景中的灯光效果

    构建 3D 的场景除了创建模型,对模型设置颜色和贴图外,还需要有灯光的效果才能更逼真的反映真实世界的场景.这个例子我觉得既美观又代表性很强,所以拿出来给大家分享一下. 本例地址:http://www. ...

  8. 3D Slicer Modify Mouse Event 修改3D Slicer中的鼠标响应事件

    在3D Slicer中,我们如果想在自己写的插件中来修改默认的鼠标响应事件的话,就需要先将原有的响应事件链接删除,然后建立自定义的响应事件链接,然后将自己要实现的功能写在响应事件函数中. 比如Slic ...

  9. WebGL和ThreeJs学习6--射线法确定3D空间中所选物体

    一.在 threejs 中如何确定下图3D空间中鼠标点击位置的 object 对象? 二.射线法确定步骤及代码 //Three.js提供一个射线类Raycaster来拾取场景里面的物体.更方便的使用鼠 ...

随机推荐

  1. 一个因xdata声明引起的隐含错误

    我们知道一般增强型c51自身的RAM只有128BYTES,根本不够用,所以一般在定义全局变量,静态变量时都要用XDATA作为关键字修饰数据的的存储类型.但要注意的是,定义和声明一定要一致,不然出现错误 ...

  2. RHEL 6.5----LVS(DR)

    主机名 IP  所需软件  master eth0==>192.168.30.140(Nat) eth0:1==>192.168.17.130(Nat) ipvsadm node-1 et ...

  3. 配置组件的 props

    组件是相互独立.可复用的单元,一个组件可能在不同地方被用到.但是在不同的场景下对这个组件的需求可能会根据情况有所不同,例如一个点赞按钮组件,在我这里需要它显示的文本是“点赞”和“取消”,当别的同事拿过 ...

  4. AJPFX关于java中的方法

    java中的方法和c语言中的函数类似,是新手入门面向对象之前的内容最大的难关如何写方法        1,明确返回值类型        2,明确参数列表 * 修饰符:目前就用 public stati ...

  5. 序列化json模块

    1.用json模块来进行序列化和反序列化 注意:用json序列化的数据类型得到的文件后缀名必须是json.因为如果不是json后缀,别人也不知道这是用json序列化的文件. 序列化:json.dump ...

  6. P3372 【模板】线段树 1 区间查询与区间修改

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个 ...

  7. 必看的dockerfile禁忌与建议!

    直接上对照组(看第三个run) test1 FROM centos MAINTAINER ** ​ RUN yum -y update RUN yum -y install wget ​ RUN wg ...

  8. FileZilla Server 端设置passive模式注意事项

    1,需求和问题的产生 实践中需要分布在各地的各个客户端向云端服务器上传文件,因此在阿里云服务器上安装了FileZilla Server软件作为文件FTP服务端. 客户端程序采用FTP方式向服务端传输文 ...

  9. MFC技术积累——基于MFC对话框类的那些事儿4

    3.3.4 借助兼容DC加载DIB位图 创建一个与设备环境相兼容的DC,通过将位图暂时导入至兼容DC,然后利用CDC::BitBlt 或者CDC::StretchBlt函数将位图绘制到设备环境中. 示 ...

  10. 程序员面试系列之Java单例模式的攻击与防御

    我写的程序员面试系列 Java面试系列-webapp文件夹和WebContent文件夹的区别? 程序员面试系列:Spring MVC能响应HTTP请求的原因? Java程序员面试系列-什么是Java ...