loop & butterfly subdivison

这篇博客主要介绍了在作业中应用的Loop细分算法和Butterfly细分算法。Loop算法参考了http://2n1.org/opengl/proj2/的实现,而Butterfly算法则依照PPT的描述进行。博客中提供了Loop.h文件和Butterfly的相关内容。
摘要由CSDN通过智能技术生成

还是作业的一部分……


loop借鉴了http://2n1.org/opengl/proj2/里面的算法, 感谢!


butterfly则是根据ppt的算法。


一下是loop。h

#ifndef LOOP_H_
#define LOOP_H_

#include "halfedge_vector.h"
#define PI 3.14159265359

#include <assert.h>

halfegde_point getMiddlePoint(halfegde_point a, halfegde_point b)
{
	halfegde_point newp1;

	newp1.x = (a.x+b.x)/2;
	newp1.y = (a.y+b.y)/2;
	newp1.z = (a.z+b.z)/2;

	newp1.isnew = true;
	newp1.edge_index = -1;

	newp1.beighbour.clear();

	return newp1;
}

void addEdge(int p1, int p2, int p3, vector<halfegde_point> &p, vector<halfegde> &e, vector<halfedge_face> &f) 
{
	halfedge_face f1;
	f.push_back(f1);
	int fi = f.size()-1;

	halfegde e1, e2, e3;
	e.push_back(e1);
	e.push_back(e2);
	e.push_back(e3);

	int ei1, ei2, ei3;
	ei3 = e.size()-1;
	ei2 = ei3-1;
	ei1 = ei2-1;

	e[ei1].original_point_index = p1;
	e[ei1].next_edge_index = ei2;
	e[ei1].previous_edge_index = ei3;
	e[ei1].twin_edge_index = -1;
	e[ei1].face_index = fi;
	e[ei1].split_point_index = -1;
	e[ei1].issplited = false;
	p[p1].edge_index = ei1;

	e[ei2].original_point_index = p2;
	e[ei2].next_edge_index = ei3;
	e[ei2].previous_edge_index = ei1;
	e[ei2].twin_edge_index = -1;
	e[ei2].face_index = fi;
	e[ei2].split_point_index = -1;
	e[ei2].issplited = false;
	p[p2].edge_index = ei2;

	e[ei3].original_point_index = p3;
	e[ei3].next_edge_index = ei1;
	e[ei3].previous_edge_index = ei2;
	e[ei3].twin_edge_index = -1;
	e[ei3].face_index = fi;
	e[ei3].split_point_index = -1;
	e[ei3].issplited = false;
	p[p3].edge_index = ei3;

	f[fi].one_edge_index = ei1;
}

void update_newpoint(vector<halfegde_point>&p, vector<halfedge_face>f, vector<halfegde>e, vector<halfegde_point> &p2)
{
	// points initial
	for (int i = 0; i< p.size(); i++)
	{
		// is it right?
		// address or data?

		halfegde_point tmp;
		tmp.x = p[i].x;
		tmp.y = p[i].y;
		tmp.z = p[i].z;
		tmp.isnew = p[i].isnew;
		tmp.edge_index = p[i].edge_index;

		for (int j  = 0; j< p[i].beighbour.size(); j++)
		{
			tmp.beighbour.push_back(p[i].beighbour[j]);
		}

		p2.push_back(tmp);
	}

	for (int i = 0; i< p.size(); i++)
	{
		vector<int> neigh = p[i].beighbour;

		int n = neigh.size();
		float bn = 1.25-(3+2*cos(2*PI/n))*(3+2*cos(2*PI/n))/32;
		float an = n*(1-bn)/bn;

		float x = 0, y = 0, z = 0;

		for (int j = 0; j< n; j++)
		{
			x+= p[neigh[j]].x;
			y+= p[neigh[j]].y;
			z+= p[neigh[j]].z;
		}

		p2[i].x = (p[i].x*an+x)/(an+n);
		p2[i].y = (p[i].y*an+y)/(an+n);
		p2[i].z = (p[i].z*an+z)/(an+n);
	}
}

