/*
===========================================================================
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 "arx_c_cinematique.h"
#include "resource.h"
#include "HERMESMain.h"
#include "HERMES_PAK.h"
#include
#define _CRTDBG_MAP_ALLOC
#include
/*-----------------------------------------------------------*/
C_BITMAP TabBitmap[MAX_BITMAP];
int MaxW, MaxH;
int NbBitmap;
BOOL Restore;
/*-----------------------------------------------------------*/
extern char AllTxt[];
extern HWND HwndPere;
extern char DirectoryChoose[];
extern char DirectoryAbs[];
void ClearAbsDirectory(char * pT, char * d);
void AddDirectory(char * pT, char * dir);
/*-----------------------------------------------------------*/
void FreeGrille(C_GRILLE * grille);
void ReajustUV(LPDIRECT3DDEVICE7 device, int id);
/*-----------------------------------------------------------*/
void InitMapLoad(CINEMATIQUE * c)
{
C_BITMAP * tb;
int nb;
MaxW = MAX_WIDTH_AND_HEIGHT;
MaxH = MAX_WIDTH_AND_HEIGHT;
if (MaxW > 256) MaxW = 256;
if (MaxH > 256) MaxH = 256;
tb = TabBitmap;
nb = MAX_BITMAP;
while (nb)
{
memset((void *)tb, 0, sizeof(C_BITMAP));
tb++;
nb--;
}
NbBitmap = 0;
Restore = TRUE;
}
/*-----------------------------------------------------------*/
C_BITMAP * GetFreeBitmap(int * num)
{
C_BITMAP * tb;
int nb;
tb = TabBitmap;
nb = MAX_BITMAP;
while (nb)
{
if (!tb->actif)
{
*num = MAX_BITMAP - nb;
return tb;
}
tb++;
nb--;
}
return NULL;
}
/*-----------------------------------------------------------*/
BOOL DeleteFreeBitmap(int num)
{
C_BITMAP * cb;
cb = &TabBitmap[num];
if (!cb->actif) return FALSE;
DeleteObject(cb->hbitmap);
free((void *)cb->dir);
free((void *)cb->name);
FreeGrille(&cb->grille);
memset((void *)cb, 0, sizeof(C_BITMAP));
NbBitmap--;
return TRUE;
}
/*-----------------------------------------------------------*/
BOOL KillTexture(LPDIRECT3DDEVICE7 device, int num)
{
C_BITMAP * cb;
cb = &TabBitmap[num];
if (!cb->actif) return FALSE;
int nb = cb->grille.nbmat;
while (nb--)
{
D3DTextr_KillTexture(cb->grille.mats[nb].tex);
}
return TRUE;
}
/*-----------------------------------------------------------*/
void DeleteAllBitmap(LPDIRECT3DDEVICE7 device)
{
int nb;
nb = MAX_BITMAP;
while (nb)
{
KillTexture(device, MAX_BITMAP - nb);
DeleteFreeBitmap(MAX_BITMAP - nb);
nb--;
}
}
/*-----------------------------------------------------------*/
BOOL AllocGrille(C_GRILLE * grille, int nbx, int nby, float tx, float ty, float dx, float dy, int echelle)
{
grille->echelle = echelle;
int oldnbx = nbx + 1;
int oldnby = nby + 1;
nbx *= echelle;
nby *= echelle;
float olddx = dx;
float olddy = dy;
dx /= ((float)echelle);
dy /= ((float)echelle);
grille->nbuvs = 0;
grille->nbinds = 0;
grille->nbuvsmalloc = grille->nbvertexs = (nbx + 1) * (nby + 1);
grille->nbfaces = (nbx * nby) << 1;
grille->nbindsmalloc = grille->nbfaces;
grille->vertexs = (EERIE_3D *)malloc(grille->nbvertexs * sizeof(EERIE_3D));
grille->uvs = (C_UV *)malloc(grille->nbvertexs * sizeof(C_UV));
grille->inds = (C_IND *)malloc(grille->nbindsmalloc * sizeof(C_IND));
grille->nbmat = 0;
grille->mats = NULL;
//vertexs
grille->nbx = nbx;
grille->nby = nby;
tx *= .5f;
ty *= .5f;
float depx = -tx;
float depy = -ty;
EERIE_3D * v = grille->vertexs;
float olddyy = olddy;
while (oldnby--)
{
nby = echelle;
if (!oldnby) nby = 1;
while (nby--)
{
float olddxx = olddx;
float depxx = depx;
float dxx = dx;
int oldnbxx = oldnbx;
while (oldnbxx--)
{
nbx = echelle;
if (!oldnbxx) nbx = 1;
while (nbx--)
{
v->x = depxx;
v->y = depy;
v->z = 0.f;
depxx += dxx;
v++;
}
olddxx += olddx;
if (olddxx > (tx * 2.f))
{
dxx = tx - depxx;
dxx /= (float)echelle;
}
}
depy += dy;
}
olddyy += olddy;
if (olddyy > (ty * 2.f))
{
dy = ty - depy;
dy /= (float)echelle;
}
}
return TRUE;
}
/*-----------------------------------------------------------*/
int AddMaterial(C_GRILLE * grille, TextureContainer * tex)
{
if (!grille->nbmat)
{
grille->mats = (C_INDEXED *)malloc(sizeof(C_INDEXED));
}
else
{
grille->mats = (C_INDEXED *)realloc(grille->mats, sizeof(C_INDEXED) * (grille->nbmat + 1));
}
int deb;
if (!grille->nbmat) deb = 0;
else
deb = grille->mats[grille->nbmat-1].startind + grille->mats[grille->nbmat-1].nbind;
grille->mats[grille->nbmat].tex = tex;
grille->mats[grille->nbmat].startind = deb;
grille->mats[grille->nbmat].nbind = 0;
return grille->nbmat++;
}
/*-----------------------------------------------------------*/
void FreeGrille(C_GRILLE * grille)
{
if (grille->vertexs)
{
free((void *)grille->vertexs);
grille->vertexs = NULL;
}
if (grille->uvs)
{
free((void *)grille->uvs);
grille->uvs = NULL;
}
if (grille->inds)
{
free((void *)grille->inds);
grille->inds = NULL;
}
if (grille->mats)
{
free((void *)grille->mats);
grille->mats = NULL;
}
}
/*-----------------------------------------------------------*/
void GetIndNumCube(C_GRILLE * grille, int cx, int cy, int * i1, int * i2, int * i3, int * i4)
{
*i1 = cy * (grille->nbx + 1) + cx;
*i2 = *i1 + 1;
*i3 = *i1 + (grille->nbx + 1);
*i4 = *i3 + 1;
}
/*-----------------------------------------------------------*/
void AddPoly(C_GRILLE * grille, int nummat, int i0, int i1, int i2)
{
ARX_CHECK_USHORT(i0);
ARX_CHECK_USHORT(i1);
ARX_CHECK_USHORT(i2);
if (grille->nbinds == grille->nbindsmalloc)
{
grille->nbindsmalloc += 100;
grille->inds = (C_IND *)realloc((void *)grille->inds, grille->nbindsmalloc * sizeof(C_IND));
}
grille->inds[grille->nbinds].i1 = ARX_CLEAN_WARN_CAST_USHORT(i0);
grille->inds[grille->nbinds].i2 = ARX_CLEAN_WARN_CAST_USHORT(i1);
grille->inds[grille->nbinds++].i3 = ARX_CLEAN_WARN_CAST_USHORT(i2);
grille->mats[nummat].nbind += 3;
}
/*-----------------------------------------------------------*/
void AddQuadUVs(C_GRILLE * grille, int depcx, int depcy, int tcx, int tcy, int bitmapposx, int bitmapposy, int bitmapwx, int bitmapwy, TextureContainer * tex)
{
int nummat = AddMaterial(grille, tex);
grille->mats[nummat].bitmapdepx = bitmapposx;
grille->mats[nummat].bitmapdepy = bitmapposy;
grille->mats[nummat].bitmapw = bitmapwx;
grille->mats[nummat].bitmaph = bitmapwy;
grille->mats[nummat].nbvertexs = (tcx + 1) * (tcy + 1);
if ((grille->nbuvs + (4 *(tcx * tcy))) > grille->nbuvsmalloc)
{
grille->nbuvsmalloc += 4 * (tcx * tcy);
grille->uvs = (C_UV *)realloc((void *)grille->uvs, grille->nbuvsmalloc * sizeof(C_UV));
}
float v = 0.f;
float du = 0.999999f / (float)tcx;
float dv = 0.999999f / (float)tcy;
tcy++;
tcx++;
int tcyy = tcy;
int depcyy = depcy;
while (tcyy--)
{
float u = 0.f;
int depcxx = depcx;
int tcxx = tcx;
while (tcxx--)
{
int i0, i1, i2, i3;
GetIndNumCube(grille, depcxx, depcyy, &i0, &i1, &i2, &i3);
//uvs
grille->uvs[grille->nbuvs].indvertex = i0;
grille->uvs[grille->nbuvs].uv.x = u;
grille->uvs[grille->nbuvs++].uv.y = v;
depcxx++;
u += du;
}
depcyy++;
v += dv;
}
tcx--;
tcy--;
while (tcy--)
{
int depcxx = depcx;
int tcxx = tcx;
while (tcxx--)
{
int i0, i1, i2, i3;
GetIndNumCube(grille, depcxx, depcy, &i0, &i1, &i2, &i3);
AddPoly(grille, nummat, i0, i1, i2);
AddPoly(grille, nummat, i1, i2, i3);
depcxx++;
}
depcy++;
}
}
/*-----------------------------------------------------------*/
HBITMAP LoadTargaFile(TCHAR * strPathname)
{
if (!PAK_FileExist(strPathname)) return NULL;
long siz = 0;
unsigned char * dat = (unsigned char *)PAK_FileLoadMalloc(strPathname, &siz);
if (NULL == dat) return NULL;
struct TargaHeader
{
BYTE IDLength;
BYTE ColormapType;
BYTE ImageType;
BYTE ColormapSpecification[5];
WORD XOrigin;
WORD YOrigin;
WORD ImageWidth;
WORD ImageHeight;
BYTE PixelDepth;
BYTE ImageDescriptor;
} tga;
long pos = 0;
memcpy(&tga, dat + pos, sizeof(TargaHeader));
pos += sizeof(TargaHeader);
// Only true color, non-mapped images are supported
if ((0 != tga.ColormapType) ||
(tga.ImageType != 10 && tga.ImageType != 2))
{
free(dat);
return NULL;
}
// Skip the ID field. The first byte of the header is the length of this field
if (tga.IDLength)
pos += tga.IDLength;
DWORD m_dwWidth = tga.ImageWidth;
DWORD m_dwHeight = tga.ImageHeight;
DWORD m_dwBPP = tga.PixelDepth;
DWORD * m_pRGBAData = NULL;
if ((m_dwBPP == 8) ||
(m_dwBPP == 32))
{
free(dat);
return NULL;
}
HDC hdc = CreateCompatibleDC(NULL);
BITMAPINFO bi;
memset((void *)&bi.bmiHeader, 0, sizeof(BITMAPINFOHEADER));
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = m_dwWidth;
bi.bmiHeader.biHeight = m_dwHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
HBITMAP hbitmap = CreateDIBSection(hdc,
&bi,
DIB_RGB_COLORS,
(void **)&m_pRGBAData,
NULL,
0);
if (!hbitmap)
{
free(dat);
return NULL;
}
DeleteDC(hdc);
if (m_pRGBAData == NULL)
{
free(dat);
return NULL;
}
for (DWORD y = 0; y < m_dwHeight; y++)
{
DWORD dwOffset;
if (0 == (tga.ImageDescriptor & 0x0010))
dwOffset = y * m_dwWidth;
else
dwOffset = (m_dwHeight - y - 1) * m_dwWidth;
for (DWORD x = 0; x < m_dwWidth; x)
{
BYTE b;
BYTE g;
BYTE r;
if (m_dwBPP == 16)
{
int a, bb;
a = dat[pos++];
bb = dat[pos++];
SHORT w = (a & 0xFF) | ((bb & 0xFF) << 8);
int iR = (w & 0x7C00) >> 7 ;
int iG = (w & 0x03E0) >> 2 ;
int iB = (w & 0x001F) << 3 ;
ARX_CHECK_BYTE(iR);
ARX_CHECK_BYTE(iG);
ARX_CHECK_BYTE(iB);
r = ARX_CLEAN_WARN_CAST_BYTE(iR);
g = ARX_CLEAN_WARN_CAST_BYTE(iG);
b = ARX_CLEAN_WARN_CAST_BYTE(iB);
}
else
{
b = dat[pos++];
g = dat[pos++];
r = dat[pos++];
}
m_pRGBAData[dwOffset+x] = RGBA_MAKE(r, g, b, 255);
x++;
}
}
free(dat);
return hbitmap;
}
HBITMAP LoadBMPImage(char * strPathname)
{
HBITMAP m_hbmBitmap = NULL;
if (!PAK_FileExist(strPathname)) return NULL;
long siz = 0;
unsigned char * dat = (unsigned char *)PAK_FileLoadMalloc(strPathname, &siz);
if (!dat) return NULL;
BITMAPINFOHEADER sBitmapH = *((BITMAPINFOHEADER *)(dat + sizeof(BITMAPFILEHEADER)));
HDC hHDC = CreateCompatibleDC(NULL);
if (!hHDC)
{
free((void *)dat);
return NULL;
}
char * mem = NULL;
int iUsage;
if (sBitmapH.biBitCount < 8)
{
free((void *)dat);
DeleteDC(hHDC);
return NULL;
}
if (sBitmapH.biBitCount == 8)
{
iUsage = DIB_PAL_COLORS;
}
else
{
iUsage = DIB_RGB_COLORS;
}
sBitmapH.biSize = sizeof(sBitmapH);
m_hbmBitmap = CreateDIBSection(hHDC, (BITMAPINFO *)&sBitmapH, iUsage, (void **)&mem, NULL, 0);
if (SelectObject(hHDC, m_hbmBitmap) == NULL)
{
DeleteDC(hHDC);
return NULL;
}
if (!mem)
{
free((void *)dat);
return NULL;
}
if (!m_hbmBitmap)
{
DeleteDC(hHDC);
free((void *)dat);
return NULL;
}
BITMAPFILEHEADER bh;
if (iUsage == DIB_PAL_COLORS)
{
RGBQUAD col[256];
memcpy(col, dat + sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER), sizeof(RGBQUAD) * 256); //sBitmapH.biSize
SetDIBColorTable(hHDC,
0, // color table index of first entry
256, // number of color table entries
col // array of color table entries
);
}
bh = *((BITMAPFILEHEADER *)(dat));
long size = sBitmapH.biSizeImage;
if (size == 0) size = sBitmapH.biHeight * sBitmapH.biWidth * sBitmapH.biBitCount >> 3;
memcpy(mem, dat + bh.bfOffBits, size);
if (sBitmapH.biCompression != BI_RGB)
{
memset(mem, 64, size);
}
DeleteDC(hHDC);
free(dat);
return m_hbmBitmap;
}
/*-----------------------------------------------------------*/
int CreateAllMapsForBitmap(char * dir, char * name, CINEMATIQUE * c, int n, int pos)
{
int nbx, nby, w, h, num, id;
C_BITMAP * bi;
if (!name || !c) return -1;
if (n >= 0)
{
bi = &TabBitmap[n];
if (!bi->actif) return -1;
bi->load = 0;
if (bi->name) free((void *)bi->name);
if (bi->dir) free((void *)bi->dir);
DeleteObject(bi->hbitmap);
KillTexture(GDevice, n);
FreeGrille(&bi->grille);
NbBitmap--;
h = NULL;
id = n;
}
else
{
bi = GetFreeBitmap(&id);
if (!bi) return -1;
}
if (dir)
{
bi->dir = (char *)malloc(strlen(dir) + 1);
if (!bi->dir) return -1;
strcpy(bi->dir, dir);
}
else dir = NULL;
bi->name = (char *)malloc(strlen(name) + 1);
if (!bi->name)
{
free((void *)bi->dir);
return -1;
}
strcpy(bi->name, name);
strcpy(AllTxt, dir);
strcat(AllTxt, name);
ClearAbsDirectory(AllTxt, "arx\\");
AddDirectory(AllTxt, DirectoryAbs);
SetExt(AllTxt, ".BMP");
if (PAK_FileExist(AllTxt))
{
bi->hbitmap = (HBITMAP)LoadBMPImage(AllTxt);
if (!bi->hbitmap)
{
strcpy(AllTxt, name);
strcat(AllTxt, " --not found--");
h = NULL;
bi->actif = 1;
NbBitmap++;
return id;
}
}
else
{
SetExt(AllTxt, ".TGA");
if (PAK_FileExist(AllTxt))
{
bi->hbitmap = LoadTargaFile(AllTxt);
if (!bi->hbitmap)
{
strcpy(AllTxt, name);
strcat(AllTxt, " --not found--");
h = NULL;
bi->actif = 1;
NbBitmap++;
return id;
}
}
else
{
return -1;
}
}
BITMAP bm;
GetObject(bi->hbitmap, sizeof(BITMAP), &bm);
nbx = (bm.bmWidth / MaxW);
nby = (bm.bmHeight / MaxH);
if (bm.bmWidth % MaxW) nbx++;
if (bm.bmHeight % MaxH) nby++;
bi->w = bm.bmWidth;
bi->h = bm.bmHeight;
bi->load = 1;
bi->nbx = nbx;
bi->nby = nby;
AllocGrille(&bi->grille, nbx, nby, (float)bi->w, (float)bi->h, (float)((bi->w > MaxW) ? MaxW : bi->w), (float)((bi->h > MaxH) ? MaxH : bi->h), 1);
num = 0;
h = bi->h;
float dy = -(float)(bi->h >> 1);
while (nby)
{
float dx = -(float)(bi->w >> 1);
int h2;
if ((h - MaxH) < 0) h2 = h;
else h2 = MaxH;
w = bi->w;
int nbxx = nbx;
while (nbxx)
{
int w2;
if ((w - MaxW) < 0) w2 = w;
else w2 = MaxW;
sprintf(AllTxt, "%s_%4d", name, num);
MakeUpcase(AllTxt);
if (FAILED(D3DTextr_CreateEmptyTexture(AllTxt, w2, h2, 0, D3DTEXTR_NO_MIPMAP, NULL)))
{
sprintf(AllTxt, "Creation de le %d ème texture -> x: %d y %d w: %d h: %d", num, (long)dx, (long)dy, w2, h2);
MessageBox(NULL, AllTxt, "Erreur", 0);
}
TextureContainer * t = FindTexture(AllTxt);
AddQuadUVs(&bi->grille, bi->nbx - nbxx, bi->nby - nby, 1, 1, bi->w - w, bi->h - h, w2, h2, t);
dx += (float)w2;
w -= MaxW;
num++;
nbxx--;
}
dy += (float)h2;
h -= MaxH;
nby--;
}
bi->actif = 1;
NbBitmap++;
if (n >= 0)
{
h = NULL;
}
else
{
h = NULL;
}
c->ActiveTexture(id);
ReajustUV(GDevice, id);
return id;
}
/*-----------------------------------------------------------*/
BOOL ReCreateAllMapsForBitmap(int id, int nmax, CINEMATIQUE * c, LPDIRECT3DDEVICE7 device)
{
int nbx, nby, w, h, num;
C_BITMAP * bi;
if (!c) return FALSE;
bi = &TabBitmap[id];
if (!bi->actif) return FALSE;
FreeGrille(&bi->grille);
nbx = (bi->w / MaxW);
nby = (bi->h / MaxH);
if (bi->w % MaxW) nbx++;
if (bi->h % MaxH) nby++;
bi->nbx = nbx;
bi->nby = nby;
AllocGrille(&bi->grille, nbx, nby, (float)bi->w, (float)bi->h, (float)((bi->w > MaxW) ? MaxW : bi->w), (float)((bi->h > MaxH) ? MaxH : bi->h), nmax);
num = 0;
h = bi->h;
float dy = -(float)(bi->h >> 1);
while (nby)
{
float dx = -(float)(bi->w >> 1);
int h2;
if ((h - MaxH) < 0) h2 = h;
else h2 = MaxH;
w = bi->w;
int nbxx = nbx;
while (nbxx)
{
int w2;
if ((w - MaxW) < 0) w2 = w;
else w2 = MaxW;
sprintf(AllTxt, "%s_%4d", bi->name, num);
MakeUpcase(AllTxt);
TextureContainer * t = FindTexture(AllTxt);
AddQuadUVs(&bi->grille, (bi->nbx - nbxx)*nmax, (bi->nby - nby)*nmax, nmax, nmax, bi->w - w, bi->h - h, w2, h2, t);
dx += (float)w2;
w -= MaxW;
num++;
nbxx--;
}
dy += (float)h2;
h -= MaxH;
nby--;
}
ReajustUV(GDevice, id);
return TRUE;
}
/*-----------------------------------------------------------*/
BOOL CINEMATIQUE::ActiveTexture(int id)
{
TextureContainer * tc;
C_BITMAP * cb;
int nb;
if (id >= MAX_BITMAP) return FALSE;
if (id < 0) return FALSE;
cb = &TabBitmap[id];
if (!cb->actif) return FALSE;
C_INDEXED * mat = cb->grille.mats;
nb = cb->grille.nbmat;
while (nb--)
{
tc = mat->tex;
if (!tc) return FALSE;
if (tc->Restore(GDevice) != S_OK) return FALSE;
if (tc->CopyBitmapToSurface2(cb->hbitmap, mat->bitmapdepx, mat->bitmapdepy, mat->bitmapw, mat->bitmaph, 1) != S_OK) return FALSE;
mat++;
}
return TRUE;
}
/*-----------------------------------------------------------*/
void ReajustUV(LPDIRECT3DDEVICE7 device, int id)
{
TextureContainer * tc;
C_BITMAP * cb;
int nb;
cb = &TabBitmap[id];
if (!cb->actif) return;
C_INDEXED * mat = cb->grille.mats;
C_UV * uvs = cb->grille.uvs;
nb = cb->grille.nbmat;
while (nb--)
{
tc = mat->tex;
if (!tc) return;
int w, h;
w = tc->m_dwWidth;
h = tc->m_dwHeight;
if ((w != (int)mat->bitmapw) ||
(h != (int)mat->bitmaph))
{
float dx = (.999999f * (float)mat->bitmapw) / ((float)w);
float dy = (.999999f * (float)mat->bitmaph) / ((float)h);
int nb2 = mat->nbvertexs;
while (nb2--)
{
uvs->uv.x *= dx;
uvs->uv.y *= dy;
uvs++;
}
}
else
{
uvs += mat->nbvertexs;
}
mat++;
}
}
/*-----------------------------------------------------------*/
BOOL ActiveAllTexture(CINEMATIQUE * c)
{
int nb;
C_BITMAP * cb;
BOOL flag = FALSE;
cb = TabBitmap;
nb = MAX_BITMAP;
while (nb)
{
if (cb->actif)
{
flag |= !c->ActiveTexture(MAX_BITMAP - nb);
}
cb++;
nb--;
}
return !flag;
}