texwnd.cpp

来自「quake3工具源码。包括生成bsp文件」· C++ 代码 · 共 2,647 行 · 第 1/5 页

CPP
2,647
字号
// TexWnd.cpp : implementation file
//

#include "stdafx.h"
#include <assert.h>
#include "Radiant.h"
#include "TexWnd.h"
#include "qe3.h"
#include "io.h"
#include "PrefsDlg.h"
#include "shaderinfo.h"
#include "pakstuff.h"
#include "str.h"
#include "PrefsDlg.h"

Str m_gStr;

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

qtexture_t *Texture_ForNamePath(char* name, char* pFullPath);
#define	TYP_MIPTEX	68
static unsigned	tex_palette[256];

qtexture_t	*notexture = NULL;
qtexture_t	*g_pluginTexture = NULL;

static qboolean	nomips = false;

#define	FONT_HEIGHT	10

HGLRC s_hglrcTexture = NULL;
HDC	 s_hdcTexture = NULL;

//int		texture_mode = GL_NEAREST;
//int		texture_mode = GL_NEAREST_MIPMAP_NEAREST;
//int		texture_mode = GL_NEAREST_MIPMAP_LINEAR;
//int		texture_mode = GL_LINEAR;
//int		texture_mode = GL_LINEAR_MIPMAP_NEAREST;
int		texture_mode = GL_LINEAR_MIPMAP_LINEAR;

// this is the global counter for GL bind numbers
int		texture_extension_number = 1;
int g_nCurrentTextureMenuName;

int g_nTextureOffset = 0;

// current active texture directory.  if empty, show textures in use
char		texture_directory[128];	// use if texture_showinuse is false
qboolean	texture_showinuse;

bool g_bFilterEnabled = false;
CString g_strFilter;

// texture layout functions
qtexture_t	*current_texture = NULL;
int			current_x, current_y, current_row;

int			texture_nummenus;
#define		MAX_TEXTUREDIRS	128
char		texture_menunames[MAX_TEXTUREDIRS][128];

qboolean	g_dontuse = true;		// set to true to load the texture but not flag as used

// void SelectTexture (int mx, int my, bool bShift = false);
void SelectTexture (int mx, int my, bool bShift, bool bFitScale=false);

void	Texture_MouseDown (int x, int y, int buttons);
void	Texture_MouseUp (int x, int y, int buttons);
void	Texture_MouseMoved (int x, int y, int buttons);

CPtrArray g_lstShaders;
CPtrArray g_lstSkinCache;

struct SkinInfo
{
  CString m_strName;
  int m_nTextureBind;
  SkinInfo(const char *pName, int n)
  {
    m_strName = pName;
    m_nTextureBind = n;
  };
  SkinInfo(){};
};

// checks wether a qtexture_t exists for a given name
//++timo FIXME: is this really any use? redundant.
bool ShaderQTextureExists(const char *pName)
{
  for (qtexture_t *q=g_qeglobals.d_qtextures ; q ; q=q->next)
  {
    if (!strcmp(q->name,  pName))
    {
      return true;
    }
  }
  return false;

}

CShaderInfo* hasShader(const char *pName)
{
  int nSize = g_lstShaders.GetSize();
  for (int i = 0; i < nSize; i++)
  {
    CShaderInfo *pInfo = reinterpret_cast<CShaderInfo*>(g_lstShaders.ElementAt(i));
    if (pInfo != NULL)
    {
      if (pInfo->m_strName.CompareNoCase(pName) == 0)
      {
        return pInfo;
      }
    }
  }
  return NULL;
}

// gets active texture extension
// 
// FIXME: fix this to be generic from project file
//
int GetTextureExtensionCount()
{
  return 2;
}

const char* GetTextureExtension(int nIndex)
{
  if ( nIndex == 0)
  {
    _QERTextureInfo *pInfo = g_pParentWnd->GetPlugInMgr().GetTextureInfo();
    const char *pTex = (pInfo != NULL) ? pInfo->m_TextureExtension : NULL;
    return (pTex == NULL) ? (g_PrefsDlg.m_bHiColorTextures == FALSE) ? "wal" : "tga" : pTex;
  }
  // return jpg for 2nd extension
  return "jpg";
}

