#160431 - DiscoStew - Tue Jul 15, 2008 7:19 pm
What I'm trying to do is extend on my 3D ship flying project to incorporate a target system, of which 2-3 3D points that are ahead of the ship (or in other terms, points that intersect the line that is coming from the front of the ship) are converted to 2D screen coordinates, and sprites are placed on those points, so the person controlling the ship knows there the lasers are directing towards. (To note, the camera will always be behind the ship, though the ship will look like it is swerving to a side because of which way the ship is altering course.)
For the most part, I had succeeded in working with raw Euler angles from the camera to recreate this aspect that I want, though the way with Euler angles in 3D isn't the best option, but now, I'm switching to quaternions for my rotations. I've looked around the net for anything involving them in this case (even the resulting rotation matrix from the quaternions), but I've come up with nothing.
Anyone have an idea on how to accomplish this?
_________________
DS - It's all about DiscoStew
#160436 - silent_code - Tue Jul 15, 2008 9:43 pm
If I understand you correctly, you want to project a 3D point onto the 2D screeen, right?
Use the hardware - there's the position test (much like the box test) available for that task.
Look for it in gbatek.
_________________
July 5th 08: "Volumetric Shadow Demo" 1.6.0 (final) source released
June 5th 08: "Zombie NDS" WIP released!
It's all on my page, just click WWW below.
#160445 - DiscoStew - Wed Jul 16, 2008 12:38 am
Hmm, project? I'm not quite following what you mean. What I'm trying to do is take a 3D point in space (modified by the rotation matrix from the camera), and converting that to 2D screen coordinates, so that I can use such things like sprites to place over the 3D layer. Not sure how POS_TEST can fit into that, especially with it's 3 16-bit input.
In another example of what I mean, imagine a 3D space environment filled with a bunch of planets, some far away from the camera. Against a star-lit background, unless the planets are close, you can't be quite sure if what you are seeing are stars or planets. In this example, I "could" use a scaled-up billboard polygon that is placed at the center of the planet, but that is still affected by depth (and limitation by hardware imo). Instead, I'd use the 2D sprite hardware to place a box on each planet, so I can if I'm seeing a planet. To do this, I'd need to know where the planets are in relation to the camera and the screen. Therefore, the 3D world coordinates -> 2D screen coordinates method would be needed.
Hoep that clarifies things a bit.
_________________
DS - It's all about DiscoStew
#160457 - silent_code - Wed Jul 16, 2008 8:52 am
You put the position into the position test register, wait a few cycles (doing something else) and read it back from the position test result register. Then you just have to scale it to the screen dimensions.
And yes, that is called (screen) projection. ;^)
_________________
July 5th 08: "Volumetric Shadow Demo" 1.6.0 (final) source released
June 5th 08: "Zombie NDS" WIP released!
It's all on my page, just click WWW below.
#160461 - a128 - Wed Jul 16, 2008 9:07 am
based on gbatek I did this once....but I am not sure if it`s ok
Code: |
Vec2 Mathtools::WorldToScreenCoord(const Vec3 &xyz) {
Vec2 screen;
int32 mtx[16];
glGetFixed(GL_GET_MATRIX_CLIP,(int32*)&mtx);
//multiply vec3 with matrix
int32 X=xyz.X();
int32 Y=xyz.Y();
int32 Z=xyz.Z();
int32 xx,yy,zz,w;
xx=mulf32(X,mtx[0])+mulf32(Y,mtx[1])+mulf32(Z,mtx[2])+mtx[3];
yy=mulf32(X,mtx[4])+mulf32(Y,mtx[5])+mulf32(Z,mtx[6])+mtx[7];
// zz=mulf32(X,mtx[8])+mulf32(Y,mtx[9])+mulf32(Z,mtx[10])+mtx[11];
// Homogenous coordinates or perspective divide?!
w=mulf32(X,mtx[12])+mulf32(Y,mtx[13])+mulf32(Z,mtx[14])+mtx[15];
/* w=div32(inttof32(1),w);
xx=mulf32(xx,w);
yy=mulf32(yy,w);
zz=mulf32(zz,w);*/
screen.x.Set( divf32(mulf32((xx+w),270-1),mulf32(inttof32(2),w)));
screen.y.Set( divf32(mulf32((yy+w),192-1),mulf32(inttof32(2),w)));
return screen;
}
|
#160473 - DiscoStew - Wed Jul 16, 2008 5:50 pm
silent_code:
While I'm beginning to see what you mean, the main problem I can see with using that is the limitation of 16 bits per dimension entry. Should I try to use it, I would have to limit the rest of my program. Maybe in certain situations, it would be worthwhile to use, so I'll see what I can do with it. thx.
a128:
Interesting. I'll try that out too. If I may ask though, I noticed that the 'z/zz' portion is commented out in favor of 'w'. Is 'z/zz' not needed, or is it dependent on what the final result of the function returns (since you have a comment just below it)?
_________________
DS - It's all about DiscoStew
#160476 - silent_code - Wed Jul 16, 2008 6:25 pm
I see. Well, but being a bit naive, I don't see a problem with 16bit coordinate components, as it's recommended to use 16bit vertex formats anyway. ;^)
Well, you can still transform the position, you don't have to submit a world absolute position.
Heck, you could probably (haven't tested it, but I will - maybe today) even just put in a "zero vector" and, if all the matrices are applied to it, the coordinate itself could be put into the translation part of the modelview matrix, with all the benefits of higher precision (32bit). ;^D
EDIT: It works, just like that!
And then there's the benefit of parallel processing, as the geometry engine will do the testing for you, the CPU will be left to be used by your program. You could roll your own software test and run that with another position while waiting for the position test result. ;^)
EDIT 1: I will test it and post anything I find out. gbatek states that only the clip matrix is applied... that makes no sense to me.
EDIT 2: Might want to take a look at libnds' <nds/arm9/postest.h>. :^)
EDIT 3: Works, but the result needs clipspace to screenspace conversion (google / wikipedia ;^D ). Matrices are applied just like with ordinary vertices. From the way it works (with 16bit coordinate components), I guess it was designed to work with vertices, anyway.
Just start the position test, (if needed) process the mesh you want the screenspace position of and send it to the geometry engine, then check if the position test is done, read back the result, convert it to screenspace and use that for whatever you need.
EDIT 4: libnds' picking example might also help, although postest.h should suffice.
EDIT 5: (I hope the last one :?D ) Remember only to draw things that are in front of the camera, that means, when W in the result is > 0!
_________________
July 5th 08: "Volumetric Shadow Demo" 1.6.0 (final) source released
June 5th 08: "Zombie NDS" WIP released!
It's all on my page, just click WWW below.
#160505 - a128 - Wed Jul 16, 2008 10:23 pm
DiscoStew wrote: |
a128:
Interesting. I'll try that out too. If I may ask though, I noticed that the 'z/zz' portion is commented out in favor of 'w'. Is 'z/zz' not needed, or is it dependent on what the final result of the function returns (since you have a comment just below it)? |
for Perspective projection you will need the step of perspective divide
this is the block
Code: |
/* w=div32(inttof32(1),w);
xx=mulf32(xx,w);
yy=mulf32(yy,w);
zz=mulf32(zz,w);*/ |
so I guess you must insert this block to have a working perspective projection
if you use
Code: |
xx=xx/zz
yy=yy/zz
screen.x.Set( divf32(mulf32((xx+zz),270-1),mulf32(inttof32(2),zz)));
screen.y.Set( divf32(mulf32((yy+zz),192-1),mulf32(inttof32(2),zz)));
|
instead of xx=xx/w... you will use the origin as the center of projection