void getloop(vector<halfegde_point>p, vector<halfedge_face>f, vector<halfegde>e, 
	vector<halfegde_point> &p2, vector<halfedge_face> &f2, vector<halfegde> &e2)
{
	// points initial
	for (int i = 0; i< p.size(); i++)
	{
		// is it right?
		// address or data?

		halfegde_point tmp;
		tmp.x = p[i].x;
		tmp.y = p[i].y;
		tmp.z = p[i].z;
		tmp.isnew = p[i].isnew;
		tmp.edge_index = p[i].edge_index;

		for (int j  = 0; j< p[i].beighbour.size(); j++)
		{
			tmp.beighbour.push_back(p[i].beighbour[j]);
		}

		p2.push_back(tmp);
	}

	// face
	for (int i = 0; i< f.size(); i++)
	{
		int edge1 = f[i].one_edge_index;
		int edge2 = e[edge1].next_edge_index;
		int edge3 = e[edge2].next_edge_index;

		assert(e[edge3].next_edge_index == edge1);

		int point1 = e[edge1].original_point_index;
		int point2 = e[edge2].original_point_index;
		int point3 = e[edge3].original_point_index;

		int newpindex1, newpindex2, newpindex3;
		// e1
		if (e[edge1].issplited)
		{
			newpindex1 = e[edge1].split_point_index;
		}
		else
		{
			halfegde_point newp1 = getMiddlePoint(p[point1], p[point2]);
			p2.push_back(newp1);
			newpindex1 = p2.size()-1;

			e[edge1].issplited = true;
			e[edge1].split_point_index = newpindex1;
			int etwin = e[edge1].twin_edge_index;
			if (etwin != -1)
			{
				e[etwin].issplited = true;
				e[etwin].split_point_index = newpindex1;
			}

		}

		// e2
		if (e[edge2].issplited)
		{
			newpindex2 = e[edge2].split_point_index;
		}
		else
		{
			halfegde_point newp2 = getMiddlePoint(p[point2], p[point3]);
			p2.push_back(newp2);
			newpindex2 = p2.size()-1;

			e[edge2].issplited = true;
			e[edge2].split_point_index = newpindex2;
			int etwin = e[edge2].twin_edge_index;
			if (etwin != -1)
			{
				e[etwin].issplited = true;
				e[etwin].split_point_index = newpindex2;
			}
		}

		// e3
		if (e[edge3].issplited)
		{
			newpindex3 = e[edge3].split_point_index;
		}
		else
		{
			halfegde_point newp3 = getMiddlePoint(p[point3], p[point1]);
			p2.push_back(newp3);
			newpindex3 = p2.size()-1;

			e[edge3].issplited = true;
			e[edge3].split_point_index = newpindex3;
			int etwin = e[edge3].twin_edge_index;
			if (etwin != -1)
			{
				e[etwin].issplited = true;
				e[etwin].split_point_index = newpindex3;
			}
		}

		// add face;
		addEdge(point1, newpindex1, newpindex3,p2, e2, f2);
		addEdge(newpindex1, point2, newpindex2,p2, e2, f2);
		addEdge(newpindex3, newpindex2, point3,p2, e2, f2);
		addEdge(newpindex1, newpindex2, newpindex3,p2, e2, f2);
	}

	// twins edge
	for (int i = 0; i< e2.size(); i++)
	{
		for (int j = i+1; j< e2.size(); j++)
		{
			int abegin = e2[i].original_point_index;
			int aend = e2[e2[i].next_edge_index].original_point_index;

			int bbegin = e2[j].original_point_index;
			int bend  = e2[e2[j].next_edge_index].original_point_index;

			if (abegin == bend
				&&aend == bbegin)
			{
				e2[i].twin_edge_index = j;
				e2[j].twin_edge_index = i;
				break;
			}
			/*
			if (twins(e2, e2[i], e2[j]))
			{
				e2[i].twin_edge_index = j;
				e2[j].twin_edge_index = i;
				break;
			}
			*/
		}
	}

	// update neighbour
	update_neighbour(p2, f2, e2);

	// update points
	vector<halfegde_point> p3;
	update_newpoint(p2, f2, e2, p3);
	p2 = p3;
}

#endif

一下是butterfly


#ifndef BUTTERFLY_H_
#define BUTTERFLY_H_

#include "halfedge_vector.h"
#define PI 3.14159265359

#include <assert.h>

