QuadTree四叉树顾名思义就是树状的数据结构,其每个节点有四个孩子节点,可将二维平面递归分割子区域。QuadTree常用于空间数据库索引,3D的椎体可见区域裁剪,甚至图片分析处理,我们今天介绍的是QuadTree最常被游戏领域使用到的碰撞检测。采用QuadTree算法将大大减少需要测试碰撞的次数,从而提高游戏刷新性能,本文例子基于HT for Web的Canvas拓扑图和WebGL的3D引擎组件,通过GraphViewGraph3dView共享同一数据模型DataModel,同时呈现QuadTree算法下的2D和3D碰撞视图效果:http://v.youku.com/v_show/id_XODQyNTA1NjY0.html

http://www.hightopo.com/demo/QuadTree/ht-quadtree.html

QuadTree的实现有很多成熟的版本,我选择的是 https://github.com/timohausmann/quadtree-js/ 四叉树的算法很简单,因此这个开源库也就两百来行代码。使用也非常简单,构建一个Quadtree对象,第一个参数传入rect信息制定游戏空间范围,在每次requestAnimationFrame刷新帧时,先通过quadtree.clear()清除老数据,通过quadtree.insert(rect)插入新的节点矩形区域,这样quadtree就初始化好了,剩下就是根据需要调用quadtree.retrieve(rect)获取指定矩形区域下,与其可能相交需要检测的矩形对象数组。

