简单渲染流水管线C++代码实现(五)---线段裁剪

线段裁剪是图形学中一个非常重要的东西。
线段裁剪简单来说,就是截取能在屏幕中显示出来的部分,这样做可以减少计算机在渲染过程中的计算量,加快渲染速度。
下面开始实现线段裁剪函数bool ClipLine(int* x1, int* y1, int* x2, int* y2)

1.划分区域,对区域编码

划分区域是为了更好的区分线段所在位置,为裁剪做准备:
线段端点在中心不必处理,若在其他区域,便需要裁剪至中心范围内
在这里插入图片描述
编码由来参照下面的代码

#define _C 0x00 //0000  中心
#define _N 0x01 //0001  北
#define _S 0x02 //0010	南
#define _W 0x04 //0100	西
#define _E 0x08 //1000	东
#define _EN (_E | _N) //1001	东北
#define _ES (_E | _S) //1010	东南
#define _WS (_W | _S) //0110	西南
#define _WN (_W | _N) //0101	西北

2.下面就是判断两点的所属区域

	//缓存,取得两点值,裁剪过程中不能修改原值
	int port1_x = *x1;
	int port1_y = *y1;
	int port2_x = *x2;
	int port2_y = *y2;

	//这里的判断隐藏了一个技巧,取<=  >=是可以避免下面判断0值问题
	char port1 = _C;
	//判断点1的位置
	if (port1_x <= 0)
		port1 |= _W;
	else if (port1_x >= _CLIENT_W)
		port1 |= _E;
	if (port1_y <= 0)
		port1 |= _N;
	else if (port1_y >= _CLIENT_H)
		port1 |= _S;

	char port2 = _C;
	//判断点2的位置
	if (port2_x <= 0)
		port2 |= _W;
	else if (port2_x >= _CLIENT_W)
		port2 |= _E;
	if (port2_y <= 0)
		port2 |= _N;
	else if (port2_y >= _CLIENT_H)
		port2 |= _S;

3.进行初判断

得到点1、点2的位置后,是可以直接去初次判断某些无法裁剪的情况
比如:
在这里插入图片描述
(1)只要线段两端点都在中心(0000)处,不需要裁剪,可以直接绘制
(2)当线段两端点有共同区域时,是不可能绘制出来显示到屏幕中的

	//两点在中心,无需裁剪
	if (port1 == _C && port2 == _C)
		return false;
	//同时包含相同方向,比如东南和东北,都包括东,无需裁剪
	if ((port1 & port2) != 0)
		return false;

4.进行裁剪

(1)正方向(正北、正南、正东、正西)上的裁剪如下
在这里插入图片描述

case _W:
	{
   
		port1_x = 0;
		port1_y = (int)(*y2 + (double)(*x2 * (*y1 - *y2)) / (*x2 - *x1) + 0.5);
		break;
	}

PS:上面的公式中后面+0.5的意义主要是为了double转int时四舍五入,如果不加0.5,编译器会在转换时向下取整,即1.9转为int时为1。
上面举了一个正西的例子,其他三个方向类似推导即可

case _E:
	{
   
		port1_x = _CLIENT_W - 1;
		port1_y = (int)(*y1 - (double)((*x1 - (_CLIENT_W - 1)) * (*y1 - *y2)) / (*x1 - *x2) + 0.5);
		break;
	}
	case _N:
	{
   
		port1_x = (int)(*x1 - *y1 * (double)(*x2 - *x1) / (*y2 - *y1) + 0.5);
		port1_y = 0;
		break;
	}
	case _S:
	{
   
		port1_x = (int)(*x2 - (double)((*x2 - *x1) * (_CLIENT_H - 1 - *y2)) / (*y1 - *y2) + 0.5);
		port1_y = _CLIENT_H - 1;
		break;
	}

(2)非正方向(东北、西北、东南、西南)上的裁剪

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值