void calculate_points(halfegde_point a, int bindex, vector<halfegde_point> p, float &x, float &y, float &z)
{
	int avaluence = a.beighbour.size();

	if (avaluence == 3)
	{
		float aweight[] = {0.417, -0.083, -0.083};

		// a
		int ab = 0;
		while (a.beighbour[ab] != bindex)
		{
			ab ++;
		}

		for (int i = 0; i< 3; i++)
		{
			int ai = a.beighbour[(ab+i)%3];

			x += p[ai].x*aweight[i];
			y += p[ai].y*aweight[i];
			z += p[ai].z*aweight[i];
		}

		float aw2 = 0.75;

		x += a.x * aw2;
		y += a.y * aw2;
		z += a.z * aw2;
	}

	else if (avaluence == 4)
	{
		float aweight[] = {0.375, 0, -0.125, 0};

		// a
		int ab = 0;
		while (a.beighbour[ab] != bindex)
		{
			ab ++;
		}

		for (int i = 0; i< 4; i++)
		{
			int ai = a.beighbour[(ab+i)%4];

			x += p[ai].x*aweight[i];
			y += p[ai].y*aweight[i];
			z += p[ai].z*aweight[i];
		}

		float aw2 = 0.75;

		x += a.x * aw2;
		y += a.y * aw2;
		z += a.z * aw2;
	}

	else
	{
		float *aweight = new float[avaluence];
		for (int i = 0; i< avaluence; i++)
		{
			aweight[i] = 1.0/avaluence*(0.25+0.5*cos(4*PI/avaluence*i)+cos(2*PI/avaluence*i));
		}

		// a
		int ab = 0;
		while (a.beighbour[ab] != bindex)
		{
			ab ++;
		}

		for (int i = 0; i< avaluence; i++)
		{
			int ai = a.beighbour[(ab+i)%avaluence];

			x += p[ai].x*aweight[i];
			y += p[ai].y*aweight[i];
			z += p[ai].z*aweight[i];
		}

		float aw2 = 1;
		for (int i = 0; i< avaluence; i++)
		{
			aw2 -= aweight[i];
		}

		// aw2  =0;

		x += a.x * aw2;
		y += a.y * aw2;
		z += a.z * aw2;

		delete [] aweight;
	}
}

halfegde_point getMiddlePoint(halfegde_point a, int aindex, halfegde_point b, int bindex, vector<halfegde_point> p)
{
	halfegde_point newp1;

	int avaluence = a.beighbour.size();
	int bvalance = b.beighbour.size();


			float x = 0, y = 0, z = 0;

	if (avaluence == 6
		&&bvalance == 6)
	{
		float aweight[] = {0.5, 0.125, -0.0625, 0, -0.0625, 0.125};
		float bweight[] = {0.5, 0, -0.0625, 0, -0.0625, 0};

		// a
		int ab = 0;
		while (a.beighbour[ab] != bindex)
		{
			ab ++;
		}

		int bb = 0;
		while (b.beighbour[bb] != aindex)
		{
			bb ++;
		}

		for (int i = 0; i< 6; i++)
		{
			int ai = a.beighbour[(ab+i)%6];
			int bi = b.beighbour[(bb+i)%6];

			x += p[ai].x*aweight[i] + p[bi].x*bweight[i]; 
			y += p[ai].y*aweight[i] + p[bi].y*bweight[i]; 
			z += p[ai].z*aweight[i] + p[bi].z*bweight[i]; 
		}
	}

	else
	{
		calculate_points(a, bindex, p, x, y, z);
		calculate_points(b, aindex, p, x, y, z);

		x = x/2;
		y = y/2;
		z = z/2;
	}

	newp1.x = x;
	newp1.y = y;
	newp1.z = z;

	newp1.isnew = true;
	newp1.edge_index = -1;

	newp1.beighbour.clear();

	return newp1;
}

void addEdge(int p1, int p2, int p3, vector<halfegde_point> &p, vector<halfegde> &e, vector<halfedge_face> &f) 
{
	halfedge_face f1;
	f.push_back(f1);
	int fi = f.size()-1;

	halfegde e1, e2, e3;
	e.push_back(e1);
	e.push_back(e2);
	e.push_back(e3);

	int ei1, ei2, ei3;
	ei3 = e.size()-1;
	ei2 = ei3-1;
	ei1 = ei2-1;

	e[ei1].original_point_index = p1;
	e[ei1].next_edge_index = ei2;
	e[ei1].previous_edge_index = ei3;
	e[ei1].twin_edge_index = -1;
	e[ei1].face_index = fi;
	e[ei1].split_point_index = -1;
	e[ei1].issplited = false;
	p[p1].edge_index = ei1;

	e[ei2].original_point_index = p2;
	e[ei2].next_edge_index = ei3;
	e[ei2].previous_edge_index = ei1;
	e[ei2].twin_edge_index = -1;
	e[ei2].face_index = fi;
	e[ei2].split_point_index = -1;
	e[ei2].issplited = false;
	p[p2].edge_index = ei2;

	e[ei3].original_point_index = p3;
	e[ei3].next_edge_index = ei1;
	e[ei3].previous_edge_index = ei2;
	e[ei3].twin_edge_index = -1;
	e[ei3].face_index = fi;
	e[ei3].split_point_index = -1;
	e[ei3].issplited = false;
	p[p3].edge_index = ei3;

	f[fi].one_edge_index = ei1;
}

