MFC背面剔除算法

本文是基于之前的三维变换三维变换完成的

首先需要添加一个向量类CVector

Vector.h
#pragma once
#include"P3.h"
#include<math.h>
class CVector
{
public:
	CVector(void);
	virtual ~CVector(void);
	CVector(double x, double y, double z);
	CVector(const CP3& p);
	CVector(const CP3& p0,const CP3& p1);
	double Magnitide(void);//计算向量的模
	CVector Normalize(void);//归一化向量
	friend CVector operator + (const CVector& v0, const CVector& v1);
	friend CVector operator - (const CVector& v0, const CVector& v1);
	friend CVector operator * (const CVector& v, double scalar);
	friend CVector operator * (double scalar, const CVector& v);
	friend CVector operator / (const CVector& v0, double scalar);
	friend double DotProduct(const CVector& v0, const CVector& v1);//点积
	friend CVector CrossProduct (const CVector& v0, const CVector& v1);//叉积
private:
	double x, y, z;
};
Vector.app
#include "pch.h"
#include "Vector.h"

CVector::CVector(void)
{
	x = 0.0, y = 0.0, z = 1.0;
}

CVector::~CVector(void)
{
}

CVector::CVector(double x, double y, double z)
{
	this->x = x;
	this->y = y;
	this->z = z;
}

CVector::CVector(const CP3& p)
{
	x = p.x;
	y = p.y;
	z = p.z;
}

CVector::CVector(const CP3& p0, const CP3& p1)
{
	x = p1.x - p0.x;
	y = p1.y - p0.y;
	z = p1.z - p0.z;
}

double CVector::Magnitide(void)
{
	return sqrt(x * x + y * y + z * z);
}

CVector CVector::Normalize(void)
{
	CVector vector;
	double magnitude = sqrt(x * x + y * y + z * z);
	if (fabs(magnitude) < 1e-4) {
		magnitude = 1.0;
	}
	vector.x = x / magnitude;
	vector.y = y / magnitude;
	vector.z = z / magnitude;
	return vector;
}

CVector operator+(const CVector& v0, const CVector& v1)
{
	CVector vector;
	vector.x = v1.x + v0.x;
	vector.y = v1.y + v0.y;
	vector.z = v1.z + v0.z;
	return vector;
}

CVector operator-(const CVector& v0, const CVector& v1)
{
	CVector vector;
	vector.x = v1.x - v0.x;
	vector.y = v1.y - v0.y;
	vector.z = v1.z - v0.z;
	return vector;
}

CVector operator*(const CVector& v, double scalar)
{
	CVector vector;
	vector.x = v.x * scalar;
	vector.y = v.y * scalar;
	vector.z = v.z * scalar;
	return vector;
}

CVector operator*(double scalar, const CVector& v)
{
	CVector vector;
	vector.x = v.x * scalar;
	vector.y = v.y * scalar;
	vector.z = v.z * scalar;
	return vector;
}

CVector operator/(const CVector& v0, double scalar)
{
	CVector vector;
	vector.x = v0.x / scalar;
	vector.y = v0.y / scalar;
	vector.z = v0.z / scalar;
	return vector;
}

double DotProduct(const CVector& v0, const CVector& v1)
{
	return (v0.x * v1.x + v0.y * v1.y + v0.z * v1.z);
}

CVector CrossProduct(const CVector& v0, const CVector& v1)
{
	CVector vector;
	vector.x = v0.y * v1.z - v0.z * v1.y;
	vector.y = v0.z * v1.x - v0.x * v1.z;
	vector.z = v0.x * v1.y - v0.y * v1.x;
	return vector;
}
在这之后我们将Vector.h导入Cube.h,然后加入私有变量 CP3 quardrP[4],并修改Cube.app中的三个Draw函数
void CCube::Draw(CDC* pDC)
{
	CP2 ScreenPoint, temp;
	CP3 ViewPoint = projection.EyePoint;
	for (int nFacet = 0; nFacet < 6; nFacet++)
	{
		for (int i = 0; i < 4; i++) {
			quardrP[i] = P[F[nFacet].Index[i]];
		}
		CVector ViewVector(quardrP[0], ViewPoint);//视向量
		ViewVector = ViewVector.Normalize();
		CVector Vector01(quardrP[0], quardrP[1]);
		CVector Vector02(quardrP[0], quardrP[2]);
		CVector Vector03(quardrP[0], quardrP[3]);//三条边向量
		CVector FacetNormalA = CrossProduct(Vector01, Vector02);
		CVector FacetNormalB = CrossProduct(Vector02, Vector03);
		CVector FacetNormal = (FacetNormalA + FacetNormalB);//面法向量
		FacetNormal = FacetNormal.Normalize();
		if (DotProduct(ViewVector, FacetNormal) >= 0) {
			for (int nPoint = 0; nPoint < 4; nPoint++)
			{
				//ScreenPoint.x = P[F[nFacet].Index[nPoint]].x;
				//ScreenPoint.y = P[F[nFacet].Index[nPoint]].y;
				ScreenPoint = projection.OrthogonalProjection(P[F[nFacet].Index[nPoint]]);
				if (0 == nPoint)
				{
					pDC->MoveTo(ROUND(ScreenPoint.x), ROUND(ScreenPoint.y));
					temp = ScreenPoint;
				}
				else
				{
					pDC->LineTo(ROUND(ScreenPoint.x), ROUND(ScreenPoint.y));
				}
			}
			pDC->LineTo(ROUND(temp.x), ROUND(temp.y));
		}
	}
}

