www.pudn.com > SimulationOfWater.rar > surface.cpp, change:2004-03-19,size:26009b
#include "surface.h"
#include <stdio.h>
#include "tools.h"
/*--------------------------------------------------------------------------------------------------------------
surface
constructor
--------------------------------------------------------------------------------------------------------------*/
surface::surface(const D3DXVECTOR3 *pos,
const D3DXVECTOR3 *n,
int size_x,
int size_y,
const LPDIRECT3DDEVICE9 device,
camera *renderingcamera,
parameterhandler *prm)
{
initialized = true;
D3DXPlaneFromPointNormal( &plane, pos, n);
D3DXVec3Normalize(&(this->normal), n);
// calculate the u and v-vectors
// take one of two vectors (the one further away from the normal) and force it into the plane
D3DXVECTOR3 x;
if(fabs( D3DXVec3Dot(&D3DXVECTOR3(1,0,0),&normal)) fabs(D3DXVec3Dot(&D3DXVECTOR3(0,0,1),&normal))){
x = D3DXVECTOR3(1,0,0);
} else {
x = D3DXVECTOR3(0,0,1);
}
u = x - normal*D3DXVec3Dot(&normal,&x);
D3DXVec3Normalize(&u,&u);
// get v (cross)
D3DXVec3Cross(&v,&u,&normal);
this->prm = prm;
this->pos = *pos;
this->device = device;
this->gridsize_x = size_x+1;
this->gridsize_y = size_y+1;
this->rendering_camera = renderingcamera;
this->projecting_camera = NULL;
this->observing_camera = NULL;
this->rendermode = RM_SOLID;
this->boxfilter = false;
set_displacement_amplitude(0.0f);
if (!initbuffers()) initialized = false; // init vertex & indexbuffers
software_brus = new software_noisemaker(gridsize_x,gridsize_y, prm, device);
/*if( FAILED( D3DXCreateTextureFromFile( device, "textures/dirt_crackeddrysoft_df_.dds", &surf_texture ) ) )
{
MessageBox(NULL, "Could not find texturehonk", "Textures.exe", MB_OK);
initialized = false;
}
*/
if( FAILED( D3DXCreateTextureFromFile( device, "textures/fresnel_water_linear.bmp", &surf_fresnel ) ) )
{
MessageBox(NULL, "Could not find fresnelmap", "Textures.exe", MB_OK);
initialized = false;
}
if( FAILED( D3DXCreateTextureFromFile( device, "textures/reflection_underwater.bmp", &underwater_fresnel ) ) )
{
MessageBox(NULL, "Could not find underwater fresnelmap", "Textures.exe", MB_OK);
initialized = false;
}
if( FAILED( D3DXCreateTextureFromFile( device, "textures/XZnoise.png", &noise2D ) ) )
{
MessageBox(NULL, "Could not find noise texture", "Textures.exe", MB_OK);
initialized = false;
}
//if( FAILED( D3DXCreateCubeTextureFromFile( device, "textures/evening.dds", &sky_cubemap ) ) )
if( FAILED( D3DXCreateCubeTextureFromFile( device, "textures/cubemap-evul.dds", &sky_cubemap ) ) )
{
MessageBox(NULL, "Could not find cubemap", "asdf", MB_OK);
initialized = false;
}
device->CreateTexture(reflrefrdetail,reflrefrdetail,1,D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf_reflection,NULL);
device->CreateTexture(reflrefrdetail,reflrefrdetail,1,D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf_refraction,NULL);
device->CreateDepthStencilSurface( reflrefrdetail, reflrefrdetail,D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, true, &depthstencil, NULL );
if(!initialized)
MessageBox(NULL, "Something went wrong in initialization of the class surface", "surface", MB_OK);
this->LoadEffect();
}
void surface::LoadEffect(){
//HRESULT hr;
//TCHAR sz[512];
//DXUtil_FindMediaFileCb(sz, sizeof(sz), _T("stuff.fx"));
//LPD3DXEFFECT l_pEffect;
char *errortext;
LPD3DXBUFFER errors;
D3DXHANDLE hTechnique;
// same for skybox.fx
D3DXCreateEffectFromFile(device, "skybox.fx",
NULL, NULL, 0, NULL, &skybox_effect, &errors );
if (errors != NULL){
errortext = (char*) errors->GetBufferPointer();
MessageBox(NULL, errortext, "Textures.exe", MB_OK);
}
skybox_effect->FindNextValidTechnique(NULL, &hTechnique);
skybox_effect->SetTechnique(hTechnique);
// same for surf_software_effect
#ifdef CPU_NORMALS
D3DXCreateEffectFromFile(device, "water_soft.fx",
NULL, NULL, 0, NULL, &surf_software_effect, &errors );
#else
D3DXCreateEffectFromFile(device, "water_R300.fx",
NULL, NULL, 0, NULL, &surf_software_effect, &errors );
#endif
if (errors != NULL){
errortext = (char*) errors->GetBufferPointer();
MessageBox(NULL, errortext, "Textures.exe", MB_OK);
}
surf_software_effect->FindNextValidTechnique(NULL, &hTechnique);
surf_software_effect->SetTechnique(hTechnique);
/*
// underwater_software_effect
D3DXCreateEffectFromFile(device, "underwater_soft.fx",
NULL, NULL, 0, NULL, &underwater_software_effect, &errors );
if (errors != NULL){
errortext = (char*) errors->GetBufferPointer();
MessageBox(NULL, errortext, "Textures.exe", MB_OK);
}
underwater_software_effect->FindNextValidTechnique(NULL, &hTechnique);
underwater_software_effect->SetTechnique(hTechnique);*/
}
/*--------------------------------------------------------------------------------------------------------------
initbuffers
prepare the vertex and indexbuffer with a uniform grid (dependant on the size parameter)
--------------------------------------------------------------------------------------------------------------*/
bool surface::initbuffers(){
SURFACEVERTEX* pdVertices;
// create the vertexbuffer used in the softwaremode (it can be empty as it'll be memcpy-ed to)
if( FAILED( device->CreateVertexBuffer( gridsize_x*gridsize_y*sizeof(SOFTWARESURFACEVERTEX),
D3DUSAGE_WRITEONLY|D3DUSAGE_DYNAMIC, D3DFVF_SOFTWARESURFACEVERTEX,
D3DPOOL_DEFAULT, &surf_software_vertices, NULL ) ) )
{
return false;
}
// create the skybox vertexbuffer
if( FAILED( device->CreateVertexBuffer( skyboxdetail*skyboxdetail*sizeof(SURFACEVERTEX),
D3DUSAGE_WRITEONLY, D3DFVF_SURFACEVERTEX,
D3DPOOL_DEFAULT, &skybox_vertices, NULL ) ) )
{
return false;
}
if( FAILED( skybox_vertices->Lock( 0, 0, (void**)&pdVertices, 0 ) ) )
return false;
{
for(int v=0; v<skyboxdetail; v++){
for(int u=0; u<skyboxdetail; u++){
float al = -2*3.14159265*((float)u/(skyboxdetail-1.0f)),
th = 0.6*3.14159265*((float)v/(skyboxdetail-1.0f));
pdVertices[v*skyboxdetail+u].position.x = sin(th)*sin(al);
pdVertices[v*skyboxdetail+u].position.y = cos(th);
pdVertices[v*skyboxdetail+u].position.z = sin(th)*cos(al);
pdVertices[v*skyboxdetail+u].displacement = 0.0f;
}
}
}
skybox_vertices->Unlock();
// create/fill the indexbuffer
if( FAILED( device->CreateIndexBuffer( sizeof(unsigned int) * 6 * (gridsize_x-1)*(gridsize_y-1),
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX32, D3DPOOL_DEFAULT,&surf_indicies,NULL)))
{
return false;
}
unsigned int *indexbuffer;
if( FAILED( surf_indicies->Lock(0,0,(void**)&indexbuffer,0 ) ) )
return false;
int i = 0;
{
for(int v=0; v<gridsize_y-1; v++){
for(int u=0; u<gridsize_x-1; u++){
// face 1 |/
indexbuffer[i++] = v*gridsize_x + u;
indexbuffer[i++] = v*gridsize_x + u + 1;
indexbuffer[i++] = (v+1)*gridsize_x + u;
// face 2 /|
indexbuffer[i++] = (v+1)*gridsize_x + u;
indexbuffer[i++] = v*gridsize_x + u + 1;
indexbuffer[i++] = (v+1)*gridsize_x + u + 1;
}
}
}
surf_indicies->Unlock();
// create/fill the indexbuffer
if( FAILED( device->CreateIndexBuffer( sizeof(unsigned int) * 6 * (skyboxdetail-1)*(skyboxdetail-1),
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX32, D3DPOOL_DEFAULT,&skybox_indicies,NULL)))
{
return false;
}
if( FAILED( skybox_indicies->Lock(0,0,(void**)&indexbuffer,0 ) ) )
return false;
i = 0;
{
for(int v=0; v<skyboxdetail-1; v++){
for(int u=0; u<skyboxdetail-1; u++){
// face 1 |/
indexbuffer[i++] = v*skyboxdetail + u;
indexbuffer[i++] = v*skyboxdetail + u + 1;
indexbuffer[i++] = (v+1)*skyboxdetail + u;
// face 2 /|
indexbuffer[i++] = (v+1)*skyboxdetail + u;
indexbuffer[i++] = v*skyboxdetail + u + 1;
indexbuffer[i++] = (v+1)*skyboxdetail + u + 1;
}
}
}
skybox_indicies->Unlock();
return true;
}
bool surface::within_frustum(const D3DXVECTOR3 *pos){
D3DXVECTOR3 test;
D3DXVec3TransformCoord(&test, pos, &(rendering_camera->viewproj));
if((fabs(test.x) 1.00001f)&&(fabs(test.y) 1.00001f)&&(fabs(test.z) 1.00001f))
return true;
return false;
}
float dispmulti(float dist){
return max(0, min(1, dist-1));
}
/*--------------------------------------------------------------------------------------------------------------
render
render surface
--------------------------------------------------------------------------------------------------------------*/
bool surface::prepare(const camera *cam)
{
if(!initialized) return false;
delete observing_camera;
observing_camera = new camera(cam);
this->SetupMatrices(this->observing_camera); // obsolete with vertexshaders
plane_within_frustum = this->getMinMax(&range);
if (plane_within_frustum){
software_brus->render_geometry(&range);
D3DVERTEXBUFFER_DESC pDesc;
SOFTWARESURFACEVERTEX *vertices;
HRESULT hr = surf_software_vertices->GetDesc( &pDesc );
if( FAILED(surf_software_vertices->Lock( 0, 0, (void**) &vertices, D3DLOCK_DISCARD)))
{
MessageBox(NULL, "Could not lock vertexbuffer", "Textures.exe", MB_OK);
}
else
{
int size = pDesc.Size;
memcpy(vertices, software_brus->vertices, size);
surf_software_vertices->Unlock();
}
}
return true;
}
void surface::render_skybox(){
device->SetStreamSource( 0, skybox_vertices, 0, sizeof(SURFACEVERTEX) );
device->SetFVF( D3DFVF_SURFACEVERTEX);
device->SetIndices(skybox_indicies);
skybox_effect->Begin(NULL,NULL);
skybox_effect->Pass(0);
// build the 'fake' viweproj with the distance vector set to 0,0,0
D3DXMATRIXA16 fvproj(observing_camera->view);
fvproj._41 = 0;
fvproj._42 = 0;
fvproj._43 = 0;
fvproj = fvproj * observing_camera->proj;
skybox_effect->SetMatrix("mViewProj",&fvproj);
skybox_effect->SetMatrix("mInvViewProj",&(observing_camera->invviewproj));
skybox_effect->SetMatrix("mInvView",&(observing_camera->invview));
skybox_effect->SetFloat("sun_alfa", prm->params[p_fSunPosAlpha].fData);
skybox_effect->SetFloat("sun_theta", prm->params[p_fSunPosTheta].fData);
skybox_effect->SetFloat("sun_shininess", 4*prm->params[p_fSunShininess].fData);
skybox_effect->SetFloat("sun_strength", prm->params[p_fSunStrength].fData);
skybox_effect->SetVector("view_position", &D3DXVECTOR4(observing_camera->position.x,observing_camera->position.y,observing_camera->position.z,1));
skybox_effect->SetTexture("EnvironmentMap",sky_cubemap);
device->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, skyboxdetail*skyboxdetail, 0, 2*(skyboxdetail-1)*(skyboxdetail-1) );
skybox_effect->End();
}
void surface::render_cutter()
{
if (plane_within_frustum)
{
//device->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
device->SetStreamSource( 0, surf_software_vertices, 0, sizeof(SOFTWARESURFACEVERTEX) );
device->SetFVF( D3DFVF_SOFTWARESURFACEVERTEX);
device->SetIndices(surf_indicies);
device->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, gridsize_x*gridsize_y, 0, 2*(gridsize_x-1)*(gridsize_y-1) );
}
}
bool surface::render(){
if (plane_within_frustum)
{
{
HRESULT hr;
/*// underwater pass
device->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
device->SetStreamSource( 0, surf_software_vertices, 0, sizeof(SOFTWARESURFACEVERTEX) );
device->SetFVF( D3DFVF_SOFTWARESURFACEVERTEX);
device->SetIndices(surf_indicies);
underwater_software_effect->Begin(NULL,NULL);
underwater_software_effect->Pass(0);
underwater_software_effect->SetMatrix("mViewProj",&(observing_camera->viewproj));
underwater_software_effect->SetFloat("sun_alfa", prm->params[p_fSunPosAlpha].fData);
underwater_software_effect->SetFloat("sun_theta", prm->params[p_fSunPosTheta].fData);
underwater_software_effect->SetFloat("sun_shininess", prm->params[p_fSunShininess].fData);
underwater_software_effect->SetFloat("sun_strength", prm->params[p_fSunStrength].fData);
underwater_software_effect->SetVector("watercolour", &D3DXVECTOR4(prm->params[p_fWaterColourR].fData,prm->params[p_fWaterColourG].fData,prm->params[p_fWaterColourB].fData,1));
underwater_software_effect->SetFloat("LODbias", prm->get_float(p_fLODbias) );
underwater_software_effect->SetVector("view_position", &D3DXVECTOR4(observing_camera->position.x,observing_camera->position.y,observing_camera->position.z,1));
underwater_software_effect->SetTexture("EnvironmentMap",sky_cubemap);
underwater_software_effect->SetTexture("FresnelMap",underwater_fresnel);
underwater_software_effect->SetTexture("Normalmap",software_brus->normalmap);
if ( prm->params[p_bAsPoints].bData )
device->DrawPrimitive( D3DPT_POINTLIST, 0, gridsize_x*gridsize_y );
else
device->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, gridsize_x*gridsize_y, 0, 2*(gridsize_x-1)*(gridsize_y-1) );
underwater_software_effect->End();
*/
// above water pass
device->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
device->SetStreamSource( 0, surf_software_vertices, 0, sizeof(SOFTWARESURFACEVERTEX) );
device->SetFVF( D3DFVF_SOFTWARESURFACEVERTEX);
device->SetIndices(surf_indicies);
#ifndef CPU_NORMALS
software_brus->generate_normalmap();
#endif
device->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
surf_software_effect->Begin(NULL,NULL);
surf_software_effect->Pass(0);
surf_software_effect->SetMatrix("mViewProj",&(observing_camera->viewproj));
surf_software_effect->SetMatrix("mView",&(observing_camera->view));
/*surf_software_effect->SetFloat("sun_alfa", prm->params[p_fSunPosAlpha].fData);
surf_software_effect->SetFloat("sun_theta", prm->params[p_fSunPosTheta].fData);*/
float sa = prm->params[p_fSunPosAlpha].fData, st = prm->params[p_fSunPosTheta].fData;
surf_software_effect->SetVector("sun_vec",&D3DXVECTOR4(cos(st)*sin(sa), sin(st), cos(st)*cos(sa),0));
surf_software_effect->SetFloat("sun_shininess", prm->params[p_fSunShininess].fData);
surf_software_effect->SetFloat("sun_strength", prm->params[p_fSunStrength].fData);
surf_software_effect->SetFloat("reflrefr_offset", prm->params[p_bReflRefrStrength].fData);
surf_software_effect->SetBool("diffuseSkyRef", prm->params[p_bDiffuseRefl].bData);
surf_software_effect->SetVector("watercolour", &D3DXVECTOR4(prm->params[p_fWaterColourR].fData,prm->params[p_fWaterColourG].fData,prm->params[p_fWaterColourB].fData,1));
surf_software_effect->SetFloat("LODbias", prm->get_float(p_fLODbias) );
surf_software_effect->SetVector("view_position", &D3DXVECTOR4(observing_camera->position.x,observing_camera->position.y,observing_camera->position.z,1));
surf_software_effect->SetTexture("EnvironmentMap",sky_cubemap);
surf_software_effect->SetTexture("FresnelMap",surf_fresnel);
#ifndef CPU_NORMALS
surf_software_effect->SetTexture("Heightmap",software_brus->heightmap);
surf_software_effect->SetTexture("Normalmap",software_brus->normalmap);
#endif
surf_software_effect->SetTexture("Refractionmap",surf_refraction);
surf_software_effect->SetTexture("Reflectionmap",surf_reflection);
//surf_software_effect->SetTexture("noiseXZ",noise2D);
if ( prm->params[p_bAsPoints].bData )
device->DrawPrimitive( D3DPT_POINTLIST, 0, gridsize_x*gridsize_y );
else
device->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, gridsize_x*gridsize_y, 0, 2*(gridsize_x-1)*(gridsize_y-1) );
surf_software_effect->End();
}
}
#ifndef CPU_NORMALS
if (prm->params[p_bDisplayTargets].bData)
{
debug_render_quad(device, software_brus->packed_noise_texture[0], 0);
debug_render_quad(device, software_brus->packed_noise_texture[1], 1);
debug_render_quad(device, software_brus->heightmap, 2);
debug_render_quad(device, software_brus->normalmap, 3);
debug_render_quad(device, surf_refraction, 4);
debug_render_quad(device, surf_reflection, 5);
}
#endif
return true;
}
/*--------------------------------------------------------------------------------------------------------------
getMinMax
get the matrix that defines the minimum rectangle in which the frustum is located
--------------------------------------------------------------------------------------------------------------*/
bool surface::getMinMax(D3DXMATRIXA16 *range){
set_displacement_amplitude(prm->params[p_fStrength].fData);
float x_min,y_min,x_max,y_max;
D3DXVECTOR3 frustum[8],proj_points[24]; // frustum to check the camera against
int n_points=0;
int cube[] = { 0,1, 0,2, 2,3, 1,3,
0,4, 2,6, 3,7, 1,5,
4,6, 4,5, 5,7, 6,7}; // which frustum points are connected together?
// transform frustum points to worldspace (should be done to the rendering_camera because it's the interesting one)
D3DXVec3TransformCoord(&frustum[0], &D3DXVECTOR3(-1,-1,-1), &(rendering_camera->invviewproj));
D3DXVec3TransformCoord(&frustum[1], &D3DXVECTOR3(+1,-1,-1), &(rendering_camera->invviewproj));
D3DXVec3TransformCoord(&frustum[2], &D3DXVECTOR3(-1,+1,-1), &(rendering_camera->invviewproj));
D3DXVec3TransformCoord(&frustum[3], &D3DXVECTOR3(+1,+1,-1), &(rendering_camera->invviewproj));
D3DXVec3TransformCoord(&frustum[4], &D3DXVECTOR3(-1,-1,+1), &(rendering_camera->invviewproj));
D3DXVec3TransformCoord(&frustum[5], &D3DXVECTOR3(+1,-1,+1), &(rendering_camera->invviewproj));
D3DXVec3TransformCoord(&frustum[6], &D3DXVECTOR3(-1,+1,+1), &(rendering_camera->invviewproj));
D3DXVec3TransformCoord(&frustum[7], &D3DXVECTOR3(+1,+1,+1), &(rendering_camera->invviewproj));
// check intersections with upper_bound and lower_bound
for(int i=0; i<12; i++){
int src=cube[i*2], dst=cube[i*2+1];
if ((upper_bound.a*frustum[src].x + upper_bound.b*frustum[src].y + upper_bound.c*frustum[src].z + upper_bound.d*1)/(upper_bound.a*frustum[dst].x + upper_bound.b*frustum[dst].y + upper_bound.c*frustum[dst].z + upper_bound.d*1)<0){
D3DXPlaneIntersectLine( &proj_points[n_points++], &upper_bound, &frustum[src], &frustum[dst]);
}
if ((lower_bound.a*frustum[src].x + lower_bound.b*frustum[src].y + lower_bound.c*frustum[src].z + lower_bound.d*1)/(lower_bound.a*frustum[dst].x + lower_bound.b*frustum[dst].y + lower_bound.c*frustum[dst].z + lower_bound.d*1)<0){
D3DXPlaneIntersectLine( &proj_points[n_points++], &lower_bound, &frustum[src], &frustum[dst]);
}
}
// check if any of the frustums vertices lie between the upper_bound and lower_bound planes
{
for(int i=0; i<8; i++){
if ((upper_bound.a*frustum[i].x + upper_bound.b*frustum[i].y + upper_bound.c*frustum[i].z + upper_bound.d*1)/(lower_bound.a*frustum[i].x + lower_bound.b*frustum[i].y + lower_bound.c*frustum[i].z + lower_bound.d*1)<0){
proj_points[n_points++] = frustum[i];
}
}
}
//
// create the camera the grid will be projected from
//
delete projecting_camera;
projecting_camera = new camera(rendering_camera);
// make sure the camera isn't too close to the plane
float height_in_plane = (lower_bound.a*projecting_camera->position.x +
lower_bound.b*projecting_camera->position.y +
lower_bound.c*projecting_camera->position.z);
bool keep_it_simple = false;
bool underwater=false;
if (height_in_plane 0.0f) underwater = true;
if(keep_it_simple)
{
projecting_camera->forward = rendering_camera->forward;
projecting_camera->update_lookat();
}
else
{
D3DXVECTOR3 aimpoint, aimpoint2;
if (height_in_plane (prm->params[p_fStrength].fData+prm->get_float(p_fElevation)))
{
if(underwater)
projecting_camera->position += D3DXVECTOR3(lower_bound.a,lower_bound.b,lower_bound.c)*(prm->params[p_fStrength].fData + prm->get_float(p_fElevation) - 2*height_in_plane);
else
projecting_camera->position += D3DXVECTOR3(lower_bound.a,lower_bound.b,lower_bound.c)*(prm->params[p_fStrength].fData + prm->get_float(p_fElevation) - height_in_plane);
}
// aim the projector at the point where the camera view-vector intersects the plane
// if the camera is aimed away from the plane, mirror it's view-vector against the plane
if( (D3DXPlaneDotNormal(&plane, &(rendering_camera->forward)) 0.0f) log_xor (D3DXPlaneDotCoord(&plane, &(rendering_camera->position)) 0.0f ) )
{
D3DXPlaneIntersectLine( &aimpoint, &plane, &(rendering_camera->position), &(rendering_camera->position + rendering_camera->forward) );
}
else
{
D3DXVECTOR3 flipped;
flipped = rendering_camera->forward - 2*normal*D3DXVec3Dot(&(rendering_camera->forward),&normal);
D3DXPlaneIntersectLine( &aimpoint, &plane, &(rendering_camera->position), &(rendering_camera->position + flipped) );
}
// force the point the camera is looking at in a plane, and have the projector look at it
// works well against horizon, even when camera is looking upwards
// doesn't work straight down/up
float af = fabs(D3DXPlaneDotNormal(&plane, &(rendering_camera->forward)));
//af = 1 - (1-af)*(1-af)*(1-af)*(1-af)*(1-af);
//aimpoint2 = (rendering_camera->position + rendering_camera->zfar * rendering_camera->forward);
aimpoint2 = (rendering_camera->position + 10.0f * rendering_camera->forward);
aimpoint2 = aimpoint2 - normal*D3DXVec3Dot(&aimpoint2,&normal);
// fade between aimpoint & aimpoint2 depending on view angle
aimpoint = aimpoint*af + aimpoint2*(1.0f-af);
//aimpoint = aimpoint2;
projecting_camera->forward = aimpoint-projecting_camera->position;
projecting_camera->update_lookat();
}
sprintf( debugdata, "n_points %i\n",n_points);
{
for(int i=0; i<n_points; i++){
// project the point onto the surface plane
proj_points[i] = proj_points[i] - normal*D3DXVec3Dot(&proj_points[i],&normal);
}
}
{
for(int i=0; i<n_points; i++){
D3DXVec3TransformCoord( &proj_points[i], &proj_points[i], &(projecting_camera->view));
sprintf( debugdata, "%s%f %f %f\n",debugdata,proj_points[i].x,proj_points[i].y,proj_points[i].z);
D3DXVec3TransformCoord( &proj_points[i], &proj_points[i], &(projecting_camera->proj));
}
}
// debughonk
/* for(int i=0; i<n_points; i++){
sprintf( debugdata, "%s%f %f %f\n",debugdata,proj_points[i].x,proj_points[i].y,proj_points[i].z);
}*/
// get max/min x & y-values to determine how big the "projection window" must be
if (n_points > 0){
x_min = proj_points[0].x;
x_max = proj_points[0].x;
y_min = proj_points[0].y;
y_max = proj_points[0].y;
for(int i=1; i<n_points; i++){
if (proj_points[i].x > x_max) x_max = proj_points[i].x;
if (proj_points[i].x x_min) x_min = proj_points[i].x;
if (proj_points[i].y > y_max) y_max = proj_points[i].y;
if (proj_points[i].y y_min) y_min = proj_points[i].y;
}
sprintf( debugdata, "%sx = [%f..%f] y = [%f..%f]\n",debugdata,x_min,x_max,y_min,y_max);
sprintf( debugdata, "%sheight_in_plane: %f\n",debugdata,height_in_plane);
//sprintf( debugdata, "%slimit_y_upper = %f\n",debugdata,limit_y_upper);
// sprintf( debugdata, "%sy1 = [%f] y2 = [%f]\n",debugdata,y1,y2);
// build the packing matrix that spreads the grid across the "projection window"
D3DXMATRIXA16 pack( x_max-x_min, 0, 0, x_min,
0, y_max-y_min, 0, y_min,
0, 0, 1, 0,
0, 0, 0, 1);
D3DXMatrixTranspose(&pack,&pack);
*range = pack*projecting_camera->invviewproj;
return true;
}
return false;
}
/*--------------------------------------------------------------------------------------------------------------
~surface
destructor
--------------------------------------------------------------------------------------------------------------*/
surface::~surface(){
#ifdef inc_hwpath
this->surf_indicies->Release();
this->surf_vertices->Release();
#endif
this->skybox_indicies->Release();
}
/*--------------------------------------------------------------------------------------------------------------
SetupMatrices
sets the matrices according to the camera
--------------------------------------------------------------------------------------------------------------*/
void surface::SetupMatrices(const camera *camera_view)
{
D3DXMATRIXA16 matWorld,matProj;
D3DXMatrixIdentity(&matWorld);
device->SetTransform( D3DTS_WORLD, &matWorld );
device->SetTransform( D3DTS_VIEW, &(camera_view->view) );
device->SetTransform( D3DTS_PROJECTION, &(camera_view->proj) );
}
void surface::set_grid_size(int size_x,
int size_y)
{
this->gridsize_x = size_x+1;
this->gridsize_y = size_y+1;
this->surf_indicies->Release();
this->surf_software_vertices->Release();
this->skybox_indicies->Release();
this->skybox_vertices->Release();
this->initbuffers();
software_brus->resize(gridsize_x, gridsize_y);
}
void surface::set_render_mode(int rendermode)
{
this->rendermode = rendermode;
}
void surface::set_displacement_amplitude(float amplitude){
D3DXPlaneFromPointNormal( &(this->upper_bound), &(this->pos + amplitude * this->normal), &(this->normal));
D3DXPlaneFromPointNormal( &(this->lower_bound), &(this->pos - amplitude * this->normal), &(this->normal));
}
float surface::get_height_at( float x, float z )
{
if (software_brus)
return software_brus->get_height_at(x,z);
return 0.0f;
}
void surface::calc_efficiency()
{
efficiency = 0;
for(int i=0; i<(gridsize_x*gridsize_y); i++)
{
D3DXVECTOR3 pos;
pos.x = software_brus->vertices[i].x;
pos.y = software_brus->vertices[i].y;
pos.z = software_brus->vertices[i].z;
if (this->within_frustum(&pos))
efficiency += 1.0f;
}
efficiency /= gridsize_x*gridsize_y;
}