void getbutterfly(vector<halfegde_point>p, vector<halfedge_face>f, vector<halfegde>e, 
	vector<halfegde_point> &p2, vector<halfedge_face> &f2, vector<halfegde> &e2)
{
	// points initial
	for (int i = 0; i< p.size(); i++)
	{
		// is it right?

		halfegde_point tmp;
		tmp.x = p[i].x;
		tmp.y = p[i].y;
		tmp.z = p[i].z;
		tmp.isnew = p[i].isnew;
		tmp.edge_index = p[i].edge_index;

		for (int j  = 0; j< p[i].beighbour.size(); j++)
		{
			tmp.beighbour.push_back(p[i].beighbour[j]);
		}
		p2.push_back(tmp);
	}

	// face
	for (int i = 0; i< f.size(); i++)
	{
		int edge1 = f[i].one_edge_index;
		int edge2 = e[edge1].next_edge_index;
		int edge3 = e[edge2].next_edge_index;

		assert(e[edge3].next_edge_index == edge1);

		int point1 = e[edge1].original_point_index;
		int point2 = e[edge2].original_point_index;
		int point3 = e[edge3].original_point_index;

		int newpindex1, newpindex2, newpindex3;
		// e1
		if (e[edge1].issplited)
		{
			newpindex1 = e[edge1].split_point_index;
		}
		else
		{
			halfegde_point newp1 = getMiddlePoint(p[point1], point1, p[point2], point2, p);
			p2.push_back(newp1);
			newpindex1 = p2.size()-1;

			e[edge1].issplited = true;
			e[edge1].split_point_index = newpindex1;
			int etwin = e[edge1].twin_edge_index;
			if (etwin != -1)
			{
				e[etwin].issplited = true;
				e[etwin].split_point_index = newpindex1;
			}

		}

		// e2
		if (e[edge2].issplited)
		{
			newpindex2 = e[edge2].split_point_index;
		}
		else
		{
			halfegde_point newp2 = getMiddlePoint(p[point2], point2, p[point3], point3, p);
			p2.push_back(newp2);
			newpindex2 = p2.size()-1;

			e[edge2].issplited = true;
			e[edge2].split_point_index = newpindex2;
			int etwin = e[edge2].twin_edge_index;
			if (etwin != -1)
			{
				e[etwin].issplited = true;
				e[etwin].split_point_index = newpindex2;
			}
		}

		// e3
		if (e[edge3].issplited)
		{
			newpindex3 = e[edge3].split_point_index;
		}
		else
		{
			halfegde_point newp3 = getMiddlePoint(p[point3], point3, p[point1], point1, p);
			p2.push_back(newp3);
			newpindex3 = p2.size()-1;

			e[edge3].issplited = true;
			e[edge3].split_point_index = newpindex3;
			int etwin = e[edge3].twin_edge_index;
			if (etwin != -1)
			{
				e[etwin].issplited = true;
				e[etwin].split_point_index = newpindex3;
			}
		}

		// add face;
		addEdge(point1, newpindex1, newpindex3,p2, e2, f2);
		addEdge(newpindex1, point2, newpindex2,p2, e2, f2);
		addEdge(newpindex3, newpindex2, point3,p2, e2, f2);
		addEdge(newpindex1, newpindex2, newpindex3,p2, e2, f2);
	}

	// twins edge
	for (int i = 0; i< e2.size(); i++)
	{
		for (int j = i+1; j< e2.size(); j++)
		{
			int abegin = e2[i].original_point_index;
			int aend = e2[e2[i].next_edge_index].original_point_index;

			int bbegin = e2[j].original_point_index;
			int bend  = e2[e2[j].next_edge_index].original_point_index;

			if (abegin == bend
				&&aend == bbegin)
			{
				e2[i].twin_edge_index = j;
				e2[j].twin_edge_index = i;
				break;
			}
			/*
			if (twins(e2, e2[i], e2[j]))
			{
				e2[i].twin_edge_index = j;
				e2[j].twin_edge_index = i;
				break;
			}
			*/
		}
	}

	// update new point
	update_neighbour(p2, f2, e2);
}

#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值