basictreedrawer.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 462 行
CPP
462 行
#include "StdAfx.h"
// TreeDrawer.cpp: implementation of the CBasicTreeDrawer class.
//
//////////////////////////////////////////////////////////////////////
#include "BasicTreeDrawer.h"
#include "Map/Ground.h"
#include "Game/Camera.h"
#include "Rendering/GL/VertexArray.h"
#include "Map/ReadMap.h"
#include "Rendering/GL/myGL.h"
#include <GL/glu.h> // Header File For The GLu32 Library
#include "Rendering/Textures/Bitmap.h"
#include "mmgr.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CBasicTreeDrawer::CBasicTreeDrawer()
{
lastListClean=0;
TdfParser resources("gamedata/resources.tdf");
CBitmap TexImage;
std::string fn("bitmaps/"+resources.SGetValueDef("gran.bmp","resources\\graphics\\trees\\gran1"));
if (!TexImage.Load(fn))
throw content_error("Could not load tree texture from " + fn);
TexImage.ReverseYAxis();
//unsigned char gran[1024][512][4];
unsigned char (*gran)[512][4]=SAFE_NEW unsigned char[1024][512][4];
if (TexImage.xsize>1){
for(int y=0;y<256;y++){
for(int x=0;x<256;x++){
if(TexImage.mem[(y*256+x)*4]==72 && TexImage.mem[(y*256+x)*4+1]==72){
gran[y][x][0]=33;
gran[y][x][1]=54;
gran[y][x][2]=29;
gran[y][x][3]=0;
} else {
gran[y][x][0]=TexImage.mem[(y*256+x)*4];
gran[y][x][1]=TexImage.mem[(y*256+x)*4+1];
gran[y][x][2]=TexImage.mem[(y*256+x)*4+2];
gran[y][x][3]=255;
}
}
}
}
fn = "bitmaps/"+resources.SGetValueDef("gran2.bmp","resources\\graphics\\trees\\gran2");
if (!TexImage.Load(fn))
throw content_error("Could not load tree texture from file " + fn);
TexImage.ReverseYAxis();
if (TexImage.xsize>1){
for(int y=0;y<256;y++){
for(int x=0;x<256;x++){
if(TexImage.mem[(y*256+x)*4]==72 && TexImage.mem[(y*256+x)*4+1]==72){
gran[y][x+256][0]=33;
gran[y][x+256][1]=54;
gran[y][x+256][2]=29;
gran[y][x+256][3]=0;
} else {
gran[y][x+256][0]=TexImage.mem[(y*256+x)*4];
gran[y][x+256][1]=TexImage.mem[(y*256+x)*4+1];
gran[y][x+256][2]=TexImage.mem[(y*256+x)*4+2];
gran[y][x+256][3]=255;
}
}
}
}
fn = "bitmaps/"+resources.SGetValueDef("birch1.bmp","resources\\graphics\\trees\\birch1");
if (!TexImage.Load(fn))
throw content_error("Could not load tree texture from file " + fn);
TexImage.ReverseYAxis();
if (TexImage.xsize>1){
for(int y=0;y<256;y++){
for(int x=0;x<128;x++){
if(TexImage.mem[(y*128+x)*4]==72 && TexImage.mem[(y*128+x)*4+1]==72){
gran[y+256][x][0]=(unsigned char)(125*0.6f);
gran[y+256][x][1]=(unsigned char)(146*0.7f);
gran[y+256][x][2]=(unsigned char)(82*0.6f);
gran[y+256][x][3]=(unsigned char)(0);
} else {
gran[y+256][x][0]=(unsigned char)(TexImage.mem[(y*128+x)*4]*0.6f);
gran[y+256][x][1]=(unsigned char)(TexImage.mem[(y*128+x)*4+1]*0.7f);
gran[y+256][x][2]=(unsigned char)(TexImage.mem[(y*128+x)*4+2]*0.6f);
gran[y+256][x][3]=255;
}
}
}
}
fn = "bitmaps/"+resources.SGetValueDef("birch2.bmp","resources\\graphics\\trees\\birch2");
if (!TexImage.Load(fn))
throw content_error("Could not load tree texture from file " + fn);
TexImage.ReverseYAxis();
if (TexImage.xsize>1){
for(int y=0;y<256;y++){
for(int x=0;x<128;x++){
if(TexImage.mem[(y*128+x)*4]==72 && TexImage.mem[(y*128+x)*4+1]==72){
gran[y+256][x+128][0]=(unsigned char)(125*0.6f);
gran[y+256][x+128][1]=(unsigned char)(146*0.7f);
gran[y+256][x+128][2]=(unsigned char)(82*0.6f);
gran[y+256][x+128][3]=0;
} else {
gran[y+256][x+128][0]=(unsigned char)(TexImage.mem[(y*128+x)*4]*0.6f);
gran[y+256][x+128][1]=(unsigned char)(TexImage.mem[(y*128+x)*4+1]*0.7f);
gran[y+256][x+128][2]=(unsigned char)(TexImage.mem[(y*128+x)*4+2]*0.6f);
gran[y+256][x+128][3]=255;
}
}
}
}
fn = "bitmaps/"+resources.SGetValueDef("birch3.bmp","resources\\graphics\\trees\\birch3");
if (!TexImage.Load(fn))
throw content_error("Could not load tree texture from file " + fn);
TexImage.ReverseYAxis();
if (TexImage.xsize>1){
for(int y=0;y<256;y++){
for(int x=0;x<256;x++){
if(TexImage.mem[(y*256+x)*4]==72 && TexImage.mem[(y*256+x)*4+1]==72){
gran[y+256][x+256][0]=(unsigned char)(125*0.6f);
gran[y+256][x+256][1]=(unsigned char)(146*0.7f);
gran[y+256][x+256][2]=(unsigned char)(82*0.6f);
gran[y+256][x+256][3]=0;
} else {
gran[y+256][x+256][0]=(unsigned char)(TexImage.mem[(y*256+x)*4]*0.6f);
gran[y+256][x+256][1]=(unsigned char)(TexImage.mem[(y*256+x)*4+1]*0.7f);
gran[y+256][x+256][2]=(unsigned char)(TexImage.mem[(y*256+x)*4+2]*0.6f);
gran[y+256][x+256][3]=255;
}
}
}
}
// create mipmapped texture
CreateTreeTex(treetex,gran[0][0],512,1024);
delete[] gran;
treesX=gs->mapx/TREE_SQUARE_SIZE;
treesY=gs->mapy/TREE_SQUARE_SIZE;
trees=SAFE_NEW TreeSquareStruct[treesX*treesY];
for(int y=0;y<treesY;y++){
for(int x=0;x<treesX;x++){
trees[y*treesX+x].displist=0;
trees[y*treesX+x].farDisplist=0;
}
}
}
CBasicTreeDrawer::~CBasicTreeDrawer()
{
glDeleteTextures (1, &treetex);
for(int y=0;y<treesY;y++){
for(int x=0;x<treesX;x++){
if(trees[y*treesX+x].displist)
glDeleteLists(trees[y*treesX+x].displist,1);
if(trees[y*treesX+x].farDisplist)
glDeleteLists(trees[y*treesX+x].farDisplist,1);
}
}
delete[] trees;
}
static CVertexArray* va;
static void inline SetArray(float t1,float t2,float3 v)
{
va->AddVertexT(v,t1,t2);
}
struct CBasicTreeSquareDrawer : CReadMap::IQuadDrawer
{
CBasicTreeSquareDrawer() {td=0;}
void DrawQuad (int x,int y);
CBasicTreeDrawer *td;
int cx,cy;
float treeDistance;
};
void CBasicTreeSquareDrawer::DrawQuad (int x,int y)
{
int treesX = td->treesX;
CBasicTreeDrawer::TreeSquareStruct* tss=&td->trees[y*treesX+x];
float3 dif;
dif.x=camera->pos.x-(x*SQUARE_SIZE*TREE_SQUARE_SIZE + SQUARE_SIZE*TREE_SQUARE_SIZE/2);
dif.y=0;
dif.z=camera->pos.z-(y*SQUARE_SIZE*TREE_SQUARE_SIZE + SQUARE_SIZE*TREE_SQUARE_SIZE/2);
float dist=dif.Length();
dif/=dist;
if(dist<SQUARE_SIZE*TREE_SQUARE_SIZE*treeDistance*2 && dist>SQUARE_SIZE*TREE_SQUARE_SIZE*(treeDistance)){//far trees
tss->lastSeenFar=gs->frameNum;
if(!tss->farDisplist || dif.dot(tss->viewVector)<0.97f){
va=GetVertexArray();
va->Initialize();
tss->viewVector=dif;
if(!tss->farDisplist)
tss->farDisplist=glGenLists(1);
float3 up(0,1,0);
float3 side=up.cross(dif);
for(std::map<int,CBasicTreeDrawer::TreeStruct>::iterator ti=tss->trees.begin();ti!=tss->trees.end();++ti){
CBasicTreeDrawer::TreeStruct* ts=&ti->second;
if(ts->type<8){
float3 base(ts->pos);
float height=MAX_TREE_HEIGHT;
float width=MAX_TREE_HEIGHT*0.3f;
SetArray(0,0,base+side*width);
SetArray(0,0.25f,base+side*width+float3(0,height,0));
SetArray(0.5f,0.25f,base-side*width+float3(0,height,0));
SetArray(0.5f,0,base-side*width);
} else {
float3 base(ts->pos);
float height=MAX_TREE_HEIGHT;
float width=MAX_TREE_HEIGHT*0.3f;
SetArray(0,0.25f,base+side*width);
SetArray(0,0.5f,base+side*width+float3(0,height,0));
SetArray(0.25f,0.5f,base-side*width+float3(0,height,0));
SetArray(0.25f,0.25f,base-side*width);
}
}
glNewList(td->trees[y*treesX+x].farDisplist,GL_COMPILE);
va->DrawArrayT(GL_QUADS);
glEndList();
}
if(dist>SQUARE_SIZE*TREE_SQUARE_SIZE*(treeDistance*2-1)){
float trans=(SQUARE_SIZE*TREE_SQUARE_SIZE*treeDistance*2-dist)/(SQUARE_SIZE*TREE_SQUARE_SIZE);
glEnable(GL_BLEND);
glColor4f(1,1,1,trans);
glAlphaFunc(GL_GREATER,(SQUARE_SIZE*TREE_SQUARE_SIZE*treeDistance*2-dist)/(SQUARE_SIZE*TREE_SQUARE_SIZE*2));
} else {
glColor4f(1,1,1,1);
glDisable(GL_BLEND);
glAlphaFunc(GL_GREATER,0.5f);
}
glCallList(tss->farDisplist);
}
if(dist<SQUARE_SIZE*TREE_SQUARE_SIZE*treeDistance){ //midle distance trees
tss->lastSeen=gs->frameNum;
if(!tss->displist){
va=GetVertexArray();
va->Initialize();
tss->displist=glGenLists(1);
for(std::map<int,CBasicTreeDrawer::TreeStruct>::iterator ti=tss->trees.begin();ti!=tss->trees.end();++ti){
CBasicTreeDrawer::TreeStruct* ts=&ti->second;
if(ts->type<8){
float3 base(ts->pos);
float height=MAX_TREE_HEIGHT;
float width=MAX_TREE_HEIGHT*0.3f;
SetArray(0,0,base+float3(width,0,0));
SetArray(0,0.25f,base+float3(width,height,0));
SetArray(0.5f,0.25f,base+float3(-width,height,0));
SetArray(0.5f,0,base+float3(-width,0,0));
SetArray(0,0,base+float3(0,0,width));
SetArray(0,0.25f,base+float3(0,height,width));
SetArray(0.5f,0.25f,base+float3(0,height,-width));
SetArray(0.5f,0,base+float3(0,0,-width));
width*=1.2f;
SetArray(0.5f,0,base+float3(width,height*0.25f,0));
SetArray(0.5f,0.25f,base+float3(0,height*0.25f,-width));
SetArray(1,0.25f,base+float3(-width,height*0.25f,0));
SetArray(1,0,base+float3(0,height*0.25f,width));
} else {
float3 base(ts->pos);
float height=MAX_TREE_HEIGHT;
float width=MAX_TREE_HEIGHT*0.3f;
SetArray(0,0.25f,base+float3(width,0,0));
SetArray(0,0.5f,base+float3(width,height,0));
SetArray(0.25f,0.5f,base+float3(-width,height,0));
SetArray(0.25f,0.25f,base+float3(-width,0,0));
SetArray(0.25f,0.25f,base+float3(0,0,width));
SetArray(0.25f,0.5f,base+float3(0,height,width));
SetArray(0.5f,0.5f,base+float3(0,height,-width));
SetArray(0.5f,0.25f,base+float3(0,0,-width));
width*=1.2f;
SetArray(0.5f,0.25f,base+float3(width,height*0.3f,0));
SetArray(0.5f,0.5f,base+float3(0,height*0.3f,-width));
SetArray(1,0.5f,base+float3(-width,height*0.3f,0));
SetArray(1,0.25f,base+float3(0,height*0.3f,width));
}
}
glNewList(tss->displist,GL_COMPILE);
va->DrawArrayT(GL_QUADS);
glEndList();
}
glColor4f(1,1,1,1);
glDisable(GL_BLEND);
glAlphaFunc(GL_GREATER,0.5f);
glCallList(tss->displist);
}
}
void CBasicTreeDrawer::Draw(float treeDistance,bool drawReflection)
{
glBindTexture(GL_TEXTURE_2D, treetex);
glEnable(GL_ALPHA_TEST);
int cx=(int)(camera->pos.x/(SQUARE_SIZE*TREE_SQUARE_SIZE));
int cy=(int)(camera->pos.z/(SQUARE_SIZE*TREE_SQUARE_SIZE));
CBasicTreeSquareDrawer drawer;
drawer.td = this;
drawer.cx = cx;
drawer.cy = cy;
drawer.treeDistance = treeDistance;
readmap->GridVisibility (camera, TREE_SQUARE_SIZE, treeDistance*2*SQUARE_SIZE*TREE_SQUARE_SIZE, &drawer);
int startClean=lastListClean*20%(treesX*treesY);
lastListClean=gs->frameNum;
int endClean=gs->frameNum*20%(treesX*treesY);
if(startClean>endClean){
for(int a=startClean;a<treesX*treesY;a++){
if(trees[a].lastSeen<gs->frameNum-50 && trees[a].displist){
glDeleteLists(trees[a].displist,1);
trees[a].displist=0;
}
if(trees[a].lastSeenFar<gs->frameNum-50 && trees[a].farDisplist){
glDeleteLists(trees[a].farDisplist,1);
trees[a].farDisplist=0;
}
}
for(int a=0;a<endClean;a++){
if(trees[a].lastSeen<gs->frameNum-50 && trees[a].displist){
glDeleteLists(trees[a].displist,1);
trees[a].displist=0;
}
if(trees[a].lastSeenFar<gs->frameNum-50 && trees[a].farDisplist){
glDeleteLists(trees[a].farDisplist,1);
trees[a].farDisplist=0;
}
}
} else {
for(int a=startClean;a<endClean;a++){
if(trees[a].lastSeen<gs->frameNum-50 && trees[a].displist){
glDeleteLists(trees[a].displist,1);
trees[a].displist=0;
}
if(trees[a].lastSeenFar<gs->frameNum-50 && trees[a].farDisplist){
glDeleteLists(trees[a].farDisplist,1);
trees[a].farDisplist=0;
}
}
}
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
}
void CBasicTreeDrawer::Update()
{
}
void CBasicTreeDrawer::CreateTreeTex(GLuint& texnum, unsigned char *data, int xsize, int ysize)
{
glGenTextures(1, &texnum);
glBindTexture(GL_TEXTURE_2D, texnum);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
int mipnum=0;
glTexImage2D(GL_TEXTURE_2D,mipnum,GL_RGBA8 ,xsize, ysize,0, GL_RGBA, GL_UNSIGNED_BYTE, data);
while(xsize!=1 || ysize!=1){
mipnum++;
if(xsize!=1)
xsize/=2;
if(ysize!=1)
ysize/=2;
for(int y=0;y<ysize;++y){
for(int x=0;x<xsize;++x){
/* for(int a=0;a<3;a++){
int temp=0;
int num=0;
if(data[(y*2*xsize*2+x*2)*4+3]){
temp+=data[(y*2*xsize*2+x*2)*4+a];
num++;
}
if(data[((y*2+1)*xsize*2+x*2)*4+3]){
temp+=data[((y*2+1)*xsize*2+x*2)*4+a];
num++;
}
if(data[((y*2)*xsize*2+x*2+1)*4+3]){
temp+=data[((y*2)*xsize*2+x*2+1)*4+a];
num++;
}
if(data[((y*2+1)*xsize*2+x*2+1)*4+3]){
temp+=data[((y*2+1)*xsize*2+x*2+1)*4+a];
num++;
}
if(num>1)
temp/=num;
data[(y*xsize+x)*4+a]=temp;
}
*/ data[(y*xsize+x)*4+0]=(data[(y*2*xsize*2+x*2)*4+0]+data[((y*2+1)*xsize*2+x*2)*4+0]+data[(y*2*xsize*2+x*2+1)*4+0]+data[((y*2+1)*xsize*2+x*2+1)*4+0])/4;
data[(y*xsize+x)*4+1]=(data[(y*2*xsize*2+x*2)*4+1]+data[((y*2+1)*xsize*2+x*2)*4+1]+data[(y*2*xsize*2+x*2+1)*4+1]+data[((y*2+1)*xsize*2+x*2+1)*4+1])/4;
data[(y*xsize+x)*4+2]=(data[(y*2*xsize*2+x*2)*4+2]+data[((y*2+1)*xsize*2+x*2)*4+2]+data[(y*2*xsize*2+x*2+1)*4+2]+data[((y*2+1)*xsize*2+x*2+1)*4+2])/4;
data[(y*xsize+x)*4+3]=(data[(y*2*xsize*2+x*2)*4+3]+data[((y*2+1)*xsize*2+x*2)*4+3]+data[(y*2*xsize*2+x*2+1)*4+3]+data[((y*2+1)*xsize*2+x*2+1)*4+3])/4;
if(data[(y*xsize+x)*4+3]>=127){
data[(y*xsize+x)*4+3]=255;
} else {
data[(y*xsize+x)*4+3]=0;
}
}
}
glTexImage2D(GL_TEXTURE_2D,mipnum,GL_RGBA8 ,xsize, ysize,0, GL_RGBA, GL_UNSIGNED_BYTE, data);
}
}
void CBasicTreeDrawer::ResetPos(const float3& pos)
{
int x=(int)(pos.x/TREE_SQUARE_SIZE/SQUARE_SIZE);
int y=(int)(pos.z/TREE_SQUARE_SIZE/SQUARE_SIZE);
int a=y*treesX+x;
if(trees[a].displist){
glDeleteLists(trees[a].displist,1);
trees[a].displist=0;
}
if(trees[a].farDisplist){
glDeleteLists(trees[a].farDisplist,1);
trees[a].farDisplist=0;
}
}
void CBasicTreeDrawer::AddTree(int type, float3 pos, float size)
{
TreeStruct ts;
ts.pos=pos;
ts.type=type;
int hash=(int)pos.x+((int)(pos.z))*20000;
int square=((int)pos.x)/(SQUARE_SIZE*TREE_SQUARE_SIZE)+((int)pos.z)/(SQUARE_SIZE*TREE_SQUARE_SIZE)*treesX;
trees[square].trees[hash]=ts;
ResetPos(pos);
}
void CBasicTreeDrawer::DeleteTree(float3 pos)
{
int hash=(int)pos.x+((int)(pos.z))*20000;
int square=((int)pos.x)/(SQUARE_SIZE*TREE_SQUARE_SIZE)+((int)pos.z)/(SQUARE_SIZE*TREE_SQUARE_SIZE)*treesX;
trees[square].trees.erase(hash);
ResetPos(pos);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?