⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 video.cpp

📁 wowmodelview魔兽世界的模型查看工具。下了看看吧
💻 CPP
字号:

#include "video.h"

bool supportCompression = false;
bool supportMultiTex = false;
bool supportVBO = false;
bool supportDrawRangeElements = false;

//bool supportAntiAlias = false;
//int	arbMultisampleFormat = 0;

TextureManager texturemanager;
int gXres, gYres;
// multitex
#ifdef _WIN32	PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements = NULL;
		PFNGLMULTITEXCOORD2FARBPROC		glMultiTexCoord2fARB	= NULL;
	PFNGLACTIVETEXTUREARBPROC		glActiveTextureARB		= NULL;
	PFNGLCLIENTACTIVETEXTUREARBPROC	glClientActiveTextureARB= NULL;	#else // linux	void (*wglGetProcAddress(const char *function_name))(void)	{		return glXGetProcAddress((GLubyte*)function_name);	}#endif// compression
PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB	= NULL;
PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB	= NULL;

// VBO
PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;	
PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;
PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL;	
PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL;
// Map / UnmapPFNGLMAPBUFFERARBPROC glMapBufferARB = NULL;
PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL;


bool isExtensionSupported(const char *search)
{
	char *exts = (char*)glGetString(GL_EXTENSIONS);
	if (exts != NULL) {
		string str(exts);
		return (str.find(search) != string::npos);
	}

	return false;
}

/*
// InitMultisample: Used To Query The Multisample Frequencies
bool InitMultisample(HDC hDC)
{  
	const char *supported = NULL;
	PROC wglGetExtString = wglGetProcAddress("wglGetExtensionsStringARB");
	if (wglGetExtString)
		supported = ((char*(__stdcall*)(HDC))wglGetExtString)(wglGetCurrentDC());

	if (supported)
	{
		string str(supported);
		supportAntiAlias = (str.find("WGL_ARB_multisample") != string::npos);
		if (supportAntiAlias == false)
			return false;
	}

	// Get Our Pixel Format
	PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");	
	if (!wglChoosePixelFormatARB) 
	{
		supportAntiAlias = false;
		return false;
	}


	int		pixelFormat;
	int		valid;
	UINT	numFormats;
	float	fAttributes[] = {0,0};

	// These Attributes Are The Bits We Want To Test For In Our Sample
	// Everything Is Pretty Standard, The Only One We Want To 
	// Really Focus On Is The SAMPLE BUFFERS ARB And WGL SAMPLES
	// These Two Are Going To Do The Main Testing For Whether Or Not
	// We Support Multisampling On This Hardware.
	int iAttributes[] =
	{
		WGL_DRAW_TO_WINDOW_ARB,GL_TRUE,
		WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
		WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
		WGL_COLOR_BITS_ARB,24,
		WGL_ALPHA_BITS_ARB,8,
		WGL_DEPTH_BITS_ARB,16,
		WGL_STENCIL_BITS_ARB,0,
		WGL_DOUBLE_BUFFER_ARB,GL_TRUE,
		WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,
		WGL_SAMPLES_ARB,6,
		0,0
	};

	// First We Check To See If We Can Get A Pixel Format For 6 Samples
	valid = wglChoosePixelFormatARB(hDC, iAttributes, fAttributes,1, &pixelFormat, &numFormats);
 
	// If We Returned True, And Our Format Count Is Greater Than 1
	if (valid && numFormats >= 1)
	{
		supportAntiAlias = true;
		arbMultisampleFormat = pixelFormat;	
		return true;
	}

	// Our Pixel Format With 6 Samples Failed, Test For 4 Samples
	iAttributes[19] = 4;
	valid = wglChoosePixelFormatARB(hDC,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
	if (valid && numFormats >= 1)
	{
		supportAntiAlias = true;
		arbMultisampleFormat = pixelFormat;	 
		return true;
	}

	// Our Pixel Format With 4 Samples Failed, Test For 2 Samples
	iAttributes[19] = 2;
	valid = wglChoosePixelFormatARB(hDC,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
	if (valid && numFormats >= 1)
	{
		supportAntiAlias = true;
		arbMultisampleFormat = pixelFormat;	 
		return true;
	}
	  
	// Return The Valid Format
	supportAntiAlias = false;
	return false;
}
*/

