/*
===========================================================================
ARX FATALIS GPL Source Code
Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company.
This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code').
Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code. If not, see
.
In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these
additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx
Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o
ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include
#include "danae.h"
#include "ARX_carte.h"
#include "ARX_levels.h"
#include "EERIEUtil.h"
#include "EERIETexture.h"
#include "Hermesmain.h"
#include "EERIEDraw.h"
#define _CRTDBG_MAP_ALLOC
#include
extern long FINAL_RELEASE;
extern long CURRENTLEVEL;
int iCreateMap = 0; // used to create mini-map bitmap
C_ARX_Carte *ARXCarte=NULL;
char ThisLevelMap[256];
//#############################################################################################
// Constructeur
//#############################################################################################
C_ARX_Carte::C_ARX_Carte(LPDIRECT3DDEVICE7 d,EERIE_BACKGROUND *bkg,int nbpix,int wrender,int hrender)
{
this->device=d;
this->background=bkg;
this->nbpixels=nbpix;
this->widthrender=wrender;
this->heightrender=hrender;
this->maxx=FLT_MIN;
this->minx=FLT_MAX;
this->maxz=FLT_MIN;
this->minz=FLT_MAX;
for(int j=0;jZsize;j++)
{
for(int i=0;iXsize;i++)
{
EERIE_BKG_INFO *eg=&bkg->Backg[i+j*bkg->Xsize];
for(int lll=0;lllnbpoly;lll++)
{
EERIEPOLY *ep=&eg->polydata[lll];
if(ep->type&POLY_IGNORE) continue;
if(ep->type&POLY_TRANS) continue;
int nb;
if(ep->type&POLY_QUAD) nb=4;
else nb=3;
while(nb--)
{
if(ep->v[nb].sxminx) this->minx=ep->v[nb].sx;
if(ep->v[nb].szminz) this->minz=ep->v[nb].sz;
if(ep->v[nb].sx>this->maxx) this->maxx=ep->v[nb].sx;
if(ep->v[nb].sz>this->maxz) this->maxz=ep->v[nb].sz;
}
}
}
}
this->posx=this->minx;
this->posz=this->minz;
this->width=this->nbpixels*(int)((this->maxx-this->minx)*this->background->Xmul);
this->height=this->nbpixels*(int)((this->maxz-this->minz)*this->background->Zmul);
this->ecx=((float)this->nbpixels)*this->background->Xmul; //1/100
this->ecz=((float)this->nbpixels)*this->background->Zmul;
this->surfacetemp=NULL;
}
//#############################################################################################
// Render de la scene
//#############################################################################################
BOOL C_ARX_Carte::Render(void)
{
if((!this->device)||(!this->background)) return E_FAIL;
CalcFPS();
device->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,0x00000000,1.0f,0L);
if(!danaeApp.DANAEStartRender()) return E_FAIL;
int depx = (int)(this->posx * this->background->Xmul);
if(depx<0) depx=0;
int depz=(int)(this->posz*this->background->Zmul);
if(depz<0) depz=0;
int endx=this->widthrender/this->nbpixels;
int endz=this->heightrender/this->nbpixels;
endx+=depx;
if(endx>this->background->Xsize) endx=this->background->Xsize;
endz+=depz;
if(endz>this->background->Zsize) endz=this->background->Zsize;
float yecran=0.f;
float zsub=((float)depz)*this->background->Zdiv;
for(int j=depz;jbackground->Xdiv;
for(int i=depx;ibackground->Backg[i+j*this->background->Xsize];
for(int lll=0;lllnbpoly;lll++)
{
EERIEPOLY *ep=&eg->polydata[lll];
if (ep)
{
if(ep->type&POLY_IGNORE) continue;
if(ep->type&POLY_TRANS) continue;
int nb;
if(ep->type&POLY_QUAD) nb=4;
else nb=3;
for(int k=0;ktv[k].sx=xecran+(ep->v[k].sx-xsub)*this->ecx;
ep->tv[k].sy=yecran+(ep->v[k].sz-zsub)*this->ecz;
ep->tv[k].rhw=(1.f/ep->v[k].sy);
if (ep->tv[k].rhw<0.f) ep->tv[k].rhw=0.f;
if (ep->tv[k].rhw>1.f) ep->tv[k].rhw=1.f;
ep->tv[k].sz=1.f-ep->tv[k].rhw;
if (ep->tv[k].sz<0.f) ep->tv[k].sz=0.f;
if (ep->tv[k].sz>1.f) ep->tv[k].sz=1.f;
ep->tv[k].color=0xFFFFFFFF;
ep->tv[k].tu=ep->v[k].tu;
ep->tv[k].tv=ep->v[k].tv;
}
if(ep->tex)
device->SetTexture(0,ep->tex->m_pddsSurface);
else
device->SetTexture(0,NULL);
EERIEDRAWPRIM( device, D3DPT_TRIANGLESTRIP,
D3DFVF_TLVERTEX|D3DFVF_DIFFUSE,
ep->tv,
nb,
0, EERIE_NOCOUNT );
}
}
xsub+=this->background->Xdiv;
xecran+=(float)this->nbpixels;
}
zsub+=this->background->Zdiv;
yecran+=(float)this->nbpixels;
}
return S_OK;
}
//#############################################################################################
// Deplace la mapp
//#############################################################################################
void C_ARX_Carte::MoveMap(float newposx,float newposz)
{
this->posx=newposx;
this->posz=newposz;
}
//#############################################################################################
// Inc deplace mapp
//#############################################################################################
void C_ARX_Carte::IncMoveMap(float incx,float incz)
{
this->posx+=incx;
this->posz+=incz;
}
//#############################################################################################
// CreateSurfTemp
//#############################################################################################
BOOL C_ARX_Carte::CreateSurfaceTemp(CD3DFramework7 *framework)
{
if(this->surfacetemp)
{
SAFE_RELEASE(this->surfacetemp);
}
LPDIRECTDRAW7 ddraw=framework->GetDirectDraw();
if(!ddraw) return FALSE;
// Setup the new surface desc
DDSURFACEDESC2 ddsd;
ddsd.dwSize=sizeof(ddsd);
LPDIRECTDRAWSURFACE7 surfacerender=framework->GetRenderSurface();
if(!surfacerender)
{
ddraw->Release();
return FALSE;
}
surfacerender->GetSurfaceDesc(&ddsd);
ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
ddsd.ddsCaps.dwCaps2 = 0L;
ddsd.dwWidth = (this->width+3)&~3;
ddsd.dwHeight = this->height;
// Create a new surface for the texture
HRESULT hr;
if(FAILED(hr=ddraw->CreateSurface(&ddsd,&this->surfacetemp,NULL)))
{
ddraw->Release();
return FALSE;
}
return TRUE;
}
//#############################################################################################
// BltOnSurfTemp
//#############################################################################################
BOOL C_ARX_Carte::BltOnSurfTemp(CD3DFramework7 *framework,int x,int y,int dw,int dh,int largs,int largh)
{
LPDIRECTDRAWSURFACE7 surfacerender;
RECT src,dst;
surfacerender=framework->GetRenderSurface();
if(!surfacerender) return FALSE;
int n=this->nbpixels>>1;
src.left=n;
src.top=n;
src.right=largs+src.left-dw;
src.bottom=largh+src.top-dh;
dst.left=x;
dst.top=y;
dst.right=dst.left+largs-dw;
dst.bottom=dst.top+largh-dh;
if(FAILED(this->surfacetemp->Blt(&dst,surfacerender,&src,DDBLT_WAIT,NULL))) return FALSE;
return TRUE;
}
//#############################################################################################
// BuildMap
//#############################################################################################
BOOL C_ARX_Carte::BuildMap(CD3DFramework7 *framework,char *name)
{
if(!this->CreateSurfaceTemp(framework)) return FALSE;
float oldposx,oldposz;
oldposx=this->posx;
oldposz=this->posz;
this->posx=this->minx;
this->posz=this->minz;
int taillex=(this->widthrender-(this->nbpixels>>1))/this->nbpixels;
taillex--;
float incx=((float)taillex)*100.f;
taillex*=this->nbpixels;
int tailley=(this->heightrender-(this->nbpixels>>1))/this->nbpixels;
tailley--;
float incy=((float)tailley)*100.f;
tailley*=this->nbpixels;
float incyy=0.f;
int nbx=this->width/taillex;
if(this->width%taillex) nbx++;
int nby=this->height/tailley;
if(this->height%tailley) nby++;
int cposy=0;
while(nby--)
{
int nbxx=nbx;
int cposx=0;
int dh=0;
if((cposy+tailley)>this->height) dh=cposy+tailley-this->height;
while(nbxx--)
{
this->Render();
danaeApp.DANAEEndRender();
int dw=0;
if((cposx+taillex)>this->width) dw=cposx+taillex-this->width;
if(!this->BltOnSurfTemp(framework,cposx,cposy,dw,dh,taillex,tailley)) return FALSE;
cposx+=taillex;
this->IncMoveMap(incx,0.f);
}
cposy+=tailley;
this->MoveMap(this->minx,this->minz);
incyy+=incy;
this->IncMoveMap(0.f,incyy);
}
DDSURFACEDESC2 ddsd;
ddsd.dwSize=sizeof(DDSURFACEDESC2);
if(FAILED(this->surfacetemp->Lock(NULL,&ddsd,DDLOCK_READONLY|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT,NULL)))
{
SAFE_RELEASE(this->surfacetemp);
return FALSE;
}
if( (ddsd.ddpfPixelFormat.dwRGBBitCount==4)||
(ddsd.ddpfPixelFormat.dwRGBBitCount==8)||
(ddsd.ddpfPixelFormat.dwRGBBitCount==24) )
{
MessageBox(NULL,"Desktop not in 16 or 32 bits","Map Generation Error!!!",0);
SAFE_RELEASE(this->surfacetemp);
return FALSE;
}
int tailleraw;
if(ddsd.ddpfPixelFormat.dwRGBBitCount==16)
{
tailleraw=(ddsd.lPitch>>1)*ddsd.dwHeight*3;
}
else
{
tailleraw=(ddsd.lPitch>>2)*ddsd.dwHeight*3;
}
//enregistre la mapp
int *mem=(int*)malloc(tailleraw);
unsigned char *memc=(unsigned char *)mem;
if(!mem)
{
SAFE_RELEASE(this->surfacetemp);
return FALSE;
}
//info
BITMAPFILEHEADER bm;
bm.bfType=(('M'<<8)+'B');
bm.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFO)-4+(tailleraw);
bm.bfReserved1=0;
bm.bfReserved2=0;
bm.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFO)-4;
BITMAPINFO bi;
bi.bmiHeader.biSize=sizeof(BITMAPINFO)-4;
bi.bmiHeader.biHeight=ddsd.dwHeight;
bi.bmiHeader.biPlanes=1;
bi.bmiHeader.biBitCount=24;
bi.bmiHeader.biCompression=BI_RGB;
bi.bmiHeader.biSizeImage=tailleraw;
bi.bmiHeader.biXPelsPerMeter=0;
bi.bmiHeader.biYPelsPerMeter=0;
bi.bmiHeader.biClrUsed=0;
bi.bmiHeader.biClrImportant=0;
//crepie
DWORD dwRMask=ddsd.ddpfPixelFormat.dwRBitMask;
DWORD dwGMask=ddsd.ddpfPixelFormat.dwGBitMask;
DWORD dwBMask=ddsd.ddpfPixelFormat.dwBBitMask;
DWORD dwAMask=ddsd.ddpfPixelFormat.dwRGBAlphaBitMask;
DWORD dwRShiftR=0;
DWORD dwGShiftR=0;
DWORD dwBShiftR=0;
DWORD dwAShiftR=0;
DWORD dwRShiftL=8;
DWORD dwGShiftL=8;
DWORD dwBShiftL=8;
DWORD dwAShiftL=8;
DWORD dwMask;
for( dwMask=dwRMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwRShiftR++;
for( ; dwMask && 1; dwMask>>=1 ) dwRShiftL--;
for( dwMask=dwGMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwGShiftR++;
for( ; dwMask && 1; dwMask>>=1 ) dwGShiftL--;
for( dwMask=dwBMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwBShiftR++;
for( ; dwMask && 1; dwMask>>=1 ) dwBShiftL--;
for( dwMask=dwAMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwAShiftR++;
for( ; dwMask && 1; dwMask>>=1 ) dwAShiftL--;
nby=ddsd.dwHeight;
if(ddsd.ddpfPixelFormat.dwRGBBitCount==16)
{
bi.bmiHeader.biWidth=ddsd.lPitch>>1;
short *mems=(short*)ddsd.lpSurface;
while(nby--)
{
nbx=ddsd.lPitch>>1;
while(nbx--)
{
unsigned short col=*mems++;
*memc++=(unsigned char)(((col&dwBMask)>>dwBShiftR)<>dwGShiftR)<>dwRShiftR)<>2;
int *mems=(int*)ddsd.lpSurface;
while(nby--)
{
int nbx=ddsd.lPitch>>2;
while(nbx--)
{
int col=*mems++;
*memc++=(unsigned char)((col&dwBMask)>>dwBShiftR);
*memc++=(unsigned char)((col&dwGMask)>>dwGShiftR);
*memc++=(unsigned char)((col&dwRMask)>>dwRShiftR);
}
}
}
this->surfacetemp->Unlock(NULL);
//sauvegarde
nby=0;
FILE *f;
f=fopen(name,"wb");
fwrite((void*)&bm,1,sizeof(BITMAPFILEHEADER),f);
fwrite((void*)&bi,1,sizeof(BITMAPINFO)-4,f);
fwrite((void*)mem,1,tailleraw,f);
fclose(f);
free((void*)mem);
SAFE_RELEASE(this->surfacetemp);
this->posx=oldposx;
this->posz=oldposz;
return TRUE;
}
//-----------------------------------------------------------------------------
BOOL NeedMapCreation()
{
char name[256];
GetLevelNameByNum(CURRENTLEVEL,name);
sprintf(ThisLevelMap,"%s\\Graph\\Levels\\Level%s\\map.bmp",Project.workingdir,name);
if (PAK_FileExist(ThisLevelMap)) return FALSE;
return TRUE;
}
//***********************************************************************************************
// EDITOR Feature ONLY !!! Creates a minimap to disk
//***********************************************************************************************
void DANAE_Manage_CreateMap()
{
if (FINAL_RELEASE) return;
SETCULL(GDevice,D3DCULL_CCW);
iCreateMap++;
if (iCreateMap==1)
{
ARXCarte=new C_ARX_Carte(danaeApp.m_pFramework->GetD3DDevice(),ACTIVEBKG,4,danaeApp.m_pFramework->m_dwRenderWidth,danaeApp.m_pFramework->m_dwRenderHeight);
}
if (iCreateMap==2)
{
ARXCarte->BuildMap(danaeApp.m_pFramework,ThisLevelMap);
}
if (iCreateMap==3)
{
delete ARXCarte;
ARXCarte=NULL;
iCreateMap=0;
}
}