📄 subdiv_mesh.cpp
字号:
#include "..\..\lib\Fly3D.h"
#include "gamelib.h"
void subdiv_mesh::init()
{
subdiv();
}
void subdiv_mesh::draw()
{
if (divmesh)
{
if (flyengine->hwlights)
{
divmesh->color.vec(1,1,1,1);
dynlights.init_draw(this);
}
else if (node)
{
divmesh->color=node->color+dynlight;
dynlight.null();
}
glPushMatrix();
glTranslatef(pos.x,pos.y,pos.z);
glMultMatrixf((float *)&mat);
divmesh->draw();
glPopMatrix();
if (flyengine->hwlights)
dynlights.end_draw();
}
}
bsp_object *subdiv_mesh::clone()
{
subdiv_mesh *tmp=new subdiv_mesh;
*tmp=*this;
tmp->source=this;
return tmp;
}
int subdiv_mesh::get_custom_param_desc(int i,param_desc *pd)
{
if (pd!=0)
switch(i)
{
case 0:
pd->type='3';
pd->data=&basemesh;
strcpy(pd->name,"basemesh");
break;
case 1:
pd->type='i';
pd->data=&nsubdiv;
strcpy(pd->name,"nsubdiv");
break;
case 2:
pd->type='i';
pd->data=&mode;
strcpy(pd->name,"mode");
break;
}
return 3;
}
int subdiv_mesh::message(vector& p,float rad,int msg,int param,void *data)
{
if (msg==FLYOBJM_CHANGEPARAM && param>=0)
init();
else
if (flyengine->hwlights)
if (msg==FLYOBJM_ILLUM || msg==FLYOBJM_DYNILLUM)
dynlights.add_light(p,*((vector *)data),rad);
else ;
else if (msg==FLYOBJM_ILLUM)
{
float fac=(p-pos).length()/rad;
if (fac<1.0f)
dynlight+=*((vector *)data)*(1.0f-fac);
}
return 0;
}
void subdiv_mesh::reset()
{
if (divmesh) delete divmesh;
if (edges) delete edges;
if (edgefaces) delete edgefaces;
divmesh=0;
edges=0;
edgefaces=0;
nedges=0;
}
void subdiv_mesh::subdiv()
{
reset();
if (source==0 || basemesh==0)
return;
int i;
mesh *m1,*m2;
m1=basemesh->clone();
pos=basemesh->pivotpos;
// for each subdiv step, subdivide mesh m1 into mesh m2
for( i=0;i<nsubdiv;i++ )
{
reset();
// create mesh
m2=new mesh;
// lists all edges for mesh m1
build_edge_list(m1);
// add one vertex at each edge in mesh m2
add_vertices(m1,m2);
// add 3 faces at each original face
add_faces(m1,m2);
// delete mesh m1 and replace it with mesh m2
delete m1;
m1=m2;
}
// store last subdivided mesh
divmesh=m1;
// compute mesh normals
divmesh->compute_normals(MESH_FACENORM|MESH_VERTNORM|MESH_BBOX);
}
int subdiv_mesh::get_edge(int v1,int v2)
{
// returns index into edges list for edge (v1,v2)
int i;
for( i=0;i<nedges;i++ )
if ((edges[i*2]==v1 && edges[i*2+1]==v2) ||
(edges[i*2+1]==v1 && edges[i*2]==v2))
break;
if (i==nedges)
return -1;
return i;
}
int subdiv_mesh::get_valence(int v1)
{
// returns the number of edges using vertex v1
int i,count=0;
for( i=0;i<nedges;i++ )
if (edges[i*2]==v1 || edges[i*2+1]==v1)
count++;
return count;
}
void subdiv_mesh::build_edge_list(mesh *m1)
{
// build the edges list adding all edges from
// all faces (faces can share edges)
int i,j;
for( i=0;i<m1->nf;i++ )
for( j=0;j<3;j++ )
add_edge(
m1->localfaces[i].vert[j]-m1->vert,
m1->localfaces[i].vert[(j+1)%3]-m1->vert,
i);
}
void subdiv_mesh::add_edge(int v1,int v2,int f)
{
// adds a new edge to the edges list
int i=get_edge(v1,v2);
if (i>=0)
// edge already exists, just store face index
edgefaces[i*2+1]=f;
else
{
// add two new entries to the lists
int *tmp;
tmp=new int [nedges*2+2];
memcpy(tmp,edges,sizeof(int)*2*nedges);
if (edges) delete edges;
edges=tmp;
tmp=new int [nedges*2+2];
memcpy(tmp,edgefaces,sizeof(int)*2*nedges);
if (edgefaces) delete edgefaces;
edgefaces=tmp;
// store edge and face
edges[nedges*2]=v1;
edges[nedges*2+1]=v2;
edgefaces[nedges*2]=f;
edgefaces[nedges*2+1]=-1;
nedges++;
}
}
void subdiv_mesh::add_vertices(mesh *m1,mesh *m2)
{
int a,i,j,k,n,v0[2],v1[2],v2[4],e[4],f0[2],f1[4],valence[2];
// alloc vertices for destination mesh m2
m2->nv=nedges + m1->nv;
m2->set_numverts(m2->nv);
// copy mesh m1 vertices into mesh m2
memcpy(m2->vert,m1->vert,sizeof(vector)*m1->nv);
// for all edges from mesh m1
for( i=0;i<nedges;i++ )
{
// find the edge vertices
v0[0]=edges[i*2];
v0[1]=edges[i*2+1];
// find the faces sharing this edge
f0[0]=edgefaces[i*2];
f0[1]=edgefaces[i*2+1];
// place vertex in the center of the edge
m2->vert[m1->nv+i]=(m1->vert[v0[0]]+m1->vert[v0[1]])*0.5f;
if (mode)
{
valence[0]=get_valence(v0[0]);
valence[1]=get_valence(v0[1]);
if (valence[0]<5 || valence[1]<5)
{
vector disp[2];
for( j=0;j<2;j++ )
if (valence[j]==3 || valence[j]==4)
{
disp[j]=m1->vert[v0[j]]*(3.0f/4.0f);
n=0;
if (valence[j]==3)
{
for( k=0;k<nedges;k++ )
if (edges[k*2]==v0[j] || edges[k*2+1]==v0[j])
{
if (edges[k*2]==v0[j])
a=edges[k*2+1];
else a=edges[k*2];
if (a==v0[!j])
disp[j]+=m1->vert[a]*(5.0f/12.0f);
else
disp[j]-=m1->vert[a]*(1.0f/12.0f);
n++;
if (n==3)
break;
}
}
else
{
int vv[4];
for( k=0;k<nedges;k++ )
if (edges[k*2]==v0[j] || edges[k*2+1]==v0[j])
{
if (edges[k*2]==v0[j])
vv[n++]=edges[k*2+1];
else vv[n++]=edges[k*2];
if (n==4)
break;
}
if (f0[1]==-1)
{
continue;
// -1/16 9/16 9/16 -1/16
}
else
{
for( k=0;k<4;k++ )
if (vv[k]==v0[!j])
disp[j]+=m1->vert[vv[k]]*(3.0f/8.0f);
else
{
for( a=0;a<3;a++ )
if (vv[k]==m1->localfaces[f0[0]].vert[a]-m1->vert ||
vv[k]==m1->localfaces[f0[1]].vert[a]-m1->vert)
break;
if (a==3)
disp[j]-=m1->vert[vv[k]]*(1.0f/8.0f);
}
}
}
}
if ((valence[0]==3 || valence[0]==4)&&
(valence[1]==3 || valence[1]==4))
m2->vert[m1->nv+i]=(disp[0]+disp[1])*0.5;
else if (valence[0]==3 || valence[0]==4)
m2->vert[m1->nv+i]=disp[0];
else if (valence[1]==3 || valence[1]==4)
m2->vert[m1->nv+i]=disp[1];
continue;
}
}
if (f0[1]==-1)
continue;
// compute the two v1 vertices
v1[0]=v1[1]=-1;
for( j=0;j<2;j++ )
for( k=0;k<3;k++ )
{
a=m1->localfaces[f0[j]].vert[k]-m1->vert;
if (a!=v0[0] && a!=v0[1])
{
v1[j]=a;
break;
}
}
// compute the four e edges
e[0]=get_edge(v0[0],v1[0]);
e[1]=get_edge(v0[0],v1[1]);
e[2]=get_edge(v0[1],v1[0]);
e[3]=get_edge(v0[1],v1[1]);
if (e[0]==-1 || e[1]==-1 || e[2]==-1 || e[3]==-1)
continue;
// compute the four f faces
for( j=0;j<4;j++ )
if (edgefaces[e[j]*2]!=edgefaces[i*2] &&
edgefaces[e[j]*2]!=edgefaces[i*2+1])
f1[j]=edgefaces[e[j]*2];
else f1[j]=edgefaces[e[j]*2+1];
if (f1[0]==-1 || f1[1]==-1 || f1[2]==-1 || f1[3]==-1)
continue;
// compute the four v2 vertices
v2[0]=v2[1]=v2[2]=v2[3]=-1;
for( j=0;j<4;j++ )
for( k=0;k<3;k++ )
{
a=m1->localfaces[f1[j]].vert[k]-m1->vert;
if (a!=edges[e[j]*2] && a!=edges[e[j]*2+1])
{
v2[j]=a;
break;
}
}
if (v2[0]==-1 || v2[1]==-1 || v2[2]==-1 || v2[3]==-1)
continue;
// move vertex based on v1 and v2 and subdivfactor
m2->vert[m1->nv+i]+=
(m1->vert[v1[0]]+m1->vert[v1[1]])*(1.0f/8.0f)+
(m1->vert[v2[0]]+m1->vert[v2[1]]+m1->vert[v2[2]]+m1->vert[v2[3]])*(-1.0f/16.0f);
}
}
void subdiv_mesh::add_faces(mesh *m1,mesh *m2)
{
int i,j,k,e[3];
float euv[3][2];
// alloc faces for destination mesh m2
m2->nf=m1->nf*4;
m2->set_numfaces(m2->nf,1);
for( i=0;i<m2->nf;i++ )
m2->faces[i]=&m2->localfaces[i];
// for all faces in m1
for( i=j=0;i<m1->nf;i++ )
{
// find edges for mesh m1 face i and
// compute the face edges center texture coordinates
for( k=0;k<3;k++ )
{
e[k]=get_edge(
m1->localfaces[i].vert[k]-m1->vert,
m1->localfaces[i].vert[(k+1)%3]-m1->vert);
euv[k][0]=0.5f*(m1->localfaces[i].uv[k][0]+m1->localfaces[i].uv[(k+1)%3][0]);
euv[k][1]=0.5f*(m1->localfaces[i].uv[k][1]+m1->localfaces[i].uv[(k+1)%3][1]);
}
// create face f1
m2->localfaces[j]=m1->localfaces[i];
m2->localfaces[j].vert[0]=&m2->vert[m1->localfaces[i].vert[0]-m1->vert];
m2->localfaces[j].vert[1]=&m2->vert[e[0]+m1->nv];
m2->localfaces[j].vert[2]=&m2->vert[e[2]+m1->nv];
m2->localfaces[j].uv[1][0]=euv[0][0];
m2->localfaces[j].uv[1][1]=euv[0][1];
m2->localfaces[j].uv[2][0]=euv[2][0];
m2->localfaces[j].uv[2][1]=euv[2][1];
j++;
// create face f2
m2->localfaces[j]=m1->localfaces[i];
m2->localfaces[j].vert[0]=&m2->vert[e[0]+m1->nv];
m2->localfaces[j].vert[1]=&m2->vert[m1->localfaces[i].vert[1]-m1->vert];
m2->localfaces[j].vert[2]=&m2->vert[e[1]+m1->nv];
m2->localfaces[j].uv[0][0]=euv[0][0];
m2->localfaces[j].uv[0][1]=euv[0][1];
m2->localfaces[j].uv[2][0]=euv[1][0];
m2->localfaces[j].uv[2][1]=euv[1][1];
j++;
// create face f3
m2->localfaces[j]=m1->localfaces[i];
m2->localfaces[j].vert[0]=&m2->vert[e[2]+m1->nv];
m2->localfaces[j].vert[1]=&m2->vert[e[1]+m1->nv];
m2->localfaces[j].vert[2]=&m2->vert[m1->localfaces[i].vert[2]-m1->vert];
m2->localfaces[j].uv[0][0]=euv[2][0];
m2->localfaces[j].uv[0][1]=euv[2][1];
m2->localfaces[j].uv[1][0]=euv[1][0];
m2->localfaces[j].uv[1][1]=euv[1][1];
j++;
// create face f4
m2->localfaces[j]=m1->localfaces[i];
m2->localfaces[j].vert[0]=&m2->vert[e[0]+m1->nv];
m2->localfaces[j].vert[1]=&m2->vert[e[1]+m1->nv];
m2->localfaces[j].vert[2]=&m2->vert[e[2]+m1->nv];
m2->localfaces[j].uv[0][0]=euv[0][0];
m2->localfaces[j].uv[0][1]=euv[0][1];
m2->localfaces[j].uv[1][0]=euv[1][0];
m2->localfaces[j].uv[1][1]=euv[1][1];
m2->localfaces[j].uv[2][0]=euv[2][0];
m2->localfaces[j].uv[2][1]=euv[2][1];
j++;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -