#概要
cscの作法、調べてみた。
練習問題やってみた。
#練習問題
レイトレースを表示せよ。
#参考にしたページ
#写真
#サンプルコード
using System;
using System.Windows.Forms;
using System.Drawing;
class form1: Form {
form1() {
Text = "ray";
ClientSize = new Size(300, 300);
}
protected override void OnPaint(PaintEventArgs e) {
Graphics g = e.Graphics;
Color clrBackground = Color.Black;
g.FillRectangle(new SolidBrush(clrBackground), new Rectangle(0, 0, 200, 200));
Rectangle rect = new Rectangle(0, 0, 200, 200);
System.Collections.ArrayList obj3dArrayList;
obj3dArrayList = new System.Collections.ArrayList();
obj3dArrayList.Add(new Sphere(0.0, 0.0, 90.0, 100.0, 0.0, 0.0, 255.0));
obj3dArrayList.Add(new Sphere(-180.0, -130.0, -110.0, 15.0, 255.0, 0.0, 0.0));
obj3dArrayList.Add(new Sphere(-140.0, -140.0, -150.0, 20.0, 255.0, 200.0, 0.0));
Graphics graphics = g;
double px = (double) 0,
py = (double) 0,
pz = (double) 500;
double lpx = (double) 200,
lpy = (double) 200,
lpz = (double) 200;
double lvx = (double) -1.0,
lvy = (double) -1.0,
lvz = (double) -1.0;
double fMax = 200.0;
for (int i = rect.Left; i <= rect.Right; i++)
{
double x = Sphere.GetCoord(rect.Left, rect.Right, -fMax, fMax, i);
for (int j = rect.Top; j <= rect.Bottom; j++)
{
double y = Sphere.GetCoord(rect.Top, rect.Bottom, fMax, -fMax, j);
double t = 1.0E10;
double vx = x - px, vy = y - py, vz = -pz;
double mod_v = Sphere.modv(vx, vy, vz);
vx = vx / mod_v;
vy = vy / mod_v;
vz = vz / mod_v;
bool bShadow = false;
Sphere spherehit = null;
for (int k = 0; k < (int) obj3dArrayList.Count; k++)
{
Sphere sphn = (Sphere) obj3dArrayList[k];
double taux = Sphere.GetSphereIntersec(sphn.cx, sphn.cy, sphn.cz, sphn.radius, px, py, pz, vx, vy, vz);
if (taux < 0) continue;
if (taux > 0 && taux < t)
{
t = taux;
spherehit = sphn;
}
}
Color color = Color.FromArgb(10, 20, 10);
if (spherehit != null)
{
double itx = px + t * vx, ity = py + t * vy, itz = pz + t * vz;
double tauxla = Sphere.GetSphereIntersec(spherehit.cx, spherehit.cy, spherehit.cz, spherehit.radius, lpx, lpy, lpz, itx - lpx, ity - lpy, itz - lpz);
for (int k = 0; k < (int)obj3dArrayList.Count; k++)
{
Sphere sphnb = (Sphere)(obj3dArrayList[k]);
if (sphnb != spherehit)
{
double tauxlb = Sphere.GetSphereIntersec(sphnb.cx, sphnb.cy, sphnb.cz, sphnb.radius, lpx, lpy, lpz, itx - lpx, ity - lpy, itz - lpz);
if (tauxlb > 0 && tauxla < tauxlb)
{
bShadow = true;
break;
}
}
}
double cost = Sphere.GetCosAngleV1V2(lvx, lvy, lvz, itx - spherehit.cx, ity - spherehit.cy, itz - spherehit.cz);
if (cost < 0) cost = 0;
double fact = 1.0;
if (bShadow == true) fact = 0.5; else fact = 1.0;
double rgbR = spherehit.clR * cost * fact;
double rgbG = spherehit.clG * cost * fact;
double rgbB = spherehit.clB * cost * fact;
color = Color.FromArgb((int)rgbR, (int)rgbG, (int)rgbB);
Pen pen = new Pen(color);
}
Brush brs = new SolidBrush(color);
graphics.FillRectangle(brs, i, j, 1, 1);
brs.Dispose();
}
}
base.OnPaint(e);
}
class Sphere {
public Sphere(double x, double y, double z, double r, double clr, double clg, double clb) {
cx = x;
cy = y;
cz = z;
radius = r;
clR = clr;
clG = clg;
clB = clb;
}
public static double GetCoord(double i1, double i2, double w1, double w2, double p) {
return ((p - i1) / (i2 - i1)) * (w2 - w1) + w1;
}
public static double modv(double vx, double vy, double vz) {
return System.Math.Sqrt(vx * vx + vy * vy + vz * vz);
}
void Move(double vx, double vy, double vz) {
cx += vx;
cy += vy;
cz += vz;
}
void MoveTo(double vx, double vy, double vz) {
cx = vx;
cy = vy;
cz = vz;
}
void RotX(double angle) {
double y = cy * System.Math.Cos(angle) - cz * System.Math.Sin(angle);
double z = cy * System.Math.Sin(angle) + cz * System.Math.Cos(angle);
cy = y;
cz = z;
}
void RotY(double angle) {
double x = cx * System.Math.Cos(angle) - cz * System.Math.Sin(angle);
double z = cx * System.Math.Sin(angle) + cz * System.Math.Cos(angle);
cx = x;
cz = z;
}
public static double GetSphereIntersec(double cx, double cy, double cz, double radius, double px, double py, double pz, double vx, double vy, double vz) {
double A = (vx * vx + vy * vy + vz * vz);
double B = 2.0 * (px * vx + py * vy + pz * vz - vx * cx - vy * cy - vz * cz);
double C = px * px - 2 * px * cx + cx * cx + py * py - 2 * py * cy + cy * cy + pz * pz - 2 * pz * cz + cz * cz - radius * radius;
double D = B * B - 4 * A * C;
double t = -1.0;
if (D >= 0)
{
double t1 = (-B - System.Math.Sqrt(D)) / (2.0 * A);
double t2 = (-B + System.Math.Sqrt(D)) / (2.0 * A);
if (t1 > t2) t = t1; else t = t2;
}
return t;
}
public static double GetCosAngleV1V2(double v1x, double v1y, double v1z, double v2x, double v2y, double v2z) {
return (v1x * v2x + v1y * v2y + v1z * v2z) / (modv(v1x, v1y, v1z) * modv(v2x, v2y, v2z));
}
public double cx,
cy,
cz,
radius,
clR,
clG,
clB;
}
[STAThread]
public static void Main() {
Application.Run(new form1());
}
}
以上。