社区讨论

求调,看了一个晚上+早上了,简单计算几何

UVA12313 A Tiny Raytracer参与者 6已保存回复 7

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
7 条
当前快照
1 份
快照标识符
@lo9k06rx
此快照首次捕获于
2023/10/28 12:40
2 年前
此快照最后确认于
2023/10/28 12:40
2 年前
查看原帖
注意:题目没有要求输出图片,而是输出每个像素的 HEX 值。
函数名写的很通俗易懂。现在遇到的问题是 isShadowed 函数韩端出错,中间一大坨都是黑色的。
CPP
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <iostream>
#include <string>

using namespace std;

struct Point3{
	double x, y, z;
	Point3(double x = 0, double y = 0, double z = 0)
		:x(x), y(y), z(z){}
	Point3 operator + (const Point3& m)const{
		return Point3(x + m.x, y + m.y, z + m.z);
	}
	Point3 operator - (const Point3& m)const{
		return Point3(x - m.x, y - m.y, z - m.z);
	}
	Point3 operator * (const double& m)const{
		return Point3(x * m, y * m, z * m);
	}
	Point3 operator * (const Point3& m)const{
		return Point3(x * m.x, y * m.y, z * m.z);
	}
	Point3 operator / (const double& m)const{
		return Point3(x / m, y / m, z / m);
	}
	double len(){
		return sqrt(x * x + y * y + z * z);
	}
	Point3 normal(){
		const double l = len();
		return Point3(x / l, y / l, z / l);
	}
};
typedef Point3 Color;
int dcmp(double x){
	return (fabs(x) <= 1e-6) ? 0 : (x > 0 ? 1 : -1);
}
struct Triangle{
	Point3 a, b, c;
	Triangle(Point3 a = Point3(), Point3 b = Point3(), Point3 c = Point3())
		:a(a), b(b), c(c){}
};
struct Ray{
	Point3 s, d;
	Ray(Point3 s = Point3(), Point3 d = Point3())
		:s(s), d(d){}
	Point3 at(const double& D)const{
		return s + d * D;
	}
};

Point3 plainNormal(const Point3& a, const Point3& b, const Point3& c){
	double na = (b.y - a.y)*(c.z - a.z) - (b.z - a.z)*(c.y - a.y);
	double nb = (b.z - a.z)*(c.x - a.x) - (b.x - a.x)*(c.z - a.z);
	double nc = (b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x);
	return Point3(na, nb, nc);
}
double Dot(const Point3& x, const Point3& y){
	return x.x * y.x + x.y * y.y + x.z * y.z;
}
Point3 Cross(const Point3& x, const Point3& y){
	return Point3(x.y * y.z - x.z * y.y, x.z * y.x - x.x * y.z, x.x * y.y - x.y * y.x);
}
double Area2(const Point3& x, const Point3& y, const Point3& z){
	return Cross(y-x, z-x).len();
}
bool PointInTriangle(const Point3& p, const Triangle& t){
	double a = Area2(p, t.a, t.b);
	double b = Area2(p, t.b, t.c);
	double c = Area2(p, t.a, t.c);
	return dcmp(a + b + c - Area2(t.a, t.b, t.c)) == 0;
}
bool TriangleIntersectionSeg(const Triangle& t, const Point3& a, const Point3& b){
	Point3 n = plainNormal(t.a, t.b, t.c);
	if(dcmp(Dot(n, b - a)) == 0)
		return false;
	double T = Dot(n, t.a - a) / Dot(n, b - a);
	if(dcmp(T) <= 0 || dcmp(T-1) >= 0)
		return false;
	Point3 p = a + (b - a) * T;
	return PointInTriangle(p, t);
}
bool TriangleIntersectionRay(const Triangle& t, const Ray& r, Point3& p){
	Point3 n = plainNormal(t.a, t.b, t.c);
	if(dcmp(Dot(n, r.d)) == 0)
		return false;
	double T = Dot(n, t.a - r.s) / Dot(n, r.d);
	if(dcmp(T) <= 0)
		return false;
	p = r.at(T);
	return PointInTriangle(p, t);
}


istream & operator>> (istream &in, Point3 &A){
    in >> A.x >> A.y >> A.z;
    return in;
}

int N;
struct Object{
	vector<Triangle> triangleList;
	Color color;
	double refl, refr;
	double medIdx;
};
vector<Object> Scene;
struct Light{
	Point3 location;
	Color color;
	double ambient;
}L;
struct Camera{
	Point3 pos, targ, up;
	double ang;
	int W, H;
	Ray forw;
}Cam;

char toHex(int x){
	return x < 10 ? (x + '0') : (x + 'a' - 10);
}
string RGBTransfer(double d){
	int x = (int)(d * 255.9999999);
	return string() + toHex(x / 16) + toHex(x % 16);
}

string formatColor(Color& color){
	return RGBTransfer(color.x) + RGBTransfer(color.y) + RGBTransfer(color.z);
}

const int MAX_TRACE_DEPTH = 4;

int getFirstIntersection(Ray r, Point3& p, Triangle& t){
	int mn = -1;
	double len = -1;
	for(int id=0; id<(int)Scene.size(); id++){
		for(Triangle tri: Scene[id].triangleList)
			if(TriangleIntersectionRay(tri, r, p)){
				double l = (p - r.s).len();
				if(len < 0)
					len = l, mn = id, t = tri;
				else if(len > l)
					len = l, mn = id, t = tri;
			}
	}
	return mn;
}
int mrk = -1;

bool isShadowed(Point3 p){
	Triangle T; Point3 P;
	p = p + (L.location - p).normal() * 0.0000001;
	if(getFirstIntersection(Ray(p, (L.location - p).normal()), P, T) == -1)
		return false;
	return (P - p).len() < (L.location - p).len();
}
double getPointColor(Point3& p, Point3 dir){
	double shade = 0;
	if(!isShadowed(p))
		shade = fabs(Dot((L.location - p).normal(), dir.normal()));
	else
		mrk = 0;
	return L.ambient + (1 - L.ambient) * shade;
}
bool getReflectedRay(Ray& r, int idx, Point3& p, Triangle& t, Point3& re){
	if(Scene[idx].medIdx == 0)
		return false;
	Point3 norm = plainNormal(t.a, t.b, t.c);
	if(dcmp(Dot(r.d, norm)) == -1)
		norm = norm * -1;
	double ang = acos(Dot(r.d, norm) / r.d.len() / norm.len());
	double srng = sin(ang) / Scene[idx].medIdx;
	if(srng > 1)
		return false;
	srng = asin(srng);
	norm = norm.normal();
	re = (r.d - norm * Dot(r.d, norm) * 2).normal() * -1;
	double h = cos(ang);
	re = (norm * h * (1 / tan(ang) + 1 / tan(srng)) - re).normal();
	return true;
}
bool getReflectedRayInner(Ray& r, int idx, Point3& p, Triangle& t, Point3& re){
	Point3 norm = plainNormal(t.a, t.b, t.c);
	if(dcmp(Dot(r.d, norm)) == -1)
		norm = norm * -1;
	double ang = acos(Dot(r.d, norm) / r.d.len() / norm.len());
	double srng = sin(ang) * Scene[idx].medIdx;
	if(srng > 1)
		return false;
	srng = asin(srng);
	norm = norm.normal();
	re = (r.d - norm * Dot(r.d, norm) * 2).normal() * -1;
	double h = cos(ang);
	re = (norm * h * (1 / tan(ang) + 1 / tan(srng)) - re).normal();
	return true;
}
bool getRefractedRay(Ray& r, int idx, Point3& p, Triangle& t, Point3& re){
	Point3 norm = plainNormal(t.a, t.b, t.c);
	if(dcmp(Dot(r.d, norm)) == -1)
		norm = norm * -1;
	norm = norm.normal();
	re = (r.d - norm * Dot(r.d, norm) * 2).normal();
	return true;
}


Color traceLight(Ray r, int dep, bool inObj = false){
	if(dep == MAX_TRACE_DEPTH)
		return Color();
	// printf("%.2f %.2f %.2f %.2f %.2f %.2f %d %d\n", r.s.x, r.s.y, r.s.z, r.d.x, r.d.y, r.d.z, dep, inObj);
	Color pointColor, reflColor, refrColor;
	Point3 p; Triangle t;
	int idx = getFirstIntersection(r, p, t);
	// printf("== INTER == %d\n", idx);
	if(idx != -1){
		// printf("! %d\n", idx);
		// mrk = idx;
		double refl = Scene[idx].refl
			 , refr = Scene[idx].refr;
		pointColor = Scene[idx].color * L.color * (1 - refl - refr)
				   * getPointColor(p, plainNormal(t.a, t.b, t.c));
		// plainNormal(t.a, t.b, t.c)
		Point3 re;
		if(inObj ? getReflectedRayInner(r, idx, p, t, re) : getReflectedRay(r, idx, p, t, re))
			reflColor = traceLight(re, dep+1, !inObj) * refl;
		if(getRefractedRay(r, idx, p, t, re))
			reflColor = traceLight(re, dep+1, inObj) * refr;
	}
	return pointColor + reflColor + refrColor;
}

int main(){
	std::ios::sync_with_stdio(false);
    std::cin.tie(0);
	vector<Point3> pl;
	freopen("out2jpg.txt", "w", stdout);
    while(cin >> N && N != 0){
    	Scene.clear();
    	for(int i=1; i<=N; i++){
    		Object nO;
    		int l; cin >> l;
    		pl.clear();
    		Point3 x;
    		while(l--){
    			cin >> x;
    			pl.push_back(x);
    		}
    		cin >> l;
    		int a, b, c;
    		while(l--){
    			cin >> a >> b >> c;
    			nO.triangleList.push_back(Triangle(pl[a], pl[b], pl[c]));
    		}
    		cin >> nO.color >> nO.refl >> nO.refr >> nO.medIdx;
    		Scene.push_back(nO);
    	}
    	cin >> L.location >> L.ambient >> L.color;
    	int q; cin >> q;
    	while(q--){
    		cin >> Cam.pos >> Cam.targ >> Cam.up >> Cam.ang >> Cam.W >> Cam.H;
    		printf("%d %d\n", Cam.W, Cam.H);
    		Cam.ang = Cam.ang * 3.14159265 / 180;
    		Cam.forw = Ray(Cam.pos, (Cam.targ - Cam.pos).normal());
    		double dis = Cam.W / 2.0 / tan(Cam.ang / 2);
    		Point3 cent = Cam.forw.at(dis);
    		Point3 dwn = Cam.up * -1;
    		Point3 rig = plainNormal(cent, cent + Cam.forw.d, cent + dwn).normal() * -1;
    		for(int x=0; x<Cam.H; x++){
    			for(int y=0; y<Cam.W; y++){
    				Point3 curr = cent + dwn * (x - Cam.H / 2.0 + 0.5) + rig * (y - Cam.W / 2.0 + 0.5);
    				Color color = traceLight(Ray(Cam.pos, curr - Cam.pos), 0);
    				// color = Color(1, 1, 1) / 1 * (mrk + 1);
    				printf("%s ", formatColor(color).c_str());
    				// printf("%c ", (mrk == -1) ? '-' : (char)(mrk + '0'));
    				mrk = -1;
    			}
    			printf("\n");
    		}
    	}
    }
	return 0;
}

回复

7 条回复,欢迎继续交流。

正在加载回复...