3ds模型--摆放地

这章加载一个地表图,也就是说画一个平面(长方形),并用一张图(纹理)贴在上面作为模型的停放地。

为了方便使用单独写成一个cpp。

定义一些变量:

GLint DibiaoChangX,DibiaoKuanZ,DibiaoGaoY;//长度,宽度,高度(拼音)
GLuint Dibiaotexture;//纹理ID
加载和设置,放到前面的 init 部分:

//载入地表图
setDibiao(DibiaoChangX,DibiaoKuanZ,me3ds[0].bian.ymin);
//载入地表图
loadDibiaoPic("Wood-cherry.jpg");
绘制放到drawAllModel中:

DrawDibiao();
前面《 opengl 显示有纹理的四面体》有一个加载bmp作纹理的函数,bmp图太大,这里用 CLoad3DS.cpp 中的 BuildTexture(char *szPathName, GLuint &texid)函数。
完整的cpp:

//地表绘制(拼音 dibiao.cpp)

#include "CLoad3DS.h"

GLint DibiaoChangX,DibiaoKuanZ,DibiaoGaoY;//长度,宽度,高度(拼音)
GLuint Dibiaotexture;//纹理ID
;


// 读入一个纹理(CLoad3DS.cpp中取出)
int BuildTexture(char *szPathName, GLuint &texid)
{
	HDC      hdcTemp;                        // 用于保存位图的 DC
	HBITMAP    hbmpTemp;                        // 暂时保存位图
	IPicture  *pPicture;                        // 图接口
	OLECHAR    wszPath[MAX_PATH+1];                  // 图片的完整路径 (WCHAR)
	char    szPath[MAX_PATH+1];                    // 图片的完整路径
	long    lWidth;                          // 逻辑单元宽度
	long    lHeight;                        // 逻辑单元高度
	long    lWidthPixels;                      // 以像素为单位的宽度
	long    lHeightPixels;                      // 以像素为单位的高度
	GLint    glMaxTexDim ;                      // 保持最大纹理大小

	if (strstr(szPathName, "http://"))                  // 如果路径名(szPathName)包含"http://" 则...
	{
		strcpy(szPath, szPathName);                    // 将路径名(szPathName)附加到szPath
	}
	else                                // 否则...我们就从文件加载
	{
		WCHAR tempPath[MAX_PATH+1]; 
		GetCurrentDirectory(MAX_PATH, tempPath);              // 获取我们的工作目录
		int lengthOfMbs = WideCharToMultiByte( CP_ACP, 0, tempPath, -1, NULL, 0, NULL, NULL); 
		WideCharToMultiByte( CP_ACP, 0, tempPath, -1, szPath, lengthOfMbs, NULL, NULL); //宽字符转为多字符
		if(!strstr(szPath, "Data\\3DS"))
		{
			strcat(szPath, PICPATH);                      // 在工作目录后面追加"\"
		}
		else
			strcat(szPath, "\\"); //如果已经包含(在命令行)
		strcat(szPath, szPathName);                    // 追加路径名
}
	//printf("图片路径:%s\n",szPath);

	MultiByteToWideChar(CP_ACP, 0, szPath, -1, wszPath, MAX_PATH);    // 从ASCII转换为Unicode
	HRESULT hr = OleLoadPicturePath(wszPath, 0, 0, 0, IID_IPicture, (void**)&pPicture);

	if(FAILED(hr)) {                           // 如果加载失败
		printf("装入纹理出错,可能是文件 %s 不存在!\n",szPathName);
		return FALSE;                          // 返回假
	}

	hdcTemp = CreateCompatibleDC(GetDC(0));                // 创建与Windows兼容的设备上下文
	if(!hdcTemp)                            // 创造失败了吗?
	{
		pPicture->Release();                      // 递减图片参考计数
		return FALSE;                          //返回假(失败)
	}

	glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTexDim);          // 获取支持的最大纹理大小

	pPicture->get_Width(&lWidth);                    // 获取图宽度(转换为像素)
	lWidthPixels  = MulDiv(lWidth, GetDeviceCaps(hdcTemp, LOGPIXELSX), 2540);
	pPicture->get_Height(&lHeight);                    // 获取图高度(转换为像素)
	lHeightPixels  = MulDiv(lHeight, GetDeviceCaps(hdcTemp, LOGPIXELSY), 2540);

	// 将图像调整为最接近的2次方
	if (lWidthPixels <= glMaxTexDim) // 图像宽度是否小于或等于卡限制
		lWidthPixels = 1 << (int)floor((log((double)lWidthPixels)/log(2.0f)) + 0.5f); 
	else // 否则设置宽度为 "最大功率的两个" 卡可以处理
		lWidthPixels = glMaxTexDim;

	if (lHeightPixels <= glMaxTexDim) // Is Image Height Greater Than Cards Limit
		lHeightPixels = 1 << (int)floor((log((double)lHeightPixels)/log(2.0f)) + 0.5f);
	else // Otherwise Set Height To "Max Power Of Two" That The Card Can Handle
		lHeightPixels = glMaxTexDim;

	//  创建临时位图
	BITMAPINFO  bi = {0};                        // 我们要的位图类型
	DWORD    *pBits = 0;                        // 指向位图位的指针

	bi.bmiHeader.biSize      = sizeof(BITMAPINFOHEADER);        // 设定结构尺寸
	bi.bmiHeader.biBitCount    = 32;                  // 32 位
	bi.bmiHeader.biWidth    = lWidthPixels;              // Power Of Two Width
	bi.bmiHeader.biHeight    = lHeightPixels;            // 使图像向上(正Y轴)
	bi.bmiHeader.biCompression  = BI_RGB;                // RGB 编码
	bi.bmiHeader.biPlanes    = 1;                  // 1 Bitplane

	//  以这种方式创建位图允许我们指定颜色深度,并允许我们立即访问位
	hbmpTemp = CreateDIBSection(hdcTemp, &bi, DIB_RGB_COLORS, (void**)&pBits, 0, 0);

	if(!hbmpTemp)                            // Did Creation Fail?
	{
		DeleteDC(hdcTemp);                        // 删除设备描述表(上下文)
		pPicture->Release();                      // 递减图片参考计数
		return FALSE;                          // Return False (Failure)
	}

	SelectObject(hdcTemp, hbmpTemp);                  // 选择处理我们的 temp DC 和我们的 temp 位图对象

	// 将图片渲染到位图上
	pPicture->Render(hdcTemp, 0, 0, lWidthPixels, lHeightPixels, 0, lHeight, lWidth, -lHeight, 0);

	// 将BGR转换为RGB格式,并添加255的α值
	for(long i = 0; i < lWidthPixels * lHeightPixels; i++)        // 循环通过所有像素
	{
		BYTE* pPixel  = (BYTE*)(&pBits[i]);              // 获取当前像素
		BYTE temp    = pPixel[0];                  // 将第一种颜色存储在 temp 变量(蓝色)中
		pPixel[0]    = pPixel[2];                  // 将红色值移到正确位置(第一个)
		pPixel[2]    = temp;                      // 将 temp 值移到正确的蓝色位置(第3个)

		// 这将使任何黑色像素完全透明(如果需要,可以硬编码该值)
		if ((pPixel[0]==0) && (pPixel[1]==0) && (pPixel[2]==0))      // 像素是完全黑色的吗?
			pPixel[3]  = 0;                      // 将α值设置为0
		else                              // Otherwise
			pPixel[3]  = 255;                      // Set The Alpha Value To 255
	}

	glGenTextures(1, &texid);                      // 创建纹理

	// 使用位图中的数据生成典型纹理
	glBindTexture(GL_TEXTURE_2D, texid);                // 绑定到纹理id
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);    // (针对所需的筛选类型修改此选项)
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // (针对所需的筛选类型修改此选项)
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lWidthPixels, lHeightPixels, 0, GL_RGBA, GL_UNSIGNED_BYTE, pBits);  // (Modify This If You Want Mipmaps)

	DeleteObject(hbmpTemp);                        // Delete The Object
	DeleteDC(hdcTemp);                          // Delete The Device Context

	pPicture->Release();                        // 递减图片参考计数

	//printf( "load %s!" , szPath );
	return TRUE;                            // Return True (都很好)

}

//载入地表图
void loadDibiaoPic(char *szPathName)
{
	// 读入地表纹理
	if(BuildTexture(szPathName, Dibiaotexture)==false)
		printf( "加载地表图失败!" );

}

//设置大小和高度
void setDibiao(GLint w,GLint h,GLint zero)
{
	DibiaoChangX=w;DibiaoKuanZ=h;DibiaoGaoY=zero;
	cout <<"大小和位置:"<< w<<"," <<h<<","<<zero<< '\n';  //
}

//绘制
void DrawDibiao()
{
	//半长宽
	GLfloat bw=DibiaoChangX/2;
	GLfloat bh=DibiaoKuanZ/2;

	// 打开纹理映射
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, Dibiaotexture);

	glBegin(GL_QUADS);
		// 给出法向量
		glNormal3f(0.0f, 1.0f, 0.0f);//向上

		glTexCoord2f(0.0f, 0.0f); glVertex3f(-bw, DibiaoGaoY,  -bh);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( bw, DibiaoGaoY,  -bh);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( bw, DibiaoGaoY,  bh);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-bw, DibiaoGaoY,  bh);
	glEnd();
}

效果图:


无光照图为什么会这么暗?只能期待高手了。





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值