void SortTextures(void)
{	
	qtexture_t	*q, *qtemp, *qhead, *qcur, *qprev;

	// standard insertion sort
	// Take the first texture from the list and
	// add it to our new list
	if ( g_qeglobals.d_qtextures == NULL)
		return;	

	qhead = g_qeglobals.d_qtextures;
	q = g_qeglobals.d_qtextures->next;
	qhead->next = NULL;
	
	// while there are still things on the old
	// list, keep adding them to the new list
	while (q)
	{
		qtemp = q;
		q = q->next;
		
		qprev = NULL;
		qcur = qhead;

		while (qcur)
		{
			// Insert it here?
			if (strcmp(qtemp->name, qcur->name) < 0)
			{
				qtemp->next = qcur;
				if (qprev)
					qprev->next = qtemp;
				else
					qhead = qtemp;
				break;
			}
			
			// Move on

			qprev = qcur;
			qcur = qcur->next;


			// is this one at the end?

			if (qcur == NULL)
			{
				qprev->next = qtemp;
				qtemp->next = NULL;
			}
		}


	}

	g_qeglobals.d_qtextures = qhead;
}

/*
==============
Texture_InitPalette
==============
*/
void Texture_InitPalette (byte *pal)
{
    int		r,g,b,v;
    int		i;
	int		inf;
	byte	gammatable[256];
	float	gamma;

	gamma = g_qeglobals.d_savedinfo.fGamma;

	if (gamma == 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 , gamma ) + 0.5;
			if (inf < 0)
				inf = 0;
			if (inf > 255)
				inf = 255;
			gammatable[i] = inf;
		}
	}

    for (i=0 ; i<256 ; i++)
    {
		  r = gammatable[pal[0]];
		  g = gammatable[pal[1]];
		  b = gammatable[pal[2]];
		  pal += 3;
		
		  v = (r<<24) + (g<<16) + (b<<8) + 255;
		  v = BigLong (v);
		
		  tex_palette[i] = v;
    }
}

void SetTexParameters (void)
{
	qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texture_mode );
	
	switch ( texture_mode )
	{
	case GL_NEAREST:
	case GL_NEAREST_MIPMAP_NEAREST:
	case GL_NEAREST_MIPMAP_LINEAR:
		qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
		break;
	case GL_LINEAR:
	case GL_LINEAR_MIPMAP_NEAREST:
	case GL_LINEAR_MIPMAP_LINEAR:
		qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
		break;
	}
}

/*
============
Texture_SetMode
============
*/
void Texture_SetMode(int iMenu)
{
	int	i, iMode;
	HMENU hMenu;
	qboolean texturing = true;

	hMenu = GetMenu(g_qeglobals.d_hwndMain);

	switch(iMenu) {
	case ID_VIEW_NEAREST:					
		iMode = GL_NEAREST;
		break;
	case ID_VIEW_NEARESTMIPMAP:
		iMode = GL_NEAREST_MIPMAP_NEAREST;
		break;
	case ID_VIEW_LINEAR:
		iMode = GL_NEAREST_MIPMAP_LINEAR;
		break;
	case ID_VIEW_BILINEAR:
		iMode = GL_LINEAR;
		break;
	case ID_VIEW_BILINEARMIPMAP:
		iMode = GL_LINEAR_MIPMAP_NEAREST;
		break;
	case ID_VIEW_TRILINEAR:
		iMode = GL_LINEAR_MIPMAP_LINEAR;
		break;

	case ID_TEXTURES_WIREFRAME:
		iMode = 0;
		texturing = false;
		break;

	case ID_TEXTURES_FLATSHADE:
		iMode = 0;
		texturing = false;
		break;

	}

	CheckMenuItem(hMenu, ID_VIEW_NEAREST, MF_BYCOMMAND | MF_UNCHECKED);
	CheckMenuItem(hMenu, ID_VIEW_NEARESTMIPMAP, MF_BYCOMMAND | MF_UNCHECKED);
	CheckMenuItem(hMenu, ID_VIEW_LINEAR, MF_BYCOMMAND | MF_UNCHECKED);
	CheckMenuItem(hMenu, ID_VIEW_BILINEARMIPMAP, MF_BYCOMMAND | MF_UNCHECKED);
	CheckMenuItem(hMenu, ID_VIEW_BILINEAR, MF_BYCOMMAND | MF_UNCHECKED);
	CheckMenuItem(hMenu, ID_VIEW_TRILINEAR, MF_BYCOMMAND | MF_UNCHECKED);
	CheckMenuItem(hMenu, ID_TEXTURES_WIREFRAME, MF_BYCOMMAND | MF_UNCHECKED);
	CheckMenuItem(hMenu, ID_TEXTURES_FLATSHADE, MF_BYCOMMAND | MF_UNCHECKED);

	CheckMenuItem(hMenu, iMenu, MF_BYCOMMAND | MF_CHECKED);

	g_qeglobals.d_savedinfo.iTexMenu = iMenu;
	texture_mode = iMode;

  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;
  }

	if ( texturing )
		SetTexParameters ();

	if ( !texturing && iMenu == ID_TEXTURES_WIREFRAME)
	{
		g_pParentWnd->GetCamera()->Camera().draw_mode = cd_wire;
		Map_BuildBrushData();
		Sys_UpdateWindows (W_ALL);
		return;

	} else if ( !texturing && iMenu == ID_TEXTURES_FLATSHADE) {

		g_pParentWnd->GetCamera()->Camera().draw_mode = cd_solid;
		Map_BuildBrushData();
		Sys_UpdateWindows (W_ALL);
		return;
	}

	for (i=1 ; i<texture_extension_number ; i++)
	{
		qglBindTexture( GL_TEXTURE_2D, i );
		SetTexParameters ();
	}

	// select the default texture
	qglBindTexture( GL_TEXTURE_2D, 0 );

	qglFinish();

	if (g_pParentWnd->GetCamera()->Camera().draw_mode != cd_texture)
	{
		g_pParentWnd->GetCamera()->Camera().draw_mode = cd_texture;
		Map_BuildBrushData();
	}

	Sys_UpdateWindows (W_ALL);
}