void InitExtensions()
{
	char *exts = (char*)glGetString(GL_EXTENSIONS);
	if (exts != NULL) {
		wxLogMessage("Supported Video Extensions:\n%s\n", exts);

#ifdef _WIN32
		if (isExtensionSupported("GL_EXT_draw_range_elements")) {
			glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) wglGetProcAddress("glDrawRangeElements");
			supportDrawRangeElements = true;
		} else supportDrawRangeElements = false;
#else
		if (isExtensionSupported("GL_EXT_draw_range_elements")) {
			supportDrawRangeElements = true;
		} else supportDrawRangeElements = false;
#endif

		if (isExtensionSupported("GL_ARB_multitexture")) {
			supportMultiTex = true;
			glActiveTextureARB		= (PFNGLACTIVETEXTUREARBPROC)		wglGetProcAddress("glActiveTextureARB");
			glClientActiveTextureARB= (PFNGLCLIENTACTIVETEXTUREARBPROC) wglGetProcAddress("glClientActiveTextureARB");
			glMultiTexCoord2fARB	= (PFNGLMULTITEXCOORD2FARBPROC)		wglGetProcAddress("glMultiTexCoord2fARB");
		} else supportMultiTex = false;

		if (isExtensionSupported("GL_ARB_vertex_buffer_object"))
		{
			supportVBO = true;
			glGenBuffersARB = (PFNGLGENBUFFERSARBPROC) wglGetProcAddress("glGenBuffersARB");
			glBindBufferARB = (PFNGLBINDBUFFERARBPROC) wglGetProcAddress("glBindBufferARB");
			glBufferDataARB = (PFNGLBUFFERDATAARBPROC) wglGetProcAddress("glBufferDataARB");
			glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) wglGetProcAddress("glDeleteBuffersARB");

			glMapBufferARB = (PFNGLMAPBUFFERARBPROC) wglGetProcAddress("glMapBufferARB");
			glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC) wglGetProcAddress("glUnmapBufferARB");
		} else supportVBO = false;

		if (isExtensionSupported("GL_ARB_texture_compression") && isExtensionSupported("GL_ARB_texture_cube_map")) {
			glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) wglGetProcAddress("glCompressedTexImage2DARB");
			supportCompression = isExtensionSupported("GL_EXT_texture_compression_s3tc");
		} else supportCompression = false;

	} else
		wxLogMessage("No video extensions supported!\n");

	wxLogMessage("Support Texture Compression: %s", supportCompression ? "true" : "false");
	wxLogMessage("Support MultiTextures: %s", supportMultiTex ? "true" : "false");
	wxLogMessage("Support DrawRangeElements: %s", supportDrawRangeElements ? "true" : "false");
	wxLogMessage("Support Vertex Buffer Object: %s\n", supportVBO ? "true" : "false");
	
}

