Gần đây tôi đã phải tự giải quyết vấn đề này cho một ứng dụng WebGL. Tôi đã đính kèm mã nguồn hoàn chỉnh, nhưng trong trường hợp nó không hoạt động ngay lập tức cho bạn đây là một số mẹo gỡ lỗi:
- Đừng gỡ lỗi phương pháp không dự đoán của bạn trong trò chơi của bạn. Nếu có thể, hãy thử viết các bài kiểm tra kiểu kiểm tra đơn vị để dễ dàng cách ly những gì đang xảy ra.
- Đảm bảo in các tia đầu ra cho cả hai mặt phẳng cắt gần và xa.
- Hãy nhớ rằng toán học ma trận KHÔNG giao hoán. A x C! = C x A. Kiểm tra lại toán học của bạn.
Ngoài ra, để trả lời một số nhận xét ở trên, bạn gần như không bao giờ muốn sử dụng API lựa chọn của OpenGL. Điều đó giúp bạn chọn các mục hiện có, như nếu bạn đang tạo menu, tuy nhiên nó không thực hiện được hầu hết các tình huống trong thế giới thực như chỉnh sửa mô hình 3D. Nơi bạn cần thêm hình học là kết quả của nhấp chuột.
Đây là thực hiện của tôi. Không có gì kỳ diệu xảy ra ở đây. Chỉ cần thư viện đóng cửa của JavaScript và Google.
gluUnProject
/**
* Port of gluUnProject. Unprojects a 2D screen coordinate into the model-view
* coordinates.
* @param {Number} winX The window point for the x value.
* @param {Number} winY The window point for the y value.
* @param {Number} winZ The window point for the z value. This should range
* between 0 and 1. 0 meaning the near clipping plane and 1 for the far.
* @param {goog.math.Matrix} modelViewMatrix The model-view matrix.
* @param {goog.math.Matrix} projectMatrix The projection matrix.
* @param {Array.<Number>} view the viewport coordinate array.
* @param {Array.<Number>} objPos the model point result.
* @return {Boolean} Whether or not the unprojection was successful.
*/
octorok.math.Matrix.gluUnProject = function(winX, winY, winZ,
modelViewMatrix, projectionMatrix,
viewPort, objPos) {
// Compute the inverse of the perspective x model-view matrix.
/** @type {goog.math.Matrix} */
var transformMatrix =
projectionMatrix.multiply(modelViewMatrix).getInverse();
// Transformation of normalized coordinates (-1 to 1).
/** @type {Array.<Number>} */
var inVector = [
(winX - viewPort[0]) / viewPort[2] * 2.0 - 1.0,
(winY - viewPort[1]) / viewPort[3] * 2.0 - 1.0,
2.0 * winZ - 1.0,
1.0 ];
// Now transform that vector into object coordinates.
/** @type {goog.math.Matrix} */
// Flip 1x4 to 4x1. (Alternately use different matrix ctor.
var inMatrix = new goog.math.Matrix([ inVector ]).getTranspose();
/** @type {goog.math.Matrix} */
var resultMtx = transformMatrix.multiply(inMatrix);
/** @type {Array.<Number>} */
var resultArr = [
resultMtx.getValueAt(0, 0),
resultMtx.getValueAt(1, 0),
resultMtx.getValueAt(2, 0),
resultMtx.getValueAt(3, 0) ];
if (resultArr[3] == 0.0) {
return false;
}
// Invert to normalize x, y, and z values.
resultArr[3] = 1.0 / resultArr[3];
objPos[0] = resultArr[0] * resultArr[3];
objPos[1] = resultArr[1] * resultArr[3];
objPos[2] = resultArr[2] * resultArr[3];
return true;
};
Sử dụng
this.sys.event_mouseClicked = function(event) {
// Relative x and y are computed via magic by SystemModule.
// Should range from 0 .. viewport width/height.
var winX = event.relativeX;
var winY = event.relativeY;
window.console.log('Camera at [' + me.camera.position_ + ']');
window.console.log('Clicked [' + winX + ', ' + winY + ']');
// viewportOriginX, viewportOriginY, viewportWidth, viewportHeight
var viewPort = [0, 0, event.viewPortWidth, event.viewPortHeight];
var objPos = []; // out parameter.
// The camera's model-view matrix is the result of gluLookAt.
var modelViewMatrix = me.camera.getCameraMatrix();
// The perspective matrix is the result of gluPerspective.
var perspectiveMatrix = pMatrix.get();
// Ray start
var result1 = octorok.math.Matrix.gluUnProject(
winX, winY, 0.0,
modelViewMatrix, perspectiveMatrix,
viewPort, objPos);
window.console.log('Seg start: ' + objPos + ' (result:' + result1 + ')');
// Ray end
var result2 = octorok.math.Matrix.gluUnProject(
winX, winY, 1.0,
modelViewMatrix, perspectiveMatrix,
viewPort, objPos);
window.console.log('Seg end: ' + objPos + ' (result:' + result2 + ')');
};
};