void CCube::Draw2(CDC* pDC)
{
	CP2 ScreenPoint, temp;
	CP3 ViewPoint = projection.EyePoint;
	for (int nFacet = 0; nFacet < 6; nFacet++)
	{
		for (int i = 0; i < 4; i++) {
			quardrP[i] = P[F[nFacet].Index[i]];
		}
		CVector ViewVector(quardrP[0], ViewPoint);
		ViewVector = ViewVector.Normalize();
		CVector Vector01(quardrP[0], quardrP[1]);
		CVector Vector02(quardrP[0], quardrP[2]);
		CVector Vector03(quardrP[0], quardrP[3]);
		CVector FacetNormalA = CrossProduct(Vector01, Vector02);
		CVector FacetNormalB = CrossProduct(Vector02, Vector03);
		CVector FacetNormal = (FacetNormalA + FacetNormalB);//面法向量
		FacetNormal = FacetNormal.Normalize();
		if (DotProduct(ViewVector, FacetNormal) >= 0) {
			for (int nPoint = 0; nPoint < 4; nPoint++)
			{
				//ScreenPoint.x = P[F[nFacet].Index[nPoint]].x - 0.3536 * P[F[nFacet].Index[nPoint]].z;
				//ScreenPoint.y = P[F[nFacet].Index[nPoint]].y - 0.3536 * P[F[nFacet].Index[nPoint]].z;
				ScreenPoint = projection.ObliqueProjection(P[F[nFacet].Index[nPoint]]);
				if (0 == nPoint)
				{
					pDC->MoveTo(ROUND(ScreenPoint.x), ROUND(ScreenPoint.y));
					temp = ScreenPoint;
				}
				else
				{
					pDC->LineTo(ROUND(ScreenPoint.x), ROUND(ScreenPoint.y));
				}
			}
			pDC->LineTo(ROUND(temp.x), ROUND(temp.y));
		}
	}
}

void CCube::Draw3(CDC* pDC)
{
	CP2 ScreenPoint, temp;
	CP3 ViewPoint = projection.EyePoint;
	for (int nFacet = 0; nFacet < 6; nFacet++)
	{

		for (int i = 0; i < 4; i++) {
			quardrP[i] = P[F[nFacet].Index[i]];
		}
		CVector ViewVector(quardrP[0], ViewPoint);
		ViewVector = ViewVector.Normalize();
		CVector Vector01(quardrP[0], quardrP[1]);
		CVector Vector02(quardrP[0], quardrP[2]);
		CVector Vector03(quardrP[0], quardrP[3]);
		CVector FacetNormalA = CrossProduct(Vector01, Vector02);
		CVector FacetNormalB = CrossProduct(Vector02, Vector03);
		CVector FacetNormal = (FacetNormalA + FacetNormalB);//面法向量
		FacetNormal = FacetNormal.Normalize();
		if (DotProduct(ViewVector, FacetNormal) >= 0) {
			for (int nPoint = 0; nPoint < 4; nPoint++)
			{
				ScreenPoint = projection.PerspectiveProjection(P[F[nFacet].Index[nPoint]]);
				if (0 == nPoint)
				{
					pDC->MoveTo(ROUND(ScreenPoint.x), ROUND(ScreenPoint.y));
					temp = ScreenPoint;
				}
				else
				{
					pDC->LineTo(ROUND(ScreenPoint.x), ROUND(ScreenPoint.y));
				}
			}
			pDC->LineTo(ROUND(temp.x), ROUND(temp.y));
		}
	}
}
效果展示

在这里插入图片描述

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值