/*
================
R_MipMap

Operates in place, quartering the size of the texture
================
*/
void R_MipMap (byte *in, int &width, int &height)
{
	int		i, j;
	byte	*out;
	int		row;
	
	row = width * 4;
	width >>= 1;
	height >>= 1;
	out = in;
	for (i=0 ; i<height ; i++, in+=row)
	{
		for (j=0 ; j<width ; j++, out+=4, in+=8)
		{
			out[0] = (in[0] + in[4] + in[row+0] + in[row+4])>>2;
			out[1] = (in[1] + in[5] + in[row+1] + in[row+5])>>2;
			out[2] = (in[2] + in[6] + in[row+2] + in[row+6])>>2;
			out[3] = (in[3] + in[7] + in[row+3] + in[row+7])>>2;
		}
	}
}

/*
=================
Texture_LoadTexture
=================
*/
//++timo NOTE: miptex_t is used only for .WAL format .. a bit outdated
qtexture_t *Texture_LoadTexture (miptex_t *qtex)
{
  byte		*source;
  unsigned	char *dest;
  int			width, height, i, count;
	int			total[3];
  qtexture_t	*q;
      
  width = LittleLong(qtex->width);
  height = LittleLong(qtex->height);

  q = (qtexture_t*)qmalloc(sizeof(*q));

  q->width = width;
  q->height = height;

	q->flags = qtex->flags;
	q->value = qtex->value;
	q->contents = qtex->contents;

	dest = (unsigned char*)qmalloc (width*height*4);

  count = width*height;
  source = (byte *)qtex + LittleLong(qtex->offsets[0]);

	// The dib is upside down so we want to copy it into 
	// the buffer bottom up.

	total[0] = total[1] = total[2] = 0;
  for (i=0 ; i<count ; i++)
	{
		dest[i] = tex_palette[source[i]];

		total[0] += ((byte *)(dest+i))[0];
		total[1] += ((byte *)(dest+i))[1];
		total[2] += ((byte *)(dest+i))[2];
	}

	q->color[0] = (float)total[0]/(count*255);
	q->color[1] = (float)total[1]/(count*255);
	q->color[2] = (float)total[2]/(count*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)->InitForMiptex( qtex );
  }

  //++timo is the m_bSGIOpenGL parameter still taken into account?
  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 ();

  int nCount = MAX_TEXTURE_QUALITY - g_PrefsDlg.m_nTextureQuality;
  while (nCount-- > 0)
  {
    if (width > 16 && height > 16)
    {
      R_MipMap(dest, width, height);
    }
    else
    {
      break;
    }
  }

  if (g_PrefsDlg.m_bSGIOpenGL)
  {
	  if (nomips)
    {
		  qglTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, dest);
    }
	  else
		  qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height,GL_RGBA, GL_UNSIGNED_BYTE, dest);
  }
  else
  {
	  if (nomips)
		  qglTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, dest);
	  else
		  qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height,GL_RGBA, GL_UNSIGNED_BYTE, dest);
  }

	free (dest);

	qglBindTexture( GL_TEXTURE_2D, 0 );

  return q;
}




/*
=================
Texture_LoadTexture
=================
*/
qtexture_t *Texture_LoadTGATexture (unsigned char* pPixels, int nWidth, int nHeight, char* pPath, int nFlags, int nContents, int nValue )
{
  int i, j, inf;
	byte	gammatable[256];
	float fGamma = g_qeglobals.d_savedinfo.fGamma;


  qtexture_t* q = (qtexture_t*)qmalloc(sizeof(*q));
  q->width = nWidth;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?