texwnd.cpp
来自「quake3工具源码。包括生成bsp文件」· C++ 代码 · 共 2,647 行 · 第 1/5 页
CPP
2,647 行
q->height = nHeight;
q->flags = nFlags;
q->value = nValue;
q->contents = nContents;
int nCount = nWidth * nHeight;
float total[3];
total[0] = total[1] = total[2] = 0.0f;
//++timo FIXME: move gamma table initialization somewhere else!
if (fGamma == 1.0)
{
for (i=0 ; i<256 ; i++)
gammatable[i] = i;
}
else
{
for (i=0 ; i<256 ; i++)
{
inf = 255 * pow ( (i+0.5)/255.5 , fGamma ) + 0.5;
if (inf < 0)
inf = 0;
if (inf > 255)
inf = 255;
gammatable[i] = inf;
}
}
// all targas are stored internally as 32bit so rgba = 4 bytes
for (i = 0 ; i < (nCount * 4) ; i += 4)
{
for (j = 0; j < 3; j++)
{
total[j] += (pPixels+i)[j];
byte b = (pPixels+i)[j];
(pPixels+i)[j] = gammatable[b];
}
}
q->color[0] = total[0] / (nCount * 255);
q->color[1] = total[1] / (nCount * 255);
q->color[2] = total[2] / (nCount * 255);
q->texture_number = texture_extension_number++;
if (g_qeglobals.bSurfacePropertiesPlugin)
{
// Timo
// Surface properties plugins can store their own data in an IPluginQTexture
q->pData = g_SurfaceTable.m_pfnQTextureAlloc( q );
GETPLUGINTEXDEF(q)->SetDefaultTexdef();
}
if (g_PrefsDlg.m_bSGIOpenGL)
{
//if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
Error ("wglMakeCurrent in LoadTexture failed");
}
qglBindTexture( GL_TEXTURE_2D, q->texture_number );
//Handle3DfxTexturing(q, width, height, dest);
SetTexParameters();
nCount = MAX_TEXTURE_QUALITY - g_PrefsDlg.m_nTextureQuality;
while (nCount-- > 0)
{
if (nWidth > 16 && nHeight > 16)
{
R_MipMap(pPixels, nWidth, nHeight);
}
else
{
break;
}
}
if (g_PrefsDlg.m_bSGIOpenGL)
{
if (nomips)
{
qglTexImage2D(GL_TEXTURE_2D, 0, 4, nWidth, nHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pPixels);
}
else
qgluBuild2DMipmaps(GL_TEXTURE_2D, 4, nWidth, nHeight,GL_RGBA, GL_UNSIGNED_BYTE, pPixels);
}
else
{
if (nomips)
qglTexImage2D(GL_TEXTURE_2D, 0, 4, nWidth, nHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pPixels);
else
qgluBuild2DMipmaps(GL_TEXTURE_2D, 4, nWidth, nHeight,GL_RGBA, GL_UNSIGNED_BYTE, pPixels);
}
qglBindTexture( GL_TEXTURE_2D, 0 );
return q;
}
qtexture_t *Texture_LoadTGATexture (unsigned char* pPixels, int nWidth, int nHeight, char *pPath)
{
CString strName;
CString strPath;
ExtractPath_and_Filename(pPath, strPath, strName);
AddSlash(strPath);
strPath += "textureinfo.ini";
strName.MakeLower();
StripExtension (strName.GetBuffer(0));
strName.ReleaseBuffer();
int nFlags = GetPrivateProfileInt(strName, "Flags", 0, strPath);
int nValue = GetPrivateProfileInt(strName, "Value", 0, strPath);
int nContents = GetPrivateProfileInt(strName, "Contents", 0, strPath);
return Texture_LoadTGATexture(pPixels, nWidth, nHeight, pPath, nFlags, nValue, nContents);
}
void Texture_LoadFromPlugIn(LPVOID vp)
{
g_pluginTexture = notexture;
_QERTextureLoad *pLoad = reinterpret_cast<_QERTextureLoad*>(vp);
if (pLoad != NULL)
{
qtexture_t *q;
q = Texture_LoadTGATexture(pLoad->m_pRGBA, pLoad->m_nWidth, pLoad->m_nHeight, NULL, pLoad->m_nFlags, pLoad->m_nContents, pLoad->m_nValue);
if (q != NULL)
{
// to save duplicate code (since one always ends up getting forgotten and out of sync) this is now done later by caller
// strcpy (q->name, pLoad->m_pName);
// StripExtension (q->name);
// if (!g_dontuse)
// q->inuse = true;
// q->next = g_qeglobals.d_qtextures;
// g_qeglobals.d_qtextures = q;
g_pluginTexture = q;
}
}
}
/*
===============
Texture_CreateSolid
Create a single pixel texture of the apropriate color
===============
*/
qtexture_t *Texture_CreateSolid (const char *name)
{
byte data[4];
qtexture_t *q;
q = (qtexture_t*)qmalloc(sizeof(*q));
if (g_qeglobals.bSurfacePropertiesPlugin)
{
// Timo
// Surface properties plugins can store their own data in an IPluginQTexture
q->pData = g_SurfaceTable.m_pfnQTextureAlloc( q );
GETPLUGINTEXDEF(q)->SetDefaultTexdef();
}
sscanf (name, "(%f %f %f)", &q->color[0], &q->color[1], &q->color[2]);
data[0] = q->color[0]*255;
data[1] = q->color[1]*255;
data[2] = q->color[2]*255;
data[3] = 255;
q->width = q->height = 1;
//q->width = q->height = 2;
q->texture_number = texture_extension_number++;
qglBindTexture( GL_TEXTURE_2D, q->texture_number );
SetTexParameters ();
if (g_PrefsDlg.m_bSGIOpenGL)
{
qglTexImage2D(GL_TEXTURE_2D, 0, 3, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
}
else
{
if (nomips)
qglTexImage2D(GL_TEXTURE_2D, 0, 3, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
else
qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, 1, 1,GL_RGBA, GL_UNSIGNED_BYTE, data);
}
qglBindTexture( GL_TEXTURE_2D, 0 );
return q;
}
/*
=================
Texture_MakeDefault
=================
*/
qtexture_t* Texture_MakeDefault (void)
{
qtexture_t *q;
byte data[4][4];
if (g_PrefsDlg.m_bSGIOpenGL)
{
if (s_hdcTexture && s_hglrcTexture)
{
//if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
Error ("wglMakeCurrent in LoadTexture failed");
}
else
return NULL;
}
q = (qtexture_t*)qmalloc(sizeof(*q));
strcpy (q->name, "notexture");
q->width = q->height = 64;
memset (data, 0, sizeof(data));
data[0][2] = data[3][2] = 255;
q->color[0] = 0;
q->color[1] = 0;
q->color[2] = 0.5;
q->texture_number = texture_extension_number++;
qglBindTexture( GL_TEXTURE_2D, q->texture_number );
SetTexParameters ();
if (nomips)
qglTexImage2D(GL_TEXTURE_2D, 0, 3, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
else
VERIFY(qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, 2, 2,GL_RGBA, GL_UNSIGNED_BYTE, data) == 0);
qglBindTexture( GL_TEXTURE_2D, 0 );
return q;
}
/*
=================
Texture_MakeNotexture
=================
*/
void Texture_MakeNotexture (void)
{
notexture = Texture_MakeDefault();
// Timo
// Surface properties plugins can store their own data in an IPluginQTexture
if (g_qeglobals.bSurfacePropertiesPlugin)
{
notexture->pData = g_SurfaceTable.m_pfnQTextureAlloc( notexture );
GETPLUGINTEXDEF(notexture)->SetDefaultTexdef();
}
}
void DemandLoadShaderTexture(qtexture_t *q, CShaderInfo *pShader)
{
char cWork[1024];
char cWork2[1024];
strcpy(cWork, (pShader->m_strTextureName.GetLength() > 0) ? pShader->m_strTextureName : pShader->m_strName);
StripExtension(cWork);
// TTimo: if the shader has a m_fTransValue != 1.0f, ignore the alpha channel when loading the texture
// in some cases (common/weapclip) the 32bit .tga has an empty alpha channel,
// causing a display bug in the camera view (brush does not seemed drawn since alpha==0 for the texture)
// NOTE: the workaround is not perfect, the same texture may have been loaded earlier with it's alpha channel
q = Texture_ForName (cWork, false, true, pShader->m_fTransValue != 1.0f, true, false);
if (q == NULL || q == notexture) {
sprintf(cWork2, "%s/%s",ValueForKey(g_qeglobals.d_project_entity, "basepath"), cWork);
q = Texture_ForNamePath( cWork, cWork2);
if (q == NULL || q == notexture) {
q = Texture_ForName (cWork, false, true, pShader->m_fTransValue != 1.0f, true, true);
}
}
if (q != NULL && q != notexture)
{
pShader->m_pQTexture = q;
strcpy(q->shadername, pShader->m_strShaderName);
q->bFromShader = true;
q->fTrans = pShader->m_fTransValue;
q->nShaderFlags = pShader->m_nFlags;
strcpy(q->name, pShader->m_strName );
}
else
{
Sys_Printf("Could not load shader editor image %s\n", cWork);
}
}
void LoadShader(char* pFilename, qtexture_t *q)
{
char* pBuff = NULL;
CString strTexture;
int nSize = LoadFile(pFilename, reinterpret_cast<void**>(&pBuff));
if (nSize == -1)
{
nSize = PakLoadAnyFile(pFilename, reinterpret_cast<void**>(&pBuff));
}
if (nSize > 0)
{
StartTokenParsing(pBuff);
while (GetToken(true))
{
// first token should be the path + name.. (from base)
CShaderInfo *pShader = new CShaderInfo();
pShader->setName(token);
pShader->m_strShaderName = pFilename;
strTexture = token;
bool bGood = true;
float fTrans = 1.0;
GetToken(true);
if (strcmp(token, "{"))
{
bGood = false;
break;
}
else
{
// we need to read until we hit a balanced }
int nMatch = 1;
while (nMatch > 0 && GetToken(true))
{
if (strcmp(token, "{") == 0)
{
nMatch++;
}
else if (strcmp(token, "}") == 0)
{
nMatch--;
}
else if (strcmpi(token, "qer_nocarve") == 0)
{
pShader->m_nFlags |= QER_NOCARVE;
}
else if (strcmpi(token, "qer_trans") == 0)
{
if (GetToken(true))
{
fTrans = atof(token);
}
pShader->m_nFlags |= QER_TRANS;
}
else if (strcmpi(token, "qer_editorimage") == 0)
{
if (GetToken(true))
{
char* pTex = copystring(token);
QE_ConvertDOSToUnixName( pTex, pTex );
CString str = pTex;
free (pTex);
FindReplace(str, "textures/", "");
FindReplace(str, ".tga", "");
int nPos = str.Find('/');
if (nPos == -1)
{
nPos = str.Find('\\');
}
if (nPos >= 0)
{
pShader->m_strTextureName = str;
pShader->m_strTextureName.MakeLower(); //avoid problems with case
/*
else
{
CString strPath = str.Left(nPos+1);
DeferredShaderLoad *deferred = new DeferredShaderLoad(str, pShader->m_strName, strPath);
g_lstDeferred.Add(deferred);
}
*/
}
}
}
else if (strcmpi(token, "surfaceparm") == 0)
{
//--while (GetToken(false))
//--{
//--
//--}
if (GetToken(true))
{
// next token should be a surface parm
//--if (strcmpi(token, "trans") == 0)
//--{
//-- fTrans = 0.33;
//--}
if (strcmpi(token, "fog") == 0)
{
if (fTrans == 1.0) // has not been explicitly set by qer_trans
{
fTrans = 0.35;
}
}
}
}
}
if (nMatch != 0)
{
bGood = false;
break;
}
}
//--if (bGood && q)
if (bGood)
{
pShader->m_fTransValue = fTrans;
g_lstShaders.Add(pShader);
int n = g_PrefsDlg.m_nShader;
if (g_PrefsDlg.m_nShader == CPrefsDlg::SHADER_ALL || (g_PrefsDlg.m_nShader == CPrefsDlg::SHADER_COMMON && strstr(pShader->m_strName, "common" )))
{
// new
if (pShader->m_strTextureName.GetLength() > 0)
{
if (!ShaderQTextureExists(pShader->m_strName))
{
DemandLoadShaderTexture(q, pShader);
}
}
}
// end new
//--q->bFromShader = true;
//--q->fTrans = fTrans;
//--// good texture here
//--//Sys_Printf("Test load texture %s\n", strTexture);
//--// FIXME.. this is a load of crap
//--strcpy(dirstring, strTexture);
//--QE_ConvertDOSToUnixName(dirstring, dirstring);
//--strTexture = dirstring;
//--FindReplace(strTexture, "textures/", "");
//--qtexture_t *q = Texture_ForName (strTexture.GetBuffer(0));
//--if (q != NULL)
//--{
//-- q->bFromShader = true;
//-- q->fTrans = fTrans;
//--}
}
else
{
Sys_Printf("Error parsing shader at texture %s\n", strTexture);
}
}
free (pBuff);
}
else
{
Sys_Printf("Unabled to read shader %s\n", pFilename);
}
}
extern bool DoesFileExist(const char* pBuff, long& lSize);
CShaderInfo* SetNameShaderInfo(qtexture_t* q, const char* pPath, const char* pName)
{
CShaderInfo *pInfo = hasShader(pName);
if (pInfo)
{
strcpy(q->shadername, pInfo->m_strShaderName);
q->bFromShader = true;
q->fTrans = pInfo->m_fTransValue;
q->nShaderFlags = pInfo->m_nFlags;
}
else
{
q->shadername[0] = 0;
}
strncpy (q->name, pName, sizeof(q->name) - 1);
StripExtension (q->name);
return pInfo;
}
void ReplaceQTexture(qtexture_t *pOld, qtexture_t *pNew, brush_t *pList)
{
for (brush_t* pBrush = pList->next ; pBrush != pList; pBrush = pBrush->next)
{
if (pBrush->patchBrush)
{
Patch_ReplaceQTexture(pBrush, pOld, pNew);
}
for (face_t* pFace = pBrush->brush_faces; pFace; pFace = pFace->next)
{
if (pFace->d_texture == pOld)
{
pFace->d_texture = pNew;
}
}
//Brush_Build(pBrush);
}
}
void Texture_Remove(qtexture_t *q)
{
qtexture_t* pTex = g_qeglobals.d_qtextures->next;
if (q == g_qeglobals.d_qtextures) // it is the head
{
g_qeglobals.d_qtextures->next = q->next->next;
g_qeglobals.d_qtextures = q->next;
}
else
{
qtexture_t* pLast = g_qeglobals.d_qtextures;
while (pTex != NULL && pTex != g_qeglobals.d_qtextures)
{
if (pTex == q)
{
pLast->next = q->next;
break;
}
pLast = pTex;
pTex = pTex->next;
}
}
qglDeleteTextures(1, reinterpret_cast<const unsigned int*>(&q->texture_number));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?