Hi,
I tried to understand how to convert world coordinates to screen coordinates. I read appropriate stuff in this forum, but I'm stil missing something.
I used code, found in this forum, it works, but partially.
Code:float x, y, z; RECT rc = {0,0,1024,768}; const float M_DEG2RAD = 0.01745329251f; float x = bobber.fPos[0]; float y = bobber.fPos[1]; float z = bobber.fPos[2]; //CVec3 vDiff = vWoWPos - camera.vPos; float fDiff[3]; fDiff[0] = x-camera.fPos[0]; fDiff[1] = y-camera.fPos[1]; fDiff[2] = z-camera.fPos[2]; //float fProd = vDiff*camera.matView[0]; float fProd = fDiff[0]*camera.fViewMat[0][0] + fDiff[1]*camera.fViewMat[0][1] + fDiff[2]*camera.fViewMat[0][2]; if( fProd < 0 ) return FALSE; //CVec3 vView = vDiff*!camera.matView; float fInv[3][3]; fInv[0][0] = camera.fViewMat[1][1]*camera.fViewMat[2][2]-camera.fViewMat[1][2]*camera.fViewMat[2][1]; fInv[1][0] = camera.fViewMat[1][2]*camera.fViewMat[2][0]-camera.fViewMat[1][0]*camera.fViewMat[2][2]; fInv[2][0] = camera.fViewMat[1][0]*camera.fViewMat[2][1]-camera.fViewMat[1][1]*camera.fViewMat[2][0]; float fDet = camera.fViewMat[0][0]*fInv[0][0]+camera.fViewMat[0][1]*fInv[1][0]+camera.fViewMat[0][2]*fInv[2][0]; float fInvDet = 1.0f / fDet; fInv[0][1] = camera.fViewMat[0][2]*camera.fViewMat[2][1]-camera.fViewMat[0][1]*camera.fViewMat[2][2]; fInv[0][2] = camera.fViewMat[0][1]*camera.fViewMat[1][2]-camera.fViewMat[0][2]*camera.fViewMat[1][1]; fInv[1][1] = camera.fViewMat[0][0]*camera.fViewMat[2][2]-camera.fViewMat[0][2]*camera.fViewMat[2][0]; fInv[1][2] = camera.fViewMat[0][2]*camera.fViewMat[1][0]-camera.fViewMat[0][0]*camera.fViewMat[1][2]; fInv[2][1] = camera.fViewMat[0][1]*camera.fViewMat[2][0]-camera.fViewMat[0][0]*camera.fViewMat[2][1]; fInv[2][2] = camera.fViewMat[0][0]*camera.fViewMat[1][1]-camera.fViewMat[0][1]*camera.fViewMat[1][0]; camera.fViewMat[0][0] = fInv[0][0]*fInvDet; camera.fViewMat[0][1] = fInv[0][1]*fInvDet; camera.fViewMat[0][2] = fInv[0][2]*fInvDet; camera.fViewMat[1][0] = fInv[1][0]*fInvDet; camera.fViewMat[1][1] = fInv[1][1]*fInvDet; camera.fViewMat[1][2] = fInv[1][2]*fInvDet; camera.fViewMat[2][0] = fInv[2][0]*fInvDet; camera.fViewMat[2][1] = fInv[2][1]*fInvDet; camera.fViewMat[2][2] = fInv[2][2]*fInvDet; float fView[3]; fView[0] = fInv[0][0]*fDiff[0]+fInv[1][0]*fDiff[1]+fInv[2][0]*fDiff[2]; fView[1] = fInv[0][1]*fDiff[0]+fInv[1][1]*fDiff[1]+fInv[2][1]*fDiff[2]; fView[2] = fInv[0][2]*fDiff[0]+fInv[1][2]*fDiff[1]+fInv[2][2]*fDiff[2]; //CVec3 vCam( -vView.fY,-vView.fZ,vView.fX ); float fCam[3]; fCam[0] = -fView[1]; fCam[1] = -fView[2]; fCam[2] = fView[0]; float fScreenX = (rc.right-rc.left)/2.0f; float fScreenY = (rc.bottom-rc.top)/2.0f; // Thanks pat0! Aspect ratio fix float fTmpX = fScreenX/tan(((camera.fFov*44.0f)/2.0f)*M_DEG2RAD); float fTmpY = fScreenY/tan(((camera.fFov*35.0f)/2.0f)*M_DEG2RAD); POINT pctMouse; pctMouse.x = fScreenX + fCam[0]*fTmpX/fCam[2]; pctMouse.y = fScreenY + fCam[1]*fTmpY/fCam[2];I found another way(didn't try yet), which calculates it from camera's position and rotation:Code:struct SCameraInfo { DWORD dwFoo1[2]; float fPos[3]; float fViewMat[3][3]; DWORD dwFoo2[2]; //[2] float fFov; };
My questions:Code:BOOL scrPos(float x, float y, float z, POINT *pt){ // return scrpos relative to leftup corner, x positive to right, y positive to downward // to be compatible with MouseClick /* some transformation, by wanyancan. transed := ({ {1, 0, 0, -camx}, {0, 1, 0, -camy}, {0, 0, 1, -camz}, {0, 0, 0, 1} }) zroted := ({ {cosY, -sinY, 0, 0}, {sinY, cosY, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1} }).transed xroted := ({ {1, 0, 0, 0}, {0, cos[alpha], sin[alpha], 0}, {0, -sin[alpha], cos[alpha], 0}, {0, 0, 0, 1} }).zroted pos := xroted.({ {myx}, {myy}, {myz}, {1} }) = {{-camx cosY + cosY myx + camy sinY - myy sinY}, {cosY myy cos[alpha] + myx sinY cos[alpha] + (-camy cosY - camx sinY) cos[alpha] - camz sin[alpha] + myz sin[alpha]}, {-camz cos[alpha] + myz cos[alpha] - cosY myy sin[alpha] - myx sinY sin[alpha] - (-camy cosY - camx sinY) sin[alpha]}, {1}} */ float camX = ReadFloat(LPCVOID(G_CAMPOS+4)); // camera position float camY = ReadFloat(LPCVOID(G_CAMPOS)); float camZ = ReadFloat(LPCVOID(G_CAMPOS+8)); float camRotX = ReadFloat(LPCVOID(G_CAMROT)); // camera horizontal direction (0 , 2*pi) north is 0, positive counter-clockwise float camRotY = ReadFloat(LPCVOID(G_CAMROT+4)); // camera vertical direction (-pi/2, pi/2) look upward is positive float alpha = asinf(camRotX); float cosY = cosf(camRotY); float sinY = sinf(camRotY); float pos0 = -camX*cosY+cosY*x+camY*sinY-y*sinY; float pos1 = cosY*y*cosf(alpha)+x*sinY*cosf(alpha)+(-camY*cosY-camX*sinY)*cosf(alpha)-camZ*sinf(alpha) + z*sinf(alpha); float pos2 = -camZ*cosf(alpha)+z*cosf(alpha)-cosY*y*sinf(alpha)-x*sinY*sin(alpha)-(-camY*cosY-camX*sinY)*sin(alpha); if (pos1<0.1) return FALSE; float fov = 3.1415926/2*0.7; // field of view , view angle is about 0.7 RECT rect; GetClientRect(wowhwnd, &rect); float modifier = 1.0f; if(1.0*rect.right/rect.bottom>1.5) modifier *=1.15; // widescreen modifier float scrX = -pos0/pos1/tanf(fov/2*1.08*modifier) * rect.right/2; float scrY = -pos2/pos1/tanf(fov/2*0.85) * rect.bottom/2; //printf("cam (%.1f,%.1f,%.1f), camRot (%.1f,%.1f), obj(%.1f,%.1f,%.1f) scr (%.1f, %.1f)\n", camX, camY, camZ, camRotX, camRotY, x,y,z, scrX, scrY); if (abs(scrX)*3>rect.right || abs(scrY)*3>rect.bottom) return FALSE; // out of center 1/3 rectangle. pt->x = scrX+rect.right/2; pt->y = scrY+rect.bottom/2; return TRUE; }
1/ Is the struct SCameraInfo stil valid? I found this: Cataclysm - WoWDev
2/ What is EXACTLY float fViewMat[3][3]; in SCameraInfo?? Is it ViewMatrix, as showed here?
3/ What is the correct way of using fViewMat[3][3] ?? In first included code it computes inverse matrice to fViewMat[3][3] etc.etc. ... please point me to clarification, what it exactly does to get screen coordinates of any object in world.
4/ Where I can find information, needed for Projection Matrix construction? The code above works for 1024/768 window only, because of hardcoded constants.
Thanx for answer
PS: sorry for my english .)