|
Model maximum fit to screen
#290783
09/21/09 12:29
09/21/09 12:29
|
Joined: Nov 2007
Posts: 1,143 United Kingdom
DJBMASTER
OP
Serious User
|
OP
Serious User
Joined: Nov 2007
Posts: 1,143
United Kingdom
|
Hi, i'm writing a little app that takes a screenshot of a model, so it can be used as a thumbnail in my level editor.
Of course, models have different sizes but i'm trying to fill as much as the screen as a i can.
I want to use a 256 x 256 thumbnail so i've set screen_size.x/y to 256.
What i need to know is how to make the model fit as much as the window as possible, like move it closer/scale it as much as possible to so it fits into my 256 x 256 area. Is there like an algorithm i can apply? Thanks, DJB.
Last edited by DJBMASTER; 09/21/09 12:31.
|
|
|
Re: Model maximum fit to screen
[Re: DJBMASTER]
#290787
09/21/09 12:35
09/21/09 12:35
|
Joined: Oct 2007
Posts: 5,210 İstanbul, Turkey
Quad
Senior Expert
|
Senior Expert
Joined: Oct 2007
Posts: 5,210
İstanbul, Turkey
|
check viewer.c in include folder for that-there is an example. that is the script that runs when you preview model from MED. also, you dont need to have a 256x256 screen ive written a function for capturing a spesific region long ago, here:
#include <acknex.h>
#include <d3d9.h>
#define D3DXIFF_BMP 0
#define D3DXIFF_JPG 1
#define D3DXIFF_TGA 2
#define D3DXIFF_PNG 3
#define D3DXIFF_DDS 4
#define D3DXIFF_PPM 5
#define D3DXIFF_DIB 6
#define D3DXIFF_HDR 7
#define D3DXIFF_PFM 8
#define D3DXIFF_FORCE_DWORD 0x7fffffff
#define D3DBACKBUFFER_TYPE_MONO 0
#define D3DBACKBUFFER_TYPE_LEFT 1
#define D3DBACKBUFFER_TYPE_RIGHT 2
#define D3DBACKBUFFER_TYPE_FORCE_DWORD 0x7fffffff
long get_screenshot(int left,int right, int top, int bottom, STRING* filename)
{
RECT ScreenRect;
HRESULT hResult;
LPDIRECT3DSURFACE9 pBackBuffer;
LPDIRECT3DDEVICE9 device = (LPDIRECT3DDEVICE9)draw_begin();
//RECT das abgelichtet wird =)
ScreenRect.left = left;
ScreenRect.right = right;
ScreenRect.top = top;
ScreenRect.bottom = bottom;
var border_wait_time = 0;
while(border_wait_time < 50){
draw_line(vector(left,top,0), vector(0,0,255), 100);
draw_line(vector(right,top,0), vector(0,0,255), 100);
draw_line(vector(right,bottom,0), vector(0,0,255), 100);
draw_line(vector(left,bottom,0), vector(0,0,255), 100);
border_wait_time+=10*time_step;
wait(1);
}
hResult = device->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&pBackBuffer);
hResult = D3DXSaveSurfaceToFile(_chr(filename),D3DXIFF_PNG,pBackBuffer,NULL,&ScreenRect);
return(1);
}
3333333333
|
|
|
Re: Model maximum fit to screen
[Re: Quad]
#290794
09/21/09 14:09
09/21/09 14:09
|
Joined: Jan 2007
Posts: 1,619 Germany
Scorpion
Serious User
|
Serious User
Joined: Jan 2007
Posts: 1,619
Germany
|
this works only for models with a rectangular bounding box, but to support irregular ones, just calculate the following steps for y and z and use the bigger distance of both. first we want to get the distance from the camera to the front face of the bounding box. To do this we are using a little bit of algebra on the shown triangle: the tangent of half the camera.arc gives you half the size of the opposite leg, if the the adjacent leg is 1 to get the size of the opposite leg for an arbitrary length, we just have to multiply it with it.
x = dist*tan(camera.arc/2)
now we just have to transpose this formula to get the distance:
dist = x/tan(camera.arc/2)
in our case x ist half the modelsize Now there is one last step we have to take: add the distance from the face to the origin to it. The code (didn't test it, so if it doesn't work find my mistakes =P) should be something like this:
float modelSize = (my.max_y-my.min_y)*0.5;
camDist = modelSize/tanv(camera.arc*0.5);
camDist += my.max_x;
vec_set(my.x, vector(camDist, 0, 0));
vec_rotate(my.x, camera.pan);
vec_add(my.x, camera.x);
vec_set(my.pan, camera.pan);
vec_inverse(my.pan);(
Maybe it's a little clearer now?^^ Scorpion edit: of course you can also change the scale of the model instead of moving it to the right position. It's your choice.
|
|
|
Re: Model maximum fit to screen
[Re: Quad]
#290795
09/21/09 14:10
09/21/09 14:10
|
Joined: Nov 2007
Posts: 1,143 United Kingdom
DJBMASTER
OP
Serious User
|
OP
Serious User
Joined: Nov 2007
Posts: 1,143
United Kingdom
|
Thanks, but file_for_screen does all that i need at the moment.
The method in viewer.c does work but its not brilliantly accurate, because i just tested with different models and some weren't centered correctly.
Is there a way to measure the number of pixels of say the height and width of a model, so then i can keep scale the model until the number of pixels is greater than the screen area.
Last edited by DJBMASTER; 09/21/09 14:11.
|
|
|
Re: Model maximum fit to screen
[Re: DJBMASTER]
#290856
09/21/09 20:36
09/21/09 20:36
|
Joined: Jan 2007
Posts: 1,619 Germany
Scorpion
Serious User
|
Serious User
Joined: Jan 2007
Posts: 1,619
Germany
|
okay, i confused angles with directional vectors in case of vec_inverse... now it works however. Another restriction is that the origin must be in the middle of the model, else it will be offset. But with a little bit easy math you can also fix that up if needed. oh yeah..the code^^ and the best: it works!
#include <acknex.h>
#include <default.c>
ENTITY* centerEnt;
void on_c_event(){
float aspect = screen_size.y/screen_size.x;
float modelSizeY = (centerEnt.max_y-centerEnt.min_y)*0.5;
float modelSizeZ = (centerEnt.max_z-centerEnt.min_z)*0.5;
float distY = modelSizeY/tanv(camera.arc*0.5);
float distZ = modelSizeZ/tanv(camera.arc*aspect*0.5);
float camDist = maxv(distY, distZ) + centerEnt.max_x;
vec_set(centerEnt.x, vector(camDist, 0, 0));
vec_rotate(centerEnt.x, camera.pan);
vec_add(centerEnt.x, camera.x);
vec_for_angle(centerEnt.pan, camera.pan);
vec_inverse(centerEnt.pan);
vec_to_angle(centerEnt.pan, centerEnt.pan);
}
void main(){
level_load(NULL);
centerEnt = ent_create(CUBE_MDL, nullvector, NULL);
wait(1);
c_setminmax(centerEnt);
}
PS: I don't know why there is a little space on the sides. afaics it's not the precision of float, but I can't find a quick explaination...whatever should be enough for a screenshot
|
|
|
|