c# 画球

news/2024/10/19 5:28:58/

主代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace RayTracing
{public partial class Form1 : Form{public Form1(){InitializeComponent();}private void Form1_Load(object sender, EventArgs e){}private void button1_Click(object sender, EventArgs e){// 眼睛Camera camera = new Camera();camera.loc = new Point3D(0, 0, 10);// 成像平面ViewPlain vp = new ViewPlain();vp.topLeftLoc = new Point3D(-4, 3, 0);vp.w = 8;vp.h = 6;vp.wRes = 800;vp.hRes = 600;// 位图Bitmap bmp = new Bitmap(vp.wRes, vp.hRes);// 求每一小格的偏移量double wStep = vp.w / vp.wRes;double hStep = vp.h / vp.hRes;// 球体Sphere sphere = new Sphere();sphere.Center = new Point3D(0, 0, -10);sphere.Radius = 3;// 在成像平面成像for (int i = 0; i < vp.wRes; i++){for (int j = 0; j < vp.hRes; j++){Point3D pLoc = new Point3D(vp.topLeftLoc.X + wStep * i,vp.topLeftLoc.Y - hStep * j, 0);Ray ray = new Ray(camera.loc, pLoc - camera.loc);ray.Dir.Normalize();HitRecord hitRecord = ray.isHit(sphere);// 光源的位置Point3D lightLoc = new Point3D(-10, 10, 0);// 光源的颜色Color lightColor = Color.FromArgb(0, 255, 0);if (hitRecord.isHit){// 光源到交点的向量Vector3D vLight = lightLoc - hitRecord.hitPoint;vLight.Normalize();// 算夹角double d = vLight * hitRecord.normal;if (d < 0){d = 0;}// 算颜色Color color = Color.FromArgb((int)(d * lightColor.R), (int)(d * lightColor.G), (int)(d * lightColor.B));bmp.SetPixel(i, j, color);}else{bmp.SetPixel(i, j, Color.Gray);}}}pictureBox1.BackgroundImage = bmp;}}
}

相关类

HitRecord

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace RayTracing
{class HitRecord{public bool isHit;public double t;public Point3D hitPoint;public Vector3D normal;}
}

Point3D

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace RayTracing
{class Point3D{// 私有的字段private double x;private double y;private double z;// 公共的属性public double X { get => x; set => x = value; }public double Y { get => y; set => y = value; }public double Z { get => z; set => z = value; }// 构造函数public Point3D(){x = 0;y = 0;z = 0;}public Point3D(double x, double y, double z){this.x = x;this.y = y;this.z = z;}public Point3D(double a){x = a;y = a;z = a;}/// <summary>/// 点 + 向量/// </summary>/// <param name="p"></param>/// <param name="v"></param>/// <returns></returns>public static Point3D operator +(Point3D p, Vector3D v){return new Point3D(p.X + v.X, p.Y + v.Y, p.Z + v.Z);}/// <summary>/// 两个点之间的减法,得到向量/// </summary>/// <param name="p1"></param>/// <param name="p2"></param>/// <returns></returns>public static Vector3D operator -(Point3D p1, Point3D p2){return new Vector3D(p1.X - p2.X, p1.Y - p2.Y, p1.Z - p2.Z);}}
}

Ray

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace RayTracing
{/// <summary>/// 射线/// </summary>class Ray{// 字段private Point3D org;private Vector3D dir;// 属性internal Point3D Org { get => org; set => org = value; }internal Vector3D Dir { get => dir; set => dir = value; }// 构造函数public Ray(){Org = new Point3D();Dir = new Vector3D();}public Ray(Point3D org, Vector3D dir){this.Org = org;this.Dir = dir;}/// <summary>/// 判断是否与球体相交/// </summary>/// <param name="sphere"></param>/// <returns></returns>public HitRecord isHit(Sphere sphere){// 计算deltaVector3D oc = Org - sphere.Center;double a = dir * dir;double b = 2.0 * (dir * oc);double c = oc * oc - sphere.Radius * sphere.Radius;double delta = b * b - 4.0 * a * c;HitRecord hitRecord = new HitRecord();// 有交点if (delta > 0){hitRecord.isHit = true;// 求tdouble t = (-b - Math.Sqrt(delta)) / (2.0 * a);if (t < 0){t = (-b + Math.Sqrt(delta)) / (2.0 * a);}hitRecord.t = t;// 求交点hitRecord.hitPoint = GetPoint(t);// 求法线hitRecord.normal = sphere.GetNormalVector(hitRecord.hitPoint);hitRecord.normal.Normalize();} else{hitRecord.isHit = false;}return hitRecord;}/// <summary>/// 依据参数t的值,得到射线上某点/// </summary>/// <param name="t"></param>/// <returns></returns>public Point3D GetPoint(double t){return org + t * dir;}}
}

Sphere

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace RayTracing
{class Sphere{private Point3D center;private double radius;public double Radius { get => radius; set => radius = value; }internal Point3D Center { get => center; set => center = value; }public Sphere(double radius, Point3D center){Radius = radius;Center = center;}public Sphere(){center = new Point3D();radius = 1.0;}/// <summary>/// 获得球面某点的法线向量/// </summary>/// <param name="p"></param>/// <returns></returns>public Vector3D GetNormalVector(Point3D p){Vector3D v = p - Center;// 单位化,简化后续计算v.Normalize();return v;}}
}

Vector

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace RayTracing
{class Vector3D{// 私有的字段private double x;private double y;private double z;// 公共的属性public double X { get => x; set => x = value; }public double Y { get => y; set => y = value; }public double Z { get => z; set => z = value; } // 构造函数public Vector3D(){x = 1;y = 0;z = 0;}public Vector3D(double x, double y, double z){this.x = x;this.y = y;this.z = z;}public Vector3D(double a){x = a;y = a;z = a;}/// <summary>/// 点乘/// </summary>/// <param name="v1"></param>/// <param name="v2"></param>/// <returns></returns>public static Double operator*(Vector3D v1, Vector3D v2){return v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z;}/// <summary>/// 数*向量/// </summary>/// <param name="d"></param>/// <param name="v"></param>/// <returns></returns>public static Vector3D operator*(double d, Vector3D v){return new Vector3D(d * v.X, d * v.Y, d * v.Z);}/// <summary>/// 向量*数/// </summary>/// <param name="v"></param>/// <param name="d"></param>/// <returns></returns>public static Vector3D operator*(Vector3D v, double d){return new Vector3D(d * v.X, d * v.Y, d * v.Z);}/// <summary>/// 向量加法/// </summary>/// <param name="v1"></param>/// <param name="v2"></param>/// <returns></returns>public static Vector3D operator +(Vector3D v1, Vector3D v2){return new Vector3D(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);}/// <summary>/// 向量减法/// </summary>/// <param name="v1"></param>/// <param name="v2"></param>/// <returns></returns>public static Vector3D operator -(Vector3D v1, Vector3D v2){return new Vector3D(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);}/// <summary>/// 向量的模/// </summary>/// <returns></returns> 模public double Magnitude(){return Math.Sqrt(X * X + Y * Y + Z * Z);}/// <summary>/// 向量单位化,本向量被改变/// </summary>public void Normalize(){double d = Magnitude();X = X / d;Y = Y / d;Z = Z / d;}/// <summary>/// 返回本向量的归一化向量,本向量不变/// </summary>/// <returns></returns> 单位化后的向量public Vector3D GetNormalizeVector(){double d = Magnitude();return new Vector3D(X/d, Y/d, Z/d);}}
}

viewPlain

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace RayTracing
{class ViewPlain{public Point3D topLeftLoc;public double w;public double h;public int wRes;public int hRes;}
}

http://www.ppmy.cn/news/1437701.html

相关文章

Python和C++音调音符规划和算法

&#x1f3af;要点 &#x1f3af;音符表征和代码实现&#xff1a;&#x1f58a;半音位置和索引之间的转换 | &#x1f58a;全音阶音调表征 | &#x1f58a;全音阶缓存 | &#x1f58a;全音阶音高表征。&#x1f3af;音程表征和代码实现&#xff1a;&#x1f58a;音程质量 | &a…

visionTransformer window平台下报错

错误&#xff1a; KeyError: Transformer/encoderblock_0/MlpBlock_3/Dense_0kernel is not a file in the archive解决方法&#xff1a; 修改这个函数即可&#xff0c;主要原因是Linux系统与window系统路径分隔符不一样导致 def load_from(self, weights, n_block):ROOT f&…

使用rust学习基本算法(三)

使用rust学习基本算法&#xff08;三&#xff09; 动态规划 动态规划算法是一种在数学、管理科学、计算机科学和经济学中广泛使用的方法&#xff0c;用于解决具有重叠子问题和最优子结构特性的问题。它通过将复杂问题分解为更小的子问题来解决问题&#xff0c;这些子问题被称为…

第7章 面向对象基础-下(内部类)

7.6 内部类(了解) 7.6.1 概述 1、什么是内部类&#xff1f; 将一个类A定义在另一个类B里面&#xff0c;里面的那个类A就称为内部类&#xff0c;B则称为外部类。 2、为什么要声明内部类呢&#xff1f; 总的来说&#xff0c;遵循高内聚低耦合的面向对象开发总原则。便于代码…

使用Azure AI Search和LlamaIndex构建高级RAG应用

RAG 是一种将公司信息合并到基于大型语言模型 &#xff08;LLM&#xff09; 的应用程序中的常用方法。借助 RAG&#xff0c;AI 应用程序可以近乎实时地访问最新信息&#xff0c;团队可以保持对其数据的控制。 在 RAG 中&#xff0c;您可以评估和修改各个阶段以改进结果&#x…

Node.js -- path模块

path.resolve(常用) // 导入fs const fs require(fs); // 写入文件 fs.writeFileSync(_dirname /index.html,love); console.log(_dirname /index.html);// D:\nodeJS\13-path\代码/index.html 我们之前使用的__dirname 路径 输出的结果前面是正斜杠/ &#xff0c;后面部分是…

acwing算法提高之图论--欧拉回路和欧拉路径

目录 1 介绍2 训练 1 介绍 本专题用来记录欧拉回路和欧拉路径相关的题目。 相关结论&#xff1a; &#xff08;1&#xff09;对于无向图&#xff0c;所有边都是连通的。 &#xff08;1.1&#xff09;存在欧拉路径的充要条件&#xff1a;度数为奇数的结点只能是0个或者2个。 &…

【银角大王——Django课程——创建项目+部门表的基本操作】

Django框架员工管理系统——创建项目部门表管理 员工管理系统创建项目命令行的形式创建Django项目——创建app注册app——在sttings中的INSTALLED_APPS [ ]数组中注册 设计表结构&#xff08;django&#xff09;连接数据库——在settings里面改写DATABASESDjango命令执行生成数…