* Orbits the camera about center point. For use with orbitControl(). * Unlike _orbit(), the direction of rotation always matches the direction of pointer movement. * @private * @param {Number} dx the x component of the rotation vector. * @param {Number} dy the y component of the rotation
(dx, dy, dRadius)
| 1950 | * @param {Number} dRadius change in radius |
| 1951 | */ |
| 1952 | _orbitFree(dx, dy, dRadius) { |
| 1953 | // Calculate the vector and its magnitude from the center to the viewpoint |
| 1954 | const diffX = this.eyeX - this.centerX; |
| 1955 | const diffY = this.eyeY - this.centerY; |
| 1956 | const diffZ = this.eyeZ - this.centerZ; |
| 1957 | let camRadius = Math.hypot(diffX, diffY, diffZ); |
| 1958 | // front vector. unit vector from center to eye. |
| 1959 | const front = new Vector(diffX, diffY, diffZ).normalize(); |
| 1960 | // up vector. camera's up vector. |
| 1961 | const up = new Vector(this.upX, this.upY, this.upZ); |
| 1962 | // side vector. Right when viewed from the front. (like x-axis) |
| 1963 | const side = Vector.cross(up, front).normalize(); |
| 1964 | // down vector. Bottom when viewed from the front. (like y-axis) |
| 1965 | const down = Vector.cross(front, side); |
| 1966 | |
| 1967 | // side vector and down vector are no longer used as-is. |
| 1968 | // Create a vector representing the direction of rotation |
| 1969 | // in the form cos(direction)*side + sin(direction)*down. |
| 1970 | // Make the current side vector into this. |
| 1971 | const directionAngle = Math.atan2(dy, dx); |
| 1972 | down.mult(Math.sin(directionAngle)); |
| 1973 | side.mult(Math.cos(directionAngle)).add(down); |
| 1974 | // The amount of rotation is the size of the vector (dx, dy). |
| 1975 | const rotAngle = Math.sqrt(dx * dx + dy * dy); |
| 1976 | // The vector that is orthogonal to both the front vector and |
| 1977 | // the rotation direction vector is the rotation axis vector. |
| 1978 | const axis = Vector.cross(front, side); |
| 1979 | |
| 1980 | // update camRadius |
| 1981 | camRadius *= Math.pow(10, dRadius); |
| 1982 | // prevent zooming through the center: |
| 1983 | if (camRadius < this.cameraNear) { |
| 1984 | camRadius = this.cameraNear; |
| 1985 | } |
| 1986 | if (camRadius > this.cameraFar) { |
| 1987 | camRadius = this.cameraFar; |
| 1988 | } |
| 1989 | |
| 1990 | // If the axis vector is likened to the z-axis, the front vector is |
| 1991 | // the x-axis and the side vector is the y-axis. Rotate the up and front |
| 1992 | // vectors respectively by thinking of them as rotations around the z-axis. |
| 1993 | |
| 1994 | // Calculate the components by taking the dot product and |
| 1995 | // calculate a rotation based on that. |
| 1996 | const c = Math.cos(rotAngle); |
| 1997 | const s = Math.sin(rotAngle); |
| 1998 | const dotFront = up.dot(front); |
| 1999 | const dotSide = up.dot(side); |
| 2000 | const ux = dotFront * c + dotSide * s; |
| 2001 | const uy = -dotFront * s + dotSide * c; |
| 2002 | const uz = up.dot(axis); |
| 2003 | up.x = ux * front.x + uy * side.x + uz * axis.x; |
| 2004 | up.y = ux * front.y + uy * side.y + uz * axis.y; |
| 2005 | up.z = ux * front.z + uy * side.z + uz * axis.z; |
| 2006 | // We won't be using the side vector and the front vector anymore, |
| 2007 | // so let's make the front vector into the vector from the center to the new eye. |
| 2008 | side.mult(-s); |
| 2009 | front.mult(c).add(side).mult(camRadius); |