/src/org/mt4j/input/inputProcessors/componentProcessors/arcballProcessor/ArcballProcessor.java

http://mt4j.googlecode.com/ · Java · 663 lines · 271 code · 130 blank · 262 comment · 39 complexity · f9d0b7b00afafc472a24de0cfeee6030 MD5 · raw file

  1. /***********************************************************************
  2. * mt4j Copyright (c) 2008 - 2009 Christopher Ruff, Fraunhofer-Gesellschaft All rights reserved.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. ***********************************************************************/
  18. package org.mt4j.input.inputProcessors.componentProcessors.arcballProcessor;
  19. import java.util.List;
  20. import javax.media.opengl.GL;
  21. import org.mt4j.components.MTComponent;
  22. import org.mt4j.components.bounds.BoundingSphere;
  23. import org.mt4j.components.visibleComponents.shapes.AbstractShape;
  24. import org.mt4j.input.inputData.AbstractCursorInputEvt;
  25. import org.mt4j.input.inputData.InputCursor;
  26. import org.mt4j.input.inputProcessors.IInputProcessor;
  27. import org.mt4j.input.inputProcessors.componentProcessors.AbstractComponentProcessor;
  28. import org.mt4j.input.inputProcessors.componentProcessors.AbstractCursorProcessor;
  29. import org.mt4j.util.math.Matrix;
  30. import org.mt4j.util.math.Quaternion;
  31. import org.mt4j.util.math.Ray;
  32. import org.mt4j.util.math.Tools3D;
  33. import org.mt4j.util.math.ToolsMath;
  34. import org.mt4j.util.math.Vector3D;
  35. import processing.core.PApplet;
  36. import processing.opengl.PGraphicsOpenGL;
  37. /**
  38. * The Class ArcballProcessor. Fires ArcBallGestureEvent events.
  39. *
  40. * @author Christopher Ruff
  41. */
  42. public class ArcballProcessor extends AbstractCursorProcessor {
  43. private PApplet applet;
  44. private Matrix identityDummy;
  45. private BoundingSphere bSphere;
  46. private MTComponent shape;
  47. private float sizeScaled = 1;
  48. private IArcball ac;
  49. /**
  50. * Instantiates a new arcball processor.
  51. *
  52. * @param applet the applet
  53. * @param shape the shape
  54. */
  55. public ArcballProcessor(PApplet applet, AbstractShape shape){
  56. this(applet, shape, new BoundingSphere(shape));
  57. }
  58. public ArcballProcessor(PApplet applet, MTComponent component, BoundingSphere bSphere){
  59. this.applet = applet;
  60. if (identityDummy == null)
  61. identityDummy = new Matrix();
  62. this.bSphere = bSphere;
  63. this.bSphere.setRadius(bSphere.getRadius() * sizeScaled);
  64. this.shape = component;
  65. // ((BoundingSphere)shape.getBoundingShape()).setRadius(((BoundingSphere)shape.getBoundingShape()).getRadius()*2);
  66. this.ac = null;
  67. this.setLockPriority(1);
  68. logger.debug("Bounding sphere center: " + bSphere.getCenter() + " Radius: " + bSphere.getRadius());
  69. }
  70. @Override
  71. public void cursorStarted(InputCursor m, AbstractCursorInputEvt positionEvent) {
  72. InputCursor[] theLockedCursors = getLockedCursorsArray();
  73. //if gesture isnt started and no other cursor on comp is locked by higher priority gesture -> start gesture
  74. if (theLockedCursors.length == 0 && this.canLock(getCurrentComponentCursorsArray())){
  75. if (this.canLock(m)){//See if we can obtain a lock on this cursor (depends on the priority)
  76. this.getLock(m);
  77. ac = new MyArcBall(m);
  78. logger.debug(this.getName() + " successfully locked cursor (id:" + m.getId() + ")");
  79. this.fireGestureEvent(new ArcBallGestureEvent(this, ArcBallGestureEvent.GESTURE_STARTED, positionEvent.getCurrentTarget(), identityDummy));
  80. }
  81. }
  82. }
  83. @Override
  84. public void cursorUpdated(InputCursor m, AbstractCursorInputEvt positionEvent) {
  85. if (getLockedCursors().contains(m)){
  86. Matrix mat = ac.getNewRotation(m);
  87. this.fireGestureEvent(new ArcBallGestureEvent(this, ArcBallGestureEvent.GESTURE_UPDATED, positionEvent.getCurrentTarget(), mat));
  88. }
  89. }
  90. @Override
  91. public void cursorEnded(InputCursor c, AbstractCursorInputEvt positionEvent) {
  92. logger.debug(this.getName() + " INPUT_ENDED RECIEVED - cursor: " + c.getId());
  93. if (getLockedCursors().contains(c)){ //cursors was a actual gesture cursors
  94. //Check if we can resume the gesture with another cursor
  95. InputCursor[] availableCursors = getFreeComponentCursorsArray();
  96. if (availableCursors.length > 0 && this.canLock(getCurrentComponentCursorsArray())){
  97. InputCursor otherCursor = availableCursors[0];
  98. ac = new MyArcBall(otherCursor);
  99. this.getLock(otherCursor);
  100. }else{
  101. this.fireGestureEvent(new ArcBallGestureEvent(this, ArcBallGestureEvent.GESTURE_ENDED, positionEvent.getCurrentTarget(), identityDummy));
  102. }
  103. }
  104. }
  105. @Override
  106. public void cursorLocked(InputCursor c, IInputProcessor lockingAnalyzer) {
  107. if (lockingAnalyzer instanceof AbstractComponentProcessor){
  108. logger.debug(this.getName() + " Recieved cursor LOCKED by (" + ((AbstractComponentProcessor)lockingAnalyzer).getName() + ") - cursor ID: " + c.getId());
  109. }else{
  110. logger.debug(this.getName() + " Recieved cursor LOCKED by higher priority signal - cursor ID: " + c.getId());
  111. }
  112. this.fireGestureEvent(new ArcBallGestureEvent(this, ArcBallGestureEvent.GESTURE_CANCELED, c.getCurrentTarget(), identityDummy));
  113. logger.debug(this.getName() + " cursor:" + c.getId() + " cursor LOCKED. Was an active cursor in this gesture!");
  114. }
  115. @Override
  116. public void cursorUnlocked(InputCursor c) {
  117. logger.debug(this.getName() + " Recieved UNLOCKED signal for cursor ID: " + c.getId());
  118. List<InputCursor> locked = getLockedCursors();
  119. if (locked.size() >= 1)
  120. return;
  121. if (getFreeComponentCursors().size() > 0 && this.canLock(getCurrentComponentCursorsArray())){
  122. ac = new MyArcBall(c);
  123. this.getLock(c);
  124. this.fireGestureEvent(new ArcBallGestureEvent(this, ArcBallGestureEvent.GESTURE_RESUMED, c.getCurrentTarget(), identityDummy));
  125. }
  126. }
  127. /**
  128. *
  129. * @author Chris
  130. *
  131. */
  132. public interface IArcball{
  133. public Matrix getNewRotation(InputCursor m);
  134. }
  135. /**
  136. *
  137. * @author Chris
  138. *
  139. */
  140. private class MyArcBall implements IArcball{
  141. private Vector3D lastPoint;
  142. private Quaternion q;
  143. private Matrix returnMatrix;
  144. private InputCursor m;
  145. private boolean doInWorldCoords = true;
  146. private boolean camInSphere = false;
  147. private float camDistToInterSection;
  148. public MyArcBall(InputCursor m){
  149. this.m = m;
  150. lastPoint = getSphereIntersectionObjSpace();
  151. if (lastPoint == null){
  152. lastPoint = new Vector3D(); //TODO hack: we should abort the gesture
  153. }
  154. // TEST
  155. if (doInWorldCoords)
  156. lastPoint.transform(shape.getGlobalMatrix());
  157. q = new Quaternion();
  158. returnMatrix = new Matrix();
  159. camDistToInterSection = 1;
  160. }
  161. public Matrix getNewRotation(InputCursor m){
  162. returnMatrix.loadIdentity();
  163. Vector3D newInterSection = getSphereIntersectionObjSpace();
  164. if (newInterSection != null){
  165. if (doInWorldCoords)
  166. newInterSection.transform(shape.getGlobalMatrix());
  167. logger.debug("Sphere hit, hitpoint: " + newInterSection);
  168. Vector3D center = bSphere.getCenterPointLocal();
  169. if (doInWorldCoords) //TODO center world cachen?
  170. center.transform(shape.getGlobalMatrix());
  171. Vector3D a = lastPoint.getSubtracted(center);
  172. Vector3D b = newInterSection.getSubtracted(center);
  173. //float dot = a.dot(b);
  174. // float angle = Vector3D.angleBetween(a, b);
  175. float angle = (float)myAngleBetween(a, b);
  176. // angle *= sizeScaled * 1.5f;
  177. Vector3D rotationAxis = a.crossLocal(b);
  178. //Inverse the angle if we are inside the boundingsphere and
  179. //hit the inner side
  180. if (camInSphere){ //we hit the backside of the boundingsphere, have to invert direction
  181. // angle *= -1;
  182. // rotationAxis.rotateZ(PApplet.radians(180)); //better than angle*-1
  183. rotationAxis.rotateZ(ToolsMath.PI); //better than angle*-1
  184. // rotationAxis.rotateX(PApplet.radians(180)); //better than angle*-1
  185. // rotationAxis.scaleLocal(-1); //like angle*-1
  186. // rotationAxis.rotateAroundAxisLocal(rotationAxis, PApplet.radians(90));
  187. }
  188. rotationAxis.normalizeLocal();
  189. //TODO map points that didnt intersect to sphere
  190. //TODO measure distance from cam to sphere intersection point and multiply angle
  191. //so that if distance big -> less angle, if distance small -> more angle
  192. // System.out.println("Distance Camera to Sphere Intersection: " + camDistToInterSection);
  193. // angle *= 1+ 1/camDistToInterSection;
  194. float dist = Vector3D.distance(shape.getViewingCamera().getPosition() , newInterSection);
  195. // System.out.println("Dist: " + dist + " Angle: " + angle);
  196. //Hack to make rotation faster if near sphere
  197. float angleScaleFactor = 500f / dist;
  198. if (angleScaleFactor < 1.5f)
  199. angleScaleFactor = 1.5f;
  200. if (angleScaleFactor > 80f)
  201. angleScaleFactor = 80f;
  202. // System.out.println("Angle Scale factor: " + angleScaleFactor);
  203. angle *= angleScaleFactor;
  204. // System.out.println();
  205. // logger.debug("New hitpoint" + NewPt);
  206. // logger.debug("Axis: " + cross);
  207. // logger.debug("Angle: " +angle + " \n");
  208. // q.fromAngleNormalAxis(angle, cross);
  209. // q.toRotationMatrix(returnMatrix);
  210. returnMatrix.fromAngleNormalAxis(angle, rotationAxis);
  211. //logger.debug(returnMatrix);
  212. this.lastPoint.setValues(newInterSection);
  213. //TODO why often invalid matrix? because we didnt norm the sphere to -1..1?
  214. if (!returnMatrix.isValid()) {
  215. // logger.debug("NaN");
  216. returnMatrix.loadIdentity();
  217. return returnMatrix;
  218. }
  219. // returnMatrix = Matrix.getZRotationMatrix(new Vector3D(), 1);
  220. // Matrix.toRotationAboutPointMatrixAndInverse(returnMatrix, null, new Vector3D());
  221. //to rotate relative to world transform rotation point
  222. if (doInWorldCoords)
  223. center = MTComponent.getGlobalVecToParentRelativeSpace(shape, center);
  224. //To rotate about the center of the object
  225. Matrix.toRotationAboutPoint(returnMatrix, center);
  226. }else{
  227. logger.debug("Sphere wasnt hit!");
  228. }
  229. return returnMatrix;
  230. }
  231. private double myAngleBetween(Vector3D a, Vector3D b) {
  232. float dot = a.dot(b);
  233. double theta = Math.acos(dot / (length(a) * (length(b)) ));
  234. return theta;
  235. }
  236. /**
  237. * Calculate the magnitude (length) of the vector.
  238. *
  239. * @return the magnitude of the vector
  240. */
  241. public double length(Vector3D v) {
  242. return Math.sqrt(v.x*v.x + v.y*v.y + v.z*v.z);
  243. }
  244. private Vector3D getSphereIntersectionObjSpace(){
  245. // Icamera cam = shape.getAncestor().getGlobalCam();
  246. //
  247. // Vector3D rayStartPoint = cam.getPosition();
  248. // Vector3D pointInRayDir = Tools3D.unprojectScreenCoords(applet, m.getLastEvent().getPositionX(), m.getLastEvent().getPositionY());
  249. //
  250. // Ray orgRay = new Ray(rayStartPoint, pointInRayDir);
  251. Ray realRayForThisObj = Tools3D.getCameraPickRay(applet, shape, m.getCurrentEvent().getX(), m.getCurrentEvent().getY());
  252. // Ray realRayForThisObj = Tools3D.toComponentCameraPickRay(applet, shape, orgRay);
  253. //TRIAL
  254. Ray invertedRay = Ray.getTransformedRay(realRayForThisObj, shape.getGlobalInverseMatrix());
  255. Vector3D is = bSphere.getIntersectionLocal(invertedRay);
  256. //Test to detect whether were inside the sphere
  257. // Vector3D camPos = cam.getPosition();
  258. Vector3D camPos = shape.getViewingCamera().getPosition();
  259. camPos.transform(shape.getGlobalInverseMatrix());
  260. if (is != null){
  261. camDistToInterSection = Vector3D.distance(camPos, is);
  262. //bSphere.distanceToEdge(camPos);
  263. }
  264. camInSphere = bSphere.containsPointLocal(camPos);
  265. return is;
  266. }
  267. }
  268. private class ArcBallContext implements IArcball{
  269. private static final float Epsilon = 1.0e-5f;
  270. Quaternion q;
  271. Vector3D StVec; //Saved click vector
  272. Vector3D EnVec; //Saved drag vector
  273. float adjustWidth; //Mouse bounds width
  274. float adjustHeight; //Mouse bounds height
  275. public ArcBallContext(float NewWidth, float NewHeight) {
  276. StVec = new Vector3D();
  277. EnVec = new Vector3D();
  278. setBounds(NewWidth, NewHeight);
  279. q = new Quaternion();
  280. }
  281. public void mapToSphere(Vector3D point, Vector3D outVector) {
  282. //Copy paramter into temp point
  283. Vector3D tempPoint = new Vector3D(point.x, point.y, point.z);
  284. //Adjust point coords and scale down to range of [-1 ... 1]
  285. tempPoint.x = (tempPoint.x * this.adjustWidth) - 1.0f;
  286. tempPoint.y = 1.0f - (tempPoint.y * this.adjustHeight);
  287. //Compute the square of the length of the vector to the point from the center
  288. float length = (tempPoint.x * tempPoint.x) + (tempPoint.y * tempPoint.y);
  289. //If the point is mapped outside of the sphere... (length > radius squared)
  290. if (length > 1.0f) {
  291. //Compute a normalizing factor (radius / sqrt(length))
  292. float norm = (float) (1.0 / Math.sqrt(length));
  293. //Return the "normalized" vector, a point on the sphere
  294. outVector.x = tempPoint.x * norm;
  295. outVector.y = tempPoint.y * norm;
  296. outVector.z = 0.0f;
  297. } else { //Else it's on the inside
  298. //Return a vector to a point mapped inside the sphere sqrt(radius squared - length)
  299. outVector.x = tempPoint.x;
  300. outVector.y = tempPoint.y;
  301. outVector.z = (float) Math.sqrt(1.0f - length);
  302. }
  303. }
  304. public void setBounds(float NewWidth, float NewHeight) {
  305. assert((NewWidth > 1.0f) && (NewHeight > 1.0f));//TODO REMOVE
  306. //Set adjustment factor for width/height
  307. adjustWidth = 1.0f / ((NewWidth - 1.0f) * 0.5f);
  308. adjustHeight = 1.0f / ((NewHeight - 1.0f) * 0.5f);
  309. }
  310. //Mouse down
  311. public void click(Vector3D NewPt) {
  312. mapToSphere(NewPt, this.StVec);
  313. }
  314. //Mouse down
  315. public void click(InputCursor m){
  316. // Icamera cam = shape.getAncestor().getGlobalCam();
  317. // Vector3D rayStartPoint = cam.getPosition();
  318. // Vector3D pointInRayDir = Tools3D.unprojectScreenCoords(applet, m.getLastEvent().getPositionX(), m.getLastEvent().getPositionY());
  319. // Ray orgRay = new Ray(rayStartPoint, pointInRayDir);
  320. // Ray realRayForThisObj = Tools3D.toComponentCameraPickRay(applet, shape, orgRay);
  321. Ray realRayForThisObj = Tools3D.getCameraPickRay(applet, shape, m.getCurrentEvent().getX(), m.getCurrentEvent().getY());
  322. //TRIAL
  323. Ray invertedRay = Ray.getTransformedRay(realRayForThisObj, shape.getGlobalInverseMatrix());
  324. Vector3D NewPt = bSphere.getIntersectionLocal(invertedRay);
  325. if (NewPt != null){
  326. PGraphicsOpenGL pgl = ((PGraphicsOpenGL)applet.g);
  327. GL gl = pgl.beginGL();
  328. gl.glPushMatrix();
  329. gl.glMultMatrixf(shape.getGlobalMatrix().toFloatBuffer());
  330. NewPt = Tools3D.projectGL(gl, pgl.glu, NewPt, NewPt);
  331. gl.glPopMatrix();
  332. pgl.endGL();
  333. this.mapToSphere(NewPt, this.StVec);
  334. }else{
  335. logger.error(getName() + " Didnt hit sphere!");
  336. }
  337. }
  338. public Matrix getNewRotation(InputCursor m){
  339. // Icamera cam = shape.getAncestor().getGlobalCam();
  340. // Vector3D rayStartPoint = cam.getPosition();
  341. // Vector3D pointInRayDir = Tools3D.unprojectScreenCoords(applet, m.getLastEvent().getPositionX(), m.getLastEvent().getPositionY());
  342. // Ray orgRay = new Ray(rayStartPoint, pointInRayDir);
  343. // Ray realRayForThisObj = Tools3D.toComponentCameraPickRay(applet, shape, orgRay);
  344. Ray realRayForThisObj = Tools3D.getCameraPickRay(applet, shape, m.getCurrentEvent().getX(), m.getCurrentEvent().getY());
  345. //TRIAL
  346. Ray invertedRay = Ray.getTransformedRay(realRayForThisObj, shape.getGlobalInverseMatrix());
  347. Vector3D NewPt = bSphere.getIntersectionLocal(invertedRay);
  348. if (NewPt != null){
  349. PGraphicsOpenGL pgl = ((PGraphicsOpenGL)applet.g);
  350. GL gl = pgl.beginGL();
  351. gl.glPushMatrix();
  352. gl.glMultMatrixf(shape.getGlobalMatrix().toFloatBuffer());
  353. NewPt = Tools3D.projectGL(gl, pgl.glu, NewPt, NewPt);
  354. gl.glPopMatrix();
  355. pgl.endGL();
  356. logger.debug(NewPt);
  357. this.drag(NewPt, q);
  358. }else{
  359. return Matrix.get4x4Identity();
  360. }
  361. return q.toRotationMatrix();
  362. }
  363. //Mouse drag, calculate rotation
  364. public void drag(Vector3D NewPt, Quaternion NewRot) {
  365. // this.EnVec.setValues(NewPt);
  366. //Map the point to the sphere
  367. this.mapToSphere(NewPt, EnVec);
  368. //Return the quaternion equivalent to the ration
  369. if (NewRot != null) {
  370. // Vector3D Perp = new Vector3D();
  371. //Compute the vector perpendicular to the begin and end vectors
  372. // Vector3D.cross(Perp, StVec, EnVec);
  373. Vector3D Perp = StVec.getCross(EnVec);
  374. //Compute the length of the perpendicular vector
  375. if (Perp.length() > Epsilon){ //if its non-zero
  376. //We're ok, so return the perpendicular vector as the transform after all
  377. NewRot.x = Perp.x;
  378. NewRot.y = Perp.y;
  379. NewRot.z = Perp.z;
  380. //In the quaternion values, w is cosine (theta / 2), where theta is rotation angle
  381. // NewRot.w = Vector3D.dot(StVec, EnVec);
  382. NewRot.w = StVec.dot(EnVec);
  383. } else { //if its zero
  384. //The begin and end vectors coincide, so return an identity transform
  385. NewRot.x = NewRot.y = NewRot.z = NewRot.w = 0.0f;
  386. }
  387. }
  388. }
  389. }
  390. // private class ArcBall {
  391. //
  392. // PApplet parent;
  393. //
  394. // float center_x, center_y, center_z, radius;
  395. // Vector3D v_down, v_drag;
  396. // Quaternion q_now, q_down, q_drag;
  397. // Vector3D[] axisSet;
  398. // int axis;
  399. //
  400. // /** defaults to radius of min(width/2,height/2) and center_z of -radius */
  401. // public ArcBall(PApplet parent) {
  402. // this(parent.g.width/2.0f,parent.g.height/2.0f,-PApplet.min(parent.g.width/2.0f,parent.g.height/2.0f),PApplet.min(parent.g.width/2.0f,parent.g.height/2.0f), parent);
  403. // }
  404. //
  405. // public ArcBall(float center_x, float center_y, float center_z, float radius, PApplet parent) {
  406. //
  407. // this.parent = parent;
  408. //
  409. // parent.registerMouseEvent(this);
  410. // parent.registerPre(this);
  411. //
  412. // this.center_x = center_x;
  413. // this.center_y = center_y;
  414. // this.center_z = center_z;
  415. // this.radius = radius;
  416. //
  417. // v_down = new Vector3D();
  418. // v_drag = new Vector3D();
  419. //
  420. // q_now = new Quaternion();
  421. // q_down = new Quaternion();
  422. // q_drag = new Quaternion();
  423. //
  424. // axisSet = new Vector3D[] {
  425. // new Vector3D(1.0f, 0.0f, 0.0f), new Vector3D(0.0f, 1.0f, 0.0f), new Vector3D(0.0f, 0.0f, 1.0f) };
  426. // axis = -1; // no constraints...
  427. // }
  428. //
  429. // public void mouseEvent(MouseEvent event) {
  430. // int id = event.getID();
  431. // if (id == MouseEvent.MOUSE_DRAGGED) {
  432. // mouseDragged();
  433. // }
  434. // else if (id == MouseEvent.MOUSE_PRESSED) {
  435. // mousePressed();
  436. // }
  437. // }
  438. //
  439. // public Matrix drag(InputCursor m){
  440. // //TODO
  441. // Icamera cam = shape.getAncestor().getGlobalCam();
  442. //
  443. // Vector3D rayStartPoint = cam.getPosition();
  444. // Vector3D pointInRayDir = Tools3D.unprojectScreenCoords(applet, m.getLastEvent().getPositionX(), m.getLastEvent().getPositionY());
  445. //
  446. // Ray orgRay = new Ray(rayStartPoint, pointInRayDir);
  447. //
  448. // Ray realRayForThisObj = Tools3D.getRealPickRay(shape, orgRay);
  449. //
  450. // //TRIAL
  451. // Ray invertedRay = Ray.getTransformedRay(realRayForThisObj, shape.getAbsoluteWorldToLocalMatrix());
  452. //
  453. // Vector3D NewPt = bSphere.getIntersectionPoint(invertedRay);
  454. //
  455. // if (NewPt != null){
  456. // logger.debug(NewPt);
  457. // this.mouseDragged();
  458. //
  459. //// this.drag(NewPt, q);
  460. // }else{
  461. // return Matrix.get4x4Identity();
  462. // }
  463. // }
  464. //
  465. // public void mousePressed() {
  466. // v_down = mouse_to_sphere(parent.mouseX, parent.mouseY);
  467. // q_down.set(q_now);
  468. //// q_drag.reset();
  469. // q_drag.loadIdentity();
  470. // }
  471. //
  472. //
  473. // public void mouseDragged(float x, float y) {
  474. // v_drag = mouse_to_sphere(y, y);
  475. //// q_drag.set(Vector3D.dot(v_down, v_drag), Vector3D.cross(v_down, v_drag));
  476. // q_drag.set(v_down.dot(v_drag), v_down.getCross(v_drag));
  477. // }
  478. //
  479. //// public void mouseDragged() {
  480. //// v_drag = mouse_to_sphere(parent.mouseX, parent.mouseY);
  481. ////// q_drag.set(Vector3D.dot(v_down, v_drag), Vector3D.cross(v_down, v_drag));
  482. //// q_drag.set(v_down.dot(v_drag), v_down.getCross(v_drag));
  483. //// }
  484. //
  485. // public void pre() {
  486. // parent.translate(center_x, center_y, center_z);
  487. //// q_now = Quaternion.mul(q_drag, q_down);
  488. // q_now = q_drag.mult(q_down);
  489. //
  490. // applyQuaternion2Matrix(q_now);
  491. // parent.translate(-center_x, -center_y, -center_z);
  492. // }
  493. //
  494. // Vector3D mouse_to_sphere(float x, float y) {
  495. // Vector3D v = new Vector3D();
  496. // v.x = (x - center_x) / radius;
  497. // v.y = (y - center_y) / radius;
  498. //
  499. // float mag = v.x * v.x + v.y * v.y;
  500. // if (mag > 1.0f) {
  501. //// v.normalize();
  502. // v.normalizeLocal();
  503. // }
  504. // else {
  505. // v.z = PApplet.sqrt(1.0f - mag);
  506. // }
  507. //
  508. // return (axis == -1) ? v : constrain_vector(v, axisSet[axis]);
  509. // }
  510. //
  511. // Vector3D constrain_vector(Vector3D vector, Vector3D axis) {
  512. // Vector3D res = new Vector3D();
  513. //// res.sub(vector, Vector3D.mul(axis, Vector3D.dot(axis, vector)));
  514. // res.subtractLocal(axis.getScaled(axis.dot(vector)));
  515. //
  516. //// res.normalize();
  517. // res.normalizeLocal();
  518. // return res;
  519. // }
  520. //
  521. // void applyQuaternion2Matrix(Quaternion q) {
  522. // // instead of transforming q into a matrix and applying it...
  523. //
  524. // float[] aa = q.getValue();
  525. // parent.rotate(aa[0], aa[1], aa[2], aa[3]);
  526. // }
  527. //
  528. // }
  529. @Override
  530. public String getName() {
  531. return "Arcball Processor";
  532. }
  533. }