cameracontroller.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /*
  2. * Copyright (c) 2009 The Chromium Authors. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are
  6. * met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above
  11. * copyright notice, this list of conditions and the following disclaimer
  12. * in the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Google Inc. nor the names of its
  15. * contributors may be used to endorse or promote products derived from
  16. * this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. // A simple camera controller which uses an HTML element as the event
  31. // source for constructing a view matrix. Assign an "onchange"
  32. // function to the controller as follows to receive the updated X and
  33. // Y angles for the camera:
  34. //
  35. // var controller = new CameraController(canvas);
  36. // controller.onchange = function(xRot, yRot) { ... };
  37. //
  38. // The view matrix is computed elsewhere.
  39. //
  40. // opt_canvas (an HTMLCanvasElement) and opt_context (a
  41. // WebGLRenderingContext) can be passed in to make the hit detection
  42. // more precise -- only opaque pixels will be considered as the start
  43. // of a drag action.
  44. function CameraController(element, opt_canvas, opt_context) {
  45. var controller = this;
  46. this.onchange = null;
  47. this.xRot = 0;
  48. this.yRot = 0;
  49. this.scaleFactor = 3.0;
  50. this.dragging = false;
  51. this.curX = 0;
  52. this.curY = 0;
  53. if (opt_canvas)
  54. this.canvas_ = opt_canvas;
  55. if (opt_context)
  56. this.context_ = opt_context;
  57. // Assign a mouse down handler to the HTML element.
  58. element.onmousedown = function(ev) {
  59. // $(element).css("cursor", "url(images/blank.png), default");
  60. $(element).css("cursor", "none");
  61. controller.curX = ev.clientX;
  62. controller.curY = ev.clientY;
  63. var dragging = false;
  64. if (controller.canvas_ && controller.context_) {
  65. var rect = controller.canvas_.getBoundingClientRect();
  66. // Transform the event's x and y coordinates into the coordinate
  67. // space of the canvas
  68. var canvasRelativeX = ev.pageX - rect.left;
  69. var canvasRelativeY = ev.pageY - rect.top;
  70. var canvasWidth = controller.canvas_.width;
  71. var canvasHeight = controller.canvas_.height;
  72. // Read back a small portion of the frame buffer around this point
  73. if (canvasRelativeX > 0 && canvasRelativeX < canvasWidth &&
  74. canvasRelativeY > 0 && canvasRelativeY < canvasHeight) {
  75. var pixels = new Uint8Array(1);
  76. controller.context_.readPixels(canvasRelativeX,
  77. canvasHeight - canvasRelativeY,
  78. 1,
  79. 1,
  80. controller.context_.RGBA,
  81. controller.context_.UNSIGNED_BYTE,
  82. pixels);
  83. // See whether this pixel has an alpha value of >= about 10%
  84. if (pixels[3] > (255.0 / 10.0)) {
  85. dragging = true;
  86. }
  87. }
  88. } else {
  89. dragging = true;
  90. }
  91. controller.dragging = dragging;
  92. };
  93. // Assign a mouse up handler to the HTML element.
  94. element.onmouseup = function(ev) {
  95. $(element).css("cursor", "default");
  96. controller.dragging = false;
  97. };
  98. // Assign a mouse move handler to the HTML element.
  99. element.onmousemove = function(ev) {
  100. if (controller.dragging) {
  101. // Determine how far we have moved since the last mouse move
  102. // event.
  103. var curX = ev.clientX;
  104. var curY = ev.clientY;
  105. var deltaX = (controller.curX - curX) / controller.scaleFactor;
  106. var deltaY = (controller.curY - curY) / controller.scaleFactor;
  107. controller.curX = curX;
  108. controller.curY = curY;
  109. // Update the X and Y rotation angles based on the mouse motion.
  110. controller.yRot = (controller.yRot + deltaX) % 360;
  111. controller.xRot = (controller.xRot + deltaY);
  112. // Clamp the X rotation to prevent the camera from going upside
  113. // down.
  114. if (controller.xRot < -90) {
  115. controller.xRot = -90;
  116. } else if (controller.xRot > 90) {
  117. controller.xRot = 90;
  118. }
  119. // Send the onchange event to any listener.
  120. if (controller.onchange != null) {
  121. controller.onchange(controller.xRot, controller.yRot);
  122. }
  123. }
  124. };
  125. }