如何检测 3d 立方体的哪一侧被点击? [英] how to detect which side of 3d cube was clicked?
问题描述
我正在用画布编写一个小型 3d引擎"……并不是真正的引擎,而是更多基于 Eric Pascarello 的演示(点击数字7"几次可以看到它在旋转)
一切都很顺利,我什至为每个平面(侧面")添加了按平均 z 值排序 - 这样我就可以使用由多个立方体组成的主体,以便最后绘制接近相机的形状.>
现在,当鼠标点击画布时,我想检测哪一侧被点击.类似于这个
提示:
- 每条边由 4 个 (x,y,z) 角定义
- 使用我认为常规的透视投影"将每个角绘制到画布上
这是我的代码 - 很酷:使用鼠标旋转
//edit: 请参阅下面我的回答中的代码
完美!我想我需要问这个问题,这样我才能回答自己:-)
该解决方案基于我发现的一些惊人的片段,用于检测多边形中点的存在.这是 2d 函数,但是嘿......我的画布也是 - 愚蠢的我.
这里是完整的跨浏览器:
<头><meta http-equiv="content-type" content="text/html; charset=UTF-8"/><title>קובייה</title><link rel="快捷方式图标" href="Rubiks.png"/><script>var isIE = false</script><!--[如果 IE]><script language="javascript" type="text/javascript" src="../js_canvas/excanvas_r69.js"></script><script>isIE = true</script><![endif]--><风格>身体 {填充:2px;字体系列:arial;}帆布 {边框:1px纯黑色;背景:白色;光标:默认;}.移动 {光标:移动;}div,td,输入{字体大小:15px;}.header {字体大小:22px;字体粗细:粗体;底边距:10px;}.subHeader {字体大小:16px;}.tblHeader {背景:#003f00;白颜色;字体粗细:粗体;字体大小:24px;边框:0px;}.信息{背景:浅黄色;边框:1px纯黑色;字体大小:15px;宽度:350px;}.opac {/*不透明度:0.85;过滤器:阿尔法(不透明度= 85);-ms-filter: "alpha(opacity=85)";-khtml-不透明度:.85;-moz-不透明度:0.85;*/}.btn {颜色:黑色;显示:内联块;宽度:100px;边框:2px 开始#ddd;文字装饰:无;填充:2px;背景:#ddd;文字对齐:居中;字体系列:arial;字体大小:12px;字体粗细:粗体;}.btn_hover {颜色:蓝色;}.btn_down {边框:2px 插入 #ddd;}</风格>头部><script type="text/javascript">//Eric Pascarello 共享的立方体代码无边长 = 50;无功宽度= 600;变量高度 = 450;var center = new Point(width/2, height/2)var 透视 = sideLength * 16;var xzRotation = -Math.PI/2;var yzRotation = 0;var xyRotation = 0;var isColored = true;var 立方体、calcCube、lgthvar 画布,ctx,动画var mouse = new Point(0,0);var absMouse = new Point(0,0)var clickedMouse = new Point(0,0)var posCanvasvar clickRGB = [248, 128, 23]//橙色 = #F88017var clickRGB = [255,192,203]//粉红色var arrPolygons = []var arrSortedIndex/** 立方体的东西 **/函数旋转(bForce){如果 (!bForce && (this.last_xyRotation == xyRotation &&this.last_xzRotation == xzRotation &&this.last_yzRotation == yzRotation||!dragCube) ) {返回}var drawStyle = getRadioValue("drawStyle")//color, bw, or trans如果(drawStyle==trans"){$("chkWire").disabled = true$("chkWire").checked = true} 别的 {$("chkWire").disabled = false}//将立方体旋转为 calcCube.还设置颜色.for (var i=0; i calcCube.sides[j].avgZ){var temp = calcCube.sides[i].avgZcalcCube.sides[i].avgZ = calcCube.sides[j].avgZcalcCube.sides[j].avgZ = 温度var temp = arrSortedIndex[i]arrSortedIndex[i] = arrSortedIndex[j]arrSortedIndex[j] = 温度}}}//绘制所有边ctx.clearRect(0,0, width, height);for (var i=0; i=0; i--) {if (isPointInPoly(calcCube.sides[arrSortedIndex[i]].polygon, inside)) {dragCube.side = arrSortedIndex[i]休息;}}/*ctx.beginPath()ctx.arc(inside.x, inside.y, 1, 0, Math.PI*2, false);ctx.stroke();*/}函数 mouseUp(e) {如果(dragCube && !dragCube.moved){var index = dragCube.side如果(索引> = 0){cube.sides[index].clickState = !cube.sides[index].clickState旋转(真)}}dragCube = nullremoveClass ($("cv"), "move")}/** 纽扣 **/函数 addClass(objElement, strClass) {如果(!objElement)返回;如果(objElement.className){removeClass(objElement, strClass);objElement.className += ' '+strClass;} 别的 {objElement.className = strClass;}}函数 removeClass(objElement, strClass) {如果(!objElement)返回;如果(objElement.className){var arrList = objElement.className.split(' ');var strClassUpper = strClass.toUpperCase();for (var i = 0; i < arrList.length; i++) {如果 (arrList[i].toUpperCase() == strClassUpper) {arrList.splice(i, 1);一世 - ;}}objElement.className = arrList.join(' ');}}/** 杂项和实用程序 **/函数 $(id) {返回 document.getElementById(id);}函数 findPos(obj) {//http://www.quirksmode.org/js/findpos.htmlvar curleft = curtop = 0;if (obj && obj.offsetParent) {做 {curleft += obj.offsetLeft;curtop += obj.offsetTop;} while (obj = obj.offsetParent);}返回新点(curleft,curtop);}函数 dec2hex(d, 填充) {var hex = Number(d).toString(16);填充 = 填充 ||2while (hex.length < padding) {十六进制 = "0" + 十六进制;}返回十六进制;}函数trimVal(val,min,max){返回 Math.max( Math.min(val, max), min)}函数 getRadioValue(名称){for (i=0;i<body onload="init()"onmousemove="mouseMove(事件)"onmouseup="mouseUp(事件)"><div dir=rtl class="header">קובייה</div><div dir=rtl class="subHeader">גיררו את הקוביה עם העכבר על מנת לסובב אותה</div</div<div dir=rtl class="subHeader">ליחצו על פאה על מנת לסמן אותה.</div><BR><!-- 主画布--><中心><div id="wrapper" dir="ltr"><canvas onmousedown="mouseDown(event)" id="cv" width="100" height="100"></canvas>
</中心><!-- 控制面板--><div dir="rtl" class="opac" style="position:absolute; background:lightyellow; border:1px纯黑; right:10px; top:100px; font-size:12px; padding:4px; width:120px"><div 目录=rtl><表格名称=frm><input name="drawStyle" type="radio" value="color" onclick="rotate(true)" onchange="rotate(true)" 选中>צבעוני<br><input name="drawStyle" type="radio" value="bw" onclick="rotate(true)" onchange="rotate(true)">שחור לבן<br><input name="drawStyle" type="radio" value="trans" onclick="rotate(true)" onchange="rotate(true)">שקוף<br><input id="chkWire" type="checkbox" onclick="rotate(true)" onchange="rotate(true)">מסגרת<BR></表单>
<div id="调试"></div>