我构建了HT(http://www.hightopo.com/)的GraphViewGraph3dView两个组件,通过ht.widget.SplitView左右分割,由于两个视图都共享同一DataModel,因此我们剩下的关注点仅是对DataModel的数据操作,构建了200个ht.Node对象,每个对象的attr属性上保存了随机的运动方向vx和vy,同时保存了将要反复插入quadtree的矩形对象,这样避免每帧更新时反复创建对象,同时矩形对象也引用了ht.Node对象,用来当通过quadtree.retrieve(rect)获取需要检测的矩形对象时,我们能指定其所关联的ht.Node对象,因为我们需要对最终检测为碰撞的图元设置上红颜色的效果,也就是ht.Node平时显示默认的蓝色,当互相碰撞时将改变为红色。

需要注意从quadtree.retrieve(rect)获取需要检测的矩形对象数组中会包含自身图元,同时这些仅仅是可能会碰撞的图元,并不意味着已经碰撞了,由于我们例子是矩形,因此采用ht.Default.intersectsRect(r1, r2)最终判断是否相交,如果你的例子是圆形则可以采用计算两个圆心距离是否小于两个半径来决定是否相交,因此最终判断的标准根据游戏类型会有差异。

采用了QuadTree还是极大了提高了运算性能,否则100个图元就需要100*100次的监测,我这个例子场景下一般也就100*(10~30)的量:http://v.youku.com/v_show/id_XODQyNTA1NjY0.html

http://www.hightopo.com/demo/QuadTree/ht-quadtree.html

除了碰撞检测外QuadTree算法还有很多有趣的应用领域,有兴趣可以玩玩这个 https://github.com/fogleman/Quads

所有代码如下供参考:

  1. function init(){
  2. d = 200;
  3. speed = 8;
  4. dataModel = new ht.DataModel();
  5. g3d = new ht.graph3d.Graph3dView(dataModel);
  6. g2d = new ht.graph.GraphView(dataModel);
  7. mainSplit = new ht.widget.SplitView(g3d, g2d);
  8. mainSplit.addToDOM();
  9. g2d.translate(300, 220);
  10. g2d.setZoom(0.8, true);
  11.  
  12. for(var i=0; i<100; i++) {
  13. var node = new ht.Node();
  14. node.s3(randMinMax(5, 30), 10, randMinMax(5, 30));
  15. node.p3(randMinMax(-d/2, d/2), 0, randMinMax(-d/2, d/2));
  16. node.s({
  17. 'batch': 'group',
  18. 'shape': 'rect',
  19. 'shape.border.width': 1,
  20. 'shape.border.color': 'white',
  21. 'wf.visible': true,
  22. 'wf.color': 'white'
  23. });
  24. node.a({
  25. vx: randMinMax(-speed, speed),
  26. vy: randMinMax(-speed, speed),
  27. obj: {
  28. width: node.getWidth(),
  29. height: node.getHeight(),
  30. data: node
  31. }
  32. });
  33. dataModel.add(node);
  34. }
  35. createShape([
  36. {x: -d, y: d},
  37. {x: d, y: d},
  38. {x: d, y: -d},
  39. {x: -d, y: -d},
  40. {x: -d, y: d}
  41. ]);
  42. quadtree = new Quadtree({ x: -d, y: -d, width: d, height: d });
  43. requestAnimationFrame(update);
  44. }
  45. function update() {
  46. quadtree.clear();
  47. dataModel.each(function(data){
  48. if(!(data instanceof ht.Shape)){
  49. var position = data.getPosition();
  50. var vx = data.a('vx');
  51. var vy = data.a('vy');
  52. var w = data.getWidth()/2;
  53. var h = data.getHeight()/2;
  54. var x = position.x + vx;
  55. var y = position.y + vy;
  56. if(x - w < -d){
  57. data.a('vx', -vx);
  58. x = -d + w;
  59. }
  60. if(x + w > d){
  61. data.a('vx', -vx);
  62. x = d - w;
  63. }
  64. if(y - h < -d){
  65. data.a('vy', -vy);
  66. y = -d + h;
  67. }
  68. if(y + h > d){
  69. data.a('vy', -vy);
  70. y = d - h;
  71. }
  72. data.setPosition(x, y);
  73. var obj = data.a('obj');
  74. obj.x = x - w;
  75. obj.y = y - h;
  76.  
  77. quadtree.insert(obj);
  78. setColor(data, undefined);
  79. }
  80. });
  81. dataModel.each(function(data){
  82. if(!(data instanceof ht.Shape)){
  83. var obj = data.a('obj');
  84. var objs = quadtree.retrieve(obj);
  85. if(objs.length > 1){
  86. for(var i=0; i<objs.length; i++ ) {
  87. var data2 = objs[i].data;
  88. if(data === data2){
  89. continue;
  90. }
  91. if(ht.Default.intersectsRect(obj, data2.a('obj'))){
  92. setColor(data, 'red');
  93. setColor(data2, 'red');
  94. }
  95. }
  96. }
  97. }
  98. });
  99. requestAnimationFrame(update);
  100. }
  101. function randMinMax(min, max) {
  102. return min + (Math.random() * (max - min));
  103. }
  104. function createShape(points){
  105. shape = new ht.Shape();
  106. shape.setPoints(points);
  107. shape.setThickness(4);
  108. shape.setTall(10);
  109. shape.s({
  110. 'all.color': 'red',
  111. 'shape.background': null,
  112. 'shape.border.width': 2,
  113. 'shape.border.color': 'red'
  114. });
  115. dataModel.add(shape);
  116. return shape;
  117. }
  118. function setColor(data, color){
  119. data.s({
  120. 'all.color': color,
  121. 'shape.background': color
  122. });
  123. }

HTML5实现3D和2D可视化QuadTree四叉树碰撞检测的更多相关文章

  1. HT for Web可视化QuadTree四叉树碰撞检测

    QuadTree四叉树顾名思义就是树状的数据结构,其每个节点有四个孩子节点,可将二维平面递归分割子区域.QuadTree常用于空间数据库索引,3D的椎体可见区域裁剪,甚至图片分析处理,我们今天介绍的是 ...

  2. 基于HTML5实现3D热图Heatmap应用

    Heatmap热图通过众多数据点信息,汇聚成直观可视化颜色效果,热图已广泛被应用于气象预报.医疗成像.机房温度监控等行业,甚至应用于竞技体育领域的数据分析. http://www.hightopo.c ...

  3. 基于 HTML5 的 PID-进料系统可视化界面

    前言 随着工业物联网和互联网技术的普及和发展,人工填料的方式已经逐渐被机械设备取代.工业厂商减小误操作.提升设备安全以及追求高效率等制造特点对设备的要求愈加高标准.严要求.同时机械生产以后还需遵从整个 ...

  4. 基于 HTML5 + Canvas 实现的 PID 可视化系统

    前言 随着工业物联网和互联网技术的普及和发展,人工填料的方式已经逐渐被机械设备取代.工业厂商减小误操作.提升设备安全以及追求高效率等制造特点对设备的要求愈加高标准.严要求.同时机械生产以后还需遵从整个 ...

  5. 基于 HTML5 WebGL 的智慧楼宇可视化系统

    前言 可视化的智慧楼宇在 21 世纪是有急迫需求的,中国被世界称为"基建狂魔",全球高层建筑数量位居首位,所以对于楼宇的监控是必不可少.智慧楼宇可视化系统更多突出的是管理方面的功能 ...

  6. 50代码HTML5 Canvas 3D 编辑器优雅搞定

    1024程序员节刚过,手痒想实现一个html的3d编辑器,看了three.js 同时还看了网上流传已久的<<基于 HTML5 Canvas 的简易 2D 3D 编辑器>>,都觉 ...

  7. 一种Flash页游前端3D转2D显示技术——PV2D, 颠覆传统吧!

    stage3D很强大,但是客户端硬件加速支持有限. 出来的图形锯齿严重,看上去和果冻一样. Stage3d不兼容2d模式. 总的来说,3D很美好,现实很残酷.但是3D有无可比拟的优势:那就是节省90% ...

  8. CutJS – 用于 HTML5 游戏开发的 2D 渲染引擎

    CutJS 是轻量级的,快速的,基于 Canvas 开发的 HTML5  2D 渲染引擎,可以用于游戏开发.它是开源的,跨平台的,与现代的浏览器和移动设备兼容.CutJS 提供了一个类似 DOM 树的 ...

  9. 8月7号晚7点Autodesk北京办公室,我们来聊聊HTML5/ WebGL 3D 模型浏览技术

    Autodesk 发布了一款完全无需插件的三维模型浏览器 Autodesk 360 Viewer,大家有没有兴趣,下班后过来聊聊吧!   8月7号 周四, 19:00~21:00 Autodesk北京 ...

随机推荐

  1. .Net Core CLI在CentOS7的安装及使用简介

    1. 安装libunwind cd /usr/local/src wget http://download.savannah.gnu.org/releases/libunwind/libunwind- ...

  2. 让人一用钟情的VS插件系列之一——Web Essentials(Web开发必备利器)

    返回VS插件总目录 本篇目录 初识Web Essentials 看国外大牛如何评价Web Essentials Web Essentials下载与安装 Web Essentials涉及到了哪些内容 初 ...

  3. 用“MEAN”技术栈开发web应用(二)express搭建服务端框架

    上一篇我们讲了如何使用angular搭建起项目的前端框架,前端抽象出一个service层来向后端发送请求,后端则返回相应的json数据.本篇我们来介绍一下,如何在nodejs环境下利用express来 ...

  4. HTML5文件上传插件 Huploadify V2.1发布

    月初发布了HUploadify2.0版本,增加了文件的断点续传功能,得到了不少朋友的好评.本着按照Uploadify原样复制的原则,本次在一些朋友的建议中采纳了几点,做了一次较小的改动,定为2.1版本 ...

  5. underscore源码阅读记录(二)

    引自underscore.js context参数用法 _.each(list, iteratee, [context]); context为上下文,如果传递了context参数,则把iterator ...

  6. Java程序员的日常 —— 响应式导航Demo

    这两天想要做响应式的页面,于是本着重复造轮子的想法,模仿Bootstrap官网,精简了一个响应式导航的Demo. 效果 代码 <!DOCTYPE html> <html> &l ...

  7. python 多线程网络编程 ( 二 )

    背景 我在[第一篇文章中]已经介绍了如何实现一个多线程的todo应用,接下来我将会研究如何使这个服务器完成下面这几个功能. 1.使用正则表达式解析用户发送的请求数据: 2.使用ThreadLocal技 ...

  8. python多线程网络编程

    背景 使用过flask框架后,我对request这个全局实例非常感兴趣.它在客户端发起请求后会保存着所有的客户端数据,例如用户上传的表单或者文件等.那么在很多客户端发起请求时,服务器是怎么去区分不同的 ...

  9. Atitit.数据库存储引擎的原理与attilax 总结

    Atitit.数据库存储引擎的原理与attilax 总结 1. 存储引擎是什么1 2. 其它数据库系统(包括大多数商业选择)仅支持一种类型的数据存储2 3. 表的存储有三个文件:结构+数据+索引2 4 ...

  10. Atitit图片复制父目录给你设计的实现 基于win 图片浏览器

    Atitit图片复制父目录给你设计的实现 基于win 图片浏览器 打开属性,获取其路径...1 Ahk参数传递,使用环境变量即可1 如何ahk异常转换为java异常1 如何获取ahk的输出.1 C:\ ...