canvas实现3D魔方
摘要:使用canvas实现可交互的3D魔方
一、简单分析
魔方物理性质:
1.中心块(6个):中心块与中心轴连接在一起,但可以顺着轴的方向自由的转动。
2.棱块(12个):棱块的表面是两个正方形,结构类似一个长方体从立方体的一个边凸出来。
3.角块(8个):角块的表面是三个正方形,结构类似一个小立方体从立方体的一个边凸出来,这样的结构可以让角块嵌在三个棱块之间。
4.可见方块(26个):魔方对于我们可见的方块有26块。
5.魔方六个面,每个面九个方块,转动时每个面绕着自己面的中心块旋转。
6.在观察魔方时,我们将整个魔方绕着三维空间中的某个点旋转
7.在人的视野范围内,魔方可见的部分只有三个面,19个方块。
二、实现方式
1)完成方块的旋转
通过简略的类图,先了解一下实现的思路。在一个三维空间中,最基础的就是点(Vertex),点组成了面(Face),面组成了空间立方体(Cube)。魔方(MagicCube)由26个Cube组成,同时将26个Cube单组不重复的分为6组(MagicFace)。当旋转观察魔方时,26个Cube绕着魔方的中心旋转。当转动魔方的某一面时,MagicFace上所有的Cube围绕以原点为起点,面的中心为终点的矢量旋转。只需要掌握点在空间中的旋转,即可完成整个魔方的旋转。三维空间中点的旋转主要用到了数学上的旋转公式。关于如何将一个三维空间的立方体投影到平面并实现旋转请看我的上一篇随笔。
2)完成方块的上色
第一步只是完成了一个透明魔方旋转。我们需要给魔方上色。初始化时为每个cube的face上色,我们不可见的面设置为白色。就像我们在现实中绘画一样,在canvas上绘制图像时后渲染的图像会把之前的覆盖掉,因此魔方的渲染顺序我们需要从后往前渲染。
我们通过面的中心距离原点的Y值(本例以Y轴垂直与屏幕作为参考轴),来确定渲染顺序。单个方块的渲染如上图,6个面(*代表看不见的面),渲染顺序为1*,2*,3*,4,5,6,后渲染的面将前面渲染的面盖住。
整个魔方的渲染,举例标了数字的三个方块,也是通过方块中点距离原点的Y值来确定渲染顺序。渲染顺序先是方块1,然后方块2把1的上半部分盖住,然后方块3把方块二的上半部分盖住。
3)完成鼠标的点击事件
交互是本例中比较难的一个点,canvas 没有提供为其内部元素添加事件监听的方法,因此如果要使 canvas 内的元素能够响应事件,需要自己动手实现。通过获得鼠标在 canvas 上的坐标,计算当前坐标在哪些元素内部,然后对元素进行相应的操作。配合自定义事件,我们就可以实现为 canvas 内的元素添加事件监听的效果。
在上图中,可旋转的面投影到二维平面的区域共有6个,图中只标识了三个。如何确定投影的区域呢?想了很多方法,最终采用了建立参考点的方法。
1.获取到3个可视面MagicFace(F1F2F3)---6个面中中心Y值最大的3个
2.获取到3个可视面无穷远的参考点(V1V2V3)--6个参考点中Y值最大的3个
4.我们循环6个面,例如循环到图中的F2面,我们过滤离F2中心最近的参考点(过滤掉与F2中心空间距离最小的点),剩下V1V3
5.获取到F2面中离V1最最近的三个方块(即上方红色区域的三个方块) -- 离参考点的空间距离
6.获取三个方块中里F2这个面中点最远的4个点(即上方红色区域的4个顶点)
通过3层循环,即可获取到所有可视面的投影。当我们鼠标点击并滑动一段距离时(图中黑点),我们就可以判断两个点所在的投影的位置是哪一个面的,获取到面之后就可以旋转那个面。
PS:我们通过建立参考点,6个无穷远的点(分别在X,Y,Z轴的正负方向上,魔方整体旋转时参考点也会旋转)。使用他与各个元素中点的距离用于判断一些特殊位置的点和面的方法。滑动部分的投影的8个点就是用参考点辅助求出的。
判断点是否在面中使用的是pnpoly算法 https://wrf.ecse.rpi.edu//Research/Short_Notes/pnpoly.html
三、最终效果
PS:面积投影越小事件效果就不灵敏了,有待优化
canvas实现3D魔方的更多相关文章
- css3之3D魔方动画(小白版)
在这里分享一下3D魔方动画,html5+CSS3即可完成~无图无真相,先上效果图 第一步非常简单,就是先将魔方的结构画出来.大家都玩过魔方,知道魔方是一个有六个面的正方体.这里我们先写一个大的di ...
- Seen.js – 使用 SVG 或者 Canvas 渲染 3D 场景
Seen.js 渲染3D场景为 SVG 或者 HTML5 画布.Seen.js 包含对于 SVG 和 HTML5 Canvas 元素的图形功能的最简单的抽象.所有这个库的其它组件都是不用关心将要渲染的 ...
- DirectX11--实现一个3D魔方(3)
前言 (2019/1/9 09:23)上一章我们主要讲述了魔方的旋转,这个旋转真是有毒啊,搞完这个部分搭键鼠操作不到半天应该就可以搭完了吧... (2019/1/9 21:25)啊,真香 有人发这张图 ...
- DirectX11--实现一个3D魔方(2)
前言 上一章我们主要讲述了魔方的构造和初始化.纹理的准备工作.目前我还没有打算讲Direct3D 11关于底层绘图的实现,因此接下来这一章的重点是魔方的旋转.因为我们要的是能玩的魔方游戏,而不是一个观 ...
- DirectX11--实现一个3D魔方(1)
前言 可以说,魔方跟我的人生也有一定的联系. 在高中的学校接触到了魔方社,那时候的我虽然也能够还原魔方,可看到大神们总是可以非常快地还原,为此我也走上了学习高级公式CFOP的坑.当初学习的网站是在魔方 ...
- 如何用CSS3画出懂你的3D魔方?
作者:首席填坑官∙苏南公众号:honeyBadger8,群:912594095,本文原创,著作权归作者所有,转载请注明原链接及出处. 前言 最近在写<每周动画点点系列>文章,上一期分享了& ...
- 用Canvas玩3D:点-线-面
声明:本文为原创文章,如需转载,请注明来源WAxes,谢谢! 玩Canvas玩了有两三个礼拜了,平面的东西玩来玩去也就那样,所以就开始折腾3D了. 因为Canvas画布终究还是平面的,所以要有3D就得 ...
- 基于 HTML5 Canvas 的 3D 模型贴图问题
之前注意到的一个例子,但是一直没有沉下心来看这个例子到底有什么优点,总觉得就是一个 list 列表,也不知道右边的 3d 场景放两个节点是要干嘛,今天突然想起来就仔细地看了一下这个例子的代码,实际操作 ...
- 基于 HTML5 Canvas 的 3D 模型列表贴图
少量图片对于我们赋值是没有什么难度,但是如果图片的量大的话,我们肯定希望能很直接地显示在界面上供我们使用,再就是排放的位置等等,这些都需要比较直观的操作,在实际应用中会让我们省很多力以及时间.下面这个 ...
随机推荐
- Leetcode_252_Implement Stack using Queues
本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/48598773 Implement the followin ...
- ubuntu安装qq教程
安装策略是wine+wine QQ TM2013,wine QQ TM2013是一款专门为wine进行优化的版本 我的ubuntu系统是14.04版本,64位 1. sudo apt-get inst ...
- javascript、ruby和C性能一瞥(1)
测试一下本地js.浏览器中的js以及ruby对于类似算法的性能.结果有些意外:浏览器js最快,本地其次当相差很小:ruby最慢而且不是一个数量级的: 因为写的匆忙,可能有重大问题没能看出来,请各位高人 ...
- 如何在linux上构建objective-c程序
swfit目前还是os x独占,以后会不会扩展到其他系统还未可知,但objective-c并不只存在于os x,在linux下gcc和clang都支持obj-c哦,下面简单把如何在ubuntu上构建o ...
- 管理xcode插件
1.打开终端 2.输入 open ~/Library/Application\ Support/Developer/Shared/Xcode/Plug-ins 3.出现 4.想删除那个就随意吧 ...
- JavaScript 对象分类
参考自W3School:JavaScript对象主要有三类. 一:JavaScript核心对象是ECMAScript标准定义好的一些对象与函数,在JavaScript语言中可以直接使用.主要常用有如下 ...
- 推荐免费小巧图片大小处理工具--Image Resizer for Windows
开源免费小巧,项目地址:http://imageresizer.codeplex.com/
- Aptana版本回滚的方法
最近Aptana对Django1.7的编译支持有点问题,开发环境必须使用Django1.6版本,今天看了一眼它的官网,版本已经到3.6.1,我的版本还是3.4.2,就checkupdate升级到3.6 ...
- LR性能测试结果样例分析
http://www.cnblogs.com/hyzhou/archive/2011/11/16/2251316.html 测试结果分析 LoadRunner性能测试结果分析是个复杂的过程,通常可 ...
- FPGA图像处理之行缓存(linebuffer)的设计一
FPGA图像处理之行缓存(linebuffer)的设计一 作者:OpenS_Lee 1 背景知识 在FPGA数字图像处理中,行缓存的使用非常频繁,例如我们需要图像矩阵操作的时候就需要进行缓存,例如图像 ...