GLuint TextureManager::add(std::string name){	GLuint id = 0;	if (names.find(name) != names.end()) {		id = names[name];		items[id]->addref();		return id;	}	Texture *tex = new Texture(name);	if (tex != NULL) {		glGenTextures(1, &id);		tex->id = id;		LoadBLP(id, tex);		do_add(name, id, tex);		return id;	}	return 0;}
void TextureManager::LoadBLP(GLuint id, Texture *tex){	// load BLP texture	glBindTexture(GL_TEXTURE_2D, id);	int offsets[16], sizes[16], w, h;	GLint format;	char attr[4];	MPQFile f(tex->name.c_str());	if (f.isEof()) {		tex->id = 0;		return;	}	f.seek(8);	f.read(attr,4);	f.read(&w,4);	f.read(&h,4);	f.read(offsets,4*16);	f.read(sizes,4*16);	tex->w = w;	tex->h = h;	bool hasmipmaps = attr[4]>0;	int mipmax = hasmipmaps ? 16 : 1;	if (attr[0] == 2) {		// compressed		unsigned char *ucbuf = NULL;		if (!supportCompression) 			ucbuf = new unsigned char[w*h*4];			format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;		int blocksize = 8;		// guesswork here :(		if (attr[1]==8) {			format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;			blocksize = 16;		} else {			if (!attr[3]) 				format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;		}		tex->compressed = true;		unsigned char *buf = new unsigned char[sizes[0]];		// do every mipmap level		for (int i=0; i<mipmax; i++) {			if (w==0) w = 1;			if (h==0) h = 1;			if (offsets[i] && sizes[i]) {				f.seek(offsets[i]);				f.read(buf,sizes[i]);				int size = ((w+3)/4) * ((h+3)/4) * blocksize;				if (supportCompression) {					glCompressedTexImage2DARB(GL_TEXTURE_2D, i, format, w, h, 0, size, buf);				} else {					decompressDXTC(format, w, h, size, buf, ucbuf);					glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ucbuf);				}			} else break;			w >>= 1;			h >>= 1;		}		delete[] buf;		if (!supportCompression) 			delete[] ucbuf;	} else if (attr[0]==1) {		// uncompressed		unsigned int pal[256];		f.read(pal,1024);		unsigned char *buf = new unsigned char[sizes[0]];		unsigned int *buf2 = new unsigned int[w*h];		unsigned int *p = NULL;		unsigned char *c = NULL, *a = NULL;		int alphabits = attr[1];		bool hasalpha = alphabits!=0;		tex->compressed = false;		for (int i=0; i<mipmax; i++) {			if (w==0) w = 1;			if (h==0) h = 1;			if (offsets[i] && sizes[i]) {				f.seek(offsets[i]);				f.read(buf,sizes[i]);				int cnt = 0;				int alpha = 0;				p = buf2;				c = buf;				a = buf + w*h;				for (int y=0; y<h; y++) {					for (int x=0; x<w; x++) {						unsigned int k = pal[*c++];						k = ((k&0x00FF0000)>>16) | ((k&0x0000FF00)) | ((k& 0x000000FF)<<16);						if (hasalpha) {							if (alphabits == 8) {								alpha = (*a++);							} else if (alphabits == 1) {								//alpha = (*a & (128 >> cnt++)) ? 0xff : 0;								alpha = (*a & (1 << cnt++)) ? 0xff : 0;								if (cnt == 8) {									cnt = 0;									a++;								}							}						} else alpha = 0xff;						k |= alpha << 24;						*p++ = k;					}				}				glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf2);			} else break;			w >>= 1;			h >>= 1;		}		delete[] buf2;		delete[] buf;	}	f.close();	if (hasmipmaps) {		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);	} else {		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);	}	// some models require texture wrapping though	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);}
void TextureManager::doDelete(GLuint id){	glDeleteTextures(1, &id);}void Texture::getPixels(unsigned char* buf){	glBindTexture(GL_TEXTURE_2D, id);	glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);}struct Color {
	unsigned char r, g, b;
};
void decompressDXTC(GLint format, int w, int h, size_t size, unsigned char *src, unsigned char *dest)
{
	// sort of copied from linghuye
	int bsx = (w<4) ? w : 4;
	int bsy = (h<4) ? h : 4;
	
	/*
	if (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
		DDSDecompressDXT1(src, w, h, dest);
		return;
	}
	*/

	if (format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) {
		DDSDecompressDXT3(src, w, h, dest);
		return;
	}

	/*
	if (format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)	{
		DXT5UnpackAlphaValues(src, w, h, dest);
		return;
	} 
	*/

	for(int y=0; y<h; y += bsy) {
		for(int x=0; x<w; x += bsx) {
			//unsigned long alpha = 0;
			//unsigned int a0 = 0, a1 = 0;

			unsigned int c0 = *(unsigned short*)(src + 0);
			unsigned int c1 = *(unsigned short*)(src + 2);
			src += 4;

			Color color[4];
			color[0].b = (unsigned char) ((c0 >> 11) & 0x1f) << 3;
			color[0].g = (unsigned char) ((c0 >>  5) & 0x3f) << 2;
			color[0].r = (unsigned char) ((c0      ) & 0x1f) << 3;
			color[1].b = (unsigned char) ((c1 >> 11) & 0x1f) << 3;
			color[1].g = (unsigned char) ((c1 >>  5) & 0x3f) << 2;
			color[1].r = (unsigned char) ((c1      ) & 0x1f) << 3;

			if(c0 > c1 || format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) {
				color[2].r = (color[0].r * 2 + color[1].r) / 3;
				color[2].g = (color[0].g * 2 + color[1].g) / 3;
				color[2].b = (color[0].b * 2 + color[1].b) / 3;
				color[3].r = (color[0].r + color[1].r * 2) / 3;
				color[3].g = (color[0].g + color[1].g * 2) / 3;
				color[3].b = (color[0].b + color[1].b * 2) / 3;
			} else {
				color[2].r = (color[0].r + color[1].r) / 2;
				color[2].g = (color[0].g + color[1].g) / 2;
				color[2].b = (color[0].b + color[1].b) / 2;
				color[3].r = 0;
				color[3].g = 0;
				color[3].b = 0;
			}

			for (int j=0; j<bsy; j++) {
				unsigned int index = *src++;
				unsigned char* dd = dest + (w*(y+j)+x)*4;
				for (int i=0; i<bsx; i++) {
					*dd++ = color[index & 0x03].b;
					*dd++ = color[index & 0x03].g;
					*dd++ = color[index & 0x03].r;
					//if (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)	{
						*dd++ = ((index & 0x03) == 3 && c0 <= c1) ? 0 : 255;
					//}
					index >>= 2;
				}
			}
		}
	}
}

⌨️ 快捷键说明

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