SBSPSS/Utils/GinExp/ExpMaterial.cpp
2001-01-12 22:40:39 +00:00

519 lines
11 KiB
C++

/*=========================================================================
EXPMATERIAL.CPP
Author: Tim Swann @ CLIMAX
Created:
Project:
Purpose:
Copyright (c) 1998 Climax Development Ltd
===========================================================================*/
/*----------------------------------------------------------------------
Includes
-------- */
#include "AsciiExp.h"
#include "string.h"
/* Std Lib
------- */
/* Glib
---- */
/* Local
----- */
/* Graphics
-------- */
/*----------------------------------------------------------------------
Tyepdefs && Defines
------------------- */
/*----------------------------------------------------------------------
Structure defintions
-------------------- */
/*----------------------------------------------------------------------
Positional Vars
--------------- */
/*----------------------------------------------------------------------
Function Prototypes
------------------- */
/*----------------------------------------------------------------------
Vars
---- */
/*----------------------------------------------------------------------
Data
---- */
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void AsciiExp::ExportMaterialList(void)
{
int numMtls = mtlList.Count();
int i = 0;
nbTexs = 0;
nbMats = 0;
if (numMtls)
{
// EXPORT TEXTURE FILE LIST
for (i=0; i<numMtls; i++) DumpMaterial( mtlList.GetMtl(i), i, -1 );
if (nbTexs)
{
WriteChunkHdr( (char*)TEXTURE_ID, 0 );
fwrite( &nbTexs, sizeof(Uint32), 1, expStream );
for (int t=0;t<nbTexs;t++)
{
int PathLen = strlen(TexList[t]) + 1;
if (PathLen&3) {
PathLen += 4 - (PathLen & 3);
}
fwrite( &TexList[t], sizeof(char), PathLen, expStream );
}
}
// EXPORT MATERIAL LIST
if (nbMats)
{
WriteChunkHdr( (char*)MATERIAL_ID, 0 );
fwrite( &nbMats, sizeof(Uint32), 1, expStream );
fwrite( &nCurObj, sizeof(Uint32), 1, expStream );
for (int m=0;m<nbMats;m++)
{
fwrite( &MatList[m].material.diffuse.alpha, sizeof(float), 1, expStream);
fwrite( &MatList[m].material.diffuse.colour.r, sizeof(float), 1, expStream);
fwrite( &MatList[m].material.diffuse.colour.g, sizeof(float), 1, expStream);
fwrite( &MatList[m].material.diffuse.colour.b, sizeof(float), 1, expStream);
fwrite( &MatList[m].material.specular.alpha, sizeof(float), 1, expStream);
fwrite( &MatList[m].material.specular.colour.r, sizeof(float), 1, expStream);
fwrite( &MatList[m].material.specular.colour.g, sizeof(float), 1, expStream);
fwrite( &MatList[m].material.specular.colour.b, sizeof(float), 1, expStream);
fwrite( &MatList[m].material.tex_flags, sizeof(Uint32), 1, expStream);
fwrite( &MatList[m].material.attr_flags, sizeof(Uint32), 1, expStream);
}
}
}
}
/*----------------------------------------------------------------------
---------------------------------------------------------------------- */
char *makerelative(char const *basepath,char const *newpath, char *outstr)
{
#define FF_PATHNAMEMAX 256
char temp1[FF_PATHNAMEMAX];
char temp2[FF_PATHNAMEMAX];
int i, j, match;
// Are the filenames the same?
match = 0;
for (j = 0; j < FF_PATHNAMEMAX; j++)
{
if (basepath[j] != newpath[j])
{
match = 0;
break;
}
else if (basepath[j] == '.') // Matching
{
match = 1;
break;
}
else if (basepath[j] == 0) // Identical
{
match = 0;
break;
}
}
if (match) // Matching paths and filenames
{
strcpy(outstr, "#");
strcat(outstr, &newpath[j]);
}
else if (basepath[0] != newpath[0]) // Drive letters are different
strcpy(outstr, newpath);
else
{
// Find the paths
strcpy(temp1, basepath);
for (i = strlen(temp1) - 1; i >= 0; i--)
if (temp1[i] == '\\')
break;
else
temp1[i] = 0;
strcpy(temp2, newpath);
for (i = strlen(temp2) - 1; i >= 0; i--)
if (temp2[i] == '\\')
break;
else
temp2[i] = 0;
// Are the paths the same?
strcpy(outstr, "");
if (strcmp(temp1, temp2) == 0) // Paths are the same
{
j = strlen(temp1);
}
else // Paths are different
{
j = 2; // Drives are the same
// Find different bits
for (i = 0; i < (int) strlen(temp1); i++)
{
if ((temp1[i] == '\\') && (temp2[i] == '\\'))
j = i + 1;
else
if (temp1[i] != temp2[i])
break;
}
if (j > 3)
{
for (i = j; i < (int) strlen(temp1); i++)
if (temp1[i] == '\\')
strcat(outstr,"..\\");
}
else
j = 2;
}
strcat(outstr, &newpath[j]);
}
return outstr;
}
bool FileExists(const char* Name)
{
FILE *f = fopen(Name,"rb");
if (f)
{
fclose(f);
return true;
}
return false;
}
TSTR AsciiExp::FindTextureFName(TSTR MapName)
{
char Out[256];
_splitpath(filename, drive, dir, fname, ext);
TSTR GinDir = TSTR(drive)+TSTR(dir);
_splitpath(MapName, drive, dir, fname, ext);
TSTR DriveDir = TSTR(drive)+TSTR(dir);
TSTR FName = TSTR(fname) + TSTR(ext);
if (!FileExists(GinDir + FName))
{
MapName = ip->GetCurFilePath();
_splitpath(MapName, drive, dir, fname, ext);
DriveDir = TSTR(drive)+TSTR(dir);
if (!FileExists(GinDir + FName))
{
int i=0;
while (i<TheManager->GetMapDirCount())
{
DriveDir = TheManager->GetMapDir(i);
DriveDir = DriveDir + TSTR("\\");
if (FileExists(DriveDir + FName)) {
break;
}
i++;
}
if (i==TheManager->GetMapDirCount())
{
DriveDir = TSTR("");
}
}
}
GinDir.toLower();
DriveDir.toLower();
makerelative(GinDir, DriveDir, Out);
return TSTR(Out);
}
void AsciiExp::DumpTexture( Mtl* mtl, int matno, int subno )
{
Texmap * subTex = mtl->GetSubTexmap(ID_DI);
TSTR N = mtl->GetName();
if (mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0))
{
if (subTex && subTex->ClassID() == Class_ID(BMTEX_CLASS_ID, 0))
{
// If it is a standard material we can see if the map is enabled.
if (((StdMat*)mtl)->MapEnabled(ID_DI))
{
Bool found = FALSE;
int texidx = nbTexs;
char TexListTemp[256];
TSTR mapName = ((BitmapTex *)subTex)->GetMapName();
TSTR RelativePath = FindTextureFName(mapName);
_splitpath(mapName, drive, dir, fname, ext);
if (RelativePath.isNull())
{
sprintf( TexListTemp, "%s%s", fname, ext);
} else
{
sprintf( TexListTemp, "%s%s%s", RelativePath, fname, ext);
}
for (int t=0;t<nbTexs;t++)
{
if (!strcmp(TexList[t], TexListTemp))
{
texidx = t;
found = TRUE;
}
}
if (!found)
{
strcpy( TexList[nbTexs], TexListTemp );
nbTexs++;
if(nbTexs>= MAXCOUNT) MessageBox( MAX_hWnd, "nbTexs Overflow", "ERROR", MB_OK);
}
MatList[matno].SubTex[(subno+1)] = texidx;
}
}
}
if (mtl->NumSubMtls() > 0)
{
for (int i=0; i<mtl->NumSubMtls(); i++)
{
Mtl * subMtl = mtl->GetSubMtl(i);
if (subMtl)
{
DumpTexture( subMtl, matno, i );
}
}
}
}
int AsciiExp::getTextureId( Mtl *mtl )
{
Texmap * subTex = mtl->GetSubTexmap(ID_DI);
TSTR N = mtl->GetName();
if (mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0))
{
if (subTex && subTex->ClassID() == Class_ID(BMTEX_CLASS_ID, 0))
{
// If it is a standard material we can see if the map is enabled.
if (((StdMat*)mtl)->MapEnabled(ID_DI))
{
Bool found = FALSE;
int texidx = nbTexs;
char TexListTemp[256];
TSTR mapName = ((BitmapTex *)subTex)->GetMapName();
TSTR RelativePath = FindTextureFName(mapName);
_splitpath(mapName, drive, dir, fname, ext);
fprintf( tempStream, " texName = %s\n", fname );
if (RelativePath.isNull())
{
sprintf( TexListTemp, "%s%s", fname, ext);
} else
{
sprintf( TexListTemp, "%s%s%s", RelativePath, fname, ext);
}
for (int t=0;t<nbTexs;t++)
{
if (!strcmp(TexList[t], TexListTemp))
{
return t;
}
}
if (!found)
{
strcpy( TexList[nbTexs], TexListTemp );
nbTexs++;
if(nbTexs>= MAXCOUNT) MessageBox( MAX_hWnd, "nbTexs Overflow", "ERROR", MB_OK);
return nbTexs-1;
}
}
}
}
return -1;
}
/*----------------------------------------------------------------------
---------------------------------------------------------------------- */
void AsciiExp::DumpMaterial( Mtl* mtl, int matno, int subno , bool recurse)
{
Color col;
float alpha;
Uint32 AttrFlags = 0;
if (!mtl) return;
sprintf( MatList[nbMats].name, "%s", FixupName( mtl->GetName() ) );
fprintf( tempStream, "matName = %s %d\n", mtl->GetName(), nbMats );
// WE KNOW THE STANDARD MATERIAL, SO WE CAN GET SOME EXTRA INFO
if (mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0))
{
StdMat * std;
std = (StdMat*)mtl;
int tmap = getTextureId(mtl);
if (std->MapEnabled(ID_DI) && tmap != -1) AttrFlags |= GIN_FLAG_USE_TEXTURE;
if (std->MapEnabled(ID_RL)) AttrFlags |= GIN_FLAG_USE_ENVTEXTURE;
if (std->GetTwoSided()) AttrFlags |= GIN_FLAG_DOUBLE_SIDE;
if (std->GetSelfIllum( 0 ) > 0.2f ) AttrFlags |= GIN_FLAG_IGNORE_LIGHT;
AttrFlags |= (std->GetTransparencyType()<<3);
col = std->GetDiffuse( 0 );
alpha = std->GetOpacity( 0 );
if (std->MapEnabled(ID_DI)) {
MatList[nbMats].material.diffuse.alpha = alpha;
MatList[nbMats].material.diffuse.colour = col;
} else {
MatList[nbMats].material.diffuse.alpha = alpha;
MatList[nbMats].material.diffuse.colour = col;
}
col = std->GetSpecular( 0 );
MatList[nbMats].material.specular.alpha = alpha;
MatList[nbMats].material.specular.colour = col;
MatList[nbMats].material.exponent = 6.f;
fprintf( tempStream, " tmap = %d\n\n", tmap );
MatList[nbMats].material.tex_flags = tmap;
MatList[nbMats].material.attr_flags = AttrFlags;
nbMats++;
} else
{
if (mtl->ClassID() != Class_ID(MULTI_CLASS_ID, 0))
{
memset(&MatList[nbMats], 0, sizeof(MATLIST));
MatList[nbMats].material.tex_flags = -1;
nbMats++;
}
}
if (mtl->NumSubMtls() > 0)
{
int c = (recurse) ? 1 : mtl->NumSubMtls();
for (int i=0; i< c ; i++)
{
Mtl* subMtl = mtl->GetSubMtl(i);
if (subMtl)
{
DumpMaterial( subMtl, matno, i , true);
} else
{
nbMats++;
}
}
}
if(nbMats>= MAXCOUNT) MessageBox( MAX_hWnd, "nbMats Overflow", "ERROR", MB_OK);
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
int MtlKeeper::GetSubMtlCount(Mtl* mtl, bool recurse)
{
int Count = 0;
if (!mtl)
return 0;
if (mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0))
Count ++;
if (mtl->NumSubMtls() > 0)
{
int c = (recurse) ? 1 : mtl->NumSubMtls();
for (int i=0; i<c; i++)
{
Mtl* subMtl = mtl->GetSubMtl(i);
if (subMtl)
{
Count += GetSubMtlCount( subMtl, true);
} else
{
Count ++;
}
}
}
return Count;
}
BOOL MtlKeeper::AddMtl(Mtl* mtl)
{
if (!mtl) return FALSE;
int numMtls = mtlTab.Count();
for (int i=0; i<numMtls; i++)
{
if (mtlTab[i] == mtl) return FALSE;
}
mtlTab.Append(1, &mtl, 25);
return TRUE;
}
int MtlKeeper::GetMtlID(Mtl* mtl)
{
int numMtls = mtlTab.Count();
int CurIdx = 0;
int count = 0;
for (int i=0; i<numMtls; i++)
{
if (mtlTab[i] == mtl) return count;
count += GetSubMtlCount(mtlTab[i], false);
}
return -1;
}
int MtlKeeper::Count()
{
return mtlTab.Count();
}
Mtl* MtlKeeper::GetMtl(int id)
{
return mtlTab[id];
}
/*===========================================================================
end */