• c# 画球


    主代码

    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;
            }
        }
    }
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102

    相关类

    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;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    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;
            }
    
            /// 
            /// 点 + 向量
            /// 
            /// 
            /// 
            /// 
            public static Point3D operator +(Point3D p, Vector3D v)
            {
                return new Point3D(p.X + v.X, p.Y + v.Y, p.Z + v.Z);
            }
    
            /// 
            /// 两个点之间的减法,得到向量
            /// 
            /// 
            /// 
            /// 
            public static Vector3D operator -(Point3D p1, Point3D p2)
            {
                return new Vector3D(p1.X - p2.X, p1.Y - p2.Y, p1.Z - p2.Z);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    Ray

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace RayTracing
    {
        /// 
        /// 射线
        /// 
        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;
            }
    
            /// 
            /// 判断是否与球体相交
            /// 
            /// 
            /// 
            public HitRecord isHit(Sphere sphere)
            {
                // 计算delta
                Vector3D 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;
    
                    // 求t
                    double 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;
            }
    
            /// 
            /// 依据参数t的值,得到射线上某点
            /// 
            /// 
            /// 
            public Point3D GetPoint(double t)
            {
                return org + t * dir;
            }
    
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93

    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;
            }
    
            /// 
            /// 获得球面某点的法线向量
            /// 
            /// 
            /// 
            public Vector3D GetNormalVector(Point3D p)
            {
                Vector3D v = p - Center;
    
                // 单位化,简化后续计算
                v.Normalize();
    
                return v;
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    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;
            }
    
            /// 
            /// 点乘
            /// 
            /// 
            /// 
            /// 
            public static Double operator*(Vector3D v1, Vector3D v2)
            {
                return v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z;
            }
    
            /// 
            /// 数*向量
            /// 
            /// 
            /// 
            /// 
            public static Vector3D operator*(double d, Vector3D v)
            {
                return new Vector3D(d * v.X, d * v.Y, d * v.Z);
            }
    
            /// 
            /// 向量*数
            /// 
            /// 
            /// 
            /// 
            public static Vector3D operator*(Vector3D v, double d)
            {
                return new Vector3D(d * v.X, d * v.Y, d * v.Z);
            }
    
            /// 
            /// 向量加法
            /// 
            /// 
            /// 
            /// 
            public static Vector3D operator +(Vector3D v1, Vector3D v2)
            {
                return new Vector3D(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
            }
    
            /// 
            /// 向量减法
            /// 
            /// 
            /// 
            /// 
            public static Vector3D operator -(Vector3D v1, Vector3D v2)
            {
                return new Vector3D(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
            }
    
            /// 
            /// 向量的模
            /// 
            /// 
            public double Magnitude()
            {
                return Math.Sqrt(X * X + Y * Y + Z * Z);
            }
    
            /// 
            /// 向量单位化,本向量被改变
            /// 
            public void Normalize()
            {
                double d = Magnitude();
                X = X / d;
                Y = Y / d;
                Z = Z / d;
            }
    
            /// 
            /// 返回本向量的归一化向量,本向量不变
            /// 
            ///  单位化后的向量
            public Vector3D GetNormalizeVector()
            {
                double d = Magnitude();
                return new Vector3D(X/d, Y/d, Z/d);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129

    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;
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
  • 相关阅读:
    基于Pytorch框架的轻量级卷积神经网络垃圾分类识别系统
    MyBatis 如何进行一对一关联查询呢?
    ABAP Json和对象的转换
    Ajax基础原理及使用教程
    redis集群主从缩容(docker中)
    C++入门篇10---stack+queue+priority_queue
    java计算机毕业设计特色农产品供需销售系统源程序+mysql+系统+lw文档+远程调试
    doris的单节点安装部署(详细)
    UART串口及Linux实现
    nginx使用详解:转发规则、负载均衡、server_name
  • 原文地址:https://blog.csdn.net/qq_73270720/article/details/138175522