賞金將在 10 小時后到期。此問題的答案有資格獲得 150聲望賞金。 clankill3r希望引起對這個問題的更多關注。
經過一組變換后,我想畫出滑鼠所在的位置。這與繪圖本身無關,當應用某種變換時,它會在 xyz 中得到重點。對于這篇文章,我只是將問題縮小到最低限度。這是我想要開始作業的代碼:
void setup() {
size(600, 600, P3D);
}
public void draw() {
background(0);
translate(width/2, height/2, -100);
pushMatrix();
float rot_y = map(mouseX, 0, width, 0, TWO_PI);
rotateY(rot_y);
int dim = min(width, height) / 2;
noFill();
stroke(255);
box(dim);
float z = 0; // or ((PGraphicsOpenGL)g).cameraNear;?
PVector pos = screenPointToWorld(mouseX, mouseY, z);
translate(pos.x, pos.y, pos.z);
box(5); // should appear where the mouse is!
popMatrix();
}
這是統一的 screenPointToWorld 的模擬: https ://docs.unity3d.com/ScriptReference/Camera.ScreenToWorldPoint.html
我確實找到了這個,這對我有幫助: https ://answers.unity.com/questions/1293942/calculation-behind-camerascreentoworldpoint.html
這些是我的 2 次嘗試:
PVector screenPointToWorld(PVector sp) {
PGraphicsOpenGL _g = ((PGraphicsOpenGL)g);
// cam.worldToCameraMatrix?? Not sure about this one
PMatrix3D final_matrix = new PMatrix3D(_g.modelview);
final_matrix.apply(_g.projection);
final_matrix.invert();
float[] in = new float[4];
in[0] = sp.x;
in[1] = sp.y;
in[2] = sp.z;
in[3] = 1.0f;
/* Map x and y from window coordinates */
// in[0] = (in[0] - viewport[0]) / viewport[2];
// in[1] = (in[1] - viewport[1]) / viewport[3];
in[0] = in[0] / width;
in[1] = in[1] / height;
/* Map to range -1 to 1 */
in[0] = in[0] * 2 - 1;
in[1] = in[1] * 2 - 1;
in[2] = in[2] * 2 - 1;
float[] out = new float[4];
final_matrix.mult(in, out);
out[0] /= out[3];
out[1] /= out[3];
out[2] /= out[3];
return new PVector(out[X], out[Y], out[Z]);
}
PVector screenPointToWorld2(PVector sp) {
PGraphicsOpenGL _g = ((PGraphicsOpenGL)g);
// cam.worldToCameraMatrix?? Not sure about this one
PMatrix3D worldToCameraMatrix = new PMatrix3D(_g.camera);
worldToCameraMatrix.invert();
PMatrix3D world2Screen = new PMatrix3D(_g.projection);
world2Screen.apply(worldToCameraMatrix);
PMatrix3D screen2World = new PMatrix3D(world2Screen);
screen2World.invert();
float[] inn = new float[4];
inn[0] = 2.0f * (sp.x / width) - 1.0f;
inn[1] = 2.0f * (sp.y / height) - 1.0f;
inn[2] = _g.cameraNear;
inn[3] = 1.0f;
float[] pos = new float[4];
screen2World.mult(inn, pos);
int X = 0;
int Y = 1;
int Z = 2;
int W = 3;
pos[W] = 1.0f / pos[W];
pos[X] *= pos[W];
pos[Y] *= pos[W];
pos[Z] *= pos[W];
return new PVector(pos[X], pos[Y], pos[Z]);
}
但它們是不正確的,我不知道為什么。我希望有人能幫幫忙。
更新:
如果我愿意,我可以在滑鼠位置上畫一個框,這不是問題。目標是讓 screenPointToWorld 按預期作業。這是一個更大的程式的一部分,它不適合在 stackoverflow 帖子中。我很清楚 pushMatrix 和 popMatrix 以及如何使用它們。但是在這種情況下它們沒有用。
uj5u.com熱心網友回復:
以下在我的 Mac 上運行。我使用了您發布的第二個函式 screenPointToWorld。除了將 x,y,z 坐標更改為 PVector 以便可以將其傳遞給 screenPointToWorld 之外,我沒有對代碼做太多事情。我看到一個由滑鼠旋轉的三維框。
PVector v;
void setup() {
size(600, 600, P3D);
}
PVector screenPointToWorld(PVector sp) {
PGraphicsOpenGL _g = ((PGraphicsOpenGL)g);
// cam.worldToCameraMatrix?? Not sure about this one
PMatrix3D worldToCameraMatrix = new PMatrix3D(_g.camera);
worldToCameraMatrix.invert();
PMatrix3D world2Screen = new PMatrix3D(_g.projection);
world2Screen.apply(worldToCameraMatrix);
PMatrix3D screen2World = new PMatrix3D(world2Screen);
screen2World.invert();
float[] inn = new float[4];
inn[0] = 2.0f * (sp.x / width) - 1.0f;
inn[1] = 2.0f * (sp.y / height) - 1.0f;
inn[2] = _g.cameraNear;
inn[3] = 1.0f;
float[] pos = new float[4];
screen2World.mult(inn, pos);
int X = 0;
int Y = 1;
int Z = 2;
int W = 3;
pos[W] = 1.0f / pos[W];
pos[X] *= pos[W];
pos[Y] *= pos[W];
pos[Z] *= pos[W];
return new PVector(pos[X], pos[Y], pos[Z]);
}
public void draw() {
background(0);
translate(width/2, height/2, -100);
pushMatrix();
float rot_y = map(mouseX, 0, width, 0, TWO_PI);
rotateY(rot_y);
int dim = min(width, height) / 2;
noFill();
stroke(255);
box(dim);
float z = 0; // or ((PGraphicsOpenGL)g).cameraNear;?
v = new PVector(mouseX, mouseY, z);
PVector pos = screenPointToWorld(v);
translate(pos.x, pos.y, pos.z);
box(5); // should appear where the mouse is!
popMatrix();
}
本次修訂顛倒了方框的順序;小家伙現在首先被要求。翻譯是累積的,所以如果它排在第一位,它將被鎖定到滑鼠坐標。不確定這是否是您希望實作的目標,但您的初始代碼似乎只是試圖更改小盒子的坐標。如果是這種情況,您可能不需要 screenPointToWorld 函式。
void setup() {
size(800, 800, P3D);
}
void draw() {
background(0);
translate(mouseX, mouseY);
box(5);
translate(200,200);
float rot_y = map(mouseX, 0, width, 0, TWO_PI);
rotateY(rot_y);
noFill();
stroke(255);
box(width/4);
}
uj5u.com熱心網友回復:
這就是目的pushMatrix()和popMatrix()目的。他們讓您應用然后洗掉轉換。如果您正確平衡推送和彈出,您將最終回到螢屏坐標:
public void draw() {
background(0);
pushMatrix(); // push a new transformation matrix for the big box
translate(width/2, height/2, -100);
float rot_y = map(mouseX, 0, width, 0, TWO_PI);
rotateY(rot_y);
int dim = min(width, height) / 2;
noFill();
stroke(255);
box(dim);
popMatrix(); // done with the big box--revert to screen coords
translate(mouseX, mouseY); // move to the mouse point to draw the small box
box(5);
}
uj5u.com熱心網友回復:
如果你愿意,讓它變得困難,但這很容易。
void setup() {
size(600, 600, P3D);
}
public void draw() {
background(0);
translate(width/2, height/2, -100);
float rot_y = map(mouseX, 0, width, 0, TWO_PI);
rotateY(rot_y);
int dim = min(width, height) / 2;
noFill();
stroke(255);
box(dim);
// Reverse rotation and first translation
rotateY(-rot_y);
translate(-width/2, -height/2, 100);
// Set a new translation so small box will follow cursor
translate(mouseX,mouseY);
box(5); // should appear where the mouse is!
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/414611.html
標籤:
