Posted By

jatkins on 10/31/16


Tagged

3D graphics rotation resizing Geometry scaling translation projection isometric


Versions (?)

Isometric 3D Projection with translation (broken when camera adjusted) and resizing(working when camera adjusted)


 / Published in: JavaScript
 

Isometric.

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <style type="text/css">
  6. html, body { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; background: #000000; }
  7. polyline, path { stroke: #000000; stroke-width: 1; fill: transparent; }
  8. .sliderControl {
  9. width: 130px;
  10. height: 16px;
  11. border: 1px solid #c3c3c3;
  12. background: #e9e9e9;
  13. position: relative;
  14. display: inline-block;
  15. vertical-align: sub;
  16. margin-left: 3px;
  17. }
  18. .sliderControl>span {
  19. display: block;
  20. width: 14px;
  21. height: 14px;
  22. border: 1px solid #666;
  23. border-radius: 15px;
  24. background: #a1a1a1;
  25. position: absolute;
  26. }
  27. #controls { position: fixed; left: 0; top: 0; }
  28. </style>
  29. <title>Test</title>
  30. </head>
  31. <body>
  32. <svg id="theater" width="100%" height="100%">
  33. <g id="axes"></g>
  34. <path id="cube" style="stroke: red; fill: rgba(255, 0, 0, 0.33)"></path>
  35. <circle id="nope" style="cursor: pointer; stroke: transparent; fill: yellow;"></circle>
  36. </svg>
  37. <script>
  38. var clamp = function (value, minLimit, maxLimit) {
  39. return Math.min(Math.max(value, minLimit), maxLimit);
  40. }, removeAllChildren = function (el) {
  41. var firstChild;
  42. while (firstChild = el.firstChild) {
  43. el.removeChild(firstChild);
  44. }
  45. }, SliderControl = function SliderControl(min, max, callback) {
  46. var sliderDiv = document.createElement('div'),
  47. sliderHandle = document.createElement('span'),
  48. diff = max - min;
  49.  
  50. this.min = min;
  51. this.max = max;
  52. this.diff = diff;
  53. this.element = sliderDiv;
  54.  
  55. sliderDiv.className = 'sliderControl';
  56. sliderDiv.onmousedown = function (mouseDownEvent) {
  57. var sliderDivBBox = sliderDiv.getBoundingClientRect();
  58.  
  59. function dragHandle(mouseMoveEvent) {
  60. var width = sliderDivBBox.width - sliderDiv.clientLeft * 2 - sliderHandle.offsetWidth,
  61. newLeft = clamp(mouseMoveEvent.pageX - sliderHandle.offsetWidth / 2 - sliderDivBBox.left - sliderDiv.clientLeft, 0, width);
  62.  
  63. sliderHandle.style.left = newLeft + 'px';
  64. this.value = min + (newLeft / width) * diff;
  65.  
  66. mouseMoveEvent.preventDefault();
  67. }
  68. function finishDrag(mouseUpEvent) {
  69. if (callback) {
  70. removeEventListener('mousemove', callback, true);
  71. removeEventListener('mouseup', callback, true);
  72. }
  73. removeEventListener('mousemove', dragHandle, true);
  74. removeEventListener('mouseup', finishDrag, true);
  75.  
  76. mouseUpEvent.preventDefault();
  77. mouseUpEvent.stopPropagation();
  78. }
  79.  
  80. if (callback) {
  81. addEventListener('mousemove', callback, true);
  82. addEventListener('mouseup', callback, true);
  83. }
  84. addEventListener('mousemove', dragHandle, true);
  85. addEventListener('mouseup', finishDrag, true);
  86.  
  87. dragHandle(mouseDownEvent); // so the slider changes with a single mousedown
  88. };
  89. sliderDiv.appendChild(sliderHandle);
  90. };
  91.  
  92. Object.defineProperties(SliderControl.prototype, {
  93. value: {
  94. get: function () { return this._value; },
  95. set: function () {
  96. var sliderHandle = this.element.childNodes[0],
  97. width = this.element.offsetWidth - this.element.clientLeft * 2 - sliderHandle.offsetWidth;
  98.  
  99. this._value = arguments[0];
  100. this.element.childNodes[0].style.left = (arguments[0] - this.min) / this.diff * width + 'px';
  101. },
  102. enumerable: true
  103. }
  104. });
  105.  
  106. var $ = function (id) {
  107. return document.getElementById(id);
  108. }, makeLine = function() {
  109. var argObj = arguments[0],
  110. line = $(argObj.id) || document.createElementNS('http://www.w3.org/2000/svg', 'line');
  111.  
  112. if(!line.id) {
  113. line.setAttributeNS(null, 'id', argObj.id);
  114. }
  115.  
  116. line.setAttributeNS(null, 'x1', argObj.fromPoint.x);
  117. line.setAttributeNS(null, 'y1', argObj.fromPoint.y);
  118. line.setAttributeNS(null, 'x2', argObj.toPoint.x);
  119. line.setAttributeNS(null, 'y2', argObj.toPoint.y);
  120. line.setAttributeNS(null, 'style', 'stroke: ' + (argObj.color || '#000000') + '; stroke-width: 1');
  121.  
  122. return line;
  123. }, makeCircle = function() {
  124. var argObj = arguments[0],
  125. circle = $(argObj.id) || document.createElementNS('http://www.w3.org/2000/svg', 'circle');
  126.  
  127. if(argObj.id) {
  128. circle.setAttributeNS(null, 'id', argObj.id);
  129. }
  130. circle.setAttributeNS(null, 'cx', argObj.x);
  131. circle.setAttributeNS(null, 'cy', argObj.y);
  132. circle.setAttributeNS(null, 'r', argObj.radius || 1);
  133. circle.setAttributeNS(null, 'style', 'fill: ' + (argObj.color || '#000000') + '; stroke: transparent');
  134.  
  135. return circle;
  136. };
  137.  
  138. var SQRT_3 = Math.sqrt(3), SQRT_3_OVER_3 = SQRT_3 / 3, SQRT_3_OVER_2 = SQRT_3 / 2, SQRT_4_OVER_3 = (2 * SQRT_3) / 3,
  139. PI_OVER_180 = Math.PI / 180, SVG_NAMESPACE = 'http://www.w3.org/2000/svg',
  140. cx = document.body.offsetWidth / 2, cy = document.body.offsetHeight / 2,
  141. c = {x: 100, y: 100, z: 1}, e = {x: 100, y: 100, z: 1}, SQRT_6_OVER_6 = Math.sqrt(6) / 6;
  142. function project3DPoint(point) {
  143. var u, v, w;
  144. //secondBit = 1 / (w - c.z);
  145. //(c,d,-1/r)
  146. //let -1/r = 100
  147. //-1=100r ... r = -1/100
  148.  
  149. point = rotateX(rotateY(rotateZ(point, cameraZCosTheta, cameraZSinTheta), cameraYCosTheta, cameraYSinTheta), cameraXCosTheta, cameraXSinTheta);
  150.  
  151. u = point.x;
  152. v = point.y;
  153. w = point.z;
  154.  
  155. return {x: Math.SQRT1_2 * (u - w) + cx, y: SQRT_6_OVER_6 * u + 2 * SQRT_6_OVER_6 * v + SQRT_6_OVER_6 * w + cy};
  156. //return {x: u - (SQRT_3_OVER_2 * w) + cx, y: (SQRT_3_OVER_3 * u) - v + (0.5 * w) + cy};
  157. /*return {
  158. x: u - Math.SQRT1_2 * w + cx,
  159. y: v + Math.SQRT1_2 * w + cy
  160. };*/
  161. }
  162.  
  163. function scale3D(point, scaleFactors, origin) {
  164. return {x: (point.x - origin.x) * scaleFactors.x + origin.x, y: (point.y - origin.y) * scaleFactors.y + origin.y, z: (point.z - origin.z) * scaleFactors.z + origin.z};
  165. };
  166. function translate3D(point, translation) {
  167. return {x: point.x + translation.x, y: point.y + translation.y, z: point.z + translation.z};
  168. }
  169. function rotateXYZ(point, cosTheta, sinTheta, origin) {
  170. return rotateZ(rotateY(rotateX(point, cosTheta, sinTheta, origin), cosTheta, sinTheta, origin), cosTheta, sinTheta, origin);
  171. };
  172. function rotateX(point, cosTheta, sinTheta, origin) {
  173. var origin = origin || {x: 0, y: 0, z: 0}, untranslatedPoint = {x: point.x - origin.x, y: point.y - origin.y, z: point.z - origin.z};
  174.  
  175. return {
  176. x: untranslatedPoint.x + origin.x,
  177. y: untranslatedPoint.y * cosTheta + untranslatedPoint.z * sinTheta + origin.y,
  178. z: untranslatedPoint.z * cosTheta - untranslatedPoint.y * sinTheta + origin.z
  179. };
  180. }
  181. function rotateY(point, cosTheta, sinTheta, origin) {
  182. var origin = origin || {x: 0, y: 0, z: 0}, untranslatedPoint = {x: point.x - origin.x, y: point.y - origin.y, z: point.z - origin.z};
  183.  
  184. return {
  185. x: untranslatedPoint.x * cosTheta + untranslatedPoint.z * sinTheta + origin.x,
  186. y: untranslatedPoint.y + origin.y,
  187. z: untranslatedPoint.z * cosTheta - untranslatedPoint.x * sinTheta + origin.z,
  188. };
  189. }
  190. function rotateZ(point, cosTheta, sinTheta, origin) {
  191. var origin = origin || {x: 0, y: 0, z: 0}, untranslatedPoint = {x: point.x - origin.x, y: point.y - origin.y, z: point.z - origin.z};
  192.  
  193. return {
  194. x: untranslatedPoint.x * cosTheta - untranslatedPoint.y * sinTheta + origin.x,
  195. y: untranslatedPoint.x * sinTheta + untranslatedPoint.y * cosTheta + origin.y,
  196. z: untranslatedPoint.z + origin.z,
  197. };
  198. }
  199.  
  200. function showAxesThroughPoint(x, y, z, colorU, colorV, colorW) {
  201. var gEl = document.createElementNS(SVG_NAMESPACE, 'g'),
  202. uAxis = document.createElementNS(SVG_NAMESPACE, 'polyline'),
  203. vAxis = document.createElementNS(SVG_NAMESPACE, 'polyline'),
  204. wAxis = document.createElementNS(SVG_NAMESPACE, 'polyline'), fromPt, toPt;
  205.  
  206. fromPt = project3DPoint({x: -99999, y: y, z: z});
  207. toPt = project3DPoint({x: 99999, y: y, z: z});
  208. uAxis.setAttributeNS(null, 'points', fromPt.x + ',' + fromPt.y + ' ' + toPt.x + ',' + toPt.y);
  209.  
  210. fromPt = project3DPoint({x: x, y: -99999, z: z});
  211. toPt = project3DPoint({x: x, y: 99999, z: z});
  212. vAxis.setAttributeNS(null, 'points', fromPt.x + ',' + fromPt.y + ' ' + toPt.x + ',' + toPt.y);
  213.  
  214. fromPt = project3DPoint({x: x, y: y, z: -99999});
  215. toPt = project3DPoint({x: x, y: y, z: 99999});
  216. wAxis.setAttributeNS(null, 'points', fromPt.x + ',' + fromPt.y + ' ' + toPt.x + ',' + toPt.y);
  217.  
  218. uAxis.setAttributeNS(null, 'style', 'stroke: ' + colorU);
  219. vAxis.setAttributeNS(null, 'style', 'stroke: ' + (colorV || colorU));
  220. wAxis.setAttributeNS(null, 'style', 'stroke: ' + (colorW || colorU));
  221.  
  222. gEl.appendChild(uAxis);
  223. gEl.appendChild(vAxis);
  224. gEl.appendChild(wAxis);
  225. axes.appendChild(gEl);
  226. }
  227.  
  228. function whichOftheseParallelLinesIsBeforeTheOther(line1, line2) {
  229. var line1IsAbove;
  230.  
  231. if (line1.gradient !== line2.gradient) {
  232. return false;
  233. }
  234.  
  235. // remember y increases as we go down, x increases as we go right
  236.  
  237. if (line1.inclined) { // .:. && line2.inclined
  238. line1IsAbove = line1.yIntercept < line2.yIntercept;
  239. } else if (line1.gradient === 0) { // .:. && line2.gradient === 0
  240. // of the form y = ...
  241. line1IsAbove = line1.y < line2.y;
  242. } else if (line1.gradient === Infinity) {
  243. // of the form x = ...
  244. line1IsAbove = line1.x < line2.x;
  245. } else {
  246. return false;
  247. }
  248.  
  249. return line1IsAbove;
  250. }
  251.  
  252. function getIntersectionPointOfTwoLines(line1, line2) {
  253. if (line1.gradient === line2.gradient) { // parallel lines don't intersect
  254. return false;
  255. }
  256.  
  257. if (line1.gradient === 0 && line2.gradient === Infinity) { // line1 is horizontal; line2 is vertical
  258. return {x: line2.x, y: line1.y};
  259. }
  260. else if (line1.gradient === Infinity && line2.gradient === 0) { // line1 is vertical; line2 is horizontal
  261. return {x: line1.x, y: line2.y};
  262. }
  263. else if (line1.inclined && line2.gradient === Infinity) { // line1 has a real, non-zero gradient; line2 is vertical
  264. return {x: line2.x, y: line1.gradient * line2.x + line1.yIntercept};
  265. }
  266. else if (line1.inclined && line2.gradient === 0) { // line1 has a real, non-zero gradient; line2 is horizontal
  267. return {x: (line2.y - line1.yIntercept) / line1.gradient, y: line2.y};
  268. }
  269. else if (line1.gradient === Infinity && line2.inclined) { // line1 has a vertical gradient; line2 has a real, non-zero gradient
  270. return {x: line1.x, y: line2.gradient * line1.x + line2.yIntercept};
  271. }
  272. else if (line1.gradient === 0 && line2.inclined) { // line1 is horizontal; line2 has a real, non-zero gradient
  273. return {x: (line1.y - line2.yIntercept) / line2.gradient, y: line1.y};
  274. }
  275. else if (line1.inclined && line2.inclined) { // both lines have real, non-zero gradients and are of the form y=mx+c
  276. // Equate f(x)s and solve for x, then substitute x into either equation of the form 'y = mx + c'
  277.  
  278. var x = (line2.yIntercept - line1.yIntercept) / (line1.gradient - line2.gradient),
  279. y = line1.gradient * x + line1.yIntercept;
  280.  
  281. return {x: x, y: y};
  282. }
  283. };
  284.  
  285. function StraightLine(point1, point2) { // test this for all cases!
  286. var inclined = false;
  287.  
  288. if (arguments.length === 1) {
  289. if ('gradient' in arguments[0] && 'point' in arguments[0]) { // use point-slope
  290. this._gradient = arguments[0].gradient;
  291. this._yIntercept = arguments[0].point.y - this.gradient * arguments[0].point.x;
  292. inclined = true;
  293. } else if ('x' in arguments[0]) {
  294. this._gradient = Infinity;
  295. this._x = arguments[0].x;
  296. } else if ('y' in arguments[0]) {
  297. this._gradient = 0;
  298. this._y = arguments[0].y;
  299. }
  300. } else if (arguments.length === 2) {
  301. this._gradient = (point2.y - point1.y) / (point2.x - point1.x);
  302. if (Math.abs(this.gradient) === Infinity) {
  303. this._gradient = Infinity;
  304. this._x = point1.x;
  305. } else if (this.gradient === 0) {
  306. this._y = point1.y;
  307. } else {
  308. this._yIntercept = point1.y - this.gradient * point1.x;
  309. inclined = true;
  310. }
  311. }
  312.  
  313. this._inclined = inclined;
  314. }
  315. StraightLine.prototype.getParallelLineFromPoint = function (point) {
  316. if (this.inclined) {
  317. return new StraightLine({gradient: this.gradient, point: point});
  318. } else if ('x' in this) {
  319. return new StraightLine({x: point.x});
  320. } else if ('y' in this) {
  321. return new StraightLine({y: point.y});
  322. }
  323. };
  324. Object.defineProperties(StraightLine.prototype, {
  325. x: { get: function() { return this._x; } },
  326. y: { get: function() { return this._y; } },
  327. gradient: { get: function() { return this._gradient; } },
  328. yIntercept: { get: function() { return this._yIntercept; } },
  329. inclined: { get: function() { return this._inclined; } }
  330. });
  331.  
  332. function updateAxisScales() {
  333. window.xAxisScale = dist(project3DPoint({x: 0, y: 0, z: 0}), project3DPoint({x: 1, y: 0, z: 0}));
  334. window.yAxisScale = dist(project3DPoint({x: 0, y: 0, z: 0}), project3DPoint({x: 0, y: 1, z: 0}));
  335. window.zAxisScale = dist(project3DPoint({x: 0, y: 0, z: 0}), project3DPoint({x: 0, y: 0, z: 1}));
  336. }
  337.  
  338. function dist(pt1, pt2) {
  339. return Math.sqrt(Math.pow(pt1.x - pt2.x, 2) + Math.pow(pt1.y - pt2.y, 2));
  340. }
  341.  
  342. var cameraXCosTheta = 1, cameraXSinTheta = 0,
  343. cameraYCosTheta = 1, cameraYSinTheta = 0,
  344. cameraZCosTheta = 1, cameraZSinTheta = 0,
  345. actionState = 'idle';
  346. onload = function () {
  347. var deg = 0, totalDeg = 0, translateX = 0,
  348. cosTheta, sinTheta, vertexIndex,
  349. vertices = [
  350. {x: 0, y: 0, z: 0},
  351. {x: 100, y: 0, z: 0},
  352. {x: 100, y: 100, z: 0},
  353. {x: 0, y: 100, z: 0},
  354.  
  355. {x: 0, y: 0, z: 100},
  356. {x: 100, y: 0, z: 100},
  357. {x: 100, y: 100, z: 100},
  358. {x: 0, y: 100, z: 100}
  359. ],
  360. vertexCount = vertices.length, verticesRotated,
  361. aboutVertexIndex, sign = 1,
  362. cubeCentroid, aboutPoint = {x: 0, y: 0, z: 0},
  363. sliderCameraXRotate = new SliderControl(0, 360, function () {
  364. cameraXCosTheta = Math.cos(this.value * PI_OVER_180);
  365. cameraXSinTheta = Math.sin(this.value * PI_OVER_180);
  366. updateAxisScales();
  367. redraw();
  368. }),
  369. sliderCameraYRotate = new SliderControl(0, 360, function () {
  370. cameraYCosTheta = Math.cos(this.value * PI_OVER_180);
  371. cameraYSinTheta = Math.sin(this.value * PI_OVER_180);
  372. updateAxisScales();
  373. redraw();
  374. }),
  375. sliderCameraZRotate = new SliderControl(0, 360, function () {
  376. cameraZCosTheta = Math.cos(this.value * PI_OVER_180);
  377. cameraZSinTheta = Math.sin(this.value * PI_OVER_180);
  378. updateAxisScales();
  379. redraw();
  380. }),
  381. controlsDiv = document.createElement('div');
  382.  
  383. updateAxisScales();
  384.  
  385. controlsDiv.appendChild(sliderCameraXRotate.element);
  386. controlsDiv.appendChild(sliderCameraYRotate.element);
  387. controlsDiv.appendChild(sliderCameraZRotate.element);
  388.  
  389. controlsDiv.id = 'controls';
  390. document.body.appendChild(controlsDiv);
  391.  
  392. /*var newLine = document.createElementNS(SVG_NAMESPACE, 'polyline');
  393. newLine.setAttributeNS(null, 'points', cx + ',' + cy + ' ' + (cx * 2 + cx) + ',' + (SQRT_3_OVER_3 * cx * 2 + cy));
  394. newLine.setAttributeNS(null, 'style', 'stroke: orange');
  395. theater.appendChild(newLine);*/
  396.  
  397. //showAxesThroughPoint(aboutPoint.x, aboutPoint.y, aboutPoint.z, 'yellow');
  398.  
  399. var verticesUntranslated, v7, v5, v7Projected, v5Projected;
  400. function dragCube (e) {
  401. var translation, intersectionWithXEqualsStartPosDotX;
  402. if (actionState === 'dragging') {
  403. if (e.ctrlKey) {
  404. translation = {x: 0, y: 0, z: (e.pageX < startPos.x ? 1 : -1) * dist({x: startPos.x, y: -SQRT_3_OVER_3 * (startPos.x - cx) + cy}, {x: e.pageX, y: -SQRT_3_OVER_3 * (e.pageX - cx) + cy}) / axisScale};
  405. } else {
  406. intersectionWithXEqualsStartPosDotX = {x: startPos.x, y: SQRT_3_OVER_3 * (startPos.x - e.pageX) + e.pageY};
  407. translation = {x: (e.pageX < startPos.x ? -1 : 1) * dist(intersectionWithXEqualsStartPosDotX, {x: e.pageX, y: e.pageY}) / axisScale, y: (intersectionWithXEqualsStartPosDotX.y - startPos.y) / axisScale, z: 0};
  408. }
  409.  
  410. for (vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) {
  411. vertices[vertexIndex] = translate3D(verticesUntranslated[vertexIndex], translation);
  412. }
  413. redraw();
  414. }
  415. e.preventDefault();
  416. }
  417.  
  418. function dropCube() {
  419. if (actionState === 'dragging') {
  420. actionState = 'idle';
  421. removeEventListener('mousemove', dragCube);
  422. removeEventListener('mouseup', dragCube);
  423. //window.cubeInterval = setInterval(reanimate, 10);
  424. }
  425. }
  426.  
  427. function resizeCube (e) {
  428. var translation, intersectionWithXEqualsStartPosDotX;
  429. /*if (actionState === 'dragging') {
  430. if (e.ctrlKey) {
  431. translation = {x: 0, y: 0, z: (e.pageX < startPos.x ? 1 : -1) * dist({x: startPos.x, y: -SQRT_3_OVER_3 * (startPos.x - cx) + cy}, {x: e.pageX, y: -SQRT_3_OVER_3 * (e.pageX - cx) + cy}) / axisScale};
  432. } else {
  433. intersectionWithXEqualsStartPosDotX = {x: startPos.x, y: SQRT_3_OVER_3 * (startPos.x - e.pageX) + e.pageY};
  434. translation = {x: (e.pageX < startPos.x ? -1 : 1) * dist(intersectionWithXEqualsStartPosDotX, {x: e.pageX, y: e.pageY}) / axisScale, y: (intersectionWithXEqualsStartPosDotX.y - startPos.y) / axisScale, z: 0};
  435. }
  436.  
  437. for (vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) {
  438. vertices[vertexIndex] = translate3D(verticesUntranslated[vertexIndex], translation);
  439. }
  440. redraw();
  441. }*/
  442. if (actionState === 'resizing') {
  443. var XDiff = e.pageX - startPos.x,
  444. YDiff = e.pageY - startPos.y,
  445. cursor2D = {x: v5Projected.x + XDiff, y: v5Projected.y + YDiff},
  446. leftLine = new StraightLine(v5Projected, project3DPoint(verticesUntranslated[6])),
  447. bottomLine = new StraightLine(v5Projected, project3DPoint(verticesUntranslated[4])),
  448. topLine = bottomLine.getParallelLineFromPoint(cursor2D),
  449. rightLine = leftLine.getParallelLineFromPoint(cursor2D),
  450. bottomLeftVertex = getIntersectionPointOfTwoLines(bottomLine, leftLine),
  451. topLeftVertex = getIntersectionPointOfTwoLines(topLine, leftLine),
  452. topRightVertex = getIntersectionPointOfTwoLines(topLine, rightLine),
  453. bottomRightVertex = getIntersectionPointOfTwoLines(bottomLine, rightLine),
  454. axisAdjustedAbsDeltaX = dist(topLeftVertex, topRightVertex) / xAxisScale,
  455. axisAdjustedAbsDeltaY = dist(topLeftVertex, bottomLeftVertex) / yAxisScale,
  456. plusXPlusY = project3DPoint({x: v5.x + axisAdjustedAbsDeltaX, y: v5.y + axisAdjustedAbsDeltaY, z: v5.z}),
  457. minusXMinusY = project3DPoint({x: v5.x - axisAdjustedAbsDeltaX, y: v5.y - axisAdjustedAbsDeltaY, z: v5.z}),
  458. minusXPlusY = project3DPoint({x: v5.x - axisAdjustedAbsDeltaX, y: v5.y + axisAdjustedAbsDeltaY, z: v5.z}),
  459. plusXMinusY = project3DPoint({x: v5.x + axisAdjustedAbsDeltaX, y: v5.y - axisAdjustedAbsDeltaY, z: v5.z}),
  460. possibles = [
  461. {dist: dist(plusXPlusY, cursor2D), xSign: 1, ySign: 1},
  462. {dist: dist(minusXMinusY, cursor2D), xSign: -1, ySign: -1},
  463. {dist: dist(minusXPlusY, cursor2D), xSign: -1, ySign: 1},
  464. {dist: dist(plusXMinusY, cursor2D), xSign: 1, ySign: -1}
  465. ], result = possibles.sort(resizeCube.sortFunction)[0],
  466. cursor3D = {
  467. x: v5.x + result.xSign * axisAdjustedAbsDeltaX,
  468. y: v5.y + result.ySign * axisAdjustedAbsDeltaY,
  469. z: v5.z
  470. },
  471. cursor3DProjected = project3DPoint(cursor3D),
  472. scaleFactors = {
  473. x: (cursor3D.x - v7.x) / (v5.x - v7.x),
  474. y: (cursor3D.y - v7.y) / (v5.y - v7.y),
  475. z: 1
  476. };
  477.  
  478. resizedPlane = $('resizedPlane') || document.createElementNS(SVG_NAMESPACE, 'path');
  479.  
  480. /*if (!resizedPlane.id) {
  481. resizedPlane.setAttributeNS(null, 'id', 'resizedPlane');
  482. }
  483. resizedPlane.setAttributeNS(null, 'd', 'M' + topLeftVertex.x + ',' + topLeftVertex.y + ' L ' + topRightVertex.x + ',' + topRightVertex.y + ' ' + bottomRightVertex.x + ',' + bottomRightVertex.y + ' ' + bottomLeftVertex.x + ',' + bottomLeftVertex.y + ' Z');
  484. resizedPlane.setAttributeNS(null, 'style', 'stroke: yellow; fill: rgba(255, 255, 0, 0.5)');
  485. theater.appendChild(resizedPlane);
  486.  
  487. theater.appendChild(makeCircle({id: 'bob', x: cursor3DProjected.x, y: cursor3DProjected.y, radius: 10, color: 'orange'}));
  488. theater.appendChild(makeCircle({id: 'bill', x: cursor2D.x, y: cursor2D.y, radius: 5, color: 'cyan'}));
  489. //theater.appendChild(makeCircle({id: 'jim', x: cursor2D.x, y: cursor2D.y, radius: 5, color: 'cyan'}));*/
  490.  
  491. for (vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) {
  492. vertices[vertexIndex] = scale3D(verticesUntranslated[vertexIndex], scaleFactors, v7);
  493. }
  494. redraw();
  495. }
  496. e.preventDefault();
  497. }
  498. resizeCube.sortFunction = function (a, b) {
  499. return a.dist < b.dist ? -1 : 1;
  500. };
  501.  
  502. function stopResizingCube() {
  503. if (actionState === 'resizing') {
  504. actionState = 'idle';
  505. removeEventListener('mousemove', resizeCube);
  506. removeEventListener('mouseup', stopResizingCube);
  507. }
  508. }
  509.  
  510. var dragging, startPos;
  511. cube.onmousedown = function (e) {
  512. //clearInterval(cubeInterval);
  513. startPos = {x: e.pageX, y: e.pageY};
  514. verticesUntranslated = [];
  515. var vertex;
  516. for (vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) {
  517. vertex = vertices[vertexIndex];
  518. verticesUntranslated[vertexIndex] = {x: vertex.x, y: vertex.y, z: vertex.z};
  519. }
  520. //verticesUntranslated[0] = {x: aboutPoint.x, y: aboutPoint.y, z: aboutPoint.z};
  521. addEventListener('mousemove', dragCube);
  522. addEventListener('mouseup', dropCube);
  523. actionState = 'dragging';
  524. e.preventDefault();
  525. };
  526.  
  527. nope.onmousedown = function (e) {
  528. startPos = {x: e.pageX, y: e.pageY};
  529. verticesUntranslated = [];
  530. var vertex;
  531. for (vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) {
  532. vertex = vertices[vertexIndex];
  533. verticesUntranslated[vertexIndex] = {x: vertex.x, y: vertex.y, z: vertex.z};
  534. }
  535. v7 = verticesUntranslated[7];
  536. v5 = verticesUntranslated[5];
  537. v7Projected = project3DPoint(v7);
  538. v5Projected = project3DPoint(v5);
  539. addEventListener('mousemove', resizeCube);
  540. addEventListener('mouseup', stopResizingCube);
  541. actionState = 'resizing';
  542. e.preventDefault();
  543. };
  544.  
  545. function reanimate() {
  546. /*if (deg > 360) {
  547. deg = 0;
  548. }
  549. if (deg % 90 === 0) {
  550. sign *= -1;
  551. }
  552. translateX+=sign*0.1;*/
  553. redraw();
  554. //deg++;
  555. //totalDeg++;
  556. }
  557.  
  558. for (vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) {
  559. vertices[vertexIndex] = translate3D(vertices[vertexIndex], {x: 0, y: -200, z: -200});
  560. }
  561.  
  562. function redraw() {
  563. removeAllChildren(axes);
  564. showAxesThroughPoint(0, 0, 0, 'red', 'green', 'blue');
  565.  
  566. var nopePos2D = project3DPoint(vertices[5]);
  567. nope.setAttributeNS(null, 'cx', nopePos2D.x);
  568. nope.setAttributeNS(null, 'cy', nopePos2D.y);
  569. nope.setAttributeNS(null, 'r', 5);
  570.  
  571. /*for (var x = 0; x < cx; x += 50) {
  572. showAxesThroughPoint(x, 0, 0, 'transparent', 'pink', 'pink');
  573. }
  574.  
  575. for (var y = 0; y < cy; y += 50) {
  576. showAxesThroughPoint(0, y, 0, 'transparent', 'pink', 'pink');
  577. }*/
  578.  
  579. /*for (var z = 0; z <= cx;z +=cx / 11) {
  580. showAxesThroughPoint(0, 0, -z, 'transparent', 'pink', 'pink');
  581. }*/
  582.  
  583. cosTheta = Math.cos(deg * PI_OVER_180);
  584. sinTheta = Math.sin(deg * PI_OVER_180);
  585.  
  586. verticesRotated = [];
  587. /*var point;
  588. for (vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) {//{x: -50, y: -50, z: 50}
  589. //verticesRotated[vertexIndex] = project3DPoint(rotateX(translate3D(vertices[vertexIndex], {x: 0, y: 0, z: 0}), cosTheta, sinTheta));
  590. //
  591. //point = translate3D(vertices[vertexIndex], {x: 0, y: -100, z: -100});
  592. //verticesRotated[vertexIndex] = vertices[vertexIndex];
  593. //verticesRotated[vertexIndex] = scale3D(vertices[vertexIndex], {x: 0.1 * translateX, y: 0.1 * translateX, z: 0.1 * translateX}, vertices[0]);
  594. //verticesRotated[vertexIndex] = project3DPoint(rotateXYZ(scale3D(vertices[vertexIndex], {x: 1, y: 1, z: 1}, {x: 0, y: 0, z: 0}), cosTheta, sinTheta, {x: 0, y: 0, z: 0}));
  595. //verticesRotated[vertexIndex] = project3DPoint(rotateX(translate3D(vertices[vertexIndex], {x: 10, y: 10, z: 10}), cosTheta, sinTheta, {x: 0, y: 0, z: 0}));
  596. }*/
  597.  
  598.  
  599. //cubeCentroid = {x: (vertices[0].x + vertices[1].x) / 2, y: (vertices[0].y + vertices[3].y) / 2, z: (vertices[0].z + vertices[4].z) / 2};
  600. for (vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) {
  601. //point = rotateX(verticesRotated[vertexIndex], cosTheta, sinTheta, vertices[0]);
  602. verticesRotated[vertexIndex] = project3DPoint(vertices[vertexIndex]);
  603. }
  604.  
  605. cube.setAttributeNS(null, 'd', 'M' + verticesRotated[0].x + ',' + verticesRotated[0].y + ' L ' + verticesRotated[1].x + ',' + verticesRotated[1].y + ' ' + verticesRotated[2].x + ',' + verticesRotated[2].y + ' ' + verticesRotated[3].x + ',' + verticesRotated[3].y + 'Z M' + verticesRotated[4].x + ',' + verticesRotated[4].y + ' L ' + verticesRotated[5].x + ',' + verticesRotated[5].y + ' ' + verticesRotated[6].x + ',' + verticesRotated[6].y + ' ' + verticesRotated[7].x + ',' + verticesRotated[7].y + ' Z M ' + verticesRotated[0].x + ',' + verticesRotated[0].y + ' L ' + verticesRotated[4].x + ',' + verticesRotated[4].y + ' M' + verticesRotated[1].x + ',' + verticesRotated[1].y + ' L ' + verticesRotated[5].x + ',' + verticesRotated[5].y + ' M ' + verticesRotated[2].x + ',' +verticesRotated[2].y + ' L ' + verticesRotated[6].x + ',' + verticesRotated[6].y + ' M' + verticesRotated[3].x + ',' + verticesRotated[3].y + ' L ' + verticesRotated[7].x + ',' + verticesRotated[7].y);
  606.  
  607. /*if (totalDeg <= 360){
  608. newCube = document.createElementNS(SVG_NAMESPACE, 'path');
  609. newCube.setAttributeNS(null, 'style', 'stroke: red');
  610. theater.appendChild(newCube);
  611. newCube.setAttributeNS(null, 'd', 'M' + verticesRotated[0].x + ',' + verticesRotated[0].y + ' L ' + verticesRotated[1].x + ',' + verticesRotated[1].y + ' ' + verticesRotated[2].x + ',' + verticesRotated[2].y + ' ' + verticesRotated[3].x + ',' + verticesRotated[3].y + 'Z M' + verticesRotated[4].x + ',' + verticesRotated[4].y + ' L ' + verticesRotated[5].x + ',' + verticesRotated[5].y + ' ' + verticesRotated[6].x + ',' + verticesRotated[6].y + ' ' + verticesRotated[7].x + ',' + verticesRotated[7].y + ' Z M ' + verticesRotated[0].x + ',' + verticesRotated[0].y + ' L ' + verticesRotated[4].x + ',' + verticesRotated[4].y + ' M' + verticesRotated[1].x + ',' + verticesRotated[1].y + ' L ' + verticesRotated[5].x + ',' + verticesRotated[5].y + ' M ' + verticesRotated[2].x + ',' +verticesRotated[2].y + ' L ' + verticesRotated[6].x + ',' + verticesRotated[6].y + ' M' + verticesRotated[3].x + ',' + verticesRotated[3].y + ' L ' + verticesRotated[7].x + ',' + verticesRotated[7].y);
  612. }*/
  613. }
  614.  
  615. //window.cubeInterval = setInterval(reanimate, 10);
  616. setTimeout(redraw, 10);
  617. };
  618. </script>
  619. </body>
  620. </html>

Report this snippet  

You need to login to post a comment.