旋转甜甜圈简单渲染

10 篇文章 0 订阅
6 篇文章 1 订阅

效果

在这里插入图片描述

在这里插入图片描述

思路

旋转曲面(甜甜圈)
均匀取点样
法向量
整体旋转(水平,竖直)
根据法向量给个光线权值
打印

说明

随便写写的,刚好数学学了多元函数,实践一下……
wasd 变换方向。

代码

#include <cstdio>
#include <conio.h>
#include <cmath>
#include <vector>
#include <cstring>
#include <iostream>
using namespace std;

const double Pi=3.14159;

//取点样参数
const int A_DIV=20;
const int B_DIV=80;
const double DA=2*Pi/A_DIV;
const double DB=2*Pi/B_DIV;

//旋转参数
const int a1_DIV=25;
const int a2_DIV=25;

//打印参数
const double XMIN=-3.5;
const double XMAX=3.5;
const double YMIN=-3.5;
const double YMAX=3.5;
const int ROW=30;
const int COL=60;
const int PIXDEP=7;
const char pix[]=" .,o0#@";
double graph[ROW][COL];

struct vector3d {
	double x, y, z;
	
	vector3d(){}
	vector3d(double _x, double _y, double _z): x(_x), y(_y), z(_z) {}
	
	/// 旋转, U' :a  , L' : b  (Pi/180 rad)
	vector3d rotate(double a, double b) {
		a=a*Pi/180;
		b=b*Pi/180;
		static double sa,sb,ca,cb;
		sa=sin(a);
		ca=cos(a);
		sb=sin(b);
		cb=cos(b);
		return vector3d (
			x*(ca)  + y*(-sa*cb)  + z*(-sa*sb) ,
			x*(sa)  + y*(ca*cb)   + z*(ca*sb)  ,
			0       + y*(-sb)     + z*(cb)
		);
	}
	
	/// 甜甜圈该点法向量 
	vector3d normalVector() {
		return vector3d (
			x-(x+x)/sqrt(x*x+y*y),
			y-(y+y)/sqrt(x*x+y*y),
			z
		);
	}
	
	/// 模 
	double norm() {
		return sqrt(x*x+y*y+z*z);
	}
	
	/// cos(夹角) 
	friend double angle(vector3d &P, vector3d &Q) {
		return (P.x*Q.x + P.y*Q.y + P.z*Q.z)/(P.norm()+Q.norm());
	}
};

int main() {
	
	vector<vector3d> pointSamples;
	
	// 取点样 
	for (int i=0; i<A_DIV; i++) {
		for (int j=0; j<B_DIV; j++) {
			pointSamples.emplace_back(vector3d( cos(i*DA)*(2+cos(j*DB)), sin(i*DA)*(2+cos(j*DB)), sin(j*DB)));
		}
	}
	
	
	int a1=0, a2=0, opr;
	vector3d tmp, tmpN, light(0,0,1);
	int indexCol,indexRow;
	double ang;
	while (1) {
		// 输入 
		opr=getch();
		if (opr=='d')
			a1=(a1+1)%a1_DIV;
		else if (opr=='a')
			a1=(a1-1+a1_DIV)%a1_DIV;
		else if (opr=='w')
			a2=(a2+1)%a2_DIV;
		else if (opr=='s')
			a2=(a2-1+a2_DIV)%a2_DIV;
		
		// 渲染
		for (int i=0; i<ROW; i++)
			for (int j=0; j<COL; j++)
				graph[i][j]=0;
		for (vector3d &I: pointSamples) {
			tmp=I.rotate(a1*360/a1_DIV, a2*360/a2_DIV);
			tmpN=I.normalVector().rotate(a1*360/a1_DIV, a2*360/a2_DIV);
			if (tmp.x>=XMIN && tmp.x<=XMAX)
				indexCol=int((tmp.x-XMIN)/((XMAX-XMIN)/COL));
			else continue;
			
			if (tmp.y>=YMIN && tmp.y<=YMAX)
				indexRow=int((tmp.y-YMIN)/((YMAX-YMIN)/ROW));
			else
				continue;
			
			if (tmpN.z>0) {
				ang=angle(tmpN, light);
				graph[indexRow][indexCol]+=max(ang,0.0);
			}
		}
		
		
		// 打印 
		for (int i=0; i<ROW; i++) {
			putchar('\n');
			for (int j=0; j<COL; j++) {
				putchar(pix[min(PIXDEP-1,int(graph[i][j]/(1.5/PIXDEP)))]);
			}
		}
		
		//break;
	}
	 
	
	return 0;
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值