Transform screen coordinates to model coordinates

醉酒当歌 提交于 2019-11-30 19:14:35

问题


I've got some sort of newbie question.

In my application (processingjs) i use scale() and translate() to allow the user to zoom and scroll through the scene. As long as i keep the scale set to 1.0 i've got no issues. BUT whenever i use the scale (i.e. scale(0.5)) i'm lost...

I need the mouseX and mouseY translated to the scene coordinates, which i use to determine the mouseOver state of the object I draw on the scene.

Can anybody help me how to translate these coordinates? Thanks in advance! /Richard


回答1:


Unfortunately for me this required a code modification. I'll look at submitting this to the Processing.JS code repository at some point, but here's what I did.

First, you'll want to use modelX() and modelY() to get the coordinates of the mouse in world view. That will look like this:

float model_x = modelX(mouseX, mouseY);
float model_y = modelY(mouseX, mouseY);

Unfortunately Processing.JS doesn't seem to calculate the modelX() and modelY() values correctly in a 2D environment. To correct that I changed the functions to be as follows. Note the test for mv.length == 16 and the section at the end for 2D:

p.modelX = function(x, y, z) {
  var mv = modelView.array();
  if (mv.length == 16) {
    var ci = cameraInv.array();
    var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];
    var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];
    var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];
    var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];
    var ox = 0, ow = 0;
    var ox = ci[0] * ax + ci[1] * ay + ci[2] * az + ci[3] * aw;
    var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw;
    return ow !== 0 ? ox / ow : ox
  }
  // We assume that we're in 2D
  var mvi = modelView.get();
  // NOTE that the modelViewInv doesn't seem to be correct in this case, so
  // having to re-derive the inverse
  mvi.invert();
  return mvi.multX(x, y);
};
p.modelY = function(x, y, z) {
  var mv = modelView.array();
  if (mv.length == 16) {
    var ci = cameraInv.array();
    var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];
    var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];
    var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];
    var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];
    var oy = ci[4] * ax + ci[5] * ay + ci[6] * az + ci[7] * aw;
    var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw;
    return ow !== 0 ? oy / ow : oy
  }
  // We assume that we're in 2D
  var mvi = modelView.get();
  // NOTE that the modelViewInv doesn't seem to be correct in this case, so
  // having to re-derive the inverse
  mvi.invert();
  return mvi.multY(x, y);
};

I hope that helps someone else who is having this problem.




回答2:


Have you tried another method?

For example, assume that you are in a 2D environment, you can "map" all the frame in a sort of matrix. Something like this:

int fWidth = 30;
int fHeight = 20;
float objWidth = 10;
float objHeight = 10;

void setup(){
  fWidth = 30;
  fHeight = 20;
  objWidth = 10;
  objHeight = 10;
  size(fWidth * objWidth, fHeight * objHeight);
}

In this case you will have a 300*200 frame, but divided in 30*20 sections. This allows you to move in somewhat ordered way your objects.

When you draw an object you have to give his sizes, so you can use objWidth and objHeight.

Here's the deal: you can make a "zoom-method" that edit the value of the object sizes. In this way you drew a smaller/bigger object without editing any frame property.

This is a simple example because of your inaccurate question. You can do it [in more complex ways], in a 3D environment too.



来源:https://stackoverflow.com/questions/8339533/transform-screen-coordinates-to-model-coordinates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!