📄 dpblend_sphere.cpp
字号:
#include "..\..\lib\Fly3D.h"
#include "gamelib.h"
void dpblend_sphere::init()
{
// initialize creating a normal map if one does not exists
if (normalmap==-1)
{
build_normalmap("sphere_normals.tga");
normalmap=flyengine->get_picture("sphere_normals.tga");
}
}
void dpblend_sphere::build_normalmap(char *file)
{
// creates a normal map for a dpblend_sphere
// and saves it as a 32 bits/pixel TGA image
if (pxlsize==0)
return;
int i,j;
float x,y;
double d;
// create picture
picture p;
p.CreatePicture32(pxlsize,pxlsize);
unsigned char *uc=p.buf[0];
// for each pixel
for( j=0;j<pxlsize;j++ )
{
y=(float)(j-pxlsize/2)/(pxlsize/2);
for( i=0;i<pxlsize;i++ )
{
x=(float)(i-pxlsize/2)/(pxlsize/2);
// if pixel insied dpblend_sphere
d=sqrt(x*x+y*y);
if (d<1.0f)
{
// store pixel normal
uc[0]=(int)(x*127)+128;
uc[1]=(int)(y*127)+128;
uc[2]=(int)(cos(d)*127)+128;
uc[3]=255;
}
else
uc[0]=uc[1]=uc[2]=uc[3]=0;
uc+=4;
}
}
// save TGA image in maps subdir
char name[256];
strcpy(name,flyengine->flydatapath);
strcat(name,"maps\\");
strcat(name,file);
p.SaveTGA(name);
}
int dpblend_sphere::step(int dt)
{
// move as subclass particle
return particle::step(dt);
}
int dpblend_sphere::message(vector& p,float rad,int msg,int param,void *data)
{
// get closest light illuminating object
if (msg==FLYOBJM_ILLUM || msg==FLYOBJM_DYNILLUM)
{
float dist=(pos-p).length();
if (dist<rad && dist<lightdist)
{
lightpos=p;
lightcolor=*((vector *)data);
lightradius=rad;
lightdist=dist;
}
}
return 0;
}
void dpblend_sphere::draw()
{
// draw object as single quad polygon
// always facing the camera
static vector x,y;
x=flyengine->cam->X*radius;
y=flyengine->cam->Y*radius;
// select normal map texture
tc->use(normalmap);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
// alpha test for removing points not in
// dpblend_sphere but in the quad polygon
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER,0);
// if mode 0 or no register combiner extension
if (mode==0 || glCombinerParameterfvNV==0)
{
// just draw polygon with normal map as texture
glColor3f(1,1,1);
glBegin(GL_QUADS);
glTexCoord2f(1,0);
glVertex3f(pos.x+x.x-y.x, pos.y+x.y-y.y, pos.z+x.z-y.z);
glTexCoord2f(1,1);
glVertex3f(pos.x+x.x+y.x, pos.y+x.y+y.y, pos.z+x.z+y.z);
glTexCoord2f(0,1);
glVertex3f(pos.x+y.x-x.x, pos.y+y.y-x.y, pos.z+y.z-x.z);
glTexCoord2f(0,0);
glVertex3f(pos.x-x.x-y.x, pos.y+-x.y-y.y, pos.z-x.z-y.z);
glEnd();
}
else
{
vector dir,color;
// initialize register combiners
init_combiners();
glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &ambient.x);
glEnable(GL_REGISTER_COMBINERS_NV);
// if no lights near
if (lightdist>1e9)
{
// clear color (just ambinet)
glColor4f(0,0,0,0);
color.null();
}
else
{
// compute light direction
dir=(lightpos-pos)*flyengine->cam->mat_t;
dir.normalize();
// store light dir in the primary color
glColor4f(
(dir.x+1.0f)*0.5f,
(dir.y+1.0f)*0.5f,
(dir.z+1.0f)*0.5f,
1.0f);
// set up color based on object diffuse color
// and light distance factor
color=diffuse*lightcolor*(1.0f-lightdist/lightradius);
}
glCombinerParameterfvNV(GL_CONSTANT_COLOR1_NV,&color.x);
// draw quad polygon
glBegin(GL_QUADS);
glTexCoord2f(1,0);
glVertex3f(pos.x+x.x-y.x, pos.y+x.y-y.y, pos.z+x.z-y.z);
glTexCoord2f(1,1);
glVertex3f(pos.x+x.x+y.x, pos.y+x.y+y.y, pos.z+x.z+y.z);
glTexCoord2f(0,1);
glVertex3f(pos.x+y.x-x.x, pos.y+y.y-x.y, pos.z+y.z-x.z);
glTexCoord2f(0,0);
glVertex3f(pos.x-x.x-y.x, pos.y+-x.y-y.y, pos.z-x.z-y.z);
glEnd();
// sets no light
lightdist=1e10;
// disable redister combiners
glDisable(GL_REGISTER_COMBINERS_NV);
}
// disabe alpha test
glDisable(GL_ALPHA_TEST);
}
void dpblend_sphere::init_combiners()
{
// sets up one combiner for dot product of L and N,
// then multiply diffuse and add ambinet
glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 1);
/* Argb = expand(texture0rgb) = N */
glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV,
GL_TEXTURE0_ARB, GL_EXPAND_NORMAL_NV, GL_RGB);
/* Brgb = expand(primaryrgb) = L */
glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV,
GL_PRIMARY_COLOR_NV, GL_EXPAND_NORMAL_NV, GL_RGB);
/* spare0rgb = Argb dot Brgb*/
glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB,
GL_SPARE0_NV, GL_DISCARD_NV, GL_DISCARD_NV,
GL_NONE, GL_NONE, GL_TRUE, GL_FALSE, GL_FALSE);
/* A = one */
glFinalCombinerInputNV(GL_VARIABLE_A_NV,
GL_ONE, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
/* B = EF */
glFinalCombinerInputNV(GL_VARIABLE_B_NV,
GL_E_TIMES_F_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
/* C = zero */
glFinalCombinerInputNV(GL_VARIABLE_C_NV,
GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
/* D = C0 = ambient illumination contribution */
glFinalCombinerInputNV(GL_VARIABLE_D_NV,
GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
/* E = C1 = diffuse material characteristic */
glFinalCombinerInputNV(GL_VARIABLE_E_NV,
GL_CONSTANT_COLOR1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
/* F = spare0rgb = diffuse illumination contribution = L dot N */
glFinalCombinerInputNV(GL_VARIABLE_F_NV,
GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
/* G = one */
glFinalCombinerInputNV(GL_VARIABLE_G_NV,
GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
}
bsp_object *dpblend_sphere::clone()
{
dpblend_sphere *tmp=new dpblend_sphere;
*tmp=*this;
tmp->source=this;
return tmp;
}
int dpblend_sphere::get_custom_param_desc(int i,param_desc *pd)
{
if (pd!=0)
switch(i)
{
case 0:
pd->type='i';
pd->data=&mode;
strcpy(pd->name,"mode");
break;
case 1:
pd->type='i';
pd->data=&pxlsize;
strcpy(pd->name,"pxlsize");
break;
case 2:
pd->type='p';
pd->data=&normalmap;
strcpy(pd->name,"normalmap");
break;
case 3:
pd->type='c';
pd->data=&ambient;
strcpy(pd->name,"ambient");
break;
case 4:
pd->type='c';
pd->data=&diffuse;
strcpy(pd->name,"diffuse");
break;
}
return 5;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -